📄 loadcofflib.c
字号:
RELOC *relsPtr[MAX_SCNS]; /* section relocation */ SEG_INFO seg; /* file segment info */ BOOL tablesAreLE; /* boolean for table sex */ BOOL symsAbsolute = FALSE; /* TRUE if already absolutely located*/ int status; /* return value */ int ix; /* temp counter */ int nbytes; /* temp counter */ char *pCommons; /* start of common symbols in bss */ char *addrBss; char fileName[255]; UINT16 group; MODULE_ID moduleId; /* Initialization */ memset ((void *)&seg, 0, sizeof (seg));#if (CPU_FAMILY == I960) /* check for fast load */ if ((symFlag & BAL_LOAD) || (symFlag == NO_SYMBOLS)) { fast_load = FALSE; if (symFlag != NO_SYMBOLS) symFlag &= ~BAL_LOAD; } else fast_load = TRUE;#endif /* Set up the module */ ioctl (fd, FIOGETNAME, (int) fileName); moduleId = loadModuleGet (fileName, MODULE_ECOFF, &symFlag); if (moduleId == NULL) return (NULL); group = moduleId->group; /* init section pointers to NULL */ for (ix = 0; ix < MAX_SCNS; ix++) { scnAddr[ix] = NULL; relsPtr[ix] = NULL; bzero((char *) &scnHdr[ix], (int) sizeof(SCNHDR)); } /* read object module header */ if (coffHdrRead (fd, &hdr, &tablesAreLE) != OK) { /* Preserve errno value from subroutine. */ goto error; } /* read in optional header */ if (hdr.f_opthdr) /* if there is an optional header */ { if (coffOpthdrRead (fd, &optHdr, tablesAreLE) != OK) { errnoSet(S_loadLib_OPTHDR_READ); goto error; } } /* read in section headers */ if (coffSecHdrRead (fd, &scnHdr[0], &hdr, tablesAreLE) != OK) { errnoSet(S_loadLib_SCNHDR_READ); goto error; } /* Determine segment sizes */ /* * XXX seg.flagsXxx mustn't be used between coffSegSizes() and * loadSegmentsAllocate(). */ coffSegSizes(&hdr, scnHdr, &seg); /* If object file is already absolutely located (by linker on host), * then override parameters pText, pData and pBss. */ if ( (hdr.f_flags & F_EXEC) && (hdr.f_flags & F_RELFLG)) { if (hdr.f_opthdr) /* if there is an optional header */ { symsAbsolute = TRUE; pText = (INT8 *)(optHdr.text_start); pData = (INT8 *)(optHdr.data_start); /* bss follows data segment */ pBss = (INT8 *) pData + optHdr.dsize; pBss += dataAlign(MAX_ALIGNMENT, pBss); } } seg.addrText = pText; seg.addrData = pData; /* * If pBss is set to LD_NO_ADDRESS, change it to something else. * The coff loader allocates one large BSS segment later on, and * loadSegmentsAllocate doesn't work correctly for it. */ seg.addrBss = (pBss == LD_NO_ADDRESS ? LD_NO_ADDRESS + 1 : pBss); /* * SPR #21836: loadSegmentsAllocate() allocate memory aligned on * the max value of sections alignement saved in seg.flagsText, * seg.flagsData, seg.flagsBss. */ if (loadSegmentsAllocate (&seg) != OK) { printErr ("Could not allocate segments\n"); goto error; } else { pText = seg.addrText; pData = seg.addrData; } /* Ensure that section starts on the appropriate alignment. */ pText += dataAlign(MAX_ALIGNMENT, pText); if (pData == LD_NO_ADDRESS) { pData = pText + seg.sizeText; } /* Ensure that section starts on the appropriate alignment. */ pData += dataAlign(MAX_ALIGNMENT, pData); seg.addrText = pText; seg.addrData = pData; /* load text and data sections */ if (coffLoadSections (fd, &scnHdr[0], &scnAddr[0], pText, pData) != OK) { errnoSet (S_loadLib_LOAD_SECTIONS); goto error; } /* get section relocation info */ if (coffReadRelocInfo (fd, &scnHdr[0], &relsPtr[0], tablesAreLE) != OK) { errnoSet (S_loadLib_RELOC_READ); goto error; } /* read symbols */ if (coffReadExtSyms (fd, &externalSyms, &externalsBuf, &hdr, tablesAreLE) != OK) { errnoSet (S_loadLib_EXTSYM_READ); goto error; } /* read string table */ if (coffReadExtStrings (fd, &stringsBuf, tablesAreLE) != OK) { errnoSet (S_loadLib_EXTSTR_READ); goto error; } /* Determine additional amount of memory required to append * common symbols on to the end of the BSS section. */ nbytes = coffTotalCommons(externalSyms, hdr.f_nsyms, seg.sizeBss); /* set up for bss */ seg.sizeBss += nbytes; if (pBss == LD_NO_ADDRESS) { if (seg.sizeBss != 0) { if ((pBss = malloc (seg.sizeBss)) == NULL) goto error; else seg.flagsBss |= SEG_FREE_MEMORY; } else { pBss = (char *) ((long) pData + (long) seg.sizeData); } } pBss += dataAlign(MAX_ALIGNMENT, pBss); seg.addrBss = pBss; /* fix up start address of bss sections */ addrBss = pBss; for (ix = 0; ix < max_scns; ix++) { if (scnHdr[ix].s_flags & STYP_BSS) {#if (CPU_FAMILY == I960) addrBss += dataAlign (scnHdr[ix].s_align, addrBss);#else /* (CPU_FAMILY == I960) */ addrBss += dataAlign (MAX_ALIGNMENT, addrBss);#endif /* (CPU_FAMILY == I960) */ scnAddr[ix] = addrBss; addrBss += scnHdr[ix].s_size; } } /* set up address for first common symbol */ pCommons = (char *) ((long) seg.addrBss + (seg.sizeBss - nbytes)); /* add segment names to symbol table before other symbols */ if (symFlag != LOAD_NO_SYMBOLS) addSegNames (fd, pText, pData, pBss, symTbl, group); /* process symbol table */ status = coffSymTab (fd, &hdr, (SYMENT *)externalSyms, &externalsBuf, symFlag, &seg, stringsBuf, symTbl, pCommons, scnHdr, scnAddr, symsAbsolute, tablesAreLE, group); /* relocate text and data segments * * note: even if symbol table had missing symbols, continue with * relocation of those symbols that were found. * note: relocation is for changing the values of the relocated * symbols. bss is uninitialized data, so it is not relocated * in the symbol table. */ if ((status == OK) || (errnoGet() == S_symLib_SYMBOL_NOT_FOUND)) for (ix = 0; ix < max_scns; ix++) { if ((relsPtr[ix] != NULL) && !(scnHdr[ix].s_flags & STYP_INFO) && !(scnHdr[ix].s_flags & STYP_NOLOAD) && (scnHdr[ix].s_flags != STYP_REG) && !(scnHdr[ix].s_flags & STYP_PAD)) {#if (CPU_FAMILY == ARM) if (coffRelSegmentArm(relsPtr[ix], scnHdr, externalsBuf, externalSyms, &seg, ix, symTbl) != OK)#else#if (CPU_FAMILY == AM29XXX) if (coffRelSegmentAm29K(relsPtr[ix], scnHdr, externalsBuf, externalSyms, &seg, ix, symTbl) != OK)#else /* (CPU_FAMILY == I960) */ if (coffRelSegmentI960(relsPtr[ix], scnHdr, scnAddr[ix], externalsBuf, externalSyms, &seg, ix, symTbl) != OK)#endif /* (CPU_FAMILY == AM29XXX) */#endif /* (CPU_FAMILY == ARM) */ { goto error; } } } coffFree(externalsBuf, externalSyms, stringsBuf, relsPtr); /* write protect the text if text segment protection is turned on */ if (seg.flagsText & SEG_WRITE_PROTECTION) { if (VM_STATE_SET (NULL, pText, seg.sizeProtectedText, VM_STATE_MASK_WRITABLE, VM_STATE_WRITABLE_NOT) == ERROR) goto error; } /* return load addresses, where called for */ if (ppText != NULL) *ppText = pText; if (ppData != NULL) *ppData = pData; if (ppBss != NULL) *ppBss = pBss; /* clear out bss */ bzero (pBss, (int) seg.sizeBss); /* * Add the segments to the module. * This has to happen after the relocation gets done. * If the relocation happens first, the checksums won't be * correct. */ moduleSegAdd (moduleId, SEGMENT_TEXT, pText, seg.sizeText, seg.flagsText); moduleSegAdd (moduleId, SEGMENT_DATA, pData, seg.sizeData, seg.flagsData); moduleSegAdd (moduleId, SEGMENT_BSS, pBss, seg.sizeBss, seg.flagsBss); if (status == OK) return (moduleId); else return (NULL); /* error: * clean up dynamically allocated temporary buffers and return ERROR */error: coffFree(externalsBuf, externalSyms, stringsBuf, relsPtr); moduleDelete (moduleId); return (NULL); }/********************************************************************************* coffFree - free any malloc'd memory**/LOCAL void coffFree ( char **pExternalsBuf, /* pointers to external symbols */ char *pExternalSyms, /* buffer for external symbols */ char *pStringsBuf, /* string table pointer */ RELOC **pRelsPtr /* section relocation */ ) { int ix; if (pStringsBuf != NULL) free (pStringsBuf); if (pExternalsBuf != NULL) free ((char *) pExternalsBuf); if (pExternalSyms != NULL) free ((char *) pExternalSyms); for (ix = 0; ix < MAX_SCNS; ix++) { if (*pRelsPtr != NULL) free((char *) *pRelsPtr); pRelsPtr++; } }/********************************************************************************* coffSegSizes - determine segment sizes** This function fills in the size fields in the SEG_INFO structure.* Note that the bss size may need to be readjusted for common symbols. */LOCAL void coffSegSizes ( FILHDR *pHdr, /* pointer to file header */ SCNHDR *pScnHdrArray, /* pointer to array of section headers */ SEG_INFO *pSeg /* section addresses and sizes */ ) { int ix; int nbytes; /* additional bytes required for alignment */ SCNHDR *pScnHdr; /* pointer to a section header */ pSeg->sizeText = 0; pSeg->sizeData = 0; pSeg->sizeBss = 0; /* * SPR #21836: pSeg->flagsText, pSeg->flagsData, pSeg->flagsBss are used * to save the max value of each segments. These max values are computed * for each sections. These fields of pSeg are only used on output, then * a temporary use is allowed. */ pSeg->flagsText = _ALLOC_ALIGN_SIZE; pSeg->flagsData = _ALLOC_ALIGN_SIZE; pSeg->flagsBss = _ALLOC_ALIGN_SIZE; for (ix=0; ix < pHdr->f_nscns; ix++) /* loop thru all sections */ { pScnHdr = pScnHdrArray + ix; if (pScnHdr->s_flags & STYP_TEXT) { /* Assume that there was a previous section of same type. * First, align data to boundary from section header. * Add the size of this section to the total segment size. */#if (CPU_FAMILY == ARM) sprFixTextOff[ix] = pSeg->sizeText;#endif#if (CPU_FAMILY == I960) nbytes = dataAlign(pScnHdr->s_align, pSeg->sizeText); /* SPR #21836 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -