📄 loadcofflib.c
字号:
#endif /* DEBUG */ } return(status); }#endif /* (CPU_FAMILY == AM29XXX) */#if (CPU_FAMILY == I960)/********************************************************************************* coffRelSegmentI960 - perform relocation for the I960 family** This routine reads the specified relocation command segment and performs* all the relocations specified therein.* Absolute symbol addresses are looked up in the 'externals' table.** This function handles the following types of relocation commands* for the i960 processor:* R_RELLONG - direct 32 bit relocation* R_IPRMED - 24-bit IP-relative relocation* R_OPTCALL - optimizable call (check if can be changed to BAL)* R_OPTCALLX - optimizable callx (check if can be changed to BALX)* * RETURNS: OK or ERROR*/LOCAL STATUS coffRelSegmentI960 ( RELOC *pRelCmds, /* list of relocation commands */ SCNHDR *pScnHdrArray, /* array of section headers */ char *scnAddr, /* section loaded address */ char **pExternals, /* array of absolute symbol values */ SYMENT *pExtSyms, /* pointer to object file symbols */ SEG_INFO *pSeg, /* section addresses and sizes */ int section, /* section number -1 for relocation */ SYMTAB_ID symTbl /* symbol table to use */ ) { FAST long *pAdrs; /* relocation address */ int nCmds; /* # reloc commands for seg */ RELOC relocCmd; /* relocation structure */ INT8 *symVal0 = 0; /* absolute symbol value */ INT8 *symVal1 = 0; /* leaf-proc absolute symbol value */ INT32 offset; /* relocation value accumulator */ char symName[MAX_SYS_SYM_LEN + 1]; /* temp buffer for symbol name */ SYM_TYPE symType; /* type from sys symbol table */ STATUS status = OK; SYMENT *pSym; /* pointer to an external symbol */ SCNHDR *pScnHdr; /* section header for relocation */ pScnHdr = pScnHdrArray + section; for (nCmds = pScnHdr->s_nreloc; nCmds > 0; nCmds--) { /* read relocation command */ relocCmd = *pRelCmds++; /* * Calculate actual address in memory that needs relocation. */ if (pScnHdr->s_flags & STYP_TEXT) { pAdrs = (long *) ((long) scnAddr + (relocCmd.r_vaddr - pScnHdr->s_vaddr)); } else /* (pScnHdr->s_flags & STYP_DATA) */ { pAdrs = (long *) ((long) scnAddr + (relocCmd.r_vaddr - pScnHdr->s_vaddr)); }#ifdef DEBUG DPRINTF("r_vaddr=%02x *pAdrs=%08x ", relocCmd.r_vaddr, *(UINT32 *)pAdrs);#endif /* DEBUG */ switch (relocCmd.r_type) { case R_OPTCALL: case R_OPTCALLX: /* Check for a call to a leaf procedure. If it is, then * replace the CALL opcode with BAL and correct the displacement. */#ifdef DEBUG if (relocCmd.r_type == R_OPTCALL) { DPRINTF("OPTCALL "); } else { DPRINTF("OPTCALLX "); }#endif if (fast_load == FALSE) { if (symFindByValue (symTbl, (UINT)symVal0, (char *) symName, (int *) &symVal0, &symType) != OK) { printErr (symNotFoundErrMsg); status = ERROR; break; /* skip to next symbol */ } if (symType & BAL_ENTRY) { /* get symbol value from externals table */ symVal0 = (INT8 *) (pExternals[relocCmd.r_symndx]); /* cat a ".lf" on the end of the symName */ strcat ((char *)symName, ".lf"); /* Now check if a symbol exists as name.lf * If it does, it is the BAL entry for the leaf proc. * start at symName[1] to ignore the '_'. */ if (symFindByName (symTbl, &symName[1], &symVal1, &symType) == OK) {#ifdef DEBUG DPRINTF("LEAF ");#endif /* DEBUG */ /* A call to a leaf procedure: replace * CALL opcode with BAL. */ if (relocCmd.r_type == R_OPTCALL) { offset = (INT32) *pAdrs; offset &= OFFSET24_MASK; /* clear opcode */ offset |= ~OFFSET24_MASK; /* sign extend */ offset += ((INT32) symVal1 - (INT32) symVal0); offset &= OFFSET24_MASK; *(UINT32 *)pAdrs = BAL_OPCODE | offset; } else /* R_OPTCALLX */ { /* Put in opcode for BALX with: * absolute displacement addressing mode and * register g14 for the return address. */ *(UINT32 *)pAdrs = BALXG14_OPCODE; *(UINT32 *)(pAdrs+1) += (INT32) symVal1 - (INT32) symVal0; #ifdef DEBUG DPRINTF("*(pAdrs+1)=%08x ", *(UINT32 *)(pAdrs+1));#endif /* DEBUG */ } } } else {#ifdef DEBUG DPRINTF("NO LEAF ");#endif /* DEBUG */ /* No leaf proc entry. * Do nothing with the OPTCALL. * This is a normal call/return routine. */ } } break; case R_RELLONG: /* * This relocation is performed by adding the absolute address * of the symbol to the relocation value in the code and * subtracting the symbol's value (relative to the section). * * The new reloc_value = * symbol_absolute_addr + reloc_value_in_code - symbol_value; * * Both reloc_value_in_code and symbol_value are relative to * the beginning of the first section in the object file. * For undefined externals, reloc_value_in_code = 0 * and symbol_value = 0. */#ifdef DEBUG DPRINTF("RELLONG "); DPRINTF("sym=%08x ", (unsigned) pExternals [relocCmd.r_symndx]);#endif /* DEBUG */ offset = (INT32) pExternals[relocCmd.r_symndx]; pSym = pExtSyms + relocCmd.r_symndx; if (! COFF_COMM(pSym)) { offset -= pSym->n_value;#ifdef DEBUG DPRINTF("n_value=0x%x ", pSym->n_value);#endif /* DEBUG */ } *pAdrs += offset; break; case R_IPRMED:#ifdef DEBUG DPRINTF("IPRMED ");#endif /* DEBUG */ pSym = pExtSyms + relocCmd.r_symndx; if (COFF_UNDF(pSym)) /* if symbol was undefined external */ { /* Code to be relocated contains an offset * to the beginning of the first section in the object file. * To relocate it, add the absolute address * of the referenced symbol and subtract the * amount by which the input section will be * relocated. */ offset = (INT32) *pAdrs; offset &= OFFSET24_MASK; /* clear opcode */ offset |= ~OFFSET24_MASK; /* sign extend */ offset += (INT32) pExternals [relocCmd.r_symndx];#ifdef DEBUG DPRINTF("sym=%08x ", (unsigned)pExternals [relocCmd.r_symndx]);#endif /* DEBUG */ /* IP-relative relocations were done assuming * text starts at 0. Adjust for actual start of text. */ offset -= (INT32)scnAddr - pScnHdr->s_vaddr; offset &= 0x00ffffff; *(UINT32 *)pAdrs = (*(UINT32 *)pAdrs & 0xff000000) | offset; } else {#ifdef DEBUG DPRINTF("NO RELOC ");#endif /* DEBUG */ /* The symbol we are relocating to came from * the same input file as the code that * references it. The relative distance * between the two will not change. Do nothing. */ } break; default: printErr("Unrecognized relocation type %d\n", relocCmd.r_type); errnoSet (S_loadLib_UNRECOGNIZED_RELOCENTRY); return (ERROR); break; }#ifdef DEBUG DPRINTF("*pAdrs=%08x\n", *(UINT32 *)pAdrs);#endif /* DEBUG */ } return(status); }#endif /* (CPU_FAMILY == I960) */#if (CPU_FAMILY == ARM)/******************************************************************************** * CoffRelSegmentArm - perform relocation for the ARM family** This routine reads the specified relocation command segment and performs* all the relocations specified therein.* Absolute symbol addresses are looked up in the 'externals' table.** This function handles the following types of relocation commands* for the ARM family of processor:** - R_RELBYTE Byte PC Relative* - R_RELWORD Word PC Relative* - R_RELARMLONG Long PC Relative* - R_RELARM26 26 bit PC Relative* - R_DONEARM26 completed 26 bit PC relative* - R_THUMB9 Thumb 9 bit PC-relative* - R_THUMB12 Thumb 12 bit PC-relative* - R_THUMB23 Thumb 23 bit PC-relative* - R_DONETHUMB23 completed Thumb 23 bit PC-relative** Note that RVA32 relocations are never produced in ARM code.** RETURNS: OK or ERROR** INTERNAL* Large parts of this code were taken lifted from the host-based loader* when it had not been fully tested and the tool-chain was full of* problems. Consequently, there may be bugs...* The handling of literal sections (.lit/.rdata) is taken from the* Am29k code above.*/ LOCAL STATUS coffRelSegmentArm ( RELOC * pRelCmds, /* list of relocation commands */ SCNHDR * pScnHdrArray, /* array of section headers */ char ** pExternals, /* array of absolute symbol values */ SYMENT * pExtSyms, /* pointer to object file symbols */ SEG_INFO * pSeg, /* section addresses and sizes */ int section, /* section number -1 for relocation */ SYMTAB_ID symTbl /* symbol table to use */ ) { void * pAdrs; /* relocation address */ int nCmds; /* # reloc commands for seg */ RELOC relocCmd; /* relocation structure */ STATUS status = OK; ULONG value; /* value being relocated */ SCNHDR * pScnHdr; /* section header for relocation */ SYMENT * pSym; /* pointer to external symbol */ pScnHdr = pScnHdrArray + section; for (nCmds = pScnHdr->s_nreloc; nCmds > 0; nCmds--) { /* read relocation command */ relocCmd = *pRelCmds++; /* calculate actual address in memory that needs relocation */ if (pScnHdr->s_flags & STYP_TEXT) { if (!(pScnHdr->s_flags & STYP_LIT)) { pAdrs = (void *) ((long) pSeg->addrText + relocCmd.r_vaddr - pScnHdr->s_vaddr + sprFixTextOff[section]); } else { /* * The lit/rdata section is located after the text section. * We take care of this by adding the "real" text size to the * text address, just like the AM29K. A better solution would * be to add .lit fields in the SEG_INFO structure. */ pAdrs = (void *) ((long) pSeg->addrText + sprFixTextOff[section] + relocCmd.r_vaddr - pScnHdr->s_vaddr); } } else pAdrs = (void *) ((long) pSeg->addrData + (relocCmd.r_vaddr - pScnHdr->s_vaddr)); /* now relocate according to type */ switch (relocCmd.r_type) { case R_RELBYTE: /* relocate a byte */ value = *(UINT8 *)pAdrs; /* * add address of symbol to the relocation value, * subtracting the symbol's value relative to the section */ value += (UINT32)pExternals[relocCmd.r_symndx]; pSym = pExtSyms + relocCmd.r_symndx; if (!COFF_COMM(pSym)) value -= pSym->n_value; /* check for overflow */ if ((value & ~0xFF) != 0) { printErr (outOfRangeErrMsg); status = ERROR; break; } *(UINT8 *)pAdrs = value; break; case R_RELWORD: /* relocate a 16 bit word */ value = *(UINT16 *)pAdrs; /* * add address of symbol to the relocation value, * subtracting the symbol's value relative to the section */ value += (UINT32)pExternals[relocCmd.r_symndx]; pSym = pExtSyms + relocCmd.r_symndx; if (!COFF_COMM(pSym)) value -= pSym->n_value; /* check for overflow */ if ((value & ~0xFFFF) != 0) { printErr (outOfRangeErrMsg); status = ERROR; break; } *(UINT16 *)pAdrs = value; break; case R_RELARMLONG: /* relocate a long */ { char symName[MAX_SYS_SYM_LEN + 1]; /* buffer for sym name */ int symVal0, symVal1; SYM_TYPE symType; value = *(UINT32 *)pAdrs; /* * add address of symbol to the relocation value, * subtracting the symbol's value relative to the section */ symVal0
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -