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

VxWorks

开发平台:

C/C++

  1. /* loadSomCoffLib.c - HP-PA SOM COFF object module loader */
  2. /* Copyright 1984-1994 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 02n,30nov98,dbt  no longer clear seg.flags<xxx> after loadSegmentAllocate()
  8.                  call. (SPR #23553).
  9. 02m,05oct98,pcn  Initialize all the fields in the SEG_INFO structure.
  10. 02l,16sep98,pcn  Set to SEG_ALIGN the flags field in seg structure
  11.                  (SPR #21836).
  12. 02k,19aug98,cym  Fixed SPR #22030: Target Loader won't load partially linked
  13.  objects.
  14. 02j,17jul98,pcn  Fixed SPR #21836: alignment mismatch between sections and
  15.                  target.
  16. 02i,01apr97,jmb  propagated an arg_reloc patch from the target server loader.
  17. 02h,14nov96,mem  rewrote handling of branch stubs in order to fix some
  18.  link problems.  Stubs now have the arg_reloc bits of the
  19.  symbol they represent stored with them, rather than
  20.  the bits of the call they where originally created with.
  21. 02g,02aug96,jmb  merged in ease patch (mem) for sign_ext.
  22. 02f,19dec95,mem  fixed fieldValue() function which did not always use the
  23.  roundConst value.
  24.  Modified section placement for GNU.
  25.  Fixed B{1,2,3,4} macros which had multiple uses of
  26.  pThisFixup++ in a single expression, (which is
  27.  undefined behavior).
  28. 02e,14nov94,kdl  removed conditional for CPU==SIMHPPA.
  29. 02d,09nov94,ms   made R_UNINIT fixup act just like R_ZEROS fixup.
  30. 02c,07nov94,kdl  merge cleanup - made conditional for CPU==SIMHPPA.
  31. 02b,02aug94,ms   cleaned up the code a bit.
  32. 02a,07jul94,ms   too many bug fixes to count. Major rewrite.
  33.                  Added "long branch stub" generation.
  34.                  Added "parameter relocation stub" generation
  35.                  Added "unwind" segment generation.
  36. 01g,03may94,ms   fixed the handling of R_PREV_FIXUP requests.
  37. 01f,02may94,ms   checked in yaos work. Added minor bug fix (bssFlag).
  38. 01e,18apr94,yao  added fileType paramater to rdSymtab().  changed to add
  39.                  DATA_SEGMENT_BASE to symbol of data type for shared 
  40.                  object files.
  41. 01d,28mar94,yao  changed to call lst operation routines in relSegments().
  42. 01c,28feb94,yao  added loadBssSizeGet () for relocatable files.  removed 
  43.                  macro STORE(), added routine fixBits() to deposit relocation 
  44.                  bits.  added fieldGetDefault(). added deassemble control 
  45.                  functions de_assemble_X(). added fixup rounding functions 
  46.                  X_fixup().
  47. 01c,02feb94,yao  included dsmLib.h.
  48. 01b,06dec93,gae  fixed warnings.
  49. 01a,12sep93,yao  written.
  50. */
  51. /*
  52. DESCRIPTION
  53. This library provides an object module loading facility for the
  54. HP-PA compiler environment.  Relocatable SOM COFF format files may be 
  55. loaded into memory, relocated, their external references resolved, 
  56. and their external definitions added to the system symbol table for use by 
  57. other modules and from the shell.  Modules may be loaded from any I/O stream
  58. which supports FIOSEEK.
  59. EXAMPLE
  60. .CS
  61.     fdX = open ("/devX/objFile", O_RDONLY);
  62.     loadModule (fdX, ALL_SYMBOLS);
  63.     close (fdX);
  64. .CE
  65. This code fragment would load the HP-PA SOM file "objFile" located on
  66. device "/devX/" into memory which would be allocated from the system
  67. memory pool.  All external and static definitions from the file would be
  68. added to the system symbol table.
  69. This could also have been accomplished from the shell, by typing:
  70. .CS
  71.     -> ld (1) </devX/objFile
  72. .CE
  73. INCLUDE FILE: loadSomCoffLib.h
  74. SEE ALSO: loadLib, usrLib, symLib, memLib,
  75. .pG "Basic OS"
  76. */
  77. /*
  78. INTERNAL
  79. The HP-PA SOM COFF linking loader is complicated as hell.
  80. This is due to a combination of the fact that the PA-RISC
  81. has a very un-RISC like instruction set, and that the
  82. calling conventions have a strange parameter passing mechanism.
  83. The following is an attempt to describe
  84. some of the differences between this loader and other VxWorks
  85. loaders.
  86. Subspace to segment mapping
  87. ---------------------------
  88. The current VxWorks paradigm assumes there are three "segments" -
  89. text, data, and bss. The SOM COFF format instead uses the concept
  90. of spaces and subspaces. There are two loadable spaces; text and data.
  91. Each of these spaces is divided into many subspaces.
  92. For example, each function is put in its own text subspace,
  93. and each global variable is put in its own data subspace.
  94. To fit the VxWorks paradigm we must map the subspaces into VxWorks segments.
  95. The routine subspaceToSegment() performs this function by looping through
  96. each subspace and deciding what segment to put it in. The array pSubInfo
  97. is initialized with information on each subspace: It's loadType (text,
  98. data, or bss), and it's loadAddr (we compute a relative load address for
  99. each subspace - it's final load address won't be know until we
  100. allocate memory for the text, data, and bss segments).
  101. Uninitailized global (but non-static) variables are treated by the
  102. compiler as "request for storage" (sometimes called "common data" or
  103. "weak externals"). All VxWorks loaders simply add these variables
  104. as bss, so we do likewise. The routine commSizeGet() computes the number
  105. of bytes needed for these variables, and this size is added to the bss size.
  106. This is more efficient than performing a malloc() for each variable,
  107. as is done in other VxWorks loaders.
  108. A "stack unwind" segment is also generated for the stack tracer to use.
  109. See src/arch/simhppa/trcLib.c for details.
  110. Long branch stubs
  111. -----------------
  112. When code is compiled with optimization, the compiler generates
  113. a PC-relative "BL" (branch and link) instruction for all procedure calls.
  114. The problem is that the displacement must fit into 19 bits, so if the
  115. called procedure is further than 256k bytes away, we have no way to
  116. fixup the instruction.
  117. The solution is to generate a two instruction "long branch stub",
  118. and make that stub the target of the "BL" instruction. It is our
  119. responsibility to generate this stub, and to make sure that the stub
  120. itself is close enough to the caller of "BL".
  121. For each text subspace, the procedure subspaceSizeExtra() computes
  122. the amount of space needed by that subspace for possible long branch stubs.
  123. Thus when we map the text subspaces to the "text segment", we actually leave
  124. a bit of room between each subspace according to the value of
  125. subspaceSizeExtra() for that subspace.
  126. Parameter relocation
  127. --------------------
  128. The PA-RISC passes the first four words of the parameter list in
  129. registers, and the return value also goes in a register.
  130. floating point parameters are passed in floating point registers,
  131. and other parameters are passed in general purpose registers.
  132. The problem is that the caller and the callee may not agree as
  133. to where the parameters are located. For example, printf() expects
  134. its parameters to be in the general purpose registers, whereas a call
  135. like
  136.    printf ("%f", myFloat)
  137. passes the second parameter in a floating point register.
  138. The compiler generates information on how a procedure expects
  139. to be called, and on how it is actually called. It is our job to
  140. make sure they match, and if they don't, to insert a "parameter
  141. relocation stub" between the caller and the callee.
  142. Parameter relocation information is encoded in 10 bits - 2 bits
  143. each for the first four arguments words and the return value.
  144. Each 2 bit quantity specifies "unused, general register, float
  145. register, or double persion float register".
  146. When a new function is loaded, the 10 bit relocation info generated
  147. by the compiler must be stored away in the VxWorks symbol table for
  148. future reference, In order to do this I had to
  149. create a new structure called "MY_SYMBOL", which is just like
  150. the VxWorks "SYMBOL", but has an extra 8 bit field at the end. It turns
  151. out that the size of MY_SYMBOL is the same as the size of SYMBOL
  152. because of compiler padding, so no harm was done. The functions
  153. externSymResolve() and externSymAdd() perform VxWorks symbol
  154. table manipulation with MY_SYMBOL stuctures.
  155. When a function is called, the 10 parameter relocation bits
  156. are encoded in the fixup request associated with the function call.
  157. The routines rbits1() and rbits2() get the bits from the fixup request
  158. (actually, the 10 bits are encoded in 9 or fewer bits in the fixup
  159. request, so rbits1() and rbits2() do some work to extract the info
  160. and decode it to 10 bits). We then compare the callers reclocation
  161. bits with the callees and if they differ, we may ned to generate
  162. a stub (if we hadn't previously generated a stub for that function).
  163. Currently, this is only done if the callee expects general registers
  164. and the caller passses a double - which takes care of functions
  165. like printf, sprintf, etc. The loader prints an error message if
  166. any other type of parameter reloction is needed. It would be easy to add
  167. other parameter relocation stubs at a later time.
  168. Fixup requests
  169. --------------
  170. The linking fixup requests are passed to us as a byte stream.
  171. The number of bytes in each fixup request depends on the
  172. fixup request, and there are 71 different types of fixup requests!
  173. The routine linkSubspaces() performs the linker fixup requests, and
  174. it is complicated as hell. The comments in that routine describe it further.
  175. just to give you an idea of how complicated our friends at HP have made
  176. things: The linker must keep a queue of the last four multi-byte
  177. fixup requests. There is a one byte fixup requests called "repeat
  178. previous fixup" which directs us to repeat one of the previous fixups
  179. from the queue, and then move the fixup to the front of the queue!
  180. Currently there are many branches in linkSubspaces() that have
  181. not been tested.
  182. */
  183. #include "vxWorks.h"
  184. #include "stdio.h"
  185. #include "som_coff.h"
  186. #include "ioLib.h"
  187. #include "dsmLib.h"
  188. #include "fioLib.h"
  189. #include "bootLoadLib.h"
  190. #include "loadLib.h"
  191. #include "loadSomCoffLib.h"
  192. #include "memLib.h"
  193. #include "pathLib.h"
  194. #include "lstLib.h"
  195. #include "string.h"
  196. #include "symLib.h"
  197. #include "sysSymTbl.h"
  198. #include "errnoLib.h"
  199. #include "stdlib.h"
  200. #include "symbol.h"
  201. #include "moduleLib.h"
  202. #include "cacheLib.h"
  203. #define LOAD_NONE   0
  204. #define LOAD_TEXT   1
  205. #define LOAD_DATA   2
  206. #define LOAD_BSS    3
  207. #define SEG_ALIGN  8
  208. /* Some PA-RISC opCodes */
  209. #define LDIL_CODE       0x08
  210. #define ADDIL_CODE      0x0a
  211. #define BL_CODE         0x3a
  212. #define COMBT_CODE      0x20
  213. #define COMBF_CODE      0x22
  214. #define ADDB_CODE       0x28
  215. #define ADDBF_CODE      0x2a
  216. #define BB_CODE         0x31
  217. #define LDW_CODE        0x12
  218. #define LDH_CODE        0x11
  219. #define LDB_CODE        0x10
  220. #define STW_CODE        0x1a
  221. #define STH_CODE        0x19
  222. #define STB_CODE        0x18
  223. #define LDWM_CODE       0x13
  224. #define STWM_CODE       0x1b
  225. #define LDO_CODE        0x0d
  226. #define ADDI_CODE       0x2d
  227. #define ADDIT_CODE      0x2c
  228. #define SUBI_CODE       0x25
  229. #define COMICKR_CODE    0x24
  230. #define ADDIBT_CODE     0x29
  231. #define ADDIBF_CODE     0x2b
  232. #define COMIBT_CODE     0x21
  233. #define COMIBF_CODE     0x23
  234. #define BE_CODE         0x38
  235. #define BLE_CODE        0x39
  236. /* some handy macros for linkSubspaces() */
  237. #define B1 (*(pThisFixup++))
  238. #define B2 ((int)(pThisFixup += 2), 
  239.     (int) ((pThisFixup[-2] << 8) + pThisFixup[-1]))
  240. #define B3 ((int)(pThisFixup += 3), 
  241.     (int) ((pThisFixup[-3] << 16) + (pThisFixup[-2] << 8) + pThisFixup[-1]))
  242. #define B4 ((int)(pThisFixup += 4), 
  243.     (int) ((pThisFixup[-4] << 24) + (pThisFixup[-3] << 16) 
  244.            + (pThisFixup[-2] << 8) + pThisFixup[-1]))
  245. #define REL_STACK_SIZE  (10000)   /* size of relocation stack pointer */
  246. #define POP_EXPR        (*--sp)
  247. #define PUSH_EXPR(x)    (*sp ++ = (x))
  248. #define CHECK_STACK_OVER  if (sp >= pExpStack + REL_STACK_SIZE) 
  249.                               { 
  250.                               printErr ("ld error: stack overflown");
  251.                               status = ERROR; 
  252.                               }
  253. #define CHECK_STACK_UNDER if (sp <= pExpStack) 
  254.                               { 
  255.                               printErr ("ld error: stack underflown");
  256.                               status = ERROR; 
  257.                               }
  258. #define FLAG_RESET(flag)  if (flag) flag = FALSE;
  259. /* subspace relocation info */
  260. typedef struct
  261.     {
  262.     char * loadAddr;
  263.     int loadType;
  264.     } SUB_INFO;
  265. /* "previous fixup" queue */
  266. typedef struct
  267.     {
  268.     NODE node;
  269.     UCHAR *pFixup;
  270.     } PREV_FIXUP;
  271. /* stack unwind structures */
  272. typedef struct
  273.     {
  274.     char *startAddr;
  275.     char *endAddr;
  276.     UINT word3;
  277.     UINT word4;
  278.     } UNWIND_DESC;
  279. typedef struct
  280.     {
  281.     NODE node;
  282.     UNWIND_DESC unwindDesc;
  283.     } UNWIND_NODE;
  284. /* list of long branch stubs */
  285. typedef struct stubListNode
  286.     {
  287.     NODE node;
  288.     int symNum;
  289.     int arg_reloc;
  290.     } STUB_LIST_NODE;
  291. /* list of argument relocation stubs */
  292. typedef struct
  293.     {
  294.     NODE     node;
  295.     SYMREC * pSym;
  296.     int      arg_reloc;
  297.     char *   stubAddr;
  298.     } ARG_RELOC_NODE;
  299. /* modified symbol table entry */
  300. typedef struct                  /* MY_SYMBOL - entry in symbol table */
  301.     {
  302.     SL_NODE     nameHNode;      /* hash node (must come first) */
  303.     char        *name;          /* pointer to symbol name */
  304.     char        *value;         /* symbol value */
  305.     UINT16      group;          /* symbol group */
  306.     SYM_TYPE    type;           /* symbol type */
  307.     UCHAR       arg_reloc;      /* relocation bits */
  308.     } MY_SYMBOL;
  309. /* local variables */
  310. /* SPR 22030: changed entry for fixup 62 from 0 to 1 */
  311. static int fixupLen [256] =
  312.     {
  313.     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 00 - 19 */
  314.     1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 2, 4, 2, 4, 1, 2, 4, 2, /* 20 - 39 */
  315.     4, 1, 2, 3, 5, 8, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, /* 40 - 59 */
  316.     5, 5, 1, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 5, 5, 0, 0, /* 60 - 79 */
  317.     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 80 - 99 */
  318.     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 4, 0, 0, 0, 0, 0, 0, /* 100 - 119 */
  319.     2, 4, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 120 - 139 */
  320.     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 140 - 159 */
  321.     2, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 2, 4, 1, 9, /* 160 - 179 */
  322.     6, 1, 1, 1, 1, 2, 4, 1, 1, 2, 3, 4, 1, 1, 1, 1, 1, 1, 1, 1, /* 180 - 199 */
  323.     1, 1, 2, 3, 4, 5, 1,12, 2, 5, 6, 1, 1, 1, 1, 1, 0, 0, 0, 0, /* 200 - 219 */
  324.     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 220 - 239 */
  325.     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0              /* 240 - 255 */
  326.     };
  327. static UINT longBranchStub[] =
  328.         {
  329.         0x20200000,     /* LDIL    0, r1 */
  330.         0xe0202002      /* BE,n    0(s4, r1) */
  331.         };
  332. static stubSize = 8;
  333. /* externals */
  334. extern low_sign_ext (int x, int len);
  335. extern sign_ext     (int x, int len);
  336. extern assemble_21  (int x);
  337. extern assemble_17  (int x, int y, int z);
  338. extern assemble_12  (int x, int y);
  339. extern sysMemTop    (void);
  340. /* forward static functions */
  341. /* The entry point to the loader */
  342. static MODULE_ID ldSomCoffMdlAtSym (int fd, int symFlag, char **ppText, 
  343.     char **ppData, char **ppBss, SYMTAB_ID symTbl);
  344. /* primary loader support functions */
  345. static void symbolNameSet (SYMREC *pSym, int nSyms, char *pSymStr,
  346.     SUBSPACE *pSubspace, int nSubs, char *pSpaceStr, SPACE *pSpace,
  347.     int nSpaces);
  348. static void subspaceToSegment (SOM_HDR *pHpHdr, UCHAR *pRelocCmds,
  349.     SUB_INFO *pSubInfo,
  350.     SPACE *pSpace, SUBSPACE *pSubspace, SYMREC *pSym,
  351.     SYMTAB_ID symTbl, int *pTextSize, int *pDataSize,
  352.     int *pBssSize);
  353. static int subspaceSizeExtra (UCHAR *pRelCmds, SUBSPACE *pSubspace,
  354.     SYMREC *pSym, int numSyms, SYMTAB_ID symTbl);
  355. static void subspaceNoReloc (SOM_HDR *pHpHdr,
  356.     SUB_INFO *  pSubInfo, SUBSPACE *  pSubspace);
  357. static void commSizeGet (SYMREC *pSym, int nEnts, SUBSPACE *pSubspace,
  358.     int *pCommSize);
  359. static STATUS rdSymtab (SYMREC * pSym, FAST int nEnts,
  360.     SUBSPACE *pSubspace, SUB_INFO *pSubInfo, int symFlag,
  361.     SYMTAB_ID symTbl, SYMREC **pSymGlobal, char *pComm, int group);
  362. static STATUS loadSubspaces (int fd, SOM_HDR *pHpHdr, SUB_INFO *pSubInfo, 
  363.     SUBSPACE *pSubspace, char *pText, char *pData, char *pBss);
  364. static STATUS linkSubspaces (UCHAR *pRelCmds, SUBSPACE *pScnHdr, 
  365.     int numSubspace, SUB_INFO *pSubInfo, SYMREC *pSym, int numSyms,
  366.     SYMTAB_ID pSymTab, SYMREC *pSymGlobal, MODULE_ID moduleId);
  367. /* Symbol table manipulation functions */
  368. static BOOL externSymResolve (SYMTAB_ID symTblId, char * name, SYMREC *pSym);
  369. static BOOL externSymAdd (SYMTAB_ID symTblId, char * name, char *value,
  370.     SYM_TYPE type, UINT16 group, UCHAR arg_reloc);
  371. /* "argument relocation stub" functions */
  372. static BOOL argRelocDiffer (int arg_reloc1, int arg_reloc2);
  373. static char *argRelocStubListFind (LIST *stubList, SYMREC *pSym,
  374.     int arg_reloc, MODULE_ID moduleId);
  375. static void rbitsShow (int rbits);
  376. static int  rbits1 (int x);
  377. static int  rbits2 (int x);
  378. /* "long branch stub" manipulation functions */
  379. static int stubListFind (LIST *stubList, int symNum, int arg_reloc);
  380. static int stubListAdd (LIST *stubList, int symNum, int arg_reloc);
  381. static void stubInit (char *stubAddr, char *procAddr);
  382. /* stack unwind manipulation functions */
  383. static void unwindListAdd (LIST *unwindList, UNWIND_NODE *pUnwindNode);
  384. static void unwindSegmentCreate (LIST *unwindList, MODULE_ID moduleId);
  385. int loadSomCoffDebug = 0;
  386. #define DBG_PUT if (loadSomCoffDebug == 1) printf
  387. int loadSomCoffWarn  = 0;
  388. #define WARN if (loadSomCoffWarn == 1) printf
  389. /*******************************************************************************
  390. *
  391. * loadSomCoffInit - initialize the system for HP-PA SOM COFF load modules
  392. *
  393. * This routine initialized VxWorks to use an extended HP-PA SOM COFF format for
  394. * loading modules.
  395. *
  396. * RETURNS: OK
  397. *
  398. * SEE ALSO: loadModuleAt()
  399. */
  400. STATUS loadSomCoffInit (void)
  401.     {
  402.     loadRoutine = (FUNCPTR) ldSomCoffMdlAtSym;
  403.     return (OK);
  404.     }
  405. /******************************************************************************
  406. *
  407. * ldSomCoffMdlAtSym - load object module into memory with symbol table
  408. *
  409. * This routine is the underlying routine to loadModuleAtSym().  This interface
  410. * allows specification of the the symbol table used to resolve undefined
  411. * external references and to which to add new symbols.
  412. *
  413. * RETURNS:
  414. * MODULE_ID, or
  415. * NULL if can't read file or not enough memory or illegal file format
  416. */  
  417. static MODULE_ID ldSomCoffMdlAtSym
  418.     (
  419.     FAST int  fd,        /* fd from which to read module */
  420.     int       symFlag,   /* symbols to be added to table 
  421.                           *   ([NO | GLOBAL | ALL]_SYMBOLS) */
  422.     char **   ppText,    /* load text segment at address pointed to by this
  423.                           * pointer, return load address via this pointer */
  424.     char **   ppData,    /* load data segment at address pointed to by this
  425.                           * pointer, return load address via this pointer */
  426.     char **   ppBss,     /* load bss segment at address pointed to by this
  427.                           * pointer, return load address via this pointer */
  428.     SYMTAB_ID symTbl     /* symbol table to use */
  429.     )
  430.     {
  431.     char *    pText = (ppText == NULL) ? LD_NO_ADDRESS : *ppText;
  432.     char *    pData = (ppData == NULL) ? LD_NO_ADDRESS : *ppData;
  433.     char *    pBss  = (ppBss  == NULL) ? LD_NO_ADDRESS : *ppBss;
  434.     char *    pComm;
  435.     int       textSize;
  436.     int       dataSize;
  437.     int       bssSize;
  438.     int       commSize;         /* gets added to bssSize */
  439.     int       status = ERROR; /* function return value */
  440.     SEG_INFO  seg;                      /* file segment info */
  441.     char      fileName[255]; /* file being loaded */
  442.     UINT16    group; /* loader group */
  443.     MODULE_ID moduleId; /* module ID */
  444.     SOM_HDR   somHdr;                   /* SOM header */
  445.     SPACE *   pSpace = NULL;            /* space dictionary */
  446.     int       spaceSize;                /* number of spaces */
  447.     SUBSPACE *pSubspace = NULL; /* subspace dictionary */
  448.     int       subspaceSize; /* number of subspaces */
  449.     char *    pSpaceStrings = NULL; /* space/subspace names */
  450.     SYMREC *  pSymBuf = NULL;           /* symbol record dictionary */
  451.     int       symBufSize;               /* number of symbols */
  452.     char *    pSymStr = NULL;           /* symbol names */
  453.     FIXUP *   pReloc = NULL; /* linker fixup requests */
  454.     int       relSize;                 /* size of fixup requests */
  455.     SUB_INFO *pSubInfo = NULL; /* subspace load info */
  456.     SYMREC *  pGlobal = NULL; /* the symbol "$global$" */
  457.     /* initialization */
  458.     memset ((void *)&seg, 0, sizeof (seg));
  459.     /* Get the name of the file we are loading */
  460.     if (ioctl (fd, FIOGETNAME, (int) fileName) == ERROR)
  461.         {
  462.         printErr ("ldSomCoffMdlAtSym: can't get filenamen");
  463.         return (NULL);
  464.         }
  465.     
  466.     if ((moduleId = loadModuleGet (fileName, MODULE_ECOFF, &symFlag)) == NULL)
  467.         return (NULL);
  468.     group = moduleId->group;
  469.     /* read the SOM header */
  470.     bzero ((char *) &somHdr, sizeof(SOM_HDR));
  471.     if (read (fd, (char *)&somHdr, sizeof (SOM_HDR)) != sizeof(SOM_HDR))
  472.         {
  473.         errno = S_loadSomCoffLib_HDR_READ;
  474.         goto error;
  475.         }
  476.     /* check object file type - only relocatable and executable are supported */
  477.     if (somHdr.a_magic != RELOC_MAGIC &&
  478.         somHdr.a_magic != EXEC_MAGIC &&
  479.         somHdr.a_magic != SHARE_MAGIC)
  480.         {
  481.         printErr ("ldSomCoffMdlAtSym: bad magic #%#xn", somHdr.a_magic);
  482.         errno = S_loadSomCoffLib_OBJ_FMT;
  483.         goto error;
  484.         }
  485.     /* read in space dictionary */
  486.     if (somHdr.space_total != 0)
  487.         {
  488.         spaceSize=somHdr.space_total*sizeof(struct space_dictionary_record);
  489.         if ((pSpace = calloc (1, spaceSize)) == NULL)
  490.             {
  491.             errno = S_loadSomCoffLib_SPHDR_ALLOC;
  492.             goto error;
  493.             }
  494.         if (ioctl (fd, FIOSEEK, somHdr.space_location) == ERROR ||
  495.             read (fd, (char*)pSpace, spaceSize) != spaceSize)
  496.             {
  497.             errno = S_loadSomCoffLib_SPHDR_READ;
  498.             goto error;
  499.             }
  500.         }
  501.     /* read in subspace dictionary */
  502.     if (somHdr.subspace_total != 0)
  503.         {
  504.         subspaceSize = somHdr.subspace_total * SBPSZ;
  505.         if ((pSubspace = calloc (1, subspaceSize)) == NULL)
  506.             {
  507.             errno = S_loadSomCoffLib_SUBSPHDR_ALLOC;
  508.             goto error;
  509.             }
  510.         if (ioctl (fd, FIOSEEK, somHdr.subspace_location) == ERROR ||
  511.             read (fd, (char*)pSubspace, subspaceSize) != subspaceSize)
  512.             {
  513.             errno = S_loadSomCoffLib_SUBSPHDR_READ;
  514.             goto error;
  515.             }
  516.         }
  517.     /* read in space string table */
  518.     if (somHdr.space_strings_size != 0)
  519.         {
  520.         if ((pSpaceStrings = (char *) calloc (1, somHdr.space_strings_size)) ==
  521.              NULL)
  522.             {
  523.             errno = S_loadSomCoffLib_SPSTRING_ALLOC;
  524.             goto error;
  525.             }
  526.         if (ioctl (fd, FIOSEEK, somHdr.space_strings_location) == ERROR ||
  527.             read (fd, pSpaceStrings, somHdr.space_strings_size) != 
  528.                      somHdr.space_strings_size)
  529.             {
  530.             errno = S_loadSomCoffLib_SPSTRING_READ;
  531.             goto error;
  532.             }
  533.         }
  534.     if (somHdr.subspace_total != 0)
  535.         {
  536.         if ((pSubInfo = (SUB_INFO *) calloc (1, sizeof(SUB_INFO) *
  537.                                             somHdr.subspace_total)) == NULL)
  538.             {
  539.             errno = S_loadSomCoffLib_INFO_ALLOC;
  540.             goto error;
  541.             }
  542.         }
  543.     else
  544.         {
  545.         pSubInfo = (SUB_INFO *) calloc (1, sizeof(SUB_INFO)); 
  546.         }
  547.     /* read in symbol table */
  548.     symBufSize = somHdr.symbol_total * sizeof (SYMREC);
  549.     if ((pSymBuf = (SYMREC *) calloc (1, symBufSize)) == NULL)
  550.         {
  551.         errno = S_loadSomCoffLib_SYM_READ;
  552.         goto error;
  553.         }
  554.     if (ioctl (fd, FIOSEEK, somHdr.symbol_location) == ERROR)
  555.         {
  556.         errno = S_loadSomCoffLib_SYM_READ;
  557.         goto error;
  558.         }
  559.     if (read (fd, (char *) pSymBuf, symBufSize) != symBufSize)
  560.         {
  561.         errno = S_loadSomCoffLib_SYM_READ;
  562.         goto error;
  563.         }
  564.     /* read in symbol string table */
  565.     if ((pSymStr = calloc (1, somHdr.symbol_strings_size)) == NULL)
  566.         {
  567.         errno = S_loadSomCoffLib_SYMSTR_READ;
  568.         goto error;
  569.         }
  570.     if (ioctl (fd, FIOSEEK,somHdr.symbol_strings_location) == ERROR ||
  571.         read (fd, pSymStr, somHdr.symbol_strings_size) != 
  572.                  somHdr.symbol_strings_size)
  573.         {
  574.         errno = S_loadSomCoffLib_SYMSTR_READ;
  575.         goto error;
  576.         }
  577.     /* read in linker fixup requests */
  578.     if (somHdr.fixup_request_total != 0)
  579.         {
  580.         relSize = (int)somHdr.fixup_request_total;
  581.         if ((pReloc = (FIXUP *) calloc (1, relSize)) == NULL)
  582.             {
  583.             errno = S_loadSomCoffLib_RELOC_ALLOC;
  584.             goto error;
  585.             }
  586.         if (ioctl (fd, FIOSEEK, somHdr.fixup_request_location) == ERROR ||
  587.             read (fd, (char*)pReloc, relSize) != relSize)
  588.             {
  589.             errno = S_loadSomCoffLib_RELOC_READ;
  590.             goto error;
  591.             }
  592.         }
  593.     /* make each symbol, space, and subspace point to its name string */
  594.     symbolNameSet (pSymBuf, somHdr.symbol_total, pSymStr,
  595.                    pSubspace, somHdr.subspace_total, pSpaceStrings,
  596.                    pSpace, somHdr.space_total);
  597.     /* We don't really load non-relocatable files.
  598.      * Since VxWorks.sym is non-relocatable, we
  599.      * allow non-relocatable files to have their
  600.      * symbols added to the symbol table, without any loading */
  601.     if (somHdr.a_magic != RELOC_MAGIC)
  602.         {
  603.         /* process subspace addresses with no relocation */
  604.         subspaceNoReloc (&somHdr, pSubInfo, pSubspace);
  605.         /* read in the symbol table */
  606.         status = rdSymtab (pSymBuf, somHdr.symbol_total, pSubspace,
  607.                            pSubInfo, symFlag, symTbl, &pGlobal,
  608.                            NULL, group);
  609.         goto done;
  610.         }
  611.     /* 
  612.      * Loaded code won't work if VxWorks was linked without the "-N" flag.
  613.      * However VxWorks itself will work - so we put this check after
  614.      * allowing VxWorks to load it's symbol table
  615.      */
  616.     if (sysMemTop() > 0x40000000)
  617.         {
  618.         printErr ("n");
  619.         printErr ("load error: VxWorks wasn't linked with the "-N" flagn");
  620.         printErr ("Please read the "source debugging" section of then");
  621.         printErr ("VxSim Users Guide for detailsn");
  622.         printErr ("n");
  623.         goto error;
  624.         }
  625.     /* Map SOM subspaces to VxWorks "segments", and get the segment sizes */
  626.     subspaceToSegment (&somHdr, (UCHAR *)pReloc, pSubInfo,
  627.         pSpace, pSubspace, pSymBuf, symTbl, &textSize, &dataSize,
  628.         &bssSize);
  629.     /* Allocate memory for text, data, and bss. We must be careful
  630.      * to align everything, since loadSegmentsAllocate() will
  631.      * put all segemnts in one block */
  632.     seg.addrText = pText;
  633.     seg.addrData = pData;
  634.     seg.addrBss  = pBss;
  635.     seg.sizeText = ROUND_UP(textSize, SEG_ALIGN);
  636.     seg.sizeData = ROUND_UP(dataSize, SEG_ALIGN);
  637.     seg.sizeBss  = ROUND_UP(bssSize, SEG_ALIGN);
  638.     /* 
  639.      * SPR #21836: pSeg->flagsText, pSeg->flagsData, pSeg->flagsBss are used
  640.      * to save the max value of each segments. These max values are computed
  641.      * for each sections. These fields of pSeg are only used on output, then
  642.      * a temporary use is allowed.
  643.      */
  644.     seg.flagsText = SEG_ALIGN;
  645.     seg.flagsData = SEG_ALIGN;
  646.     seg.flagsBss  = SEG_ALIGN;
  647.     commSizeGet (pSymBuf, somHdr.symbol_total,
  648.                     pSubspace, (int *)&commSize);
  649.     seg.sizeBss += ROUND_UP(commSize, SEG_ALIGN);
  650.     DBG_PUT ("bssSize = 0x%x, commSize = 0x%xn", bssSize, commSize);
  651.     /* 
  652.      * SPR #21836: loadSegmentsAllocate() allocate memory aligned on 
  653.      * the max value of sections alignement saved in seg.flagsText,
  654.      * seg.flagsData, seg.flagsBss.
  655.      */
  656.     if (loadSegmentsAllocate (&seg) != OK)
  657.         {
  658.         printErr ("Could not allocate segmentsn");
  659.         goto error;
  660.         }
  661.     /*
  662.      * make sure all allocated segments are aligned OK.
  663.      * This will always be true if the memory is malloc'ed,
  664.      * since SEG_ALIGN, and _MEM_ALIGN, and the maximum
  665.      * possible subspace alignment are all "8"
  666.      */
  667.     pText = (char *) ROUND_UP (seg.addrText, SEG_ALIGN);
  668.     pData = (char *) ROUND_UP (seg.addrData, SEG_ALIGN);
  669.     pBss  = (char *) ROUND_UP (seg.addrBss, SEG_ALIGN);
  670.     pComm = (char *) ((int)pBss + seg.sizeBss
  671.                       - ROUND_UP(commSize, SEG_ALIGN));
  672.     if ( (pText != seg.addrText) ||
  673.          (pData != seg.addrData) ||
  674.          (pBss  != seg.addrBss) )
  675.         {
  676.         printErr ("loadModuleAtSym: segment alignment errorn");
  677.         goto error;
  678.         }
  679.     DBG_PUT ("pText = 0x%x, pData = 0x%x, pBss = 0x%x pComm = 0x%xn",
  680.              (int)pText, (int)pData, (int)pBss, (int)pComm);
  681.     DBG_PUT ("sizeText = 0x%x, sizeData = 0x%x, sizeBss = 0x%xn",
  682.              seg.sizeText, seg.sizeData, seg.sizeBss);
  683.     /* load all subspaces into memory */
  684.     if (loadSubspaces (fd, &somHdr, pSubInfo, pSubspace, pText, pData, pBss)
  685.                       != OK)
  686.         {
  687.         errno = S_loadSomCoffLib_LOAD_SPACE;
  688.         goto error;
  689.         }
  690.     /* add segment names to symbol table before other symbols */
  691.     if (!(symFlag & LOAD_NO_SYMBOLS))
  692.         addSegNames (fd, pText, pData, pBss, symTbl, group);
  693.     /* process symbol table */
  694.     status = rdSymtab (pSymBuf, somHdr.symbol_total, pSubspace,
  695.                        pSubInfo, symFlag, symTbl, &pGlobal, pComm, group);
  696.     /* Perform linker fixup requests on the subspaces */
  697.     if (somHdr.version_id == NEW_VERSION_ID)
  698.         {
  699.         if (somHdr.fixup_request_total != 0)
  700.             (void) linkSubspaces ((UCHAR *) pReloc, pSubspace, 
  701.                                    somHdr.subspace_total, pSubInfo, pSymBuf, 
  702.                                    somHdr.symbol_total,
  703.                                    symTbl, pGlobal, moduleId);
  704.         }
  705.     else
  706.         {
  707.         errno = S_loadSomCoffLib_RELOC_VERSION;
  708.         goto error;
  709.         }
  710.     /* return load addresses, where called for */
  711.     if (ppText != NULL)
  712.         *ppText = pText;
  713.     if (ppData != NULL)
  714.         *ppData = pData;
  715.     if (ppBss != NULL)
  716.         *ppBss = pBss;
  717.     /* clear out bss */
  718.     bzero (pBss, (int) seg.sizeBss);
  719.     /* flush text to memory */
  720.     CACHE_TEXT_UPDATE (pText, seg.sizeText);
  721.     /*
  722.      * Add the segments to the module.
  723.      * This has to happen after the relocation gets done.
  724.      * If the relocation happens first, the checksums won't be
  725.      * correct.
  726.      */
  727.     moduleSegAdd (moduleId, SEGMENT_TEXT, pText, seg.sizeText, seg.flagsText);
  728.     moduleSegAdd (moduleId, SEGMENT_DATA, pData, seg.sizeData, seg.flagsData);
  729.     moduleSegAdd (moduleId, SEGMENT_BSS, pBss, seg.sizeBss, seg.flagsBss);
  730.                 
  731.     /* error:
  732.      * clean up dynamically allocated temporary buffers and return ERROR */
  733. error:
  734. done:
  735.     if (pSubInfo != NULL)
  736.         free ((char *) pSubInfo);
  737.     if (pSpaceStrings != NULL)
  738.         free ((char *) pSpaceStrings);
  739.     if (pSpace!= NULL)
  740.         free ((char *) pSpace);
  741.     if (pSubspace!= NULL)
  742.         free ((char *) pSubspace);
  743.     if (pSymBuf != NULL)
  744.         free ((char *) pSymBuf);
  745.     if (pSymStr != NULL)
  746.         free ((char *) pSymStr);
  747.     if (pReloc!= NULL)
  748.         free ((char *) pReloc);
  749.     if (status == OK)
  750.         return (moduleId);
  751.     else
  752.         {
  753.         moduleDelete (moduleId);
  754.         return (NULL);
  755.         }
  756.     }
  757. /******************************************************************************
  758. *
  759. * symbolNameSet - make all symbols records point to their name strings
  760. */ 
  761.  
  762. static void symbolNameSet
  763.     (
  764.     SYMREC *   pSym,           /* pointer to symbol table */
  765.     int        nSyms,          /* # of entries in symbol table */
  766.     char *     pSymStr,        /* pointer to symbol string table */
  767.     SUBSPACE * pSubspace,      /* pointer to subspace dictionary */
  768.     int        nSubs,          /* number of subspaces */
  769.     char *     pSpaceStr,      /* pointer to space name string table */
  770.     SPACE *    pSpace,        /* pointer to space dictionary */
  771.     int        nSpaces        /* number of spaces */
  772.     )
  773.     {
  774.     int ix;
  775.     for (ix = 0; ix < nSyms; ix++)
  776.         pSym[ix].symbol_name = pSymStr + pSym[ix].name.n_strx;
  777.     for (ix = 0; ix < nSubs; ix++)
  778.         pSubspace[ix].subspace_name = pSpaceStr + pSubspace[ix].name.n_strx;
  779.     for (ix = 0; ix < nSpaces; ix++)
  780.         pSpace[ix].space_name = pSpaceStr + pSpace[ix].name.n_strx;
  781.     }
  782. /*******************************************************************************
  783. *
  784. * commSizeGet - this routine go through the symbol table to calculate the 
  785. *                  size of STORAGE data for relocatable files
  786. *
  787. * STORAGE requests (i.e., "common data") are simply turned into BSS
  788. * by this loader (and all other VxWorks loaders). The loader adds
  789. * an area for these symbols by increasing the normal BSS area.
  790. * This allows us to not have to malloc memory for each STORAGE symbol.
  791. *
  792. * As a side effect, all the STORAGE symbols are partially relocated.
  793. * That is - the symbol_value field of the symbols SYMREC structure
  794. * is turned into an offset from the start of the STORAGE segment
  795. */
  796. static void commSizeGet
  797.     (
  798.     SYMREC * pSymBuf,              /* symbol dictionary */
  799.     int      nEnts,                /* number of symbols */
  800.     SUBSPACE *pSubspace,           /* subspace relocation info */
  801.     int *    pCommSize             /* where to return comm size */
  802.     )
  803.     {
  804.     SYMREC * pSym = pSymBuf;
  805.     int      size =  0;
  806.     int      subspaceIndex;
  807.     int      ix;
  808.     int      iy;
  809.     SYMREC * pSearch;
  810.     int      symSize;
  811.     for (ix = 0; ix < nEnts; ix ++)
  812.         {
  813.         if (pSym->symbol_type == ST_STORAGE)
  814.             {
  815.             pSearch = pSymBuf;
  816.             /* XXX - search for the previous record for same symbol
  817.              * in symbol table. For some reason STORAGE symbols
  818.              * sometime appear in pairs.
  819.              */
  820.             for (iy = 0; iy < ix; iy ++)
  821.                 {
  822.                 if (strcmp(pSym->symbol_name, pSearch->symbol_name) == 0)
  823.                     break;
  824.                 pSearch ++;
  825.                 }
  826.             /* deal with a new storage symbol */
  827.             if (iy == ix)
  828.                 {
  829.                 subspaceIndex = pSym->symbol_info;
  830.                 size = ROUND_UP (size, pSubspace[subspaceIndex].alignment);
  831.                 symSize = pSym->symbol_value;
  832.                 pSym->symbol_value = size;
  833.                 size += symSize;
  834.                 pSym->secondary_def = 0;
  835.                 }
  836.             /* duplicate storage symbol */
  837.             else
  838.                 {
  839.                 pSym->secondary_def = 1;
  840.                 }
  841.             }
  842.         pSym ++;
  843.         }
  844.     *pCommSize = size;
  845.     }
  846. /*******************************************************************************
  847. *
  848. * rdSymtab - Process the VxWorks symbol table
  849. *
  850. * This is passed a pointer to an HP-PA SOM symbol table and processes
  851. * each of the external symbols defined therein.  This processing performs
  852. * two functions:
  853. *  1) New symbols are entered in the system symbol table as
  854. *     specified by the "symFlag" argument:
  855. *        ALL_SYMBOLS    = all defined symbols (LOCAL and GLOBAL) are added,
  856. *        GLOBAL_SYMBOLS = only external (GLOBAL) symbols are added,
  857. *        NO_SYMBOLS     = no symbols are added;
  858. *  2) Undefined externals are looked up in the system table.
  859. *     If an undefined external cannot be found in the symbol table,
  860. *     an error message is printed, but ERROR is not returned until the entire
  861. *     symbol table has been read, which allows all undefined externals to be
  862. *     reported.
  863. *
  864. * Absolute symbols are automatically discarded.
  865. *
  866. * RETURNS: OK or ERROR
  867. */
  868. static STATUS rdSymtab 
  869.     (
  870.     SYMREC *   pSymBuf, /* pointer to symbol table */
  871.     FAST int   nEnts,           /* # of entries in symbol table */
  872.     SUBSPACE * pSubspace,       /* pointer to subspace dictionary */
  873.     SUB_INFO * pSubInfo,        /* subspace relocation info */
  874.     int        symFlag,         /* symbols to be added to table 
  875.                                  *   ([NO|GLOBAL|ALL]_SYMBOLS) */
  876.     SYMTAB_ID  symTbl,          /* symbol table to use */
  877.     SYMREC **  pSymGlobal,      /* '$global$' symbol entry pointer */
  878.     char *     pComm,           /* start of comm area (within bss segment) */
  879.     int        group            /* symbol group */
  880.     )
  881.     {
  882.     char *   name;              /* symbol name (plus EOS) */
  883.     SYMREC * pSym = (SYMREC *) pSymBuf;  /* symbol entry pointer */
  884.     int      ix; /* symbols subspace index */
  885.     SYM_TYPE vxSymType;         /* symbol type */
  886.     UCHAR    arg_reloc; /* argument relocation info */
  887.     int      status  = OK;      /* return status */
  888.     *pSymGlobal = NULL;
  889.     for (; nEnts > 0; nEnts -= 1, pSym ++)
  890.         {
  891.         /* throw away absolute symbols */
  892.         if (pSym->symbol_type == ST_ABSOLUTE)
  893.             continue;
  894.         /* throw away symbol and argument extentions */
  895.         if (pSym->symbol_type == ST_SYM_EXT)
  896.             continue;
  897.         if (pSym->symbol_type == ST_ARG_EXT)
  898.             continue;
  899.         /* throw away invalid symbols */
  900.         if (pSym->symbol_type == ST_NULL)
  901.             continue;
  902.         /* get the symbol name */
  903.         name = pSym->symbol_name;
  904.         /* keep the symbol $global$ handy */
  905.         if ( (pSym->symbol_type == ST_DATA) && (!strcmp(name, "$global$")) )
  906.             *pSymGlobal = pSym;
  907.         if (!pSubspace[pSym->symbol_info].is_loadable)
  908.             WARN ("Warning: symbol %s is unloadable!n", name);
  909.         if (pSym->must_qualify)
  910.             WARN ("Warning: symbol %s must qualify!n", name);
  911.         if (pSym->is_common || pSym->dup_common)
  912.             WARN ("Warning: symbol %s is a common block!n", name);
  913.         /* add new symbols to the symbol table */
  914.         if ((pSym->symbol_scope == SS_UNIVERSAL) ||
  915.             (pSym->symbol_scope == SS_LOCAL))
  916.             {
  917.             /* relocate the symbol relative to it's associated subspace */
  918.             ix = pSym->symbol_info;
  919.             pSym->symbol_value = pSym->symbol_value
  920.                                  - pSubspace[ix].subspace_start
  921.                                  + (unsigned int)pSubInfo[ix].loadAddr;
  922.             switch (pSym->symbol_type)
  923.                 {
  924.                 /* Data or BSS symbols */
  925.                 case ST_DATA:
  926.                     if (pSubInfo[ix].loadType == LOAD_BSS)
  927.                         {
  928.                         vxSymType = N_BSS;
  929.                         DBG_PUT ("new BSS symbol %s (0x%x)n", name,
  930.                                  pSym->symbol_value);
  931.                         }
  932.                     else
  933.                         {
  934.                         vxSymType = N_DATA;
  935.                         DBG_PUT ("new DATA symbol %s (0x%x)n", name, 
  936.                                  pSym->symbol_value);
  937.                         }
  938.                     arg_reloc = 0;
  939.                     break;
  940.                 /* Text symbols */
  941.                 case ST_CODE:
  942.                 case ST_PRI_PROG:
  943.                 case ST_SEC_PROG:
  944.                 case ST_MILLICODE:
  945.                 case ST_ENTRY:
  946.                     vxSymType = N_TEXT | ((UCHAR)(pSym->arg_reloc & 3) << 6);
  947.                     arg_reloc = (UCHAR)(pSym->arg_reloc >> 2);
  948.                     pSym->symbol_value &= 0xfffffffc;
  949.                     break;
  950.                 /* ignore stubs */
  951.                 case ST_STUB:
  952.                     continue;
  953.                 /* These have never popped up yet */
  954.                 case ST_MODULE:
  955.                 case ST_PLABEL:
  956.                 case ST_OCT_DIS:
  957.                 case ST_MILLI_EXT:
  958.                 default:
  959.                     WARN ("Warning: symbol %s is of type %dn", 
  960.                               name, pSym->symbol_type);
  961.                     continue;
  962.                 }
  963.             if ( (pSym->symbol_scope == SS_UNIVERSAL) && (!pSym->hidden) )
  964.                 vxSymType |= N_EXT;
  965.             if ( ((symFlag & LOAD_LOCAL_SYMBOLS) && !(vxSymType & N_EXT)) ||
  966.                 ((symFlag & LOAD_GLOBAL_SYMBOLS) && (vxSymType & N_EXT)) )
  967.                 {
  968.                 DBG_PUT ("adding symbol %s to symTbln", name);
  969.                 if (externSymAdd (symTbl, name, (char*)pSym->symbol_value,
  970.                             vxSymType, group, arg_reloc) != OK)
  971.                     {
  972.                     printErr ("can't add symbol %s (errno=%#x)n",
  973.                                 name, errnoGet());
  974.                     }
  975.                 }
  976.             }
  977.         /* Add STORAGE (common) symbols as BSS */
  978.         else if (pSym->symbol_type == ST_STORAGE)
  979.             {
  980.             if (pSym->secondary_def)
  981.                 continue;
  982.             vxSymType = N_BSS | N_EXT;
  983.             pSym->symbol_value += (unsigned int)pComm;
  984.             DBG_PUT ("new STORAGE symbol %s (0x%x)n", name,
  985.                      pSym->symbol_value);
  986.             if (externSymAdd (symTbl, name, (char*)pSym->symbol_value,
  987.                 vxSymType, group, 0) != OK)
  988.                 {
  989.                 printErr ("can't add symbol %s (errno=%#x)n",
  990.                             name, errnoGet());
  991.                 }
  992.             }
  993.         /* look up external symbols */
  994.         else
  995.             {
  996.             if (externSymResolve (symTbl, name, pSym) != OK)
  997.                 {
  998.                 printErr ("undefined symbol: %sn", name);
  999.                 status = ERROR;
  1000.                 }
  1001.             }
  1002.         }
  1003.     DBG_PUT ("done with rdSymtabn");
  1004.     return (status);
  1005.     }
  1006. /*******************************************************************************
  1007. *
  1008. * de_assemble_21 - encode a 21 bit immediate.
  1009. *
  1010. * The PA-RISC encode immediate values in the instruction word in bizaar
  1011. * ways. See the PA-RISC architecture manual for details.
  1012. */
  1013. static int de_assemble_21
  1014.     (
  1015.     unsigned int x
  1016.     )
  1017.     {
  1018.     return ((x & 0x100000) >> 20 | (x & 0xffe00) >> 8 |
  1019.             (x & 0x180) << 7  | ( x & 0x7c) << 14 | (x & 0x3) << 12);
  1020.     }
  1021. /*******************************************************************************
  1022. *
  1023. * de_assemble_17 - encode a 17 bit immediate.
  1024. *
  1025. * The PA-RISC encode immediate values in the instruction word in bizaar
  1026. * ways. See the PA-RISC architecture manual for details.
  1027. */
  1028. static int de_assemble_17 
  1029.     (
  1030.     unsigned int x
  1031.     )
  1032.     {
  1033.     return ((x & 0x10000) >> 16 | (x & 0xf800) << 5 | (x & 0x400) >> 8 |
  1034.             (x & 0x3ff) << 3);
  1035.     }
  1036. /*******************************************************************************
  1037. *
  1038. * de_assemble_12 - encode a 12 bit immediate.
  1039. *
  1040. * The PA-RISC encode immediate values in the instruction word in bizaar
  1041. * ways. See the PA-RISC architecture manual for details.
  1042. */
  1043. static int de_assemble_12
  1044.     (
  1045.     unsigned  int x
  1046.     )
  1047.     {
  1048.     return ((x & 0x800) >> 11 | (x & 0x400) >> 8 | (x & 0x3ff) << 3);
  1049.     }
  1050. /*******************************************************************************
  1051. *
  1052. * de_low_sign_ext - encode a sign extended immediate of length len
  1053. *
  1054. * The PA-RISC encode immediate values in the instruction word in bizaar
  1055. * ways. See the PA-RISC architecture manual for details.
  1056. */
  1057. static int de_low_sign_ext
  1058.     (
  1059.     int x,
  1060.     int len
  1061.     )
  1062.     {
  1063.     int tmp;
  1064.     if (len > 32)
  1065.         return (x);
  1066.     tmp = x & ((1 << len) - 1);
  1067.     return ((tmp & ((1 << (len - 1)))) >> (len - 1) |
  1068.             ((tmp & ((1 << (len -1)) - 1)) << 1));
  1069.     }
  1070. /*******************************************************************************
  1071. *
  1072. * L_fixValue - mask off the low bits.
  1073. */
  1074. static unsigned long L_fixValue 
  1075.     (
  1076.     unsigned long x
  1077.     )
  1078.     {
  1079.     return (x & 0xfffff800);
  1080.     }
  1081. /*******************************************************************************
  1082. *
  1083. * R_fixValue - mask off the high bits.
  1084. */
  1085. static unsigned long R_fixValue 
  1086.     (
  1087.     unsigned long x
  1088.     )
  1089.     {
  1090.     return (x & 0x000007ff);
  1091.     }
  1092. /*******************************************************************************
  1093. *
  1094. * RND_fixValue - round to nearest 8k (0x2000) byte boundary
  1095. */
  1096. static unsigned long RND_fixValue 
  1097.     (
  1098.     unsigned long x
  1099.     )
  1100.     {
  1101.     return ((x + 0x1000) & 0xffffe000);
  1102.     }
  1103. /******************************************************************************
  1104. *
  1105. * LR_fixValue - mask off low bits after rounding.
  1106. */
  1107. static unsigned long LR_fixValue 
  1108.     (
  1109.     unsigned long x,
  1110.     unsigned long fixConst
  1111.     )
  1112.     {
  1113.     return (L_fixValue (x + RND_fixValue(fixConst)));
  1114.     }
  1115. /******************************************************************************
  1116. *
  1117. * RR_fixValue - mask off high bits after rounding.
  1118. */
  1119. static unsigned long RR_fixValue 
  1120.     (
  1121.     unsigned long x,
  1122.     unsigned long fixConst
  1123.     )
  1124.     {
  1125.     return (R_fixValue (x + RND_fixValue(fixConst)) + 
  1126.             (fixConst - RND_fixValue(fixConst)));
  1127.     }
  1128. /*******************************************************************************
  1129. *
  1130. * fieldValue - perform rounding.
  1131. *
  1132. * This function performs rounding during a fixup request.
  1133. * The field selector, mode selector, and round constant are computed
  1134. * by the fuction fieldGetDefault() (see below) and passed to us.
  1135. *
  1136. * RETURNS: A rounded value, based on the original value, field selector,
  1137. *          mode selector, and round constant.
  1138. */
  1139. static UINT fieldValue
  1140.     (
  1141.     UINT value,
  1142.     UINT fSel,
  1143.     UINT mSel,
  1144.     UINT roundConst
  1145.     )
  1146.     {
  1147.     UINT retVal = value;
  1148.     switch (fSel)
  1149.         {
  1150.         /* FSEL = no rounding needed */
  1151.       case R_FSEL:
  1152. retVal = value + roundConst;
  1153. break;
  1154.         /* LSEL = "left" bits (round first, then zero out the right bits) */
  1155.       case R_LSEL:
  1156. switch (mSel)
  1157.     {
  1158.   case R_N_MODE:        /* round down (L') mode */
  1159.     retVal = L_fixValue (value + roundConst);
  1160.     break;
  1161.   case R_S_MODE:        /* round to nearest page (LS') mode */
  1162.     value += roundConst;
  1163.     if (value & 0x00000400)
  1164. retVal = L_fixValue (value + 0x800);
  1165.     else
  1166. retVal = value;
  1167.     break;
  1168.   case R_D_MODE:        /* round up (LD') mode */
  1169.     retVal = L_fixValue (value + roundConst + 0x800);
  1170.     break;
  1171.   case R_R_MODE:        /* round up with adjust (LR') mode */
  1172.     retVal = LR_fixValue (value, roundConst);
  1173.     break;
  1174.     }
  1175. break;
  1176.         /* RSEL = "right" bits (round first, then zero out the left bits) */
  1177.       case R_RSEL:        
  1178. switch (mSel)
  1179.     {
  1180.   case R_N_MODE:        /* round down (R') mode */
  1181.     retVal = R_fixValue (value + roundConst);
  1182.     break;
  1183.   case R_S_MODE:        /* round to nearest page (RS') mode */
  1184.     value += roundConst;
  1185.     if (value & 0x00000400)
  1186. retVal = value | 0xfffff800;
  1187.     else
  1188. retVal = value;
  1189.     break;
  1190.   case R_D_MODE:        /* round up (RD') mode */
  1191.     retVal = (value + roundConst) | 0xfffff800;
  1192.     break;
  1193.   case R_R_MODE:        /* round with adjust (RR') mode */
  1194.     retVal = RR_fixValue (value, roundConst);
  1195.     break;
  1196.     }
  1197. break;
  1198.       default:
  1199. WARN ("Warning: unknown field selector %dn", fSel);
  1200. break;
  1201.         }
  1202.     return (retVal);
  1203.     }
  1204. /*******************************************************************************
  1205. *
  1206. * fieldGetDefault - compute the field selector and rounding mode.
  1207. *
  1208. * This function looks at the current instruction to determine
  1209. * the field value, rounding mode, and rounding constant.
  1210. */
  1211. static void fieldGetDefault 
  1212.     (
  1213.     UINT  instr,                  /* machine instruction */
  1214.     int   fieldOverride,          /* field selector override flag */
  1215.     int   dataOverride,           /* fixed constant override flag */
  1216.     int * pFieldSel,              /* where to return field selector */
  1217.     int * pFormat,                /* how to deposit bits */
  1218.     int * pFixConst               /* where to return fixup constant */
  1219.     )
  1220.     {
  1221.     unsigned int disp;
  1222.     unsigned int majorCode = (instr & 0xfc000000) >> 26;
  1223.     /* set field selector */
  1224.     if (!fieldOverride)
  1225.         {
  1226.         switch (majorCode)
  1227.             {
  1228.             case LDIL_CODE:
  1229.             case ADDIL_CODE:
  1230.                 *pFieldSel = R_LSEL;
  1231.                 break;
  1232.             case BL_CODE:
  1233.             case COMBT_CODE:
  1234.             case COMBF_CODE:
  1235.             case ADDB_CODE:
  1236.             case ADDBF_CODE:
  1237.             case BB_CODE:
  1238.                 *pFieldSel = R_FSEL;
  1239.                 break;
  1240.             default:
  1241.                 *pFieldSel = R_RSEL;
  1242.                 break;
  1243.             }
  1244.         }
  1245.     /* get relocation bit */
  1246.     switch (majorCode)
  1247.         {
  1248.         /* i_exp14 */
  1249.         case LDW_CODE:
  1250.         case LDH_CODE:
  1251.         case LDB_CODE:
  1252.         case STW_CODE:
  1253.         case STH_CODE:
  1254.         case STB_CODE:
  1255.         case LDWM_CODE:
  1256.         case STWM_CODE:
  1257.         case LDO_CODE:
  1258.             disp = instr & 0x3fff;
  1259.             disp = low_sign_ext (disp, 14);
  1260.             *pFormat = i_exp14;
  1261.             break;
  1262.         /* i_exp11 */
  1263.         case ADDI_CODE:
  1264.         case ADDIT_CODE:
  1265.         case SUBI_CODE:
  1266.         case COMICKR_CODE:
  1267.             disp = instr & 0x7ff;
  1268.             disp = low_sign_ext (disp, 11);
  1269.             *pFormat = i_exp11;
  1270.             break;
  1271.         /* i_exp21 */
  1272.         case LDIL_CODE:
  1273.         case ADDIL_CODE:
  1274.             disp = assemble_21 (instr & 0x1fffff);
  1275.             disp = disp & 0x3fff;
  1276.             *pFormat = i_exp21;
  1277.             break;
  1278.         /* i_rel17 */
  1279.         case BL_CODE:
  1280.         /* i_abs17 */
  1281.         case BE_CODE:
  1282.         case BLE_CODE:
  1283.             disp = instr & 0x1fffff;
  1284.             disp = sign_ext(assemble_17 ((disp & 0x1f0000)>>16, 
  1285.                                          (disp & 0x1ffc) >> 2,
  1286.                                          disp & 0x1), 17) << 2;
  1287.             *pFormat = i_rel17;        /* i_rel17 and i_abs17 same format */
  1288.             break;
  1289.         /* i_rel12 */
  1290.         case ADDIBT_CODE:
  1291.         case ADDIBF_CODE:
  1292.         case COMIBT_CODE:
  1293.         case COMIBF_CODE:
  1294.             disp = instr & 0x1ffd;
  1295.             disp = sign_ext (assemble_12 ((disp & 0x1ffc) >> 2, disp & 0x1), 12)
  1296.                    << 2;
  1297.             *pFormat = i_rel12;
  1298.             break;
  1299.         default:
  1300.             disp = 0;
  1301.             *pFormat = i_none;
  1302.             break;
  1303.         }
  1304.     if (!dataOverride)
  1305.         *pFixConst = disp;
  1306.     }
  1307. /*******************************************************************************
  1308. *
  1309. * fixBits - Perform a linker fixup to modify an instruction.
  1310. */
  1311. static void fixBits
  1312.     (
  1313.     INSTR * adrs,        /* where to fix */
  1314.     int     value,       /* value to fix */
  1315.     int     format       /* fixup format */
  1316.     )
  1317.     {
  1318.     int mask;
  1319.     switch (format)
  1320.         {
  1321.         case i_exp14:
  1322.             value = de_low_sign_ext (value, 14);
  1323.             mask = 0x3fff;
  1324.             break;
  1325.         case i_exp21:
  1326.             value = de_assemble_21 (value >> 11);
  1327.             mask = 0x1fffff;
  1328.             break;
  1329.         case i_exp11:
  1330.             value = de_low_sign_ext (value, 11);
  1331.             mask = 0x7ff;
  1332.             break;
  1333.         case i_rel17:
  1334.         case i_abs17:
  1335.             value = de_assemble_17 (value >> 2);
  1336.             mask = 0x001f1ffd;
  1337.             break;
  1338.         case i_rel12:
  1339.             value = de_assemble_12 (value >> 2);
  1340.             mask = 0x1ffd;
  1341.             break;
  1342.         case i_data:
  1343.             mask = 0xffffffff;
  1344.             break;
  1345.         case i_milli:
  1346.         case i_break:
  1347.         default:
  1348.             mask = 0;
  1349.             break;
  1350.         }
  1351.     *adrs = ((*adrs) & ~mask) | (value & mask);
  1352.     }
  1353. /*******************************************************************************
  1354. *
  1355. * linkSubspaces - perform linker fixup commands for relocation.
  1356. *
  1357. * RETURNS: OK or ERROR
  1358. */
  1359. static STATUS linkSubspaces
  1360.     (
  1361.     UCHAR *   pRelCmds,        /* list of relocation commands */
  1362.     SUBSPACE *pSubspace,       /* subspace dictionary */
  1363.     int       nSubs,           /* number of subspaces */
  1364.     SUB_INFO *pSubInfo,        /* load information for the subspaces */
  1365.     SYMREC *  pSym,            /* symbols dictionary */
  1366.     int       numSyms,         /* number of symbols */
  1367.     SYMTAB_ID pSymTab,         /* VxWorks symbol table */
  1368.     SYMREC *  pSymGlobal,      /* pointer to '$global$' entry */
  1369.     MODULE_ID moduleId         /* module being linked */
  1370.     )
  1371.     {
  1372.     int status = OK; /* function return value */
  1373.     /*
  1374.      * generic fixup variables
  1375.      *
  1376.      * For each subspace, we must process a stream of fixup requests
  1377.      * in order to complete the relocation. The fixup requests are
  1378.      * variable size, and there are no "markers" to separate the
  1379.      * fixups - so ya gotta be real careful. The first byte of each
  1380.      * fixup request is called the opCode.
  1381.      */
  1382.     int ix; /* index of subspace being fixed up */
  1383.     UCHAR * pThisFixup; /* start of relocation fixup stream */
  1384.     UCHAR * pLastFixup; /* end of stream */
  1385.     UCHAR opCode;               /* the type of fixup request */
  1386.     char *relAdr;               /* address that need fixing */
  1387.     int relValue;               /* value to apply (e.g., a function address) */
  1388.     /*
  1389.      * Variables for maintaining the REPEAT_PREV_FIXUP list.
  1390.      *
  1391.      * The linker maintains a list of the last 4 multibyte
  1392.      * fixup requests. When a REPEAT_PREV_FIXUP fixup occurs,
  1393.      * we repeat one of the fixups from our list.
  1394.      */
  1395.     LIST prevFixupList;         /* previous fixup list */
  1396.     PREV_FIXUP prevFixupNodes[4];    /* the nodes in the list */
  1397.     PREV_FIXUP *pPrevFixupNode; /* pointer to some node in the list */
  1398.     UCHAR *pOldFixup = 0;       /* before executing a previous fixup, we save
  1399.                                  * our current place in the fixup stream */
  1400.     BOOL usingPrevFixup;        /* are we currently are using a queued fixup? */
  1401.     /*
  1402.      * variables for fixups that manipulate the expession stack.
  1403.      *
  1404.      * An expession stack is used to evaluate complex combinations of values.
  1405.      * The R_COMPX fixups either push a value on the expression stack or
  1406.      * modifies what is on top of the stack (e.g., it might pop the top
  1407.      * two elements, and push their sum).
  1408.      * These fixups have a secondary opCode which describes what to do.
  1409.      * The value at the top of the expession stack is used in the
  1410.      * R_DATA_EXPR and R_CODE_EXPR fixups.
  1411.      * XXX - these have not been tested yet.
  1412.      */
  1413.     UCHAR opCode2;              /* 2nd opcode for stack manipulation fixups */
  1414.     int * pExpStack;                /* initial stack pointer */
  1415.     int * sp; /* current stack pointer */
  1416.     int top1;                   /* first item on stack */
  1417.     int top2;                   /* second item on stack */
  1418.     int C;                      /* condition code for stack operation */
  1419.     /*
  1420.      * variables to hold the fixup request parameters.
  1421.      *
  1422.      * Most fixup requests pass us parameters (e.g., the symbol number
  1423.      * which we need to branch to). The parameters passed depend on
  1424.      * the fixup. The way the parameters are encoded in the fixup stream
  1425.      * also depends on the fixup.
  1426.      */
  1427.     int L;                      /* number of bytes to relocate */
  1428.     int S;                      /* symbol index used */
  1429.     int R = 0;                  /* parameter relocation bits */
  1430.     int V = 0;                  /* variable or fix up constant */
  1431.     int U; /* stack unwind bits */
  1432.     int F; /* procedure stack frame size */
  1433.     int D;                      /* difference of operation code */
  1434.     int X; /* previous fixup index */
  1435.     int M; /* number of bytes for R_REPEATED_INIT */
  1436.     int N; /* statement number in R_STATEMENT */
  1437.     /*
  1438.      * variables for handling the rounding mode during fixups
  1439.      *
  1440.      * Many fixups come in pairs, where we move the left (high order)
  1441.      * bits of a value in the first fixup, and the right (low order)
  1442.      * bits in the next fixup. Before applying a fixup value
  1443.      * at an address, it must be rounded.
  1444.      * The rounded constant is then applied to the address.
  1445.      *
  1446.      * The field selector specifies if we should apply the
  1447.      * left bits (LSEL), the right bits (RSEL), or everything (FSEL).
  1448.      * The field selector depends on the current instruction, but
  1449.      * can be overridden with a feild selector override fixup.
  1450.      *
  1451.      * The interpretation of the field selector depends on the current
  1452.      * rounding mode. The rounding mode selector can be
  1453.      * round down (N_MODE), round to nearest page (S_MODE), round up (D_MODE),
  1454.      * or round down with adjusted constant (R_MODE).
  1455.      * The rounding mode is persistent until explicity changed by
  1456.      * a mode select fixup request. The default at the begining of each
  1457.      * subspace is N_MODE.
  1458.      *
  1459.      * The function fieldGetDefault() computes the field selector
  1460.      * (and adjusted constant if we are in R_MODE) based on the current
  1461.      * instruction and rounding mode. It also computes how to
  1462.      * apply the rounded constant to a given instruction.
  1463.      */
  1464.     int fixConstant;            /* adjusted constant used in R_MODE rounding */
  1465.     int modeSel;                /* mode select */
  1466.     int fieldSel;               /* field select */
  1467.     int fieldOverride; /* field select override flag */
  1468.     int dataOverride;           /* data override flag */
  1469.     int relFormat; /* how to apply the rounded constant */
  1470.     /* 
  1471.      * variables for stub manipulation.
  1472.      *
  1473.      * The linker must generate "long branch stubs" and "parameter
  1474.      * relocation stubs" whenever needed. Read the INTERNAL
  1475.      * comments at the begining of the file for more info.
  1476.      * The long branch stubs are generated per subspace, while
  1477.      * the parameter relocation stubs are generated per module.
  1478.      */
  1479.     LIST stubList;              /* list of current long branch stubs */
  1480.     char *pLongBranchStubs;     /* starting address this subspaces stubs */
  1481.     char *pStub;                /* address of current stub */
  1482.     int stubIx;                 /* current stubs index in the list */
  1483.     LIST argRelocStubList; /* list of argument relocation stubs */
  1484.     /*
  1485.      * variables for stack unwind generation
  1486.      *
  1487.      * The PA-RISC has no frame pointer. To calculate the frame pointer,
  1488.      * the linker must generate an array of stack unwind descriptors
  1489.      * which, for each function, specifies its starting address, ending
  1490.      * address, and the amount of stack space it requires. 
  1491.      */
  1492.     LIST unwindList; /* linked list of unwind descriptors */
  1493.     UNWIND_NODE *pUnwindNode = NULL; /* pointer to an unwind descriptor */
  1494.     /* scratch variables */
  1495.     char *tmpBuf;               /* tempoaray buffer */
  1496.     int bufSize;                /* size of temporary buffer */
  1497.     /* create the expression stack */
  1498.     if ((pExpStack = (int *) calloc (1, REL_STACK_SIZE)) == NULL)
  1499.         {
  1500.         printErr ("ld error: unable to allocate relocation stackn");
  1501.         return (ERROR);
  1502.         }
  1503.     /* Initialize the previous fixup queue */
  1504.     lstInit (&prevFixupList);
  1505.     for (ix = 0; ix < 4; ix++)
  1506.         {
  1507.         lstAdd (&prevFixupList, &(prevFixupNodes[ix].node));
  1508.         prevFixupNodes[ix].pFixup = NULL;
  1509.         }
  1510.     /* initialize the list of long branch and parameter relocation stubs */
  1511.     lstInit (&stubList);
  1512.     lstInit (&argRelocStubList);
  1513.     /* initialize the stack unwind list */
  1514.     lstInit (&unwindList);
  1515.     /* perform linker fixups on each subspace */
  1516.     for (ix = 0; ix < nSubs; ix ++, pSubspace++)
  1517.         {
  1518.         if (!pSubspace->is_loadable)
  1519.             {
  1520.             DBG_PUT ("linker: skipping fixups for unloadable subspacen");
  1521.             continue;
  1522.             }
  1523.         if (pSubspace->fixup_request_quantity == 0)
  1524.             {
  1525.             continue;
  1526.             }
  1527.         DBG_PUT ("nnnsubSpace: 0x%x - 0x%xn", (int)(pSubInfo[ix].loadAddr),
  1528.                  (int)(pSubInfo[ix].loadAddr) + pSubspace->subspace_length);
  1529.         /* Initialize the long branch stub list for this subspace to be empty */
  1530.         lstFree (&stubList);
  1531.         pLongBranchStubs = pSubInfo[ix].loadAddr +
  1532.                            pSubspace->subspace_length;
  1533.         pLongBranchStubs = (char *)ROUND_UP (pLongBranchStubs,
  1534.                            pSubspace->alignment);
  1535.         /* get the starting address for this subspace */
  1536.         relAdr = (pSubInfo + ix)->loadAddr;
  1537.         /* get the list of fixup requests for this subspace */
  1538.         pThisFixup = pRelCmds + pSubspace->fixup_request_index;
  1539.         pLastFixup = pThisFixup + pSubspace->fixup_request_quantity;
  1540.         /* set some default modes */
  1541.         modeSel = R_N_MODE; /* default rounding mode for each subspace */
  1542.         fieldSel = R_FSEL;      /* default field selector. XXX - needed? */
  1543.         dataOverride = FALSE;
  1544.         fieldOverride = FALSE;
  1545.         usingPrevFixup = FALSE;
  1546.         sp = pExpStack; /* each subspace starts with a fresh
  1547.                                  * expression stack. XXX - added */
  1548.         /* process this subspaces fixups in a huge switch statement */
  1549.         while (pThisFixup < pLastFixup)
  1550.             {
  1551.             opCode = *pThisFixup;
  1552.             DBG_PUT ("opCode (0x%x) = %d. relAdr = 0x%x.n", (int)pThisFixup,
  1553.                      opCode, (int)relAdr);
  1554.             /* keep track of the last 4 multibyte fixup requests */
  1555.             if (fixupLen[opCode] > 1)
  1556.                 {
  1557.                 pPrevFixupNode = (PREV_FIXUP *)lstNth (&prevFixupList, 4);
  1558.                 lstDelete (&prevFixupList, &(pPrevFixupNode->node));
  1559.                 pPrevFixupNode->pFixup = pThisFixup;
  1560.                 lstInsert (&prevFixupList, NULL, &(pPrevFixupNode->node));
  1561.                 }
  1562.             pThisFixup++;
  1563.             /* perform the fixup based on the opCode */
  1564.             if (/* opCode >= R_NO_RELOCATION && */ opCode < R_ZEROES )
  1565.                 {
  1566.                 /* 00-1f: n words, not relocatable */
  1567.                 if (opCode < 24)
  1568.                     {
  1569.                     D = opCode - R_NO_RELOCATION;
  1570.                     L = (D + 1) * 4;
  1571.                     }
  1572.                 else if (opCode >= 24 && opCode < 28)
  1573.                     {
  1574.                     D = opCode - 24;
  1575.                     L = ((D << 8) + B1 + 1) * 4;
  1576.                     }
  1577.                 else if (opCode >= 28 && opCode < 31)
  1578.                     {
  1579.                     D = opCode - 28;
  1580.                     L = ((D << 16) + B2 + 1) * 4;
  1581.                     }
  1582.                 else
  1583.                     {
  1584.                     D = opCode - 31;
  1585.                     L = B3 + 1;
  1586.                     }
  1587.                 DBG_PUT ("R_NO_RELOCATION: 0x%x bytesn", L);
  1588.                 relAdr += L;
  1589.                 }
  1590.             else if (opCode >= R_ZEROES && opCode < R_UNINIT)
  1591.                 {
  1592.                 /* 20-21: n words, all zero */
  1593.                 if (opCode == R_ZEROES)
  1594.                     {
  1595.                     L = (B1 + 1) * 4;
  1596.                     }
  1597.                 else
  1598.                     {
  1599.                     L = B3 + 1;
  1600.                     }
  1601.                 /* insert L bytes zero */
  1602.                 bufSize = (int)(pSubInfo+ix)->loadAddr +
  1603.                         pSubspace->subspace_length - (int)relAdr;
  1604.                 tmpBuf = malloc (bufSize); 
  1605.                 if (tmpBuf == NULL)
  1606.                         printErr ("ld error: reloc malloc failedn");
  1607.                 DBG_PUT ("inserting %d zeros at 0x%xn",
  1608.                             L, (int)relAdr);
  1609.                 bcopy (relAdr, tmpBuf, bufSize);
  1610.                 bzero (relAdr, L);
  1611.                 relAdr += L;
  1612.                 bcopy (tmpBuf, relAdr, bufSize - L);
  1613.                 free ((char *) tmpBuf);
  1614.                 }
  1615.             else if (opCode >= R_UNINIT && opCode < R_RELOCATION)
  1616.                 {
  1617.                 /* 22-23: n words, uninitialized */
  1618.                 if (opCode == R_UNINIT)
  1619.                     {
  1620.                     L = (B1 + 1) * 4;
  1621.                     }
  1622.                 else
  1623.                     {
  1624.                     L = B3 + 1;
  1625.                     }
  1626.                 /* skip L bytes */
  1627.                 bufSize = (int)(pSubInfo+ix)->loadAddr +
  1628.                                 pSubspace->subspace_length - (int)relAdr;
  1629.                 tmpBuf = malloc (bufSize); 
  1630.                 if (tmpBuf == NULL)
  1631.                         printErr ("ld error: reloc malloc failedn");
  1632.                 DBG_PUT ("skipping %d bytes at 0x%x.n", L, (int)relAdr);
  1633.                 bcopy ((char *) relAdr, tmpBuf, bufSize);
  1634.                 bzero (relAdr, L);
  1635.                 relAdr += L;
  1636.                 bcopy (tmpBuf, relAdr, bufSize - L);
  1637.                 free ((char *) tmpBuf);
  1638.                 }
  1639.             else if (opCode == R_RELOCATION)
  1640.                 { /* XXX - untested */
  1641.                 /* 24: 1 word relocatable data */
  1642.                 relValue = *(int *)relAdr + (int)(pSubInfo[ix].loadAddr);
  1643.                 *((unsigned int *)(relAdr)) = relValue;
  1644.                 WARN ("Warning: R_RELOCATION fixup is untestedn");
  1645.                 WARN ("address = 0x%xn", (int)relAdr);
  1646.                 relAdr += 4;
  1647.                 }
  1648.             else if (opCode >= R_DATA_ONE_SYMBOL && opCode < R_DATA_PLABEL)
  1649.                 {
  1650.                 /* 25-26: 1 word, data external reference */
  1651.                 if (opCode == R_DATA_ONE_SYMBOL)
  1652.                     {
  1653.                     S = B1;
  1654.                     }
  1655.                 else
  1656.                     {
  1657.                     S = B3;
  1658.                     }
  1659.                 relValue = *(int *)relAdr + (pSym + S)->symbol_value;
  1660.                 *((int *)relAdr) = relValue;
  1661.                 DBG_PUT ("R_DATA_ONE_SYMBOL: relAdr = 0x%xn", (int)relAdr);
  1662.                 relAdr +=4;
  1663.                 }
  1664.             else if (opCode >= R_DATA_PLABEL && opCode < R_SPACE_REF)
  1665.                 {
  1666.                 /* 27-28: 1 word, data plabel reference */
  1667.                 if (opCode == R_DATA_PLABEL)
  1668.                     {
  1669.                     S = B1;
  1670.                     }
  1671.                 else
  1672.                     {
  1673.                     S = B3;
  1674.                     }
  1675.                 relValue = ((SYMREC *)(pSym + S))->symbol_value;
  1676.                 *((int *)relAdr) = relValue;
  1677.                 DBG_PUT ("R_DATA_PLABEL: relAdr = 0x%xn", (int)relAdr);
  1678.                 relAdr += 4;
  1679.                 }
  1680.             else if (opCode == R_SPACE_REF)
  1681.                 {
  1682.                 /* 29: 1 word, initialized space id */
  1683.                 printErr ("ld error: R_SPACE_REF relocation unsupportedn");
  1684.                 status = ERROR;
  1685.                 }
  1686.             else if (opCode >= R_REPEATED_INIT && opCode < 46)
  1687.                 {
  1688.                 /* 30-3d: n words, repeated pattern */
  1689.                 if (opCode == R_REPEATED_INIT)
  1690.                     {
  1691.                     L = 4;
  1692.                     M = (B1 + 1) * 4;
  1693.                     }
  1694.                 else if (opCode == (R_REPEATED_INIT + 1))
  1695.                     {
  1696.                     L = B1 * 4;
  1697.                     M = (B1 + 1) * L;
  1698.                     }
  1699.                 else if (opCode == (R_REPEATED_INIT + 2))
  1700.                     {
  1701.                     L = B1 * 4;
  1702.                     M = (B3 + 1) * 4;
  1703.                     }
  1704.                 else
  1705.                     {
  1706.                     L = B3 + 1;
  1707.                     M = B4 + 1;
  1708.                     }
  1709.                 DBG_PUT ("Bcopy R_REPEATED_INITn");
  1710.                 bcopy (relAdr, relAdr + L, M);
  1711.                 relAdr += M + L;
  1712.                 }
  1713.             else if (opCode >= R_PCREL_CALL && opCode < 62)
  1714.                 {
  1715.                 /* 3e-3f: 1 word, pc-relative call */
  1716.                 if (opCode >= R_PCREL_CALL && opCode < (R_PCREL_CALL + 10))
  1717.                     {
  1718.                     D = opCode - R_PCREL_CALL;
  1719.                     R = rbits1 (D);
  1720.                     S = B1;
  1721.                     }
  1722.                 else if (opCode >= (R_PCREL_CALL + 10) && 
  1723.                          opCode < (R_PCREL_CALL + 12))
  1724.                     {
  1725.                     D = opCode - (R_PCREL_CALL + 10);
  1726.                     R = rbits2 ((D << 8) + B1);
  1727.                     S = B1;
  1728.                     }
  1729.                 else
  1730.                     {
  1731.                     D = opCode - (R_PCREL_CALL + 12);
  1732.                     R = rbits2 ((D << 8) + B1);
  1733.                     S = B3;
  1734.                     }
  1735.                 DBG_PUT ("R_PCREL_CALL %dn", opCode - R_PCREL_CALL);
  1736.                 fieldGetDefault (*(unsigned int *)relAdr, fieldOverride, 
  1737.                                  dataOverride, &fieldSel, &relFormat, 
  1738.                                  &fixConstant);
  1739.                 relValue = fieldValue ((int)((pSym+S)->symbol_value - 
  1740.                                         (int)relAdr - 8), fieldSel, 
  1741.                                         modeSel, fixConstant);
  1742.                 /*
  1743.                  * if we are out of range for a PC relative branch,
  1744.                  * then we must create a "long branch stub"
  1745.                  * and patch this routine to jump to the stub 
  1746.                  */
  1747.                 if ( (relValue > 0x3ffff) || (relValue < -0x40000) ||
  1748.                     argRelocDiffer (pSym[S].arg_reloc, R) )
  1749.                     {
  1750.                     stubIx = stubListFind (&stubList, S, R);
  1751.                     if (stubIx == -1)
  1752.                         {
  1753.                         char *procAddr;
  1754. int parm_reloc;
  1755. /* Always add unmodified arg_reloc case first */
  1756. stubIx = stubListFind(&stubList, S, pSym[S].arg_reloc);
  1757. if (stubIx == -1)
  1758.     {
  1759.                             procAddr = (char *) pSym[S].symbol_value;
  1760.     stubIx = stubListAdd (&stubList, S,
  1761.   pSym[S].arg_reloc);
  1762.     pStub = pLongBranchStubs + stubIx*stubSize;
  1763.     DBG_PUT ("Creating long branch stub at 0x%x calling 0x%xn",
  1764.      (int) pStub, pSym[S].symbol_value);
  1765.     stubInit (pStub, (char *) pSym[S].symbol_value);
  1766.     }
  1767. /* See if a parameter reloc stub is needed */
  1768. parm_reloc = (pSym[S].arg_reloc & 0x03f3) | 0x0c;
  1769. if (argRelocDiffer (pSym[S].arg_reloc, R)
  1770.     && !argRelocDiffer (parm_reloc, R))
  1771.     {
  1772.     stubIx = stubListAdd (&stubList, S, parm_reloc);
  1773.     pStub = pLongBranchStubs + stubIx*stubSize;
  1774.                             procAddr = argRelocStubListFind (&argRelocStubList,
  1775.                                           pSym + S, R, moduleId);
  1776.     DBG_PUT ("Creating long branch stub at 0x%x calling 0x%x (0x%x)n",
  1777.      (int) pStub, (int) procAddr,
  1778.      pSym[S].symbol_value);
  1779.     stubInit (pStub, procAddr);
  1780.     }
  1781. if (stubIx == -1)
  1782.     {
  1783.     printErr ("stub not foundn");
  1784.     break;
  1785.     }
  1786.                         }
  1787.                     pStub = pLongBranchStubs + stubIx*stubSize;
  1788.                     relValue = fieldValue ((int)(pStub - (int)relAdr - 8),
  1789.                                            fieldSel, modeSel, fixConstant);
  1790.                     }
  1791.                 fixBits ((INSTR *) relAdr, relValue, relFormat);
  1792.                 FLAG_RESET (fieldOverride);
  1793.                 FLAG_RESET (dataOverride);
  1794.                 relAdr += 4;
  1795.                 }
  1796.             else if (opCode == 62)
  1797. {
  1798. /* SPR 22030: ignore this reserved fixup type */
  1799. }
  1800.             else if (opCode >= R_ABS_CALL && opCode < 78)
  1801.                 {
  1802.                 /* 40-4d: 1 word, absolute call */
  1803.                 /* 4e-4f: reserved */
  1804.                 if ( opCode >= 0x40 && opCode < 0x4a)
  1805.                     {
  1806.                     D = opCode - R_ABS_CALL;
  1807.                     R = rbits1 (D);
  1808.                     S = B1;
  1809.                     }
  1810.                 else if (opCode == 74 || opCode == 75)
  1811.                     {
  1812.                     D = opCode - 74;
  1813.                     R = rbits2 ((D << 8) + B1);
  1814.                     S = B1;
  1815.                     }
  1816.                 else
  1817.                     {
  1818.                     D = opCode - 76;
  1819.                     R = rbits2 ((D << 8) + B1);
  1820.                     S = B3;
  1821.                     }
  1822.                 DBG_PUT ("R_ABS_CALL + %dn", opCode - R_ABS_CALL);
  1823.                 fieldGetDefault (*(unsigned int *)relAdr, fieldOverride, 
  1824.                                  dataOverride, &fieldSel, &relFormat, 
  1825.                                  &fixConstant);
  1826.                 /*
  1827.                  * if we are calling a procedure with the wrong parameters,
  1828.                  * then we must generate a "parameter relocation stub"
  1829.                  * and call the stub instead
  1830.                  */
  1831.                 if (argRelocDiffer(R, pSym[S].arg_reloc))
  1832.                     {
  1833.                     tmpBuf = argRelocStubListFind (&argRelocStubList,
  1834.                                           pSym + S, R, moduleId);
  1835.                     relValue = fieldValue ((int)(tmpBuf), fieldSel,
  1836.                                             modeSel, fixConstant);
  1837.                     }
  1838.                 else
  1839.                     {
  1840.                     relValue = fieldValue (
  1841.                         (int)(pSym[S].symbol_value),
  1842.                         fieldSel, modeSel, fixConstant);
  1843.                     }
  1844.                 fixBits ((INSTR *) relAdr, relValue, relFormat);
  1845.                 FLAG_RESET (fieldOverride);
  1846.                 FLAG_RESET (dataOverride);
  1847.                 relAdr += 4;
  1848.                 }
  1849.             else if (opCode >= R_DP_RELATIVE && opCode < 114)
  1850.                 {
  1851.                 /* 50-72: 1 word, dp-relative load/store */
  1852.                 /* 73-77: reserved */
  1853.                 if (opCode == 112)
  1854.                     {
  1855.                     S = B1;
  1856.                     }
  1857.                 else if (opCode == 113)
  1858.                     {
  1859.                     S = B3;
  1860.                     }
  1861.                 else
  1862.                     {
  1863.                     D = opCode - R_DP_RELATIVE;
  1864.                     S = D;
  1865.                     }
  1866.                 fieldGetDefault (*(unsigned int *)relAdr, fieldOverride, 
  1867.                                  dataOverride, &fieldSel, &relFormat, 
  1868.                                  &fixConstant);
  1869.                 if (pSymGlobal == NULL)
  1870.                     {
  1871.                     printErr ("ld error: no $global$n");
  1872.                     status = ERROR;
  1873.                     }
  1874.                 else
  1875.                     {
  1876.                     relValue = (int)((pSym+S)->symbol_value) - 
  1877.                                pSymGlobal->symbol_value;
  1878.                     relValue = fieldValue (relValue, fieldSel, modeSel, 
  1879.                                            fixConstant);
  1880.                     fixBits ((INSTR *) relAdr, relValue, relFormat);
  1881.                     }
  1882.                 DBG_PUT ("R_DP_RELATIVE at 0x%xn", (int)relAdr);
  1883.                 FLAG_RESET (fieldOverride);
  1884.                 FLAG_RESET (dataOverride);
  1885.                 relAdr += 4;
  1886.                 }
  1887.             else if (opCode >= R_DLT_REL && opCode < 122)
  1888.                 {
  1889.                 /* 78-79: 1 word, dlt-relative load/store */
  1890.                 if (opCode == R_DLT_REL)
  1891.                     {
  1892.                     S = B1;
  1893.                     }
  1894.                 else
  1895.                     {
  1896.                     S = B3;
  1897.                     }
  1898.                 printErr ("ld error: R_DLT_REL relocation unsupportedn");
  1899.                 status = ERROR;
  1900.                 relAdr += 4;
  1901.                 }
  1902.             else if (opCode >= R_CODE_ONE_SYMBOL && opCode < 162)
  1903.                 {
  1904.                 /* 80-a2: 1 word, relocatable code */
  1905.                 /* a3-ad: reserved */
  1906.                 if (opCode == 160)
  1907.                     {
  1908.                     S = B1;
  1909.                     }
  1910.                 else if (opCode == 161)
  1911.                     {
  1912.                     S = B3;
  1913.                     }
  1914.                 else
  1915.                     {
  1916.                     D = opCode - R_CODE_ONE_SYMBOL;
  1917.                     S = D;
  1918.                     }
  1919.                 fieldGetDefault (*(unsigned int *)relAdr, fieldOverride, 
  1920.                                  dataOverride, &fieldSel, &relFormat, 
  1921.                                  &fixConstant);
  1922.                 relValue = fieldValue ((int)((pSym + S)->symbol_value),
  1923.                                         fieldSel, modeSel, fixConstant);
  1924.                 DBG_PUT ("    fieldValue(0x%x, %d, %d, 0x%x) = 0x%xn",
  1925.  (int)((pSym + S)->symbol_value),
  1926.  fieldSel, modeSel, fixConstant, relValue);
  1927.                 fixBits ((INSTR *) relAdr, relValue, relFormat);
  1928.                 FLAG_RESET (fieldOverride);
  1929.                 FLAG_RESET (dataOverride);
  1930.                 DBG_PUT ("R_CODE_ONE_SYMBOL at 0x%xn", (int)relAdr);
  1931.                 DBG_PUT ("    symVal= 0x%x fixConst= 0x%x, relValue= 0x%xn",
  1932.  (int)((pSym + S)->symbol_value), fixConstant,
  1933.  relValue);
  1934.                 relAdr += 4;
  1935.                 }
  1936.             else if (opCode >= R_MILLI_REL && opCode < R_CODE_PLABEL)
  1937.                 {
  1938.                 /* ae-af: 1 word, millicode-relative branch */
  1939.                 if (opCode == R_MILLI_REL)
  1940.                     {
  1941.                     S = B1;
  1942.                     }
  1943.                 else
  1944.                     {
  1945.                     S = B3;
  1946.                     }
  1947.                 fieldGetDefault (*(unsigned int *)relAdr, fieldOverride, 
  1948.                                  dataOverride, &fieldSel, &relFormat, 
  1949.                                  &fixConstant);
  1950.                 WARN ("Warning: R_MILLI_REL fixup is untestedn");
  1951.                 WARN ("address = 0x%xn", (int)relAdr);
  1952.                 relValue = fieldValue ((pSym[S].symbol_value -
  1953.                                        pSym[1].symbol_value + fixConstant),
  1954.                                        fieldSel, modeSel, fixConstant);
  1955.                 fixBits ((INSTR *) relAdr, relValue, relFormat); 
  1956.                 FLAG_RESET (fieldOverride);
  1957.                 FLAG_RESET (dataOverride);
  1958.                 relAdr += 4;
  1959.                 }
  1960.             else if (opCode >= R_CODE_PLABEL && opCode < R_BREAKPOINT)
  1961.                 {
  1962.                 /* b0-b1: 1 word, code plabel reference */
  1963.                 if (opCode == R_CODE_PLABEL)
  1964.                     {
  1965.                     S = B1;
  1966.                     }
  1967.                 else
  1968.                     {
  1969.                     S = B3;
  1970.                     }
  1971.                 fieldGetDefault (*(unsigned int *)relAdr, fieldOverride, 
  1972.                                  dataOverride, &fieldSel, &relFormat, 
  1973.                                  &fixConstant);
  1974.                 if (fixConstant != 0 && fixConstant != 2)
  1975.                     printErr ("R_CODE_PLABEL: wrong displacement valuen");
  1976.                 relValue = fieldValue ((int)(pSym + S)->symbol_value, 
  1977.                                        fieldSel, modeSel, fixConstant);
  1978.                 fixBits ((INSTR *) relAdr, relValue, relFormat);
  1979.                 FLAG_RESET (fieldOverride);
  1980.                 FLAG_RESET (dataOverride);
  1981.                 relAdr += 4;
  1982.                 }
  1983.             else if (opCode == R_BREAKPOINT)
  1984.                 {
  1985.                 /* b2: 1 word, statement breakpoint */
  1986.                 *(int *)relAdr = 0;
  1987.                 DBG_PUT ("R_BREAKPOINT at address 0x%xn", (int)relAdr);
  1988.                 relAdr += 4;
  1989.                 }
  1990.             else if (opCode >= R_ENTRY && opCode < R_ALT_ENTRY)
  1991.                 {
  1992.                 /* b3-b4: procedure entry */
  1993.                 if (opCode == R_ENTRY)
  1994.                     {
  1995.                     U = B4; /* unwind descriptor word 3 */
  1996.                     F = B4; /* unwind descriptor word 4 */
  1997.                     }
  1998.                 else
  1999.                     {
  2000.                     U = B4 << 5;
  2001.                     U |= (B1 >> 3);
  2002.                     CHECK_STACK_UNDER;
  2003.                     F = POP_EXPR;
  2004.                     }
  2005.                 DBG_PUT ("proc entry at 0x%xn", (int)relAdr);
  2006.                 pUnwindNode = (UNWIND_NODE *)malloc (sizeof(UNWIND_NODE));
  2007.                 pUnwindNode->unwindDesc.startAddr = relAdr;
  2008.                 pUnwindNode->unwindDesc.word3 = U;
  2009.                 pUnwindNode->unwindDesc.word4 = F;
  2010.                 }
  2011.             else if (opCode == R_ALT_ENTRY)
  2012.                 {
  2013.                 /* b5: alternate entry */
  2014.                 WARN ("alternate entry point at 0x%x ignored!n", (int)relAdr);
  2015.                 }
  2016.             else if (opCode == R_EXIT)
  2017.                 {
  2018.                 /* b6: procedure exit */
  2019.                 DBG_PUT ("proc exit at 0x%xn", (int)relAdr);
  2020.                 if (pUnwindNode == NULL)
  2021.                     {
  2022.                     WARN ("proc exit has no proc entry!n");
  2023.                     }
  2024.                 else
  2025.                     {
  2026.                     pUnwindNode->unwindDesc.endAddr = relAdr - 4;
  2027.                     pUnwindNode->unwindDesc.word3 &= (~0x18000000);
  2028.                     unwindListAdd (&unwindList, pUnwindNode);
  2029.                     }
  2030.                 pUnwindNode = NULL;
  2031.                 }
  2032.             else if (opCode == R_BEGIN_TRY)
  2033.                 {
  2034.                 /* b7: start of try block */
  2035.                 }
  2036.             else if (opCode >= R_END_TRY && opCode < R_BEGIN_BRTAB)
  2037.                 {
  2038.                 /* b8-ba: end of try block */
  2039.                 if (opCode == R_END_TRY)
  2040.                     {
  2041.                     R = 0;
  2042.                     }
  2043.                 else if (opCode == (R_END_TRY + 1))
  2044.                     {
  2045.                     R = B1 * 4;
  2046.                     }
  2047.                 else
  2048.                     {
  2049.                     R = B3 * 4;
  2050.                     }
  2051.                 }
  2052.             else if (opCode == R_BEGIN_BRTAB)
  2053.                 {
  2054.                 /* bb: start of branch table */
  2055.                 }
  2056.             else if (opCode == R_END_BRTAB)
  2057.                 {
  2058.                 /* bc: end of branch table */
  2059.                 }
  2060.             else if (opCode >= R_STATEMENT && opCode < R_DATA_EXPR)
  2061.                 {
  2062.                 /* bd-bf: statement number */
  2063.                 if (opCode == R_STATEMENT)
  2064.                     {
  2065.                     N = B1;
  2066.                     }
  2067.                 else if (opCode == (R_STATEMENT + 1))
  2068.                     {
  2069.                     N = B2;
  2070.                     }
  2071.                 else
  2072.                     {
  2073.                     N = B3;
  2074.                     }
  2075.                 }
  2076.             else if (opCode == R_DATA_EXPR)
  2077.                 { /* XXX - untested */
  2078.                 /* c0: 1 word, relocatable data expr */
  2079.                 CHECK_STACK_UNDER;
  2080.                 relValue = (*(int *)relAdr) + POP_EXPR;
  2081.                 *(int *)relAdr = relValue;
  2082.                 WARN ("Warning: R_DATA_EXPR fixup is untestedn");
  2083.                 WARN ("address = 0x%xn", (int)relAdr);
  2084.                 relAdr += 4;
  2085.                 }
  2086.             else if (opCode == R_CODE_EXPR)
  2087.                 {
  2088.                 /* c1: 1 word, relocatable code expr */
  2089.                 CHECK_STACK_UNDER;
  2090.                 fieldGetDefault (*(unsigned int *)relAdr, fieldOverride,
  2091.                                  dataOverride, 
  2092.                                  &fieldSel, &relFormat, &fixConstant);
  2093.                 relValue = fixConstant + POP_EXPR;
  2094.                 fixBits ((INSTR *) relAdr, relValue, relFormat);
  2095.                 FLAG_RESET (fieldOverride);
  2096.                 FLAG_RESET (dataOverride);
  2097.                 relAdr += 4;
  2098.                 }
  2099.             else if (opCode == R_FSEL)
  2100.                 {
  2101.                 /* c2: F' override */
  2102.                 fieldSel = R_FSEL;
  2103.                 fieldOverride = TRUE;
  2104.                 DBG_PUT ("R_FSELn");
  2105.                 }
  2106.             else if (opCode == R_LSEL)
  2107.                 {
  2108.                 /* c3: L'/LD'/LS'/LR' override */
  2109.                 fieldSel = R_LSEL;
  2110.                 fieldOverride = TRUE;
  2111.                 DBG_PUT ("R_LSELn");
  2112.                 }
  2113.             else if (opCode == R_RSEL)
  2114.                 {
  2115.                 /* c4: R'/RD'/RS'/RR' override */
  2116.                 fieldSel = R_RSEL;
  2117.                 fieldOverride = TRUE;
  2118.                 DBG_PUT ("R_RSELn");
  2119.                 }
  2120.             else if (opCode == R_N_MODE)
  2121.                 {
  2122.                 /* c5: set L'/R' mode */
  2123.                 modeSel = R_N_MODE;
  2124.                 DBG_PUT ("R_N_MODEn");
  2125.                 }
  2126.             else if (opCode == R_S_MODE)
  2127.                 {
  2128.                 /* c6: set LS'/RS' mode */
  2129.                 modeSel = R_S_MODE;
  2130.                 DBG_PUT ("R_N_MODEn");
  2131.                 }
  2132.             else if (opCode == R_D_MODE)
  2133.                 {
  2134.                 /* c7: set LD'/RD' mode */
  2135.                 modeSel = R_D_MODE;
  2136.                 DBG_PUT ("R_D_MODEn");
  2137.                 }
  2138.             else if (opCode == R_R_MODE)
  2139.                 {
  2140.                 /* c8: set LR'/RR' mode */
  2141.                 modeSel = R_R_MODE;
  2142.                 DBG_PUT ("R_R_MODEn");
  2143.                 }
  2144.             else if (opCode >= R_DATA_OVERRIDE && opCode < R_TRANSLATED)
  2145.                 {
  2146.                 /* c9-cd: get data from fixup area */
  2147.                 if (opCode == 201)
  2148.                     V = 0;
  2149.                 else if (opCode == 202)
  2150.                     V = sign_ext (B1, 8);
  2151.                 else if (opCode == 203)
  2152.                     V = sign_ext (B2, 16);
  2153.                 else if (opCode == 204)
  2154.                     V = sign_ext (B3, 24);
  2155.                 else /* opCode == 205 */
  2156.                     V = B4;
  2157.                 fixConstant = V;
  2158.                 dataOverride = TRUE;
  2159.                 }
  2160.             else if (opCode == R_TRANSLATED)
  2161.                 {
  2162.                 /* ce: toggle translated mode */
  2163.                 printErr ("ld error: R_TRANSLATED not supportedn");
  2164.                 }
  2165.             else if (opCode == R_AUX_UNWIND)
  2166.                 {
  2167.                 /* cf: auxiliary unwind (proc begin) */
  2168.                 int SK;
  2169.                 int SN;
  2170.                 int CN;
  2171.                 CN = B3;
  2172.                 SN = B4;
  2173.                 SK = B4;
  2174.                 }
  2175.             else if (opCode == R_COMP1)
  2176.                 {
  2177.                 /* d0: arbitrary expression */
  2178.                 opCode2 = B1;
  2179.                 V = opCode2 & 0x3f;
  2180.                 C = opCode2 & 0x1f;
  2181.                 switch (opCode2)
  2182.                     {
  2183.                     case R_PUSH_PCON1:
  2184.                         CHECK_STACK_OVER;
  2185.                         PUSH_EXPR (abs(V));
  2186.                         break;
  2187.                     case R_PUSH_DOT:
  2188.                         CHECK_STACK_OVER;
  2189.                         PUSH_EXPR ((int)relAdr);
  2190.                         break;
  2191.                     case R_MAX:
  2192.                         CHECK_STACK_UNDER;
  2193.                         top1 = POP_EXPR;
  2194.                         CHECK_STACK_UNDER;
  2195.                         top2 = POP_EXPR;
  2196.                         CHECK_STACK_OVER;
  2197.                         PUSH_EXPR (max (top1, top2));
  2198.                         break;
  2199.                     case R_MIN:
  2200.                         CHECK_STACK_UNDER;
  2201.                         top1 = POP_EXPR;
  2202.                         CHECK_STACK_UNDER;
  2203.                         top2 = POP_EXPR;
  2204.                         CHECK_STACK_OVER;
  2205.                         PUSH_EXPR (min (top1, top2));
  2206.                         break;
  2207.                     case R_ADD:
  2208.                         CHECK_STACK_UNDER;
  2209.                         top1 = POP_EXPR;
  2210.                         CHECK_STACK_UNDER;
  2211.                         top2 = POP_EXPR;
  2212.                         CHECK_STACK_OVER;
  2213.                         PUSH_EXPR (top1 + top2);
  2214.                         break;
  2215.                     case R_SUB:
  2216.                         CHECK_STACK_UNDER;
  2217.                         top1 = POP_EXPR;
  2218.                         CHECK_STACK_UNDER;
  2219.                         top2 = POP_EXPR;
  2220.                         CHECK_STACK_OVER;
  2221.                         PUSH_EXPR (top2 - top1);
  2222.                         break;
  2223.                     case R_MULT:
  2224.                         CHECK_STACK_UNDER;
  2225.                         top1 = POP_EXPR;
  2226.                         CHECK_STACK_UNDER;
  2227.                         top2 = POP_EXPR;
  2228.                         CHECK_STACK_OVER;
  2229.                         PUSH_EXPR (top1 * top2);
  2230.                         break;
  2231.                     case R_DIV:
  2232.                         CHECK_STACK_UNDER;
  2233.                         top1 = POP_EXPR;
  2234.                         CHECK_STACK_UNDER;
  2235.                         top2 = POP_EXPR;
  2236.                         CHECK_STACK_OVER;
  2237.                         PUSH_EXPR (top2 / top1);
  2238.                         break;
  2239.                     case R_MOD:
  2240.                         CHECK_STACK_UNDER;
  2241.                         top1 = POP_EXPR;
  2242.                         CHECK_STACK_UNDER;
  2243.                         top2 = POP_EXPR;
  2244.                         CHECK_STACK_OVER;
  2245.                         PUSH_EXPR (top2 % top1);
  2246.                         break;
  2247.                     case R_AND:
  2248.                         CHECK_STACK_UNDER;
  2249.                         top1 = POP_EXPR;
  2250.                         CHECK_STACK_UNDER;
  2251.                         top2 = POP_EXPR;
  2252.                         CHECK_STACK_OVER;
  2253.                         PUSH_EXPR (top1 & top2);
  2254.                         break;
  2255.                     case R_OR:
  2256.                         CHECK_STACK_UNDER;
  2257.                         top1 = POP_EXPR;
  2258.                         CHECK_STACK_UNDER;
  2259.                         top2 = POP_EXPR;
  2260.                         CHECK_STACK_OVER;
  2261.                         PUSH_EXPR (top1 | top2);
  2262.                         break;
  2263.                     case R_XOR:
  2264.                         CHECK_STACK_UNDER;
  2265.                         top1 = POP_EXPR;
  2266.                         CHECK_STACK_UNDER;
  2267.                         top2 = POP_EXPR;
  2268.                         CHECK_STACK_OVER;
  2269.                         PUSH_EXPR (top1 ^ top2);
  2270.                         break;
  2271.                     case R_NOT: 
  2272.                         CHECK_STACK_UNDER;
  2273.                         top1 = POP_EXPR;
  2274.                         CHECK_STACK_OVER;
  2275.                         PUSH_EXPR (~top1);
  2276.                         break;
  2277.                     case R_LSHIFT:
  2278.                         if (C == 0)
  2279.                             {
  2280.                             CHECK_STACK_UNDER;
  2281.                             top1 = POP_EXPR;
  2282.                             CHECK_STACK_UNDER;
  2283.                             top2 = POP_EXPR;
  2284.                             CHECK_STACK_OVER;
  2285.                             PUSH_EXPR (top2 << top1);
  2286.                             }
  2287.                         else
  2288.                             {
  2289.                             top1 = POP_EXPR;
  2290.                             PUSH_EXPR (top1 << C);
  2291.                             }
  2292.                         break;
  2293.                     case R_ARITH_RSHIFT:
  2294.                         if (C == 0)
  2295.                             {
  2296.                             CHECK_STACK_UNDER;
  2297.                             top1 = POP_EXPR;
  2298.                             CHECK_STACK_UNDER;
  2299.                             top2 = POP_EXPR;
  2300.                             CHECK_STACK_OVER;
  2301.                             PUSH_EXPR (top2 >> top1);
  2302.                             }
  2303.                         else
  2304.                             {
  2305.                             top1 = POP_EXPR;
  2306.                             PUSH_EXPR (top1 >> C);
  2307.                             }
  2308.                         break;
  2309.                     case R_LOGIC_RSHIFT:
  2310.                         if (C == 0)
  2311.                             {
  2312.                             CHECK_STACK_UNDER;
  2313.                             top1 = POP_EXPR;
  2314.                             CHECK_STACK_UNDER;
  2315.                             top2 = POP_EXPR;
  2316.                             PUSH_EXPR (((UINT)top2) >> top1);
  2317.                             }
  2318.                         else
  2319.                             {
  2320.                             top1 = POP_EXPR;
  2321.                             PUSH_EXPR (((UINT)top1) >> C);
  2322.                             }
  2323.                         break;
  2324.                     case R_PUSH_NCON1:
  2325.                         CHECK_STACK_OVER;
  2326.                         PUSH_EXPR (-abs(V));
  2327.                         break;
  2328.                     default:
  2329.                         printErr ("linker: error reading fixupsn");
  2330.                         status = ERROR;
  2331.                         break;
  2332.                     }
  2333.                 }
  2334.             else if (opCode == R_COMP2)
  2335.                 {
  2336.                 /* d1: arbitrary expression */
  2337.                 opCode2 = B1;
  2338.                 S = B3;
  2339.                 L = opCode2 & 1;
  2340.                 switch (opCode2)
  2341.                     {
  2342.                     case R_PUSH_PCON2:
  2343.                         CHECK_STACK_OVER;
  2344.                         PUSH_EXPR (abs(V));
  2345.                         break;
  2346.                     case R_PUSH_SYM:
  2347.                         CHECK_STACK_OVER;
  2348.                         PUSH_EXPR (pSym[S].symbol_value);
  2349.                         break;
  2350.                     case R_PUSH_PLABEL:
  2351.                         CHECK_STACK_OVER;
  2352.                         PUSH_EXPR (pSym[S].symbol_value);
  2353.                         break;
  2354.                     case R_PUSH_NCON2:
  2355.                         CHECK_STACK_OVER;
  2356.                         PUSH_EXPR (-abs(V));
  2357.                         break;
  2358.                     default:
  2359.                         printErr ("linker: error reading fixupsn");
  2360.                         status = ERROR;
  2361.                         break;
  2362.                     }
  2363.                 }
  2364.             else if (opCode == R_COMP3)
  2365.                 {
  2366.                 /* d2: arbitrary expression */
  2367.                 opCode2 = B1;
  2368.                 V = B4;
  2369.                 S = V & 0xffffff;
  2370.                 R = ((opCode2 & 1) << 8) | (V >> 16);
  2371.                 switch (opCode2)
  2372.                     {
  2373.                     case R_PUSH_PROC:
  2374.                         CHECK_STACK_OVER;
  2375.                         if (argRelocDiffer (pSym[S].arg_reloc, R))
  2376.                             relValue = (int)argRelocStubListFind (
  2377.                                           &argRelocStubList, pSym + S, R,
  2378.                                           moduleId);
  2379.                         else
  2380.                             relValue = pSym[S].symbol_value;
  2381.                         PUSH_EXPR (relValue);
  2382.                         break;
  2383.                     case R_PUSH_CONST:
  2384.                         CHECK_STACK_OVER;
  2385.                         PUSH_EXPR (V);
  2386.                         break;
  2387.                     default:
  2388.                         printErr ("linker: error reading fixupsn");
  2389.                         status = ERROR;
  2390.                         break;
  2391.                     }
  2392.                 WARN ("Warning: R_COMP3 fixup is untestedn");
  2393.                 }
  2394.             else if (opCode >= R_PREV_FIXUP && opCode < R_SEC_STMT)
  2395.                 {
  2396.                 /* d3-d6: apply previous fixup again */
  2397.                 X = opCode - R_PREV_FIXUP + 1;
  2398.                 DBG_PUT ("R_PREV_FIXUP - X = %dn", X);
  2399.                 /* remember our old place in the fixup stream */
  2400.                 pOldFixup = pThisFixup;
  2401.                 /* restore old fixup pointer (from list) */
  2402.                 pPrevFixupNode = (PREV_FIXUP *)lstNth (&prevFixupList, X);
  2403.                 if (pPrevFixupNode->pFixup == NULL)
  2404.                     printErr ("fixup request queue emptyn");
  2405.                 pThisFixup = pPrevFixupNode->pFixup;
  2406.                 /* remove old fixup pointer from the list */
  2407.                 lstDelete (&prevFixupList, &(pPrevFixupNode->node));
  2408.                 lstAdd (&prevFixupList, &(pPrevFixupNode->node));
  2409.                 pPrevFixupNode->pFixup = NULL;
  2410.                 usingPrevFixup = TRUE;
  2411.                 continue;
  2412.                 }
  2413.             else if (opCode == R_SEC_STMT)
  2414.                 {
  2415.                 /* d7: secondary statement number */
  2416.                 /* d8-df: reserved */
  2417.                 }
  2418.             else
  2419.                 {        
  2420.                 printErr ("loader: error reading fixup listn");
  2421.                 return (ERROR);
  2422.                 }
  2423.             if (usingPrevFixup)
  2424.                 {
  2425.                 pThisFixup = pOldFixup;
  2426.                 usingPrevFixup = FALSE;
  2427.                 }
  2428.             }
  2429.         }
  2430.     /*
  2431.      * allocate an array of unwind desciptors.
  2432.      * copy the "unwindList" into the array.
  2433.      * add the array as a module segment of type SEGMENT_UNWIND
  2434.      */
  2435.     unwindSegmentCreate (&unwindList, moduleId);
  2436.     /* free up dynamically allocated memory */
  2437.     free ((char *) pExpStack);
  2438.     lstFree (&stubList);
  2439.     lstFree (&argRelocStubList);
  2440.     lstFree (&unwindList);
  2441.     return (status);
  2442.     }
  2443. /*******************************************************************************
  2444. *
  2445. * subspaceToSegment - map subspaces into VxWorks "segments"
  2446. *
  2447. * For each subspace, we decidide if it belongs in the text, data, or
  2448. * bss segment.
  2449. * This routine alse performs partial subspace relocation by setting the
  2450. * subspace load addresses relative to zero. Full relocation will have
  2451. * to wait until we have malloc'ed text, data, and bss segments.
  2452. * We are careful to leave some space ebtween text subspaces for
  2453. * possible "long branch" stub insertion later on.
  2454. * RETURNS: N/A
  2455. */
  2456. static void subspaceToSegment 
  2457.     (
  2458.     SOM_HDR *    pHpHdr,         /* file header */
  2459.     UCHAR *      pRelocCmds,     /* relocation commands */
  2460.     SUB_INFO *   pSubInfo,       /* pointer to subspace information */
  2461.     SPACE *      pSpace,         /* pointer to space dictionary */ 
  2462.     SUBSPACE *   pSubspace,      /* pointer to subspace dictionary */ 
  2463.     SYMREC *     pSym,           /* pointer to symbol table */
  2464.     SYMTAB_ID    pSymTab,        /* symbol table */
  2465.     int *        pTextSize,      /* returns textsize */
  2466.     int *        pDataSize,      /* returns data size */ 
  2467.     int *        pBssSize        /* returns bss size */ 
  2468.     )
  2469.     {
  2470.     int  ix;
  2471.     int  tSize = 0;
  2472.     int  dSize = 0;
  2473.     int  bSize = 0;
  2474.     int  sizeExtra;
  2475.     /* locate the $LIT$ section */
  2476.     for (ix = 0; ix < pHpHdr->subspace_total; ix ++)
  2477.         {
  2478. if (!pSubspace[ix].is_loadable)
  2479.             continue;
  2480. if (!strcmp(pSubspace[ix].subspace_name, "$LIT$"))
  2481.     {
  2482.     tSize = ROUND_UP (tSize, pSubspace[ix].alignment);
  2483.     pSubInfo[ix].loadAddr = (char *)tSize;
  2484.     tSize += pSubspace[ix].subspace_length;
  2485.     pSubInfo[ix].loadType = LOAD_TEXT;
  2486.     }
  2487. }
  2488.     /* locate the $CODE$ section */
  2489.     for (ix = 0; ix < pHpHdr->subspace_total; ix ++)
  2490.         {
  2491. if (!pSubspace[ix].is_loadable)
  2492.             continue;
  2493. if (!strcmp(pSubspace[ix].subspace_name, "$CODE$"))
  2494.     {
  2495.     tSize = ROUND_UP (tSize, pSubspace[ix].alignment);
  2496.     pSubInfo[ix].loadAddr = (char *)tSize;
  2497.     tSize += pSubspace[ix].subspace_length;
  2498.     pSubInfo[ix].loadType = LOAD_TEXT;
  2499.     /* compute how much room is needed for long branch stubs */
  2500.     sizeExtra = subspaceSizeExtra (pRelocCmds, &pSubspace[ix], pSym,
  2501.    pHpHdr->symbol_total, pSymTab);
  2502.     DBG_PUT ("subspace %d sizeExtra= 0x%xn", ix, sizeExtra);
  2503.     tSize = ROUND_UP (tSize, pSubspace[ix].alignment);
  2504.     tSize += sizeExtra;
  2505.     }
  2506. }
  2507.     /* locate the $DATA$ section */
  2508.     for (ix = 0; ix < pHpHdr->subspace_total; ix ++)
  2509.         {
  2510. if (!pSubspace[ix].is_loadable)
  2511.             continue;
  2512. if (!strcmp(pSubspace[ix].subspace_name, "$DATA$"))
  2513.     {
  2514.     dSize = ROUND_UP (dSize, pSubspace[ix].alignment);
  2515.     pSubInfo[ix].loadAddr = (char *)dSize;
  2516.     dSize += pSubspace[ix].subspace_length;
  2517.     pSubInfo[ix].loadType = LOAD_DATA;
  2518.     }
  2519. }
  2520.     /* locate the $BSS$ section */
  2521.     for (ix = 0; ix < pHpHdr->subspace_total; ix ++)
  2522.         {
  2523. if (!pSubspace[ix].is_loadable)
  2524.             continue;
  2525. if (!strcmp(pSubspace[ix].subspace_name, "$BSS$"))
  2526.     {
  2527.     bSize = ROUND_UP (bSize, pSubspace[ix].alignment);
  2528.     pSubInfo[ix].loadAddr = (char *)bSize;
  2529.     bSize += pSubspace[ix].subspace_length;
  2530.     pSubInfo[ix].loadType = LOAD_BSS;
  2531.     }
  2532. }
  2533.     /* set return value */
  2534.     *pTextSize = tSize;
  2535.     *pDataSize = dSize;
  2536.     *pBssSize  = bSize;
  2537.     }
  2538. /*******************************************************************************
  2539. *
  2540. * subspaceNoReloc -
  2541. *
  2542. * Set the load address to be the same as the subspace start address.
  2543. *
  2544. * RETURNS: OK or ERROR
  2545. */
  2546. static void subspaceNoReloc
  2547.     (
  2548.     SOM_HDR *   pHpHdr,         /* file header */
  2549.     SUB_INFO *  pSubInfo,       /* pointer to subspace information */
  2550.     SUBSPACE *  pSubspace       /* pointer to subspace dictionary */
  2551.     )
  2552.     {
  2553.     int   ix;
  2554.     char *name;
  2555.     for (ix = 0; ix < pHpHdr->subspace_total; ix ++)
  2556.         {
  2557.         pSubInfo[ix].loadAddr = (char *) (pSubspace[ix].subspace_start);
  2558.         name = pSubspace[ix].subspace_name;
  2559.         if ((int)strstr (name, "BSS"))
  2560.             pSubInfo[ix].loadType = LOAD_BSS;
  2561.         }
  2562.     }
  2563. /*******************************************************************************
  2564. *
  2565. * loadSubspaces - load the subspaces with initial data from the object file.
  2566. *
  2567. * RETURNS: OK or ERROR
  2568. */
  2569. static STATUS loadSubspaces 
  2570.     (
  2571.     int           fd,
  2572.     SOM_HDR *     pHpHdr, 
  2573.     SUB_INFO *    pSubInfo, 
  2574.     SUBSPACE *    pSubspace, 
  2575.     char *        pText, 
  2576.     char *        pData, 
  2577.     char *        pBss
  2578.     )
  2579.     {
  2580.     int      ix;
  2581.     /* loop through each subspace to get info */
  2582.     for (ix = 0; ix < pHpHdr->subspace_total; ix ++)
  2583. {
  2584.         if (!pSubspace[ix].is_loadable || !pSubspace[ix].subspace_length)
  2585.     continue;
  2586.         if (pSubspace[ix].continuation)
  2587.             WARN ("Warning: continuation subspaces are untestedn");
  2588. switch (pSubInfo[ix].loadType)
  2589.     {
  2590.   case LOAD_TEXT:
  2591.     pSubInfo[ix].loadAddr += (int) pText;
  2592.     break;
  2593.   case LOAD_DATA:
  2594.     pSubInfo[ix].loadAddr += (int) pData;
  2595.     break;
  2596.   case LOAD_BSS:
  2597.     pSubInfo[ix].loadAddr += (int) pBss;
  2598.     break;
  2599.   default:
  2600.             WARN ("unknown load typen");
  2601.     break;
  2602.     }
  2603.         DBG_PUT ("subspace %d type= %d addr= 0x%x size= 0x%xn",
  2604.  ix, pSubInfo[ix].loadType, (int)pSubInfo[ix].loadAddr,
  2605.  pSubspace[ix].subspace_length);
  2606.         /* if initialization length == 0, fill subspace with pattern
  2607.          * specified by file_loc_init_value */
  2608. if (pSubspace[ix].initialization_length == 0)
  2609.     {
  2610.             DBG_PUT ("initializing subspace with pattern 0x%xn",
  2611.      pSubspace[ix].file_loc_init_value);
  2612.             *(int *)(pSubInfo[ix].loadAddr)
  2613. = pSubspace[ix].file_loc_init_value;
  2614.             bcopyLongs (pSubInfo[ix].loadAddr, pSubInfo[ix].loadAddr + 4,
  2615.                         (pSubspace[ix].subspace_length - 4)/4);
  2616.             continue;
  2617.             }
  2618.         /* if initialization length != 0, read from file into subspace */
  2619.         if (ioctl (fd, FIOSEEK, pSubspace[ix].file_loc_init_value)
  2620.                    == ERROR ||
  2621.             read (fd, pSubInfo[ix].loadAddr, pSubspace[ix].initialization_length)
  2622.     != pSubspace[ix].initialization_length)
  2623.             {
  2624.             printErr ("loadSubspaces: error reading filen");
  2625.             return (ERROR);
  2626.             }
  2627.         if (pSubspace[ix].replicate_init)
  2628.             {
  2629.             bcopy (pSubInfo[ix].loadAddr,
  2630.    pSubInfo[ix].loadAddr + pSubspace[ix].initialization_length,
  2631.    pSubspace[ix].subspace_length - pSubspace[ix].initialization_length);
  2632.             }
  2633.         }
  2634.     return (OK);
  2635.     }
  2636. /******************************************************************************
  2637. *
  2638. * argRelocDiffer - decide if the two argument relocation bit desciptors
  2639. *                  are compatable.
  2640. *
  2641. * RETURNS: TRUE if an argument relocation stub is needed.
  2642. */
  2643. static BOOL argRelocDiffer (int arg_reloc1, int arg_reloc2)
  2644.     {
  2645.     int i;
  2646.     int reloc1, reloc2;
  2647.     for (i=0; i<5; i++)
  2648.         {
  2649.         reloc1 = arg_reloc1 & 3;
  2650.         reloc2 = arg_reloc2 & 3;
  2651.         if (reloc1 && reloc2 && (reloc1 != reloc2))
  2652.             return (TRUE);
  2653.         arg_reloc1 >>= 2;
  2654.         arg_reloc2 >>= 2;
  2655.         }
  2656.     return (FALSE);
  2657.     }
  2658. /******************************************************************************
  2659. *
  2660. * subspaceSizeExtra - calculate additional space needed for a subspace
  2661. *
  2662. * This routine calculates additional storage space needed for each
  2663. * subspace. It is used to reserve space for "long branch stubs"
  2664. * which we must insert later if a fixup request for a PC relative call
  2665. * can't be stuffed into a 19 bit immediate.
  2666. *
  2667. * RETURNS number of additional bytes needed
  2668. */
  2669. static int subspaceSizeExtra
  2670.     (
  2671.     UCHAR *    pRelCmds,        /* address of relocation commands */
  2672.     SUBSPACE * pSubspace,       /* subspace index */
  2673.     SYMREC *   pSym,            /* pointer to symbol records */
  2674.     int        numSyms,         /* maximun number of symbols */
  2675.     SYMTAB_ID  symTblId
  2676.     )
  2677.     {
  2678.     UCHAR *  pNextFixup;             /* current fixup request pointer */
  2679.     UCHAR *  pLastFixup;             /* last fixup request pointer */
  2680.     UCHAR    opCode;                 /* fixup request opCode */
  2681.     int      symNum;
  2682.     int      R;
  2683.     LIST     stubList;
  2684.     int      numStubs;
  2685.     lstInit (&stubList);
  2686.     if (pSubspace->fixup_request_quantity == 0)
  2687.         return (0);
  2688.     pNextFixup = pRelCmds + pSubspace->fixup_request_index;
  2689.     pLastFixup = pNextFixup + pSubspace->fixup_request_quantity;
  2690.     while (pNextFixup < pLastFixup)
  2691.         {
  2692.         opCode = *pNextFixup;
  2693.         R = 0;
  2694.         /* do we have a pc-relative call fixup request? */
  2695.         /* SPR 22030 :Changed R_ABS_CALL below to 62 */
  2696.         if ( (opCode >= R_PCREL_CALL) && (opCode < 62) )
  2697.             {
  2698.             /* if so, get the symbol index we are calling */
  2699.             if (opCode <= 57)
  2700.                 {
  2701.                 R = rbits1 ((int)opCode - R_PCREL_CALL);
  2702.                 symNum = *(pNextFixup + 1);
  2703.                 }
  2704.             else if (opCode <= 59)
  2705.                 {
  2706.                 R = rbits2 ( (((int)opCode - 58)<<8) + *(pNextFixup+1) );
  2707.                 symNum = *(pNextFixup + 2);
  2708.                 }
  2709.             else
  2710.                 {
  2711.                 R = rbits2 ( (((int)opCode - 60)<<8) + *(pNextFixup+1) );
  2712.                 symNum = ((int)(*(pNextFixup + 2)) << 16) +
  2713.                          ((int)(*(pNextFixup + 3)) << 8) +
  2714.                          *(pNextFixup + 4);
  2715.                 }
  2716.             DBG_PUT ("sizeExtra: symNum = %d n", symNum);
  2717.             if (stubListFind (&stubList, symNum, R) == -1)
  2718. {
  2719. SYMREC tmp;
  2720. int arg_reloc;
  2721. int parm_reloc;
  2722. if (externSymResolve(symTblId, pSym[symNum].symbol_name, &tmp) == OK)
  2723.     arg_reloc = tmp.arg_reloc;
  2724.                 else
  2725.     arg_reloc = pSym[symNum].arg_reloc;
  2726.                 if (!arg_reloc)
  2727.     WARN("symbol %s has arg_reloc of zero.n",
  2728. pSym[symNum].symbol_name);
  2729. /* Now make sure we don't get a duplicate entry */
  2730. if (stubListFind(&stubList, symNum, tmp.arg_reloc) == -1)
  2731.     stubListAdd (&stubList, symNum, tmp.arg_reloc);
  2732. /* Now see if we need a parm reloc stub */
  2733. parm_reloc = (tmp.arg_reloc & 0x03f3) | 0x0c;
  2734. if (argRelocDiffer(R, tmp.arg_reloc)
  2735.     && !argRelocDiffer(R, parm_reloc))
  2736.     {
  2737.     stubListAdd (&stubList, symNum, parm_reloc);
  2738.     }
  2739.                 }
  2740.             }
  2741.         if (fixupLen [opCode] == 0)
  2742.             {
  2743.             printErr ("subspaceSizeExtra: error reading fixup table.n");
  2744.             break;
  2745.             }
  2746.         pNextFixup += fixupLen [opCode];
  2747.         }
  2748.     numStubs = lstCount (&stubList);
  2749.     lstFree (&stubList);
  2750.     return (numStubs*stubSize);
  2751.     }
  2752. /******************************************************************************
  2753. *
  2754. * externSymResolve - look up a MY_SYMBOL in the VxWorks symbol table.
  2755. */
  2756. static BOOL externSymResolve
  2757.     (
  2758.     SYMTAB_ID symTblId,
  2759.     char *    name,
  2760.     SYMREC *  pSym
  2761.     )
  2762.     {
  2763.     MY_SYMBOL *pSymbol;
  2764.     MY_SYMBOL keySym;
  2765.     keySym.name = name;
  2766.     keySym.type = N_EXT;
  2767.     pSymbol = (MY_SYMBOL *)hashTblFind (symTblId->nameHashId,
  2768.                                        &keySym.nameHNode, N_EXT);
  2769.     if (pSymbol == NULL)
  2770.         return (ERROR);
  2771.     pSym->symbol_value = (int)pSymbol->value;
  2772.     pSym->arg_reloc    = (pSymbol->arg_reloc << 2) | ((pSymbol->type >> 6) & 3);
  2773.     return (OK);
  2774.     }
  2775. /******************************************************************************
  2776. *
  2777. * externSymAdd - add a MY_SYMBOL to the VxWorks symbol table.
  2778. */
  2779. static BOOL externSymAdd
  2780.     (
  2781.     SYMTAB_ID symTblId,
  2782.     char *    name,
  2783.     char      *value,           /* symbol address */
  2784.     SYM_TYPE  type,             /* symbol type */
  2785.     UINT16    group,            /* symbol group */
  2786.     UCHAR     arg_reloc
  2787.     )
  2788.     {
  2789.     SYMBOL *pSymbol = symAlloc (symTblId, name, value, type, group);
  2790.     if (pSymbol == NULL)                        /* out of memory? */
  2791.         return (ERROR);
  2792.     ((MY_SYMBOL *)pSymbol)->arg_reloc = arg_reloc;
  2793.     if (symTblAdd (symTblId, pSymbol) != OK)    /* try to add symbol */
  2794.         {
  2795.         symFree (symTblId, pSymbol);            /* deallocate symbol if fail */
  2796.         return (ERROR);
  2797.         }
  2798.     return (OK);
  2799.     }
  2800. /******************************************************************************
  2801. *
  2802. * rbitsShow - Display the 10 bit argument relocation info in human readable
  2803. *             form.
  2804. */
  2805. static void rbitsShow (int x)
  2806.     {
  2807.     int i;
  2808.     DBG_PUT ("(");
  2809.     for (i=0; i<4; i++)
  2810.         {
  2811.         switch ((x >> (8 - 2*i)) & 3)
  2812.             {
  2813.             case 0:
  2814.                 DBG_PUT ("? ");
  2815.                 break;
  2816.             case 1:
  2817.                 DBG_PUT ("int ");
  2818.                 break;
  2819.             case 2:
  2820.                 DBG_PUT ("float ");
  2821.                 break;
  2822.             case 3:
  2823.                 DBG_PUT ("double ");
  2824.                 break;
  2825.             }
  2826.         DBG_PUT ("arg%d", i);
  2827.         if (i != 3)
  2828.             DBG_PUT (", ");
  2829.         }
  2830.     DBG_PUT (")");
  2831.     DBG_PUT (". Returns: ");
  2832.     switch (x & 3)
  2833.         {
  2834.         case 0:
  2835.             DBG_PUT ("?n");
  2836.             break;
  2837.         case 1:
  2838.             DBG_PUT ("intn");
  2839.             break;
  2840.         case 2:
  2841.             DBG_PUT ("floatn");
  2842.             break;
  2843.         case 3:
  2844.             DBG_PUT ("doublen");
  2845.             break;
  2846.         }
  2847.     }
  2848. /******************************************************************************
  2849. *
  2850. * rbits1 - return the 10 argument relocation bits encoded in a fixup.
  2851. */
  2852. static int rbits1 (int x)
  2853.     {
  2854.     return ( ((0x55 & ~((1 << 2*(4 - (x % 5))) - 1)) << 2) | (x/5));
  2855.     }
  2856. /******************************************************************************
  2857. *
  2858. * rbits2 - return the 10 argument relocation bits encoded in a fixup.
  2859. */
  2860. static int rbits2 (int x)
  2861.     {
  2862.     int args01;
  2863.     int args23;
  2864.     int arg0, arg1, arg2, arg3;
  2865.     args01 = (x>>2) / 10;
  2866.     if (args01 == 9)
  2867.         {
  2868.         arg0 = 0;
  2869.         arg1 = 3;
  2870.         }
  2871.     else
  2872.         {
  2873.         arg0 = args01 / 3;
  2874.         arg1 = args01 % 3;
  2875.         }
  2876.     args23 = (x>>2) % 10;
  2877.     if (args23 == 9)
  2878.         {
  2879.         arg2 = 0;
  2880.         arg3 = 3;
  2881.         }
  2882.     else
  2883.         {
  2884.         arg2 = args23 / 3;
  2885.         arg3 = args23 % 3;
  2886.         }
  2887.     return ((arg0 << 8) | (arg1 << 6) | (arg2 << 4) | (arg3 << 2) | (x & 3));
  2888.     }
  2889. /******************************************************************************
  2890. *
  2891. * stubListFind - find a long branch stub in the list.
  2892. *
  2893. * RETURNS: the index in the list of the stub, or -1 if the stub isn't found.
  2894. */
  2895. static int stubListFind
  2896.     (
  2897.     LIST *stubList,
  2898.     int symNum,
  2899.     int arg_reloc
  2900.     )
  2901.     {
  2902.     STUB_LIST_NODE *pNode;
  2903.     int i = 0;
  2904.     for (pNode = (STUB_LIST_NODE *)lstFirst(stubList);
  2905.         pNode != NULL;
  2906.         pNode = (STUB_LIST_NODE *)lstNext(&(pNode->node)))
  2907.         {
  2908.         if ( (pNode->symNum == symNum) &&
  2909.             !argRelocDiffer (pNode->arg_reloc, arg_reloc))
  2910.             break;
  2911.         i++;
  2912.         }
  2913.     return (pNode == NULL ? -1 : i);
  2914.     }
  2915. /******************************************************************************
  2916. *
  2917. * stubListAdd - add a long branch stub to the list.
  2918. */
  2919. static int stubListAdd
  2920.     (
  2921.     LIST *stubList,
  2922.     int symNum,
  2923.     int arg_reloc
  2924.     )
  2925.     {
  2926.     STUB_LIST_NODE *pNode;
  2927.     pNode = (STUB_LIST_NODE *)malloc (sizeof(STUB_LIST_NODE));
  2928.     pNode->symNum = symNum;
  2929.     pNode->arg_reloc = arg_reloc;
  2930.     lstAdd (stubList, &(pNode->node));
  2931.     return (lstCount(stubList) - 1);
  2932.     }
  2933. /******************************************************************************
  2934. *
  2935. * stubInit - initialize a long branch stub at address stubAddr. The stub
  2936. *            created branches to the procedure at procAddr.
  2937. */
  2938. static void stubInit
  2939.     (
  2940.     char *stubAddr,
  2941.     char *procAddr
  2942.     )
  2943.     {
  2944.     bcopy ((char *)longBranchStub, stubAddr, stubSize);
  2945.     fixBits ((INSTR *)stubAddr, (int)procAddr, i_exp21);
  2946.     fixBits ((INSTR *)(stubAddr+4), (int)procAddr & 0x7ff, i_rel12);
  2947.     }
  2948. /******************************************************************************
  2949. *
  2950. * argRelocStubCreate - create an argument relocation stub.
  2951. *
  2952. * The stub created relocates the arguments from the arg_reloc format
  2953. * to the pSym->arg_reloc format, and then branches to procAddr.
  2954. *
  2955. * RETURNS: the address of the newly created stub. If a stub cannot be
  2956. *          generated (we currently only support one type of stub),
  2957. *          then an error message is printed and NULL is returned.
  2958. */
  2959. static char *argRelocStubCreate
  2960.     (
  2961.     SYMREC * pSym,
  2962.     int      arg_reloc,
  2963.     char *   procAddr
  2964.     )
  2965.     {
  2966.     char *   stubAddr;
  2967.     int      parm_reloc;
  2968.    /*
  2969.     * This is the stub code for parameter relocation if the second parameter
  2970.     * is passed in a double persion floating point register, and must be
  2971.     * move to the general registers.
  2972.     * Currently, this is the only parameter relocation stub this linker
  2973.     * generates, but it would be a simple matter to add others.
  2974.     */
  2975.     static int argReloc_double_to_regs[5] =
  2976.         {
  2977.         0x2fd01227,     /* FSTDS,MA fr7, 8(r30)   */
  2978.         0x0fd91098,     /* LDWS     -4(r30),r24   */
  2979.         0x0fd130b7,     /* LDWS,MB  -8(r30),r23   */
  2980.         0x20200000,     /* LDIL    0, r1          */
  2981.         0xe0202002      /* BE,n    0(s4, r1)      */
  2982.         };
  2983.     parm_reloc = (pSym->arg_reloc & 0x03f3) | 0x0c;
  2984.     if (!argRelocDiffer (parm_reloc, arg_reloc))
  2985.         {
  2986.         int oldLoadSomCoffDebug = loadSomCoffDebug;
  2987.         loadSomCoffDebug = 1;
  2988.         printErr ("Link error: You called %s ");
  2989.         rbitsShow (arg_reloc);
  2990.         printErr ("But it is supposed to be called as ");
  2991.         rbitsShow (pSym->arg_reloc);
  2992.         printErr ("Unable to relocate these parameters between ");
  2993.         printErr ("the floating point and general purpose registers!n");
  2994.         loadSomCoffDebug = oldLoadSomCoffDebug;
  2995.         return (NULL);
  2996.         }
  2997.     stubAddr = (char *)malloc (sizeof (argReloc_double_to_regs));
  2998.     DBG_PUT ("creating arg_reloc stub at 0x%x, which jumps to %sn",
  2999.               (int)stubAddr, pSym->symbol_name);
  3000.     bcopy ((char *)argReloc_double_to_regs, stubAddr,
  3001.            sizeof (argReloc_double_to_regs));
  3002.     fixBits ((INSTR *)(stubAddr + 12), (int)procAddr, i_exp21);
  3003.     fixBits ((INSTR *)(stubAddr + 16), (int)procAddr & 0x7ff, i_rel12);
  3004.     return (stubAddr);
  3005.     }
  3006. /******************************************************************************
  3007. *
  3008. * argRelocStubListAdd - put an argument relocation stub into the list.
  3009. *
  3010. * After the stub is created, we add a node to the list which points to
  3011. * the stub. This way we can keep track of the stubs already generated
  3012. * so we don't generate the same stub twice.
  3013. */
  3014. static BOOL argRelocStubListAdd
  3015.     (
  3016.     LIST *   stubList,
  3017.     SYMREC * pSym,
  3018.     int      arg_reloc,
  3019.     char *   stubAddr
  3020.     )
  3021.     {
  3022.     ARG_RELOC_NODE *pNode;
  3023.     pNode = (ARG_RELOC_NODE *)malloc (sizeof(ARG_RELOC_NODE));
  3024.     if (pNode == NULL)
  3025.         return (ERROR);
  3026.     pNode->pSym = pSym;
  3027.     pNode->arg_reloc = arg_reloc;
  3028.     pNode->stubAddr = stubAddr;
  3029.     lstAdd (stubList, &pNode->node);
  3030.     return (OK);
  3031.     }
  3032. /******************************************************************************
  3033. *
  3034. * argRelocStubListFind - Find an argument relocation stub in the list.
  3035. *                 If it doesn;t exist, create it and add it to the list.
  3036. *
  3037. * RETURNS: the address of the stub.
  3038. */
  3039. static char *argRelocStubListFind
  3040.     (
  3041.     LIST *    stubList,
  3042.     SYMREC *  pSym,
  3043.     int       arg_reloc,
  3044.     MODULE_ID moduleId
  3045.     )
  3046.     {
  3047.     ARG_RELOC_NODE *pNode;
  3048.     char *    stubAddr;
  3049.     int       parm_reloc;
  3050.     for (pNode = (ARG_RELOC_NODE *)lstFirst(stubList);
  3051.         pNode != NULL;
  3052.         pNode = (ARG_RELOC_NODE *)lstNext(&(pNode->node)))
  3053.         {
  3054.         if ( (pNode->pSym == pSym) &&
  3055.             !argRelocDiffer (pNode->arg_reloc, arg_reloc))
  3056.             {
  3057.             DBG_PUT ("found stub at 0x%xn", (int)pNode->stubAddr);
  3058.             return (pNode->stubAddr);
  3059.             }
  3060.         }
  3061.     stubAddr = argRelocStubCreate (pSym, arg_reloc,
  3062.                                   (char *)(pSym->symbol_value));
  3063.     if (stubAddr == NULL)
  3064.         return (NULL);
  3065.     moduleSegAdd (moduleId, SEGMENT_STUB, stubAddr, 0, SEG_FREE_MEMORY);
  3066.     parm_reloc = (arg_reloc & 0x03f3) | 0x0c;
  3067.     if (argRelocStubListAdd (stubList, pSym, parm_reloc, stubAddr) == ERROR)
  3068.         return (NULL);
  3069.     return (stubAddr);
  3070.     }
  3071. /******************************************************************************
  3072. *
  3073. * unwindSegmentCreate - Create a stack unwind segement for a module.
  3074. *
  3075. * This routine takes a sorted linked list of stack unwind descriptors.
  3076. * It uses this list to create an unwind segment for the module.
  3077. * The unwind segment is needed by the stack tracer.
  3078. */
  3079. static void unwindSegmentCreate
  3080.     (
  3081.     LIST *    unwindList,
  3082.     MODULE_ID moduleId
  3083.     )
  3084.     {
  3085.     UNWIND_DESC * unwindArray;
  3086.     UNWIND_NODE * pThisNode;
  3087.     int           numDescs;
  3088.     int           i;
  3089.     numDescs = lstCount(unwindList);
  3090.     unwindArray = calloc (numDescs, sizeof (UNWIND_DESC));
  3091.     if (unwindArray == NULL)
  3092.         {
  3093.         printErr ("load error: can't allocate stack unwind descriptorsn");
  3094.         return;
  3095.         }
  3096.     DBG_PUT ("initializing unwind array of size %d at 0x%xn", 
  3097.               (int)numDescs, (int)unwindArray);
  3098.     for (pThisNode = (UNWIND_NODE *)lstFirst (unwindList), i = 0;
  3099.          (pThisNode != NULL) && (i < numDescs);
  3100.          pThisNode = (UNWIND_NODE *)lstNext (&pThisNode->node), i++)
  3101.         {
  3102.         bcopy ((char *)(&pThisNode->unwindDesc), (char *)(unwindArray + i),
  3103.                sizeof (UNWIND_DESC));
  3104.         }
  3105.     moduleSegAdd (moduleId, SEGMENT_UNWIND, (void *)unwindArray,
  3106.                   sizeof (UNWIND_DESC) * numDescs, SEG_FREE_MEMORY);
  3107.     }
  3108. /******************************************************************************
  3109. *
  3110. * unwindListAdd - add a stack unwind descriptor to a list.
  3111. *
  3112. * The desciptor is sorted into the list.
  3113. */
  3114. static void unwindListAdd
  3115.     (
  3116.     LIST *        unwindList,
  3117.     UNWIND_NODE * pUnwindNode
  3118.     )
  3119.     {
  3120.     UNWIND_NODE * pThisNode;
  3121.     for (pThisNode = (UNWIND_NODE *)lstLast (unwindList);
  3122.          pThisNode != NULL;
  3123.          pThisNode = (UNWIND_NODE *)lstPrevious (&pThisNode->node))
  3124.         {
  3125.         if (pUnwindNode->unwindDesc.startAddr > pThisNode->unwindDesc.startAddr)
  3126.             break;
  3127.         }
  3128.     lstInsert (unwindList, &pThisNode->node, &pUnwindNode->node);
  3129.     }