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

📄 ldelf.c

📁 T-kernel 的extension源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
		}	}	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 != 0 ) {				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 > 0 ) {				err = _ER_REC(TSD_LDE_ERR_4);				goto err_ret2;			}			eli->stack_size = phdr->p_memsz;			break;		  case 0:			if ( (phdr->p_filesz > 0) || (phdr->p_memsz > 0) ) {				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 == 0) || (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] == 1)	    && 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 */		err = GetELFLoadInfoPhdr(eli, hdr, pohdr, bzr);		if ( err < E_OK ) {			goto err_ret;		}		break;	  case ET_REL:		/* Obtain loading information from section header */		err = GetELFLoadInfoShdr(eli, hdr, pohdr, bzr);		if ( err < E_OK ) {			goto err_ret;		}		break;	  default:		err = _ER_REC(TSD_LDE_ERR_2);		goto err_ret;	}	return E_OK;err_ret:	DEBUG_PRINT(("GetELFLoadInfo err = %d (%d)\n", err, (UH)err));	return err;}typedef struct {	W	*addr;	UW	val;} Ahi_Info;#define AHI_INFO_UNIT	1/* * Relocate one section */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 ){	Elf32_Rel	*reloc, *rp, *reloc_end;	Ahi_Info	*ahi_info = NULL;	Ahi_Info	*ahi_infotmp;	W		ahi_infomax = AHI_INFO_UNIT;	W		ahi_infonext = 0;	W		ahi_infoused = 0;	W		ind;	W		ahl, addend, nadr = 0;	UH		*hp;	W		*wp, sv, i;	VB		*ladr;	ER		err;	if ( rtblsz == 0 ) {		return E_OK;  /* No section to be relocated */	}	/* Load relocation information */	reloc = Vmalloc((size_t)rtblsz);	if ( reloc == NULL ) {		err = E_NOMEM;		goto err_ret1;	}	err = ReadProgFile(pohdr, rtbl, (VB*)reloc, rtblsz, bzr);	if ( err < E_OK ) {		goto err_ret2;	}	reloc_end = &reloc[rtblsz / (W)sizeof(*reloc)];	if ( eli->vir_or_off != 0 ) {		for ( rp = reloc; rp < reloc_end; rp++ ) {			rp->r_offset = (VP)((UB*)rp->r_offset - ((UW)sect - (UW)lofs));		}	}	for ( rp = reloc; rp < reloc_end; rp++ ) {		i = (W)ELF32_R_SYM(rp->r_info);		if ( (i >= syment) || ((UW)rp->r_offset >= (UW)sectsz) ) {			err = _ER_REC(TSD_LDE_ERR_1);			goto err_ret2;		}		if ( ELF32_R_TYPE(rp->r_info) == 0 ) {			continue;		}		wp = (W*)(sect + (UW)rp->r_offset);		sv = (W)symtbl[i].st_value;		if ( symtbl[i].st_shndx == eli->text_shndx ) {			ladr = eli->text_ladr;		} else if ( symtbl[i].st_shndx == eli->data_shndx ) {			ladr = eli->data_ladr;		} else if ( symtbl[i].st_shndx == eli->bss_shndx ) {			ladr = eli->bss_ladr;		} else if ( symtbl[i].st_shndx == SHN_ABS ) {			ladr = (VB*)(-lofs);		} else if ( symtbl[i].st_shndx == SHN_UNDEF ) {			if ( ELF32_ST_BIND(symtbl[i].st_info) == STB_WEAK ) {				continue;			}							if ( i == 0 ) {				ladr = (VB*)(-lofs); /* ABS Section */				sv = 0;			} else {				err = _ER_REC(TSD_LDE_ERR_2);				goto err_ret2;			}		} else {			err = _ER_REC(TSD_LDE_ERR_2);			goto err_ret2;		}		/* Relocation */		switch ( ELF32_R_TYPE(rp->r_info) ) {		  case R_MIPS_32:			if ( eli->vir_or_off != 0 ) {				SetMisalignW((UB*)wp, GetMisalignW((UB*)wp) - (UW)sv);				sv -= (W)ladr;			}			SetMisalignW((UB*)wp, GetMisalignW((UB*)wp) + (UW)ladr + (UW)sv + (UW)lofs);		  	break;		  case R_MIPS_26:			if ( eli->vir_or_off != 0 ) {				if ( ELF32_ST_TYPE(symtbl[i].st_info) == STT_SECTION ){						nadr = (W)((UW)(TSD_RL1_VAL_MC1 - (UW)ladr) >> TSD_RL1_SFT_2);					*wp = (W)(( (UW)*wp & TSD_RL1_MSK_0XFC000000) | ( (UW)nadr & TSD_RL1_MSK_0X03FFFFFF));				} else {					/* *wp &= 0xfc000000U; */					*wp = (W)((UW)*wp & TSD_RL1_MSK_0XFC000000);				}				sv -= (W)ladr;			}			addend = (W)((UW)*wp & TSD_RL1_ADD_0X03FFFFFF);			if ( ELF32_ST_TYPE(symtbl[i].st_info) == STT_SECTION ){					nadr = (W)(((UW)addend << TSD_RL1_SFT_2) | ((UW)((W)ladr + (W)rp->r_offset) & TSD_RL1_MSK_0XF0000000));			}else{				nadr = TSD_RL1_SFT_MC1; 			}			nadr += (W)ladr + sv + lofs;			nadr = (W)((UW)nadr >> TSD_RL1_NAD_2);			*wp = (W)(( (UW)*wp & TSD_RL1_MSK_0XFC000000) | ( (UW)nadr & TSD_RL1_MSK_0X03FFFFFF));		  	break;		  case R_MIPS_HI16:			if ( ahi_info == NULL) {				ahi_info = Vmalloc( sizeof( Ahi_Info) * AHI_INFO_UNIT);				if ( ahi_info == NULL) {					err = E_NOMEM;					goto err_ret2;				}			}			if( ahi_infoused != 0 ) {				ahi_infonext = 0;				ahi_infoused = 0;			}			if( ahi_infomax <= ahi_infonext){				ahi_infotmp = Vrealloc( ahi_info, sizeof( Ahi_Info) * (UW)( ahi_infomax + AHI_INFO_UNIT));				if ( ahi_infotmp == NULL ) {					err = E_NOMEM;					goto err_ret2;				}				ahi_info = ahi_infotmp;				ahi_infomax += AHI_INFO_UNIT;			}			ahi_info[ ahi_infonext].addr = wp;			ahi_info[ ahi_infonext].val  = (UW)*wp << TSD_RL1_WP_16;			ahi_infonext++;		  	break;		  case R_MIPS_LO16:			if ( ahi_info == NULL) {				err = _ER_REC(TSD_LDE_ERR_4);				goto err_ret2;			}			if ( ahi_infoused == 0 ) {				ahi_infoused = 1;			  	for ( ind = 0; ind < ahi_infonext; ind++ ) {				  	ahl = (W)( ahi_info[ ind].val & TSD_RL1_MSK_0XFFFF0000) + ( short)((UW)*wp & TSD_RL1_MSK_0XFFFF);					if ( eli->vir_or_off != 0 ) {						ahl -= sv;						sv -= (W)ladr;					}					nadr = ahl + (W)ladr + sv + lofs;			  		*ahi_info[ ind].addr = (W)((((UW)( nadr - (short)nadr) >> TSD_RL1_SFT_16) & TSD_RL1_MSK_0X0000FFFF) 			  					| ( (UW)*ahi_info[ ind].addr & TSD_RL1_MSK_0XFFFF0000));				}				if ( 1 < ahi_infonext ) {					ahi_info[ 0] = ahi_info[ ahi_infonext - 1];					ahi_infonext = 1;				}			} else {			  	ahl = (W)( ahi_info[ 0].val & TSD_RL1_MSK_0XFFFF0000) + ( short)((UW)*wp & TSD_RL1_MSK_0XFFFF);				if ( eli->vir_or_off != 0 ) {					ahl -= sv;					sv -= (W)ladr;				}				nadr = ahl + (W)ladr + sv + lofs;			}		  	*wp = (W)(( (UW)nadr & TSD_RL1_MSK_0XFFFF) | ((UW)*wp & TSD_RL1_MSK_0XFFFF0000));		  	break;		  case R_MIPS_GPREL16:		  case R_MIPS_LITERAL:		  	if ( eli->vir_or_off != 0 ) {				break;		  	}			addend = (W)((UW)*wp & TSD_RL1_ADD_0XFFFF);			if ( ELF32_ST_TYPE(symtbl[i].st_info) == STT_SECTION ){				nadr = (W)((UW)((W)ladr + (W)((UW)( sv + addend + eli->gp ) & TSD_RL1_NAD_0X0000FFFF) - eli->gp) & TSD_RL1_NAD_0X0000FFFF);			}else{				nadr = (W)((UW)((W)ladr + sv + addend - eli->gp ) & TSD_RL1_NAD_0X0000FFFF);			}		  	*wp = (W)((UW)nadr | ((UW)*wp & TSD_RL1_MSK_0XFFFF0000));		  	break;		  case R_MIPS16_26:		  	if ( !eli->vir_or_off ) {				err = _ER_REC(TSD_LDE_ERR_7);				goto err_ret2;		  	}			hp = (UH*)wp;			addend =  (W)(TSD_RL1_VAL_MC2				| TSD_RL1_VAL_MC3				| TSD_RL1_VAL_MC4);			if ( ELF32_ST_TYPE(symtbl[i].st_info) == STT_SECTION ){					addend -= (W)ladr;			} else {				addend = 0;			}			sv -= (W)ladr;			/***/			if ( ELF32_ST_TYPE(symtbl[i].st_info) == STT_SECTION ){					nadr = (W)(((UW)addend << TSD_RL1_SFT_2) | ((UW)((W)ladr + (W)rp->r_offset) & TSD_RL1_MSK_0XF0000000));			} else {				nadr = TSD_RL1_SFT_MC1; 			}			nadr += (W)ladr + sv + lofs;			nadr = (W)((UW)nadr >> TSD_RL1_NAD_2);			*hp = (*hp & (UH)TSD_RL1_MSK_0XFC00) 				| (UH)TSD_RL1_VAL_MC5				| (UH)TSD_RL1_VAL_MC6;		  	*(hp+1) = (UH)nadr & (UH)0xffffU;		  	break;		  case	R_MIPS16_GPREL:		  	if ( !eli->vir_or_off ) {				err = _ER_REC(TSD_LDE_ERR_8);				goto err_ret2;		  	}		  	break;		  		  default:			err = _ER_REC(TSD_LDE_ERR_3);			goto err_ret2;		}	}	if( ahi_info != 0 ) { 		Vfree(ahi_info);	}	Vfree(reloc);	return E_OK;err_ret2:	if( ahi_info != 0 ) {		Vfree(ahi_info);	}	Vfree(reloc);err_ret1:	DEBUG_PRINT(("reloc1 err = %d (%d)\n", err, (UH)err));	return err;}/* * Obtain gp */LOCAL ER elf_get_gp( POBJ_HDR *pohdr, ELF_LoadInfo *eli, BzRead *bzr ){	ER	err;	W	n;	Elf32_RegInfo	reginfo;	/* Load register information */	n = (W)eli->reginf_size;	if( n <= 0) {		err = _ER_REC(TSD_LDE_ERR_1);		goto err_ret;	}	err = ReadProgFile(pohdr, (W)eli->reginf_fofs, (VB*)&reginfo, n, bzr);	if ( err < E_OK ) {		goto err_ret;	}

⌨️ 快捷键说明

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