📄 ldelf.c
字号:
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 */ 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)*wp & TSD_RL1_MSK_0X03FFFFFF) << TSD_RL1_SFT_2) - (UW)ladr) >> TSD_RL1_SFT_2); *wp = (W)(( (UW)*wp & TSD_RL1_MSK_0XFC000000) | ( (UW)nadr & TSD_RL1_MSK_0X03FFFFFF)); } else { *wp = (W)((UW)*wp & TSD_RL1_MSK_0XFC000000); } sv -= (W)ladr; } addend = (W)((UW)*wp & TSD_RL1_MSK_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_MCR; } nadr += (W)ladr + sv + lofs; nadr = (W)((UW)nadr >> TSD_RL1_SFT_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_SFT_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_MSK_0XFFFF); if ( ELF32_ST_TYPE(symtbl[i].st_info) == STT_SECTION ){ nadr = (W)((UW)((W)ladr + (W)((UW)( sv + addend + eli->gp ) & TSD_RL1_MSK_0X0000FFFF) - eli->gp) & TSD_RL1_MSK_0X0000FFFF); }else{ nadr = (W)((UW)((W)ladr + sv + addend - eli->gp ) & TSD_RL1_MSK_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)(((UW)(*hp & TSD_RL1_MSK_0X03E0) << TSD_RL1_SFT_13) | ((UW)(*hp & TSD_RL1_MSK_0X001F) << TSD_RL1_SFT_23) | ((UW)*(hp + 1) << TSD_RL1_SFT_2)); 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_MCR; } nadr += (W)ladr + sv + lofs; nadr = (W)((UW)nadr >> TSD_RL1_SFT_2); *hp = (UH)((*hp & TSD_RL1_MSK_0XFC00) | (( (UW)nadr & TSD_RL1_MSK_0X03E00000) >> TSD_RL1_SFT_21) | (( (UW)nadr & TSD_RL1_MSK_0X001F0000) >> TSD_RL1_SFT_11)); *(hp+1) = (UH)((UW)nadr & TSD_RL1_MSK_0XFFFF); 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*)®info, n, bzr); if ( err < E_OK ) { goto err_ret; } eli->gp = reginfo.ri_gp_value; return E_OK;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -