📄 loadelflib.c
字号:
SYM_INFO_TBL symInfoTbl /* array of absolute symbol values and types */ ) { UINT32 value; /* relocation value */ value = pRelocCmd->r_addend - (UINT32)symInfoTbl [ELF32_R_SYM (pRelocCmd->r_info)].pAddr; *((UINT16 *)pAdrs) = (UINT16) HA_VALUE (value); return (OK); }#ifdef INCLUDE_SDA/********************************************************************************* elfPpcSdaRel16Reloc - perform the R_PPC_SDAREL relocation* * This routine handles the R_PPC_SDAREL relocation (half16, S + A - SDA_BASE).** RETURNS : OK or ERROR if computed value can't be written down in target* memory or offset too large for relocation.*/LOCAL STATUS elfPpcSdaRel16Reloc ( void * pAdrs, /* relocation address */ Elf32_Rela * pRelocCmd, /* points to a relocation structure */ SYM_INFO_TBL symInfoTbl, /* array of absolute symbol values and types */ SEG_INFO * pSeg /* section addresses and sizes */ ) { UINT32 value; /* relocation value */ if ((symInfoTbl[ELF32_R_SYM (pRelocCmd->r_info)].type & SYM_SDA) != SYM_SDA) { printErr ("Referenced symbol does not belong to SDA.\n"); return (ERROR); } value = (UINT32)symInfoTbl [ELF32_R_SYM (pRelocCmd->r_info)].pAddr + pRelocCmd->r_addend - (UINT32)(((SDA_INFO *)pSeg->pAdnlInfo)->sdaBaseAddr); /* * Do some checking: R_PPC_SDAREL relocation must fit in * 16 bits. */ if (!CHECK_LOW16 (value)) { printErr ("Relocation value does not fit in 16 bits.\n"); return (ERROR); } /* handle unalignment */ *((UINT16 *)pAdrs) = (UINT16) value; return (OK); }/********************************************************************************* elfPpcEmbSda21Reloc - perform the R_PPC_EMB_SDA21 relocation* * This routine handles the R_PPC_EMB_SDA21 relocation. The most significant 11* bits of the address pointed to by the relocation entry are untouched (opcode* and rS/rD field). The next most significant 5 bits (rA field) will hold the* value 13 (SDA symbol) or 2 (SDA2 symbol). The least significant 16 bits are* set to the two's complement of the following computation:* symbol address + r_addend value - SDA_BASE (or SDA2_BASE) value.** RETURNS : OK or ERROR if computed value can't be written down in target* memory.*/LOCAL STATUS elfPpcEmbSda21Reloc ( void * pAdrs, /* relocation address */ Elf32_Rela * pRelocCmd, /* points to a relocation structure */ SYM_INFO_TBL symInfoTbl, /* array of absolute symbol values and types */ SEG_INFO * pSeg /* section addresses and sizes */ ) { UINT32 value; /* relocation value */ UINT32 instr; /* previous instruction in memory */ BOOL symbolIsInSda; /* TRUE if symbol belongs to the SDA area */ BOOL sizeFit; /* TRUE if computed value is 16 bit long */ /* * Only symbols (or reference to) belonging to a .sdata, .sbss, .sdata2 * or .sbss2 section are supported. */ switch (symInfoTbl[ELF32_R_SYM (pRelocCmd->r_info)].type & SYM_SDA_MASK) { case (SYM_SDA): symbolIsInSda = TRUE; break; case (SYM_SDA2): symbolIsInSda = FALSE; break; default: printErr ("Referenced symbol does not belong to SDA/SDA2.\n"); return (ERROR); break; } value = (UINT32)symInfoTbl [ELF32_R_SYM (pRelocCmd->r_info)].pAddr + pRelocCmd->r_addend; instr = *((UINT32 *)pAdrs); /* * We applied here the same relocation process as the GNU does since * the EABI document is totally phony on this one... */ if (symbolIsInSda) { value -= (UINT32)(((SDA_INFO *)pSeg->pAdnlInfo)->sdaBaseAddr); sizeFit = CHECK_LOW16_STRICT (value); value = (instr & ~RA_MSK) | GPR13_MSK | ((~value + 1) & 0xffff); } else { value -= (UINT32)(((SDA_INFO *)pSeg->pAdnlInfo)->sda2BaseAddr); sizeFit = CHECK_LOW16_STRICT (value); value = (instr & ~RA_MSK) | GPR2_MSK | ((~value + 1) & 0xffff); } /* * Do some checking: R_PPC_EMB_SDA21 relocation must fit in * 21 bits, thus the offset must fit in 16 bits. */ if (!sizeFit) { printErr ("Relocation offset does not fit in 16 bits.\n"); return (ERROR); } *((UINT32 *)pAdrs) = value; return (OK); }/********************************************************************************* elfPpcEmbSda2RelReloc - perform the R_PPC_EMB_SDA2REL relocation* * This routine handles the R_PPC_EMB_SDA2REL relocation (uhalf16,* S + A - SDA2_BASE).** RETURNS : OK or ERROR if computed value can't be written down in target* memory.*/LOCAL STATUS elfPpcEmbSda2RelReloc ( void * pAdrs, /* relocation address */ Elf32_Rela * pRelocCmd, /* points to a relocation structure */ SYM_INFO_TBL symInfoTbl, /* array of absolute symbol values and types */ SEG_INFO * pSeg /* section addresses and sizes */ ) { UINT32 value; /* relocation value */ if ((symInfoTbl[ELF32_R_SYM (pRelocCmd->r_info)].type & SYM_SDA2) != SYM_SDA2) { printErr ("Referenced symbol does not belong to SDA2.\n"); return (ERROR); } value = (UINT32)symInfoTbl [ELF32_R_SYM (pRelocCmd->r_info)].pAddr + pRelocCmd->r_addend - (UINT32)(((SDA_INFO *)pSeg->pAdnlInfo)->sda2BaseAddr); *((UINT16 *)pAdrs) = (UINT16) value; return (OK); }/********************************************************************************* elfPpcEmbRelSdaReloc - perform the R_PPC_EMB_RELSDA relocation* * This routine handles the R_PPC_EMB_RELSDA relocation.** RETURNS : OK or ERROR if computed value can't be written down in target* memory.*/LOCAL STATUS elfPpcEmbRelSdaReloc ( void * pAdrs, /* relocation address */ Elf32_Rela * pRelocCmd, /* points to a relocation structure */ SYM_INFO_TBL symInfoTbl, /* array of absolute symbol values and types */ SEG_INFO * pSeg /* section addresses and sizes */ ) { UINT32 value; /* relocation value */ BOOL symbolIsInSda; /* TRUE if symbol belongs to the SDA area */ /* * Only symbols (or reference to) belonging to a .sdata, .sbss, .sdata2 * or .sbss2 section are supported. */ switch (symInfoTbl[ELF32_R_SYM (pRelocCmd->r_info)].type & SYM_SDA_MASK) { case (SYM_SDA): symbolIsInSda = TRUE; break; case (SYM_SDA2): symbolIsInSda = FALSE; break; default: printErr ("Referenced symbol does not belong to SDA/SDA2.\n"); return (ERROR); break; } value = (UINT32)symInfoTbl [ELF32_R_SYM (pRelocCmd->r_info)].pAddr + pRelocCmd->r_addend; if (symbolIsInSda) value -= (UINT32)(((SDA_INFO *)pSeg->pAdnlInfo)->sdaBaseAddr); else value -= (UINT32)(((SDA_INFO *)pSeg->pAdnlInfo)->sda2BaseAddr); /* * Do some checking: R_PPC_EMB_RELSDA 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); }#endif /* INCLUDE_SDA */ #endif /* CPU_FAMILY == PPC */#if (CPU_FAMILY == SIMSPARCSOLARIS)/********************************************************************************* elfSparcSegReloc - 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.** RETURNS: OK or ERROR*/STATUS elfSparcSegReloc ( 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, /* pointer to section header table */ 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_Shdr * pScnHdr; /* section to which the relocations apply */ 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 */ pScnHdr = pScnHdrTbl + pRelHdr->sh_info; /* Some sanity checking */ if (pRelHdr->sh_type != SHT_RELA) { errnoSet (S_loadElfLib_RELA_SECTION); printErr ("Relocation sections of type %d are not supported.\n", pRelHdr->sh_type); return (OK); } if (pRelHdr->sh_entsize != sizeof (Elf32_Rela)) { printErr ("Wrong relocation entry size.\n"); 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_SPARC_8): if (elfSparc8Reloc (pAdrs, &relocCmd, symInfoTbl) != OK) status = ERROR; break; case (R_SPARC_16): if (elfSparc16Reloc (pAdrs, &relocCmd, symInfoTbl) != OK) status = ERROR; break; case (R_SPARC_32): if (elfSparc32Reloc (pAdrs, &relocCmd, symInfoTbl) != OK) status = ERROR; break; case (R_SPARC_DISP8): if (elfSparcDisp8Reloc(pAdrs, &relocCmd, symInfoTbl) != OK) status = ERROR; break; case (R_SPARC_DISP16): if (elfSparcDisp16Reloc(pAdrs, &relocCmd, symInfoTbl) != OK) status = ERROR; break; case (R_SPARC_DISP32): if (elfSparcDisp32Reloc(pAdrs, &relocCmd, symInfoTbl) != OK) status = ERROR; break; case (R_SPARC_WDISP30): if (elfSparcWDisp30Reloc (pAdrs, &relocCmd, symInfoTbl) != OK) status = ERROR; break; case (R_SPARC_WDISP22): if (elfSparcWDisp22Reloc (pAdrs, &relocCmd, symInfoTbl) != OK) status = ERROR; break; case (R_SPARC_HI22): if (elfSparcHi22Reloc (pAdrs, &relocCmd, symInfoTbl) != OK) status = ERROR; break; case (R_SPARC_22): if (elfSparc22Reloc (pAdrs, &relocCmd, symInfoTbl) != OK) status = ERROR; break; case (R_SPARC_13): if (elfSparc13Reloc (pAdrs, &relocCmd, symInfoTbl) != OK) status = ERROR; break; case (R_SPARC_LO10): if (elfSparcLo10Reloc (pAdrs, &relocCmd, symInfoTbl) != OK) status = ERROR; break; case (R_SPARC_PC10): if (elfSparcPc10Reloc (pAdrs, &relocCmd, symInfoTbl) != OK) status = ERROR; break; case (R_SPARC_PC22): if (elfSparcPc22Reloc (pAdrs, &relocCmd, symInfoTbl) != OK) status = ERROR; break; case (R_SPARC_UA32): case (R_SPARC_GLOB_DAT): if (elfSparcUa32Reloc (pAdrs, &relocCmd, symInfoTbl) != OK) status = ERROR; break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -