📄 loadpecofflib.c
字号:
/* fix up start address of bss sections */ addrBss = pBss; for (ix = 0; ix < max_scns; ix++) { if (scnHdr[ix].s_flags & STYP_BSS) { addrBss += dataAlign (MAX_ALIGNMENT, addrBss); 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 = pecoffSymTab (fd, &hdr, (SYMENT *)externalSyms, &externalsBuf, symFlag, &seg, stringsBuf, symTbl, pCommons, scnHdr, scnAddr, symsAbsolute, tablesAreLE, group, optHdr.image_base); /* 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 (pecoffRelSegmentI386 (relsPtr[ix], scnHdr, externalsBuf, externalSyms, &seg, ix, symTbl) != OK) { goto error; } } } pecoffFree(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: pecoffFree(externalsBuf, externalSyms, stringsBuf, relsPtr); moduleDelete (moduleId); return (NULL); }/******************************************************************************** loadPecoffInit - initialize the system for pecoff load modules.** This routine initializes VxWorks to use a PECOFF format for loading * modules.** RETURNS: OK** SEE ALSO: loadModuleAt()*/STATUS loadPecoffInit ( ) { /* XXX check for installed? */ loadRoutine = (FUNCPTR) ldPecoffModAtSym; return (OK); }/********************************************************************************* pecoffFree - free any malloc'd memory**/LOCAL void pecoffFree ( 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++; } }/********************************************************************************* pecoffSegSizes - 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 pecoffSegSizes ( 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. */ nbytes = dataAlign(MAX_ALIGNMENT, pSeg->sizeText); pSeg->sizeText += pScnHdr->s_size + nbytes; /* SPR #21836 */ if (MAX_ALIGNMENT > pSeg->flagsText) pSeg->flagsText = MAX_ALIGNMENT; } else if (pScnHdr->s_flags & STYP_DATA) { nbytes = dataAlign(MAX_ALIGNMENT, pSeg->sizeData); pSeg->sizeData += pScnHdr->s_size + nbytes; /* SPR #21836 */ if (MAX_ALIGNMENT > pSeg->flagsData) pSeg->flagsData = MAX_ALIGNMENT; } else if (pScnHdr->s_flags & STYP_BSS) { nbytes = dataAlign(MAX_ALIGNMENT, pSeg->sizeBss); pSeg->sizeBss += pScnHdr->s_size + nbytes; /* SPR #21836 */ if (MAX_ALIGNMENT > pSeg->flagsBss) pSeg->flagsBss = MAX_ALIGNMENT; } } }/********************************************************************************* pecoffLoadSections - read sections into memory* */LOCAL STATUS pecoffLoadSections ( int fd, SCNHDR *pScnHdr, char **pScnAddr, char *pText, char *pData ) { int ix; int textCount = 0; int dataCount = 0; INT32 size; /* section size */ int nbytes; /* additional bytes required for alignment */ char *pLoad; /* address to load data at */ for (ix = 0; ix < max_scns; ix++) { pLoad = NULL; size = pScnHdr->s_size; if (size != 0 && pScnHdr->s_scnptr != 0) { if (pScnHdr->s_flags & STYP_TEXT) { pLoad = pText; nbytes = dataAlign(MAX_ALIGNMENT, pLoad); pLoad += nbytes; pText = (char *) ((int) pLoad + size); /* for next load */ textCount += size + nbytes; } else if (pScnHdr->s_flags & STYP_DATA) { pLoad = pData; nbytes = dataAlign(MAX_ALIGNMENT, pLoad); pLoad += nbytes; pData = (char *) ((int) pLoad + size); /* for next load */ dataCount += size + nbytes; } else { /* ignore all other sections */ pScnAddr[ix] = pLoad; pScnHdr++; continue; } /* Advance to position in file * and read section directly into memory. */ if ((lseek (fd, pScnHdr->s_scnptr, SEEK_SET) == ERROR) || (fioRead (fd, pLoad, size) != size)) { return (ERROR); } } pScnAddr[ix] = pLoad; pScnHdr++; } return (OK); }/********************************************************************************* pecoffSymTab -** This is passed a pointer to a pecoff symbol table and processes* each of the external symbols defined therein. This processing performs* two functions:** 1) Defined symbols are entered in the system symbol table as* specified by the "symFlag" argument:* LOAD_ALL_SYMBOLS = all defined symbols (LOCAL and GLOBAL) are added,* LOAD_GLOBAL_SYMBOLS = only external (GLOBAL) symbols are added,* LOAD_NO_SYMBOLS = no symbols are added;** 2) Any undefined externals are looked up in the system symbol table to* determine their values. The values are entered into the specified* 'externals' array. This array is indexed by the symbol number* (position in the symbol table).* Note that all symbol values, not just undefined externals, are entered* into the 'externals' array. The values are used to perform relocations.** Note that "common" symbols have type undefined external - the value* field of the symbol will be non-zero for type common, indicating* the size of the object.** If an undefined external cannot be found in the system symbol table,* an error message is printed, but ERROR is not returned until the entire* symbol table has been read, which allows all undefined externals to be* looked up.** RETURNS: OK or ERROR*/LOCAL STATUS pecoffSymTab ( int fd, FILHDR *pHdr, /* pointer to file header */ SYMENT *externalSyms, /* pointer to symbols array */ char ***externals, /* pointer to pointer to array to fill in symbol absolute values */ int symFlag, /* symbols to be added to table * ([NO|GLOBAL|ALL]_SYMBOLS) */ SEG_INFO *pSeg, /* pointer to segment information */ char *symStrings, /* symbol string table */ SYMTAB_ID symTbl, /* symbol table to use */ char *pNextCommon, /* next common address in bss */ SCNHDR *pScnHdrArray, /* pointer to PECOFF section header array */ char **pScnAddr, /* pointer to section loaded address array */ BOOL symsAbsolute, /* TRUE if symbols already absolutely located*/ BOOL swapTables, UINT16 group, int imageBase ) { int status = OK; /* return status */ FAST char *name; /* symbol name (plus EOS) */ SYMENT *symbol; /* symbol struct */ SYM_TYPE vxSymType; /* vxWorks symbol type */ int symNum; /* symbol index */ char *adrs; /* table resident symbol address */ char *bias; /* section relative address */ ULONG bssAlignment; /* alignment value of common type */ long scnFlags; /* flags from section header */ int auxEnts = 0; /* auxiliary symbol entries to skip */ SCNHDR *pScnHdr = NULL; /* pointer to a PECOFF section header */ char *scnAddr = NULL; /* section loaded address */ char nameTemp[SYMNMLEN+1]; /* temporary for symbol name string */ /* Loop thru all symbol table entries in object file */ for (symNum = 0, symbol = externalSyms; symNum < pHdr->f_nsyms; symbol++, symNum++) { if (auxEnts) /* if this is an auxiliary entry */ { auxEnts--; continue; /* skip it */ } auxEnts = symbol->n_numaux; /* # of aux entries for this symbol */ if (symbol->n_scnum == N_DEBUG) continue; /* Setup pointer to symbol name string */ if (symbol->n_zeroes) /* if name is in symbol entry */ { name = symbol->n_name; if ( *(name + SYMNMLEN -1) != '\0') { /* If the symbol name array is full, * the string is not terminated by a null. * So, move the string to a temporary array, * where it can be null terminated. */ bcopy(name, nameTemp, SYMNMLEN); nameTemp[SYMNMLEN] = '\0'; name = nameTemp; } } else name = symStrings + symbol->n_offset; if ( ! PECOFF_UNDF(symbol) && ! PECOFF_COMM(symbol)) { /* Symbol is not an undefined external. * * Determine symbol's section and address bias */ if (symbol->n_scnum > 0) { pScnHdr = pScnHdrArray + (symbol->n_scnum - 1); scnAddr = pScnAddr[symbol->n_scnum - 1]; scnFlags = pScnHdr->s_flags; } else { scnFlags = 0; /* section has no text, data or bss */ continue; } if (symbol->n_scnum == N_ABS) /* special check for absolute syms */ { bias = 0; vxSymType = VX_ABS; } else if (scnFlags & STYP_TEXT) {/* define GNU_LD_ADDS_VMA if ldsimpc -r gets fixed */#ifdef GNU_LD_ADDS_VMA bias = (char *) (scnAddr - (char *) pScnHdr->s_vaddr);#else bias = (char *) scnAddr;#endif vxSymType = VX_TEXT; } else if (scnFlags & STYP_DATA) {#ifdef GNU_LD_ADDS_VMA bias = (char *) (scnAddr - (char *) pScnHdr->s_vaddr);#else bias = (char *) scnAddr;#endif vxSymType = VX_DATA; } else if (scnFlags & STYP_BSS) {#ifdef GNU_LD_ADDS_VMA bias = (char *) (scnAddr - (char *) pScnHdr->s_vaddr);#else bias = (char *) scnAddr;#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -