📄 elfarm.c
字号:
/* elfArm.c - ELF/ARM relocation unit *//* Copyright 2001-2002 Wind River Systems, Inc. */#include "copyright_wrs.h"/*modification history--------------------01c,13feb02,jn Add printed error messages when CHECK_FITS fails01b,21nov01,pad Minor changes: added error messages, made elfArmSegReloc local, etc.01a,28aug01,jn written, based on AE version (elfArm.c@@/main/tor3_x/12) and ppc specific parts of loadElfLib.c@@/main/8 *//*DESCRIPTIONThis file contains the relocation unit for the ELF/ARM combination.Each relocation entry is applied to the sections loaded in the target memoryimage in order to eventually get an executable program linked at the requiredaddress.The relocation computations handled by this relocation unit are: R_ARM_NONE none, no computation R_ARM_PC24 word32, S + A - P R_ARM_ABS32 word32, S + A R_ARM_REL32 word32, S + A - P R_ARM_THM_PC22 BL pair S - P + A R_ARM_THM_PC9 low8, S - P + A R_ARM_THM_PC11 low11, S - P + AWith: 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.Both the Elf32_Rel and Elf32_Rela relocation entry types are acceptedby this relocation unit, as permitted by the ELF ABI for the ARMarchitecture.*//* Includes */#include "vxWorks.h"#include "string.h"#include "stdio.h"#include "elf.h"#include "elftypes.h"#include "errnoLib.h"#include "moduleLib.h"#include "loadLib.h"#include "loadElfLib.h" #include "private/vmLibP.h"#include "symbol.h"#include "symLib.h"#include "arch/arm/elfArm.h"/* Defines */#define MEM_READ_32(pRelocAdrs, offset) (offset = *((UINT32 *)(pRelocAdrs)))#define MEM_READ_16(pRelocAdrs, offset) (offset = *((UINT16 *)(pRelocAdrs)))#define MEM_READ_8(pRelocAdrs, offset) (offset = *((UINT8 *)(pRelocAdrs)))#define MEM_WRITE_32(pRelocAdrs, value32) \ (*((UINT32 *)(pRelocAdrs)) = (value32))#define MEM_WRITE_16(pRelocAdrs, value16) \ (*((UINT16 *)(pRelocAdrs)) = (value16))#define MEM_WRITE_8(pRelocAdrs, value8) \ (*((UINT8 *)(pRelocAdrs)) = (value8))/* Locals */LOCAL STATUS elfArmPc24Reloc ( Elf32_Word sh_type, /* Relocation sec. type (SHT_REL or SHT_RELA) */ void * pRelocAdrs, /* Relocation address */ void * pSymAdrs, /* Addr of sym involved in relocation */ Elf32_Sword relocAddend /* Addend from reloc. - arg used for RELA only */ );LOCAL STATUS elfArmAbs32Reloc ( Elf32_Word sh_type, /* Relocation sec. type (SHT_REL or SHT_RELA) */ void * pRelocAdrs, /* Relocation address */ void * pSymAdrs, /* Addr of sym involved in relocation */ Elf32_Sword relocAddend, /* Addend from reloc. - arg used for RELA only */ SYM_TYPE symType /* Type of symbol */ );LOCAL STATUS elfArmRel32Reloc ( Elf32_Word sh_type, /* Relocation sec. type (SHT_REL or SHT_RELA) */ void * pRelocAdrs, /* Relocation address */ void * pSymAdrs, /* Addr of sym involved in relocation */ Elf32_Sword relocAddend /* Addend from reloc. - arg used for RELA only */ );LOCAL STATUS elfThumbPc22Reloc ( Elf32_Word sh_type, /* Relocation sec. type (SHT_REL or SHT_RELA) */ void * pRelocAdrs, /* Relocation address */ void * pSymAdrs, /* Addr of sym involved in relocation */ Elf32_Sword relocAddend /* Addend from reloc. - arg used for RELA only */ );LOCAL STATUS elfThumbPc9Reloc ( Elf32_Word sh_type, /* Relocation sec. type (SHT_REL or SHT_RELA) */ void * pRelocAdrs, /* Relocation address */ void * pSymAdrs, /* Addr of sym involved in relocation */ Elf32_Sword relocAddend /* Addend from reloc. - arg used for RELA only */ );LOCAL STATUS elfThumbPc11Reloc ( Elf32_Word sh_type, /* Relocation sec. type (SHT_REL or SHT_RELA) */ void * pRelocAdrs, /* Relocation address */ void * pSymAdrs, /* Addr of sym involved in relocation */ Elf32_Sword relocAddend /* Addend from reloc. - arg used for RELA only */ );LOCAL STATUS relocationSelect ( Elf32_Word sh_type, /* Relocation sec. type (SHT_REL or SHT_RELA) */ void * pRelocAdrs, /* Addr where the relocation applies */ void * pSymAdrs, /* Addr of sym involved in relocation */ Elf32_Word relocInfo, /* Info from relocation command */ Elf32_Sword relocAddend, /* Addend from reloc. - arg used for RELA only */ SYM_TYPE symType /* Type of sym involved in relocation */ );/**************************************************************************** elfArmSegReloc - perform relocation commands for ARM rel or rela segments** This routine reads the relocation command segments and dispatches* the relocation work to either relArmSegmentRel or relArmSegment depending* on whether the relocation section is type REL or RELA. The relocation * commands reside in the sections with section type SHT_RELA or SHT_REL.** RETURNS: OK or ERROR*/LOCAL STATUS elfArmSegReloc ( int fd, /* object file to read in */ MODULE_ID moduleId, /* ID of object module being relocated */ int loadFlag, /* load options (not used here) */ int posCurRelocCmd,/* position of current relocation command */ Elf32_Shdr * pScnHdrTbl, /* ptr to section header table (unused here) */ 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 (not used here) */ SYMTAB_ID symTbl, /* current symbol table (not used here) */ SEG_INFO * pSeg /* section addresses and sizes */ ) { Elf32_Rela relaRelocCmd; /* relocation structure, RELA version */ Elf32_Rel relRelocCmd; /* relocation structure, REL version */ Elf32_Addr relocOffset = 0;/* offset from relocation structure */ Elf32_Word relocInfo = 0; /* info from relocation structure */ Elf32_Sword relocAddend = 0;/* addend from reloc struct. (RELA only) */ UINT32 relocNum; /* number of reloc entries in section */ UINT32 relocIdx; /* index of the reloc entry being processed */ void * pRelocAdrs; /* relocation address */ void * pSymAdrs; /* address of symbol involved in relocation */ SYM_TYPE symType; /* type of symbol involved in relocation */ STATUS status = OK; /* whether or not all relocations were ok */ /* Sanity checking */ if (pRelHdr->sh_type == SHT_RELA) { if (pRelHdr->sh_entsize != sizeof (Elf32_Rela)) { printErr ("Wrong relocation entry size.\n"); errnoSet (S_loadElfLib_RELOC); return ERROR; } } else if (pRelHdr->sh_type == SHT_REL) { if (pRelHdr->sh_entsize != sizeof (Elf32_Rel)) { printErr ("Wrong relocation entry size.\n"); errnoSet (S_loadElfLib_RELOC); return ERROR; } } else { printErr ("Unknown relocation entry type.\n"); errnoSet (S_loadElfLib_RELOC); return ERROR; } /* Get the number of relocation entries */ relocNum = pRelHdr->sh_size / pRelHdr->sh_entsize; /* Relocation loop */ for (relocIdx = 0; relocIdx < relocNum; relocIdx++) { /* Read relocation command (SHT_RELA or SHT_REL type) */ if (pRelHdr->sh_type == SHT_RELA) { if ((posCurRelocCmd = elfRelocRelaEntryRd (fd, posCurRelocCmd, &relaRelocCmd)) == ERROR) { errnoSet (S_loadElfLib_READ_SECTIONS); return ERROR; } relocOffset = relaRelocCmd.r_offset; relocInfo = relaRelocCmd.r_info; relocAddend = relaRelocCmd.r_addend; } else if (pRelHdr->sh_type == SHT_REL) { if ((posCurRelocCmd = elfRelocRelEntryRd (fd, posCurRelocCmd, &relRelocCmd)) == ERROR) { errnoSet (S_loadElfLib_READ_SECTIONS); return ERROR; } relocOffset = relRelocCmd.r_offset; relocInfo = relRelocCmd.r_info; relocAddend = 0; /* addend is extracted from memory in REL case. */ } /* * If the target symbol's address is null, then this symbol is * undefined. The computation of its value can be out of range * so let's not waste our time on it. A warning message has already * been displayed for this symbol. * * Note: ELF32_R_SYM(relocInfo) gives the index of the symbol in * the module's symbol table. This same index is used to * store the symbol information (address and type for * now) in the symInfoTbl table (see loadElfSymTabProcess()). */ if ((pSymAdrs = symInfoTbl [ELF32_R_SYM(relocInfo)].pAddr) == NULL) continue; /* * Calculate actual remote address that needs relocation, and * perform external or section relative relocation. */ pRelocAdrs = (void *)((Elf32_Addr)*pScnAddr + relocOffset); symType = symInfoTbl [ELF32_R_SYM (relocInfo)].type; if (relocationSelect (pRelHdr->sh_type, pRelocAdrs, pSymAdrs, relocInfo, relocAddend, symType) != OK) status = ERROR; } return status; }/********************************************************************************* relocationSelect - select, and execute, the appropriate relocation** This routine selects, then executes, the relocation computation as per the* relocation command.** NOTE* This routine should use two different errnos:* - S_loadElfLib_UNSUPPORTED: when a relocation type is not supported on * purpose.* - S_loadElfLib__UNRECOGNIZED_RELOCENTRY: when a relocation type is not * recognized (default case of the switch).** RETURNS : OK or ERROR if computed value can't be written down in target* memory.*/LOCAL STATUS relocationSelect ( Elf32_Word sh_type, /* Relocation sec. type (SHT_REL or SHT_RELA) */ void * pRelocAdrs, /* Addr where the relocation applies */ void * pSymAdrs, /* Addr of sym involved in relocation */ Elf32_Word relocInfo, /* Info from relocation command */ Elf32_Sword relocAddend, /* Addend from reloc. - arg used for RELA only */ SYM_TYPE symType /* Type of sym involved in relocation */ ) { switch (ELF32_R_TYPE (relocInfo)) { case (R_ARM_NONE): /* none */ break; case (R_ARM_PC24): /* word32, S + A - P */ if (elfArmPc24Reloc (sh_type, pRelocAdrs, pSymAdrs, relocAddend) != OK) return ERROR; break; case (R_ARM_ABS32): /* word32, S + A */ if (elfArmAbs32Reloc (sh_type, pRelocAdrs, pSymAdrs, relocAddend, symType) != OK) return ERROR; break; case (R_ARM_REL32): /* word32, S + A - P */ if (elfArmRel32Reloc (sh_type, pRelocAdrs, pSymAdrs, relocAddend) != OK) return ERROR; break; case (R_ARM_PC13): /* low12 + U-but, S + A - P */ case (R_ARM_ABS16): /* word16, S + A */ case (R_ARM_ABS12): /* low12, S + A */ case (R_ARM_THM_ABS5): /* 6-10 bits, S + A */ case (R_ARM_ABS8): /* byte8, S + A */ printErr ("Unsupported relocation type %d\n", ELF32_R_TYPE (relocInfo)); errnoSet (S_loadElfLib_UNSUPPORTED); return ERROR; break; case (R_ARM_THM_PC22): /* BL pair, S - P + A */ if (elfThumbPc22Reloc (sh_type, pRelocAdrs, pSymAdrs, relocAddend) != OK) return ERROR; break; case (R_ARM_THM_PC8): /* low8, S - P + A */ printErr ("Unsupported relocation type %d\n", ELF32_R_TYPE (relocInfo)); errnoSet (S_loadElfLib_UNSUPPORTED); return ERROR; break; case (R_ARM_THM_PC9): /* low8, S - P + A */ if (elfThumbPc9Reloc (sh_type, pRelocAdrs, pSymAdrs, relocAddend) != OK) return ERROR; break; case (R_ARM_THM_PC11): /* low11, S - P + A */ if (elfThumbPc11Reloc (sh_type, pRelocAdrs, pSymAdrs, relocAddend) != OK) return ERROR; break; default: printErr ("Unknown relocation type %d\n", ELF32_R_TYPE (relocInfo)); errnoSet (S_loadElfLib_UNRECOGNIZED_RELOCENTRY); return ERROR; break; } return OK; }/********************************************************************************* elfArmPc24Reloc - perform the R_ARM_PC24 relocation** This routine handles the R_ARM_PC24 relocation (B/BL low24, (S - P + 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 elfArmPc24Reloc ( Elf32_Word sh_type, /* Relocation sec. type (SHT_REL or SHT_RELA) */ void * pRelocAdrs, /* Relocation address */ void * pSymAdrs, /* Addr of sym involved in relocation */ Elf32_Sword relocAddend /* Addend from reloc. - arg used for RELA only */ ) { UINT32 value; /* Relocation value */ UINT32 memValue; /* Previous value in memory */ UINT32 addend = 0; /* Relocation Addend initially extracted from memValue */ MEM_READ_32 (pRelocAdrs, memValue); /* * The offset should be stored in the relocation as 24 bits, sign-extended * to 32 bits but, in case it's not, we extract it and sign-extend it * appropriately. */ LOW24_INSERT(addend, memValue);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -