📄 loadpecofflib.c
字号:
/* loadPecoffLib.c - pecoff object module loader *//* Copyright 1998-2002 Wind River Systems, Inc. */#include "copyright_wrs.h"/*modification history--------------------01l,11may02,fmk SPR 77007 - improve common symbol support01k,13mar02,pfl removed GNU_LD_ADDS_VMA, fixed data symbol relocation calculation (SPR 73145)01j,08mar02,pfl rewind to the beginning of the file before reading the header information (SPR 73136)01i,19oct01,pad Fixed erroneous relocation of non-text segments and made compliant with a Microsoft-directed bizarreness (BSS section size set in BSS section header's physical address field) in the Gnu toolchain (SPR 70767). This fixes SPR 71534 along the way. Now discardable sections are really not relocated. Now really handles absolute symbols. No longer complains because of .stab and .stabstr symbols. Tidied setting of errnos and other little things of the like.01h,26sep01,jmp increased MAX_SCNS to 100 (SPR# 63431).01g,30nov98,dbt no longer clear seg.flags<xxx> after loadSegmentAllocate() call. (SPR #23553).01f,05oct98,pcn Initialize all the fields in the SEG_INFO structure.01e,23sep98,cym adding check for STYP_INFO,NO_LOAD,REG,PAD before relocating.01d,18sep98,pcn Set to _ALLOC_ALIGN_SIZE the flags field in seg structure (SPR #21836).01c,15sep98,cym ignoring s_vaddr for relocatable objects until ldsimpc -r is fixed to sych it correctly.01b,17jul98,pcn Fixed SPR #21836: alignment mismatch between sections and target.01a,19mar98,cym created from on loadCoffLib.c*//*DESCRIPTIONThis library provides an object module loading facility for loadingPECOFF format object files. The object files are loaded into memory, relocated properly, their external references resolved, and their external definitions added to the 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", READ); loadModule (fdX, ALL_SYMBOLS); close (fdX);.CEThis code fragment would load the PECOFF 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: loadLib.hSEE ALSO: usrLib, symLib, memLib,.pG "Basic OS"*//* includes */#include "vxWorks.h"#include "bootLoadLib.h"#include "cacheLib.h"#include "errnoLib.h"#include "fioLib.h"#include "ioLib.h"#include "loadLib.h"#include "memLib.h"#include "pathLib.h"#include "stdio.h"#include "stdlib.h"#include "string.h"#include "symLib.h"#include "symbol.h" /* for SYM_TYPE typedef */#include "sysSymTbl.h"#include "private/vmLibP.h"#include "private/loadLibP.h"#if CPU==SIMNT#include "loadPecoffLib.h"/* VxWorks Symbol Type definitions. * * These are the symbol types for symbols stored in the vxWorks symbol table. * These are currently defined in b_out.h as N_xxx (e.g. N_ABS). * They are defined with new macro names so that they are * independent of the object format. * It would probably be better to define these in symLib.h. */#define VX_ABS 2 /* Absolute symbol */#define VX_TEXT 4 /* Text symbol */#define VX_DATA 6 /* Data symbol */#define VX_BSS 8 /* BSS symbol */#define VX_EXT 1 /* External symbol (OR'd in with one of above) *//* * SYM_BASIC_NOT_COMM_MASK and SYM_BASIC_MASK are temporary masks until * symbol values are harmonized between host and target sides */#define SYM_BASIC_NOT_COMM_MASK 0x0d /* basic mask but unset bit two for common symbol */#define SYM_BASIC_MASK 0x0f /* only basic types are of interest *//* * Abridged edition of a object file symbol entry SYMENT * * This is used to minimize the amount of malloc'd memory. * The abridged edition contains all elements of SYMENT required * to perform relocation. */struct symentAbridged { long n_value; /* value of symbol */ short n_scnum; /* section number */ char n_sclass; /* storage class */ char n_numaux; /* number of auxiliary entries */};#define SYMENT_A struct symentAbridged#define SYMESZ_A sizeof(SYMENT_A) /* * PECOFF symbol types and classes as macros * * 'sym' in the macro defintion must be defined as: SYMENT *sym; */#define U_SYM_VALUE n_value#define PECOFF_EXT(sym) \ ((sym)->n_sclass == C_EXT)/* PECOFF Undefined External Symbol */#define PECOFF_UNDF(sym) \ (((sym)->n_sclass == C_EXT) && ((sym)->n_scnum == N_UNDEF))/* PECOFF Common Symbol * A common symbol type is denoted by undefined external * with its value set to non-zero. */#define PECOFF_COMM(sym) ((PECOFF_UNDF(sym)) && ((sym)->n_value != 0))/* PECOFF Unassigned type * An unassigned type symbol of class C_STAT generated by * some assemblers */#define PECOFF_UNASSIGNED(sym) (((sym)->n_sclass == C_STAT) && ((sym)->n_type == T_NULL))/* misc defines */#define INSERT_HWORD(WORD,HWORD) \ (((WORD) & 0xff00ff00) | (((HWORD) & 0xff00) << 8) | ((HWORD)& 0xff))#define EXTRACT_HWORD(WORD) \ (((WORD) & 0x00ff0000) >> 8) | ((WORD)& 0xff)#define SIGN_EXTEND_HWORD(HWORD) \ ((HWORD) & 0x8000 ? (HWORD)|0xffff0000 : (HWORD))#define SWAB_SHORT(s) \ ((((unsigned short) s & 0x00ff) << 8) | (((unsigned short) s & 0xff00) >> 8))#define MAX_SCNS 100 /* max sections supported */#define NO_SCNS 0#define MAX_ALIGNMENT 4 /* max boundary for architecture */char *addrScn[MAX_SCNS]; /* where each section is located */LOCAL int max_scns = MAX_SCNS; /* load with MAX */LOCAL char stringMemErrMsg [] = "loadLib error: insufficient memory for strings table (need %d bytes).\n";LOCAL char extMemErrMsg [] = "loadLib error: insufficient memory for externals table (need %d bytes).\n";LOCAL char cantConvSymbolType [] = "loadLib error: can't convert '%s' symbol type - error = %#x.\n";LOCAL char cantAddSymErrMsg [] = "loadLib error: can't add '%s' to system symbol table - error = %#x.\n";#ifndef MULTIPLE_LOADERSLOCAL char fileTypeUnsupported [] = "loadLib error: File type with magic number %#x is not supported.\n";#endif/* forward declarations */LOCAL void pecoffFree ();LOCAL void pecoffSegSizes ();LOCAL STATUS pecoffReadSym ();LOCAL STATUS fileRead ();LOCAL STATUS swabData ();LOCAL void swabLong ();LOCAL ULONG pecoffTotalCommons ();LOCAL ULONG dataAlign ();LOCAL STATUS pecoffHdrRead ();LOCAL STATUS pecoffOpthdrRead ();LOCAL STATUS pecoffSecHdrRead ();LOCAL STATUS pecoffLoadSections ();LOCAL STATUS pecoffReadRelocInfo ();LOCAL STATUS pecoffReadExtSyms ();LOCAL STATUS pecoffReadExtStrings ();LOCAL STATUS pecoffRelSegmentI386 ();LOCAL STATUS pecoffSymTab (int fd, struct filehdr * pHdr, SYMENT * pSymbols, char *** externals, int symFlag, SEG_INFO * pSeg, char * symStrings, SYMTAB_ID symTbl, char * pNextCommon, struct scnhdr * pScnHdrArray, char ** pScnAddr, BOOL fullyLinked, UINT16 group, int imageBase);LOCAL STATUS loadPecoffCommonManage (char * symName, SYMTAB_ID symTbl, SYM_ADRS * pSymAddr, SYM_TYPE * pSymType, int loadFlag);/******************************************************************************** ldPecoffModAtSym - load object module into memory with specified symbol table** This routine is the underlying routine to loadModuleAtSum(). 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*/MODULE_ID ldPecoffModAtSym ( 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; /* array of symbol absolute values */ char *externalSyms = NULL; /* buffer for object file symbols */ char *stringsBuf = NULL; /* string table pointer */ FILHDR hdr; /* module's PECOFF header */ PEOPTION optHdr; /* module's PECOFF optional header */ SCNHDR scnHdr[MAX_SCNS]; /* module's PECOFF section headers */ char *scnAddr[MAX_SCNS]; /* array of section loaded address */ RELOC *relsPtr[MAX_SCNS]; /* section relocation */ SEG_INFO seg; /* file segment info */ BOOL tablesAreLE; /* boolean for table sex */ BOOL fullyLinked = 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; int hdrEnd; /* 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++) { scnAddr[ix] = NULL; relsPtr[ix] = NULL; bzero((char *) &scnHdr[ix], (int) sizeof(SCNHDR)); } /* read object module header */ if (pecoffHdrRead (fd, &hdr, &tablesAreLE) != OK) { /* Preserve errno value from subroutine. */ goto error; } hdrEnd = lseek (fd, 0, SEEK_CUR); /* Read in optional header if one exists */ if (hdr.f_opthdr) { if (pecoffOpthdrRead (fd, &optHdr, tablesAreLE) != OK) { errnoSet(S_loadLib_OPTHDR_READ); goto error; } } lseek (fd,hdrEnd + hdr.f_opthdr, SEEK_SET); /* read in section headers */ if (pecoffSecHdrRead (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(). */ pecoffSegSizes (&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 */ { fullyLinked = TRUE; pText = (INT8 *)(optHdr.text_start + optHdr.image_base); pData = (INT8 *)(optHdr.data_start + optHdr.image_base); /* 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 pecoff 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; pBss = LD_NO_ADDRESS; } /* 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 (!fullyLinked) { if (pecoffLoadSections (fd, &scnHdr[0], &scnAddr[0], pText, pData) != OK) { errnoSet (S_loadLib_LOAD_SECTIONS); goto error; } /* get section relocation info */ if (pecoffReadRelocInfo (fd, &scnHdr[0], &relsPtr[0], tablesAreLE) != OK) { errnoSet (S_loadLib_RELOC_READ); goto error; } } /* read symbols */ if (pecoffReadExtSyms (fd, &externalSyms, &externalsBuf, &hdr, tablesAreLE) != OK) { errnoSet (S_loadLib_EXTSYM_READ); goto error; } /* read string table */ if (pecoffReadExtStrings (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 = pecoffTotalCommons(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) { 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, fullyLinked, 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. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -