loadPecoffLib.c
上传用户:baixin
上传日期:2008-03-13
资源大小:4795k
文件大小:58k
开发平台:

MultiPlatform

  1. /* loadPecoffLib.c - pecoff object module loader */
  2. /* Copyright 1998-2002 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 01l,11may02,fmk  SPR 77007 - improve common symbol support
  8. 01k,13mar02,pfl  removed GNU_LD_ADDS_VMA, fixed data symbol relocation 
  9.                  calculation (SPR 73145)
  10. 01j,08mar02,pfl  rewind to the beginning of the file before reading the
  11.                  header information (SPR 73136)
  12. 01i,19oct01,pad  Fixed erroneous relocation of non-text segments and made
  13.  compliant with a Microsoft-directed bizarreness (BSS section
  14.  size set in BSS section header's physical address field) in
  15.  the Gnu toolchain (SPR 70767). This fixes SPR 71534 along the
  16.  way. Now discardable sections are really not relocated.
  17.  Now really handles absolute symbols. No longer complains
  18.  because of .stab and .stabstr symbols. Tidied setting of
  19.  errnos and other little things of the like.
  20. 01h,26sep01,jmp  increased MAX_SCNS to 100 (SPR# 63431).
  21. 01g,30nov98,dbt  no longer clear seg.flags<xxx> after loadSegmentAllocate()
  22.                  call. (SPR #23553).
  23. 01f,05oct98,pcn  Initialize all the fields in the SEG_INFO structure.
  24. 01e,23sep98,cym  adding check for STYP_INFO,NO_LOAD,REG,PAD before relocating.
  25. 01d,18sep98,pcn  Set to _ALLOC_ALIGN_SIZE the flags field in seg structure
  26.                  (SPR #21836).
  27. 01c,15sep98,cym  ignoring s_vaddr for relocatable objects until ldsimpc -r
  28.  is fixed to sych it correctly.
  29. 01b,17jul98,pcn  Fixed SPR #21836: alignment mismatch between sections and
  30.                  target.
  31. 01a,19mar98,cym  created from on loadCoffLib.c
  32. */
  33. /*
  34. DESCRIPTION
  35. This library provides an object module loading facility for loading
  36. PECOFF format object files.  The object files are loaded into memory, 
  37. relocated properly, their external references resolved, and their external 
  38. definitions added to the system symbol table for use by other modules and 
  39. from the shell.  Modules may be loaded from any I/O stream.
  40. EXAMPLE
  41. .CS
  42.     fdX = open ("/devX/objFile", READ);
  43.     loadModule (fdX, ALL_SYMBOLS);
  44.     close (fdX);
  45. .CE
  46. This code fragment would load the PECOFF file "objFile" located on
  47. device "/devX/" into memory which would be allocated from the system
  48. memory pool.  All external and static definitions from the file would be
  49. added to the system symbol table.
  50. This could also have been accomplished from the shell, by typing:
  51. .CS
  52.     -> ld (1) </devX/objFile
  53. .CE
  54. INCLUDE FILE: loadLib.h
  55. SEE ALSO: usrLib, symLib, memLib,
  56. .pG "Basic OS"
  57. */
  58. /* includes */
  59. #include "vxWorks.h"
  60. #include "bootLoadLib.h"
  61. #include "cacheLib.h"
  62. #include "errnoLib.h"
  63. #include "fioLib.h"
  64. #include "ioLib.h"
  65. #include "loadLib.h"
  66. #include "memLib.h"
  67. #include "pathLib.h"
  68. #include "stdio.h"
  69. #include "stdlib.h"
  70. #include "string.h"
  71. #include "symLib.h"
  72. #include "symbol.h" /* for SYM_TYPE typedef */
  73. #include "sysSymTbl.h"
  74. #include "private/vmLibP.h"
  75. #include "private/loadLibP.h"
  76. #if CPU==SIMNT
  77. #include "loadPecoffLib.h"
  78. /*  VxWorks Symbol Type definitions.
  79.  *
  80.  *  These are the symbol types for symbols stored in the vxWorks symbol table.
  81.  *  These are currently defined in b_out.h as N_xxx (e.g. N_ABS).
  82.  *  They are defined with new macro names so that they are
  83.  *       independent of the object format.
  84.  *  It would probably be better to define these in symLib.h.
  85.  */
  86. #define VX_ABS 2 /* Absolute symbol */
  87. #define VX_TEXT 4 /* Text symbol */
  88. #define VX_DATA 6 /* Data symbol */
  89. #define VX_BSS 8 /* BSS symbol */
  90. #define VX_EXT 1 /* External symbol (OR'd in with one of above) */
  91. /* 
  92.  * SYM_BASIC_NOT_COMM_MASK and SYM_BASIC_MASK are temporary masks until
  93.  * symbol values are harmonized between host and target sides
  94.  */
  95. #define SYM_BASIC_NOT_COMM_MASK   0x0d   /* basic mask but unset bit two for common symbol */
  96. #define SYM_BASIC_MASK            0x0f   /* only basic types are of interest */
  97. /*
  98.  *  Abridged edition of a object file symbol entry SYMENT
  99.  *
  100.  *  This is used to minimize the amount of malloc'd memory.
  101.  *  The abridged edition contains all elements of SYMENT required
  102.  *  to perform relocation.
  103.  */
  104. struct symentAbridged {
  105. long n_value; /* value of symbol */
  106. short n_scnum; /* section number */
  107. char n_sclass; /* storage class */
  108. char n_numaux;       /* number of auxiliary entries  */
  109. };
  110. #define SYMENT_A struct symentAbridged
  111. #define SYMESZ_A sizeof(SYMENT_A)
  112. /* 
  113.  *  PECOFF symbol types and classes as macros
  114.  *
  115.  *   'sym' in the macro defintion must be defined as:   SYMENT *sym;
  116.  */
  117. #define U_SYM_VALUE    n_value
  118. #define PECOFF_EXT(sym) 
  119.     ((sym)->n_sclass == C_EXT)
  120. /*  PECOFF Undefined External Symbol */
  121. #define PECOFF_UNDF(sym) 
  122.     (((sym)->n_sclass == C_EXT) && ((sym)->n_scnum == N_UNDEF))
  123. /*  PECOFF Common Symbol
  124.  *    A common symbol type is denoted by undefined external
  125.  *    with its value set to non-zero.
  126.  */
  127. #define PECOFF_COMM(sym) ((PECOFF_UNDF(sym)) && ((sym)->n_value != 0))
  128. /* PECOFF Unassigned type
  129.  *    An unassigned type symbol of class C_STAT generated by
  130.  *    some assemblers
  131.  */
  132. #define PECOFF_UNASSIGNED(sym) (((sym)->n_sclass == C_STAT) && ((sym)->n_type == T_NULL))
  133. /* misc defines */
  134. #define INSERT_HWORD(WORD,HWORD)        
  135.     (((WORD) & 0xff00ff00) | (((HWORD) & 0xff00) << 8) | ((HWORD)& 0xff))
  136. #define EXTRACT_HWORD(WORD) 
  137.     (((WORD) & 0x00ff0000) >> 8) | ((WORD)& 0xff)
  138. #define SIGN_EXTEND_HWORD(HWORD) 
  139.     ((HWORD) & 0x8000 ? (HWORD)|0xffff0000 : (HWORD))
  140. #define SWAB_SHORT(s) 
  141.   ((((unsigned short) s & 0x00ff) << 8) | (((unsigned short) s & 0xff00) >> 8))
  142. #define MAX_SCNS        100 /* max sections supported */
  143. #define NO_SCNS         0
  144. #define MAX_ALIGNMENT 4 /* max boundary for architecture */
  145. char *addrScn[MAX_SCNS];                /* where each section is located */
  146. LOCAL int  max_scns = MAX_SCNS; /* load with MAX */
  147. LOCAL char stringMemErrMsg [] =
  148.     "loadLib error: insufficient memory for strings table (need %d bytes).n";
  149. LOCAL char extMemErrMsg [] =
  150.     "loadLib error: insufficient memory for externals table (need %d bytes).n";
  151. LOCAL char cantConvSymbolType [] =
  152.     "loadLib error: can't convert '%s' symbol type - error = %#x.n";
  153. LOCAL char cantAddSymErrMsg [] =
  154.     "loadLib error: can't add '%s' to system symbol table - error = %#x.n";
  155. #ifndef MULTIPLE_LOADERS
  156. LOCAL char fileTypeUnsupported [] =
  157.     "loadLib error: File type with magic number %#x is not supported.n";
  158. #endif
  159. /* forward declarations */
  160. LOCAL void pecoffFree ();
  161. LOCAL void pecoffSegSizes ();
  162. LOCAL STATUS pecoffReadSym ();
  163. LOCAL STATUS fileRead ();
  164. LOCAL STATUS swabData ();
  165. LOCAL void swabLong ();
  166. LOCAL ULONG pecoffTotalCommons ();
  167. LOCAL ULONG dataAlign ();
  168. LOCAL STATUS pecoffHdrRead ();
  169. LOCAL STATUS pecoffOpthdrRead ();
  170. LOCAL STATUS pecoffSecHdrRead ();
  171. LOCAL STATUS pecoffLoadSections ();
  172. LOCAL STATUS pecoffReadRelocInfo ();
  173. LOCAL STATUS pecoffReadExtSyms ();
  174. LOCAL STATUS pecoffReadExtStrings ();
  175. LOCAL STATUS pecoffRelSegmentI386 ();
  176. LOCAL STATUS pecoffSymTab (int fd, struct filehdr * pHdr, SYMENT * pSymbols, 
  177.    char *** externals, int symFlag, SEG_INFO * pSeg,
  178.    char * symStrings, SYMTAB_ID symTbl,
  179.    char * pNextCommon, struct scnhdr * pScnHdrArray,
  180.    char ** pScnAddr, BOOL fullyLinked,
  181.    UINT16 group, int imageBase);
  182. LOCAL STATUS loadPecoffCommonManage (char * symName, SYMTAB_ID symTbl, 
  183.                                      SYM_ADRS * pSymAddr,
  184.                                      SYM_TYPE * pSymType, int loadFlag);
  185. /******************************************************************************
  186. *
  187. * ldPecoffModAtSym - load object module into memory with specified symbol table
  188. *
  189. * This routine is the underlying routine to loadModuleAtSum().  This interface
  190. * allows specification of the the symbol table used to resolve undefined
  191. * external references and to which to add new symbols.
  192. *
  193. * RETURNS:
  194. * MODULE_ID, or
  195. * NULL if can't read file or not enough memory or illegal file format
  196. *
  197. * NOMANUAL
  198. */
  199. MODULE_ID ldPecoffModAtSym
  200.     (
  201.     int fd, /* fd from which to read module */
  202.     int symFlag, /* symbols to be added to table 
  203.  *   ([NO | GLOBAL | ALL]_SYMBOLS) */
  204.     char **ppText, /* load text segment at address pointed to by this
  205.  * pointer, return load address via this pointer */
  206.     char **ppData, /* load data segment at address pointed to by this
  207.  * pointer, return load address via this pointer */
  208.     char **ppBss, /* load bss segment at address pointed to by this
  209.  * pointer, return load address via this pointer */
  210.     SYMTAB_ID symTbl /* symbol table to use */
  211.     )
  212.     {
  213.     char *pText = (ppText == NULL) ? LD_NO_ADDRESS : *ppText;
  214.     char *pData = (ppData == NULL) ? LD_NO_ADDRESS : *ppData;
  215.     char *pBss  = (ppBss  == NULL) ? LD_NO_ADDRESS : *ppBss;
  216.     char **externalsBuf = NULL;         /* array of symbol absolute values */
  217.     char *externalSyms = NULL;          /* buffer for object file symbols */
  218.     char *stringsBuf = NULL; /* string table pointer */
  219.     FILHDR hdr; /* module's PECOFF header */
  220.     PEOPTION optHdr;              /* module's PECOFF optional header */
  221.     SCNHDR scnHdr[MAX_SCNS]; /* module's PECOFF section headers */
  222.     char *scnAddr[MAX_SCNS];            /* array of section loaded address */
  223.     RELOC  *relsPtr[MAX_SCNS];  /* section relocation */
  224.     SEG_INFO seg; /* file segment info */
  225.     BOOL tablesAreLE; /* boolean for table sex */
  226.     BOOL fullyLinked = FALSE;          /* TRUE if already absolutely located*/
  227.     int status; /* return value */
  228.     int ix; /* temp counter */
  229.     int nbytes; /* temp counter */
  230.     char *pCommons;                     /* start of common symbols in bss */
  231.     char *addrBss;
  232.     char        fileName[255];
  233.     UINT16      group;
  234.     MODULE_ID   moduleId;
  235.     int hdrEnd;
  236.     /* initialization */
  237.     memset ((void *)&seg, 0, sizeof (seg));
  238.     /* Set up the module */
  239.     ioctl (fd, FIOGETNAME, (int) fileName);
  240.     moduleId = loadModuleGet (fileName, MODULE_ECOFF, &symFlag);
  241.     if (moduleId == NULL)
  242.         return (NULL);
  243.     group = moduleId->group;
  244.     /* init section pointers to NULL */
  245.     for (ix = 0; ix < MAX_SCNS; ix++)
  246. {
  247. scnAddr[ix] = NULL;
  248. relsPtr[ix] = NULL;
  249. bzero((char *) &scnHdr[ix], (int) sizeof(SCNHDR));
  250. }
  251.     /* read object module header */
  252.     if (pecoffHdrRead (fd, &hdr, &tablesAreLE) != OK)
  253. {
  254. /*  Preserve errno value from subroutine. */
  255. goto error;
  256. }
  257.     hdrEnd = lseek (fd, 0, SEEK_CUR);
  258.     /* Read in optional header if one exists */
  259.     if (hdr.f_opthdr)
  260.         {
  261.         if (pecoffOpthdrRead (fd, &optHdr, tablesAreLE) != OK)
  262.             {
  263.     errnoSet(S_loadLib_OPTHDR_READ);
  264.             goto error;
  265.             }
  266.         }
  267.     lseek (fd,hdrEnd + hdr.f_opthdr, SEEK_SET);
  268.     /* read in section headers */
  269.     if (pecoffSecHdrRead (fd, &scnHdr[0], &hdr, tablesAreLE) != OK)
  270. {
  271. errnoSet(S_loadLib_SCNHDR_READ);
  272. goto error;
  273. }
  274.     /* Determine segment sizes */
  275.     /* 
  276.      * XXX seg.flagsXxx mustn't be used between coffSegSizes() and 
  277.      * loadSegmentsAllocate().
  278.      */
  279.     pecoffSegSizes (&hdr, scnHdr, &seg);
  280.     /* 
  281.      * If object file is already absolutely located (by linker on host),
  282.      *  then override parameters pText, pData and pBss.
  283.      */
  284.     if ((hdr.f_flags & F_EXEC) || (hdr.f_flags & F_RELFLG))
  285.         {
  286.         if (hdr.f_opthdr)               /* if there is an optional header */
  287.             {
  288.             fullyLinked = TRUE;
  289.             pText = (INT8 *)(optHdr.text_start + optHdr.image_base);
  290.             pData = (INT8 *)(optHdr.data_start + optHdr.image_base);
  291.             /* bss follows data segment */
  292.             pBss = (INT8 *) pData + optHdr.dsize;
  293.             pBss += dataAlign(MAX_ALIGNMENT, pBss);
  294.     }
  295. }
  296.     seg.addrText = pText;
  297.     seg.addrData = pData;
  298.     /*
  299.      * If pBss is set to LD_NO_ADDRESS, change it to something else.
  300.      * The pecoff loader allocates one large BSS segment later on, and
  301.      * loadSegmentsAllocate doesn't work correctly for it.
  302.      */
  303.     seg.addrBss = (pBss == LD_NO_ADDRESS ? LD_NO_ADDRESS + 1 : pBss);
  304.     /* 
  305.      * SPR #21836: loadSegmentsAllocate() allocate memory aligned on 
  306.      * the max value of sections alignement saved in seg.flagsText,
  307.      * seg.flagsData, seg.flagsBss.
  308.      */
  309.     if (loadSegmentsAllocate (&seg) != OK)
  310.         {
  311.         printErr ("Could not allocate segmentsn");
  312.         goto error;
  313.         }
  314.     else
  315.         {
  316.         pText = seg.addrText;
  317.         pData = seg.addrData;
  318.         pBss = LD_NO_ADDRESS;
  319.         }
  320.     /*  Ensure that section starts on the appropriate alignment.
  321.      */
  322.     pText += dataAlign (MAX_ALIGNMENT, pText);
  323.     if (pData == LD_NO_ADDRESS)
  324.         {
  325. pData = pText + seg.sizeText;
  326.         }
  327.     /*  Ensure that section starts on the appropriate alignment.
  328.      */
  329.     pData += dataAlign (MAX_ALIGNMENT, pData);
  330.     seg.addrText = pText;
  331.     seg.addrData = pData;
  332.     /* load text and data sections */
  333.     if (!fullyLinked)
  334.         {
  335. if (pecoffLoadSections (fd, &scnHdr[0], &scnAddr[0], pText,
  336. pData) != OK)
  337.     {
  338.     errnoSet (S_loadLib_LOAD_SECTIONS);
  339.     goto error;
  340.     }
  341. /* get section relocation info */
  342.         if (pecoffReadRelocInfo (fd, &scnHdr[0], &relsPtr[0],
  343.  tablesAreLE) != OK)
  344.         {
  345.     errnoSet (S_loadLib_RELOC_READ);
  346.     goto error;
  347.     }
  348.         }
  349.     /* read symbols */
  350.     if (pecoffReadExtSyms (fd, &externalSyms, &externalsBuf, &hdr,
  351.    tablesAreLE) != OK)
  352. {
  353. errnoSet (S_loadLib_EXTSYM_READ);
  354. goto error;
  355. }
  356.     /* read string table */
  357.     if (pecoffReadExtStrings (fd, &stringsBuf, tablesAreLE) != OK)
  358. {
  359. errnoSet (S_loadLib_EXTSTR_READ);
  360. goto error;
  361. }
  362.     /*  Determine additional amount of memory required to append
  363.      *  common symbols on to the end of the BSS section.
  364.      */
  365.     nbytes = pecoffTotalCommons(externalSyms, hdr.f_nsyms, seg.sizeBss);
  366.     /* set up for bss */
  367.     seg.sizeBss += nbytes;
  368.     if (pBss == LD_NO_ADDRESS)
  369.         {
  370.         if (seg.sizeBss != 0)
  371.             {
  372.             if ((pBss = malloc (seg.sizeBss)) == NULL) 
  373.                 goto error;
  374.             else                                 
  375. seg.flagsBss |= SEG_FREE_MEMORY;  
  376.             }
  377.         else
  378.             {
  379.             pBss = (char *) ((long) pData + (long) seg.sizeData);
  380.             }
  381.         }
  382.     pBss += dataAlign(MAX_ALIGNMENT, pBss);
  383.     seg.addrBss = pBss;
  384.     /* fix up start address of bss sections */
  385.     addrBss = pBss;
  386.     for (ix = 0; ix < max_scns; ix++)
  387.         {
  388.         if (scnHdr[ix].s_flags & STYP_BSS)
  389.     {
  390.     addrBss += dataAlign (MAX_ALIGNMENT, addrBss);
  391.     scnAddr[ix] = addrBss;
  392.     addrBss += scnHdr[ix].s_size;
  393.             }
  394.         }
  395.     
  396.     /* set up address for first common symbol */
  397.     pCommons = (char *) ((long) seg.addrBss + (seg.sizeBss - nbytes));
  398.     /* add segment names to symbol table before other symbols */
  399.     if (symFlag != LOAD_NO_SYMBOLS)
  400.         addSegNames (fd, pText, pData, pBss, symTbl, group);
  401.     /* process symbol table */
  402.     status = pecoffSymTab (fd, &hdr, (SYMENT *)externalSyms, &externalsBuf, 
  403.  symFlag, &seg, stringsBuf, symTbl, pCommons, scnHdr,
  404.  scnAddr, fullyLinked, group, optHdr.image_base);
  405.     /* 
  406.      * Relocate text and data segments
  407.      *
  408.      *   note: even if symbol table had missing symbols, continue with
  409.      *   relocation of those symbols that were found.
  410.      *   note: relocation is for changing the values of the relocated
  411.      *   symbols.  bss is uninitialized data, so it is not relocated
  412.      *   in the symbol table.
  413.      */
  414.     if ((status == OK) || (errnoGet() == S_symLib_SYMBOL_NOT_FOUND))
  415.         for (ix = 0; ix < max_scns; ix++)
  416.     {
  417.     /*
  418.      * Only meaningful sections are relocated. Note that the section
  419.      * flags set for PECOFF do not allow to test for STYP_REG. The
  420.      * PE extension IMAGE_SCN_MEM_DISCARDABLE should be used instead.
  421.      */
  422.     if ((relsPtr[ix] != NULL)   &&
  423.                 !(scnHdr[ix].s_flags & STYP_INFO)   &&
  424.                 !(scnHdr[ix].s_flags & STYP_NOLOAD)   &&
  425.                 !(scnHdr[ix].s_flags & IMAGE_SCN_MEM_DISCARDABLE) &&
  426.                 !(scnHdr[ix].s_flags & STYP_PAD))
  427. {
  428.                 if (pecoffRelSegmentI386 (relsPtr[ix], scnHdr, externalsBuf, 
  429.                                externalSyms, &seg, ix) != OK)
  430.     {
  431.             goto error;
  432.     }
  433. }
  434.     }
  435.     pecoffFree(externalsBuf, externalSyms, stringsBuf, relsPtr);
  436.     /* write protect the text if text segment protection is turned on */
  437.     if (seg.flagsText & SEG_WRITE_PROTECTION)
  438. {
  439. if (VM_STATE_SET (NULL, pText, seg.sizeProtectedText,
  440.   VM_STATE_MASK_WRITABLE,
  441.   VM_STATE_WRITABLE_NOT) == ERROR)
  442.     goto error;
  443. }
  444.     /* return load addresses, where called for */
  445.     if (ppText != NULL)
  446.         *ppText = pText;
  447.     if (ppData != NULL)
  448.         *ppData = pData;
  449.     if (ppBss != NULL)
  450.         *ppBss = pBss;
  451.     /* clear out bss */
  452.     bzero (pBss, (int) seg.sizeBss);
  453.     /*
  454.      * Add the segments to the module.
  455.      * This has to happen after the relocation gets done.
  456.      * If the relocation happens first, the checksums won't be
  457.      * correct.
  458.      */
  459.     moduleSegAdd (moduleId, SEGMENT_TEXT, pText, seg.sizeText, seg.flagsText);
  460.     moduleSegAdd (moduleId, SEGMENT_DATA, pData, seg.sizeData, seg.flagsData);
  461.     moduleSegAdd (moduleId, SEGMENT_BSS, pBss, seg.sizeBss, seg.flagsBss);
  462.     if (status == OK)
  463.         return (moduleId);
  464.     else
  465.         return (NULL);
  466.     /* error:
  467.      * clean up dynamically allocated temporary buffers and return ERROR
  468.      */
  469. error:
  470.     pecoffFree(externalsBuf, externalSyms, stringsBuf, relsPtr);
  471.     moduleDelete (moduleId);
  472.     return (NULL);
  473.     }
  474. /******************************************************************************
  475. *
  476. * loadPecoffInit - initialize the system for pecoff load modules.
  477. *
  478. * This routine initializes VxWorks to use a PECOFF format for loading 
  479. * modules.
  480. *
  481. * RETURNS: OK
  482. *
  483. * SEE ALSO: loadModuleAt()
  484. */
  485. STATUS loadPecoffInit (void)
  486.     {
  487.     /* XXX check for installed? */
  488.     loadRoutine = (FUNCPTR) ldPecoffModAtSym;
  489.     return (OK);
  490.     }
  491. /*******************************************************************************
  492. *
  493. * pecoffFree - free any malloc'd memory
  494. *
  495. */
  496. LOCAL void pecoffFree
  497.     (
  498.     char **pExternalsBuf,       /* pointers to external symbols */
  499.     char *pExternalSyms,        /* buffer for external symbols */
  500.     char *pStringsBuf, /* string table pointer */
  501.     RELOC  **pRelsPtr  /* section relocation */
  502.     )
  503.     {
  504.     int ix;
  505.     if (pStringsBuf != NULL)
  506. free (pStringsBuf);
  507.     if (pExternalsBuf != NULL)
  508. free ((char *) pExternalsBuf);
  509.     if (pExternalSyms != NULL)
  510. free ((char *) pExternalSyms);
  511.     for (ix = 0; ix < MAX_SCNS; ix++)
  512. {
  513. if (*pRelsPtr != NULL)
  514.     free((char *) *pRelsPtr);
  515.         pRelsPtr++;
  516. }
  517.     }
  518. /*******************************************************************************
  519. *
  520. * pecoffSegSizes - determine segment sizes
  521. *
  522. * This function fills in the size fields in the SEG_INFO structure.
  523. * Note that the bss size may need to be readjusted for common symbols. 
  524. */
  525. LOCAL void pecoffSegSizes
  526.     (
  527.     FILHDR *pHdr,               /* pointer to file header */
  528.     SCNHDR *pScnHdrArray,       /* pointer to array of section headers */
  529.     SEG_INFO *pSeg        /* section addresses and sizes */
  530.     )
  531.     {
  532.     int ix;
  533.     int nbytes;             /* additional bytes required for alignment */
  534.     SCNHDR *pScnHdr;            /* pointer to a section header */
  535.     pSeg->sizeText = 0;
  536.     pSeg->sizeData = 0;
  537.     pSeg->sizeBss = 0;
  538.     /* 
  539.      * SPR #21836: pSeg->flagsText, pSeg->flagsData, pSeg->flagsBss are used
  540.      * to save the max value of each segments. These max values are computed
  541.      * for each sections. These fields of pSeg are only used on output, then
  542.      * a temporary use is allowed.
  543.      */
  544.     pSeg->flagsText = _ALLOC_ALIGN_SIZE;
  545.     pSeg->flagsData = _ALLOC_ALIGN_SIZE;
  546.     pSeg->flagsBss  = _ALLOC_ALIGN_SIZE;
  547.     for (ix=0; ix < pHdr->f_nscns; ix++) /* loop thru all sections */
  548.         {
  549.         pScnHdr = pScnHdrArray + ix;
  550.         if (pScnHdr->s_flags & STYP_TEXT)
  551.             {
  552.             /*  Assume that there was a previous section of same type.
  553.              *  First, align data to boundary from section header.
  554.              *  Add the size of this section to the total segment size.
  555.              */
  556.             nbytes = dataAlign(MAX_ALIGNMENT, pSeg->sizeText);
  557.             pSeg->sizeText += pScnHdr->s_size + nbytes;
  558.     /* SPR #21836 */
  559.     if (MAX_ALIGNMENT > pSeg->flagsText)
  560. pSeg->flagsText = MAX_ALIGNMENT;
  561.             }
  562.         else if (pScnHdr->s_flags & STYP_DATA)
  563.             {
  564.             nbytes = dataAlign(MAX_ALIGNMENT, pSeg->sizeData);
  565.             pSeg->sizeData += pScnHdr->s_size + nbytes;
  566.     /* SPR #21836 */
  567.     if (MAX_ALIGNMENT > pSeg->flagsData)
  568. pSeg->flagsData = MAX_ALIGNMENT;
  569.             }
  570.         else if (pScnHdr->s_flags & STYP_BSS)
  571.             {
  572.             nbytes = dataAlign(MAX_ALIGNMENT, pSeg->sizeBss);
  573.             pSeg->sizeBss += pScnHdr->s_size + nbytes;
  574.     /* SPR #21836 */
  575.     if (MAX_ALIGNMENT > pSeg->flagsBss)
  576. pSeg->flagsBss = MAX_ALIGNMENT;
  577.             }
  578.         }
  579.     }
  580. /*******************************************************************************
  581. *
  582. * pecoffLoadSections - read sections into memory
  583. */
  584. LOCAL STATUS pecoffLoadSections
  585.     (
  586.     int     fd,
  587.     SCNHDR  *pScnHdr,
  588.     char    **pScnAddr,
  589.     char    *pText,
  590.     char    *pData
  591.     )
  592.     {
  593.     int     ix;
  594.     int     textCount = 0;
  595.     int     dataCount = 0;
  596.     INT32   size;               /* section size */
  597.     int     nbytes;             /* additional bytes required for alignment */
  598.     char    *pLoad;             /* address to load data at */
  599.     for (ix = 0; ix < max_scns; ix++)
  600. {
  601.         pLoad = NULL;
  602.         size = pScnHdr->s_size;
  603. if (size != 0 && pScnHdr->s_scnptr != 0)
  604.     {
  605.             if (pScnHdr->s_flags & STYP_TEXT)
  606.                 {
  607.                 pLoad = pText;
  608.                 nbytes = dataAlign(MAX_ALIGNMENT, pLoad);
  609.                 pLoad += nbytes;
  610.                 pText = (char *) ((int) pLoad + size); /* for next load */
  611.                 textCount += size + nbytes;
  612.                 }
  613.             else if (pScnHdr->s_flags & STYP_DATA)
  614.                 {
  615.                 pLoad = pData;
  616.                 nbytes = dataAlign(MAX_ALIGNMENT, pLoad);
  617.                 pLoad += nbytes;
  618.                 pData = (char *) ((int) pLoad + size); /* for next load */
  619.                 dataCount += size + nbytes;
  620.                 }
  621.             else
  622.                 {
  623.                 /* ignore all other sections */
  624.                 pScnAddr[ix] = pLoad;
  625.                pScnHdr++;
  626. continue;
  627.                 }
  628.             /*  Advance to position in file
  629.              *  and read section directly into memory.
  630.              */
  631.     if ((lseek (fd, pScnHdr->s_scnptr, SEEK_SET) == ERROR) ||
  632. (fioRead (fd, pLoad, size) != size))
  633. {
  634. return (ERROR);
  635. }
  636.     }
  637.         pScnAddr[ix] = pLoad;
  638. pScnHdr++;
  639. }
  640.     return (OK);
  641.     }
  642. /*******************************************************************************
  643. *
  644. * loadPecoffCommonManage - process a common symbol
  645. *
  646. * This routine processes the common symbols found in the object module.
  647. * Common symbols are symbols declared global without being assigned a
  648. * value.  
  649. *
  650. * loadPecoffCommonManage() is derived from loadCommonMange() in
  651. * loadLib.c, but unlike loadCommonManage(), loadPecoffCommonManage() does
  652. * not allocate memory or add symbols to the symbol table:
  653. * loadPecoffCommonManage() leaves the chores of allocating memory
  654. * or adding symbols to the symbol table up to the caller.
  655. *
  656. * For more information on common symbol types,LOAD_COMMON_MATCH_NONE,
  657. * LOAD_COMMON_MATCH_USER and LOAD_COMMON_MATCH_ALL see
  658. * loadCommonManage() in loadLib.c.
  659. *
  660. * NOMANUAL 
  661. */
  662. LOCAL STATUS loadPecoffCommonManage
  663.     (
  664.     char *       symName,        /* symbol name */
  665.     SYMTAB_ID    symTbl,        /* target symbol table */
  666.     SYM_ADRS *   pSymAddr,       /* where to return symbol's address */
  667.     SYM_TYPE *   pSymType,       /* where to return symbol's type */
  668.     int          loadFlag       /* control of loader's behavior */
  669.     )
  670.     {
  671.     COMMON_INFO commInfo;       /* what to do with commons */
  672.     /* Force the default choice if no flag set */
  673.     if(!(loadFlag & LOAD_COMMON_MATCH_ALL) &&
  674.        !(loadFlag & LOAD_COMMON_MATCH_USER) &&
  675.        !(loadFlag & LOAD_COMMON_MATCH_NONE))
  676.         loadFlag |= LOAD_COMMON_MATCH_NONE;
  677.     /* Must we do more than the default ? */
  678.     if(!(loadFlag & LOAD_COMMON_MATCH_NONE))
  679.         {
  680.         /* Initialization */
  681.         memset (&commInfo, 0, sizeof (COMMON_INFO));
  682.         commInfo.symName = symName;
  683.         /* Do we involve the core's symbols ? */
  684.         if(loadFlag & LOAD_COMMON_MATCH_USER)
  685.             commInfo.vxWorksSymMatched = FALSE;    /* no */
  686.         else if(loadFlag & LOAD_COMMON_MATCH_ALL)
  687.             commInfo.vxWorksSymMatched = TRUE;    /* yes */
  688.         /* Get the last occurences of matching global symbols in bss and data  */
  689.         loadCommonMatch (&commInfo, symTbl);
  690.         /* Prefered order for matching symbols is : bss then data */
  691.         if(commInfo.pSymAddrBss != NULL)    /* matching sym in bss */
  692.             {
  693.             *pSymAddr = commInfo.pSymAddrBss;
  694.             *pSymType = commInfo.bssSymType;
  695.             }
  696.         else if(commInfo.pSymAddrData != NULL)    /* matching sym in data */
  697.             {
  698.             *pSymAddr = commInfo.pSymAddrData;
  699.             *pSymType = commInfo.dataSymType;
  700.             }
  701.         else *pSymAddr = NULL;          /* no matching symbol */
  702.         /* If we found a matching symbol, stop here */
  703.         if(*pSymAddr != NULL)
  704.             return (OK);
  705. }
  706.     
  707.     /* if a matching common symbol is not found, return ERROR*/
  708.     return (ERROR);
  709.     }
  710. /*******************************************************************************
  711. *
  712. * pecoffSymTab - process an object module symbol table
  713. *
  714. * This is passed a pointer to a pecoff symbol table and processes
  715. * each of the external symbols defined therein.  This processing performs
  716. * two functions:
  717. *
  718. *  1) Defined symbols are entered in the system symbol table as
  719. *     specified by the "symFlag" argument:
  720. * LOAD_ALL_SYMBOLS = all defined symbols (LOCAL and GLOBAL) are added,
  721. * LOAD_GLOBAL_SYMBOLS = only external (GLOBAL) symbols are added,
  722. * LOAD_NO_SYMBOLS = no symbols are added;
  723. *
  724. *  2) Any undefined externals are looked up in the system symbol table to
  725. *     determine their values.  The values are entered into the specified
  726. *     'externals' array.  This array is indexed by the symbol number
  727. *     (position in the symbol table).
  728. *     Note that all symbol values, not just undefined externals, are entered
  729. *     into the 'externals' array.  The values are used to perform relocations.
  730. *
  731. *     Note that "common" symbols have type undefined external - the value
  732. *     field of the symbol will be non-zero for type common, indicating
  733. *     the size of the object.
  734. *
  735. * If an undefined external cannot be found in the system symbol table,
  736. * an error message is printed, but ERROR is not returned until the entire
  737. * symbol table has been read, which allows all undefined externals to be
  738. * looked up.
  739. *
  740. * RETURNS: OK or ERROR
  741. */
  742. LOCAL STATUS pecoffSymTab
  743.     (
  744.     int fd, /* file descriptor of module being loaded */
  745.     FILHDR * pHdr, /* pointer to file header */
  746.     SYMENT * externalSyms, /* pointer to symbols array */
  747.     char *** externals, /* pointer to pointer to array to fill in 
  748.    symbol absolute values */
  749.     int symFlag, /* symbols to be added to table 
  750.  *   ([NO|GLOBAL|ALL]_SYMBOLS) */
  751.     SEG_INFO * pSeg, /* pointer to segment information */
  752.     char * symStrings, /* symbol string table */
  753.     SYMTAB_ID symTbl, /* symbol table to use */
  754.     char * pNextCommon, /* next common address in bss */
  755.     SCNHDR * pScnHdrArray, /* pointer to PECOFF section header array */
  756.     char ** pScnAddr, /* pointer to section loaded address array */
  757.     BOOL fullyLinked, /* TRUE if module already absolutely located */
  758.     UINT16 group, /* module's group */
  759.     int imageBase /* base addr of the simulateur image in RAM */
  760.     )
  761.     {
  762.     int status  = OK; /* return status */
  763.     char * name; /* symbol name (plus EOS) */
  764.     SYMENT * symbol; /* symbol struct */
  765.     SYM_TYPE vxSymType; /* vxWorks symbol type */
  766.     int symNum; /* symbol index */
  767.     char * adrs; /* table resident symbol address */
  768.     char * bias; /* section relative address */
  769.     ULONG bssAlignment; /* alignment value of common type */
  770.     long scnFlags; /* flags from section header */
  771.     int auxEnts = 0; /* auxiliary symbol entries to skip */
  772.     SCNHDR * pScnHdr = NULL; /* pointer to a PECOFF section header */
  773.     char * scnAddr = NULL; /* section loaded address */
  774.     char nameTemp[SYMNMLEN+1]; /* temporary for symbol name string */
  775.     /*  Loop thru all symbol table entries in object file */
  776.     for (symNum = 0, symbol = externalSyms; symNum < pHdr->f_nsyms; 
  777.  symbol++, symNum++)
  778. {
  779.         if (auxEnts)                    /* if this is an auxiliary entry */
  780.             {
  781.             auxEnts--;
  782.             continue;                   /* skip it */
  783.             }
  784.         auxEnts = symbol->n_numaux;      /* # of aux entries for this symbol */
  785. /* Get rid of debug symbols */
  786.         if (symbol->n_scnum == N_DEBUG)
  787.             continue;
  788. /* Setup pointer to symbol name string */
  789.         if (symbol->n_zeroes)            /* if name is in symbol entry */
  790.             {
  791.             name = symbol->n_name;
  792.             if (*(name + SYMNMLEN -1) != '')
  793.                 {
  794.                 /*
  795.  * If the symbol name array is full,
  796.                  * the string is not terminated by a null.
  797.                  * So, move the string to a temporary array,
  798.                  * where it can be null terminated.
  799.                  */
  800.                 bcopy (name, nameTemp, SYMNMLEN);
  801.                 nameTemp[SYMNMLEN] = '';
  802.                 name = nameTemp;
  803.                 }
  804.             }
  805.         else
  806.             name = symStrings + symbol->n_offset;
  807.         if (! PECOFF_UNDF(symbol) && ! PECOFF_COMM(symbol))
  808.             {
  809.             /*
  810.      * The symbol is a defined, local or global (though not common).
  811.              *
  812.              * Determine symbol's section and address bias
  813.              */
  814.             if (symbol->n_scnum > 0)
  815.                 {
  816.                 pScnHdr = pScnHdrArray + (symbol->n_scnum - 1);
  817. scnAddr = pScnAddr[symbol->n_scnum - 1];
  818.                 scnFlags = pScnHdr->s_flags;
  819.                 }
  820.             else
  821.                 scnFlags = 0;       /* section has no text, data or bss */
  822.             if (symbol->n_scnum == N_ABS) /* special check for absolute syms */
  823.                 {
  824. /*
  825.  * No bias is applied to absolute symbols: they have to be
  826.  * valid for the actual location in Window's memory space
  827.  * where the simulator is installed.
  828.  *
  829.  * PLEASE, DO NOT CHANGE THIS AS THIS IS A CONSCIOUS AND
  830.  * DOCUMENTED DECISION.
  831.  */
  832.                 bias = 0;
  833.                 vxSymType = VX_ABS;
  834.                 }
  835.             else if (scnFlags & STYP_TEXT)
  836.                 {
  837.                 bias = (char *) scnAddr;
  838.                 vxSymType = VX_TEXT;
  839. }
  840.             else if (scnFlags & STYP_DATA)
  841.                 {
  842.                 bias = (char *) scnAddr;
  843.                 vxSymType = VX_DATA;
  844. }
  845.             else if (scnFlags & STYP_BSS)
  846.                 {
  847.                 bias = (char *) scnAddr;
  848.                 vxSymType = VX_BSS;
  849. }
  850.             else if (scnFlags & STYP_DRECTVE)
  851.                 {
  852. /* Ignore this section */
  853.                 continue;
  854.                 }
  855.             else
  856.                 {
  857. /*
  858.  * Lets not print error messages for debug-related symbols
  859.  * that are not flagged as N_DEBUG...
  860.  */
  861. if (!strcmp (name, ".stab") || !strcmp (name, ".stabstr"))
  862.     continue;
  863.                 printErr (cantConvSymbolType, name, errnoGet());
  864.                 continue;
  865.                 }
  866.     /*
  867.      * Since, in the VxWorks simulator's image all the symbols' values
  868.      * are offsets from zero a bias has to be introduced to get the
  869.      * real (post-installation) addresses of these symbols in
  870.      * Windows' memory space. The bias computation is however
  871.      * different from the one for the regular object modules and must
  872.      * overwrite whatever has been computed just above: the bias is
  873.      * the base address of the simulator in Windows' memory space
  874.      * plus the offset to the section which holds the symbol.
  875.      *
  876.      * Note: the section header's s_vaddr field holds this offset
  877.      *       _not_ a real virtual address...
  878.      */
  879.             if (fullyLinked)
  880. bias = (char *)(pScnHdr->s_vaddr + imageBase);
  881.             /*  Determine if symbol should be put into symbol table */
  882.             if (((symFlag & LOAD_LOCAL_SYMBOLS) && !PECOFF_EXT(symbol))
  883.                 || ((symFlag & LOAD_GLOBAL_SYMBOLS) && PECOFF_EXT(symbol)))
  884.                 {
  885.                 if (PECOFF_EXT(symbol))
  886.                     vxSymType |= VX_EXT;
  887.                 /*  Add symbol to symbol table but cut out Local tags */
  888.                 if (name[0] != '$')
  889.          if (symSAdd (symTbl, name, symbol->U_SYM_VALUE + bias,
  890.      vxSymType, group) != OK)
  891.         printErr (cantAddSymErrMsg, name, errnoGet());
  892.                 }
  893.             /* Add symbol address to externals table.
  894.              * For PECOFF, we add all symbol addresses into the externals
  895.              * table, not only those symbols saved in the vxWorks symbol
  896.              * table.
  897.              */
  898.             (*externals) [symNum] = symbol->U_SYM_VALUE + bias;
  899.     }
  900. else
  901.     {
  902.     /* Undefined external symbol or "common" symbol
  903.              *
  904.      *   A common symbol type is denoted by undefined external
  905.              *   with its value set to non-zero.
  906.      */
  907.     /* if symbol is a common, then allocate space and add to
  908.      * symbol table as BSS
  909.      */
  910.     /* common symbol - create new symbol */
  911.             if (PECOFF_COMM(symbol))
  912. {
  913. if (symFlag == LOAD_NO_SYMBOLS)
  914.     ;
  915. else
  916.     {
  917.     /* 
  918.      *  common symbol - create new symbol 
  919.      *
  920.      *  Common symbols are now tacked to the end of the bss
  921.      *  section.  This is done to accomodate systems that have
  922.      *  multiple boards sharing memory with common symbols
  923.      *  over the system bus.  
  924.      *  This portion of code checks for a matching
  925.                      *  common symbol. If a matching common symbol is not
  926.                      *  found the symbol value is read
  927.      *  (which contains the symbol size) and the symbol is
  928.                      *  placed in the bss section.  The function dataAlign uses
  929.      *  the next possible address for a common symbol to
  930.      *  determine the proper alignment.
  931.      */
  932.       
  933.                     if (loadPecoffCommonManage (name, symTbl, (void *) &adrs,
  934.                         &vxSymType, symFlag) != OK)
  935.                 {
  936.                 adrs = pNextCommon;
  937.                 bssAlignment = dataAlign (symbol->U_SYM_VALUE,
  938.                                                   (ULONG)adrs);
  939.                 adrs += bssAlignment;
  940.                 pNextCommon += (symbol->U_SYM_VALUE + bssAlignment);
  941.     
  942.                 if (symSAdd (symTbl, name, adrs, (VX_BSS | VX_EXT),
  943.                     group) != OK)
  944.             printErr (cantAddSymErrMsg, name, errnoGet());
  945.         }
  946.     }
  947. }
  948.     /* look up undefined external symbol in symbol table */
  949.     else if (symFindByNameAndType (symTbl, name, &adrs, &vxSymType,
  950.    VX_EXT, VX_EXT) != OK)
  951.                 {
  952.                 /* Symbol not found in symbol table */
  953.                 printErr ("undefined symbol: %sn", name);
  954.                 adrs = NULL;
  955.                 status = ERROR;
  956.                 }
  957.     /* Add symbol address to externals table */
  958.     (*externals) [symNum] = adrs;
  959.     }
  960. }
  961.     
  962.     return status;
  963.     }
  964. /*******************************************************************************
  965. *
  966. * pecoffRelSegmentI386 - perform relocation for the I386 family
  967. *
  968. * This routine reads the specified relocation command segment and performs
  969. * all the relocation specified therein.
  970. * Absuolute symbol addresses are looked up in the 'externals' table.
  971. *
  972. * This function handles the following types of relocation commands for the
  973. * I386 family of processor:
  974. *  IMAGE_REL_I386_DIR32  - direct 32 bit relocation
  975. *  IMAGE_REL_I386_REL32  - relative 32b bit relocation
  976. *
  977. * RETURNS: OK or ERROR
  978. */
  979. LOCAL STATUS pecoffRelSegmentI386
  980.     (
  981.     RELOC * pRelCmds, /* list of relocation commands */
  982.     SCNHDR * pScnHdrArray,  /* array of section headers */
  983.     char ** pExternals, /* array of absolute symbols values */
  984.     SYMENT * pExtSyms, /* pointer to object file symbols */ 
  985.     SEG_INFO *  pSeg, /* section addresses and sizes */
  986.     int         section         /* section number -1 for relocation */
  987.     )
  988.     {
  989.     long *      pAdrs = NULL;   /* relocation address */
  990.     int         nCmds;          /* # reloc commands for seg */
  991.     RELOC       relocCmd;       /* relocation structure */
  992.     SCNHDR *    pScnHdr;        /* section header for relocation */
  993.     STATUS      status = OK;
  994.     pScnHdr = pScnHdrArray + section;
  995.     for (nCmds = pScnHdr->s_nreloc; nCmds > 0; nCmds--)
  996.         {
  997.         /* read relocation command */
  998.         relocCmd = *pRelCmds++;
  999. /*
  1000.          * Calculate actual address in memory that needs relocation.
  1001.  * XXX PAD - we now apply the fix for SPR 70767 
  1002.          */
  1003. if (pScnHdr->s_flags & STYP_TEXT)
  1004.     {
  1005.     if (!(pScnHdr->s_flags & STYP_LIT))
  1006. {
  1007. pAdrs = (long *)((long) pSeg->addrText + relocCmd.r_vaddr);
  1008. }
  1009.     else
  1010. {
  1011. printf ("STYP_LIT type sections are unsupported.n");
  1012. return ERROR;
  1013. }
  1014.     }
  1015. else
  1016.     /*
  1017.      * The computation of the address of relocable data symbol 
  1018.              * should take into account the offset from the beginning of the
  1019.              * file that the compiler toolchain may require to account for
  1020.              * in some cases. The code was fixed to substract this offset
  1021.              * for data symbol, SPR 73145. 
  1022.      */
  1023.     {
  1024.     pAdrs = (long *)((long) pSeg->addrData +
  1025.              (relocCmd.r_vaddr - pScnHdr->s_vaddr));
  1026.     }
  1027. /* do relocations */
  1028.         switch (relocCmd.r_type)
  1029.             {
  1030.     case IMAGE_REL_I386_DIR32:
  1031. /*
  1032.  * This relocation is preformed by adding the absolute address
  1033.  * of the symbol to the relocation value in the code.
  1034.  */
  1035. *pAdrs += (INT32) pExternals [relocCmd.r_symndx];
  1036.    break;
  1037.     case IMAGE_REL_I386_REL32:
  1038. /*
  1039.  * Call near, displacement relative to the next instruction.
  1040.  * First, find the next instruction addr, then subtract it from
  1041.  * the addr of the found symbol to obtain the relocation addr.
  1042.  */
  1043.                 *pAdrs = (UINT32)pExternals[relocCmd.r_symndx] -
  1044.          ((UINT32)pAdrs + 4);
  1045.                 break;
  1046.     default:
  1047. printf("Unknown Relocation Errorn");
  1048. errnoSet (S_loadLib_UNRECOGNIZED_RELOCENTRY);
  1049. status = ERROR;
  1050. break;
  1051.             }
  1052.         }
  1053.     return status;
  1054.     }
  1055. /*******************************************************************************
  1056. *
  1057. * pecoffHdrRead - read in PECOFF header and swap if necessary
  1058. * Note:  To maintain code portability, we can not just read sizeof(FILHDR) 
  1059. * bytes.  Compilers pad structures differently,
  1060. * resulting in different structure sizes.
  1061. * So, we read the structure in an element at a time, using the size
  1062. * of each element.
  1063. */
  1064. LOCAL STATUS pecoffHdrRead
  1065.     (
  1066.     int fd,
  1067.     FILHDR *pHdr,
  1068.     BOOL *pSwap
  1069.     )
  1070.     {
  1071.     int status;
  1072.     int i;
  1073.     struct dosheader dhead;
  1074.     *pSwap = 0;
  1075.     ioctl(fd, FIOSEEK, 0);
  1076.     if (fioRead (fd, (char *) &(pHdr->f_magic), sizeof (pHdr->f_magic))
  1077. != sizeof (pHdr->f_magic))
  1078. {
  1079. errnoSet (S_loadLib_FILE_READ_ERROR);
  1080. return ERROR;
  1081. }
  1082.     switch (pHdr->f_magic)
  1083. {
  1084. case (SWAB_SHORT(IMAGE_DOS_SIGNATURE)):
  1085.             *pSwap = TRUE;
  1086. case (IMAGE_DOS_SIGNATURE):
  1087.     /* Remove DOS EXE header */
  1088.             fioRead(fd,(char *)&dhead + 2,sizeof(dhead)-2);
  1089.     lseek (fd, dhead.e_lfanew, SEEK_SET);
  1090.             /* Check for NT SIGNATURE */
  1091.             fioRead (fd, (char *)&i, 4);
  1092.             if ( i != IMAGE_NT_SIGNATURE )
  1093.                 {
  1094.                 printf("Bad Image Signature %x %xn",i,IMAGE_NT_SIGNATURE);
  1095. errnoSet (S_loadLib_HDR_READ);
  1096.                 return ERROR;
  1097.                 }
  1098.             fioRead (fd, (char *)&pHdr->f_magic, 2);
  1099.     break;
  1100. case (SWAB_SHORT(IMAGE_FILE_MACHINE_I386)):
  1101.             *pSwap = TRUE;
  1102.     break;
  1103.         case (IMAGE_FILE_MACHINE_I386):
  1104.     *pSwap = FALSE;
  1105.     break;
  1106.     
  1107. default:
  1108. #ifndef MULTIPLE_LOADERS
  1109.     printErr (fileTypeUnsupported, pHdr->f_magic);
  1110. #endif
  1111.     errnoSet (S_loadLib_FILE_ENDIAN_ERROR);
  1112.     return ERROR;
  1113.     break;
  1114. }
  1115.     status = fileRead (fd, &pHdr->f_nscns, sizeof(pHdr->f_nscns), *pSwap);
  1116.     status |= fileRead (fd, &pHdr->f_timdat, sizeof(pHdr->f_timdat), *pSwap);
  1117.     status |= fileRead (fd, &pHdr->f_symptr, sizeof(pHdr->f_symptr), *pSwap);
  1118.     status |= fileRead (fd, &pHdr->f_nsyms, sizeof(pHdr->f_nsyms), *pSwap);
  1119.     status |= fileRead (fd, &pHdr->f_opthdr, sizeof(pHdr->f_opthdr), *pSwap);
  1120.     status |= fileRead (fd, &pHdr->f_flags, sizeof(pHdr->f_flags), *pSwap);
  1121.     max_scns = pHdr->f_nscns;
  1122.     return status;
  1123.     }
  1124. /*******************************************************************************
  1125. *
  1126. * pecoffOpthdrRead - read in PECOFF optional header and swap if necessary
  1127. */
  1128. LOCAL STATUS pecoffOpthdrRead
  1129.     (
  1130.     int      fd,
  1131.     PEOPTION  *pOptHdr,
  1132.     BOOL     swapTables
  1133.     )
  1134.     {
  1135.     int status;
  1136.     status = fileRead(fd, &pOptHdr->magic, sizeof(pOptHdr->magic),
  1137.                             swapTables);
  1138.     status |= fileRead(fd, &pOptHdr->vstamp, sizeof(pOptHdr->vstamp),
  1139.                             swapTables);
  1140.     status |= fileRead(fd, &pOptHdr->tsize, sizeof(pOptHdr->tsize),
  1141.                             swapTables);
  1142.     status |= fileRead(fd, &pOptHdr->dsize, sizeof(pOptHdr->dsize),
  1143.                             swapTables);
  1144.     status |= fileRead(fd, &pOptHdr->bsize, sizeof(pOptHdr->bsize),
  1145.                             swapTables);
  1146.     status |= fileRead(fd, &pOptHdr->entry, sizeof(pOptHdr->entry),
  1147.                             swapTables);
  1148.     status |= fileRead(fd, &pOptHdr->text_start, sizeof(pOptHdr->text_start),
  1149.                             swapTables);
  1150.     status |= fileRead(fd, &pOptHdr->data_start, sizeof(pOptHdr->data_start),
  1151.                             swapTables);
  1152.     status |= fileRead(fd, &pOptHdr->image_base, sizeof(pOptHdr->image_base),
  1153.                             swapTables);
  1154.     status |= fileRead(fd, &pOptHdr->section_align, sizeof(pOptHdr->section_align),
  1155.                             swapTables);
  1156.     status |= fileRead(fd, &pOptHdr->file_align, sizeof(pOptHdr->file_align),
  1157.                             swapTables);
  1158.     return (status);
  1159.     }
  1160. /*******************************************************************************
  1161. *
  1162. * pecoffSecHdrRead - read in PECOFF section header and swap if necessary
  1163. */
  1164. LOCAL STATUS pecoffSecHdrRead
  1165.     (
  1166.     int    fd,
  1167.     SCNHDR *pScnHdr,
  1168.     FILHDR *pHdr,
  1169.     BOOL   swapTables
  1170.     )
  1171.     {
  1172.     int ix;
  1173.     int status = 0;
  1174.     /* check for correct section count */
  1175.     if (pHdr->f_nscns > MAX_SCNS)
  1176. {
  1177. return (ERROR);
  1178. }
  1179.     for (ix = 0; ix < pHdr->f_nscns; ix++)
  1180. {
  1181.         status = fileRead(fd, pScnHdr->s_name, sizeof(pScnHdr->s_name),
  1182.                           FALSE);
  1183.         status |= fileRead(fd, &pScnHdr->s_paddr, sizeof(pScnHdr->s_paddr),
  1184.                            swapTables);
  1185.         status |= fileRead(fd, &pScnHdr->s_vaddr, sizeof(pScnHdr->s_vaddr),
  1186.                             swapTables);
  1187.         status |= fileRead(fd, &pScnHdr->s_size, sizeof(pScnHdr->s_size),
  1188.                             swapTables);
  1189.         status |= fileRead(fd, &pScnHdr->s_scnptr, sizeof(pScnHdr->s_scnptr),
  1190.                             swapTables);
  1191.         status |= fileRead(fd, &pScnHdr->s_relptr, sizeof(pScnHdr->s_relptr),
  1192.                             swapTables);
  1193.         status |= fileRead(fd, &pScnHdr->s_lnnoptr, sizeof(pScnHdr->s_lnnoptr),
  1194.                             swapTables);
  1195.         status |= fileRead(fd, &pScnHdr->s_nreloc, sizeof(pScnHdr->s_nreloc),
  1196.                             swapTables);
  1197.         status |= fileRead(fd, &pScnHdr->s_nlnno, sizeof(pScnHdr->s_nlnno),
  1198.                             swapTables);
  1199.         status |= fileRead(fd, &pScnHdr->s_flags, sizeof(pScnHdr->s_flags),
  1200.                             swapTables);
  1201. /*
  1202.  * In order to comply with an obscure requirement from Microsoft, the
  1203.  * GNU toolchain puts the size of the bss section in the section
  1204.  * header's physical address field. This piece of code addresses the
  1205.  * SPR 70767 by reseting the s_size field as appropriate for the rest
  1206.  * of the loader code.
  1207.  */
  1208. if (pScnHdr->s_flags & STYP_BSS)
  1209.     {
  1210.     if ((pScnHdr->s_size == 0) && (pScnHdr->s_paddr != 0))
  1211. pScnHdr->s_size = pScnHdr->s_paddr;
  1212.     }
  1213. pScnHdr++;
  1214. }
  1215.     return (status);
  1216.     }
  1217. /*******************************************************************************
  1218. *
  1219. * pecoffReadRelocInfo - read in PECOFF relocation info and swap if necessary
  1220. * Assumptions:  The file pointer is positioned at the start of the relocation
  1221. * records.
  1222. *
  1223. * The relocation records are ordered by section.
  1224. */
  1225. LOCAL STATUS pecoffReadRelocInfo
  1226.     (
  1227.     int     fd,
  1228.     SCNHDR  *pScnHdr,
  1229.     RELOC   **pRelsPtr,
  1230.     BOOL    swapTables
  1231.     )
  1232.     {
  1233.     int ix;
  1234.     int iy;
  1235.     int relocSize;
  1236.     int status = OK;
  1237.     RELOC *pRels;                       /* pointer to single reloc entry */
  1238.     for (ix = 0; ix < max_scns; ix++)
  1239. {
  1240.         if (pScnHdr->s_nreloc > 0)
  1241.     {
  1242.     relocSize = (int) pScnHdr->s_nreloc * RELSZ;
  1243.     if ((*pRelsPtr = (RELOC *)malloc (relocSize)) == NULL)
  1244. {
  1245. return (ERROR);
  1246. }
  1247. if (lseek (fd, pScnHdr->s_relptr, SEEK_SET) == ERROR)
  1248.     {
  1249.     return (ERROR);
  1250.     }
  1251.             for (iy = 0, pRels = *pRelsPtr;
  1252.                  (iy < (int) pScnHdr->s_nreloc) && (status == OK);
  1253.                  iy++, pRels++)
  1254.                 {
  1255.                 status = fileRead(fd, &pRels->r_vaddr,
  1256.                                    sizeof(pRels->r_vaddr), swapTables);
  1257.                 status |= fileRead(fd, &pRels->r_symndx,
  1258.                                    sizeof(pRels->r_symndx), swapTables);
  1259.                 status |= fileRead(fd, &pRels->r_type,
  1260.                                    sizeof(pRels->r_type), swapTables);
  1261.                 }
  1262.             if (status != OK)
  1263.                 return(status);
  1264.     }
  1265. pScnHdr++;
  1266. pRelsPtr++;
  1267.         }
  1268.     return (OK);
  1269.     }
  1270. /*******************************************************************************
  1271. *
  1272. * pecoffReadSym - read one PECOFF symbol entry
  1273. */
  1274. LOCAL STATUS pecoffReadSym
  1275.     (
  1276.     int     fd,
  1277.     SYMENT *pSym,                       /* where to read symbol entry */
  1278.     BOOL    swapTables
  1279.     )
  1280.     {
  1281.     int status;
  1282.     status = fioRead (fd, pSym->n_name, sizeof(pSym->n_name));
  1283.     if(status != sizeof(pSym->n_name))
  1284.         {
  1285.         printf(" Status %x %x : %x %x %x %xn",status,sizeof(pSym->n_name),
  1286.             pSym->n_name[0], 
  1287.             pSym->n_name[1], 
  1288.             pSym->n_name[2], 
  1289.             pSym->n_name[3]);
  1290.     status = fioRead (fd, pSym->n_name, sizeof(pSym->n_name));
  1291.         printf(" Status  #2 %x : %x %x %x %xn",status,
  1292.             pSym->n_name[0], 
  1293.             pSym->n_name[1], 
  1294.             pSym->n_name[2], 
  1295.             pSym->n_name[3]);
  1296. status = ERROR;
  1297.         }
  1298.     else
  1299.         status = OK;
  1300.     if (swapTables && (status == OK))
  1301.         {
  1302.         /*  The n_name field is part of a union in the syment struct.
  1303.          *  If the union uses n_name (array of char), then no
  1304.          *  swabbing in required.
  1305.          *  If the union uses n_offset (into string table), then
  1306.          *  the n_offset must be swabbed.
  1307.          */
  1308.         if (pSym->n_zeroes == 0)
  1309.             {
  1310.             swabData(&pSym->n_offset, sizeof(pSym->n_offset));
  1311.             }
  1312.         }
  1313.      status |= fileRead (fd, &pSym->n_value, sizeof(pSym->n_value),
  1314.                         swapTables);
  1315.     status |= fileRead (fd, &pSym->n_scnum, sizeof(pSym->n_scnum),
  1316.                         swapTables);
  1317.     status |= fileRead (fd, &pSym->n_type, sizeof(pSym->n_type),
  1318.                         swapTables);
  1319.     status |= fileRead (fd, &pSym->n_sclass, sizeof(pSym->n_sclass),
  1320.                         swapTables);
  1321.     status |= fileRead (fd, &pSym->n_numaux, sizeof(pSym->n_numaux),
  1322.                         swapTables);
  1323.     return(status);
  1324.     }
  1325. /*******************************************************************************
  1326. *
  1327. * pecoffReadExtSyms - read PECOFF symbols
  1328. *  For low memory systems, we can't afford to keep the entire
  1329. *  symbol table in memory at once.
  1330. *  For each symbol entry, the fields required for relocation
  1331. *  are saved in the externalSyms array.
  1332. */
  1333. LOCAL STATUS pecoffReadExtSyms
  1334.     (
  1335.     int fd,
  1336.     SYMENT **pSymbols,       /* pointer to array of symbol entries */
  1337.     char ***pSymAddr,          /* pointer to array of addresses */
  1338.     FILHDR *pHdr,
  1339.     BOOL    swapTables
  1340.     )
  1341.     {
  1342.     int status;
  1343.     int ix;
  1344.     SYMENT *pSym;                     /* pointer to symbol entry */
  1345.     if (pHdr->f_nsyms)
  1346.         {
  1347.         /*  malloc space for array of absolute addresses
  1348.          */
  1349.         if ((*pSymAddr = malloc((UINT)(pHdr->f_nsyms) * sizeof(char *)))
  1350.             == NULL)
  1351.     {
  1352.     printErr (extMemErrMsg, (UINT)(pHdr->f_nsyms) * sizeof (char *));
  1353.     return (ERROR);
  1354.     }
  1355.         /*  malloc space for symbols
  1356.          */
  1357.         if ((*pSymbols = malloc((UINT)(pHdr->f_nsyms) * SYMESZ))
  1358.             == NULL)
  1359.     {
  1360.     return (ERROR);
  1361.     }
  1362. if (lseek (fd, pHdr->f_symptr, SEEK_SET) == ERROR)
  1363.     {
  1364.     return (ERROR);
  1365.     }
  1366.         for (ix = 0, pSym = *pSymbols; ix < pHdr->f_nsyms; ix++, pSym++)
  1367.             {
  1368.             if ((status = pecoffReadSym(fd, pSym, swapTables) != OK))
  1369. return (status);
  1370.             }
  1371.       }
  1372.     return (OK);
  1373.     }
  1374. /*******************************************************************************
  1375. *
  1376. * pecoffReadExtStrings - read in PECOFF external strings
  1377. * Assumptions:  The file pointer is positioned at the start of the
  1378. * string table.
  1379. */
  1380. #define STR_BYTES_SIZE 4                /* size of string table length field */
  1381. LOCAL STATUS pecoffReadExtStrings
  1382.     (
  1383.     int fd,
  1384.     char **pStrBuf,
  1385.     BOOL    swapTables
  1386.     )
  1387.     {
  1388.     unsigned long strBytes;
  1389.     int status;
  1390.     /* Read length of string table
  1391.      */
  1392.     if ((status = fileRead (fd, &strBytes, STR_BYTES_SIZE, swapTables))
  1393.         != OK)
  1394.         {
  1395.         return (status);
  1396.         }
  1397.     if (strBytes > STR_BYTES_SIZE)
  1398.         {
  1399.         if ((*pStrBuf = malloc(strBytes)) == NULL)
  1400.     {
  1401.             printErr (stringMemErrMsg, strBytes);
  1402.     return (ERROR);
  1403.     }
  1404.         bcopy((char *) &strBytes, (char *) *pStrBuf, STR_BYTES_SIZE);
  1405.         strBytes -= STR_BYTES_SIZE;     /* # bytes left to read  */
  1406.     if (fioRead (fd, *pStrBuf + STR_BYTES_SIZE, strBytes) 
  1407. != strBytes)
  1408.     {
  1409.     return (ERROR);
  1410.     }
  1411.         }
  1412.     return (OK);
  1413.     }
  1414. #if FALSE /* XXX PAD - this is no longer used apparently */
  1415. /*******************************************************************************
  1416. *
  1417. * softSeek - seek forward into a file
  1418. *
  1419. * This procedure seeks forward into a file without actually using seek
  1420. * calls.  It is usefull since seek does not work on all devices.
  1421. *
  1422. * RETURNS:
  1423. * OK, or
  1424. * ERROR if forward seek could not be accomplished
  1425. *
  1426. */
  1427. #define SEEKBUF 1024
  1428. LOCAL STATUS softSeek
  1429.     (
  1430.     int fd, /* fd to seek with */
  1431.     int startOfFileOffset /* byte index to seek to */
  1432.     )
  1433.     {
  1434.     int position; /* present file position */
  1435.     int bytesToRead; /* bytes needed to read */
  1436.     char tempBuffer[SEEKBUF]; /* temp buffer for bytes */
  1437.     position = ioctl (fd, FIOWHERE, startOfFileOffset);
  1438.     if (position > startOfFileOffset)
  1439. return(ERROR);
  1440.     /* calculate bytes to read */
  1441.     bytesToRead = startOfFileOffset - position;
  1442.     while (bytesToRead >= SEEKBUF)
  1443. {
  1444.         if (fioRead (fd, tempBuffer, SEEKBUF) != SEEKBUF)
  1445.     return (ERROR);
  1446. bytesToRead -= SEEKBUF;
  1447. }
  1448.     if (bytesToRead > 0)
  1449. {
  1450.         if (fioRead (fd, tempBuffer, bytesToRead) != bytesToRead)
  1451.     return (ERROR);
  1452. }
  1453. #ifdef NO_PECOFF_SOFT_SEEK
  1454.     if (ioctl (fd, FIOSEEK, startOfFileOffset) == ERROR)
  1455.         return (ERROR);
  1456. #endif
  1457.     return(OK);
  1458.     }
  1459. #endif /* FALSE */
  1460. /*******************************************************************************
  1461. *
  1462. * fileRead - loader file read function
  1463. */
  1464. LOCAL STATUS fileRead
  1465.     (
  1466.     int     fd,
  1467.     char    *pBuf,                      /* buffer to read data into */
  1468.     UINT    size,                       /* size of data field in bytes */
  1469.     BOOL    swap
  1470.     )
  1471.     {
  1472.     int     status = OK;
  1473.     if (fioRead (fd, pBuf, size) != size)
  1474.         {
  1475. errnoSet (S_loadLib_FILE_READ_ERROR);
  1476.         return(ERROR);
  1477.         }
  1478.     if (swap)
  1479.         {
  1480.         status = swabData(pBuf, size);
  1481.         }
  1482.     return(status);
  1483.     }
  1484. /*******************************************************************************
  1485. *
  1486. *  swabData - swap endianess of data field of any length
  1487. *
  1488. */
  1489. LOCAL STATUS swabData
  1490.     (
  1491.     char    *pBuf,                      /* buffer containing data */
  1492.     UINT    size                       /* size of data field in bytes */
  1493.     )
  1494.     {
  1495. #define TEMP_BUF_SIZE 256
  1496.     int     status = OK;
  1497.     char    tempBuf[TEMP_BUF_SIZE];
  1498.     switch(size)
  1499.         {
  1500.         case sizeof(char):
  1501.             break;                      /* ok as is */
  1502.         case sizeof(short):
  1503.             *(unsigned short *) pBuf = SWAB_SHORT(*(unsigned short *) pBuf);
  1504.             break;
  1505.         case sizeof(long):
  1506.             swabLong(pBuf, tempBuf);
  1507.             bcopy(tempBuf, pBuf, size);
  1508.             break;
  1509.         default:
  1510.             if (size <= TEMP_BUF_SIZE)
  1511.                 {
  1512.                 swab(pBuf, tempBuf, size);
  1513.                 bcopy(tempBuf, pBuf, size);
  1514.                 }
  1515.             else
  1516.                 status = ERROR;
  1517.             break;
  1518.         }
  1519.     return(status);
  1520.     }
  1521. /*******************************************************************************
  1522. *
  1523. *  swabLong - swap endianess of long word
  1524. *
  1525. */
  1526. LOCAL void swabLong
  1527.     (
  1528.     char input[],
  1529.     char output[]
  1530.     )
  1531.     {
  1532.     output[0] = input[3];
  1533.     output[1] = input[2];
  1534.     output[2] = input[1];
  1535.     output[3] = input[0];
  1536.     }
  1537. /*******************************************************************************
  1538. *
  1539. * pecoffTotalCommons - 
  1540. *  INTERNAL
  1541. *  All common external symbols are being tacked on to the end
  1542. *  of the BSS section.  This function determines the additional amount
  1543. *  of memory required for the common symbols.
  1544. *  
  1545. */
  1546. LOCAL ULONG pecoffTotalCommons
  1547.     (
  1548.     SYMENT *pSym, /* pointer to external symbols */
  1549.     int nEnts, /* # of entries in symbol table */
  1550.     ULONG startAddr /* address to start from */
  1551.     )
  1552.     {
  1553.     int ix;
  1554.     ULONG alignBss; /* next boundry for common entry */
  1555.     int nbytes; /* bytes for alignment + data */
  1556.     int totalBytes = 0; /* total additional count for bss */
  1557.     int auxEnts = 0;                    /* auxiliary symbol entries to skip */
  1558.     /* calculate room for external commons in bss */
  1559.     alignBss = startAddr;
  1560.     for (ix = 0; ix < nEnts; ix++, pSym++)
  1561. {
  1562.         if (auxEnts)                    /* if this is an auxiliary entry */
  1563.             {
  1564.             auxEnts--;
  1565.             continue;                   /* skip it */
  1566.             }
  1567.         auxEnts = pSym->n_numaux;       /* # of aux entries for this symbol */
  1568. if (PECOFF_COMM(pSym))
  1569.     {
  1570.             nbytes = dataAlign(pSym->U_SYM_VALUE, alignBss)
  1571.                     + pSym->U_SYM_VALUE;
  1572.             totalBytes += nbytes;
  1573.             alignBss += nbytes;
  1574.             }
  1575. }
  1576.     return(totalBytes);
  1577.     }
  1578. /*******************************************************************************
  1579. *
  1580. *  dataAlign - determine address alignment for a data operand in memory
  1581. *  The address of a data operand must be correctly aligned for data access.
  1582. *  This is architecture dependent. 
  1583. *  Generally, data operands are aligned on 'natural' boundaries as follows:
  1584. *          bytes on byte boundaries (they already are)
  1585. *          half-word operands on half-word boundaries
  1586. *          word operands on word boundaries
  1587. *          double-word operands on double-word boundaries
  1588. *
  1589. *  However, if a structure of size = 7 had to be aligned, it would need
  1590. *  to be aligned on a boundary that is a multiple of 4 bytes.
  1591. *
  1592. *  RETURNS:
  1593. * nbytes - number of bytes to be added to the address to obtain the
  1594. *                 correct alignment for the data
  1595. */
  1596. LOCAL ULONG dataAlign
  1597.     (
  1598.     ULONG size,                         /* size of data to be aligned */
  1599.     ULONG addr                         /* next possible address for data */
  1600.     )
  1601.     {
  1602.     ULONG nbytes;                 /* # bytes for alignment */
  1603.     int align;                        /* address should be multiple of align */
  1604.     if (size <= 1)
  1605.         align = 1;
  1606.     else if (size < 4)
  1607.         align = 2;
  1608.     else if (size < 8)
  1609.         align = 4;
  1610.     else if (size < 16)
  1611.         align = 8;
  1612.     else
  1613.         align = MAX_ALIGNMENT;          /* max required alignment */
  1614.     nbytes = addr % align;
  1615.     if (nbytes != 0)                    /* if not on correct boundary */
  1616.         nbytes = align - nbytes;
  1617.     return(nbytes);
  1618.     }
  1619. /*******************************************************************************
  1620. *
  1621. * bootPecoffModule - load an object module into memory
  1622. *
  1623. * This routine loads an object module in PECOFF format from the specified
  1624. * file, and places the code, data, and BSS at the locations specified within
  1625. * the file.  The entry point of the module is returned in <pEntry>.  This 
  1626. * routine is generally used for bootstrap loading.
  1627. *
  1628. * RETURNS:
  1629. * OK, or
  1630. * ERROR if the routine cannot read the file
  1631. *
  1632. * SEE ALSO: loadModuleAt()
  1633. */
  1634. STATUS bootPecoffModule
  1635.     (
  1636.     int fd, /* fd from which to read load module */
  1637.     FUNCPTR *pEntry /* entry point of module */
  1638.     )
  1639.     {
  1640.     FILHDR hdr; /* module's PECOFF header */
  1641.     PEOPTION optHdr;              /* module's PECOFF optional header */
  1642.     int nBytes;
  1643.     char tempBuf[MAX_SCNS * SCNHSZ];
  1644.     int tablesAreLE;
  1645.     /* read object module header */
  1646.     if (pecoffHdrRead (fd, &hdr, &tablesAreLE) != OK)
  1647. return (ERROR);
  1648.     /*  read in optional header */
  1649.     if (pecoffOpthdrRead (fd, &optHdr, tablesAreLE) != OK)
  1650. return (ERROR);
  1651.     /*  Read until start of text
  1652.      *
  1653.      *  Section headers aren't needed, but this is the easiest way to
  1654.      *  read passed them.
  1655.      */
  1656.     if (pecoffSecHdrRead (fd, (SCNHDR *)tempBuf, &hdr, tablesAreLE) != OK)
  1657. {
  1658. return(ERROR);
  1659. }
  1660.     printf ("%d", (int)optHdr.tsize);
  1661.     nBytes = fioRead (fd, (char *) optHdr.text_start, (int) optHdr.tsize);
  1662.     if (nBytes < optHdr.tsize)
  1663.         return (ERROR);
  1664.     printf (" + %d", (int)optHdr.dsize);
  1665.     nBytes = fioRead (fd, (char *) optHdr.data_start, (int) optHdr.dsize);
  1666.     if (nBytes < optHdr.dsize)
  1667.         return (ERROR);
  1668.     printf (" + %dn", (int)optHdr.bsize);
  1669.     /*  bss is zeroed by vxWorks startup code. 
  1670.      */
  1671.     *pEntry = (FUNCPTR) optHdr.entry;
  1672.     return (OK);
  1673.     }
  1674. /******************************************************************************
  1675. *
  1676. * bootPecoffInit - Initialize the system for pecoff load modules
  1677. *
  1678. * This routine initialized VxWorks to use the PECOFF format for
  1679. * boot loading modules.
  1680. *
  1681. * RETURNS:
  1682. * OK, or
  1683. * ERROR if XXX
  1684. *
  1685. * SEE ALSO: loadModuleAt()
  1686. */
  1687. STATUS bootPecoffInit
  1688.     (
  1689.     )
  1690.     {
  1691.     /* XXX check for installed ? */
  1692.     bootLoadRoutine = bootPecoffModule;
  1693.     return (OK);
  1694.     }
  1695. #endif /* CPU==SIMNT */