📄 loadecofflib.c
字号:
/* following cast to short guarantees sign extension */ relocConstant = (*pAddress << 16) + (int) ((short)(LS16BITS & *pNextAddress)); targetAddr = (long) pExternals[relocCmd.r_symndx] + relocConstant; if ((LS16BITS & targetAddr) >= OVERFLOW) targetAddr += OVERFLOW_COMPENSATION; *pAddress = (MS16BITS & *pAddress) + ((unsigned) targetAddr >> 16); *pNextAddress = (MS16BITS & *pNextAddress) + (LS16BITS & targetAddr); break; case R_REFLO: /* * Since a REFHI must occur with a REFLO pair (lui, addi * instructions) it was originally thought that a REFLO * entry would never be seen alone. This turned out to be * an incorrect assumption. If a R_REFLO is by itself, it * is assumed to belong to the last R_REFHI entry. */ /* following cast to short guarantees sign extension */ relocConstant = refhiConstant + (int) ((short)(LS16BITS & *pAddress)); targetAddr = (long) pExternals[relocCmd.r_symndx] + relocConstant; if ((LS16BITS & targetAddr) >= OVERFLOW) targetAddr += OVERFLOW_COMPENSATION; *pAddress = (MS16BITS & *pAddress) + (LS16BITS & targetAddr); break; case R_GPREL: case R_LITERAL: printErr (gpRelativeReloc); errnoSet (S_loadEcoffLib_GPREL_REFERENCE); return (ERROR); /* gp reg addressing not supported */ break; case R_ABS: break; /* relocation already performed */ default: printErr("Unrecognized ext relocation type %d\n", relocCmd.r_type); errnoSet (S_loadEcoffLib_UNRECOGNIZED_RELOCENTRY); return (ERROR); break; } } else /* local relocation */ { switch (relocCmd.r_symndx) { case R_SN_INIT: case R_SN_TEXT: relSegment = RTEXT; break; case R_SN_DATA: case R_SN_RDATA: case R_SN_SDATA: /* treat as data with no GP */ relSegment = RDATA; break; case R_SN_BSS: case R_SN_SBSS: /* treat as bss with no GP */ relSegment = RBSS; break; case R_SN_LIT4: case R_SN_LIT8: printErr (gpRelativeReloc); errnoSet (S_loadEcoffLib_GPREL_REFERENCE); return (ERROR); break; default: printErr ("Unknown symbol number %d\n", relocCmd.r_symndx); errnoSet (S_loadEcoffLib_UNRECOGNIZED_RELOCENTRY); return (ERROR); break; } switch (relocCmd.r_type) { case R_REFWORD: /* * This relocation is performed by adding the 32 bit address * of the symbol to the contents of pAddress. The address of * the symbol is found by adding the relative segment address * to the contents of the address we are relocating. * See IDT Assembly language programmers guide pg. 10-16 */ if (relSegment == RTEXT) { relocOffset = *pAddress; *pAddress = ((long) pSeg->addrText + relocOffset); } else if (relSegment == RDATA) { relocOffset = *pAddress - pSeg->sizeText; *pAddress = ((long) pSeg->addrData + relocOffset); } else /* relSegment == RBSS */ { relocOffset = *pAddress - pSeg->sizeText - pSeg->sizeData; *pAddress = ((long) pSeg->addrBss + relocOffset); } break; case R_REFHALF: /* WARNING: UNTESTED */ /* * This case is not well documented by MIPS, and has never * been generated. REFWORD and REFHALF relocation entries * are generally used for pointers, and a case where you have * a 16 bit pointer is very unlikely to occur on a 32 bit * architecture. */ if (relSegment == RTEXT) { relocOffset = *pAddress; *pAddress = ((long) pSeg->addrText + relocOffset); } else if (relSegment == RDATA) { relocOffset = *pAddress - pSeg->sizeText; *pAddress = ((long) pSeg->addrData + relocOffset); } else /* relSegment == RBSS */ { relocOffset = *pAddress - pSeg->sizeText - pSeg->sizeData; *pAddress = ((long) pSeg->addrBss + relocOffset); } if (LS16BITS & *pAddress >= OVERFLOW) { errnoSet (S_loadEcoffLib_REFHALF_OVFL); return (ERROR); } break; case R_JMPADDR: /* * For this relocation type the loader determines the address * for the jump, shifts the address right two bits, and adds * the lower 26 bits of the result to the low 26 bits of the * instruction at pAddress (after sign extension). The * results go back into the low 26 bits at pAddress. * The initial check is to see if the jump is within range. * The current address is incremented by 4 because the jump * actually takes place in the branch delay slot of the * current address. The address for the jump is dependant * on the contents of the address we are relocating and * the address of the relative section. * See IDT Assembly language programmers guide pg. 10-16 */ if (relSegment == RTEXT) { targetAddr = (((LS26BITS & *pAddress) << 2) + (MS4BITS & (long) pAddress ) + (long) pSeg->addrText); } else if (relSegment == RDATA) { targetAddr = (((LS26BITS & *pAddress) << 2) + (MS4BITS & (long) pAddress ) + (long) pSeg->addrData); } else /* relSegment == RBSS */ { targetAddr = (((LS26BITS & *pAddress) << 2) + (MS4BITS & (long) pAddress ) + (long) pSeg->addrBss); } if (MS4BITS & targetAddr != (MS4BITS & ((long) pAddress + sizeof(INSTR)))) { errnoSet (S_loadEcoffLib_JMPADDR_ERROR); return (ERROR); } targetAddr = (unsigned) targetAddr >> 2; /* checking for overflows here is not valid */ targetAddr &= LS26BITS; *pAddress = (MS6BITS & *pAddress) | targetAddr; break; case R_REFHI: /* * A refhi relocation is done by reading the next relocation * entry (always the coresponding reflo entry). This least * significant 16 bits are taken from the refhi instruction * and shifted left to form a 32 bit value. This value is * added to the least significant 16 bits of the reflo * instruction (taking into account sign extention) to form * a 32 bit reference pointer. The target address is added * to this constant and placed back in the least significant * 16 bits of each instruction address. The contents of the * lower 16 bits of pAddress (refhiConstant) are saved for any * other reflo entries that the refhi entry may correspond to. * See IDT Assembly language programmers guide pg. 10-16 */ refhiConstant = (*pAddress << 16); nextRelocCmd = *pRelCmds++; nCmds -= 1; if (nextRelocCmd.r_type != R_REFLO) { errnoSet (S_loadEcoffLib_NO_REFLO_PAIR); return (ERROR); } if (segment == RTEXT) { pNextAddress = (long *) ((long) pSeg->addrText + nextRelocCmd.r_vaddr); } else /* segment == RDATA */ { pNextAddress = (long *) ((long) pSeg->addrData + (nextRelocCmd.r_vaddr - (long) pSeg->sizeText)); } /* following cast to short guarantees sign extension */ relocConstant = ((LS16BITS & *pAddress) << 16) + (int) ((short) (LS16BITS & *pNextAddress)); if (relSegment == RTEXT) { targetAddr = relocConstant + (long) pSeg->addrText; } else if (relSegment == RDATA) { relocConstant = relocConstant - pSeg->sizeText; targetAddr = relocConstant + (long) pSeg->addrData; } else /* relSegment == RBSS */ { relocConstant = relocConstant - pSeg->sizeText - pSeg->sizeData; targetAddr = relocConstant + (long) pSeg->addrBss; } if ((LS16BITS & targetAddr) >= OVERFLOW) targetAddr += OVERFLOW_COMPENSATION; *pAddress = ((MS16BITS & *pAddress) | ((unsigned) (MS16BITS & targetAddr) >> 16)); *pNextAddress = (MS16BITS & *pNextAddress) | (LS16BITS & targetAddr); break; case R_REFLO: /* * Since a REFHI must occur with a REFLO pair (lui, addi * instructions) it was originally thought that a REFLO * entry would never be seen alone. This turned out to * be an incorrect assumption. If a R_REFLO is by itself, * it is assumed to belong to the last R_REFHI entry. */ /* following cast to short guarantees sign extension */ relocConstant = (LS16BITS & refhiConstant) + (int) ((short) (LS16BITS & *pAddress)); if (relSegment == RTEXT) { targetAddr = relocConstant + (long) pSeg->addrText; } else if (relSegment == RDATA) { relocConstant = relocConstant - pSeg->sizeText; targetAddr = relocConstant + (long) pSeg->addrData; } else /* relSegment == RBSS */ { relocConstant = relocConstant - pSeg->sizeText - pSeg->sizeData; targetAddr = relocConstant + (long) pSeg->addrBss; } if ((LS16BITS & targetAddr) >= OVERFLOW) targetAddr += OVERFLOW_COMPENSATION; *pAddress = ((MS16BITS & *pAddress) | (LS16BITS & targetAddr)); break; case R_GPREL: case R_LITERAL: printErr (gpRelativeReloc); errnoSet (S_loadEcoffLib_GPREL_REFERENCE); return (ERROR); /* gp relative addressing not supported */ break; case R_ABS: break; /* relocation already completed */ default: printErr ("Unknown relocation type %d\n", relocCmd.r_type); errnoSet (S_loadEcoffLib_UNRECOGNIZED_RELOCENTRY); return (ERROR); /* unrecognized relocation type */ break; } } } return (OK); }/********************************************************************************* softSeek - seek forward into a file** This procedure seeks forward into a file without actually using seek* calls. It is usefull since seek does not work on all devices.** RETURNS:* OK, or* ERROR if forward seek could not be accomplished**/LOCAL STATUS softSeek ( int fd, /* fd to seek with */ int startOfFileOffset /* byte index to seek to */ ) { int position; /* present file position */ int bytesToRead; /* bytes needed to read */ char tempBuffer[BUFSIZE]; /* temp buffer for bytes */ position = ioctl (fd, FIOWHERE, (int) 0); if (position > startOfFileOffset) return(ERROR); /* calculate bytes to read */ bytesToRead = startOfFileOffset - position; while (bytesToRead >= BUFSIZE) { if (fioRead (fd, tempBuffer, BUFSIZE) != BUFSIZE) return (ERROR); bytesToRead -= BUFSIZE; } if (bytesToRead > 0) { if (fioRead (fd, tempBuffer, bytesToRead) != bytesToRead) return (ERROR); } return(OK); }/********************************************************************************* ecoffToVxSym - Translate an ecoff symbol type to a VxWorks symbol type** This procedure translates an ecoff symbol type to a symbol type that the * VxWorks symbol table can understand.** RETURNS:* OK, or* ERROR if the symbol could not be tranlated.**/LOCAL STATUS ecoffToVxSym ( EXTR *symbol, /* ecoff symbol to convert */ SYM_TYPE *pVxSymType /* where to place conversion */ ) { switch(symbol->U_SYM_TYPE) { case scText: *pVxSymType = (SYM_TYPE) N_TEXT; break; case scData: case scRData: case scSData: *pVxSymType = (SYM_TYPE) N_DATA; break; case scBss: case scSBss: *pVxSymType = (SYM_TYPE) N_BSS; break; case scCommon: case scSCommon: *pVxSymType = (SYM_TYPE) N_COMM; break; case scUndefined: case scSUndefined: case scNil: case scAbs: errnoSet (S_loadEcoffLib_UNEXPECTED_SYM_CLASS); return (ERROR); break; default: errnoSet (S_loadEcoffLib_UNRECOGNIZED_SYM_CLASS); return (ERROR); break; } /* convert to global symbol ? */ if (COFF_EXT(symbol)) *pVxSymType |= (SYM_TYPE) N_EXT; return (OK); }/********************************************************************************* nameToRelocSection - Convert COFF section name to integer representation** This procedure converts a COFF section name to it's appropriate integer* designator. ** RETURNS:* Integer value of section name* or ERROR if section relocation is not supported.**/LOCAL int nameToRelocSection ( char * pName /* section name */ ) { if (strcmp (pName,_TEXT) == 0) return (R_SN_TEXT); else if (strcmp (pName,_RDATA) == 0) return (R_SN_RDATA); else if (strcmp (pName,_DATA) == 0) return (R_SN_DATA); else if (strcmp (pName,_SDATA) == 0) return (ERROR); /* R_SN_SDATA: no gp rel sections */ else if (strcmp (pName,_SBSS) == 0) return (ERROR); /* R_SN_SBSS: no gp rel sections */ else if (strcmp (pName,_BSS) == 0) return (ERROR); /* R_SN_BSS: bss not relocatable */ else if (strcmp (pName,_INIT) == 0) return (R_SN_INIT); else if (strcmp (pName,_LIT8) == 0) return (ERROR); /* R_SN_LIT8: no gp rel sections */ else if (strcmp (pName,_LIT4) == 0) return (ERROR); /* R_SN_LIT8: no gp rel sections */ else return (ERROR); /* return ERROR */ }/********************************************************************************* swapCoffscnHdr - swap endianess of COFF section header* */LOCAL void swapCoffscnHdr ( SCNHDR *pScnHdr /* module's ECOFF section header */ ) { SCNHDR tempScnHdr; bcopy ((char *) &pScnHdr->s_name[0], (char *) &tempScnHdr.s_name[0], 8); swabLong ((char *) &pScnHdr->s_paddr, (char *) &tempScnHdr.s_paddr); swabLong ((char *) &pScnHdr->s_vaddr, (char *) &tempScnHdr.s_vaddr); swabLong ((char *) &pScnHdr->s_size, (char *) &tempScnHdr.s_size); swabLong ((char *) &pScnHdr->s_scnptr, (char *) &tempScnHdr.s_scnptr); swabLong ((char *) &pScnHdr->s_relptr, (char *) &tempScnHdr.s_relptr); swabLong ((char *) &pScnHdr->s_lnnoptr, (char *) &tempScnHdr.s_lnnoptr); swab ((char *) &pScnHdr->s_nreloc, (char *) &tempScnHdr.s_nreloc,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -