📄 loadelflib.c
字号:
} /********************************************************************************* elfRelocRelEntryRd - read in ELF relocation entry for REL relocation* * This routine fills a relocation structure with information from the object* module in memory. ** RETURNS : the address of the next relocation entry or ERROR if entry not read.*/int elfRelocRelEntryRd ( int fd, /* file to read in */ int posRelocEntry, /* position of reloc. command in object file */ Elf32_Rel * pReloc /* ptr on relocation structure to fill */ ) { int nbytes; /* number of bytes to copy */ nbytes = sizeof (Elf32_Rel); if ((ioctl (fd, FIOSEEK, posRelocEntry)) == ERROR) return ERROR; if ((fioRead (fd, (char *) pReloc, nbytes)) == ERROR) return ERROR; return (posRelocEntry + nbytes); }#if (CPU_FAMILY == PPC)/********************************************************************************* elfPpcSegReloc - perform relocation for the PowerPC family** This routine reads the specified relocation command segment and performs* all the relocations specified therein. Only relocation command from sections* with section type SHT_RELA are considered here.** Absolute symbol addresses are looked up in the 'externals' table.** This function handles the following types of relocation commands* for the PowerPC processor:** System V ABI:* R_PPC_NONE : none* R_PPC_ADDR32 : word32, S + A* R_PPC_ADDR24 : low24, (S + A) >> 2* R_PPC_ADDR16 : half16, S + A* R_PPC_ADDR16_LO : half16, #lo(S + A)* R_PPC_ADDR16_HI : half16, #hi(S + A)* R_PPC_ADDR16_HA : half16, #ha(S + A)* R_PPC_ADDR14 : low14, (S + A) >> 2* R_PPC_ADDR14_BRTAKEN : low14, (S + A) >> 2* R_PPC_ADDR14_BRNTAKEN : low14, (S + A) >> 2* R_PPC_REL24 : low24, (S + A - P) >> 2* R_PPC_REL14 : low14, (S + A - P) >> 2* R_PPC_REL14_BRTAKEN : low14, (S + A - P) >> 2* R_PPC_REL14_BRNTAKEN : low14, (S + A - P) >> 2* R_PPC_UADDR32 : word32, S + A* R_PPC_UADDR16 : half16, S + A* R_PPC_REL32 : word32, S + A - P* R_PPC_SDAREL : half16, S + A - SDA_BASE** PowerPC EABI:* R_PPC_EMB_NADDR32 : uword32, A - S* R_PPC_EMB_NADDR16 : uhalf16, A - S* R_PPC_EMB_NADDR16_LO : uhalf16, #lo(A - S)* R_PPC_EMB_NADDR16_HI : uhalf16, #hi(A - S)* R_PPC_EMB_NADDR16_HA : uhalf16, #ha(A - S)* R_PPC_EMB_MRKREF : none* R_PPC_EMB_SDA21 : ulow21, complex* R_PPC_EMB_SDA2REL : uhalf16, S + A - SDA2_BASE* R_PPC_EMB_RELSDA : uhalf16, complex** RETURNS: OK or ERROR*/LOCAL STATUS elfPpcSegReloc ( int fd, /* file to read in */ MODULE_ID moduleId, /* module id */ int loadFlag, /* not used */ int posCurRelocCmd,/* position of current relocation command */ Elf32_Shdr * pScnHdrTbl, /* not used */ Elf32_Shdr * pRelHdr, /* pointer to relocation section header */ SCN_ADRS * pScnAddr, /* section address once loaded */ SYM_INFO_TBL symInfoTbl, /* array of absolute symbol values and types */ Elf32_Sym * pSymsArray, /* pointer to symbols array */ SYMTAB_ID symTbl, /* not used */ SEG_INFO * pSeg /* section addresses and sizes */ ) { Elf32_Rela relocCmd; /* relocation structure */ UINT32 relocNum; /* number of reloc entries in section */ UINT32 relocIdx; /* index of the reloc entry being processed */ void * pAdrs; /* relocation address */ Elf32_Sym * pSym; /* pointer to an external symbol */ STATUS status = OK; /* whether or not the relocation was ok */ /* Some sanity checking */ if (pRelHdr->sh_type != SHT_RELA) { errnoSet (S_loadElfLib_RELA_SECTION); return (OK); } if (pRelHdr->sh_entsize != sizeof (Elf32_Rela)) { errnoSet (S_loadElfLib_RELA_SECTION); return (ERROR); } /* Relocation loop */ relocNum = pRelHdr->sh_size / pRelHdr->sh_entsize; for (relocIdx = 0; relocIdx < relocNum; relocIdx++) { /* read relocation command */ if ((posCurRelocCmd = elfRelocRelaEntryRd (fd, posCurRelocCmd, &relocCmd)) == ERROR) { errnoSet (S_loadElfLib_READ_SECTIONS); return (ERROR); } /* * Calculate actual remote address that needs relocation, and * perform external or section relative relocation. */ pAdrs = (void *)((Elf32_Addr)*pScnAddr + relocCmd.r_offset); pSym = pSymsArray + ELF32_R_SYM (relocCmd.r_info); /* * System V ABI defines the following notations: * * A - the addend used to compute the value of the relocatable field. * S - the value (address) of the symbol whose index resides in the * relocation entry. Note that this function uses the value stored * in the external symbol value array instead of the symbol's * st_value field. * P - the place (section offset or address) of the storage unit being * relocated (computed using r_offset) prior to the relocation. */ switch (ELF32_R_TYPE (relocCmd.r_info)) { case (R_PPC_NONE): /* none */ break; case (R_PPC_ADDR32): /* word32, S + A */ if (elfPpcAddr32Reloc (pAdrs, &relocCmd, symInfoTbl, moduleId) != OK) status = ERROR; break; case (R_PPC_ADDR24): /* low24, (S+A) >> 2 */ if (elfPpcAddr24Reloc (pAdrs, &relocCmd, symInfoTbl) != OK) status = ERROR; break; case (R_PPC_ADDR16): /* half16, S + A */ if (elfPpcAddr16Reloc (pAdrs, &relocCmd, symInfoTbl) != OK) status = ERROR; break; case (R_PPC_ADDR16_LO): /* half16, #lo(S + A) */ if (elfPpcAddr16LoReloc (pAdrs, &relocCmd, symInfoTbl) != OK) status = ERROR; break; case (R_PPC_ADDR16_HI): /* half16, #hi(S + A) */ if (elfPpcAddr16HiReloc (pAdrs, &relocCmd, symInfoTbl) != OK) status = ERROR; break; case (R_PPC_ADDR16_HA): /* half16, #ha(S + A) */ if (elfPpcAddr16HaReloc (pAdrs, &relocCmd, symInfoTbl) != OK) status = ERROR; break; case (R_PPC_ADDR14): case (R_PPC_ADDR14_BRTAKEN): case (R_PPC_ADDR14_BRNTAKEN): /* low14, (S+A) >> 2 */ if (elfPpcAddr14Reloc (pAdrs, &relocCmd, symInfoTbl) != OK) status = ERROR; break; case (R_PPC_REL24): /* low24, (S+A-P) >> 2*/ if (elfPpcRel24Reloc (pAdrs, &relocCmd, symInfoTbl) != OK) status = ERROR; break; case (R_PPC_REL14): case (R_PPC_REL14_BRTAKEN): case (R_PPC_REL14_BRNTAKEN): /* low14, (S+A-P) >> 2*/ if (elfPpcRel14Reloc (pAdrs, &relocCmd, symInfoTbl) != OK) status = ERROR; break; case (R_PPC_UADDR32): /* word32, S + A */ if (elfPpcUaddr32Reloc (pAdrs, &relocCmd, symInfoTbl) != OK) status = ERROR; break; case (R_PPC_UADDR16): /* half16, S + A */ if (elfPpcUaddr16Reloc (pAdrs, &relocCmd, symInfoTbl) != OK) status = ERROR; break; case (R_PPC_REL32): /* word32, S + A - P */ if (elfPpcRel32Reloc (pAdrs, &relocCmd, symInfoTbl) != OK) status = ERROR; break; case (R_PPC_EMB_NADDR32): /* uword32, A - S */ if (elfPpcEmbNaddr32Reloc (pAdrs, &relocCmd, symInfoTbl) != OK) status = ERROR; break; case (R_PPC_EMB_NADDR16): /* uhalf16, A - S */ if (elfPpcEmbNaddr16Reloc (pAdrs, &relocCmd, symInfoTbl) != OK) status = ERROR; break; case (R_PPC_EMB_NADDR16_LO): /* uhalf16, #lo(A - S)*/ if (elfPpcEmbNaddr16LoReloc (pAdrs, &relocCmd, symInfoTbl) != OK) status = ERROR; break; case (R_PPC_EMB_NADDR16_HI): /* uhalf16, #hi(A - S)*/ if (elfPpcEmbNaddr16HiReloc (pAdrs, &relocCmd, symInfoTbl) != OK) status = ERROR; break; case (R_PPC_EMB_NADDR16_HA): /* uhalf16, #ha(A - S)*/ if (elfPpcEmbNaddr16HaReloc (pAdrs, &relocCmd, symInfoTbl) != OK) status = ERROR; break; case (R_PPC_EMB_MRKREF): /* none */ break;#ifdef INCLUDE_SDA case (R_PPC_SDAREL): /* half16, S + A - SDA_BASE */ if (elfPpcSdaRel16Reloc (pAdrs, &relocCmd, symInfoTbl, pSeg) != OK) status = ERROR; break; case (R_PPC_EMB_SDA21): /* ulow21, complex ! */ if (elfPpcEmbSda21Reloc (pAdrs, &relocCmd, symInfoTbl, pSeg) != OK) status = ERROR; break; case (R_PPC_EMB_SDA2REL): /* uhalf16, S + A - SDA2_BASE */ if (elfPpcEmbSda2RelReloc (pAdrs, &relocCmd, symInfoTbl, pSeg) != OK) status = ERROR; break; case (R_PPC_EMB_RELSDA): /* uhalf16, complex ! */ if (elfPpcEmbRelSdaReloc (pAdrs, &relocCmd, symInfoTbl, pSeg) != OK) status = ERROR; break;#endif /* INCLUDE_SDA */ default: printErr ("Unsupported relocation type %d\n", ELF32_R_TYPE (relocCmd.r_info)); status = ERROR; break; } } return (status); }/********************************************************************************* elfPpcAddr32Reloc - perform the R_PPC_ADDR32 relocation* * This routine handles the R_PPC_ADDR32 relocation (word32, S + A).** RETURNS : OK or ERROR if computed value can't be written down in target* memory.*/LOCAL STATUS elfPpcAddr32Reloc ( void * pAdrs, /* relocation address */ Elf32_Rela * pRelocCmd, /* points to a relocation structure */ SYM_INFO_TBL symInfoTbl, /* array of absolute symbol values and types */ MODULE_ID moduleId /* module id */ ) { UINT32 value; /* relocation value */ value = (UINT32)symInfoTbl [ELF32_R_SYM (pRelocCmd->r_info)].pAddr + pRelocCmd->r_addend; *((UINT32 *)pAdrs) = value; return (OK); }/********************************************************************************* elfPpcAddr24Reloc - perform the R_PPC_ADDR24 relocation* * This routine handles the R_PPC_ADDR24 relocation (low24, S + A).** RETURNS : OK or ERROR if computed value can't be written down in target* memory or offset too large for relocation.*/LOCAL STATUS elfPpcAddr24Reloc ( void * pAdrs, /* relocation address */ Elf32_Rela * pRelocCmd, /* points to a relocation structure */ SYM_INFO_TBL symInfoTbl /* array of absolute symbol values and types */ ) { UINT32 value; /* relocation value */ UINT32 offset; /* previous value in memory */ value = (UINT32)symInfoTbl [ELF32_R_SYM (pRelocCmd->r_info)].pAddr + pRelocCmd->r_addend; /* * Do some checking: R_PPC_ADDR24 relocation must fit in * 24 bits and lower 2 bits should always be null. */ if (!CHECK_LOW24 (value)) { printErr ("Relocation value does not fit in 24 bits.\n"); return (ERROR); } if (value & 0x3) printErr ("Relocation value's lower 2 bits not zero.\n"); offset = *((UINT32 *)pAdrs); LOW24_INSERT (offset, value); *((UINT32 *)pAdrs) = offset; return (OK); }/********************************************************************************* elfPpcAddr16Reloc - perform the R_PPC_ADDR16 relocation* * This routine handles the R_PPC_ADDR16 relocation (half16, S + A).** RETURNS : OK or ERROR if computed value can't be written down in target* memory or offset too large for relocation.*/LOCAL STATUS elfPpcAddr16Reloc ( void * pAdrs, /* relocation address */ Elf32_Rela * pRelocCmd, /* points to a relocation structure */ SYM_INFO_TBL symInfoTbl /* array of absolute symbol values and types */ ) { UINT32 value; /* relocation value */ value = (UINT32)symInfoTbl [ELF32_R_SYM (pRelocCmd->r_info)].pAddr + pRelocCmd->r_addend; /* * Do some checking: R_PPC_ADDR16 relocation must fit in * 16 bits. */ if (!CHECK_LOW16 (value)) { printErr ("Relocation value does not fit in 16 bits.\n"); return (ERROR); } *((UINT16 *)pAdrs) = (UINT16) value; return (OK); }/********************************************************************************* elfPpcAddr16LoReloc - perform the R_PPC_ADDR16_LO relocation* * This routine handles the R_PPC_ADDR16_LO relocation (half16, #lo(S + A)).** RETURNS : OK or ERROR if computed value can't be written down in target* memory.*/LOCAL STATUS elfPpcAddr16LoReloc ( void * pAdrs, /* relocation address */ Elf32_Rela * pRelocCmd, /* points to a relocation structure */ SYM_INFO_TBL symInfoTbl /* array of absolute symbol values and types */ ) { UINT32 value; /* relocation value */ value = (UINT32)symInfoTbl [ELF32_R_SYM (pRelocCmd->r_info)].pAddr + pRelocCmd->r_addend; *((UINT16 *)pAdrs) = (UINT16) LO_VALUE (value); return (OK); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -