loadCoffLib.c
上传用户:nvosite88
上传日期:2007-01-17
资源大小:4983k
文件大小:89k
源码类别:

VxWorks

开发平台:

C/C++

  1. /* loadCoffLib.c - UNIX coff object module loader */
  2. /* Copyright 1984-1998 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 02o,22may01,h_k  fixed R_RELTHUMB23 for big-endian
  8. 02n,08feb99,pcn  Added pai changes: fix MAX_SYS_SYM_LEN (SPR #9028) and added
  9.                  functionality to boot an image with multiple text and / or
  10.                  multiple data sections (SPR #22452).
  11. 02m,30nov98,dbt  no longer clear seg.flags<xxx> after loadSegmentAllocate()
  12.                  call. (SPR #23553).
  13. 02m,13nov98,cdp  added support for ARM generic Thumb library (ARM_THUMB);
  14.                  merged ARM big-endian support - check object file endianness.
  15. 02l,05oct98,pcn  Set to _ALLOC_ALIGN_SIZE the flags field in seg structure
  16.                  (SPR #21836).
  17. 02k,02sep98,cym  fix static constructor/multiple text segments (SPR #21809)
  18. 02h,10aug98,jgn  fix loadModuleAt problem with bss segment (SPR #21635)
  19. 02i,17jul98,pcn  Fixed SPR #21836: alignment mismatch between sections and
  20.                  target.
  21. 02h,19jun98,c_c  Ignore STYP_REG relocations.
  22. 02g,03mar98,cdp  make bootCoffModule skip bytes between scnhdrs and raw data
  23.  (fixes loading of ARM stripped kernels).
  24. 02f,07nov97,yp   made changes to work with tool-chain fix related to 02d.
  25. 02e,24oct97,cdp  add support for THUMB23D relocs and trap THUMB9 and THUMB12.
  26. 02d,16oct97,cdp  temporary fix to THUMB23 relocs while waiting tool-chain fix.
  27. 02c,13aug97,cdp  added Thumb (ARM7TDMI_T) support;
  28.  tighten up RELARM26 overflow test;
  29.  initialise 'bias' in coffSymTab to prevent warning.
  30. 02b,04mar97,pad  Prevented relocations associated with STYP_INFO, STYP_NOLOAD
  31.  and STYP_PAD section to be done. Now refuses STYP_REG
  32.  sections. Silently ignore sections with NOLOAD bit set and
  33.  symbols from such sections. coffSecHdrRead() now sets the
  34.  errno.
  35. 02a,04feb97,cdp  Fix ARM non-common relocs, 16-bit transfers, overflow tests.
  36. 01z,08jan97,cdp  added ARM support.
  37. 01y,31oct96,elp  Replaced symAdd() call by symSAdd() call (symtbls synchro).
  38. 01x,02jul96,dbt  removed all references to ANSI C library (SPR #4321).
  39.  Updated copyright.
  40. 01w,19jun95,jmb  fix memory leak -- BSS wasn't freed and
  41.  the open object file wasn't closed.
  42. 01v,06jan95,yp   we now recognize C_STAT T_NULL symbols for 29k
  43. 01u,10dec94,pad  now recompute bss sections base addresses for Am29K also and
  44.  store then in scnAddr array. 
  45. 01t,10dec94,kdl  Merge cleanup - restore fast_load handling (SPR 3852).
  46. 01s,03nov94,pad  Fixed bugs, fixed history, added comments, achieved
  47.  separation of i960 and Am29k architectures.
  48.  Multiple Text segments is not supported by Am29k architecture.
  49. 01r,09sep94,ism  integrated a fix from Japan to allow multiple Text segments
  50. 01q,14mar94,pme  fixed nested const/consth relocation carry propagation
  51.    +tpr  in coffRelSegmentAm29K() (SPR #3074).
  52.  Added comments about relocation.
  53.  Removed AM29030 tests around VM_STATE_SET().
  54. 01p,16dec93,tpr  fixed address computation bug. 
  55. 01o,29oct93,tpr  added carry out management into coffRelSegmentAm29K().
  56. 01n,09jul93,pme  added text protection for AM29030.
  57.  added Am29K family support.
  58.                  Need to be reworked one day to really support .lit sections.
  59. 01m,19apr93,wmd+ added flag to check to choose between faster load without
  60.     01nov94,kdl  bal optimizations, or normal load with bal optimizations.
  61. 01l,11mar93,wmd  changed coffSymTab() so that it returns ERROR for undefined
  62.  symbols correctly (SPR # 2056). Modified to use buffered
  63.  I/O to speedup loader. Moved call to symFindByValue() in
  64.  coffRelSegment() to after the check for BAL_ENTRY. Fixed
  65.  SPR # 2031 - use new style loader flags. Modified coffSymTab()
  66.  not to load common symbols if NO_SYMBOLS option is passed.
  67. 01k,11sep92,ajm  changed OFFSET_MASK to OFFSET24_MASK due to b.out redefines,
  68.  got rid of b.out.h reference, fixed warnings
  69. 01j,28aug92,wmd  changed to allow loader to handle absolute symbols
  70.  which allows two pass compilation to occur,
  71.  courtesy of F.Opila at Intel.
  72. 01i,31jul92,jmm  changed doc for return value of ldCoffModAtSym
  73. 01h,28jul92,jmm  removed ifdefs for I960, now compiles for all arch's.
  74.                  installed moduleLib and unloader support
  75. 01g,24jul92,jmm  changed SEG_COFF_INFO back to SEG_INFO
  76.                  forced symFlags to 1 for ldCoffModAtSym()
  77.  forced return value of for ldCoffModAtSym()
  78. 01f,24jul92,rrr  change SEG_INFO to SEG_COFF_INFO to avoid conflict
  79.                  also changed addSegNames to _addSegNames
  80. 01e,18jul92,smb  Changed errno.h to errnoLib.h.
  81. 01d,17jul92,rrr  ifdef the file to only compile on 960
  82. 01c,21may92,wmd  modified per Intel to support multiple loaders.
  83. 01b,26jan92,ajm  cleaned up from review
  84. 01a,21oct91,ajm  written: some culled from loadLib.c
  85. */
  86. /*
  87. DESCRIPTION
  88. This library provides an object module loading facility for loading
  89. COFF format object files.
  90. The object files are loaded into memory, relocated properly, their
  91. external references resolved, and their external definitions added to
  92. the system symbol table for use by other modules and from the shell.
  93. Modules may be loaded from any I/O stream.
  94. EXAMPLE
  95. .CS
  96.     fdX = open ("/devX/objFile", READ);
  97.     loadModule (fdX, ALL_SYMBOLS);
  98.     close (fdX);
  99. .CE
  100. This code fragment would load the COFF file "objFile" located on
  101. device "/devX/" into memory which would be allocated from the system
  102. memory pool.  All external and static definitions from the file would be
  103. added to the system symbol table.
  104. This could also have been accomplished from the shell, by typing:
  105. .CS
  106.     -> ld (1) </devX/objFile
  107. .CE
  108. INCLUDE FILE: loadLib.h
  109. SEE ALSO: usrLib, symLib, memLib,
  110. .pG "Basic OS"
  111. */
  112. /* LINTLIBRARY */
  113. #include "vxWorks.h"
  114. #include "bootLoadLib.h"
  115. #include "cacheLib.h"
  116. #include "errnoLib.h"
  117. #include "fioLib.h"
  118. #include "ioLib.h"
  119. #include "loadCoffLib.h"
  120. #include "loadLib.h"
  121. #include "memLib.h"
  122. #include "pathLib.h"
  123. #include "stdio.h"
  124. #include "stdlib.h"
  125. #include "string.h"
  126. #include "symLib.h"
  127. #include "symbol.h" /* for SYM_TYPE typedef */
  128. #include "sysSymTbl.h"
  129. #include "private/vmLibP.h"
  130. /*  VxWorks Symbol Type definitions.
  131.  *
  132.  *  These are the symbol types for symbols stored in the vxWorks symbol table.
  133.  *  These are currently defined in b_out.h as N_xxx (e.g. N_ABS).
  134.  *  They are defined with new macro names so that they are
  135.  *       independent of the object format.
  136.  *  It would probably be better to define these in symLib.h.
  137.  */
  138. #define VX_ABS 2 /* Absolute symbol */
  139. #define VX_TEXT 4 /* Text symbol */
  140. #define VX_DATA 6 /* Data symbol */
  141. #define VX_BSS 8 /* BSS symbol */
  142. #define VX_EXT 1 /* External symbol (OR'd in with one of above) */
  143. /* fast download */
  144. #define BAL_LOAD 0x80 /* flag indicating download with branch-and-link
  145.    optimization - results in slower download */
  146. LOCAL int fast_load = TRUE;
  147. /*
  148.  *  DEBUG Stuff
  149.  *  #define DEBUG 
  150.  */
  151. #ifdef DEBUG
  152. int debug = 2;                          /* 2 = printf relocation info */
  153. #endif  /* DEBUG */
  154. #ifdef DEBUG
  155. #define DPRINTF if (debug >= 2) printf
  156. #else
  157. #define DPRINTF noop
  158. void noop() { }
  159. #endif
  160. /* #define DEBUG_MALLOC
  161.  */
  162. #ifdef DEBUG_MALLOC
  163. char *
  164. debugMalloc(nbytes)
  165.     int nbytes;
  166.     {
  167.     printf("Calling malloc(%d)n", nbytes);
  168.     memShow(0);
  169.     return( (char *) malloc(nbytes));
  170.     }
  171. #define malloc debugMalloc
  172. #endif
  173. /*
  174.  *  Abridged edition of a object file symbol entry SYMENT
  175.  *
  176.  *  This is used to minimize the amount of malloc'd memory.
  177.  *  The abridged edition contains all elements of SYMENT required
  178.  *  to perform relocation.
  179.  */
  180. #ifdef __GNUC__
  181. #pragma align 1 /* tell gcc960 to not pad structures */
  182. #endif
  183. struct symentAbridged {
  184. long n_value; /* value of symbol */
  185. short n_scnum; /* section number */
  186. char n_sclass; /* storage class */
  187. char n_numaux;       /* number of auxiliary entries  */
  188. };
  189. #define SYMENT_A struct symentAbridged
  190. #define SYMESZ_A sizeof(SYMENT_A)
  191. #ifdef __GNUC__
  192. #pragma align 0 /* turn off alignment requirement */
  193. #endif
  194. /* 
  195.  *  COFF symbol types and classes as macros
  196.  *
  197.  *   'sym' in the macro defintion must be defined as:   SYMENT *sym;
  198.  */
  199. #define U_SYM_VALUE    n_value
  200. #if (CPU_FAMILY == I960)
  201. #define COFF_EXT(sym) 
  202.     (((sym)->n_sclass == C_EXT) || ((sym)->n_sclass == C_LEAFEXT))
  203. #else /* (CPU_FAMILY == I960) */
  204. #if (CPU_FAMILY == ARM)
  205. #define COFF_EXT(sym) 
  206.     (((sym)->n_sclass == C_EXT) || 
  207.      ((sym)->n_sclass == C_THUMBEXT) || 
  208.      ((sym)->n_sclass == C_THUMBEXTFUNC))
  209. #else /* (CPU_FAMILY == ARM) */
  210. #define COFF_EXT(sym) 
  211.     ((sym)->n_sclass == C_EXT)
  212. #endif /* (CPU_FAMILY == ARM) */
  213. #endif /* (CPU_FAMILY == I960) */
  214. /*  COFF Undefined External Symbol */
  215. #define COFF_UNDF(sym) 
  216.     (((sym)->n_sclass == C_EXT) && ((sym)->n_scnum == N_UNDEF))
  217. /*  COFF Common Symbol
  218.  *    A common symbol type is denoted by undefined external
  219.  *    with its value set to non-zero.
  220.  */
  221. #define COFF_COMM(sym) ((COFF_UNDF(sym)) && ((sym)->n_value != 0))
  222. /* COFF Unassigned type
  223.  *    An unassigned type symbol of class C_STAT generated by
  224.  *    some assemblers
  225.  */
  226. #define COFF_UNASSIGNED(sym) (((sym)->n_sclass == C_STAT) && ((sym)->n_type == T_NULL))
  227. /* misc defines */
  228. #define INSERT_HWORD(WORD,HWORD)        
  229.     (((WORD) & 0xff00ff00) | (((HWORD) & 0xff00) << 8) | ((HWORD)& 0xff))
  230. #define EXTRACT_HWORD(WORD) 
  231.     (((WORD) & 0x00ff0000) >> 8) | ((WORD)& 0xff)
  232. #define SIGN_EXTEND_HWORD(HWORD) 
  233.     ((HWORD) & 0x8000 ? (HWORD)|0xffff0000 : (HWORD))
  234. #define SWAB_SHORT(s) 
  235.   ((((unsigned short) s & 0x00ff) << 8) | (((unsigned short) s & 0xff00) >> 8))
  236. #define MAX_SCNS        11              /* max sections supported */
  237. #define NO_SCNS         0
  238. #if (CPU_FAMILY == I960)
  239. #define MAX_ALIGNMENT 16              /* max boundary for architecture */
  240. #else /* (CPU_FAMILY == I960) */
  241. #define MAX_ALIGNMENT 4 /* max boundary for architecture */
  242. #endif /* (CPU_FAMILY == I960) */
  243. #if (CPU_FAMILY == AM29XXX) || (CPU_FAMILY == ARM)
  244. LOCAL int textSize; /* size of the "real" text not */
  245. /* including the .lit section size */
  246. /* needed by the 29K coff files */
  247. #endif /* (CPU_FAMILY == AM29XXX) || (CPU_FAMILY == ARM) */
  248. char *addrScn[MAX_SCNS];                /* where each section is located */
  249. LOCAL int  max_scns = MAX_SCNS; /* load with MAX */
  250. LOCAL char stringMemErrMsg [] =
  251.     "loadLib error: insufficient memory for strings table (need %d bytes).n";
  252. LOCAL char extMemErrMsg [] =
  253.     "loadLib error: insufficient memory for externals table (need %d bytes).n";
  254. LOCAL char cantConvSymbolType [] =
  255.     "loadLib error: can't convert '%s' symbol type - error = %#x.n";
  256. LOCAL char cantAddSymErrMsg [] =
  257.     "loadLib error: can't add '%s' to system symbol table - error = %#x.n";
  258. #ifndef MULTIPLE_LOADERS
  259. LOCAL char fileTypeUnsupported [] =
  260.     "loadLib error: File type with magic number %#x is not supported.n";
  261. #endif
  262. #if (CPU_FAMILY == I960)
  263. LOCAL char symNotFoundErrMsg [] =
  264.     "loadLib error: trying to relocate to non-existent symboln";
  265. #endif /* (CPU_FAMILY == I960) */
  266. #if (CPU_FAMILY == AM29XXX)
  267. LOCAL char outOfRangeErrMsg [] =
  268.     "loadLib error: relative address out of rangen";
  269. LOCAL char hiHalfErrMsg [] =
  270.     "loadLib error: IHIHALF missing in modulen";
  271. #endif /* (CPU_FAMILY == AM29XXX) */
  272. #if (CPU_FAMILY == ARM)
  273. LOCAL int sprFixTextOff[100]; /* SPR 21809 */
  274. LOCAL char outOfRangeErrMsg [] =
  275.     "loadLib error: relative address out of rangen";
  276. LOCAL char symNotFoundErrMsg [] =
  277.     "loadLib error: trying to relocate to non-existent symboln";
  278. LOCAL char incorrectEndiannessErrMsg [] =
  279.     "loadLib error: incorrect endianness for targetn";
  280. #endif  /* (CPU_FAMILY == ARM) */
  281. /* forward declarations */
  282. LOCAL void coffFree ();
  283. LOCAL void coffSegSizes ();
  284. LOCAL STATUS coffReadSym ();
  285. #if (CPU_FAMILY == AM29XXX)
  286. LOCAL STATUS coffRelSegmentAm29K ();
  287. #endif /* (CPU_FAMILY == AM29XXX) */
  288. #if (CPU_FAMILY == I960)
  289. LOCAL STATUS coffRelSegmentI960 ();
  290. #endif /* (CPU_FAMILY == I960) */
  291. #if (CPU_FAMILY == ARM)
  292. LOCAL STATUS coffRelSegmentArm ();
  293. #endif  /* (CPU_FAMILY == ARM) */
  294. LOCAL STATUS softSeek ();
  295. LOCAL STATUS fileRead ();
  296. LOCAL STATUS swabData ();
  297. LOCAL void swabLong ();
  298. LOCAL ULONG coffTotalCommons ();
  299. LOCAL ULONG dataAlign ();
  300. LOCAL STATUS coffHdrRead ();
  301. LOCAL STATUS coffOpthdrRead ();
  302. LOCAL STATUS coffSecHdrRead ();
  303. LOCAL STATUS coffLoadSections ();
  304. LOCAL STATUS coffReadRelocInfo ();
  305. LOCAL STATUS coffReadExtSyms ();
  306. LOCAL STATUS coffReadExtStrings ();
  307. LOCAL STATUS coffSymTab (int fd, struct filehdr *pHdr, SYMENT *pSymbols, 
  308.  char ** *externals,
  309.                          int symFlag, SEG_INFO *pSeg, char *symStrings,
  310.                          SYMTAB_ID symTbl, char *pNextCommon,
  311.                          struct scnhdr *pScnHdrArray, char **pScnAddr,
  312.  BOOL symsAbsolute, BOOL swapTables, UINT16 group);
  313. /******************************************************************************
  314. *
  315. * loadCoffInit - initialize the system for coff load modules.
  316. *
  317. * This routine initializes VxWorks to use a COFF format for loading 
  318. * modules.
  319. *
  320. * RETURNS: OK
  321. *
  322. * SEE ALSO: loadModuleAt()
  323. */
  324. STATUS loadCoffInit
  325.     (
  326.     )
  327.     {
  328.     /* XXX check for installed? */
  329.     loadRoutine = (FUNCPTR) ldCoffModAtSym;
  330.     return (OK);
  331.     }
  332. /******************************************************************************
  333. *
  334. * ldCoffModAtSym - load object module into memory with specified symbol table
  335. *
  336. * This routine is the underlying routine to loadModuleAtSum().  This interface
  337. * allows specification of the the symbol table used to resolve undefined
  338. * external references and to which to add new symbols.
  339. *
  340. * RETURNS:
  341. * MODULE_ID, or
  342. * NULL if can't read file or not enough memory or illegal file format
  343. *
  344. * NOMANUAL
  345. */
  346. MODULE_ID ldCoffModAtSym
  347.     (
  348.     FAST int fd, /* fd from which to read module */
  349.     int symFlag, /* symbols to be added to table 
  350.  *   ([NO | GLOBAL | ALL]_SYMBOLS) */
  351.     char **ppText, /* load text segment at address pointed to by this
  352.  * pointer, return load address via this pointer */
  353.     char **ppData, /* load data segment at address pointed to by this
  354.  * pointer, return load address via this pointer */
  355.     char **ppBss, /* load bss segment at address pointed to by this
  356.  * pointer, return load address via this pointer */
  357.     SYMTAB_ID symTbl /* symbol table to use */
  358.     )
  359.     {
  360.     char *pText = (ppText == NULL) ? LD_NO_ADDRESS : *ppText;
  361.     char *pData = (ppData == NULL) ? LD_NO_ADDRESS : *ppData;
  362.     char *pBss  = (ppBss  == NULL) ? LD_NO_ADDRESS : *ppBss;
  363.     char **externalsBuf = NULL;         /* array of symbol absolute values */
  364.     char *externalSyms = NULL;          /* buffer for object file symbols */
  365.     char *stringsBuf = NULL; /* string table pointer */
  366.     FILHDR hdr; /* module's COFF header */
  367.     AOUTHDR optHdr;              /* module's COFF optional header */
  368.     SCNHDR scnHdr[MAX_SCNS]; /* module's COFF section headers */
  369.     char *scnAddr[MAX_SCNS];            /* array of section loaded address */
  370.     RELOC  *relsPtr[MAX_SCNS];  /* section relocation */
  371.     SEG_INFO seg; /* file segment info */
  372.     BOOL tablesAreLE; /* boolean for table sex */
  373.     BOOL symsAbsolute = FALSE;          /* TRUE if already absolutely located*/
  374.     int status; /* return value */
  375.     int ix; /* temp counter */
  376.     int nbytes; /* temp counter */
  377.     char *pCommons;                     /* start of common symbols in bss */
  378.     char *addrBss;
  379.     char        fileName[255];
  380.     UINT16      group;
  381.     MODULE_ID   moduleId;
  382.     /* Initialization */
  383.     memset ((void *)&seg, 0, sizeof (seg));
  384. #if (CPU_FAMILY == I960)
  385.     /* check for fast load */
  386.     if ((symFlag & BAL_LOAD) || (symFlag == NO_SYMBOLS))
  387. {
  388. fast_load = FALSE;
  389. if (symFlag != NO_SYMBOLS)
  390.     symFlag &= ~BAL_LOAD;
  391. }
  392.     else
  393.         fast_load = TRUE;
  394. #endif
  395.     /* Set up the module */
  396.     ioctl (fd, FIOGETNAME, (int) fileName);
  397.     moduleId = loadModuleGet (fileName, MODULE_ECOFF, &symFlag);
  398.     if (moduleId == NULL)
  399.         return (NULL);
  400.     group = moduleId->group;
  401.     /* init section pointers to NULL */
  402.     for (ix = 0; ix < MAX_SCNS; ix++)
  403. {
  404. scnAddr[ix] = NULL;
  405. relsPtr[ix] = NULL;
  406. bzero((char *) &scnHdr[ix], (int) sizeof(SCNHDR));
  407. }
  408.     /* read object module header */
  409.     if (coffHdrRead (fd, &hdr, &tablesAreLE) != OK)
  410. {
  411. /*  Preserve errno value from subroutine. */
  412. goto error;
  413. }
  414.     /* read in optional header */
  415.     if (hdr.f_opthdr)                   /* if there is an optional header */
  416.         {
  417.         if (coffOpthdrRead (fd, &optHdr, tablesAreLE) != OK)
  418.             {
  419.             errnoSet(S_loadLib_OPTHDR_READ);
  420.             goto error;
  421.             }
  422.         }
  423.     /* read in section headers */
  424.     if (coffSecHdrRead (fd, &scnHdr[0], &hdr, tablesAreLE) != OK)
  425. {
  426. errnoSet(S_loadLib_SCNHDR_READ);
  427. goto error;
  428. }
  429.     /* Determine segment sizes */
  430.     /* 
  431.      * XXX seg.flagsXxx mustn't be used between coffSegSizes() and 
  432.      * loadSegmentsAllocate().
  433.      */
  434.     coffSegSizes(&hdr, scnHdr, &seg);
  435.     /*  If object file is already absolutely located (by linker on host),
  436.      *  then override parameters pText, pData and pBss.
  437.      */
  438.     if (   (hdr.f_flags & F_EXEC)
  439.         && (hdr.f_flags & F_RELFLG))
  440.         {
  441.         if (hdr.f_opthdr)               /* if there is an optional header */
  442.             {
  443.             symsAbsolute = TRUE;
  444.             pText = (INT8 *)(optHdr.text_start);
  445.             pData = (INT8 *)(optHdr.data_start);
  446.             /* bss follows data segment */
  447.             pBss = (INT8 *) pData + optHdr.dsize;
  448.             pBss += dataAlign(MAX_ALIGNMENT, pBss);
  449.     }
  450. }
  451.     seg.addrText = pText;
  452.     seg.addrData = pData;
  453.     /*
  454.      * If pBss is set to LD_NO_ADDRESS, change it to something else.
  455.      * The coff loader allocates one large BSS segment later on, and
  456.      * loadSegmentsAllocate doesn't work correctly for it.
  457.      */
  458.     seg.addrBss = (pBss == LD_NO_ADDRESS ? LD_NO_ADDRESS + 1 : pBss);
  459.     /* 
  460.      * SPR #21836: loadSegmentsAllocate() allocate memory aligned on 
  461.      * the max value of sections alignement saved in seg.flagsText,
  462.      * seg.flagsData, seg.flagsBss.
  463.      */
  464.     if (loadSegmentsAllocate (&seg) != OK)
  465.         {
  466.         printErr ("Could not allocate segmentsn");
  467.         goto error;
  468.         }
  469.     else
  470.         {
  471.         pText = seg.addrText;
  472.         pData = seg.addrData;
  473.         }
  474.     /*  Ensure that section starts on the appropriate alignment.
  475.      */
  476.     pText += dataAlign(MAX_ALIGNMENT, pText);
  477.     if (pData == LD_NO_ADDRESS)
  478.         {
  479. pData = pText + seg.sizeText;
  480.         }
  481.     /*  Ensure that section starts on the appropriate alignment.
  482.      */
  483.     pData += dataAlign(MAX_ALIGNMENT, pData);
  484.     seg.addrText = pText;
  485.     seg.addrData = pData;
  486.     /* load text and data sections */
  487.     if (coffLoadSections (fd, &scnHdr[0], &scnAddr[0], pText, pData) != OK)
  488. {
  489. errnoSet (S_loadLib_LOAD_SECTIONS);
  490. goto error;
  491. }
  492.     /* get section relocation info */
  493.     if (coffReadRelocInfo (fd, &scnHdr[0], &relsPtr[0], tablesAreLE) != OK)
  494. {
  495. errnoSet (S_loadLib_RELOC_READ);
  496. goto error;
  497. }
  498.     /* read symbols */
  499.     if (coffReadExtSyms (fd, &externalSyms, &externalsBuf, &hdr, tablesAreLE)
  500.         != OK)
  501. {
  502. errnoSet (S_loadLib_EXTSYM_READ);
  503. goto error;
  504. }
  505.     /* read string table */
  506.     if (coffReadExtStrings (fd, &stringsBuf, tablesAreLE) != OK)
  507. {
  508. errnoSet (S_loadLib_EXTSTR_READ);
  509. goto error;
  510. }
  511.     /*  Determine additional amount of memory required to append
  512.      *  common symbols on to the end of the BSS section.
  513.      */
  514.     nbytes = coffTotalCommons(externalSyms, hdr.f_nsyms, seg.sizeBss);
  515.     /* set up for bss */
  516.     seg.sizeBss += nbytes;
  517.     if (pBss == LD_NO_ADDRESS)
  518.         {
  519.         if (seg.sizeBss != 0)
  520.             {
  521.             if ((pBss = malloc (seg.sizeBss)) == NULL) 
  522.                 goto error;
  523.             else                                 
  524. seg.flagsBss |= SEG_FREE_MEMORY;  
  525.             }
  526.         else
  527.             {
  528.             pBss = (char *) ((long) pData + (long) seg.sizeData);
  529.             }
  530.         }
  531.     pBss += dataAlign(MAX_ALIGNMENT, pBss);
  532.     seg.addrBss = pBss;
  533.     /* fix up start address of bss sections */
  534.     addrBss = pBss;
  535.     for (ix = 0; ix < max_scns; ix++)
  536.         {
  537.         if (scnHdr[ix].s_flags & STYP_BSS)
  538.     {
  539. #if (CPU_FAMILY == I960) 
  540.     addrBss += dataAlign (scnHdr[ix].s_align, addrBss);
  541. #else /* (CPU_FAMILY == I960) */
  542.     addrBss += dataAlign (MAX_ALIGNMENT, addrBss);
  543. #endif /* (CPU_FAMILY == I960) */
  544.     scnAddr[ix] = addrBss;
  545.     addrBss += scnHdr[ix].s_size;
  546.             }
  547.         }
  548.     
  549.     /* set up address for first common symbol */
  550.     pCommons = (char *) ((long) seg.addrBss + (seg.sizeBss - nbytes));
  551.     /* add segment names to symbol table before other symbols */
  552.     if (symFlag != LOAD_NO_SYMBOLS)
  553.         addSegNames (fd, pText, pData, pBss, symTbl, group);
  554.     /* process symbol table */
  555.     status = coffSymTab (fd, &hdr, (SYMENT *)externalSyms, &externalsBuf, 
  556.  symFlag, &seg, stringsBuf, symTbl, pCommons, scnHdr,
  557.  scnAddr, symsAbsolute, tablesAreLE, group);
  558.     /* relocate text and data segments
  559.      *
  560.      *   note: even if symbol table had missing symbols, continue with
  561.      *   relocation of those symbols that were found.
  562.      *   note: relocation is for changing the values of the relocated
  563.      *   symbols.  bss is uninitialized data, so it is not relocated
  564.      *   in the symbol table.
  565.      */
  566.     if ((status == OK) || (errnoGet() == S_symLib_SYMBOL_NOT_FOUND))
  567.         for (ix = 0; ix < max_scns; ix++)
  568.     {
  569.     if ((relsPtr[ix] != NULL) &&
  570. !(scnHdr[ix].s_flags & STYP_INFO) &&
  571. !(scnHdr[ix].s_flags & STYP_NOLOAD) &&
  572.  (scnHdr[ix].s_flags != STYP_REG) && 
  573. !(scnHdr[ix].s_flags & STYP_PAD))
  574. {
  575. #if (CPU_FAMILY == ARM)
  576.                 if (coffRelSegmentArm(relsPtr[ix], scnHdr, externalsBuf,
  577.                                externalSyms, &seg, ix, symTbl) != OK)
  578. #else
  579. #if (CPU_FAMILY == AM29XXX)
  580.                 if (coffRelSegmentAm29K(relsPtr[ix], scnHdr, externalsBuf, 
  581.                                externalSyms, &seg, ix, symTbl) != OK)
  582. #else /* (CPU_FAMILY == I960) */
  583.                 if (coffRelSegmentI960(relsPtr[ix], scnHdr, scnAddr[ix],
  584.        externalsBuf, externalSyms, &seg, ix,
  585.        symTbl) != OK)
  586. #endif /* (CPU_FAMILY == AM29XXX) */
  587. #endif /* (CPU_FAMILY == ARM) */
  588.     {
  589.             goto error;
  590.     }
  591. }
  592.     }
  593.     coffFree(externalsBuf, externalSyms, stringsBuf, relsPtr);
  594.     /* write protect the text if text segment protection is turned on */
  595.     if (seg.flagsText & SEG_WRITE_PROTECTION)
  596. {
  597. if (VM_STATE_SET (NULL, pText, seg.sizeProtectedText,
  598.   VM_STATE_MASK_WRITABLE,
  599.   VM_STATE_WRITABLE_NOT) == ERROR)
  600.     goto error;
  601. }
  602.     /* return load addresses, where called for */
  603.     if (ppText != NULL)
  604.         *ppText = pText;
  605.     if (ppData != NULL)
  606.         *ppData = pData;
  607.     if (ppBss != NULL)
  608.         *ppBss = pBss;
  609.     /* clear out bss */
  610.     bzero (pBss, (int) seg.sizeBss);
  611.     /*
  612.      * Add the segments to the module.
  613.      * This has to happen after the relocation gets done.
  614.      * If the relocation happens first, the checksums won't be
  615.      * correct.
  616.      */
  617.     moduleSegAdd (moduleId, SEGMENT_TEXT, pText, seg.sizeText, seg.flagsText);
  618.     moduleSegAdd (moduleId, SEGMENT_DATA, pData, seg.sizeData, seg.flagsData);
  619.     moduleSegAdd (moduleId, SEGMENT_BSS, pBss, seg.sizeBss, seg.flagsBss);
  620.     if (status == OK)
  621.         return (moduleId);
  622.     else
  623.         return (NULL);
  624.     /* error:
  625.      * clean up dynamically allocated temporary buffers and return ERROR
  626.      */
  627. error:
  628.     coffFree(externalsBuf, externalSyms, stringsBuf, relsPtr);
  629.     moduleDelete (moduleId);
  630.     return (NULL);
  631.     }
  632. /*******************************************************************************
  633. *
  634. * coffFree - free any malloc'd memory
  635. *
  636. */
  637. LOCAL void coffFree
  638.     (
  639.     char **pExternalsBuf,       /* pointers to external symbols */
  640.     char *pExternalSyms,        /* buffer for external symbols */
  641.     char *pStringsBuf, /* string table pointer */
  642.     RELOC  **pRelsPtr  /* section relocation */
  643.     )
  644.     {
  645.     int ix;
  646.     if (pStringsBuf != NULL)
  647. free (pStringsBuf);
  648.     if (pExternalsBuf != NULL)
  649. free ((char *) pExternalsBuf);
  650.     if (pExternalSyms != NULL)
  651. free ((char *) pExternalSyms);
  652.     for (ix = 0; ix < MAX_SCNS; ix++)
  653. {
  654. if (*pRelsPtr != NULL)
  655.     free((char *) *pRelsPtr);
  656.         pRelsPtr++;
  657. }
  658.     }
  659. /*******************************************************************************
  660. *
  661. * coffSegSizes - determine segment sizes
  662. *
  663. * This function fills in the size fields in the SEG_INFO structure.
  664. * Note that the bss size may need to be readjusted for common symbols. 
  665. */
  666. LOCAL void coffSegSizes
  667.     (
  668.     FILHDR *pHdr,               /* pointer to file header */
  669.     SCNHDR *pScnHdrArray,       /* pointer to array of section headers */
  670.     SEG_INFO *pSeg        /* section addresses and sizes */
  671.     )
  672.     {
  673.     int ix;
  674.     int nbytes;             /* additional bytes required for alignment */
  675.     SCNHDR *pScnHdr;            /* pointer to a section header */
  676.     pSeg->sizeText = 0;
  677.     pSeg->sizeData = 0;
  678.     pSeg->sizeBss = 0;
  679.     /* 
  680.      * SPR #21836: pSeg->flagsText, pSeg->flagsData, pSeg->flagsBss are used
  681.      * to save the max value of each segments. These max values are computed
  682.      * for each sections. These fields of pSeg are only used on output, then
  683.      * a temporary use is allowed.
  684.      */
  685.     pSeg->flagsText = _ALLOC_ALIGN_SIZE;
  686.     pSeg->flagsData = _ALLOC_ALIGN_SIZE;
  687.     pSeg->flagsBss  = _ALLOC_ALIGN_SIZE;
  688.     for (ix=0; ix < pHdr->f_nscns; ix++) /* loop thru all sections */
  689.         {
  690.         pScnHdr = pScnHdrArray + ix;
  691.         if (pScnHdr->s_flags & STYP_TEXT)
  692.             {
  693.             /*  Assume that there was a previous section of same type.
  694.              *  First, align data to boundary from section header.
  695.              *  Add the size of this section to the total segment size.
  696.              */
  697. #if (CPU_FAMILY == ARM)
  698.             sprFixTextOff[ix] = pSeg->sizeText;
  699. #endif
  700. #if (CPU_FAMILY == I960)
  701.             nbytes = dataAlign(pScnHdr->s_align, pSeg->sizeText);
  702.     /* SPR #21836 */
  703.     if (pScnHdr->s_align > pSeg->flagsText)
  704. pSeg->flagsText = pScnHdr->s_align;
  705. #else /* (CPU_FAMILY == I960) */
  706.             nbytes = dataAlign(MAX_ALIGNMENT, pSeg->sizeText);
  707.     /* SPR #21836 */
  708.     if (MAX_ALIGNMENT > pSeg->flagsText)
  709. pSeg->flagsText = MAX_ALIGNMENT;
  710. #endif /* (CPU_FAMILY == I960) */
  711.             pSeg->sizeText += pScnHdr->s_size + nbytes;
  712.             }
  713.         else if (pScnHdr->s_flags & STYP_DATA)
  714.             {
  715. #if (CPU_FAMILY == I960)
  716.             nbytes = dataAlign(pScnHdr->s_align, pSeg->sizeData);
  717.     /* SPR #21836 */
  718.     if (pScnHdr->s_align >  pSeg->flagsData)
  719. pSeg->flagsData = pScnHdr->s_align;
  720. #else /* (CPU_FAMILY == I960) */
  721.             nbytes = dataAlign(MAX_ALIGNMENT, pSeg->sizeData);
  722.     /* SPR #21836 */
  723.     if (MAX_ALIGNMENT > pSeg->flagsData)
  724. pSeg->flagsData = MAX_ALIGNMENT;
  725. #endif /* (CPU_FAMILY == I960) */
  726.             pSeg->sizeData += pScnHdr->s_size + nbytes;
  727.             }
  728.         else if (pScnHdr->s_flags & STYP_BSS)
  729.             {
  730. #if (CPU_FAMILY == I960)
  731.             nbytes = dataAlign(pScnHdr->s_align, pSeg->sizeBss);
  732.     /* SPR #21836 */
  733.     if (pScnHdr->s_align > pSeg->flagsBss)
  734. pSeg->flagsBss = pScnHdr->s_align;
  735. #else /* (CPU_FAMILY == I960) */
  736.             nbytes = dataAlign(MAX_ALIGNMENT, pSeg->sizeBss);
  737.     /* SPR #21836 */
  738.     if (MAX_ALIGNMENT > pSeg->flagsBss)
  739. pSeg->flagsBss = MAX_ALIGNMENT;
  740. #endif /* (CPU_FAMILY == I960) */
  741.             pSeg->sizeBss += pScnHdr->s_size + nbytes;
  742.             }
  743.         }
  744.     }
  745. /*******************************************************************************
  746. *
  747. * coffLoadSections - read sections into memory
  748. */
  749. LOCAL STATUS coffLoadSections
  750.     (
  751.     int     fd,
  752.     SCNHDR  *pScnHdr,
  753.     char    **pScnAddr,
  754.     char    *pText,
  755.     char    *pData
  756.     )
  757.     {
  758.     int     ix;
  759.     int     textCount = 0;
  760.     int     dataCount = 0;
  761.     INT32   size;               /* section size */
  762.     int     nbytes;             /* additional bytes required for alignment */
  763.     char    *pLoad;             /* address to load data at */
  764. #if (CPU_FAMILY == AM29XXX) || (CPU_FAMILY == ARM)
  765.     textSize = 0; /* clear "real" text size */
  766. #endif /* (CPU_FAMILY == AM29XXX) || (CPU_FAMILY == ARM) */
  767.     for (ix = 0; ix < max_scns; ix++)
  768. {
  769.         pLoad = NULL;
  770.         size = pScnHdr->s_size;
  771. #ifdef DEBUG
  772.         DPRINTF("sec size=%#x sec ptr=%#xn", size, pScnHdr->s_scnptr);
  773. #endif  /* DEBUG */
  774. if (size != 0 && pScnHdr->s_scnptr != 0)
  775.     {
  776.             if (pScnHdr->s_flags & STYP_TEXT)
  777.                 {
  778. #if (CPU_FAMILY == AM29XXX) || (CPU_FAMILY == ARM)
  779.              /* 
  780.  * if section is not .lit add its size to the "real" 
  781.  * text size. Note that this is a hack a better way 
  782.  * should be to add a pLit parameter to coffLoadSections().
  783.  *
  784.  * Note: ARM rdata sections have both _LIT and _TEXT flags set.
  785.  */
  786.         if (!(pScnHdr->s_flags & STYP_LIT))
  787.               textSize += size;
  788. #endif /* (CPU_FAMILY == AM29XXX) */
  789.                 pLoad = pText;
  790. #if (CPU_FAMILY == I960) 
  791.                 nbytes = dataAlign(pScnHdr->s_align, pLoad);
  792. #else /* (CPU_FAMILY == I960) */
  793.                 nbytes = dataAlign(MAX_ALIGNMENT, pLoad);
  794. #endif /* (CPU_FAMILY == I960) */
  795.                 pLoad += nbytes;
  796.                 pText = (char *) ((int) pLoad + size); /* for next load */
  797.                 textCount += size + nbytes;
  798.                 }
  799.             else if (pScnHdr->s_flags & STYP_DATA)
  800.                 {
  801.                 pLoad = pData;
  802. #if (CPU_FAMILY == I960) 
  803.                 nbytes = dataAlign(pScnHdr->s_align, pLoad);
  804. #else /* (CPU_FAMILY == I960) */
  805.                 nbytes = dataAlign(MAX_ALIGNMENT, pLoad);
  806. #endif /* (CPU_FAMILY == I960) */
  807.                 pLoad += nbytes;
  808.                 pData = (char *) ((int) pLoad + size); /* for next load */
  809.                 dataCount += size + nbytes;
  810.                 }
  811.             else
  812.                 {
  813. #if (CPU_FAMILY == AM29XXX) || (CPU_FAMILY == ARM)
  814. goto skipSection;
  815. #else
  816.                 /* ignore all other sections */
  817. continue;
  818. #endif /* (CPU_FAMILY == AM29XXX) || (CPU_FAMILY == ARM) */
  819.                 }
  820.             /*  Advance to position in file
  821.              *  and read section directly into memory.
  822.              */
  823.     if ((lseek (fd, pScnHdr->s_scnptr, SEEK_SET) == ERROR) ||
  824. (fioRead (fd, pLoad, size) != size))
  825. {
  826. return (ERROR);
  827. }
  828.     }
  829. #if (CPU_FAMILY == AM29XXX) || (CPU_FAMILY == ARM)
  830. skipSection:
  831. #endif /* (CPU_FAMILY == AM29XXX) || (CPU_FAMILY == ARM) */
  832.         pScnAddr[ix] = pLoad;
  833. pScnHdr++;
  834. }
  835.     return (OK);
  836.     }
  837. /*******************************************************************************
  838. *
  839. * coffSymTab -
  840. *
  841. * This is passed a pointer to a coff symbol table and processes
  842. * each of the external symbols defined therein.  This processing performs
  843. * two functions:
  844. *
  845. *  1) Defined symbols are entered in the system symbol table as
  846. *     specified by the "symFlag" argument:
  847. * LOAD_ALL_SYMBOLS = all defined symbols (LOCAL and GLOBAL) are added,
  848. * LOAD_GLOBAL_SYMBOLS = only external (GLOBAL) symbols are added,
  849. * LOAD_NO_SYMBOLS = no symbols are added;
  850. *
  851. *  2) Any undefined externals are looked up in the system symbol table to
  852. *     determine their values.  The values are entered into the specified
  853. *     'externals' array.  This array is indexed by the symbol number
  854. *     (position in the symbol table).
  855. *     Note that all symbol values, not just undefined externals, are entered
  856. *     into the 'externals' array.  The values are used to perform relocations.
  857. *
  858. *     Note that "common" symbols have type undefined external - the value
  859. *     field of the symbol will be non-zero for type common, indicating
  860. *     the size of the object.
  861. *
  862. * If an undefined external cannot be found in the system symbol table,
  863. * an error message is printed, but ERROR is not returned until the entire
  864. * symbol table has been read, which allows all undefined externals to be
  865. * looked up.
  866. *
  867. * RETURNS: OK or ERROR
  868. */
  869. LOCAL STATUS coffSymTab
  870.     (
  871.     int fd,
  872.     FILHDR *pHdr,               /* pointer to file header */
  873.     SYMENT *externalSyms, /* pointer to symbols array */
  874.     char ***externals, /* pointer to pointer to array to fill in 
  875.    symbol absolute values */
  876.     int symFlag, /* symbols to be added to table 
  877.  *   ([NO|GLOBAL|ALL]_SYMBOLS) */
  878.     SEG_INFO *pSeg, /* pointer to segment information */
  879.     char *symStrings, /* symbol string table */
  880.     SYMTAB_ID symTbl, /* symbol table to use */
  881.     char *pNextCommon, /* next common address in bss */
  882.     SCNHDR *pScnHdrArray, /* pointer to COFF section header array */
  883.     char **pScnAddr, /* pointer to section loaded address array */
  884.     BOOL symsAbsolute,          /* TRUE if symbols already absolutely located*/
  885.     BOOL    swapTables,
  886.     UINT16 group
  887.     )
  888.     {
  889.     int status  = OK; /* return status */
  890.     FAST char *name; /* symbol name (plus EOS) */
  891.     SYMENT *symbol; /* symbol struct */
  892.     SYM_TYPE vxSymType; /* vxWorks symbol type */
  893.     int symNum; /* symbol index */
  894.     char *adrs; /* table resident symbol address */
  895.     char *bias = 0; /* section relative address */
  896.     ULONG bssAlignment; /* alignment value of common type */
  897.     long scnFlags;              /* flags from section header */
  898.     int auxEnts = 0;            /* auxiliary symbol entries to skip */
  899.     SCNHDR *pScnHdr = NULL; /* pointer to a COFF section header */
  900.     char *scnAddr = NULL; /* section loaded address */
  901.     char nameTemp[SYMNMLEN+1];  /* temporary for symbol name string */
  902.     /*  Loop thru all symbol table entries in object file
  903.      */
  904.     for (symNum = 0, symbol = externalSyms; symNum < pHdr->f_nsyms; 
  905.  symbol++, symNum++)
  906. {
  907.         if (auxEnts)                    /* if this is an auxiliary entry */
  908.             {
  909.             auxEnts--;
  910.             continue;                   /* skip it */
  911.             }
  912.         auxEnts = symbol->n_numaux;      /* # of aux entries for this symbol */
  913.         if (symbol->n_scnum == N_DEBUG)
  914.             continue;
  915. /* Setup pointer to symbol name string
  916.  */
  917.         if (symbol->n_zeroes)            /* if name is in symbol entry */
  918.             {
  919.             name = symbol->n_name;
  920.             if ( *(name + SYMNMLEN -1) != '')
  921.                 {
  922.                 /*  If the symbol name array is full,
  923.                  *  the string is not terminated by a null.
  924.                  *  So, move the string to a temporary array,
  925.                  *  where it can be null terminated.
  926.                  */
  927.                 bcopy(name, nameTemp, SYMNMLEN);
  928.                 nameTemp[SYMNMLEN] = '';
  929.                 name = nameTemp;
  930.                 }
  931.             }
  932.         else
  933.             name = symStrings + symbol->n_offset;
  934.         if (   ! COFF_UNDF(symbol)
  935.             && ! COFF_COMM(symbol))
  936.             {
  937.             /*  Symbol is not an undefined external.
  938.              *
  939.              *  Determine symbol's section and address bias
  940.              */
  941.             if (symbol->n_scnum > 0)
  942.                 {
  943.                 pScnHdr = pScnHdrArray + (symbol->n_scnum - 1);
  944. scnAddr = pScnAddr[symbol->n_scnum - 1];
  945.                 scnFlags = pScnHdr->s_flags;
  946.                 }
  947.             else
  948.                 {
  949.                 scnFlags = 0;       /* section has no text, data or bss */
  950.                 }
  951.             if (symbol->n_scnum == N_ABS) /* special check for absolute syms */
  952.                 {
  953.                 bias = 0;
  954.                 vxSymType = VX_ABS;
  955.                 }
  956.     else if (scnFlags == STYP_REG)
  957. {
  958. printf ("Symbol %s from section of type STYP_REG. Ignored.n",
  959. name);
  960. }
  961. #if (CPU_FAMILY == AM29XXX) || (CPU_FAMILY == ARM) 
  962.             else if ((scnFlags & STYP_TEXT) && !(scnFlags & STYP_LIT))
  963. #else
  964.             else if (scnFlags & STYP_TEXT)
  965. #endif /* (CPU_FAMILY == AM29XXX) || (CPU_FAMILY == ARM) */
  966.                 {
  967. #if (CPU_FAMILY == ARM)
  968.                 bias = (char *) (scnAddr + sprFixTextOff[symbol->n_scnum - 1] - 
  969.     (char *) pScnHdr->s_vaddr);
  970. #else
  971.                 bias = (char *) (scnAddr - (char *) pScnHdr->s_vaddr);
  972. #endif /* (CPU_FAMILY == ARM) */
  973.                 vxSymType = VX_TEXT;
  974.                 }
  975.             else if (scnFlags & STYP_DATA)
  976.                 {
  977.                 bias = (char *) (scnAddr - (char *) pScnHdr->s_vaddr);
  978.                 vxSymType = VX_DATA;
  979.                 }
  980.             else if (scnFlags & STYP_BSS)
  981.                 {
  982.                 bias = (char *) (scnAddr - (char *) pScnHdr->s_vaddr);
  983.                 vxSymType = VX_BSS;
  984.                 }
  985.     /* If it has the NOLOAD or INFO bit set, ignore it silently */
  986.     else if ((scnFlags & STYP_NOLOAD) ||
  987.      (scnFlags & STYP_INFO))
  988. {
  989. continue;
  990. }
  991. #if (CPU_FAMILY == AM29XXX) || (CPU_FAMILY == ARM)
  992.     /* 
  993.      * If section is .lit it will be located just behind the text
  994.      * section. We use the global variable textSize to determine
  995.      * the end of the "real" text. A better solution would be to
  996.      * add fieds for the .lit section in the SEG_INFO structure.
  997.      * Note that the following test is always false for the i960
  998.      * architecture.
  999.      */
  1000.             else if (scnFlags & STYP_LIT)
  1001.                 {
  1002. #if (CPU_FAMILY == ARM)
  1003.                 bias = (char *)((char *) pSeg->addrText + 
  1004. sprFixTextOff[symbol->n_scnum - 1] - 
  1005. (char *)pScnHdr->s_vaddr);
  1006. #else
  1007.                 bias = (char *)((char *) pSeg->addrText + textSize -
  1008. (char *)pScnHdr->s_vaddr);
  1009. #endif /* (CPU_FAMILY == ARM) */
  1010.                 vxSymType = VX_TEXT;
  1011.                 }
  1012.     else if (COFF_UNASSIGNED(symbol))
  1013.                 continue;
  1014. #endif /* (CPU_FAMILY == AM29XXX) || (CPU_FAMILY == ARM) */
  1015.             else
  1016.                 {
  1017.                 printErr (cantConvSymbolType, name, errnoGet());
  1018.                 continue;
  1019.                 }
  1020.             /*  If object file is already absolutely located
  1021.              *  (by linker on host),
  1022.              *  then the symbol values are already correct.
  1023.              *  There is no need to bias them. 
  1024.              */
  1025.             if (symsAbsolute)
  1026.                 {
  1027.                 bias = 0x00;
  1028.                 }
  1029. #ifdef DEBUG
  1030. DPRINTF("symbol=%#x bias=%#x vaddr=%#x type=%#x ", (int)symbol, (int)bias, 
  1031. (int)pScnHdr->s_vaddr, vxSymType);
  1032. #endif  /* DEBUG */
  1033.             /*  Determine if symbol should be put into symbol table.
  1034.              */
  1035.             if (((symFlag & LOAD_LOCAL_SYMBOLS) && !COFF_EXT(symbol))
  1036.                 || ((symFlag & LOAD_GLOBAL_SYMBOLS) && COFF_EXT(symbol)))
  1037.                 {
  1038.                 if (COFF_EXT(symbol))
  1039.                     vxSymType |= VX_EXT;
  1040. #if (CPU_FAMILY == I960)
  1041.                 if (   (symbol->n_sclass == C_LEAFEXT)
  1042.                     || (symbol->n_sclass == C_LEAFSTAT))
  1043.                     {
  1044.                     vxSymType |= BAL_ENTRY; /* can call with branch & link */
  1045.                     }
  1046. #endif /* (CPU_FAMILY == I960) */
  1047.                 /*  Add symbol to symbol table.
  1048.                  */
  1049. #if ((CPU_FAMILY == ARM) && ARM_THUMB)
  1050. /*
  1051.  * Make sure we flag any functions so that relocator knows
  1052.  * to set bit zero
  1053.  */
  1054.  
  1055. if ((scnFlags & STYP_TEXT) &&
  1056.     ((unsigned char)symbol->n_sclass == C_THUMBEXTFUNC ||
  1057.      (unsigned char)symbol->n_sclass == C_THUMBSTATFUNC))
  1058.     {
  1059.     vxSymType |= SYM_THUMB;
  1060.     }
  1061. #endif /* CPU_FAMILY == ARM */
  1062. if (symSAdd (symTbl, name, symbol->U_SYM_VALUE + bias,
  1063.      vxSymType, group) != OK)
  1064.     printErr (cantAddSymErrMsg, name, errnoGet());
  1065.                 }
  1066. #if ((CPU_FAMILY == ARM) && ARM_THUMB)
  1067.     /*
  1068.      * Make sure we set bit zero of the addresses of any static
  1069.      * functions
  1070.      */
  1071.     if ((scnFlags & STYP_TEXT) &&
  1072. ((unsigned char)symbol->n_sclass == C_THUMBEXTFUNC ||
  1073.  (unsigned char)symbol->n_sclass == C_THUMBSTATFUNC))
  1074. {
  1075. bias = (char *)((UINT32)bias | 1);
  1076. }
  1077. #endif /* CPU_FAMILY == ARM */
  1078.             /* Add symbol address to externals table.
  1079.              * For COFF, we add all symbol addresses into the externals
  1080.              * table, not only those symbols saved in the vxWorks symbol
  1081.              * table.
  1082.              */
  1083.             (*externals) [symNum] = symbol->U_SYM_VALUE + bias;
  1084. #ifdef DEBUG
  1085. DPRINTF("new symbol=%#x n", (unsigned) (symbol->U_SYM_VALUE + bias));
  1086. #endif  /* DEBUG */
  1087.     }
  1088. else
  1089.     {
  1090.     /* Undefined external symbol or "common" symbol
  1091.              *
  1092.      *   A common symbol type is denoted by undefined external
  1093.              *   with its value set to non-zero.
  1094.      */
  1095.     /* if symbol is a common, then allocate space and add to
  1096.      * symbol table as BSS
  1097.      */
  1098.     /* common symbol - create new symbol */
  1099.             if (COFF_COMM(symbol))
  1100. {
  1101. if (symFlag == LOAD_NO_SYMBOLS)
  1102.     ;
  1103. else
  1104.     {
  1105.     /* 
  1106.      *  common symbol - create new symbol 
  1107.      *
  1108.      *  Common symbols are now tacked to the end of the bss
  1109.      *  section.  This is done to accomodate systems that have
  1110.      *  multiple boards sharing memory with common symbols
  1111.      *  over the system bus.  
  1112.      *  This portion of code reads the symbol value
  1113.      *  (which contains the symbol size) and places the symbol
  1114.      *  in the bss section.  The function dataAlign uses
  1115.      *  the next possible address for a common symbol to determine
  1116.      *  the proper alignment.
  1117.      */
  1118.     
  1119.     adrs = pNextCommon;
  1120.     bssAlignment = dataAlign (symbol->U_SYM_VALUE, (ULONG) adrs);
  1121.     adrs += bssAlignment;
  1122.     pNextCommon += (symbol->U_SYM_VALUE + bssAlignment);
  1123.     
  1124.     if (symSAdd (symTbl, name, adrs, (VX_BSS | VX_EXT), group) != OK)
  1125.     printErr (cantAddSymErrMsg, name, errnoGet());
  1126.     
  1127.     }
  1128. }
  1129.     /* look up undefined external symbol in symbol table */
  1130.     else if (symFindByNameAndType (symTbl, name, &adrs, &vxSymType,
  1131.    VX_EXT, VX_EXT) != OK)
  1132.                 {
  1133.                 /* symbol not found in symbol table */
  1134.                 printErr ("undefined symbol: %sn", name);
  1135.                 adrs = NULL;
  1136.                 status = ERROR;
  1137.                 }
  1138.     /* add symbol address to externals table
  1139.              */
  1140.     (*externals) [symNum] = adrs;
  1141.     }
  1142. }
  1143.     return (status);
  1144.     }
  1145. #if (CPU_FAMILY == AM29XXX)
  1146. /*******************************************************************************
  1147. *
  1148. * CoffRelSegmentAm29K - perform relocation for the Am29K family
  1149. *
  1150. * This routine reads the specified relocation command segment and performs
  1151. * all the relocations specified therein.
  1152. * Absolute symbol addresses are looked up in the 'externals' table.
  1153. *
  1154. * This function handles the following types of relocation commands
  1155. * for the Am29K family of processor:
  1156. *
  1157. *  - R_IREL instruction relative (jmp/call)
  1158. *  - R_IABS instruction absolute (jmp/call)
  1159. *  - R_ILOHALF instruction low half  (const)
  1160. *  - R_IHIHALF instruction high half (consth) part 1
  1161. *  - R_IHCONST instruction high half (consth) part 2
  1162. * constant offset of R_IHIHALF relocation
  1163. *  - R_BYTE relocatable byte value
  1164. *  - R_HWORD relocatable halfword value
  1165. *  - R_WORD relocatable word value
  1166. *
  1167. *  - R_IGLBLRC instruction global register RC
  1168. *  - R_IGLBLRA instruction global register RA
  1169. *  - R_IGLBLRB instruction global register RB
  1170. *
  1171. *
  1172. * RETURNS: OK or ERROR
  1173. * INTERNAL
  1174. * Note that we don't support multi-sections management for the Am29k 
  1175. * architecture.
  1176. */
  1177. LOCAL STATUS coffRelSegmentAm29K
  1178.     (
  1179.     RELOC * pRelCmds, /* list of relocation commands */
  1180.     SCNHDR * pScnHdrArray, /* array of section headers */
  1181.     char ** pExternals, /* array of absolute symbol values */
  1182.     SYMENT * pExtSyms, /* pointer to object file symbols */
  1183.     SEG_INFO * pSeg, /* section addresses and sizes */
  1184.     int  section, /* section number -1 for relocation */
  1185.     SYMTAB_ID  symTbl /* symbol table to use */
  1186.     )
  1187.     {
  1188.     long * pAdrs; /* relocation address */
  1189.     int nCmds; /* # reloc commands for seg */
  1190.     RELOC  relocCmd; /* relocation structure */
  1191.     STATUS  status = OK;
  1192.     UINT32 unsignedValue; /* const and consth values */
  1193.     UINT32 symVal; /* value associated with symbol */
  1194.     SYMENT * pSym; /* pointer to an external symbol */
  1195.     SCNHDR * pScnHdr; /* section header for relocation */
  1196.     INT32 signedValue; /* IREL case temporary */
  1197.     /*
  1198.      * The 29k loader needs to keep track of some values between
  1199.      * the IHICONST and ICONST relocation processing. We use static
  1200.      * variables here which makes the loader not re-entrant.
  1201.      * This should be fixed later.
  1202.      */
  1203.     static BOOL consthActive; /* CONSTH processing in progress flag */
  1204.     static UINT32 consthValue; /* CONSTH processing in progress value */
  1205.     pScnHdr = pScnHdrArray + section;
  1206.     for (nCmds = pScnHdr->s_nreloc; nCmds > 0; nCmds--)
  1207. {
  1208. /* read relocation command */
  1209. relocCmd = *pRelCmds++;
  1210. /* 
  1211.  * Calculate actual address in memory that needs relocation.
  1212.  */
  1213.         if (pScnHdr->s_flags & STYP_TEXT)
  1214.     {
  1215.     if (!(pScnHdr->s_flags & STYP_LIT))
  1216. pAdrs = (long *) ((long) pSeg->addrText + relocCmd.r_vaddr);
  1217.     else
  1218.     /* 
  1219.      * The lit section is located after the text section, we take 
  1220.      * care of this by adding the "real" text size to the text address.
  1221.      * A better solution would be to add .lit fields in the 
  1222.      * SEG_INFO structure.
  1223.      */
  1224. pAdrs = (long *) ((long) pSeg->addrText + textSize 
  1225.    + relocCmd.r_vaddr - pScnHdr->s_vaddr);
  1226.     }
  1227. else 
  1228.     {
  1229.     pAdrs = (long *) ((long) pSeg->addrData + 
  1230. (relocCmd.r_vaddr - pScnHdr->s_vaddr));
  1231.     }
  1232. #ifdef DEBUG
  1233.         DPRINTF("r_vaddr=%02x pAdrs=%08x ", 
  1234.                 relocCmd.r_vaddr, (int) pAdrs);
  1235. #endif  /* DEBUG */
  1236.         switch (relocCmd.r_type)
  1237.             {
  1238.         case R_IABS:
  1239.     /* Nothing to do in this case */
  1240. #ifdef DEBUG
  1241.             DPRINTF("IABS ");
  1242.             DPRINTF("sym=%08x ", (unsigned) pExternals [relocCmd.r_symndx]);
  1243. #endif  /* DEBUG */
  1244.     break;
  1245.         case R_IREL:
  1246.     /* 
  1247.      * Relative jmp/call: in this case we must calculate the address
  1248.      * of the target using the symbol value and the offset 
  1249.      * found in the instruction.
  1250.      */
  1251. #ifdef DEBUG
  1252.             DPRINTF("IREL ");
  1253.             DPRINTF("sym=%08x ", (unsigned) pExternals [relocCmd.r_symndx]);
  1254. #endif  /* DEBUG */
  1255.     signedValue = EXTRACT_HWORD(*pAdrs) << 2;
  1256.     signedValue = SIGN_EXTEND_HWORD(signedValue);
  1257.     signedValue += (unsigned) pExternals [relocCmd.r_symndx];
  1258.     /*
  1259.      * Now if its an absolute jmp/call set the absolute bit (A) of
  1260.      * the instruction.
  1261.      * See gnu compiler sources src/bfd/coff-a29k.c
  1262.      */
  1263.     if ((signedValue &~ 0x3ffff) == 0)
  1264. {
  1265. *pAdrs = *pAdrs | (1 << 24);
  1266. }
  1267.     else
  1268. {
  1269. signedValue -= relocCmd.r_vaddr;
  1270. if (signedValue > 0x1ffff || signedValue < -0x20000)
  1271.     printErr (outOfRangeErrMsg);
  1272. }
  1273.     
  1274.     signedValue = signedValue >> 2;
  1275.     *pAdrs = INSERT_HWORD(*pAdrs, signedValue);
  1276.     break;
  1277. case R_ILOHALF:
  1278.     /*
  1279.      * This is a CONST instruction, put the 16 lower bits of the
  1280.      * symbol value at the right place in the instruction.
  1281.      *
  1282.      * CONST instruction format:  |OP|const bit 15-8|RA|const bit 7-0|
  1283.      */
  1284. #ifdef DEBUG
  1285.             DPRINTF("ILOHALF ");
  1286.             DPRINTF("sym=%08x ", (unsigned) pExternals [relocCmd.r_symndx]);
  1287. #endif  /* DEBUG */
  1288.          pSym = pExtSyms + relocCmd.r_symndx;
  1289. #ifdef DEBUG
  1290.             DPRINTF("pSym=%08x ", (unsigned) pSym);
  1291. #endif  /* DEBUG */
  1292.     unsignedValue = EXTRACT_HWORD(*(UINT32 *)pAdrs);
  1293.     unsignedValue += (unsigned) pExternals [relocCmd.r_symndx];
  1294.     *(UINT32 *)pAdrs = INSERT_HWORD(*(UINT32 *)pAdrs, unsignedValue);
  1295.     break;
  1296. case R_IHIHALF:
  1297.     /*
  1298.      * This is the first stage of a CONSTH instruction relocation, 
  1299.      * just keep track of the fact and keep the value.
  1300.      * We don't modify the instruction until R_IHCONST.
  1301.      *
  1302.      * CONSTH instruction format:  |OP|const bit 15-8|RA|const bit 7-0|
  1303.      */
  1304. #ifdef DEBUG
  1305.             DPRINTF("IHIHALF ");
  1306.             DPRINTF("sym=%08x ", (unsigned) pExternals [relocCmd.r_symndx]);
  1307. #endif  /* DEBUG */
  1308.     pSym = pExtSyms + relocCmd.r_symndx;
  1309. #ifdef DEBUG
  1310.             DPRINTF("pSym=%08x ", (unsigned) pSym);
  1311. #endif  /* DEBUG */
  1312.     consthActive = TRUE;
  1313.     consthValue = (unsigned) pExternals [relocCmd.r_symndx];
  1314.     break;
  1315. case R_IHCONST:
  1316.     /*
  1317.      * This is the second stage of a CONSTH instruction relocation, 
  1318.      * put the 16 higher bits of the symbol value at the right place 
  1319.      * in the instruction.
  1320.      *
  1321.      * CONSTH instruction format:  |OP|const bit 15-8|RA|const bit 7-0|
  1322.      */
  1323. #ifdef DEBUG
  1324.             DPRINTF("IHCONST ");
  1325.             DPRINTF("relocOffset=%08x ", relocCmd.r_symndx);
  1326. #endif  /* DEBUG */
  1327.     if (!consthActive)
  1328. {
  1329. printErr (hiHalfErrMsg);
  1330. break;
  1331. }
  1332. /* 
  1333.  * If the parameter to a CONSTH instruction is a relocatable type, two
  1334.  * relocation records are written.  The first has an r_type of R_IHIHALF
  1335.  * (33 octal) and a normal r_vaddr and r_symndx.  The second relocation
  1336.  * record has an r_type of R_IHCONST (34 octal), a normal r_vaddr (which
  1337.  * is redundant), and an r_symndx containing the 32-bit constant offset
  1338.  * to the relocation instead of the actual symbol table index.  This
  1339.  * second record is always written, even if the constant offset is zero.
  1340.  * The constant fields of the instruction are set to zero.
  1341.  */
  1342.             unsignedValue = relocCmd.r_symndx;
  1343.             unsignedValue += consthValue ;
  1344.     unsignedValue = unsignedValue >> 16;
  1345.     *(UINT32 *)pAdrs = INSERT_HWORD(*(UINT32 *)pAdrs, unsignedValue);
  1346.     consthActive = FALSE;
  1347.     break;
  1348. case R_BYTE:
  1349.     /* Relocatable byte, just set *pAdrs with byte value. */
  1350. #ifdef DEBUG
  1351.             DPRINTF("BYTE ");
  1352.             DPRINTF("sym=%08x ", (unsigned) pExternals [relocCmd.r_symndx]);
  1353. #endif  /* DEBUG */
  1354.     pSym = pExtSyms + relocCmd.r_symndx;
  1355. #ifdef DEBUG
  1356.             DPRINTF("pSym=%08x *pAdrs %08x", (unsigned)pSym, *(char *)pAdrs);
  1357. #endif  /* DEBUG */
  1358.     symVal = (UINT32) pExternals[relocCmd.r_symndx];
  1359.          *(UINT8 *)pAdrs = *(UINT8*) pAdrs + symVal;
  1360.     break;
  1361. case R_HWORD:
  1362.     /* Relocatable half word, just set *pAdrs with half word value. */
  1363. #ifdef DEBUG
  1364.             DPRINTF("HWORD ");
  1365.             DPRINTF("sym=%08x ", (unsigned) pExternals [relocCmd.r_symndx]);
  1366. #endif  /* DEBUG */
  1367.     pSym = pExtSyms + relocCmd.r_symndx;
  1368. #ifdef DEBUG
  1369.             DPRINTF("pSym=%08x *pAdrs %08x", (unsigned)pSym, *(short *)pAdrs);
  1370. #endif  /* DEBUG */
  1371.     symVal = (UINT32) pExternals[relocCmd.r_symndx];
  1372.          *(UINT16 *)pAdrs = *(UINT16*) pAdrs + symVal;
  1373.     break;
  1374. case R_WORD:
  1375.     /* Relocatable word, just add symbol to current address content. */
  1376. #ifdef DEBUG
  1377.             DPRINTF("WORD ");
  1378.             DPRINTF("sym=%08x ", (unsigned) pExternals [relocCmd.r_symndx]);
  1379. #endif  /* DEBUG */
  1380.     pSym = pExtSyms + relocCmd.r_symndx;
  1381. #ifdef DEBUG
  1382.             DPRINTF("pSym=%08x *pAdrs %08x", (unsigned)pSym, (unsigned)*pAdrs);
  1383. #endif  /* DEBUG */
  1384.     symVal = (UINT32) pExternals[relocCmd.r_symndx];
  1385.          *(UINT32 *)pAdrs = *(UINT32*) pAdrs + symVal;
  1386.     break;
  1387. case R_IGLBLRA:
  1388.     /*
  1389.      * This is a global register A relocation, we have to set the
  1390.      * register A field of the current instruction to the value
  1391.      * associated with symbol.
  1392.      *
  1393.      * instruction format: |OP|RC|RA|RB|
  1394.      */
  1395. #ifdef DEBUG
  1396.             DPRINTF("IGLBLRA ");
  1397.             DPRINTF("sym=%08x ", (unsigned) pExternals [relocCmd.r_symndx]);
  1398. #endif  /* DEBUG */
  1399.     symVal = (UINT32) pExternals[relocCmd.r_symndx];
  1400.     *(UINT32 *)pAdrs = (*(UINT32 *)pAdrs | 
  1401.         ((symVal & REG_MASK) << REG_A_OFFSET));
  1402.     break;
  1403. case R_IGLBLRB:
  1404.     /*
  1405.      * This is a global register B relocation, we have to set the
  1406.      * register B field of the current instruction to the value
  1407.      * associated with symbol.
  1408.      *
  1409.      * instruction format: |OP|RC|RA|RB|
  1410.      */
  1411. #ifdef DEBUG
  1412.             DPRINTF("IGLBLRB ");
  1413.             DPRINTF("sym=%08x ", (unsigned) pExternals [relocCmd.r_symndx]);
  1414. #endif  /* DEBUG */
  1415.     symVal = (UINT32) pExternals[relocCmd.r_symndx];
  1416.     *(UINT32 *)pAdrs = (*(UINT32 *)pAdrs | 
  1417.         ((symVal & REG_MASK) << REG_B_OFFSET));
  1418.     break;
  1419. case R_IGLBLRC:
  1420.     /*
  1421.      * This is a global register C relocation, we have to set the
  1422.      * register C field of the current instruction to the value
  1423.      * associated with symbol.
  1424.      *
  1425.      * instruction format: |OP|RC|RA|RB|
  1426.      */
  1427. #ifdef DEBUG
  1428.             DPRINTF("IGLBLRC ");
  1429.             DPRINTF("sym=%08x ", (unsigned) pExternals [relocCmd.r_symndx]);
  1430. #endif  /* DEBUG */
  1431.     symVal = (UINT32) pExternals[relocCmd.r_symndx];
  1432.     *(UINT32 *)pAdrs = (*(UINT32 *)pAdrs | 
  1433.         ((symVal & REG_MASK) << REG_C_OFFSET));
  1434.     break;
  1435. default:
  1436.             printErr("Unrecognized relocation type %dn",
  1437.                      relocCmd.r_type);
  1438.             errnoSet (S_loadLib_UNRECOGNIZED_RELOCENTRY);
  1439.             return (ERROR);
  1440.             break;
  1441.     }
  1442. #ifdef DEBUG
  1443.             DPRINTF("n");
  1444. #endif  /* DEBUG */
  1445. }
  1446.     return(status);
  1447.     }
  1448. #endif /* (CPU_FAMILY == AM29XXX) */
  1449. #if (CPU_FAMILY == I960)
  1450. /*******************************************************************************
  1451. *
  1452. * coffRelSegmentI960 - perform relocation for the I960 family
  1453. *
  1454. * This routine reads the specified relocation command segment and performs
  1455. * all the relocations specified therein.
  1456. * Absolute symbol addresses are looked up in the 'externals' table.
  1457. *
  1458. * This function handles the following types of relocation commands
  1459. * for the i960 processor:
  1460. * R_RELLONG  - direct 32 bit relocation
  1461. * R_IPRMED   - 24-bit IP-relative relocation
  1462. *       R_OPTCALL  - optimizable call (check if can be changed to BAL)
  1463. *       R_OPTCALLX - optimizable callx (check if can be changed to BALX)
  1464. *
  1465. * RETURNS: OK or ERROR
  1466. */
  1467. LOCAL STATUS coffRelSegmentI960
  1468.     (
  1469.     RELOC *pRelCmds, /* list of relocation commands */
  1470.     SCNHDR *pScnHdrArray, /* array of section headers */
  1471.     char *scnAddr, /* section loaded address */
  1472.     char **pExternals, /* array of absolute symbol values */
  1473.     SYMENT *pExtSyms,         /* pointer to object file symbols */
  1474.     SEG_INFO *pSeg, /* section addresses and sizes */
  1475.     int section,                /* section number -1 for relocation */
  1476.     SYMTAB_ID symTbl /* symbol table to use */
  1477.     )
  1478.     {
  1479.     FAST long *pAdrs;           /* relocation address */
  1480.     int nCmds;                  /* # reloc commands for seg */
  1481.     RELOC relocCmd;             /* relocation structure */
  1482.     INT8 *symVal0 = 0;          /* absolute symbol value */
  1483.     INT8 *symVal1 = 0;          /* leaf-proc absolute symbol value */
  1484.     INT32 offset;         /* relocation value accumulator */
  1485.     char symName[MAX_SYS_SYM_LEN + 1];      /* temp buffer for symbol name */
  1486.     SYM_TYPE symType;           /* type from sys symbol table */
  1487.     STATUS status = OK;
  1488.     SYMENT *pSym;             /* pointer to an external symbol */
  1489.     SCNHDR *pScnHdr; /* section header for relocation */
  1490.     pScnHdr = pScnHdrArray + section;
  1491.     for (nCmds = pScnHdr->s_nreloc; nCmds > 0; nCmds--)
  1492. {
  1493. /* read relocation command */
  1494. relocCmd = *pRelCmds++;
  1495. /* 
  1496.  * Calculate actual address in memory that needs relocation.
  1497.  */
  1498.         if (pScnHdr->s_flags & STYP_TEXT)
  1499.     {
  1500.     pAdrs = (long *) ((long) scnAddr + (relocCmd.r_vaddr - pScnHdr->s_vaddr));
  1501.     }
  1502. else                            /* (pScnHdr->s_flags & STYP_DATA) */
  1503.     {
  1504.     pAdrs = (long *) ((long) scnAddr + (relocCmd.r_vaddr - pScnHdr->s_vaddr));
  1505.     }
  1506. #ifdef DEBUG
  1507.         DPRINTF("r_vaddr=%02x *pAdrs=%08x ", 
  1508.                 relocCmd.r_vaddr, *(UINT32 *)pAdrs);
  1509. #endif  /* DEBUG */
  1510.         switch (relocCmd.r_type)
  1511.             {
  1512.         case R_OPTCALL:
  1513.         case R_OPTCALLX:
  1514.             /* Check for a call to a leaf procedure.  If it is, then
  1515.              * replace the CALL opcode with BAL and correct the displacement.
  1516.              */
  1517. #ifdef DEBUG
  1518.             if (relocCmd.r_type == R_OPTCALL)
  1519.                 {
  1520.                 DPRINTF("OPTCALL ");
  1521.                 }
  1522.             else
  1523.                 {
  1524.                 DPRINTF("OPTCALLX ");
  1525.                 }
  1526. #endif
  1527.     if (fast_load == FALSE)
  1528. {
  1529. if (symFindByValue (symTbl, (UINT)symVal0, (char *) symName,
  1530.     (int *) &symVal0, &symType)
  1531.     != OK)
  1532.     {
  1533.     printErr (symNotFoundErrMsg);
  1534.     status = ERROR;
  1535.     break;  /* skip to next symbol */
  1536.     }
  1537. if (symType & BAL_ENTRY)
  1538.     {
  1539.     /* get symbol value from externals table */
  1540.     symVal0 = (INT8 *) (pExternals[relocCmd.r_symndx]);
  1541.     /* cat a ".lf" on the end of the symName */
  1542.     strcat ((char *)symName, ".lf");
  1543.     /* Now check if a symbol exists as name.lf
  1544.      * If it does, it is the BAL entry for the leaf proc.
  1545.      * start at symName[1] to ignore the '_'.
  1546.      */
  1547.     if (symFindByName (symTbl, &symName[1],
  1548.        &symVal1, &symType) == OK)
  1549. {
  1550. #ifdef DEBUG
  1551. DPRINTF("LEAF ");
  1552. #endif  /* DEBUG */
  1553. /* A call to a leaf procedure: replace
  1554.  * CALL opcode with BAL.
  1555.  */
  1556. if (relocCmd.r_type == R_OPTCALL)
  1557.     {
  1558.     offset = (INT32) *pAdrs;
  1559.     offset &= OFFSET24_MASK; /* clear opcode */
  1560.     offset |= ~OFFSET24_MASK; /* sign extend */
  1561.     offset += ((INT32) symVal1 - (INT32) symVal0);
  1562.     offset &= OFFSET24_MASK;
  1563.     *(UINT32 *)pAdrs = BAL_OPCODE | offset;
  1564.     }
  1565. else                /* R_OPTCALLX */
  1566.     {
  1567.     /*  Put in opcode for BALX with:
  1568.      *      absolute displacement addressing mode and
  1569.      *      register g14 for the return address.
  1570.      */
  1571.     *(UINT32 *)pAdrs = BALXG14_OPCODE;
  1572.     *(UINT32 *)(pAdrs+1) +=
  1573.                             (INT32) symVal1 - (INT32) symVal0; 
  1574. #ifdef DEBUG
  1575.     DPRINTF("*(pAdrs+1)=%08x ", *(UINT32 *)(pAdrs+1));
  1576. #endif  /* DEBUG */
  1577.     }
  1578. }
  1579.     }
  1580. else
  1581.     {
  1582. #ifdef DEBUG
  1583.     DPRINTF("NO LEAF ");
  1584. #endif  /* DEBUG */
  1585.     /* No leaf proc entry.
  1586.      * Do nothing with the OPTCALL.
  1587.      * This is a normal call/return routine.
  1588.      */
  1589.     }
  1590. }
  1591.             break;
  1592.         case R_RELLONG:
  1593.             /*
  1594.              *  This relocation is performed by adding the absolute address
  1595.              *  of the symbol to the relocation value in the code and
  1596.              *  subtracting the symbol's value (relative to the section).
  1597.              *
  1598.              * The new reloc_value =
  1599.              *   symbol_absolute_addr + reloc_value_in_code - symbol_value;
  1600.              *
  1601.              *  Both reloc_value_in_code and symbol_value are relative to
  1602.              *  the beginning of the first section in the object file.
  1603.              *  For undefined externals, reloc_value_in_code = 0
  1604.              *  and symbol_value = 0.
  1605.              */
  1606. #ifdef DEBUG
  1607.             DPRINTF("RELLONG ");
  1608.             DPRINTF("sym=%08x ", (unsigned) pExternals [relocCmd.r_symndx]);
  1609. #endif  /* DEBUG */
  1610.             offset = (INT32) pExternals[relocCmd.r_symndx];
  1611.             pSym = pExtSyms + relocCmd.r_symndx;
  1612.             if (! COFF_COMM(pSym))
  1613.                 {
  1614.                 offset -= pSym->n_value;
  1615. #ifdef DEBUG
  1616.                 DPRINTF("n_value=0x%x ", pSym->n_value);
  1617. #endif  /* DEBUG */
  1618.                 }
  1619.             *pAdrs += offset;
  1620.             break;
  1621.         case R_IPRMED:
  1622. #ifdef DEBUG
  1623.             DPRINTF("IPRMED  ");
  1624. #endif  /* DEBUG */
  1625.             pSym = pExtSyms + relocCmd.r_symndx;
  1626.             if (COFF_UNDF(pSym))        /* if symbol was undefined external */
  1627.                 {
  1628.                 /* Code to be relocated contains an offset
  1629.                  * to the beginning of the first section in the object file.
  1630.                  * To relocate it, add the absolute address
  1631.                  * of the referenced symbol and subtract the
  1632.                  * amount by which the input section will be
  1633.                  * relocated.
  1634.                  */
  1635.                 offset = (INT32) *pAdrs;
  1636.                 offset &= OFFSET24_MASK; /* clear opcode */
  1637.                 offset |= ~OFFSET24_MASK; /* sign extend */
  1638.                 offset += (INT32) pExternals [relocCmd.r_symndx];
  1639. #ifdef DEBUG
  1640.                 DPRINTF("sym=%08x ", (unsigned)pExternals [relocCmd.r_symndx]);
  1641. #endif  /* DEBUG */
  1642.                 /* IP-relative relocations were done assuming
  1643.                  * text starts at 0. Adjust for actual start of text. */
  1644.                 offset -= (INT32)scnAddr - pScnHdr->s_vaddr;
  1645.                 offset &= 0x00ffffff;
  1646.                 *(UINT32 *)pAdrs = (*(UINT32 *)pAdrs & 0xff000000) | offset;
  1647.                 }
  1648.             else
  1649.                 {
  1650. #ifdef DEBUG
  1651.                 DPRINTF("NO RELOC ");
  1652. #endif  /* DEBUG */
  1653.                 /* The symbol we are relocating to came from
  1654.                  * the same input file as the code that
  1655.                  * references it.  The relative distance
  1656.                  * between the two will not change.  Do nothing.
  1657.                  */
  1658.                 }
  1659.             break;
  1660. default:
  1661.             printErr("Unrecognized relocation type %dn",
  1662.                      relocCmd.r_type);
  1663.             errnoSet (S_loadLib_UNRECOGNIZED_RELOCENTRY);
  1664.             return (ERROR);
  1665.             break;
  1666.     }
  1667. #ifdef DEBUG
  1668.         DPRINTF("*pAdrs=%08xn", *(UINT32 *)pAdrs);
  1669. #endif  /* DEBUG */
  1670. }
  1671.     return(status);
  1672.     }
  1673. #endif /* (CPU_FAMILY == I960) */
  1674. #if (CPU_FAMILY == ARM)
  1675. /*******************************************************************************
  1676. *            
  1677. * CoffRelSegmentArm - perform relocation for the ARM family
  1678. *
  1679. * This routine reads the specified relocation command segment and performs
  1680. * all the relocations specified therein.
  1681. * Absolute symbol addresses are looked up in the 'externals' table.
  1682. *
  1683. * This function handles the following types of relocation commands
  1684. * for the ARM family of processor:
  1685. *
  1686. * - R_RELBYTE Byte PC Relative
  1687. * - R_RELWORD Word PC Relative
  1688. * - R_RELARMLONG Long PC Relative
  1689. * - R_RELARM26 26 bit PC Relative
  1690. * - R_DONEARM26 completed 26 bit PC relative
  1691. * - R_THUMB9 Thumb  9 bit PC-relative
  1692. * - R_THUMB12 Thumb 12 bit PC-relative
  1693. * - R_THUMB23 Thumb 23 bit PC-relative
  1694. * - R_DONETHUMB23 completed Thumb 23 bit PC-relative
  1695. *
  1696. * Note that RVA32 relocations are never produced in ARM code.
  1697. *
  1698. * RETURNS: OK or ERROR
  1699. *
  1700. * INTERNAL
  1701. * Large parts of this code were taken lifted from the host-based loader
  1702. * when it had not been fully tested and the tool-chain was full of
  1703. * problems. Consequently, there may be bugs...
  1704. * The handling of literal sections (.lit/.rdata) is taken from the
  1705. * Am29k code above.
  1706. */
  1707.  
  1708. LOCAL STATUS coffRelSegmentArm
  1709.     (
  1710.     RELOC * pRelCmds, /* list of relocation commands */
  1711.     SCNHDR * pScnHdrArray, /* array of section headers */
  1712.     char ** pExternals, /* array of absolute symbol values */
  1713.     SYMENT * pExtSyms, /* pointer to object file symbols */
  1714.     SEG_INFO * pSeg, /* section addresses and sizes */
  1715.     int section, /* section number -1 for relocation */
  1716.     SYMTAB_ID symTbl /* symbol table to use */
  1717.     )
  1718.     {
  1719.     void * pAdrs; /* relocation address */
  1720.     int nCmds; /* # reloc commands for seg */
  1721.     RELOC relocCmd; /* relocation structure */
  1722.     STATUS status = OK;
  1723.     ULONG value; /* value being relocated */
  1724.     SCNHDR * pScnHdr; /* section header for relocation */
  1725.     SYMENT * pSym; /* pointer to external symbol */
  1726.  
  1727.     pScnHdr = pScnHdrArray + section;
  1728.  
  1729.     for (nCmds = pScnHdr->s_nreloc; nCmds > 0; nCmds--)
  1730. {
  1731. /* read relocation command */
  1732. relocCmd = *pRelCmds++;
  1733.  
  1734. /* calculate actual address in memory that needs relocation  */
  1735.  
  1736. if (pScnHdr->s_flags & STYP_TEXT)
  1737.     {
  1738.     if (!(pScnHdr->s_flags & STYP_LIT))
  1739.         {
  1740. pAdrs = (void *) ((long) pSeg->addrText + relocCmd.r_vaddr -
  1741. pScnHdr->s_vaddr + sprFixTextOff[section]); 
  1742. }
  1743.     else
  1744.         {
  1745. /*
  1746.  * The lit/rdata section is located after the text section.
  1747.  * We take care of this by adding the "real" text size to the
  1748.  * text address, just like the AM29K. A better solution would
  1749.  * be to add .lit fields in the SEG_INFO structure.
  1750.  */
  1751. pAdrs = (void *) ((long) pSeg->addrText + sprFixTextOff[section]
  1752. + relocCmd.r_vaddr - pScnHdr->s_vaddr);
  1753.         }
  1754.     }
  1755. else
  1756.     pAdrs = (void *) ((long) pSeg->addrData +
  1757. (relocCmd.r_vaddr - pScnHdr->s_vaddr));
  1758.  
  1759.  
  1760. /* now relocate according to type */
  1761.  
  1762. switch (relocCmd.r_type)
  1763.     {
  1764.     case R_RELBYTE: /* relocate a byte */
  1765. value = *(UINT8 *)pAdrs;
  1766. /*
  1767.  * add address of symbol to the relocation value,
  1768.  * subtracting the symbol's value relative to the section
  1769.  */
  1770. value += (UINT32)pExternals[relocCmd.r_symndx];
  1771. pSym = pExtSyms + relocCmd.r_symndx;
  1772. if (!COFF_COMM(pSym))
  1773.     value -= pSym->n_value;
  1774. /* check for overflow */
  1775. if ((value & ~0xFF) != 0)
  1776.     {
  1777.     printErr (outOfRangeErrMsg);
  1778.     status = ERROR;
  1779.     break;
  1780.     }
  1781. *(UINT8 *)pAdrs = value;
  1782. break;
  1783.  
  1784.  
  1785.     case R_RELWORD: /* relocate a 16 bit word */
  1786. value = *(UINT16 *)pAdrs;
  1787. /*
  1788.  * add address of symbol to the relocation value,
  1789.  * subtracting the symbol's value relative to the section
  1790.  */
  1791. value += (UINT32)pExternals[relocCmd.r_symndx];
  1792. pSym = pExtSyms + relocCmd.r_symndx;
  1793. if (!COFF_COMM(pSym))
  1794.     value -= pSym->n_value;
  1795. /* check for overflow */
  1796. if ((value & ~0xFFFF) != 0)
  1797.     {
  1798.     printErr (outOfRangeErrMsg);
  1799.     status = ERROR;
  1800.     break;
  1801.     }
  1802. *(UINT16 *)pAdrs = value;
  1803. break;
  1804.     case R_RELARMLONG: /* relocate a long */
  1805. {
  1806. char symName[MAX_SYS_SYM_LEN + 1];  /* buffer for sym name */
  1807. int symVal0, symVal1;
  1808. SYM_TYPE symType;
  1809. value = *(UINT32 *)pAdrs;
  1810. /*
  1811.  * add address of symbol to the relocation value,
  1812.  * subtracting the symbol's value relative to the section
  1813.  */
  1814. symVal0 = (UINT32)pExternals[relocCmd.r_symndx];
  1815. value += symVal0;
  1816. pSym = pExtSyms + relocCmd.r_symndx;
  1817. if (!COFF_COMM(pSym))
  1818.     value -= pSym->n_value;
  1819. /* determine whether it's a Thumb code symbol */
  1820. if (symFindByValue (symTbl, symVal0, symName,
  1821.     &symVal1, &symType) != OK)
  1822.     {
  1823.     printErr (symNotFoundErrMsg);
  1824.     status = ERROR;
  1825.     break;  /* skip to next symbol */
  1826.     }
  1827. else
  1828.     if (symType & SYM_THUMB && symVal0 == symVal1)
  1829. {
  1830. /* it *is* a Thumb code symbol */
  1831. value |= 1;
  1832. }
  1833. *(UINT32 *)pAdrs = value;
  1834. break;
  1835. }
  1836.  
  1837.  
  1838.     case R_RELARM26:    /* relocate a 26 bit offset e.g. BL */
  1839. {
  1840. ULONG reloc;
  1841. value = *(UINT32 *)pAdrs;
  1842. /*
  1843.  * extract word offset from instruction, convert to
  1844.  * byte offset and sign-extend it
  1845.  */
  1846. reloc = (value & 0x00ffffff) << 2; /* byte offset */
  1847. reloc = (reloc ^ 0x02000000) - 0x02000000; /* sign extend  */
  1848.  
  1849. /*
  1850.  * relocate it by calculating the offset from the instruction
  1851.  * to the symbol, adjusted by the symbol's value relative
  1852.  * to the section
  1853.  */
  1854. reloc += (UINT32)pExternals[relocCmd.r_symndx] - (UINT32)pAdrs;
  1855. pSym = pExtSyms + relocCmd.r_symndx;
  1856. #if FALSE
  1857.                 /* It is quite possible that we will encounter a assembler that
  1858.                  * will generate a relocation literal that has this value encode
  1859.                  * as does the I960. For now the GNU ARM assembler does not and
  1860.                  * so the code is dissabled.
  1861.                  */
  1862.  
  1863. if (!COFF_COMM(pSym))
  1864.     reloc -= pSym->n_value;
  1865. #endif
  1866. /* check for overflow */
  1867. if ((reloc & 3) ||
  1868.     ((reloc & 0x02000000) &&
  1869.      ((reloc & ~0x03ffffff) != ~0x03ffffffU)) ||
  1870.     ((reloc & 0x02000000) == 0 && (reloc & ~0x03ffffff)))
  1871.     {
  1872.     /* overflow in 26 bit relocation */
  1873.     
  1874.     printErr (outOfRangeErrMsg);
  1875.     status = ERROR;
  1876.     break;
  1877.     }
  1878.  
  1879. /* put calculated offset into instruction */
  1880.  
  1881. value &= ~0x00ffffff; /* extract cmd */
  1882. value |= (reloc >> 2) & 0x00ffffff; /* insert offset */
  1883. *(UINT32 *)pAdrs = value;
  1884. break;
  1885. }
  1886.  
  1887.     case R_RELTHUMB9: /* relocate a Thumb 9 bit offset e.g. BEQ */
  1888.     case R_RELTHUMB12: /* relocate a Thumb 12 bit offset e.g. B */
  1889. printErr ("THUMB%d relocations not supportedn",
  1890.   relocCmd.r_type == R_RELTHUMB9 ? 9 : 12);
  1891. errnoSet (S_loadLib_NO_RELOCATION_ROUTINE);
  1892. return ERROR;
  1893. break;
  1894.     case R_RELTHUMB23: /* relocate a Thumb 23 bit offset e.g. BL */
  1895. {
  1896. ULONG reloc;
  1897. value = *(UINT16 *)pAdrs | (*(UINT16 *)(pAdrs + 2) << 16);
  1898. /*
  1899.  * extract offset from instruction, convert to
  1900.  * byte offset and sign-extend it
  1901.  */
  1902. #if defined(ARMEB)
  1903. reloc = ((value & 0x7ff) << 1) | ((value & 0x07ff0000) >> 4);
  1904. #else
  1905. reloc = ((value & 0x7ff) << 12) | ((value & 0x07ff0000) >> 15);
  1906. #endif
  1907. reloc = (reloc ^ 0x00400000) - 0x00400000; /* sign extend */
  1908. /*
  1909.  * relocate it by calculating the offset from the instruction
  1910.  * to the symbol, and subtract the symbol's value relative
  1911.  * to the section
  1912.  */
  1913. reloc += (UINT32)pExternals[relocCmd.r_symndx] & ~1;
  1914. reloc -= (UINT32)pAdrs;
  1915. pSym = pExtSyms + relocCmd.r_symndx;
  1916. #if FALSE
  1917.                 /* It is quite possible that we will encounter a assembler that
  1918.                  * will generate a relocation literal that has this value encode
  1919.                  * as does the I960. For now the GNU ARM assembler does not and
  1920.                  * so the code is dissabled.
  1921.                  */
  1922.  
  1923. if (!COFF_COMM(pSym))
  1924.     reloc -= pSym->n_value;
  1925. #endif
  1926. /* check for overflow */
  1927. if ((reloc & 1) ||
  1928.      ((reloc & 0x00400000) &&
  1929.       ((reloc & ~0x007fffff) != ~0x007fffffU)) ||
  1930.      ((reloc & 0x00400000) == 0 && (reloc & ~0x007fffff)))
  1931.     {
  1932.     /* overflow in 23 bit relocation */
  1933.     printErr (outOfRangeErrMsg);
  1934.     status = ERROR;
  1935.     break;
  1936.     }
  1937. /* put calculated offset into instruction */
  1938. value &= ~0x07ff07ff; /* Extract cmd */
  1939. #if defined(ARMEB)
  1940. value |= ((reloc & 0xffe) >> 1) | ((reloc << 4) & 0x7ff0000);
  1941. #else
  1942. value |= ((reloc & 0xffe) << 15) | ((reloc >> 12) & 0x7ff);
  1943. #endif
  1944. *(UINT16 *)pAdrs = value;
  1945. *(UINT16 *)(pAdrs + 2) = value >> 16;
  1946. break;
  1947. }
  1948.  
  1949.     case R_DONEARM26: /* already relocated */
  1950.     case R_DONETHUMB23: /* already relocated */
  1951. break;
  1952.  
  1953.  
  1954.     default:
  1955. printErr("Unrecognized relocation type %dn", relocCmd.r_type);
  1956. errnoSet (S_loadLib_UNRECOGNIZED_RELOCENTRY);
  1957. return ERROR;
  1958. break;
  1959.     }
  1960. }
  1961.     return status;
  1962.     }
  1963. #endif /* (CPU_FAMILY == ARM) */
  1964. /*******************************************************************************
  1965. *
  1966. * coffHdrRead - read in COFF header and swap if necessary
  1967. * Note:  To maintain code portability, we can not just read sizeof(FILHDR) 
  1968. * bytes.  Compilers pad structures differently,
  1969. * resulting in different structure sizes.
  1970. * So, we read the structure in an element at a time, using the size
  1971. * of each element.
  1972. */
  1973. LOCAL STATUS coffHdrRead
  1974.     (
  1975.     int fd,
  1976.     FILHDR *pHdr,
  1977.     BOOL *pSwap
  1978.     )
  1979.     {
  1980.     int status;
  1981.     if (fioRead (fd, (char *) &(pHdr->f_magic), sizeof (pHdr->f_magic) )
  1982. != sizeof (pHdr->f_magic))
  1983. {
  1984. errnoSet ((int) S_loadLib_FILE_READ_ERROR);
  1985. return (ERROR);
  1986. }
  1987.     switch (pHdr->f_magic)
  1988. {
  1989.         case I960ROMAGIC:
  1990.         case I960RWMAGIC:
  1991. case AM29KBIGMAGIC:
  1992. case ARMMAGIC:
  1993.             *pSwap = FALSE;
  1994.             break;
  1995.         case SWAB_SHORT(I960ROMAGIC):
  1996.         case SWAB_SHORT(I960RWMAGIC):
  1997. case AM29KLITTLEMAGIC:
  1998. case SWAB_SHORT(ARMMAGIC):
  1999.             *pSwap = TRUE;
  2000.             break;
  2001. default:
  2002. #ifndef MULTIPLE_LOADERS
  2003.     printErr (fileTypeUnsupported, pHdr->f_magic);
  2004. #endif
  2005.     errnoSet (S_loadLib_FILE_ENDIAN_ERROR);
  2006.     return (ERROR);
  2007.     break;
  2008. }
  2009.     status = fileRead (fd, &pHdr->f_nscns, sizeof(pHdr->f_nscns), *pSwap);
  2010.     status |= fileRead (fd, &pHdr->f_timdat, sizeof(pHdr->f_timdat), *pSwap);
  2011.     status |= fileRead (fd, &pHdr->f_symptr, sizeof(pHdr->f_symptr), *pSwap);
  2012.     status |= fileRead (fd, &pHdr->f_nsyms, sizeof(pHdr->f_nsyms), *pSwap);
  2013.     status |= fileRead (fd, &pHdr->f_opthdr, sizeof(pHdr->f_opthdr), *pSwap);
  2014.     status |= fileRead (fd, &pHdr->f_flags, sizeof(pHdr->f_flags), *pSwap);
  2015. #if (CPU_FAMILY == ARM)
  2016.     if (status != ERROR)
  2017. {
  2018. /* check endianness of object matches endianness of target */
  2019. #if (_BYTE_ORDER == _BIG_ENDIAN)
  2020. if ((pHdr->f_flags & (F_AR32W | F_AR32WR)) != F_AR32W)
  2021. #else
  2022. if ((pHdr->f_flags & (F_AR32W | F_AR32WR)) != F_AR32WR)
  2023. #endif
  2024.     {
  2025.     printErr (incorrectEndiannessErrMsg);
  2026.     errnoSet (S_loadLib_FILE_ENDIAN_ERROR);
  2027.     return (ERROR);
  2028.     }
  2029. }
  2030. #endif /* CPU_FAMILY == ARM */
  2031.     max_scns = pHdr->f_nscns;
  2032.     return (status);
  2033.     }
  2034. /*******************************************************************************
  2035. *
  2036. * coffOpthdrRead - read in COFF optional header and swap if necessary
  2037. */
  2038. LOCAL STATUS coffOpthdrRead
  2039.     (
  2040.     int     fd,
  2041.     AOUTHDR *pOptHdr,
  2042.     BOOL    swapTables
  2043.     )
  2044.     {
  2045.     int status;
  2046.     status = fileRead(fd, &pOptHdr->magic, sizeof(pOptHdr->magic),
  2047.                             swapTables);
  2048.     status |= fileRead(fd, &pOptHdr->vstamp, sizeof(pOptHdr->vstamp),
  2049.                             swapTables);
  2050.     status |= fileRead(fd, &pOptHdr->tsize, sizeof(pOptHdr->tsize),
  2051.                             swapTables);
  2052.     status |= fileRead(fd, &pOptHdr->dsize, sizeof(pOptHdr->dsize),
  2053.                             swapTables);
  2054.     status |= fileRead(fd, &pOptHdr->bsize, sizeof(pOptHdr->bsize),
  2055.                             swapTables);
  2056.     status |= fileRead(fd, &pOptHdr->entry, sizeof(pOptHdr->entry),
  2057.                             swapTables);
  2058.     status |= fileRead(fd, &pOptHdr->text_start, sizeof(pOptHdr->text_start),
  2059.                             swapTables);
  2060.     status |= fileRead(fd, &pOptHdr->data_start, sizeof(pOptHdr->data_start),
  2061.                             swapTables);
  2062. #if (CPU_FAMILY == I960)
  2063.     status |= fileRead(fd, &pOptHdr->tagentries, sizeof(pOptHdr->tagentries),
  2064.                             swapTables);
  2065. #endif /* (CPU_FAMILY == I960) */
  2066.     return (status);
  2067.     }
  2068. /*******************************************************************************
  2069. *
  2070. * coffSecHdrRead - read in COFF section header and swap if necessary
  2071. */
  2072. LOCAL STATUS coffSecHdrRead
  2073.     (
  2074.     int    fd,
  2075.     SCNHDR *pScnHdr,
  2076.     FILHDR *pHdr,
  2077.     BOOL   swapTables
  2078.     )
  2079.     {
  2080.     int ix;
  2081.     int status = 0;
  2082.     /* check for correct section count */
  2083.     if (pHdr->f_nscns > MAX_SCNS)
  2084. {
  2085.         errnoSet(S_loadLib_SCNHDR_READ);
  2086. return (ERROR);
  2087. }
  2088.     for (ix = 0; ix < pHdr->f_nscns; ix++)
  2089. {
  2090.         status = fileRead(fd, pScnHdr->s_name, sizeof(pScnHdr->s_name),
  2091.                           FALSE);
  2092.         status |= fileRead(fd, &pScnHdr->s_paddr, sizeof(pScnHdr->s_paddr),
  2093.                            swapTables);
  2094.         status |= fileRead(fd, &pScnHdr->s_vaddr, sizeof(pScnHdr->s_vaddr),
  2095.                             swapTables);
  2096.         status |= fileRead(fd, &pScnHdr->s_size, sizeof(pScnHdr->s_size),
  2097.                             swapTables);
  2098.         status |= fileRead(fd, &pScnHdr->s_scnptr, sizeof(pScnHdr->s_scnptr),
  2099.                             swapTables);
  2100.         status |= fileRead(fd, &pScnHdr->s_relptr, sizeof(pScnHdr->s_relptr),
  2101.                             swapTables);
  2102.         status |= fileRead(fd, &pScnHdr->s_lnnoptr, sizeof(pScnHdr->s_lnnoptr),
  2103.                             swapTables);
  2104.         status |= fileRead(fd, &pScnHdr->s_nreloc, sizeof(pScnHdr->s_nreloc),
  2105.                             swapTables);
  2106.         status |= fileRead(fd, &pScnHdr->s_nlnno, sizeof(pScnHdr->s_nlnno),
  2107.                             swapTables);
  2108.         status |= fileRead(fd, &pScnHdr->s_flags, sizeof(pScnHdr->s_flags),
  2109.                             swapTables);
  2110. #if (CPU_FAMILY == I960)
  2111.         status |= fileRead(fd, &pScnHdr->s_align, sizeof(pScnHdr->s_align),
  2112.                             swapTables);
  2113. #endif /* (CPU_FAMILY == I960) */
  2114. pScnHdr++;
  2115. }
  2116.     return (status);
  2117.     }
  2118. /*******************************************************************************
  2119. *
  2120. * coffReadRelocInfo - read in COFF relocation information and swap if necessary
  2121. * Assumptions:  The file pointer is positioned at the start of the relocation
  2122. * records.
  2123. *
  2124. * The relocation records are ordered by section.
  2125. */
  2126. LOCAL STATUS coffReadRelocInfo
  2127.     (
  2128.     int     fd,
  2129.     SCNHDR  *pScnHdr,
  2130.     RELOC   **pRelsPtr,
  2131.     BOOL    swapTables
  2132.     )
  2133.     {
  2134.     int ix;
  2135.     int iy;
  2136.     int relocSize;
  2137.     int status = OK;
  2138.     RELOC *pRels;                       /* pointer to single reloc entry */
  2139.     for (ix = 0; ix < max_scns; ix++)
  2140. {
  2141.         if (pScnHdr->s_nreloc > 0)
  2142.     {
  2143.     relocSize = (int) pScnHdr->s_nreloc * RELSZ;
  2144.     if ((*pRelsPtr = (RELOC *)malloc (relocSize)) == NULL)
  2145. {
  2146. return (ERROR);
  2147. }
  2148. if (lseek (fd, pScnHdr->s_relptr, SEEK_SET) == ERROR)
  2149.     {
  2150.     return (ERROR);
  2151.     }
  2152.             for (iy = 0, pRels = *pRelsPtr;
  2153.                  (iy < (int) pScnHdr->s_nreloc) && (status == OK);
  2154.                  iy++, pRels++)
  2155.                 {
  2156.                 status = fileRead(fd, &pRels->r_vaddr,
  2157.                                    sizeof(pRels->r_vaddr), swapTables);
  2158.                 status |= fileRead(fd, &pRels->r_symndx,
  2159.                                    sizeof(pRels->r_symndx), swapTables);
  2160.                 status |= fileRead(fd, &pRels->r_type,
  2161.                                    sizeof(pRels->r_type), swapTables);
  2162. #if ((CPU_FAMILY == I960) || (CPU_FAMILY == ARM))
  2163.                 status |= fileRead(fd, pRels->pad,
  2164.                                    sizeof(pRels->pad), swapTables);
  2165. #endif /* (CPU_FAMILY == I960) */
  2166.                 }
  2167.             if (status != OK)
  2168.                 return(status);
  2169.     }
  2170. pScnHdr++;
  2171. pRelsPtr++;
  2172.         }
  2173.     return (OK);
  2174.     }
  2175. /*******************************************************************************
  2176. *
  2177. * coffReadSym - read one COFF symbol entry
  2178. */
  2179. LOCAL STATUS coffReadSym
  2180.     (
  2181.     int     fd,
  2182.     SYMENT *pSym,                       /* where to read symbol entry */
  2183.     BOOL    swapTables
  2184.     )
  2185.     {
  2186.     int status = OK;
  2187.     if (fioRead (fd, pSym->n_name, sizeof(pSym->n_name)) 
  2188. != sizeof(pSym->n_name))
  2189. status = ERROR;
  2190.     if (swapTables && (status == OK))
  2191.         {
  2192.         /*  The n_name field is part of a union in the syment struct.
  2193.          *  If the union uses n_name (array of char), then no
  2194.          *  swabbing in required.
  2195.          *  If the union uses n_offset (into string table), then
  2196.          *  the n_offset must be swabbed.
  2197.          */
  2198.         if (pSym->n_zeroes == 0)
  2199.             {
  2200.             swabData(&pSym->n_offset, sizeof(pSym->n_offset));
  2201.             }
  2202.         }
  2203.      status |= fileRead (fd, &pSym->n_value, sizeof(pSym->n_value),
  2204.                         swapTables);
  2205.     status |= fileRead (fd, &pSym->n_scnum, sizeof(pSym->n_scnum),
  2206.                         swapTables);
  2207. #if (CPU_FAMILY == I960)
  2208.     status |= fileRead (fd, &pSym->n_flags, sizeof(pSym->n_flags),
  2209.                         swapTables);
  2210. #endif /* (CPU_FAMILY == I960) */
  2211.     status |= fileRead (fd, &pSym->n_type, sizeof(pSym->n_type),
  2212.                         swapTables);
  2213.     status |= fileRead (fd, &pSym->n_sclass, sizeof(pSym->n_sclass),
  2214.                         swapTables);
  2215.     status |= fileRead (fd, &pSym->n_numaux, sizeof(pSym->n_numaux),
  2216.                         swapTables);
  2217. #if (CPU_FAMILY == I960)
  2218.     status |= fileRead (fd, pSym->pad2, sizeof(pSym->pad2),
  2219.                         swapTables);
  2220. #endif /* (CPU_FAMILY == I960) */
  2221.     return(status);
  2222.     }
  2223. /*******************************************************************************
  2224. *
  2225. * coffReadExtSyms - read COFF symbols
  2226. *  For low memory systems, we can't afford to keep the entire
  2227. *  symbol table in memory at once.
  2228. *  For each symbol entry, the fields required for relocation
  2229. *  are saved in the externalSyms array.
  2230. */
  2231. LOCAL STATUS coffReadExtSyms
  2232.     (
  2233.     int fd,
  2234.     SYMENT **pSymbols,       /* pointer to array of symbol entries */
  2235.     char ***pSymAddr,          /* pointer to array of addresses */
  2236.     FILHDR *pHdr,
  2237.     BOOL    swapTables
  2238.     )
  2239.     {
  2240.     int status;
  2241.     int ix;
  2242.     SYMENT *pSym;                     /* pointer to symbol entry */
  2243.     if (pHdr->f_nsyms)
  2244.         {
  2245.         /*  malloc space for array of absolute addresses
  2246.          */
  2247.         if ((*pSymAddr = malloc((UINT)(pHdr->f_nsyms) * sizeof(char *)))
  2248.             == NULL)
  2249.     {
  2250.     printErr (extMemErrMsg, (UINT)(pHdr->f_nsyms) * sizeof (char *));
  2251.     return (ERROR);
  2252.     }
  2253.         /*  malloc space for symbols
  2254.          */
  2255.         if ((*pSymbols = malloc((UINT)(pHdr->f_nsyms) * SYMESZ))
  2256.             == NULL)
  2257.     {
  2258.     return (ERROR);
  2259.     }
  2260. if (lseek (fd, pHdr->f_symptr, SEEK_SET) == ERROR)
  2261.     {
  2262.     return (ERROR);
  2263.     }
  2264.         for (ix = 0, pSym = *pSymbols; ix < pHdr->f_nsyms; ix++, pSym++)
  2265.             {
  2266.             if ((status = coffReadSym(fd, pSym, swapTables) != OK))
  2267. return (status);
  2268.             }
  2269.       }
  2270.     return (OK);
  2271.     }
  2272. /*******************************************************************************
  2273. *
  2274. * coffReadExtStrings - read in COFF external strings
  2275. * Assumptions:  The file pointer is positioned at the start of the
  2276. * string table.
  2277. */
  2278. #define STR_BYTES_SIZE 4                /* size of string table length field */
  2279. LOCAL STATUS coffReadExtStrings
  2280.     (
  2281.     int fd,
  2282.     char **pStrBuf,
  2283.     BOOL    swapTables
  2284.     )
  2285.     {
  2286.     unsigned long strBytes;
  2287.     int status;
  2288.     /* Read length of string table
  2289.      */
  2290.     if ((status = fileRead (fd, &strBytes, STR_BYTES_SIZE, swapTables))
  2291.         != OK)
  2292.         {
  2293.         return (status);
  2294.         }
  2295.     if (strBytes > STR_BYTES_SIZE)
  2296.         {
  2297.         if ((*pStrBuf = malloc(strBytes)) == NULL)
  2298.     {
  2299.             printErr (stringMemErrMsg, strBytes);
  2300.     return (ERROR);
  2301.     }
  2302.         bcopy((char *) &strBytes, (char *) *pStrBuf, STR_BYTES_SIZE);
  2303.         strBytes -= STR_BYTES_SIZE;     /* # bytes left to read  */
  2304.     if (fioRead (fd, *pStrBuf + STR_BYTES_SIZE, strBytes) 
  2305. != strBytes)
  2306.     {
  2307.     return (ERROR);
  2308.     }
  2309.         }
  2310.     return (OK);
  2311.     }
  2312. /*******************************************************************************
  2313. *
  2314. * softSeek - seek forward into a file
  2315. *
  2316. * This procedure seeks forward into a file without actually using seek
  2317. * calls.  It is usefull since seek does not work on all devices.
  2318. *
  2319. * RETURNS:
  2320. * OK, or
  2321. * ERROR if forward seek could not be accomplished
  2322. *
  2323. */
  2324. #define SEEKBUF 1024
  2325. LOCAL STATUS softSeek
  2326.     (
  2327.     int fd, /* fd to seek with */
  2328.     int startOfFileOffset /* byte index to seek to */
  2329.     )
  2330.     {
  2331.     int position; /* present file position */
  2332.     int bytesToRead; /* bytes needed to read */
  2333.     char tempBuffer[SEEKBUF]; /* temp buffer for bytes */
  2334.     position = ioctl (fd, FIOWHERE, startOfFileOffset);
  2335.     if (position > startOfFileOffset)
  2336. return(ERROR);
  2337.     /* calculate bytes to read */
  2338.     bytesToRead = startOfFileOffset - position;
  2339.     while (bytesToRead >= SEEKBUF)
  2340. {
  2341.         if (fioRead (fd, tempBuffer, SEEKBUF) != SEEKBUF)
  2342.     return (ERROR);
  2343. bytesToRead -= SEEKBUF;
  2344. }
  2345.     if (bytesToRead > 0)
  2346. {
  2347.         if (fioRead (fd, tempBuffer, bytesToRead) != bytesToRead)
  2348.     return (ERROR);
  2349. }
  2350. #ifdef NO_COFF_SOFT_SEEK
  2351.     if (ioctl (fd, FIOSEEK, startOfFileOffset) == ERROR)
  2352.         return (ERROR);
  2353. #endif
  2354.     return(OK);
  2355.     }
  2356. /*******************************************************************************
  2357. *
  2358. * fileRead - loader file read function
  2359. */
  2360. LOCAL STATUS fileRead
  2361.     (
  2362.     int     fd,
  2363.     char    *pBuf,                      /* buffer to read data into */
  2364.     UINT    size,                       /* size of data field in bytes */
  2365.     BOOL    swap
  2366.     )
  2367.     {
  2368.     int     status = OK;
  2369.     if (fioRead (fd, pBuf, size) != size)
  2370.         {
  2371. errnoSet (S_loadLib_FILE_READ_ERROR);
  2372.         return(ERROR);
  2373.         }
  2374.     if (swap)
  2375.         {
  2376.         status = swabData(pBuf, size);
  2377.         }
  2378.     return(status);
  2379.     }
  2380. /*******************************************************************************
  2381. *
  2382. *  swabData - swap endianess of data field of any length
  2383. *
  2384. */
  2385. LOCAL STATUS swabData
  2386.     (
  2387.     char    *pBuf,                      /* buffer containing data */
  2388.     UINT    size                       /* size of data field in bytes */
  2389.     )
  2390.     {
  2391. #define TEMP_BUF_SIZE 256
  2392.     int     status = OK;
  2393.     char    tempBuf[TEMP_BUF_SIZE];
  2394.     switch(size)
  2395.         {
  2396.         case sizeof(char):
  2397.             break;                      /* ok as is */
  2398.         case sizeof(short):
  2399.             *(unsigned short *) pBuf = SWAB_SHORT(*(unsigned short *) pBuf);
  2400.             break;
  2401.         case sizeof(long):
  2402.             swabLong(pBuf, tempBuf);
  2403.             bcopy(tempBuf, pBuf, size);
  2404.             break;
  2405.         default:
  2406.             if (size <= TEMP_BUF_SIZE)
  2407.                 {
  2408.                 swab(pBuf, tempBuf, size);
  2409.                 bcopy(tempBuf, pBuf, size);
  2410.                 }
  2411.             else
  2412.                 status = ERROR;
  2413.             break;
  2414.         }
  2415.     return(status);
  2416.     }
  2417. /*******************************************************************************
  2418. *
  2419. *  swabLong - swap endianess of long word
  2420. *
  2421. */
  2422. LOCAL void swabLong
  2423.     (
  2424.     char input[],
  2425.     char output[]
  2426.     )
  2427.     {
  2428.     output[0] = input[3];
  2429.     output[1] = input[2];
  2430.     output[2] = input[1];
  2431.     output[3] = input[0];
  2432.     }
  2433. /*******************************************************************************
  2434. *
  2435. * coffTotalCommons - 
  2436. *  INTERNAL
  2437. *  All common external symbols are being tacked on to the end
  2438. *  of the BSS section.  This function determines the additional amount
  2439. *  of memory required for the common symbols.
  2440. *  
  2441. */
  2442. LOCAL ULONG coffTotalCommons
  2443.     (
  2444.     SYMENT *pSym,             /* pointer to external symbols */
  2445.     FAST int nEnts, /* # of entries in symbol table */
  2446.     ULONG startAddr             /* address to start from */
  2447.     )
  2448.     {
  2449.     int ix;
  2450.     ULONG alignBss; /* next boundry for common entry */
  2451.     int nbytes; /* bytes for alignment + data */
  2452.     int totalBytes = 0; /* total additional count for bss */
  2453.     int auxEnts = 0;                    /* auxiliary symbol entries to skip */
  2454.     /* calculate room for external commons in bss */
  2455.     alignBss = startAddr;
  2456.     for (ix = 0; ix < nEnts; ix++, pSym++)
  2457. {
  2458.         if (auxEnts)                    /* if this is an auxiliary entry */
  2459.             {
  2460.             auxEnts--;
  2461.             continue;                   /* skip it */
  2462.             }
  2463.         auxEnts = pSym->n_numaux;       /* # of aux entries for this symbol */
  2464. if (COFF_COMM(pSym))
  2465.     {
  2466.             nbytes = dataAlign(pSym->U_SYM_VALUE, alignBss)
  2467.                     + pSym->U_SYM_VALUE;
  2468.             totalBytes += nbytes;
  2469.             alignBss += nbytes;
  2470.             }
  2471. }
  2472.     return(totalBytes);
  2473.     }
  2474. /*******************************************************************************
  2475. *
  2476. *  dataAlign - determine address alignment for a data operand in memory
  2477. *  The address of a data operand must be correctly aligned for data access.
  2478. *  This is architecture dependent. 
  2479. *  Generally, data operands are aligned on 'natural' boundaries as follows:
  2480. *          bytes on byte boundaries (they already are)
  2481. *          half-word operands on half-word boundaries
  2482. *          word operands on word boundaries
  2483. *          double-word operands on double-word boundaries
  2484. *
  2485. *  However, if a structure of size = 7 had to be aligned, it would need
  2486. *  to be aligned on a boundary that is a multiple of 4 bytes.
  2487. *
  2488. *  RETURNS:
  2489. * nbytes - number of bytes to be added to the address to obtain the
  2490. *                 correct alignment for the data
  2491. */
  2492. LOCAL ULONG dataAlign
  2493.     (
  2494.     ULONG size,                         /* size of data to be aligned */
  2495.     ULONG addr                         /* next possible address for data */
  2496.     )
  2497.     {
  2498.     ULONG nbytes;                 /* # bytes for alignment */
  2499.     int align;                        /* address should be multiple of align */
  2500.     if (size <= 1)
  2501.         align = 1;
  2502.     else if (size < 4)
  2503.         align = 2;
  2504.     else if (size < 8)
  2505.         align = 4;
  2506.     else if (size < 16)
  2507.         align = 8;
  2508.     else
  2509.         align = MAX_ALIGNMENT;          /* max required alignment */
  2510.     nbytes = addr % align;
  2511.     if (nbytes != 0)                    /* if not on correct boundary */
  2512.         nbytes = align - nbytes;
  2513.     return(nbytes);
  2514.     }
  2515. /*******************************************************************************
  2516. *
  2517. * bootCoffModule - load an object module into memory
  2518. *
  2519. * This routine loads an object module in COFF format from the specified
  2520. * file, and places the code, data, and BSS at the locations specified within
  2521. * the file.  The entry point of the module is returned in <pEntry>.  This 
  2522. * routine is generally used for bootstrap loading.
  2523. *
  2524. * RETURNS:
  2525. * OK, or
  2526. * ERROR if the routine cannot read the file
  2527. *
  2528. * SEE ALSO: loadModuleAt()
  2529. */
  2530. STATUS bootCoffModule
  2531.     (
  2532.     int fd, /* fd from which to read load module */
  2533.     FUNCPTR *pEntry /* entry point of module */
  2534.     )
  2535.     {
  2536.     FILHDR hdr; /* module's COFF header */
  2537.     AOUTHDR optHdr;              /* module's COFF optional header */
  2538.     SCNHDR scnHdr[MAX_SCNS]; /* module's COFF section headers */
  2539.     int nBytes;
  2540.     int tablesAreLE;
  2541.     ULONG pos;
  2542.     char c;
  2543.     unsigned short idx;          /* index into section headers */
  2544.     /* read object module header */
  2545.     if (coffHdrRead (fd, &hdr, &tablesAreLE) != OK)
  2546. return (ERROR);
  2547.     /* read in optional header */
  2548.     if (coffOpthdrRead (fd, &optHdr, tablesAreLE) != OK)
  2549. return (ERROR);
  2550.     /* read in the section headers */
  2551.     if (coffSecHdrRead (fd, &scnHdr[0], &hdr, tablesAreLE) != OK)
  2552. return(ERROR);
  2553.     /*
  2554.      * Read until start of raw data for first section (to cope with stripped
  2555.      * ARM kernels).
  2556.      *
  2557.      * We can't do an ioctl FIOWHERE on a rcmd opened file descriptor
  2558.      * so must determine where we are by what we've read so far.
  2559.      * Note that this uses single-byte reads which are slow but should be OK.
  2560.      */
  2561.     for (pos = FILHSZ + AOUTSZ + hdr.f_nscns * SCNHSZ;
  2562.     pos < (ULONG)scnHdr[0].s_scnptr; ++pos)
  2563. if (nBytes = fioRead(fd, &c, 1), nBytes < 1)
  2564.     return ERROR;
  2565.     /* now read in the .text and .data sections (SPR #22452) */
  2566.     for (idx = 0; idx < hdr.f_nscns; idx++)
  2567.         {
  2568.         if ((scnHdr[idx].s_flags & STYP_TEXT) ||
  2569.             (scnHdr[idx].s_flags & STYP_LIT)  ||  /* Am29k only ? */
  2570.             (scnHdr[idx].s_flags & STYP_DATA)
  2571.            )
  2572.             {
  2573.             printf ("%ld + ", scnHdr[idx].s_size);
  2574.             nBytes = fioRead (fd, (char *) scnHdr[idx].s_vaddr, 
  2575.       scnHdr[idx].s_size);
  2576.             if (nBytes < scnHdr[idx].s_size)
  2577.                 {
  2578.                 return (ERROR);
  2579.                 }
  2580.             }
  2581.         }
  2582.     printf ("%ldn", optHdr.bsize);
  2583.     /*  bss is zeroed by vxWorks startup code. 
  2584.      */
  2585.     *pEntry = (FUNCPTR) optHdr.entry;
  2586.     return (OK);
  2587.     }
  2588. /******************************************************************************
  2589. *
  2590. * bootCoffInit - Initialize the system for coff load modules
  2591. *
  2592. * This routine initialized VxWorks to use the COFF format for
  2593. * boot loading modules.
  2594. *
  2595. * RETURNS:
  2596. * OK, or
  2597. * ERROR if XXX
  2598. *
  2599. * SEE ALSO: loadModuleAt()
  2600. */
  2601. STATUS bootCoffInit
  2602.     (
  2603.     )
  2604.     {
  2605.     /* XXX check for installed ? */
  2606.     bootLoadRoutine = bootCoffModule;
  2607.     return (OK);
  2608.     }