⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ldelf.c

📁 T-kernel 的extension源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *---------------------------------------------------------------------- *    T-Kernel / Standard Extension * *    Copyright (C) 2006 by Ken Sakamura. All rights reserved. *    T-Kernel / Standard Extension is distributed  *      under the T-License for T-Kernel / Standard Extension. *---------------------------------------------------------------------- * *    Version:   1.00.00 *    Released by T-Engine Forum(http://www.t-engine.org) at 2006/8/11. * *---------------------------------------------------------------------- *//* *	ldelf.c (memory) * *	ELF format program loading (SH7751R Virtual storage version) * *	Supports the following loading formats: *	* On-demand loading *	* Global loading/not relocated *	* Global loading/relocated */#include "segmgr.h"#include <cnvend.h>#ifdef DEBUG#  define _ER_REC(n)	( E_REC | (n) )#else#  define _ER_REC(n)	( E_REC )#endif#define	LINK_ADDR	0x00100000	/* Link address */#define TSD_LDE_ERR_1	1#define TSD_LDE_ERR_2	2#define TSD_LDE_ERR_3	3#define TSD_LDE_ERR_4	4#define TSD_LDE_ERR_5	5#define TSD_LDE_ERR_6	6#define TSD_LDE_ERR_7	7#define TSD_LDE_ERR_8	8#define TSD_LDE_ERR_9	9#define TSD_LDE_ERR_10	10#define TSD_LDE_ERR_11	11#define TSD_LDE_ERR_12	12#define TSD_LDE_ERR_13	13#define TSD_LDE_ERR_14	14#define TSD_LDE_ERR_15	15#define TSD_LDE_ERR_16	16#define TSD_GEI_SYM_M1	(-1)#define TSD_GEI_VAL_2	2#define TSD_DLE_POS_0	0#define TSD_DLE_POS_1	1/* Format checking for each supported model */#define CHK_ELFDATA(n)		( (n) == ELFDATA2LSB )#define CHK_ELFMACH(n)		( (n) == EM_SH )/* * ELF loading information */typedef struct {	VB*	text_ladr;	/* text area loading address */	UW	text_fofs;	/* text area file position */	UW	text_size;	/* text area size */	VB*	data_ladr;	/* data area loading address */	UW	data_fofs;	/* data area file position */	UW	data_size;	/* data area size */	VB*	bss_ladr;	/* bss  area first address */	UW	bss_size;	/* bss  area size */	UW	stack_size;	/* Stack size */	UH	text_shndx;	/* text area section number */	UH	data_shndx;	/* data area section number */	UH	bss_shndx;	/* bss  area section number */	UW	rel_text_fofs;	/* File position of text area relocation information */	UW	rel_text_size;	/* Size of text area relocation information */	UW	rel_data_fofs;	/* File position of data area relocation information */	UW	rel_data_size;	/* Size of data area relocation information */	UW	symtbl_fofs;	/* File position of symbol table */	UW	symtbl_size;	/* Size of symbol table */	BOOL	vir_or_off;	/* Virtual address (TRUE) or offset (FALSE) */} ELF_LoadInfo;LOCAL ER CheckLoadAddress( ELF_LoadInfo *eli );LOCAL ER CheckSysLoadAddress( ELF_LoadInfo *eli );LOCAL ER GetELFLoadInfoShdr( ELF_LoadInfo *eli, Elf32_Ehdr *hdr, POBJ_HDR *pohdr, BzRead *bzr );LOCAL BOOL HasDynSeg( Elf32_Ehdr *hdr, POBJ_HDR *pohdr, BzRead *bzr );LOCAL BOOL HasRelSec( Elf32_Ehdr *hdr, POBJ_HDR *pohdr, BzRead *bzr );LOCAL ER GetELFLoadInfoPhdr( ELF_LoadInfo *eli, Elf32_Ehdr *hdr, POBJ_HDR *pohdr, BzRead *bzr );LOCAL ER GetELFLoadInfo( ELF_LoadInfo *eli, Elf32_Ehdr *hdr, POBJ_HDR *pohdr, BzRead *bzr, BOOL relsec );LOCAL ER reloc1( ELF_LoadInfo *eli, POBJ_HDR *pohdr, W rtbl, W rtblsz, W lofs, VB *sect, W sectsz, Elf32_Sym *symtbl, W syment, BzRead *bzr );LOCAL ER elf_relocation( LDINFO *li, ELF_LoadInfo *eli, W lofs, BzRead *bzr );#ifdef DEBUGLOCAL void prELFLoadInfo( ELF_LoadInfo *eli ){	DEBUG_PRINT(("ELF_LoadInfo\n"));	DEBUG_PRINT(("\t.text_ladr     = 0x%08x\n",	eli->text_ladr));	DEBUG_PRINT(("\t.text_fofs     = 0x%08x\n",	eli->text_fofs));	DEBUG_PRINT(("\t.text_size     = 0x%08x\n",	eli->text_size));	DEBUG_PRINT(("\t.data_ladr     = 0x%08x\n",	eli->data_ladr));	DEBUG_PRINT(("\t.data_fofs     = 0x%08x\n",	eli->data_fofs));	DEBUG_PRINT(("\t.data_size     = 0x%08x\n",	eli->data_size));	DEBUG_PRINT(("\t.bss_ladr      = 0x%08x\n",	eli->bss_ladr));	DEBUG_PRINT(("\t.bss_size      = 0x%08x\n",	eli->bss_size));	DEBUG_PRINT(("\t.stack_size    = %d\n",		eli->stack_size));	DEBUG_PRINT(("\t.text_shndx    = %d\n",		eli->text_shndx));	DEBUG_PRINT(("\t.data_shndx    = %d\n",		eli->data_shndx));	DEBUG_PRINT(("\t.bss_shndx     = %d\n",		eli->bss_shndx));	DEBUG_PRINT(("\t.rel_text_fofs = 0x%08x\n",	eli->rel_text_fofs));	DEBUG_PRINT(("\t.rel_text_size = %d\n",		eli->rel_text_size));	DEBUG_PRINT(("\t.rel_data_fofs = 0x%08x\n",	eli->rel_data_fofs));	DEBUG_PRINT(("\t.rel_data_size = %d\n",		eli->rel_data_size));	DEBUG_PRINT(("\t.symtbl_fofs   = 0x%08x\n",	eli->symtbl_fofs));	DEBUG_PRINT(("\t.symtbl_size   = %d\n",		eli->symtbl_size));}#endif/* * Check if the loading address is within a range of the process unique space. */LOCAL ER CheckLoadAddress( ELF_LoadInfo *eli ){	ER	err;	if ( !isLocalSpace(eli->text_ladr)	  || !isLocalSpace(eli->bss_ladr + eli->bss_size) ) {		err = _ER_REC(TSD_LDE_ERR_1);		goto err_ret;	}	return E_OK;err_ret:	DEBUG_PRINT(("CheckLoadAddress err = %d (%d)\n", err, (UH)err));	return err;}/* * Check if the loading address is within a range of system program loading. */LOCAL ER CheckSysLoadAddress( ELF_LoadInfo *eli ){	ER	err;	if ( !isSysLoadSpace(eli->text_ladr)	  || !isSysLoadSpace(eli->bss_ladr + eli->bss_size) ) {		err = _ER_REC(TSD_LDE_ERR_1);		goto err_ret;	}	return E_OK;err_ret:	DEBUG_PRINT(("CheckSysLoadAddress err = %d (%d)\n", err, (UH)err));	return err;}/* * Obtain loading information from ELF section header. */LOCAL ER GetELFLoadInfoShdr( ELF_LoadInfo *eli, Elf32_Ehdr *hdr, POBJ_HDR *pohdr, BzRead *bzr ){	Elf32_Shdr	*shdr_buf, *shdr, *p;	W		n;	VB		*adr;	W		symsect = TSD_GEI_SYM_M1;	ER		err;	if ( (hdr->e_shentsize < sizeof(Elf32_Shdr)) || (hdr->e_shnum == 0) ) {		err = _ER_REC(TSD_LDE_ERR_1);		goto err_ret1;	}	/* Buffer for loading section header */	n = hdr->e_shentsize * hdr->e_shnum;	shdr_buf = Vmalloc((size_t)n);	if ( shdr_buf == NULL ) {		err = E_NOMEM;		goto err_ret1;	}	/* Load section header */	err = ReadProgFile(pohdr, (W)hdr->e_shoff, (VB*)shdr_buf, n, bzr);	if ( err < E_OK ) {		goto err_ret2;	}	eli->stack_size = (UW)DefaultStackSize;	for ( n = (W)hdr->e_shnum, shdr = shdr_buf;			--n >= 0; shdr = (Elf32_Shdr*)((VB*)shdr + hdr->e_shentsize) ) {		switch ( shdr->sh_type ) {		  case SHT_PROGBITS:			if (( shdr->sh_flags & SHF_ALLOC) == 0U) {				continue; /* Ignore */			}						switch ( shdr->sh_flags ) {			  case SHF_ALLOC|SHF_EXECINSTR:	/* text area */				if ( eli->text_size != 0U ) {					err = _ER_REC(TSD_LDE_ERR_2);					goto err_ret2;				}				eli->text_ladr = shdr->sh_addr;				eli->text_fofs = shdr->sh_offset;				eli->text_size = shdr->sh_size;				eli->text_shndx = (UH)(shdr - shdr_buf);				break;			  case SHF_ALLOC|SHF_WRITE:	/* data area */				if ( eli->data_ladr != NULL ) {					err = _ER_REC(TSD_LDE_ERR_3);					goto err_ret2;				}				eli->data_ladr = shdr->sh_addr;				eli->data_fofs = shdr->sh_offset;				eli->data_size = shdr->sh_size;				eli->data_shndx = (UH)(shdr - shdr_buf);				break;			  default:				err = _ER_REC(TSD_LDE_ERR_4);				goto err_ret2;			}			break;		  case SHT_NOBITS:			switch ( shdr->sh_flags ) {			  case SHF_ALLOC|SHF_WRITE:	/* bss area */				if ( eli->bss_ladr != NULL ) {					err = _ER_REC(TSD_LDE_ERR_5);					goto err_ret2;				}				eli->bss_ladr = shdr->sh_addr;				eli->bss_size = shdr->sh_size;				eli->bss_shndx = (UH)(shdr - shdr_buf);				break;			  case SHF_ALLOC:		/* stack area */				eli->stack_size = shdr->sh_size;				break;			  case 0:				continue; /* Ignore */			  default:				err = _ER_REC(TSD_LDE_ERR_6);				goto err_ret2;			}			break;		  case SHT_RELA:			if ( (shdr->sh_info >= hdr->e_shnum)			  || (shdr->sh_link >= hdr->e_shnum) ) {			  	err = _ER_REC(TSD_LDE_ERR_7);			  	goto err_ret2;			}			/* Section to be relocated */			p = &shdr_buf[shdr->sh_info];			if ( p->sh_type != SHT_PROGBITS ) {				continue;			}			switch ( p->sh_flags ) {			  case SHF_ALLOC|SHF_EXECINSTR:	/* text area */				if ( eli->rel_text_size != 0U ) {					err = _ER_REC(TSD_LDE_ERR_9);					goto err_ret2;				}				eli->rel_text_fofs = shdr->sh_offset;				eli->rel_text_size = shdr->sh_size;				break;			  case SHF_ALLOC|SHF_WRITE:	/* data area */				if ( eli->rel_data_size != 0U ) {					err = _ER_REC(TSD_LDE_ERR_10);					goto err_ret2;				}				eli->rel_data_fofs = shdr->sh_offset;				eli->rel_data_size = shdr->sh_size;				break;			  case 0:				continue; /* Ignore */			  default:				err = _ER_REC(TSD_LDE_ERR_11);				goto err_ret2;			}			if ( (symsect >= 0) && (shdr->sh_link != (UW)symsect) ) {				err = _ER_REC(TSD_LDE_ERR_12);				goto err_ret2;			}			symsect = (W)shdr->sh_link;			break;		  default:			continue; /* Ignore */		}	}	/* Check validity */	if ( eli->text_size == 0U ) {		err = _ER_REC(TSD_LDE_ERR_13);		goto err_ret2;	}	adr = PageAlignU(eli->text_ladr + eli->text_size);	if ( eli->data_ladr != adr ) {		err = _ER_REC(TSD_LDE_ERR_14);		goto err_ret2;	}	adr += eli->data_size;	if ( eli->bss_ladr < adr ) {		err = _ER_REC(TSD_LDE_ERR_15);		goto err_ret2;	}	if ( symsect >= 0 ) {		/* Symbol table for relocation */		if ( shdr_buf[symsect].sh_type != SHT_SYMTAB ) {			err = _ER_REC(TSD_LDE_ERR_16);			goto err_ret2;		}		eli->symtbl_fofs = shdr_buf[symsect].sh_offset;		eli->symtbl_size = shdr_buf[symsect].sh_size;	}	Vfree(shdr_buf);	return E_OK;err_ret2:	Vfree(shdr_buf);err_ret1:	DEBUG_PRINT(("GetELFLoadInfoShdr err = %d (%d)\n", err, (UH)err));	return err;}/* * Obtain loading information from ELF program header */LOCAL BOOL HasDynSeg( Elf32_Ehdr *hdr, POBJ_HDR *pohdr, BzRead *bzr ){	Elf32_Phdr	*phdr_buf, *phdr;	W		n;	ER		err;	if ( (hdr->e_phentsize < sizeof(Elf32_Phdr)) || (hdr->e_phnum < 1) ) {		err = _ER_REC(TSD_LDE_ERR_1);		goto err_ret1;	}	n = hdr->e_phentsize * hdr->e_phnum;	phdr_buf = Vmalloc((size_t)n);	if ( phdr_buf == NULL ) {		err = E_NOMEM;		goto err_ret1;	}	/* Load program header */	err = ReadProgFile(pohdr, (W)hdr->e_phoff, (VB*)phdr_buf, n, bzr);	if ( err < E_OK ) {		goto err_ret2;	}	for ( n = (W)hdr->e_phnum, phdr = phdr_buf;			--n >= 0; phdr = (Elf32_Phdr*)((VB*)phdr + hdr->e_phentsize) ) {		if ( phdr->p_type == PT_DYNAMIC ) {			goto found;		}	}	Vfree(phdr_buf);	return FALSE;found:	Vfree(phdr_buf);	return TRUE;err_ret2:	Vfree(phdr_buf);err_ret1:	DEBUG_PRINT(("HasDynSeg err = %d (%d)\n", err, (UH)err));	return FALSE;}/* * Relocation section check */LOCAL BOOL HasRelSec( Elf32_Ehdr *hdr, POBJ_HDR *pohdr, BzRead *bzr ){	Elf32_Shdr	*shdr_buf, *shdr;	W		n;	ER		err;	if ( (hdr->e_shentsize < sizeof(Elf32_Shdr)) || (hdr->e_shnum == 0) ) {		err = _ER_REC(TSD_LDE_ERR_1);		goto err_ret1;	}	n = hdr->e_shentsize * hdr->e_shnum;	shdr_buf = Vmalloc((size_t)n);	if ( shdr_buf == NULL ) {		err = E_NOMEM;		goto err_ret1;	}	/* Load section header */	err = ReadProgFile(pohdr, (W)hdr->e_shoff, (VB*)shdr_buf, n, bzr);	if ( err < E_OK ) {		goto err_ret2;	}	for ( n = (W)hdr->e_shnum, shdr = shdr_buf;			--n >= 0; shdr = (Elf32_Shdr*)((VB*)shdr + hdr->e_shentsize) ) {		switch ( shdr->sh_type ) {		  case SHT_RELA:			goto found;		  default:			continue; /* Ignore */		}	}	Vfree(shdr_buf);	return FALSE;found:	Vfree(shdr_buf);	return TRUE;err_ret2:	Vfree(shdr_buf);err_ret1:	DEBUG_PRINT(("HasRelSec err = %d (%d)\n", err, (UH)err));	return FALSE;}/* * Obtain loading information from ELF program header */LOCAL ER GetELFLoadInfoPhdr( ELF_LoadInfo *eli, Elf32_Ehdr *hdr, POBJ_HDR *pohdr, BzRead *bzr ){	Elf32_Phdr	*phdr_buf, *phdr;	W		n;	VB		*adr;	ER		err;	if ( (hdr->e_phentsize < sizeof(Elf32_Phdr)) || (hdr->e_phnum < TSD_GEI_VAL_2) ) {		err = _ER_REC(TSD_LDE_ERR_1);		goto err_ret1;	}	/* Buffer for loading program header */	n = hdr->e_phentsize * hdr->e_phnum;	phdr_buf = Vmalloc((size_t)n);	if ( phdr_buf == NULL ) {		err = E_NOMEM;		goto err_ret1;	}	/* Load program header */	err = ReadProgFile(pohdr, (W)hdr->e_phoff, (VB*)phdr_buf, n, bzr);	if ( err < E_OK ) {		goto err_ret2;	}	eli->stack_size = (UW)DefaultStackSize;	for ( n = (W)hdr->e_phnum, phdr = phdr_buf;			--n >= 0; phdr = (Elf32_Phdr*)((VB*)phdr + hdr->e_phentsize) ) {		/* Ignore non-loadable segments */		if ( phdr->p_type != (UW)PT_LOAD ) {			continue;		}		switch ( phdr->p_flags ) {		  case PF_R|PF_X:	/* text area */			if ( eli->text_size != 0U ) {				err = _ER_REC(TSD_LDE_ERR_2);				goto err_ret2;			}			eli->text_ladr = phdr->p_vaddr;			eli->text_fofs = phdr->p_offset;			eli->text_size = phdr->p_filesz;			break;		  case PF_R|PF_W:	/* data, bss area */			if ( eli->data_ladr != NULL ) {				err = _ER_REC(TSD_LDE_ERR_3);				goto err_ret2;			}			eli->data_ladr = phdr->p_vaddr;			eli->data_fofs = phdr->p_offset;			eli->data_size = phdr->p_filesz;			eli->bss_ladr = (VB*)phdr->p_vaddr + phdr->p_filesz;			eli->bss_size = phdr->p_memsz - phdr->p_filesz;			break;		  case PF_R:		/* stack area */			if ( phdr->p_filesz > 0U ) {				err = _ER_REC(TSD_LDE_ERR_4);				goto err_ret2;			}			eli->stack_size = phdr->p_memsz;			break;		  case 0:			if ( (phdr->p_filesz > 0U) || (phdr->p_memsz > 0U) ) {				err = _ER_REC(TSD_LDE_ERR_5);				goto err_ret2;			}			continue; /* Ignore */		  default:			err = _ER_REC(TSD_LDE_ERR_6);			goto err_ret2;		}	}	/* Check validity */	if ( (eli->text_size == 0U) || (eli->data_ladr == NULL) ) {		err = _ER_REC(TSD_LDE_ERR_7);		goto err_ret2;	}	adr = eli->text_ladr + eli->text_size;	if ( eli->data_ladr < (VB*)PageAlignU(adr) ) {		err = _ER_REC(TSD_LDE_ERR_8);		goto err_ret2;	}	Vfree(phdr_buf);	return E_OK;err_ret2:	Vfree(phdr_buf);err_ret1:	DEBUG_PRINT(("GetELFLoadInfoPhdr err = %d (%d)\n", err, (UH)err));	return err;}/* * Obtain ELF loading information */LOCAL ER GetELFLoadInfo( ELF_LoadInfo *eli, Elf32_Ehdr *hdr, POBJ_HDR *pohdr, BzRead *bzr, BOOL relsec ){	ER	err;	memset(eli, 0, (size_t)sizeof(ELF_LoadInfo));	/* Check header */	if ( !((hdr->e_ident[EI_CLASS] == ELFCLASS32)	    && CHK_ELFDATA(hdr->e_ident[EI_DATA])	    && (hdr->e_ident[EI_VERSION] == 1U)	    && CHK_ELFMACH(hdr->e_machine)	    && (hdr->e_version == EV_CURRENT)) ) {		err = _ER_REC(TSD_LDE_ERR_1);		goto err_ret;	}	switch ( hdr->e_type ) {	  case ET_EXEC:	  	if ( relsec != 0 ) {			/* Section Header */			eli->vir_or_off = TRUE;			err = GetELFLoadInfoShdr(eli, hdr, pohdr, bzr);		} else {			/* Program Header */			err = GetELFLoadInfoPhdr(eli, hdr, pohdr, bzr);		}		if ( err < E_OK ) {			goto err_ret;		}		break;	  case ET_DYN:		/* Obtain loading information from program header */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -