📄 loadelflib.c
字号:
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 == MIPS)/********************************************************************************* 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.**/LOCAL 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); ioctl(fd, FIOSEEK, posRelocEntry); fioRead(fd, (char *) pReloc, nbytes); return (posRelocEntry + nbytes); }/********************************************************************************* relSegmentRela - perform relocation commands for MIPS RELA segments** This routine reads a relocation command segments and performs all the* relocations specified therein. The relocation commands reside in the* sections with section type SHT_RELA. RELA segments are assumed to contain* SDE style relocations** RETURNS: OK or ERROR** NOMANUAL*/LOCAL STATUS relMipsSegmentRela ( int fd, /* file descriptor */ Elf32_Shdr * pSh, /* relocation section header */ SCN_ADRS * pScnAddr, /* section address once loaded */ Elf32_Sym * pSymsArray, /* elf symbols */ int posRelocEntry, /* relocation information */ SYM_INFO_TBL symInfoTbl /* array of absolute symbol values and types */ ) { int iy; int nRel; UINT32 insn; void * relBaseAddr; UINT32 relVal; void * relAddr; Elf32_Rela relocCmd; /* relocation structure */ Elf32_Sym * pst; /* symbol table entry */ if (pSh->sh_entsize != sizeof (Elf32_Rela)) { errnoSet (S_loadElfLib_RELA_SECTION); return (ERROR); } nRel = pSh->sh_size / pSh->sh_entsize; relBaseAddr = (void *) *pScnAddr; DBG(("\nrelBaseAddr = 0x%08x\n", relBaseAddr)); for (iy = 0; iy < nRel; iy++) { posRelocEntry = elfRelocRelaEntryRd (fd, posRelocEntry, &relocCmd); if (ELF32_R_TYPE (relocCmd.r_info) & 0x80) /* old SDE-ELF section-relative relocation */ relVal = (UINT32) symInfoTbl [ELF32_R_SYM (relocCmd.r_info)].pAddr; else { /* standard ELF reloc */ pst = pSymsArray + ELF32_R_SYM (relocCmd.r_info); if (pst->st_info == ELF32_ST_INFO(STB_LOCAL, STT_SECTION)) /* section-relative relocation */ relVal = (UINT32) symInfoTbl [ELF32_R_SYM (relocCmd.r_info)].pAddr; else /* symbol-relative relocation */ relVal = pst->st_value; } relVal += relocCmd.r_addend; relAddr = (void*) ((UINT32) relBaseAddr + relocCmd.r_offset); switch (ELF32_R_TYPE(relocCmd.r_info) & 0x7f) { case R_SDE_8: DBG (("R_SDE_8 relAddr=0x%x(0x%x) reloc=0x%x\n", relAddr, *(unsigned char *)relAddr, relVal)); *(UINT8 *) relAddr = relVal; break; case R_SDE_16: DBG (("R_SDE_16 relAddr=0x%x(0x%x) reloc=0x%x\n", relAddr, *(unsigned short *)relAddr, relVal)); *(USHORT *) relAddr = relVal; break; case R_SDE_32: DBG (("R_SDE_32 relAddr=0x%x(0x%x) reloc=0x%x\n", relAddr, *(unsigned int *)relAddr, relVal)); *(UINT32 *) relAddr = relVal; break; case R_SDE_ILALO: /* "lw $m, addr" low part ref */ DBG (("R_SDE_ILALO\n")); insn = *(UINT32 *) relAddr; insn = (insn & ~0xffff) | (relVal & 0xffff); *(UINT32 *) relAddr = insn; break; case R_SDE_ILA: /* "lw $m, addr" low and high combined */ DBG (("R_SDE_ILA\n")); insn = *(UINT32 *) ((UINT32)relAddr + 4); insn = (insn & ~0xffff) | (relVal & 0xffff); *(UINT32 *) ((UINT32) relAddr + 4) = insn; /* FALL THROUGH */ case R_SDE_ILAHI: /* "lw $m, addr" high part reference * (adjusting for low-half sign extension) */ DBG (("R_SDE_ILAHI\n")); relVal += ((relVal & 0x8000) << 1); /* yowza */ insn = *(UINT32 *) relAddr; insn = (insn & ~0xffff) | ((relVal >> 16) & 0xffff); *(UINT32 *)relAddr = insn; break; case R_SDE_IJMP: DBG (("R_SDE_IJMP\n")); /* 26-bit absolute jump (top 4 bits of pc stay the same) */ if ((relVal >> 28) != (((UINT32) relAddr + 4) >> 28)) { errnoSet (S_loadElfLib_JMPADDR_ERROR); return (ERROR); } insn = *(UINT32 *) relAddr; insn = (insn & ~0x03ffffff) | ((relVal>>2) & 0x03ffffff); *(UINT32 *) relAddr = insn; break; case R_SDE_IBRA: /* 16 bit pc relative branch */ /* assembler includes the -4 in the relocation addend */ DBG (("R_SDE_IBRA\n")); relVal -= (UINT32) relAddr; insn = *(UINT32 *) relAddr; insn = (insn & ~0xffff) | ((relVal >> 2) & 0xffff); *(UINT32 *) relAddr = insn; break; case R_SDE_ILITERAL: /* "li.d $fn,1.234" reference */ case R_SDE_IGPREL: errnoSet (S_loadElfLib_GPREL_REFERENCE); printErr ("loadLib error: can't relocate, "); printErr ("recompile module with -G 0 flags.\n"); return (ERROR); default: errnoSet (S_loadElfLib_UNRECOGNIZED_RELOCENTRY); printErr ("Unrecognized relocation type %d\n", ELF32_R_TYPE (relocCmd.r_info) & 0x7f); return (ERROR); } } return (OK); } /**************************************************************************** relMipsSegmentRel - perform relocation commands for MIPS REL segments** This routine reads a relocation command segments and performs all the * relocations specified therein. The relocation commands reside in the * sections with section type SHT_REL. REL segments are assumed to contain* MIPS-ABI style relocations** RETURNS: OK or ERROR** NOMANUAL*/LOCAL STATUS relMipsSegmentRel ( int fd, /* file descriptor */ Elf32_Shdr * pSh, /* relocation section header */ SCN_ADRS * pScnAddr, /* section address once loaded */ Elf32_Sym * pSymsArray, /* elf symbols */ int posRelocEntry, /* relocation information */ SYM_INFO_TBL symInfoTbl /* array of absolute symbol values and types */ ) { int nRel; /* number of relocation entries */ UINT32 insn; /* instruction at relocation address */ void * relBaseAddr; /* relocation base address */ UINT32 relVal; /* relocation value */ void * relAddr; /* relocation address */ Elf32_Sym * pst; /* symbol table entry */ UINT32 hinsn=0; Elf32_Sym *refhi_pst=NULL; UINT32 refhi_insn=0; void * refhi_addr=0; BOOL refhi_relocated = FALSE; Elf32_Rel relocCmd; /* relocation structure */ unsigned int x; int iy; /* index */ if (pSh->sh_entsize != sizeof (Elf32_Rel)) { errnoSet (S_loadElfLib_REL_SECTION); return (ERROR); } nRel = pSh->sh_size / pSh->sh_entsize; relBaseAddr = (void *) *pScnAddr; DBG(("\nrelBaseAddr = 0x%08x\n", relBaseAddr)); for (iy = 0; iy < nRel; iy++) { /* read relocation command */ posRelocEntry = elfRelocRelEntryRd (fd, posRelocEntry, &relocCmd); relAddr = (void *)((UINT32)relBaseAddr + relocCmd.r_offset); pst = pSymsArray + ELF32_R_SYM (relocCmd.r_info); relVal = (UINT32) symInfoTbl [ELF32_R_SYM (relocCmd.r_info)].pAddr; /* Part of the relocation is included in the instruction */ if (ELF32_R_TYPE(relocCmd.r_info) == R_MIPS_16) { insn = 0; insn = *((UINT16 *)relAddr); } else insn = *((UINT32 *)relAddr); DBG(("%08x: %08x %08x ", relAddr, insn, relVal)); switch (ELF32_R_TYPE(relocCmd.r_info)) { case R_MIPS_NONE: DBG(("R_MIPS_NONE")); break; case R_MIPS_16: DBG (("R_MIPS_16")); insn = insn + relVal; if (insn & ~0xffff) { errnoSet (S_loadElfLib_RELOC); return (ERROR); } break; case R_MIPS_32: DBG(("R_MIPS_32")); insn = insn + relVal; break; case R_MIPS_26: DBG(("R_MIPS_26")); /* 26/28-bit absolute jump (top 4 bits of $pc stay the same) */ if (pst) /* external relocation (symbol relative) sign extend */ x = (((int)insn & 0x03ffffff) << 6) >> 4; else /* local relocation (section relative) */ x = ((insn & 0x03ffffff) << 2) | ((UINT32)relAddr & 0xf0000000); x += relVal; insn = (insn & ~0x03ffffff) | ((x >> 2) & 0x03ffffff); break; case R_MIPS_HI16: DBG(("R_MIPS_HI16\n"));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -