📄 loadcofflib.c
字号:
*/ if ((scnFlags & STYP_TEXT) && ((unsigned char)symbol->n_sclass == C_THUMBEXTFUNC || (unsigned char)symbol->n_sclass == C_THUMBSTATFUNC)) { bias = (char *)((UINT32)bias | 1); }#endif /* CPU_FAMILY == ARM */ /* Add symbol address to externals table. * For COFF, we add all symbol addresses into the externals * table, not only those symbols saved in the vxWorks symbol * table. */ (*externals) [symNum] = symbol->U_SYM_VALUE + bias;#ifdef DEBUG DPRINTF("new symbol=%#x \n", (unsigned) (symbol->U_SYM_VALUE + bias));#endif /* DEBUG */ } else { /* Undefined external symbol or "common" symbol * * A common symbol type is denoted by undefined external * with its value set to non-zero. */ /* if symbol is a common, then allocate space and add to * symbol table as BSS */ /* common symbol - create new symbol */ if (COFF_COMM(symbol)) { if (symFlag == LOAD_NO_SYMBOLS) ; else { /* * common symbol - create new symbol * * Common symbols are now tacked to the end of the bss * section. This is done to accomodate systems that have * multiple boards sharing memory with common symbols * over the system bus. * This portion of code reads the symbol value * (which contains the symbol size) and places the symbol * in the bss section. The function dataAlign uses * the next possible address for a common symbol to determine * the proper alignment. */ adrs = pNextCommon; bssAlignment = dataAlign (symbol->U_SYM_VALUE, (ULONG) adrs); adrs += bssAlignment; pNextCommon += (symbol->U_SYM_VALUE + bssAlignment); if (symSAdd (symTbl, name, adrs, (VX_BSS | VX_EXT), group) != OK) printErr (cantAddSymErrMsg, name, errnoGet()); } } /* look up undefined external symbol in symbol table */ else if (symFindByNameAndType (symTbl, name, &adrs, &vxSymType, VX_EXT, VX_EXT) != OK) { /* symbol not found in symbol table */ printErr ("undefined symbol: %s\n", name); adrs = NULL; status = ERROR; } /* add symbol address to externals table */ (*externals) [symNum] = adrs; } } return (status); }#if (CPU_FAMILY == AM29XXX)/********************************************************************************* CoffRelSegmentAm29K - perform relocation for the Am29K 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 Am29K family of processor:** - R_IREL instruction relative (jmp/call)* - R_IABS instruction absolute (jmp/call)* - R_ILOHALF instruction low half (const)* - R_IHIHALF instruction high half (consth) part 1* - R_IHCONST instruction high half (consth) part 2* constant offset of R_IHIHALF relocation* - R_BYTE relocatable byte value* - R_HWORD relocatable halfword value* - R_WORD relocatable word value** - R_IGLBLRC instruction global register RC* - R_IGLBLRA instruction global register RA* - R_IGLBLRB instruction global register RB** * RETURNS: OK or ERROR* * INTERNAL* Note that we don't support multi-sections management for the Am29k * architecture.*/LOCAL STATUS coffRelSegmentAm29K ( 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 */ ) { long * pAdrs; /* relocation address */ int nCmds; /* # reloc commands for seg */ RELOC relocCmd; /* relocation structure */ STATUS status = OK; UINT32 unsignedValue; /* const and consth values */ UINT32 symVal; /* value associated with symbol */ SYMENT * pSym; /* pointer to an external symbol */ SCNHDR * pScnHdr; /* section header for relocation */ INT32 signedValue; /* IREL case temporary */ /* * The 29k loader needs to keep track of some values between * the IHICONST and ICONST relocation processing. We use static * variables here which makes the loader not re-entrant. * This should be fixed later. */ static BOOL consthActive; /* CONSTH processing in progress flag */ static UINT32 consthValue; /* CONSTH processing in progress value */ 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 = (long *) ((long) pSeg->addrText + relocCmd.r_vaddr); else /* * The lit section is located after the text section, we take * care of this by adding the "real" text size to the text address. * A better solution would be to add .lit fields in the * SEG_INFO structure. */ pAdrs = (long *) ((long) pSeg->addrText + textSize + relocCmd.r_vaddr - pScnHdr->s_vaddr); } else { pAdrs = (long *) ((long) pSeg->addrData + (relocCmd.r_vaddr - pScnHdr->s_vaddr)); }#ifdef DEBUG DPRINTF("r_vaddr=%02x pAdrs=%08x ", relocCmd.r_vaddr, (int) pAdrs);#endif /* DEBUG */ switch (relocCmd.r_type) { case R_IABS: /* Nothing to do in this case */#ifdef DEBUG DPRINTF("IABS "); DPRINTF("sym=%08x ", (unsigned) pExternals [relocCmd.r_symndx]);#endif /* DEBUG */ break; case R_IREL: /* * Relative jmp/call: in this case we must calculate the address * of the target using the symbol value and the offset * found in the instruction. */#ifdef DEBUG DPRINTF("IREL "); DPRINTF("sym=%08x ", (unsigned) pExternals [relocCmd.r_symndx]);#endif /* DEBUG */ signedValue = EXTRACT_HWORD(*pAdrs) << 2; signedValue = SIGN_EXTEND_HWORD(signedValue); signedValue += (unsigned) pExternals [relocCmd.r_symndx]; /* * Now if its an absolute jmp/call set the absolute bit (A) of * the instruction. * See gnu compiler sources src/bfd/coff-a29k.c */ if ((signedValue &~ 0x3ffff) == 0) { *pAdrs = *pAdrs | (1 << 24); } else { signedValue -= relocCmd.r_vaddr; if (signedValue > 0x1ffff || signedValue < -0x20000) printErr (outOfRangeErrMsg); } signedValue = signedValue >> 2; *pAdrs = INSERT_HWORD(*pAdrs, signedValue); break; case R_ILOHALF: /* * This is a CONST instruction, put the 16 lower bits of the * symbol value at the right place in the instruction. * * CONST instruction format: |OP|const bit 15-8|RA|const bit 7-0| */#ifdef DEBUG DPRINTF("ILOHALF "); DPRINTF("sym=%08x ", (unsigned) pExternals [relocCmd.r_symndx]);#endif /* DEBUG */ pSym = pExtSyms + relocCmd.r_symndx;#ifdef DEBUG DPRINTF("pSym=%08x ", (unsigned) pSym);#endif /* DEBUG */ unsignedValue = EXTRACT_HWORD(*(UINT32 *)pAdrs); unsignedValue += (unsigned) pExternals [relocCmd.r_symndx]; *(UINT32 *)pAdrs = INSERT_HWORD(*(UINT32 *)pAdrs, unsignedValue); break; case R_IHIHALF: /* * This is the first stage of a CONSTH instruction relocation, * just keep track of the fact and keep the value. * We don't modify the instruction until R_IHCONST. * * CONSTH instruction format: |OP|const bit 15-8|RA|const bit 7-0| */#ifdef DEBUG DPRINTF("IHIHALF "); DPRINTF("sym=%08x ", (unsigned) pExternals [relocCmd.r_symndx]);#endif /* DEBUG */ pSym = pExtSyms + relocCmd.r_symndx;#ifdef DEBUG DPRINTF("pSym=%08x ", (unsigned) pSym);#endif /* DEBUG */ consthActive = TRUE; consthValue = (unsigned) pExternals [relocCmd.r_symndx]; break; case R_IHCONST: /* * This is the second stage of a CONSTH instruction relocation, * put the 16 higher bits of the symbol value at the right place * in the instruction. * * CONSTH instruction format: |OP|const bit 15-8|RA|const bit 7-0| */#ifdef DEBUG DPRINTF("IHCONST "); DPRINTF("relocOffset=%08x ", relocCmd.r_symndx);#endif /* DEBUG */ if (!consthActive) { printErr (hiHalfErrMsg); break; }/* * If the parameter to a CONSTH instruction is a relocatable type, two * relocation records are written. The first has an r_type of R_IHIHALF * (33 octal) and a normal r_vaddr and r_symndx. The second relocation * record has an r_type of R_IHCONST (34 octal), a normal r_vaddr (which * is redundant), and an r_symndx containing the 32-bit constant offset * to the relocation instead of the actual symbol table index. This * second record is always written, even if the constant offset is zero. * The constant fields of the instruction are set to zero. */ unsignedValue = relocCmd.r_symndx; unsignedValue += consthValue ; unsignedValue = unsignedValue >> 16; *(UINT32 *)pAdrs = INSERT_HWORD(*(UINT32 *)pAdrs, unsignedValue); consthActive = FALSE; break; case R_BYTE: /* Relocatable byte, just set *pAdrs with byte value. */#ifdef DEBUG DPRINTF("BYTE "); DPRINTF("sym=%08x ", (unsigned) pExternals [relocCmd.r_symndx]);#endif /* DEBUG */ pSym = pExtSyms + relocCmd.r_symndx;#ifdef DEBUG DPRINTF("pSym=%08x *pAdrs %08x", (unsigned)pSym, *(char *)pAdrs);#endif /* DEBUG */ symVal = (UINT32) pExternals[relocCmd.r_symndx]; *(UINT8 *)pAdrs = *(UINT8*) pAdrs + symVal; break; case R_HWORD: /* Relocatable half word, just set *pAdrs with half word value. */#ifdef DEBUG DPRINTF("HWORD "); DPRINTF("sym=%08x ", (unsigned) pExternals [relocCmd.r_symndx]);#endif /* DEBUG */ pSym = pExtSyms + relocCmd.r_symndx;#ifdef DEBUG DPRINTF("pSym=%08x *pAdrs %08x", (unsigned)pSym, *(short *)pAdrs);#endif /* DEBUG */ symVal = (UINT32) pExternals[relocCmd.r_symndx]; *(UINT16 *)pAdrs = *(UINT16*) pAdrs + symVal; break; case R_WORD: /* Relocatable word, just add symbol to current address content. */#ifdef DEBUG DPRINTF("WORD "); DPRINTF("sym=%08x ", (unsigned) pExternals [relocCmd.r_symndx]);#endif /* DEBUG */ pSym = pExtSyms + relocCmd.r_symndx;#ifdef DEBUG DPRINTF("pSym=%08x *pAdrs %08x", (unsigned)pSym, (unsigned)*pAdrs);#endif /* DEBUG */ symVal = (UINT32) pExternals[relocCmd.r_symndx]; *(UINT32 *)pAdrs = *(UINT32*) pAdrs + symVal; break; case R_IGLBLRA: /* * This is a global register A relocation, we have to set the * register A field of the current instruction to the value * associated with symbol. * * instruction format: |OP|RC|RA|RB| */#ifdef DEBUG DPRINTF("IGLBLRA "); DPRINTF("sym=%08x ", (unsigned) pExternals [relocCmd.r_symndx]);#endif /* DEBUG */ symVal = (UINT32) pExternals[relocCmd.r_symndx]; *(UINT32 *)pAdrs = (*(UINT32 *)pAdrs | ((symVal & REG_MASK) << REG_A_OFFSET)); break; case R_IGLBLRB: /* * This is a global register B relocation, we have to set the * register B field of the current instruction to the value * associated with symbol. * * instruction format: |OP|RC|RA|RB| */#ifdef DEBUG DPRINTF("IGLBLRB "); DPRINTF("sym=%08x ", (unsigned) pExternals [relocCmd.r_symndx]);#endif /* DEBUG */ symVal = (UINT32) pExternals[relocCmd.r_symndx]; *(UINT32 *)pAdrs = (*(UINT32 *)pAdrs | ((symVal & REG_MASK) << REG_B_OFFSET)); break; case R_IGLBLRC: /* * This is a global register C relocation, we have to set the * register C field of the current instruction to the value * associated with symbol. * * instruction format: |OP|RC|RA|RB| */#ifdef DEBUG DPRINTF("IGLBLRC "); DPRINTF("sym=%08x ", (unsigned) pExternals [relocCmd.r_symndx]);#endif /* DEBUG */ symVal = (UINT32) pExternals[relocCmd.r_symndx]; *(UINT32 *)pAdrs = (*(UINT32 *)pAdrs | ((symVal & REG_MASK) << REG_C_OFFSET)); break; default: printErr("Unrecognized relocation type %d\n", relocCmd.r_type); errnoSet (S_loadLib_UNRECOGNIZED_RELOCENTRY); return (ERROR); break; }#ifdef DEBUG DPRINTF("\n");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -