📄 ldelf.c
字号:
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;}/* * 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; W ofs; 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_ARM_PC24: if ( eli->vir_or_off != 0 ) { break; } ofs = (W)((UW)*wp << TSD_RL1_SFT_8) >> TSD_RL1_SFT_8; /* sign expansion for 24 bit value */ if ( ELF32_ST_TYPE(symtbl[i].st_info) == STT_SECTION ){ ofs -= (W)rp->r_offset >> TSD_RL1_MSK_2; } else { ofs += (sv - (W)rp->r_offset) >> TSD_RL1_MSK_2; } *wp = (W)(((UW)*wp & TSD_RL1_MSK_0XFF000000) | ((UW)ofs & TSD_RL1_MSK_0X00FFFFFF)); break; case R_ARM_ABS32: if ( eli->vir_or_off != 0 ) { sv = 0; *wp -= (W)ladr; } *wp += sv + (W)ladr + lofs; break; case R_ARM_THM_PC22: if ( !eli->vir_or_off ) { err = _ER_REC(TSD_LDE_ERR_6); goto err_ret2; } break; default: err = _ER_REC(TSD_LDE_ERR_3); goto err_ret2; } } Vfree(reloc); return E_OK;err_ret2: Vfree(reloc);err_ret1: DEBUG_PRINT(("reloc1 err = %d (%d)\n", err, (UH)err)); return err;}/* * ELF relocation */LOCAL ER elf_relocation( LDINFO *li, ELF_LoadInfo *eli, W lofs, BzRead *bzr ){ Elf32_Sym *symtbl; W n; ER err; if ( eli->symtbl_size == 0U ) { return E_OK; /* There is no relocation information. */ } /* Load symbol table. */ n = (W)eli->symtbl_size; symtbl = Vmalloc((size_t)n); if ( symtbl == NULL ) { err = E_NOMEM; goto err_ret1; } err = ReadProgFile(&(li->pohdr), (W)eli->symtbl_fofs, (VB*)symtbl, n, bzr); if ( err < E_OK ) { goto err_ret2; } n /= (W)sizeof(Elf32_Sym); /* Relocate text area */ err = reloc1(eli, &(li->pohdr), (W)eli->rel_text_fofs, (W)eli->rel_text_size, lofs, eli->text_ladr + lofs, (W)eli->text_size, symtbl, n, bzr); if ( err < E_OK ) { goto err_ret2; } /* Relocate data area */ err = reloc1(eli, &(li->pohdr), (W)eli->rel_data_fofs, (W)eli->rel_data_size, lofs, eli->data_ladr + lofs, (W)eli->data_size, symtbl, n, bzr); if ( err < E_OK ) { goto err_ret2; } Vfree(symtbl); return E_OK;err_ret2: Vfree(symtbl);err_ret1: DEBUG_PRINT(("elf_relocation err = %d (%d)\n", err, (UH)err)); return err;}/* * Load all ELF-format objects at once from the file. * lsid == 0 Load into system space, Relocated/not relocated * lsid != 0 Load into local space, Not relocated */EXPORT ER DirectLoad_elf( LDINFO *li, UW lsid, UW ldmode, Elf32_Ehdr *hdr, FP *entry, BzRead *bzr ){ ELF_LoadInfo eli; VB *ladr, *top_adr; UW npage; W lofs, sz; BOOL sys = ( (ldmode & LDMD_SYS) != 0U )? TRUE: FALSE; BOOL dyn = ( (ldmode & LDMD_DYN) != 0U )? TRUE: FALSE; BOOL relsec; ER err; if ( hdr->e_type == ET_EXEC ) { relsec = (HasDynSeg(hdr, &(li->pohdr), bzr) != 0 ) ? FALSE: HasRelSec(hdr, &(li->pohdr), bzr); } else { relsec = FALSE; } if ( dyn != 0 ) { /* Only relocatable format cannot be used for dynamic loading. */ if ( (hdr->e_type == ET_REL) || ((hdr->e_type == ET_EXEC) && relsec) ) { err = _ER_REC(TSD_LDE_ERR_1); goto err_ret1; } } else { /* Shared object format cannot be used for normal loading. */ if ( hdr->e_type == ET_DYN ) { err = _ER_REC(TSD_LDE_ERR_2); goto err_ret1; } } /* Obtain ELF loading information */ err = GetELFLoadInfo(&eli, hdr, &(li->pohdr), bzr, relsec); if ( err < E_OK ) { goto err_ret1; } top_adr = PageAlignL(eli.text_ladr); /* Load size */ npage = PageCount((UW)eli.bss_ladr + eli.bss_size - (UW)top_adr); sz = 0; if ( !dyn ) { /* Examine loading address */ if ( lsid == 0U ) { if ( (hdr->e_type == ET_EXEC) && !eli.vir_or_off ) { err = CheckSysLoadAddress(&eli); if ( err < E_OK ) { goto err_ret1; } } } else { if ( (hdr->e_type == ET_EXEC) && eli.vir_or_off ) { err = _ER_REC(TSD_LDE_ERR_3); goto err_ret1; } err = CheckLoadAddress(&eli); if ( err < E_OK ) { goto err_ret1; } sz = (W)PageCount(eli.stack_size); } } /* Check remaining memory */ err = ChkSysRsvMem((W)npage + sz); if ( err < E_OK ) { err = ERtoERR(err); goto err_ret1; } ladr = top_adr; if ( dyn || ((lsid == 0U) && ( (hdr->e_type != ET_EXEC) || ( (hdr->e_type == ET_EXEC) && eli.vir_or_off)))) { /* Reserve memory space for loading */ ladr = AllocMemorySpace((W)npage, lsid); if ( ladr == NULL ) { err = E_NOMEM; goto err_ret1; } } li->topadr = ladr; /* Loading address */ li->dpage = 0; /* Number of disk map pages */ li->mpage = npage; /* Number of memory map pages */ /* Set memory space Set text data to "Not cleared"; bss to "Cleared". */ sz = (eli.data_ladr + eli.data_size - top_adr) / PAGESIZE; err = MakeSpace(ladr, sz, (W)lsid, ( sys != 0 )? PTE_SMEM_NC: PTE_UMEM_NC); if ( err < E_OK ) { err = ERtoERR(err); goto err_ret2; } err = MakeSpace(ladr + (sz * PAGESIZE), (W)npage - sz, (W)lsid, ( sys != 0 )? PTE_SMEM_CL: PTE_UMEM_CL); if ( err < E_OK ) { err = ERtoERR(err); goto err_ret3; } lofs = ladr - top_adr; /* Load text area from file */ err = ReadProgFile(&(li->pohdr), (W)eli.text_fofs, eli.text_ladr + lofs, (W)eli.text_size, bzr); if ( err < E_OK ) { goto err_ret4; } /* Load data area from file */ err = ReadProgFile(&(li->pohdr), (W)eli.data_fofs, eli.data_ladr + lofs, (W)eli.data_size, bzr); if ( err < E_OK ) { goto err_ret4; } if ( (hdr->e_type == ET_REL) || ( (hdr->e_type == ET_EXEC) && eli.vir_or_off)) { /* Relocation */ err = elf_relocation(li, &eli, lofs, bzr); if ( err < E_OK ) { goto err_ret4; } } /* Set text area to not writable */ sz = eli.text_ladr + eli.text_size - top_adr; err = ChangeSpace(ladr, (INT)PageCount((UINT)sz), (INT)lsid, ( sys != 0 )? PTE_SMEM_RO: PTE_UMEM_RO); if ( err < E_OK ) { err = ERtoERR(err); goto err_ret4; } /* Synchronize cache memory */ SyncIDCacheArea(ladr, sz, lsid); /* Stack size */ li->stacksz = eli.stack_size; /* Start address */ *entry = (FP)((VB*)hdr->e_entry + lofs); return E_OK;err_ret4: sz = (W)npage;err_ret3: UnmakeSpace(ladr, sz, (W)lsid);err_ret2: if ( dyn || ((lsid == 0U) && ( (hdr->e_type != ET_EXEC) || ( (hdr->e_type == ET_EXEC) && eli.vir_or_off)))) { FreeMemorySpace(ladr, 0); }err_ret1: DEBUG_PRINT(("DirectLoad_elf err = %d (%d)\n", err, (UH)err)); return err;}/* * Load ELF-format objects on demand from the file. * lsid == 0 Load into system space, Not relocated * lsid != 0 Load into local space, Not relocated */EXPORT ER DemandLoad_elf( LDINFO *li, UW lsid, UW ldmode, Elf32_Ehdr *hdr, ID did, PhyBlk *pb, FP *entry, BzRead *bzr ){ ELF_LoadInfo eli; MapMode mode; PhyBlk *mpb; UW top, npg, ofs, n, loadofs; VB *ladr, *loadaddr = NULL; BOOL sys = ( (ldmode & LDMD_SYS) != 0U )? TRUE: FALSE; BOOL dyn = ( (ldmode & LDMD_DYN) != 0U )? TRUE: FALSE; BOOL relsec; ER err; if ( hdr->e_type == ET_EXEC ) { relsec = (HasDynSeg(hdr, &(li->pohdr), bzr) != 0 ) ? FALSE: HasRelSec(hdr, &(li->pohdr), bzr); } else { relsec = FALSE; } if ( dyn != 0 ) { /* Only relocatable format cannot be used for dynamic loading. */ if ( (hdr->e_type == ET_REL) || ((hdr->e_type == ET_EXEC) && relsec) ) { err = _ER_REC(TSD_LDE_ERR_1); goto err_ret1; } } else { /* Only fixed-address format can be used for normal loading. */ if ( (hdr->e_type != ET_EXEC) || relsec ) { err = _ER_REC(TSD_LDE_ERR_2); goto err_ret1; } } /* Obtain ELF loading information */ err = GetELFLoadInfo(&eli, hdr, &(li->pohdr), bzr, relsec); if ( err < E_OK ) { goto err_ret1; } n = 0; if ( !dyn ) { /* Examine loading address */ if ( lsid == 0U ) { err = CheckSysLoadAddress(&eli); if ( err < E_OK ) { goto err_ret1; } } else { err = CheckLoadAddress(&eli); if ( err < E_OK ) { goto err_ret1; } n = PageCount(eli.stack_size); } } /* Check remaining memory */ err = ChkSysRsvMem((W)(PageCount(eli.data_size + eli.bss_size) + n)); if ( err < E_OK ) { err = ERtoERR(err); goto err_ret1; } loadofs = 0; if ( dyn != 0 ) { /* Reserve memory space for loading */ n = ofs = PageOffset((VP)eli.text_fofs); npg = PageCount(ofs + eli.text_size); ofs = PageOffset((VP)eli.data_fofs); npg += PageCount(ofs + eli.data_size + eli.bss_size); loadaddr = AllocMemorySpace((W)npg, lsid); if ( loadaddr == NULL ) { err = E_NOMEM; goto err_ret1; } loadofs = (UW)loadaddr - ((UW)eli.text_ladr - n); } /* Map attribute */ mode.resv = 0; mode.rank = MapRankPROG; mode.real = 0; mode.clear = MapNoClr; mode.level = ( sys != 0 )? (MapSystem | MapExecute | MapRead): (MapUser | MapExecute | MapRead); mode.space = lsid; mode.info = MAP_LOADPROG; /* Text area mapping */ top = eli.text_fofs / (UW)PAGESIZE; ofs = PageOffset((VP)eli.text_fofs); npg = PageCount(ofs + eli.text_size); mpb = CutPhyBlks(did, pb, top, npg); if ( mpb == NULL ) { err = _ER_REC(TSD_LDE_ERR_3); goto err_ret2; } mode.addr = eli.text_ladr - ofs + loadofs; err = MapDisk(did, mpb, &mode); Ifree(mpb); if ( err < E_OK ) { goto err_ret2; } li->mid[TSD_DLE_POS_0] = (ID)err; /* Map ID */ li->topadr = mode.addr; /* Loading address */ li->dpage = npg; /* Number of disk map pages */ if ( isValidCopyOnWrite(did) != 0 ) { /* Data area mapping */ top = eli.data_fofs / (UW)PAGESIZE; ofs = PageOffset((VP)eli.data_fofs); npg = PageCount(ofs + eli.data_size); mpb = CutPhyBlks(did, pb, top, npg); if ( mpb == NULL ) { err = _ER_REC(TSD_LDE_ERR_4); goto err_ret3; } mode.addr = eli.data_ladr - ofs + loadofs; err = MapDisk(did, mpb, &mode); Ifree(mpb); if ( err < E_OK ) { goto err_ret3; } li->mid[TSD_DLE_POS_1] = (ID)err; /* Map ID */ li->dpage += npg; /* Number of disk map pages */ /* Set data area memory space to copy-on-write. */ err = ChangeSpace(mode.addr, (W)npg, (W)lsid, ( sys != 0 )? PTE_SMEM_CW: PTE_UMEM_CW); if ( err < E_OK ) { err = ERtoERR(err); goto err_ret4; } /* Set memory space in bss area */ n = (UW)((VB*)PageAlignU(eli.bss_ladr) - eli.bss_ladr); li->mpage = ( eli.bss_size > n )? /* Number of memory map pages */ PageCount(eli.bss_size - n): 0; ladr = eli.bss_ladr + loadofs; err = MakeSpace(ladr + n, (W)li->mpage, (W)lsid, ( sys != 0 )? PTE_SMEM_CL: PTE_UMEM_CL); if ( err < E_OK ) { err = ERtoERR(err); goto err_ret4; } /* Since the boundary between data and bss areas is not a page boundary, clear the part of bss area included in the data area. */ if ( n > 0U ) { bzero(ladr, (size_t)n); } } else { /* Load data area */ ofs = PageOffset(eli.data_ladr); li->mpage = PageCount(ofs + eli.data_size + eli.bss_size); ladr = eli.data_ladr - ofs + loadofs; /* Set memory space Set data to "Not cleared"; bss to "Cleared". */ npg = (ofs + eli.data_size) / (UW)PAGESIZE; err = MakeSpace(ladr, (W)npg, (W)lsid, ( sys != 0 )? PTE_SMEM_NC: PTE_UMEM_NC); if ( err < E_OK ) { err = ERtoERR(err); goto err_ret4; } err = MakeSpace(ladr + (npg * (UW)PAGESIZE), (W)li->mpage - (W)npg, (W)lsid, ( sys != 0 )? PTE_SMEM_CL: PTE_UMEM_CL); if ( err < E_OK ) { err = ERtoERR(err); goto err_ret5; } /* Load data area from file */ err = ReadProgFile(&(li->pohdr), (W)eli.data_fofs, eli.data_ladr + loadofs, (W)eli.data_size, bzr); if ( err < E_OK ) { goto err_ret6; } } /* Stack size */ li->stacksz = eli.stack_size; /* Start address */ *entry = (FP)((VB*)hdr->e_entry + loadofs); return E_OK;err_ret6: npg = li->mpage;err_ret5: UnmakeSpace(ladr, (W)npg, (W)lsid);err_ret4: if ( li->mid[TSD_DLE_POS_1] > 0 ) { UnmapDisk(li->mid[TSD_DLE_POS_1], MD_RDONLY); }err_ret3: UnmapDisk(li->mid[TSD_DLE_POS_0], MD_RDONLY);err_ret2: if ( dyn != 0 ) { FreeMemorySpace(loadaddr, lsid); }err_ret1: DEBUG_PRINT(("DemandLoad_elf err = %d (%d)\n", err, (UH)err)); return err;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -