📄 loadelflib.c
字号:
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 */ posCurRelocCmd = elfRelocRelaEntryRd (fd, posCurRelocCmd, &relocCmd); /* * 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); }/********************************************************************************* elfPpcAddr16HiReloc - perform the R_PPC_ADDR16_HI relocation* * This routine handles the R_PPC_ADDR16_HI relocation (half16, #hi(S + A)).** RETURNS : OK or ERROR if computed value can't be written down in target* memory.*/LOCAL STATUS elfPpcAddr16HiReloc ( 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) (HI_VALUE (value)); return (OK); }/********************************************************************************* elfPpcAddr16HaReloc - perform the R_PPC_ADDR16_HA relocation* * This routine handles the R_PPC_ADDR16_HA relocation (half16, #ha(S + A)).** RETURNS : OK or ERROR if computed value can't be written down in target* memory.*/LOCAL STATUS elfPpcAddr16HaReloc ( 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) HA_VALUE (value); return (OK); }/********************************************************************************* elfPpcAddr14Reloc - perform the R_PPC_ADDR14 relocation* * This routine handles the R_PPC_ADDR14 relocation (low14, (S + A) >> 2).** RETURNS : OK or ERROR if computed value can't be written down in target* memory or offset too large for relocation.*/LOCAL STATUS elfPpcAddr14Reloc ( 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_ADDR14* relocations must fit in * 14 bits and lower 2 bits should always be null. */ if (!CHECK_LOW14 (value)) { printErr ("Relocation value does not fit in 14 bits.\n"); return (ERROR); } if (value & 0x3) printErr ("Relocation value's lower 2 bits not zero.\n"); offset = *((UINT32 *)pAdrs); LOW14_INSERT (offset, value); *((UINT32 *)pAdrs) = offset; return (OK); }/********************************************************************************* elfPpcRel24Reloc - perform the R_PPC_REL24 relocation* * This routine handles the R_PPC_REL24 relocation (low24, (S + A - P) >> 2).
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -