📄 loadecofflib.c
字号:
/* loadEcoffLib.c - UNIX extended coff object module loader *//* Copyright 1984-1996 Wind River Systems, Inc. */#include "copyright_wrs.h"/*modification history--------------------01q,30nov98,dbt no longer clear seg.flags<xxx> after loadSegmentAllocate() call. (SPR #23553).01p,05oct98,pcn Initialize all the fields in the SEG_INFO structure.01o,16sep98,pcn Set to _ALLOC_ALIGN_SIZE the flags field in seg structure (SPR #21836).01n,17jul98,pcn Fixed SPR #21836: alignment mismatch between sections and target.01m,31oct96,elp Replaced symAdd() call by symSAdd() call (symtbls synchro).01l,22feb94,caf modified rdEcoffSymTab() to pass through the object file's symbol table twice. this way, undefined symbols can be resolved w/ those appearing later in the table (SPR #3077).01k,23jan94,jpb fixed pointer skew problem (SPR #2896).01j,31jul92,dnw changed to call CACHE_TEXT_UPDATE. doc tweak.01i,29jul92,jmm fixed setting of address for BSS segment01h,23jul92,jmm moved SEG_INFO to loadLib.h memory allocation now done by loadSegmentsAllocate01g,23jul92,jmm removed include of loadCommonLib.h 01f,23jul92,ajm made boot loader independent01e,18jul92,smb Changed errno.h to errnoLib.h.01d,16jul92,jmm added module tracking code moved addSegNames to loadLib.c01c,07jul92,ajm updated cache interface01b,23jun92,ajm reduced ansi warnings for 68k compiler01a,14jun92,ajm merged from 5.0.5 loadLib.c v01b*//*DESCRIPTIONThis library provides an object module loading facility particuarly for theMIPS compiler environment. Any MIPS SYSV ECOFFformat files may be loaded into memory, relocated properly, theirexternal references resolved, and their external definitions added tothe system symbol table for use by other modules and from the shell.Modules may be loaded from any I/O stream.EXAMPLE.CS fdX = open ("/devX/objFile", O_RDONLY); loadModule (fdX, ALL_SYMBOLS); close (fdX);.CEThis code fragment would load the ecoff file "objFile" located ondevice "/devX/" into memory which would be allocated from the systemmemory pool. All external and static definitions from the file would beadded to the system symbol table.This could also have been accomplished from the shell, by typing:.CS -> ld (1) </devX/objFile.CEINCLUDE FILE: loadEcoffLib.hSEE ALSO: loadLib, usrLib, symLib, memLib,.pG "Basic OS"*//* LINTLIBRARY */#include "vxWorks.h"#include "stdio.h"#include "loadEcoffLib.h"#include "ecoffSyms.h"#include "ecoff.h"#include "ioLib.h"#include "fioLib.h"#include "bootLoadLib.h"#include "loadLib.h"#include "memLib.h"#include "pathLib.h"#include "string.h"#include "symLib.h"#include "sysSymTbl.h"#include "cacheLib.h"#include "errnoLib.h"#include "stdlib.h"#include "symbol.h" /* for SYM_TYPE typedef */#include "moduleLib.h"#include "loadEcoffComm.h"#define RTEXT 0#define RDATA 1#define RBSS 2#define U_SYM_TYPE asym.sc /* coff classes act as a.out types */#define U_SYM_VALUE asym.value/* coff types and classes as macros */#define COFF_EXT(symbol) (((symbol)->asym.st == stProc) || \ ((symbol)->asym.st == stGlobal))#define COFF_ABS(symbol) (((symbol)->asym.sc == scNil) || \ ((symbol)->asym.sc == scAbs))#define COFF_TEXT(symbol) ((symbol)->asym.sc == scText)#define COFF_DATA(symbol) (((symbol)->asym.sc == scData) || \ ((symbol)->asym.sc == scRData) || \ ((symbol)->asym.sc == scSData))#define COFF_BSS(symbol) (((symbol)->asym.sc == scBss) || \ ((symbol)->asym.sc == scSBss))#define COFF_UNDF(symbol) (((symbol)->asym.sc == scUndefined) || \ ((symbol)->asym.sc == scSUndefined))#define COFF_COMM(symbol) (((symbol)->asym.sc == scCommon) || \ ((symbol)->asym.sc == scSCommon))/* misc defines */#define COMMON_ALIGNMENT sizeof(double)#define OVERFLOW_COMPENSATION 0x10000#define OVERFLOW 0x00008000#define LS16BITS 0x0000ffff#define MS16BITS 0xffff0000#define MS4BITS 0xf0000000#define MS6BITS 0xfc000000#define LS26BITS 0x03ffffffLOCAL char extMemErrMsg [] = "loadEcoffLib error: insufficient memory for externals (need %d bytes).\n";LOCAL char cantConvSymbolType [] = "loadEcoffLib error: can't convert '%s' symbol type, error = %#x.\n";LOCAL char cantAddSymErrMsg [] = "loadEcoffLib error: can't add '%s' to system symbol table, error = %#x.\n";LOCAL char gpRelativeReloc [] = "loadEcoffLib error: can't relocate, recompile module with -G 0 flags.\n";/* forward static functions */static MODULE_ID ldEcoffMdlAtSym (int fd, int symFlag, char **ppText, char **ppData, char **ppBss, SYMTAB_ID symTbl);static STATUS rdEcoffSymTab (EXTR * pExtSyms, FAST int nEnts, char ***externals, int max_symbols, int symFlag, SEG_INFO *pSeg, char *symStrings, SYMTAB_ID symTbl, char *pNextCommon, int group);static STATUS relSegmentR3k (RELOC *pRelCmds, SCNHDR *pScnHdr, char **pExternals, int section, SEG_INFO *pSeg);static ULONG sizeEcoffCommons (EXTR *pNextSym, ULONG alignBss);static STATUS ecoffSecHdrRead (int fd, SCNHDR *pScnHdr, FILHDR *pHdr, BOOL swapTables);static STATUS ecoffReadInSections (int fd, char **pSectPtr, SCNHDR *pScnHdr, BOOL swapTables);static STATUS ecoffLdSections (char **pSectPtr, SCNHDR *pScnHdr, AOUTHDR *pOptHdr, char *pText, char *pData);static STATUS ecoffReadRelocInfo (int fd, SCNHDR *pScnHdr, RELOC **pRelsPtr, BOOL swapTables);static STATUS ecoffReadSymHdr (int fd, HDRR *pSymHdr, FILHDR *pHdr, BOOL swapTables);static STATUS ecoffReadExtStrings (int fd, char **pStrBuf, HDRR *pSymHdr);static STATUS ecoffReadExtSyms (int fd, EXTR **pExtSyms, HDRR *pSymHdr, BOOL swapTables);static int nameToRelocSection (char * pName);static STATUS ecoffToVxSym (EXTR *symbol, SYM_TYPE *pVxSymType);/********************************************************************************* loadEcoffInit - initialize the system for ecoff load modules** This routine initialized VxWorks to use an extended coff format for* loading modules.** RETURNS:* OK, or* ERROR if XXX** SEE ALSO: loadModuleAt()*/STATUS loadEcoffInit ( ) { /* XXX check for installed ? */ loadRoutine = (FUNCPTR) ldEcoffMdlAtSym; return (OK); }/******************************************************************************** ldEcoffMdlAtSym - load object module into memory with specified symbol table** This routine is the underlying routine to loadModuleAtSym(). This interface* allows specification of the the symbol table used to resolve undefined* external references and to which to add new symbols.** RETURNS:* MODULE_ID, or* NULL if can't read file or not enough memory or illegal file format** NOMANUAL*/ LOCAL MODULE_ID ldEcoffMdlAtSym ( FAST int fd, /* fd from which to read module */ int symFlag, /* symbols to be added to table * ([NO | GLOBAL | ALL]_SYMBOLS) */ char **ppText, /* load text segment at address pointed to by this * pointer, return load address via this pointer */ char **ppData, /* load data segment at address pointed to by this * pointer, return load address via this pointer */ char **ppBss, /* load bss segment at address pointed to by this * pointer, return load address via this pointer */ SYMTAB_ID symTbl /* symbol table to use */ ) { char *pText = (ppText == NULL) ? LD_NO_ADDRESS : *ppText; char *pData = (ppData == NULL) ? LD_NO_ADDRESS : *ppData; char *pBss = (ppBss == NULL) ? LD_NO_ADDRESS : *ppBss; char **externalsBuf = NULL; /* buffer for reading externals */ EXTR *externalSyms = NULL; /* buffer for reading ecoff externals */ EXTR *pNextSym = NULL; /* temp pointer to symbols */ char *stringsBuf = NULL; /* string table pointer */ FILHDR hdr; /* module's ECOFF header */ AOUTHDR optHdr; /* module's ECOFF optional header */ SCNHDR scnHdr[MAX_SCNS]; /* module's ECOFF section headers */ char *sectPtr[MAX_SCNS]; /* ecoff sections */ RELOC *relsPtr[MAX_SCNS]; /* section relocation */ HDRR symHdr; /* symbol table header */ SEG_INFO seg; /* file segment info */ BOOL tablesAreLE; /* boolean for table sex */ ULONG alignBss; /* next boundry for common entry */ ULONG symbolValue; /* size of a symbol */ int status; /* return value */ int section; /* ecoff section number */ int ix; /* temp counter */ int nbytes = 0; /* temp counter */ char fileName[255]; UINT16 group; MODULE_ID moduleId; /* Initialization */ memset ((void *)&seg, 0, sizeof (seg)); /* 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++) { sectPtr[ix] = NULL; relsPtr[ix] = NULL; bzero ((char *) &scnHdr[ix], (int) sizeof(SCNHDR)); } /* read object module header */ if (ecoffHdrRead (fd, &hdr, &tablesAreLE) != OK) { errnoSet(S_loadEcoffLib_HDR_READ); goto error; } /* read in optional header */ if (ecoffOpthdrRead (fd, &optHdr, &hdr, tablesAreLE) != OK) { errnoSet(S_loadEcoffLib_OPTHDR_READ); goto error; } 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); seg.sizeText = optHdr.tsize; seg.sizeData = optHdr.dsize; seg.sizeBss = optHdr.bsize; /* * 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. */ seg.flagsText = _ALLOC_ALIGN_SIZE; seg.flagsData = _ALLOC_ALIGN_SIZE; seg.flagsBss = _ALLOC_ALIGN_SIZE; /* * 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; pBss = LD_NO_ADDRESS; } /* read in section headers */ if (ecoffSecHdrRead (fd, &scnHdr[0], &hdr, tablesAreLE) != OK) { errnoSet(S_loadEcoffLib_SCNHDR_READ); goto error; } /* read in all sections */ if (ecoffReadInSections (fd, §Ptr[0], &scnHdr[0], tablesAreLE) != OK) { errnoSet(S_loadEcoffLib_READ_SECTIONS); goto error; } /* copy sections to text, and data */ if (ecoffLdSections (§Ptr[0], &scnHdr[0], &optHdr, pText, pData) != OK) { errnoSet (S_loadEcoffLib_LOAD_SECTIONS); goto error; } /* * free section memory that is no longer needed (sectPtr). * note: free should be as early as possible to allow memory reuse, * this is extremenly important in order to load large object modules. */ for (ix = 0; ix < MAX_SCNS; ix++) { if (sectPtr[ix] != NULL) { free((char *) sectPtr[ix]); sectPtr[ix] = NULL; } } /* get section relocation info */ if (ecoffReadRelocInfo (fd, &scnHdr[0], &relsPtr[0], tablesAreLE) != OK) { errnoSet (S_loadEcoffLib_RELOC_READ); goto error; } /* read in symbolic header */ if (ecoffReadSymHdr (fd, &symHdr, &hdr, tablesAreLE) != OK) { errnoSet (S_loadEcoffLib_SYMHDR_READ); goto error; } /* read in local symbols XXX */ /* read in local string table XXX */ /* read external string table */ if (ecoffReadExtStrings (fd, &stringsBuf, &symHdr) != OK) { errnoSet (S_loadEcoffLib_EXTSTR_READ); goto error; } /* read in external symbols */ if (ecoffReadExtSyms (fd, &externalSyms, &symHdr, tablesAreLE) != OK) { errnoSet (S_loadEcoffLib_EXTSYM_READ); goto error; } /* calculate room for external commons in bss */ alignBss = COMMON_ALIGNMENT; nbytes = 0; for(pNextSym = (EXTR *) externalSyms; pNextSym < (EXTR *) ((long) externalSyms + (symHdr.iextMax * cbEXTR)); pNextSym++) { if (COFF_EXT(pNextSym) && COFF_COMM(pNextSym)) { symbolValue = sizeEcoffCommons (pNextSym, alignBss); nbytes += symbolValue; alignBss += symbolValue; } } /* add common size to bss */ seg.sizeBss = nbytes + optHdr.bsize; if ((pBss == LD_NO_ADDRESS) || (seg.sizeBss > 0)) { if ((pBss = (char *) malloc (seg.sizeBss)) == NULL) goto error; seg.addrBss = pBss; seg.flagsBss |= SEG_FREE_MEMORY; } /* allocate the externalsBuf */ if (symHdr.iextMax != 0) { externalsBuf = (char **) malloc ((long) symHdr.iextMax * sizeof (char *)); if (externalsBuf == NULL) { printErr (extMemErrMsg, symHdr.iextMax * sizeof (char *)); goto error; } } /* 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 = rdEcoffSymTab (externalSyms, symHdr.iextMax, &externalsBuf, symHdr.iextMax, symFlag, &seg, stringsBuf, symTbl, (char *) ((long) seg.addrBss + (seg.sizeBss - nbytes)), group); if (stringsBuf != NULL) { free (stringsBuf); /* finished with stringsBuf */ stringsBuf = NULL; } if (externalSyms != NULL) { free (externalSyms); /* finished with externalSyms */ externalSyms = NULL; } /* * 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. * caution: the order of relocation sections is not always the same * as the order of the sections */ if ((status == OK) || (errnoGet () == S_symLib_SYMBOL_NOT_FOUND)) { for (ix = 0; ix < MAX_SCNS; ix++) { if (relsPtr[ix] != NULL) { if ((section = nameToRelocSection (scnHdr[ix].s_name)) == ERROR) { errnoSet (S_loadEcoffLib_GPREL_REFERENCE); printErr (gpRelativeReloc); goto error; } if (relSegmentR3k (relsPtr[ix], &scnHdr[ix], externalsBuf, section, &seg) != OK) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -