C6474 required changes
[keystone-rtos/ibl.git] / src / interp / coff / cload.mike.c
1 /***************************************************************************
2 * FILENAME: cload.c
3 * VERSION:  2.6  5/2/96  13:11:03
4 * SCCS ID:  "@(#)cload.c        2.6  5/2/96"
5 ***************************************************************************/
6 /******************************************************************************/
7 /* CLOAD.C  - Generic COFF Loader                      Version 6.00 4/96      */
8 /******************************************************************************/
9 /*                                                                            */
10 /*  This module contains functions to read in and load a COFF object file.    */
11 /*  The following routines are defined here:                                  */
12 /*                                                                            */
13 /*    cload()           - Main driver for COFF loader.                        */
14 /*    cload_headers()   - Read in the various headers of the COFF file.       */
15 /*    cload_data()      - Read in the raw data and load it into memory.       */
16 /*    cload_sect_data() - Read, relocate, and write out one section.          */
17 /*    cload_cinit()     - Process one buffer of C initialization records.     */
18 /*    cload_symbols()   - Read in the symbol table.                           */
19 /*    cload_strings()   - Read in the string table.                           */
20 /*    str_free()        - Free a string table.                                */
21 /*    sym_read()        - Read and relocate a symbol and its aux entry.       */
22 /*    sym_name()        - Return a pointer to the name of a symbol.           */
23 /*    sym_add_name()    - Add a symbol name to the string table.              */
24 /*    reloc_add()       - Add a symbol to the relocation symbol table.        */
25 /*    relocate()        - Perform a single relocation.                        */
26 /*    reloc_read()      - Read in and swap one relocation entry.              */
27 /*    reloc_size()      - Return the field size of a relocation type.         */
28 /*    reloc_offset()    - Return the field offset of a relocation type.       */
29 /*    reloc_stop()      - Return the number of bits to read for a reloc type. */
30 /*    sym_reloc_amount()- Return relocation amount for a relocation entry.    */
31 /*    unpack()          - Extract a relocation field from object bytes.       */
32 /*    repack()          - Encode a relocated field into object bytes.         */
33 /*    cload_lineno()    - Read in & swap line number entries.                 */
34 /*    swap4byte()       - Swap the order of bytes in a int.                  */
35 /*    swap2byte()       - Swap the order of bytes in a short.                 */
36 /*                                                                            */
37 /*  The loader calls the following external functions to perform application  */
38 /*  specific tasks:                                                           */
39 /*                                                                            */
40 /*   set_reloc_amount() - Define relocation amounts for each section.         */
41 /*   mem_write()        - Load a buffer of data into memory.                  */
42 /*   lookup_sym()       - Look up a symbol in an external symbol table.       */
43 /*   load_syms()        - Build the symbol table for the application.         */
44 /*   load_msg()         - Write diagnostic messages during loading.           */
45 /*                                                                            */
46 /******************************************************************************/
47 #include "types.h"
48 #include "ibl.h"
49 #include "iblloc.h"
50 #include "iblcfg.h"
51 #include "coff.h"
52 #include "coff_trg.h"
53 #include "cload.h"
54 #include <string.h>
56 #if (FILE_BASED)
57 #include <stdio.h>
58 #endif
59 /*----------------------------------------------------------------------------*/
60 /* CONSTANTS, MACROS, VARIABLES, AND STRUCTURES FOR THE LOADER.               */
61 /*----------------------------------------------------------------------------*/
62 #define MIN(a,b) ((a)<(b)?(a):(b))
63 #define MAX(a,b) ((a)>(b)?(a):(b))
65 #define TRUE 1
66 #define FALSE 0
67 #define WORDSZ sizeof(T_DATA)           /* SIZE OF DATA UNITS IN OBJ FILE     */
69 #ifdef TMS320C60
70    extern int target_coff (unsigned short flags);
71 #endif
73 /*----------------------------------------------------------------------------*/
74 /* APPLICATION VARIABLES                                                      */
75 /*----------------------------------------------------------------------------*/
76 #if (FILE_BASED)
77 FILE   *fin;                                                    /* INPUT FILE                         */
78 #else
79 /* extern unsigned char gRxBuffer[0x400040]; */
80 extern unsigned char gRxBuffer[0x10];
81 #endif
83 unsigned char gRxBuffer[0x10];
86 int     need_data    = TRUE;            /* APPLICATION NEEDS RAW DATA         */
87 int     need_symbols = FALSE;           /* APPLICATION NEEDS SYMBOL TABLE     */
88 int     clear_bss    = FALSE;           /* CLEAR BSS SECTION                  */
91 /*----------------------------------------------------------------------------*/
92 /* FILL VALUES TO BE USED BY LOADERS                                          */
93 /*----------------------------------------------------------------------------*/
94 #if defined(OTIS)
95 extern int fill_bss;
96 extern int fill_bss_value;
97 #else
98 #define fill_bss 0
99 #define fill_bss_value 0
100 #endif
102 /*----------------------------------------------------------------------------*/
103 /* LOADER VARIABLES                                                           */
104 /*----------------------------------------------------------------------------*/
105 FILHDR  file_hdr;                       /* FILE HEADER STRUCTURE              */
106 int     coff_version;                   /* COFF VERSION USED IN FILE          */
107 AOUTHDR o_filehdr;                      /* OPTIONAL (A.OUT) FILE HEADER       */
108 T_ADDR  entry_point;                    /* ENTRY POINT OF MODULE              */
109 T_ADDR *reloc_amount = NULL;            /* AMOUNT OF RELOCATION PER SECTION   */
110 int     n_sections;                     /* NUMBER OF SECTIONS IN THE FILE     */
111 int     big_e_target;                   /* TARGET DATA IN BIG-ENDIAN FORMAT   */
112 int     byte_swapped;                   /* BYTE ORDERING OPPOSITE OF HOST     */
113 int     curr_sect;                      /* SECTION NUMBER CURRENTLY LOADING   */
114 int     load_err;                       /* ERROR CODE RETURNED IF LOADER FAILS*/
115 struct strtab *str_head = NULL;         /* LIST OF STRING TABLE BUFFERS       */
117 static T_SIZE  init_size = 0;           /* CURRENT SIZE OF C INITIALIZATION   */
118 static int     need_reloc;              /* RELOCATION REQUIRED                */
121 int  n_array_sections;                  /* The number of sections in sect_hdrs */
123 SCNHDR   sect_hdrs[MAX_COFF_SECTION_HEADERS];  /* Array of loadable sections */
124 O_SCNHDR o_sect_hdrs;                          /* A single old section header */
126 unsigned int paBuf[LOADBUFSIZE];        /* Temp buffer for packet load */
128 int stream_offset;                      /* The current stream offset */
129                             
131 #if TMS320C60
132 int big_e_config = TRG_DEF_BIG_E;       /* ENDIANNESS CONFIGURATION           */
133 #else
134 int big_e_config = DONTCARE;            /* ENDIANNESS CONFIGURATION           */
135 #endif
137 /*----------------------------------------------------------------------------*/
138 /* THIS STRUCTURE IS USED TO STORE THE RELOCATION AMOUNTS FOR SYMBOLS.        */
139 /* EACH RELOCATABLE SYMBOL HAS A CORRESPONDING ENTRY IN THIS TABLE.           */
140 /* THE TABLE IS SORTED BY SYMBOL INDEX; LOOKUP USES A BINARY SEARCH.          */
141 /*----------------------------------------------------------------------------*/
142 typedef struct
144    int rt_index;                       /* INDEX OF SYMBOL IN SYMBOL TABLE    */
145    int rt_disp;                        /* AMOUNT OF RELOCATION               */
146 } RELOC_TAB;
148 /*----------------------------------------------------------------------------*/
149 /* THE RELOCATION SYMBOL TABLE IS ALLOCATED DYNAMICALLY, AND REALLOCATED      */
150 /* AS MORE SPACE IS NEEDED.                                                   */
151 /*----------------------------------------------------------------------------*/
152 #define RELOC_TAB_START 128             /* STARTING SIZE OF TABLE             */
153 #define RELOC_GROW_SIZE 128             /* REALLOC AMOUNT FOR TABLE           */
155 static RELOC_TAB *reloc_tab = NULL;     /* RELOCATION SYMBOL TABLE            */
157 static int        reloc_tab_size;       /* CURRENT ALLOCATED AMOUNT           */
158 static int        reloc_sym_index;      /* CURRENT SIZE OF TABLE              */
160 /*----------------------------------------------------------------------------*/
161 /* RUN-TIME RELOCATION (AS OPPOSED TO LOAD-TIME) RELOCATION IS DETERMINED     */
162 /* AS FOLLOWS:  IF THE SECTION'S RUNTIME ADDRESS == LOADTIME ADDRESS, USE     */
163 /* LOADTIME RELOCATION.  OTHERWISE, ASSUME LOADTIME RELOC ONLY (RUNTIME RELOC */
164 /* == 0).                                                                     */
165 /*----------------------------------------------------------------------------*/
166 #define RUN_RELOC_AMOUNT(i) ((SECT_HDR(i)->s_paddr == SECT_HDR(i)->s_vaddr) ?  \
167                                     reloc_amount[i] : 0)
169 /*----------------------------------------------------------------------------*/
170 /* DEFINE A STRUCTURE FOR STRING TABLE BUFFERS.  THESE BUFFERS ARE STORED     */
171 /* AS A LINKED LIST OF MEMORY PACKETS, EACH CONTAINING UP TO 64K OF THE       */
172 /* STRING TABLE.                                                              */
173 /*----------------------------------------------------------------------------*/
174 typedef struct strtab
176    unsigned int  size;                 /* SIZE OF THIS PACKET                */
177    unsigned int  offset;               /* STARTING OFFSET OF THIS PACKET     */
178    unsigned int  index;                /* AMOUNT CURRENTLY FILLED            */
179    struct strtab *next;                 /* NEXT BUFFER                        */
180    char           buf[1];               /* STRING DATA (EXPAND AS ALLOCATED)  */
181 } STRTAB;
183 #define MAX_STRING_ALLOC (unsigned int)(0xffff-sizeof(STRTAB)+1)
184                                        /* MAX STRING BUFFER: 64K (SMALL HOSTS)*/
185 #define MIN_STRING_ALLOC 0x0400        /* MIN STRING BUFFER: 1K               */
187 unsigned int unpack();
189 /* extern void mem_copy(unsigned char* dst, unsigned char* src, int nbytes); */
190 #define mem_copy(dest,src,nbytes) memcpy((void *)(dest),(void *)(src),nbytes)
191 #define mem_write(buf, nbytes, addr, page)  memcpy((void *)(addr),(void *)(buf),nbytes)
192 #define str_comp strcmp
193 /******************************************************************************/
194 /*                                                                            */
195 /* CLOAD() - Main driver for COFF loader.                                     */
196 /*                                                                            */
197 /******************************************************************************/
198 int cload(BOOT_MODULE_FXN_TABLE *bootFxn, Uint32 *ientry_point)
200    int result;
202    load_err      = 0;
203    stream_offset = 0;
204    result        = cload_headers(bootFxn, ientry_point) && cload_data(bootFxn);
206    if (reloc_tab) free(reloc_tab);
207    reloc_tab = NULL;
209    if(result == TRUE)
210        return 0;
211    else  {
212        *ientry_point = 0;
213        return -1;
214    }
217 \f
218 /******************************************************************************/
219 /*                                                                            */
220 /* CLOAD_HEADERS() - Read in the various headers of the COFF file.            */
221 /*                                                                            */
222 /******************************************************************************/
223 int cload_headers(BOOT_MODULE_FXN_TABLE *bootFxn, Uint32 *ientry_point)
225    int i;
227    byte_swapped = FALSE;
228    need_reloc   = FALSE;
230    *ientry_point = NULL;   /* Error return value */
232     if ((*bootFxn->read)((Uint8 *)&file_hdr, FILHSZ) < 0)
233         return (FALSE);
234     stream_offset += FILHSZ;
237    /*-------------------------------------------------------------------------*/
238    /* MAKE SURE THIS IS REALLY A COFF FILE. CHECK FOR SWAPPED FILES.          */
239    /* DETERMINE BYTE ORDERING OF OBJECT DATA.                                 */
240    /*-------------------------------------------------------------------------*/
241    if (!ISCOFF(file_hdr.f_magic))
242    {
243        swap2byte(&file_hdr.f_magic);
245        if (!ISCOFF(file_hdr.f_magic)) { load_err = E_MAGIC; return FALSE; }
247        byte_swapped = TRUE;
249        swap2byte(&file_hdr.f_nscns);  swap4byte(&file_hdr.f_timdat);
250        swap4byte(&file_hdr.f_symptr); swap4byte(&file_hdr.f_nsyms);
251        swap2byte(&file_hdr.f_opthdr); swap2byte(&file_hdr.f_flags);
252 #if COFF_VERSION_1 || COFF_VERSION_2
253        swap2byte(&file_hdr.f_target_id); 
254 #endif
255    }
257    /*-------------------------------------------------------------------------*/
258    /* DETERMINE THE ENDIANNESS OF THE COFF FILE, AND ENSURE THE ENDIANNESS OF */
259    /* THE FILE IS THE SAME AS THE TARGET, IF THERE IS A TARGET.               */
260    /*-------------------------------------------------------------------------*/
261    big_e_target = ((file_hdr.f_flags & F_BIG) != 0);
262    if (big_e_config != DONTCARE && big_e_target != big_e_config) 
263       { load_err = E_ENDIAN; return FALSE; }
265    /*-------------------------------------------------------------------------*/
266    /* DETERMINE VERSION OF COFF BEING USED, CHECK TARGET ID IF NEEDED.        */
267    /*-------------------------------------------------------------------------*/
268    if (ISCOFF_1(file_hdr.f_magic) || ISCOFF_2(file_hdr.f_magic))
269    {
270        if (!ISMAGIC(file_hdr.f_target_id)) { load_err = E_MAGIC; return FALSE; }
271        coff_version = file_hdr.f_magic;
272    } 
273    else coff_version = COFF_MAGIC_0;
275 #ifdef TMS320C60
276    /*-------------------------------------------------------------------------*/
277    /* DETERMINE WHETHER THE RIGHT COFF IS BEING LOADED                        */
278    /*-------------------------------------------------------------------------*/
279    if ( !target_coff( file_hdr.f_flags) )
280        { load_err = E_FILE; return FALSE; }
281 #endif
282  
283    /*-------------------------------------------------------------------------*/
284    /* READ IN OPTIONAL HEADER, IF THERE IS ONE, AND SWAP IF NEEDED.           */
285    /*-------------------------------------------------------------------------*/
286    if (file_hdr.f_opthdr == AOUTSZ)
287    {
289     if ((*bootFxn->read)((Uint8 *)&o_filehdr, file_hdr.f_opthdr) < 0)
290         return (FALSE);
291     stream_offset += file_hdr.f_opthdr;
293       if (byte_swapped)
294       {
295           swap2byte(&o_filehdr.magic);      swap2byte(&o_filehdr.vstamp);
296           swap4byte(&o_filehdr.tsize);      swap4byte(&o_filehdr.dsize);
297           swap4byte(&o_filehdr.bsize);      swap4byte(&o_filehdr.entrypt);
298           swap4byte(&o_filehdr.text_start); swap4byte(&o_filehdr.data_start);
299       }
301       entry_point   = o_filehdr.entrypt;
302       *ientry_point = entry_point;
303    }
305    /*-------------------------------------------------------------------------*/
306    /* Read in string table so that we can see long section names, if needed.  */
307    /* This used tobe read right before the symbol table was read, but now the */
308    /* section headers use "flexname" method to specify section names and so   */
309    /* might need access to a string table entry.                              */
310    /*-------------------------------------------------------------------------*/
311    //if (!cload_strings()) return FALSE;
313    /*-------------------------------------------------------------------------*/
314    /* READ IN SECTION HEADERS.                                                */
315    /*-------------------------------------------------------------------------*/
317    n_array_sections = 0;
318    for (i = 0; i < file_hdr.f_nscns; i++)  {
320      SCNHDR   *sptr = (SCNHDR *)&sect_hdrs[n_array_sections];
321      O_SCNHDR *tptr = (O_SCNHDR *)&o_sect_hdrs;
323      if (ISCOFF_2(coff_version))  {
325         if ((*bootFxn->read)((Uint8 *)sptr, SCNHSZ_IN(coff_version)) < 0)
326             return (FALSE);
327         stream_offset += SCNHSZ_IN(coff_version);
330        if (byte_swapped)  {
332          if (sptr->s_zeroes == 0L) swap4byte(&sptr->s_offset);
333              swap4byte(&sptr->s_paddr);  
334              swap4byte(&sptr->s_vaddr);
335              swap4byte(&sptr->s_size);   
336              swap4byte(&sptr->s_scnptr);
337              swap4byte(&sptr->s_relptr); 
338              swap4byte(&sptr->s_lnnoptr);
339              swap4byte(&sptr->s_nreloc); 
340              swap4byte(&sptr->s_nlnno);
341              swap4byte(&sptr->s_flags);  
342              /* s_mwidth   - single byte */
343              /* s_reserved - single byte */
344              swap2byte(&sptr->s_page);
345           }
348     }  else  {
350         if ((*bootFxn->read)((Uint8 *)tptr, SCNHSZ_IN(coff_version)) < 0)
351             return (FALSE);
352         stream_offset += SCNHSZ_IN(coff_version);
354        if (byte_swapped)  {
355              swap4byte(&tptr->os_paddr);  
356              swap4byte(&tptr->os_vaddr);
357              swap4byte(&tptr->os_size);   
358              swap4byte(&tptr->os_scnptr);
359              swap4byte(&tptr->os_relptr); 
360              swap4byte(&tptr->os_lnnoptr);
361              swap2byte(&tptr->os_nreloc); 
362              swap2byte(&tptr->os_nlnno);
363              swap2byte(&tptr->os_flags);
364              /* os_reserved - one byte */
365              /* os_page     - one byte */
366        }
367     
368           strncpy(sptr->s_name, tptr->os_name, SYMNMLEN);
369           sptr->s_paddr   = tptr->os_paddr;
370           sptr->s_vaddr   = tptr->os_vaddr;
371           sptr->s_size    = tptr->os_size;
372           sptr->s_scnptr  = tptr->os_scnptr;
373           sptr->s_relptr  = tptr->os_relptr;
374           sptr->s_lnnoptr = tptr->os_lnnoptr;
375           sptr->s_nreloc  = tptr->os_nreloc;
376           sptr->s_nlnno   = tptr->os_nlnno;
377           sptr->s_flags   = tptr->os_flags;
378           sptr->s_page    = tptr->os_page;
379        }
381      /* Dont keep the section if it is not loaded */
383      if ((sptr->s_scnptr || ((clear_bss || fill_bss) && IS_BSS(sptr)))   &&
384              (sptr->s_size)                                                  &&
385         !(sptr->s_flags & (STYP_DSECT | STYP_NOLOAD)))
387        n_array_sections += 1;
389    }
392    return TRUE;
395 \f
396 /******************************************************************************/
397 /*                                                                            */
398 /* CLOAD_DATA() - Read in the raw data and load it into memory.               */
399 /*                                                                            */
400 /******************************************************************************/
401 int cload_data(BOOT_MODULE_FXN_TABLE *bootFxn)
403    int ok = TRUE;
405    if (!need_data) return TRUE;
407    /*-------------------------------------------------------------------------*/
408    /* LOOP THROUGH THE SECTIONS AND LOAD THEM ONE AT A TIME.                  */
409    /*-------------------------------------------------------------------------*/
410    for (curr_sect = 0; curr_sect < n_array_sections && ok; curr_sect++)
411    {
412       SCNHDR *sptr = &sect_hdrs[curr_sect];
413       char   *sname = (sptr->s_zeroes == 0L) ? 
414                                 sptr->s_nptr : SNAMECPY(sptr->s_name);
416       /*----------------------------------------------------------------------*/
417       /* IF THIS IS THE TEXT SECTION, RELOCATE THE ENTRY POINT.               */
418       /*----------------------------------------------------------------------*/
419       if ((sptr->s_flags & STYP_TEXT) && !strcmp(sname, ".text"))
420          entry_point += RUN_RELOC_AMOUNT(curr_sect);
422       /*----------------------------------------------------------------------*/
423       /* IGNORE EMPTY SECTIONS OR SECTIONS WHOSE FLAGS INDICATE THE           */
424       /* SECTION IS NOT TO BE LOADED.  IF THE CLEAR_BSS FLAG IS SET, BSS      */
425       /* IS "LOADED" EVEN THOUGH IT HAS NO DATA                               */
426       /*----------------------------------------------------------------------*/
427       if ((sptr->s_scnptr || ((clear_bss || fill_bss) && IS_BSS(sptr)))   &&
428               (sptr->s_size)                                              &&
429          !(sptr->s_flags & (STYP_DSECT | STYP_NOLOAD)))  {
431         if (!(sptr->s_flags & STYP_COPY))
432                 ok &= cload_sect_data(sptr, bootFxn);
433         else
434             ok &= cload_sect_data(sptr, bootFxn);
435       }
436    }
439    return ok;
442 \f
443 /******************************************************************************/
444 /*                                                                            */
445 /* CLOAD_SECT_DATA() - Read, relocate, and write out the data for one section.*/
446 /*                                                                            */
447 /******************************************************************************/
448 int cload_sect_data(SCNHDR *sptr, BOOT_MODULE_FXN_TABLE *bootFxn)
450    T_ADDR        addr    = sptr->s_vaddr; /* CURRENT ADDRESS IN SECTION       */
451    unsigned int nbytes;                  /* BYTE COUNT WITHIN SECTION        */
452    int           packet_size = 0;         /* SIZE OF CURRENT DATA BUFFER      */
453    int           excess  = 0;             /* BYTES LEFT FROM PREVIOUS BUFFER  */
454    unsigned int  n_reloc = 0;             /* COUNTER FOR RELOCATION ENTRIES   */
455    RELOC         reloc;                   /* RELOCATION ENTRY                 */
456    int           relsz   = RELSZ_IN(coff_version); 
457    unsigned char *packet = (unsigned char *)paBuf; /* LOAD BUFFER                      */
458    unsigned int section_length = (unsigned int)LOCTOBYTE(sptr->s_size);
459    unsigned int buffer_size    = LOADBUFSIZE;
461 #if defined (UNBUFFERED) && UNBUFFERED
462    /*-------------------------------------------------------------------------*/
463    /* IF UNBUFFERED, THEN SET SIZE TO SECTION LENGTH ROUNDED UP TO MULTIPLE   */
464    /* 32 BYTES.  WE MAINTAIN A MINIMIUM OF LOADBUFSIZE IN THE EVENT SOMEONE   */
465    /* CONTINUES TO USE THAT MACRO AS A SIZE LIMIT.                            */
466    /*-------------------------------------------------------------------------*/
467    buffer_size = MAX(buffer_size, (section_length + 32) & ~31ul); 
468 #endif
470    /*-------------------------------------------------------------------------*/
471    /* ENSURE LOADBUFSIZE IS A MULTIPLE OF 2                                   */
472    /*-------------------------------------------------------------------------*/
473    if (LOADBUFSIZE % 2) 
474    {
475        return -1;
476    }
478    /*-------------------------------------------------------------------------*/
479    /* ALLOCATE THE PACKET BUFFER                                              */
480    /*-------------------------------------------------------------------------*/
481    if (!packet) { load_err = E_ALLOC; return FALSE; }
483 #ifdef OTIS
484    if (IS_BSS(sptr))
485    {
486       TRG_MVAL filval = fill_bss_value;
488       free (packet);
490       if (!mem_fill(filval, LOCTOBYTE(sptr->s_size), addr, sptr->s_page))
491          { load_err = E_MEMWRITE; return FALSE; }
492       return TRUE;
493    }
494 #else
495    /*-------------------------------------------------------------------------*/
496    /* Always want to clear memory for cases where memsize is not a multiple   */
497    /* of the data size being written out.  If we do not clear the array, the  */
498    /* last byte or so can be corrupted with data from the last buffer read.   */
499    /*-------------------------------------------------------------------------*/
500    for (nbytes = 0; nbytes < buffer_size; ++nbytes) packet[nbytes] = 0;
501 #endif
504    /* Advance the stream to the start of the section */
505    if (sptr->s_scnptr)  {
507         unsigned int offset;
509         offset = sptr->s_scnptr;
511         /* Advance the stream to the next section */
512         if (offset > stream_offset)  {
514             unsigned int delta, rsize;
515             int k;
516             
517                 
518             delta = sptr->s_scnptr - stream_offset;
520             for (k = 0; k < delta; k += rsize)  {
522                 rsize = MIN(delta, sizeof(paBuf));
524                 if ((*bootFxn->read)((Uint8 *)paBuf, rsize) < 0)
525                     return (FALSE);
526                 stream_offset += rsize;
528             }
530          }
532     }
534        
535    /*-------------------------------------------------------------------------*/
536    /* COPY ALL THE DATA IN THE SECTION.                                       */
537    /*-------------------------------------------------------------------------*/
539    for (nbytes = 0; nbytes < section_length; nbytes += packet_size)
540    {
541       int j;
543       /*----------------------------------------------------------------------*/
544       /* READ IN A BUFFER OF DATA.  IF THE PREVIOUS RELOCATION SPANNED        */
545       /* ACROSS THE END OF THE LAST BUFFER, COPY THE LEFTOVER BYTES INTO      */
546       /* THE BEGINNING OF THE NEW BUFFER.                                     */
547       /*----------------------------------------------------------------------*/
548       for (j = 0; j < excess; ++j) packet[j] = packet[packet_size + j];
550       packet_size = (int)MIN(LOCTOBYTE(sptr->s_size) - nbytes, buffer_size);
552       if (sptr->s_scnptr)  {
554          if ((*bootFxn->read)((Uint8 *)((Uint8 *)packet+ excess), packet_size - excess) < 0)
555             return (FALSE);
556          stream_offset += (packet_size - excess);
558       }
561       excess = 0;
563       /*----------------------------------------------------------------------*/
564       /* Clear out end of packet in case we write padding.                    */
565       /*----------------------------------------------------------------------*/
566       if (excess + packet_size < buffer_size)
567           for(j = excess + packet_size; j < buffer_size; j++)
568               packet[j] = 0;
571 #if 0       /* For some reason I have a section with STYP_COPY set, but
572              * the name is not .cinit (first section). The address of
573              * this section is 0, so if memcpy is called it returns 0,
574              * which results in the load_err case */
575              
576       /*----------------------------------------------------------------------*/
577       /* WRITE OUT THE RELOCATED DATA TO THE TARGET DEVICE.  IF THIS IS A     */
578       /* CINIT SECTION, CALL A SPECIAL FUNCTION TO HANDLE IT.                 */
579       /*----------------------------------------------------------------------*/
580       if (!(IS_CINIT(sptr) ?
581               cload_cinit(packet, &packet_size, &excess) :
582               (int)memcpy ((void *)addr, packet, packet_size)))
583          { load_err = E_MEMWRITE; free (packet); return FALSE; }
584 #endif
588       if (IS_CINIT(sptr))  {
589         if (cload_cinit(packet, &packet_size, &excess))  {
590             load_err = E_MEMWRITE; return (FALSE); 
591            
592         }
594       }  else  {
595         
596         /* If a copy section, but not cinit, ignore it */
597         if (!(sptr->s_flags & STYP_COPY)) 
598               memcpy ((void *)addr, packet, packet_size);
600      }
603       /*----------------------------------------------------------------------*/
604       /* KEEP TRACK OF THE ADDRESS WITHIN THE SECTION.                        */
605       /*----------------------------------------------------------------------*/
606       addr += BYTETOLOC(packet_size);
608    }
610    return TRUE;
613 \f
614 /******************************************************************************/
615 /*                                                                            */
616 /* CLOAD_CINIT() - Process one buffer of C initialization records.            */
617 /*                                                                            */
618 /******************************************************************************/
619 int cload_cinit(unsigned char *packet, int *packet_size, int *excess)
621    int           i;                      /* BYTE COUNTER                      */
622    int           init_packet_size;       /* SIZE OF CURRENT INITIALIZATION    */
623    static T_ADDR init_addr;              /* ADDRESS OF CURRENT INITIALIZATION */
624    int           bss_page = 0;           /* BSS SECTION PAGE NUMBER           */
625  
626    /*-------------------------------------------------------------------------*/
627    /* FIND THE BSS SECTION ASSOCIATED WITH THE THE CINIT SECTION CURRENTLY    */
628    /* BEING LOADED.                                                           */
629    /*-------------------------------------------------------------------------*/
630    for (i = 0; i < n_sections; ++i)
631       if (IS_BSS(SECT_HDR(i))) 
632           { bss_page = SECT_HDR(i)->s_page; break; }
634    /*-------------------------------------------------------------------------*/
635    /*  PROCESS ALL THE INITIALIZATION RECORDS IN THE BUFFER.                  */
636    /*-------------------------------------------------------------------------*/
637    for (i = 0; i < *packet_size; i += init_packet_size)
638    {
639       /*----------------------------------------------------------------------*/
640       /* IF STARTING A NEW INITIALIZATION, READ THE SIZE AND ADDRESS FROM     */
641       /* THE TABLE.                                                           */
642       /*----------------------------------------------------------------------*/
643       if (init_size == 0)
644       {
645          T_SIZE temp;
646          int    align;
648          /*-------------------------------------------------------------------*/
649          /* POSITION THE BYTE INDEX ON THE NEXT INIT RECORD.                  */
650          /*-------------------------------------------------------------------*/
651          if (align = (i % INIT_ALIGN)) i += (INIT_ALIGN - align);
653          /*-------------------------------------------------------------------*/
654          /* IF THE SIZE AND ADDRESS ARE NOT FULLY CONTAINED IN THIS BUFFER,   */
655          /* STOP HERE.  SET THE 'EXCESS' COUNTER TO THE NUMBER OF UNPROCESSED */
656          /* BYTES - THESE WILL BE COPIED TO THE HEAD OF THE NEXT BUFFER.      */
657          /*-------------------------------------------------------------------*/
658          if ((int)(i + sizeof(T_SIZE)) > *packet_size)
659             { *excess += *packet_size - i;  *packet_size = i;  break; }
661          /*-------------------------------------------------------------------*/
662          /* IF THE NEXT SIZE FIELD IS ZERO, BREAK.                            */
663          /*-------------------------------------------------------------------*/
664          temp = unpack(packet + i, sizeof(T_SIZE)*8, sizeof(T_SIZE)*8, 0);
665          if (temp == 0) break;
667          /*-------------------------------------------------------------------*/
668          /* READ THE ADDRESS FIELD ,IF IT'S ALL HERE.                         */
669          /*-------------------------------------------------------------------*/
670          if ((int)(i + sizeof(T_SIZE) + sizeof(T_IADDR)) > *packet_size)
671              { *excess += *packet_size - i;  *packet_size = i;  break; }
673          i         += sizeof(T_SIZE);
674          init_size  = temp;
675          init_addr  = unpack(packet+i,sizeof(T_IADDR)*8,sizeof(T_IADDR)*8,0);
676          i         += sizeof(T_IADDR);
677       }
679       /*----------------------------------------------------------------------*/
680       /* WRITE OUT THE CURRENT PACKET, UP TO THE END OF THE BUFFER.           */
681       /*----------------------------------------------------------------------*/
682       if (init_packet_size = MIN(*packet_size-i, (int)(init_size * INIT_WSIZE)))
683       {
684         
685          if (!mem_write(packet + i, init_packet_size, init_addr, bss_page))
686             return FALSE;
688          init_addr += BYTETOLOC(init_packet_size);
689          init_size -= init_packet_size / INIT_WSIZE;
690       }
691    }
692    return TRUE;
695 #if 0
696 /******************************************************************************/
697 /*                                                                            */
698 /* CLOAD_SYMBOLS() - Read in the symbol table.                                */
699 /*                                                                            */
700 /******************************************************************************/
701 int cload_symbols()
703    SYMENT sym;
704    AUXENT aux;
705    int first, next;
707    if (file_hdr.f_nsyms == 0 || (!need_symbols && !need_reloc)) return TRUE;
709    /*------------------------------------------------------------------------*/
710    /* ALLOCATE THE RELOCATION SYMBOL TABLE.                                  */
711    /*------------------------------------------------------------------------*/
712    if (need_reloc)
713    {
714       reloc_sym_index = 0;
715       reloc_tab_size  = MIN(RELOC_TAB_START, (int)file_hdr.f_nsyms);
717       if (!(reloc_tab = (RELOC_TAB *)malloc(reloc_tab_size*sizeof(RELOC_TAB))))
718           { load_err = E_ALLOC; return FALSE; }
719    }
721    /*------------------------------------------------------------------------*/
722    /* IF THE APPLICATION NEEDS THE SYMBOL TABLE, LET IT READ IT IN.          */
723    /* PASS NEED_RELOC TO THE APPLICATION SO THAT IT CAN CALL RELOC_ADD().    */
724    /*------------------------------------------------------------------------*/
725    if (need_symbols) 
726    {
727       if (load_syms(need_reloc)) return TRUE;
728       else { load_err = E_SYM; return FALSE; }
729    }
731    /*------------------------------------------------------------------------*/
732    /*  READ THE SYMBOL TABLE AND BUILD THE RELOCATION SYMBOL TABLE           */
733    /*  FOR SYMBOLS THAT CAN BE USED IN RELCOATION, STORE THEM IN A           */
734    /*  SPECIAL SYMBOL TABLE THAT CAN BE SEARCHED QUICKLY DURING              */
735    /*  RELOCATION.                                                           */
736    /*------------------------------------------------------------------------*/
737    for (first = 0; first < file_hdr.f_nsyms; first = next)
738    {
739        if (!(next = sym_read(first, &sym, &aux))) 
740           { load_err = E_FILE; return FALSE; }
742        if (sym.n_sclass == C_EXT     || sym.n_sclass == C_EXTREF  ||
743            sym.n_sclass == C_STAT    || sym.n_sclass == C_LABEL   ||
744            sym.n_sclass == C_SYSTEM  || sym.n_sclass == C_BLOCK   || 
745            sym.n_sclass == C_FCN     || sym.n_sclass == C_STATLAB || 
746            sym.n_sclass == C_EXTLAB) 
747           if (!reloc_add(first, &sym)) return FALSE;
748    }
749    return TRUE;
753 /******************************************************************************/
754 /*                                                                            */
755 /* CLOAD_STRINGS() - Read in the string table.                                */
756 /*                                                                            */
757 /******************************************************************************/
758 int cload_strings()
760    unsigned int str_size;              /* SIZE OF STRING TABLE              */
761    unsigned int bufsize;               /* SIZE OF CURRENT BUFFER            */
762    unsigned int ntoread;                /* AMOUNT TO READ FROM FILE          */
763    int excess;                          /* AMOUNT LEFT OVER FROM LAST BUFFER */
764    STRTAB *packet;                      /* STRING TABLE BUFFER PACKET        */
765    unsigned int i = 0;
767    /*----------------------------------------------------------------------*/
768    /* Do not load if not loading/saving the symbol tables.                 */
769    /* This is because the string table is an extension of the symbol table */
770    /* and if you free and rebuild it, the symbol table's str_head will be  */
771    /* incorrect.                                                           */
772    /*----------------------------------------------------------------------*/
773    if (!need_symbols) return TRUE;
775    /*------------------------------------------------------------------------*/
776    /* FREE ANY PREVIOUS STRING BUFFERS                                       */
777    /*------------------------------------------------------------------------*/
778    str_free(str_head); str_head = NULL;
780    /*------------------------------------------------------------------------*/
781    /* SEEK TO THE END OF THE SYMBOL TABLE AND READ IN THE SIZE OF THE STRING */
782    /* TABLE.                                                                 */
783    /*------------------------------------------------------------------------*/
784 #if FILE_BASED
785    if ((file_hdr.f_nsyms == 0) ||
786            fseek(fin, file_hdr.f_symptr + (file_hdr.f_nsyms * SYMESZ), 0) != 0 ||
787        fread(&str_size, sizeof(int), 1, fin) != 1)
788        return TRUE;
789 #else
790    mem_copy(&str_size, &gRxBuffer[file_hdr.f_symptr + (file_hdr.f_nsyms * SYMESZ)], sizeof(int));       
791    if ((file_hdr.f_nsyms == 0))
792        return TRUE; 
793 #endif
794    if (byte_swapped) swap4byte(&str_size);
796    /*------------------------------------------------------------------------*/
797    /* THE STRING TABLE IS READ IN AS A LINKED LIST OF BUFFERS.  TO           */
798    /* PREVENT NAMES FROM BEING SPLIT ACROSS MULTIPLE BUFFERS, ANY PARTIAL    */
799    /* NAME AT THE END OF A BUFFER IS COPIED INTO THE BEGINNING OF THE        */
800    /* NEXT BUFFER.  THE VARIABLE 'EXCESS' KEEPS TRACK OF HOW MUCH NEEDS      */
801    /* TO BE COPIED FROM THE PREVIOUS BUFFER.                                 */
802    /*------------------------------------------------------------------------*/
803    str_size -= 4;                       /* SUBTRACT OFF 4 BYTES ALREADY READ */
804    excess    = 0;                       /* INITIALIZE LAST-BUFFER OVERFLOW   */
807    /*------------------------------------------------------------------------*/
808    /* READ STRING BUFFERS UNTIL THE WHOLE STRING TABLE IS READ.              */
809    /*------------------------------------------------------------------------*/
810    while (str_size)
811    {
812       /*---------------------------------------------------------------------*/
813       /* ALLOCATE A NEW BUFFER.  ON 16-BIT MACHINES, RESTRICT THE            */
814       /* BUFFER SIZE TO THE MAXIMUM THAT CAN BE ALLOCATED AT ONCE.           */
815       /*---------------------------------------------------------------------*/
816       bufsize = str_size + excess;
818       if (sizeof(int) < 4  && bufsize > MAX_STRING_ALLOC)
819          bufsize = MAX_STRING_ALLOC;
821       if (!(packet = (struct strtab *)malloc(sizeof(STRTAB) + 
822                                              (unsigned int)bufsize - 1)))
823          { load_err = E_ALLOC; return FALSE; }
825       /*---------------------------------------------------------------------*/
826       /* COPY ANY PARTIAL STRING FROM THE LAST BUFFER INTO THIS ONE.         */
827       /* THEN FILL THE REST OF THE BUFFER BY READING FROM THE FILE.          */
828       /*---------------------------------------------------------------------*/
829       if (excess)
830          strn_copy(packet->buf, str_head->buf + str_head->size, excess);
832       ntoread = (unsigned int)(bufsize - excess);
833 #if FILE_BASED
834       if (fread(packet->buf + excess, ntoread, 1, fin) != 1) 
835          { load_err = E_FILE; return FALSE; }
836 #else
837         mem_copy(packet->buf + excess, &gRxBuffer[file_hdr.f_symptr + (file_hdr.f_nsyms * SYMESZ) +sizeof(int)+ i++*ntoread], ntoread);
838 #endif   
839       str_size -= ntoread;
841       /*---------------------------------------------------------------------*/
842       /* IF THE BUFFER ENDS IN A PARTIAL STRING (DOESN'T END IN NULL),       */
843       /* KEEP TRACK OF HOW MANY CHARACTERS ARE IN THE PARTIAL STRING         */
844       /* SO THEY CAN BE COPIED INTO THE NEXT BUFFER.                         */
845       /*---------------------------------------------------------------------*/
846       for (excess = 0; packet->buf[bufsize - 1]; --bufsize, ++excess) ;
848       /*---------------------------------------------------------------------*/
849       /* LINK THE NEW BUFFER INTO THE HEAD OF THE LIST.                      */
850       /*---------------------------------------------------------------------*/
851       packet->size   = 
852       packet->index  = bufsize;
853       packet->next   = str_head;
854       packet->offset = str_head ? (str_head->offset + str_head->size) : 4;
855       str_head       = packet;
856    }
857    return TRUE;
860 \f
861 /******************************************************************************/
862 /*                                                                            */
863 /* STR_FREE() - Free the list of string table buffers.                        */
864 /*                                                                            */
865 /******************************************************************************/
866 void str_free(STRTAB *head)
868    STRTAB *this_one, *next;
869    for (this_one = head; this_one; this_one = next)
870    {
871       next = this_one->next;
872       free(this_one);
873    }
878 /******************************************************************************/
879 /*                                                                            */
880 /* SYM_READ() - Read and relocate a symbol and its aux entry.  Return the     */
881 /*              index of the next symbol.                                     */
882 /*                                                                            */
883 /******************************************************************************/
884 int sym_read(int index, SYMENT *sym, AUXENT *aux)
886     /*------------------------------------------------------------------------*/
887     /* READ IN A SYMBOL AND ITS AUX ENTRY.                                    */
888     /*------------------------------------------------------------------------*/
889 #if FILE_BASED
890     if (fseek(fin, file_hdr.f_symptr + (index * SYMESZ), 0) != 0 ||
891         fread(sym, SYMESZ, 1, fin) != 1                                ||
892         (sym->n_numaux && fread(aux, SYMESZ, 1, fin) != 1)) 
893       { load_err = E_FILE; return FALSE; }
894 #else
895         mem_copy((void*)sym, (void*)&gRxBuffer[file_hdr.f_symptr + (index * SYMESZ)], SYMESZ); 
896     if (sym->n_numaux) 
897     { 
898         mem_copy((void*)aux, (void*)&gRxBuffer[file_hdr.f_symptr + ( (index+1) * SYMESZ)], SYMESZ);
899         load_err = E_FILE; 
900         return FALSE; 
901     }
902 #endif
903     if (byte_swapped)
904     {
905         /*--------------------------------------------------------------------*/
906         /* SWAP THE SYMBOL TABLE ENTRY.                                       */
907         /*--------------------------------------------------------------------*/
908         if (sym->n_zeroes == 0) swap4byte(&sym->n_offset);
909         swap4byte(&sym->n_value);
910         swap2byte(&sym->n_scnum);
911         swap2byte(&sym->n_type);
913         /*--------------------------------------------------------------------*/
914         /* SWAP THE AUX ENTRY, BASED ON THE STORAGE CLASS.                    */
915         /*--------------------------------------------------------------------*/
916         if (sym->n_numaux) switch(sym->n_sclass)
917         {
918           case C_FILE    : break;
920           case C_STRTAG  :
921           case C_UNTAG   :
922           case C_ENTAG   : swap4byte(&aux->x_tag.x_fsize);
923                            swap4byte(&aux->x_tag.x_endndx);
924                            break;
926           case C_FCN     : if (!str_comp(sym->n_name, ".bf"))
927                            {
928                                swap2byte(&aux->x_block.x_lcnt);
929                                swap4byte(&aux->x_block.x_regmask); 
930                                swap4byte(&aux->x_block.x_framesize);
931                            }
932                                 
933           case C_BLOCK   : swap2byte(&aux->x_block.x_lnno);
934                            swap4byte(&aux->x_block.x_endndx);
935                            break;
937           case C_EOS     : swap4byte(&aux->x_eos.x_fsize);
938                            swap4byte(&aux->x_eos.x_tagndx);
939                            break;
941           default        : /*-------------------------------------------------*/
942                            /* HANDLE FUNCTION DEFINITION SYMBOL               */
943                            /*-------------------------------------------------*/
944                            if (((sym->n_type >> 4) & 3) == DCT_FCN)
945                            {
946                                swap4byte(&aux->x_func.x_tagndx);
947                                swap4byte(&aux->x_func.x_fsize);
948                                swap4byte(&aux->x_func.x_lnnoptr);
949                                swap4byte(&aux->x_func.x_endndx);
950                            }
952                            /*-------------------------------------------------*/
953                            /* HANDLE ARRAYS.                                  */
954                            /*-------------------------------------------------*/
955                            else if (((sym->n_type >> 4) & 3) == DCT_ARY)
956                            {
957                                swap4byte(&aux->x_array.x_tagndx);
958                                swap4byte(&aux->x_array.x_fsize);
959                                swap2byte(&aux->x_array.x_dimen[0]);
960                                swap2byte(&aux->x_array.x_dimen[1]);
961                                swap2byte(&aux->x_array.x_dimen[2]);
962                                swap2byte(&aux->x_array.x_dimen[3]);
963                            }
965                            /*-------------------------------------------------*/
966                            /* HANDLE SECTION DEFINITIONS                      */
967                            /*-------------------------------------------------*/
968                            else if (sym->n_type == 0)
969                            {
970                                swap4byte(&aux->x_scn.x_scnlen);
971                                swap2byte(&aux->x_scn.x_nreloc);
972                                swap2byte(&aux->x_scn.x_nlinno);
973                            }
975                            /*-------------------------------------------------*/
976                            /* HANDLE MISC SYMBOL RECORD                       */
977                            /*-------------------------------------------------*/
978                            else
979                            {
980                                swap4byte(&aux->x_sym.x_fsize);
981                                swap4byte(&aux->x_sym.x_tagndx);
982                            }
983         }
984     }
986     /*------------------------------------------------------------------------*/
987     /* RELOCATE THE SYMBOL, BASED ON ITS STORAGE CLASS.                       */
988     /*------------------------------------------------------------------------*/
989     switch(sym->n_sclass)
990     {
991        case C_SYSTEM  :
992        case C_EXT     :
993        case C_EXTREF  :
994        case C_STAT    :
995        case C_LABEL   :
996        case C_BLOCK   :
997        case C_FCN     : 
998        case C_STATLAB :
999        case C_EXTLAB  :
1000           /*------------------------------------------------------------------*/
1001           /* IF THE SYMBOL IS UNDEFINED, CALL AN APPLICATION ROUTINE TO LOOK  */
1002           /* IT UP IN AN EXTERNAL SYMBOL TABLE.  IF THE SYMBOL IS DEFINED,    */
1003           /* RELOCATE IT ACCORDING TO THE SECTION IT IS DEFINED IN.           */
1004           /*------------------------------------------------------------------*/
1005           if (sym->n_scnum == 0) 
1006              lookup_sym((short)index, sym, aux);
1007           else if (sym->n_scnum > 0) 
1008           {
1009              if (sym->n_sclass == C_STATLAB || sym->n_sclass == C_EXTLAB)
1010                   sym->n_value += reloc_amount[sym->n_scnum - 1];
1011              else sym->n_value += RUN_RELOC_AMOUNT(sym->n_scnum - 1);
1012           }
1013     }
1015     return (index + sym->n_numaux + 1);
1018 \f
1019 /******************************************************************************/
1020 /*                                                                            */
1021 /* SYM_NAME() - Return a pointer to the name of a symbol in either the symbol */
1022 /*              entry or the string table.                                    */
1023 /*                                                                            */
1024 /******************************************************************************/
1025 char *sym_name(SYMENT *symptr)
1027     static char temp[9];
1029     if (symptr->n_zeroes == 0)
1030     {
1031        STRTAB *packet = str_head;
1033        /*---------------------------------------------------------------------*/
1034        /* Return the empty string if this symbol has no name (offset == 0)    */
1035        /*---------------------------------------------------------------------*/
1036        if (symptr->n_offset < 4) /* Anything below 4 isn't valid */
1037        {
1038           temp[0] = 0;
1039           return temp;
1040        }
1042        /*---------------------------------------------------------------------*/
1043        /* Otherwise, return the string in the string table.                   */
1044        /*---------------------------------------------------------------------*/
1045        while (packet && symptr->n_offset < (int)packet->offset)
1046           packet = packet->next;
1048        /*---------------------------------------------------------------------*/
1049        /* Return the empty string if packet NULL (invalid offset)             */
1050        /*---------------------------------------------------------------------*/
1051        if (!packet)
1052        {
1053           temp[0] = 0;
1054           return temp;
1055        }
1057        return packet->buf + (symptr->n_offset - packet->offset);
1058     }
1059     
1060     strn_copy(temp, symptr->n_name, 8);
1061     temp[8] = 0;
1062     return temp;
1066 /******************************************************************************/
1067 /*                                                                            */
1068 /* SYM_ADD_NAME() - Given a symbol table entry, return a pointer to the       */
1069 /*                  symbol's name in the string table.  Add the name to the   */
1070 /*                  table if it's not already there.                          */
1071 /*                                                                            */
1072 /******************************************************************************/
1073 char *sym_add_name(SYMENT *symptr)
1075     char *dest;
1076     char *result;
1077     int i;
1079     /*------------------------------------------------------------------------*/
1080     /* IF THE SYMBOL'S NAME WAS IN THE COFF STRING TABLE, LOOK THROUGH THE    */
1081     /* LIST OF STRING TABLE BUFFERS UNTIL FINDING THE ONE THE NAME IS IN,     */
1082     /* AND SIMPLY POINT INTO THE BUFFER.                                      */
1083     /*------------------------------------------------------------------------*/
1084     if (symptr->n_zeroes == 0)
1085        return sym_name(symptr);
1087     /*------------------------------------------------------------------------*/
1088     /* OTHERWISE ADD THE STRING TO THE STRING TABLE.                          */
1089     /* ALLOCATE AND LINK IN A NEW PACKET IF NECESSARY.  NEW PACKETS ARE       */
1090     /* LINKED TO THE HEAD OF THE LIST TO EASE ADDING NEW SYMBOLS.             */
1091     /*------------------------------------------------------------------------*/
1092     if (!str_head || str_head->index + SYMNMLEN + 1 > str_head->size)
1093     {
1094        STRTAB *packet;
1096        if (!(packet = (STRTAB *)malloc(sizeof(STRTAB) + MIN_STRING_ALLOC - 1)))
1097           { load_err = E_ALLOC; return NULL; }
1099        packet->size   = MIN_STRING_ALLOC;
1100        packet->index  = 0;
1101        packet->next   = str_head;
1102        packet->offset = str_head ? (str_head->offset + str_head->size) : 4;
1103        str_head       = packet;
1104     }
1106     /*------------------------------------------------------------------------*/
1107     /* COPY THE NAME INTO THE STRING TABLE.                                   */
1108     /*------------------------------------------------------------------------*/
1109     result = dest = str_head->buf + str_head->index; 
1110     for (i = 0; *dest++ = symptr->n_name[i++]; )
1111        if (i == SYMNMLEN) { *dest++ = '\0'; ++i; break; }
1113     symptr->n_zeroes = 0;
1114     symptr->n_offset = str_head->offset + str_head->index;
1115     str_head->index += i;
1116     return result;
1118 #endif
1120 /******************************************************************************/
1121 /*                                                                            */
1122 /* RELOC_ADD() - Add an entry to the relocation symbol table.  This table     */
1123 /*               stores relocation information for each relocatable symbol.   */
1124 /*                                                                            */
1125 /******************************************************************************/
1126 int reloc_add(int index, SYMENT *sym)
1128    int disp;                            /* RELOCATION AMOUNT FOR THIS SYMBOL */
1130    if (!need_reloc) return TRUE;
1132    /*-------------------------------------------------------------------------*/
1133    /* USE THE SYMBOL VALUE TO CALCULATE THE RELOCATION AMOUNT:                */
1134    /* 1) IF THE SYMBOL WAS UNDEFINED (DEFINED IN SECTION 0), USE THE          */
1135    /*    SYMBOL'S VALUE.                                                      */
1136    /* 2) IF THE SYMBOL HAS A POSITIVE SECTION NUMBER, USE THE RELOCATION      */
1137    /*    AMOUNT FOR THE SECTION IN WHICH THE SYMBOL IS DEFINED.               */
1138    /* 3) OTHERWISE, THE SYMBOL IS ABSOLUTE, SO THE RELOCATION AMOUNT IS 0.    */
1139    /*-------------------------------------------------------------------------*/
1140    if (sym->n_scnum == 0)
1141       disp = sym->n_value;
1142    else if (sym->n_scnum > 0)
1143    {
1144       if (sym->n_sclass == C_STATLAB || sym->n_sclass == C_EXTLAB)
1145            disp = reloc_amount[sym->n_scnum - 1];
1146       else disp = RUN_RELOC_AMOUNT(sym->n_scnum - 1);
1147    }
1148    else disp = 0;
1150    /*-------------------------------------------------------------------------*/
1151    /* IF THERE IS A NON-ZERO RELOCATION AMOUNT, ADD THE SYMBOL TO THE TABLE.  */
1152    /*-------------------------------------------------------------------------*/
1153    if (disp == 0) return TRUE;
1155    if (reloc_sym_index >= reloc_tab_size)
1156    {
1157       reloc_tab_size += RELOC_GROW_SIZE;
1158       reloc_tab = (RELOC_TAB *)realloc((char *)reloc_tab, 
1159                                        reloc_tab_size*sizeof(RELOC_TAB));
1161       if (!reloc_tab) { load_err = E_ALLOC; return FALSE; }
1162    }
1163    reloc_tab[reloc_sym_index  ].rt_index = index;
1164    reloc_tab[reloc_sym_index++].rt_disp  = disp;
1166    return TRUE;
1169 /******************************************************************************/
1170 /*                                                                            */
1171 /* RELOCATE() - Perform a single relocation by patching the raw data.         */
1172 /*                                                                            */
1173 /******************************************************************************/
1174 int relocate(RELOC *rp, unsigned char *data, int s)
1176 /*   RELOC         *rp;                    RELOCATION ENTRY                   */
1177 /*   unsigned char *data;                  DATA BUFFER                        */
1178 /*   int            s;                     INDEX OF CURRENT SECTION           */
1179    int fieldsz = reloc_size(rp->r_type);     /* SIZE OF ACTUAL PATCH VALUE    */
1180    int offset  = reloc_offset(rp->r_type);   /* OFFSET OF ACTUAL PATCH VALUE  */
1181    int wordsz  = MAX(fieldsz, reloc_stop(rp->r_type)); /* SIZE CONTAINING FLD */
1182    int objval;                              /* FIELD TO BE PATCHED           */
1183    int reloc_amt;                           /* AMOUNT OF RELOCATION          */
1185    int pp_shift_cnt = 0;
1186    int pp_local     = FALSE;
1188    if (rp->r_type == R_ABS) return TRUE;          /* NOTHING TO DO   */
1190    /*-------------------------------------------------------------------------*/
1191    /* DETERMINE THE RELOCATION AMOUNT FROM THE RELOCATION SYMBOL TABLE.       */
1192    /*-------------------------------------------------------------------------*/
1193    reloc_amt = (rp->r_symndx == -1) ? RUN_RELOC_AMOUNT(s) 
1194                                     : sym_reloc_amount(rp);
1196    /*-------------------------------------------------------------------------*/
1197    /* EXTRACT THE RELOCATABLE FIELD FROM THE OBJECT DATA.                     */
1198    /*-------------------------------------------------------------------------*/
1199    objval = unpack(data, fieldsz, wordsz, offset + BIT_OFFSET(rp->r_vaddr));
1201    /*-------------------------------------------------------------------------*/
1202    /* MODIFY THE FIELD BASED ON THE RELOCATION TYPE.                          */
1203    /*-------------------------------------------------------------------------*/
1204    switch (rp->r_type)
1205    {
1206       /*----------------------------------------------------------------------*/
1207       /* NORMAL RELOCATIONS: ADD IN THE RELOCATION AMOUNT.                    */
1208       /*----------------------------------------------------------------------*/
1209       case R_RELBYTE:
1210       case R_RELWORD:
1211       case R_REL24:
1212       case R_RELLONG:
1213       case R_DIR32:
1214       case R_PARTLS16:
1215          objval += reloc_amt;
1216          break;
1218       /*--------------------------------------------------------------------*/
1219       /* ADD IN THE RELOCATION AMOUNT, BUT MAKE SURE WE'RE STILL IN THE     */
1220       /* 370'S REGISTER FILE.                                               */
1221       /*--------------------------------------------------------------------*/
1222       case R_RRNREG:
1223       case R_RRRELREG:
1224          if (rp->r_type == R_RRNREG)
1225             objval = ((char)objval + reloc_amt);
1226          else objval += reloc_amt;
1227  
1228          if (objval & ((-1L >> 8*fieldsz) << 8*fieldsz))
1229          {
1230             /* ERROR */
1231          }
1232  
1233          break;
1234  
1235       /*--------------------------------------------------------------------*/
1236       /* PP UNSCALED 15-BIT OFFSET RELOCATION.                              */
1237       /*--------------------------------------------------------------------*/
1238       case R_PP15    :
1239       case R_PPL15   :
1240       case R_PPN15   :
1241       case R_PPLN15  :
1242          {
1243             int  bit;
1244             char *sname = (SECT_HDR(s)->s_zeroes == 0L) ?
1245                           SECT_HDR(s)->s_nptr : SNAMECPY(SECT_HDR(s)->s_name);
1247             pp_local = (rp->r_type == R_PPL15) || (rp->r_type == R_PPLN15);
1249             /*--------------------------------------------------------------*/
1250             /* IF NEGATIVE RELOC TYPE, THEN TREAT CONST OFFSET AS A NEGATIVE*/
1251             /*--------------------------------------------------------------*/
1252             if (rp->r_type == R_PPN15 || rp->r_type == R_PPLN15)
1253             {
1254                 objval      = -objval;
1255                 rp->r_type -= 010;           /* CHANGE TYPE TO NON NEG.     */
1256             }
1258             objval += reloc_amt;
1260             /*--------------------------------------------------------------*/
1261             /* IF THE ADDRESS STILL FALLS WITHIN AN APPROPRIATE RANGE       */
1262             /*--------------------------------------------------------------*/
1263             if ((objval >= 0x00000000 && objval <= 0x00007fff) || 
1264                 (objval >= 0x01000000 && objval <= 0x010007ff) )
1265                 break;
1267             /*--------------------------------------------------------------*/
1268             /* IF THE ADDRESS FALLS OUTSIDE AN APPROPRIATE RANGE, BUT CAN   */
1269             /* BE SCALED BY SIZE TO GET BACK INTO RANGE, THEN READ THE UPPER*/
1270             /* BIT OF THE SIZE FIELD.  IF IT IS A 1, THEN WE CAN SCALE THIS */
1271             /* OFFSET BY 4, IF IT IS 0, THEN WE CAN SCALE THIS OFFSET BY 2. */ 
1272             /*--------------------------------------------------------------*/
1273             bit = unpack(data, 1, 64, pp_local ? 30 : 8);
1274  
1275             /*--------------------------------------------------------------*/
1276             /* DETERMINE IF THE OFFSET IS ALIGNED FOR SCALING.  IF SO,      */
1277             /* THEN PACK THE SCALED OFFSET INTO INSTRUCTION, CHANGE THE     */
1278             /* RELOC TYPE TO SCALED, AND TURN ON SCALE BIT IN INSTRUCT.     */
1279             /*--------------------------------------------------------------*/
1280             if (!(objval & ((2<<bit)-1)) && 
1281                  (objval >>= (bit+1)) >= 0 && objval <= 0x7fff)
1282             {
1283                 rp->r_type = pp_local ? (bit ? R_PPL15W : R_PPL15H) : 
1284                                         (bit ? R_PP15W : R_PP15H);
1285                 repack(1, data, 1, 64, pp_local ? 28 : 6);
1286                 break;
1287             }
1288             
1289             /*--------------------------------------------------------------*/
1290             /* ERROR, THE OFFSET WILL NOT FIT SCALED OR UNSCALED.           */
1291             /*--------------------------------------------------------------*/
1292             
1293             load_err = E_RELOCENT;
1294             return FALSE;
1295          }
1297       /*--------------------------------------------------------------------*/
1298       /* PP SCALED 15-BIT OFFSET RELOCATION. FOR R_PP15W THE RELOC_AMT IS   */
1299       /* DIVIDED BY 4.  FOR R_PP15H THE RELOC_AMT IS DIVIDED BY 2.          */ 
1300       /*--------------------------------------------------------------------*/
1301       case R_PP15W   :
1302       case R_PPL15W  :
1303       case R_PPN15W  :
1304       case R_PPLN15W :  pp_shift_cnt++;   /* FALL THROUGH */
1306       case R_PP15H   :
1307       case R_PPL15H  :
1308       case R_PPN15H  :
1309       case R_PPLN15H :  pp_shift_cnt++;   /* FALL THROUGH */
1310          {
1311             int obj_addr_x;
1312             char *sname = (SECT_HDR(s)->s_zeroes == 0) ? 
1313                           SECT_HDR(s)->s_nptr : SNAMECPY(SECT_HDR(s)->s_name);
1315             /*--------------------------------------------------------------*/
1316             /* NOTE THAT THIS IS DEPENDENT ON THE NUMBERING OF THESE RELOC  */
1317             /* VALUES.                                                      */
1318             /*--------------------------------------------------------------*/
1319             pp_local = (rp->r_type & 4);
1321             /*--------------------------------------------------------------*/
1322             /* IF NEGATIVE RELOC TYPE, THEN TREAT CONST OFFSET AS NEGATIVE  */
1323             /*--------------------------------------------------------------*/
1324             if (rp->r_type >= R_PPN15) 
1325             {
1326                 objval      = -objval;
1327                 rp->r_type -= 010;           /* CHANGE TYPE TO NON NEG.     */
1328             }
1330             obj_addr_x = (objval << pp_shift_cnt) + reloc_amt;
1332             /*--------------------------------------------------------------*/
1333             /* LINK TIME ADDRESS VIOLATES THE SCALING FACTOR WE ARE USING   */
1334             /* FOR THIS OPERAND. UNSCALE THE VALUE IF IT WILL FIT IN 15 BITS*/
1335             /* BY CHANGING RELOC TYPE TO UNSCALED, AND CHANGING SCALE BIT   */
1336             /* IN THE INSTRUCTION.                                          */
1337             /*--------------------------------------------------------------*/
1338             if (pp_shift_cnt && (reloc_amt & ((1<<pp_shift_cnt)-1)))
1339             {
1340                 objval     = obj_addr_x;
1341                 rp->r_type = (pp_local ? R_PPL15 : R_PP15);
1342                 repack(0, data, 1, 64, pp_local ? 28 : 6);
1343             }
1344             else objval = obj_addr_x >> pp_shift_cnt;
1346             /*--------------------------------------------------------------*/
1347             /* IF THE ADDRESS STILL FALLS WITHIN AN APPROPRIATE RANGE       */
1348             /*--------------------------------------------------------------*/
1349             if ((objval     >= 0x00000000  && objval     <= 0x00007fff) || 
1350                 (obj_addr_x >= 0x01000000  && obj_addr_x <= 0x010007ff) )
1351                 break;
1353             /*--------------------------------------------------------------*/
1354             /* ERROR, THE OFFSET WILL NOT FIT SCALED OR UNSCALED.           */
1355             /*--------------------------------------------------------------*/
1356             
1357             load_err = E_RELOCENT;
1358             return FALSE;
1359          }
1361       /*--------------------------------------------------------------------*/
1362       /* PP 16-bit byte offset relocation. For R_PP16B the lower 15-bits    */
1363       /* are handled just like R_PP15, and the upper bit is placed in the   */
1364       /* scale indicator bit of the field.                                  */
1365       /*--------------------------------------------------------------------*/
1366       case R_PP16B   :
1367       case R_PPL16B  :
1368       case R_PPN16B  :
1369       case R_PPLN16B :
1370          {
1371             char *sname = (SECT_HDR(s)->s_zeroes == 0) ? 
1372                           SECT_HDR(s)->s_nptr : SNAMECPY(SECT_HDR(s)->s_name);
1374             pp_local = (rp->r_type == R_PPL16B) || (rp->r_type == R_PPLN16B);
1376             /*--------------------------------------------------------------*/
1377             /* READ THE SCALE BIT (16th BIT) AND CREATE 16 BIT CONSTANT OFF */
1378             /*--------------------------------------------------------------*/
1379             objval |= (unpack(data, 1, 64, pp_local ? 28 : 6) << 15);
1381             /*--------------------------------------------------------------*/
1382             /* IF NEGATIVE RELOC TYPE, THEN TREAT CONST OFFSET AS NEGATIVE  */
1383             /*--------------------------------------------------------------*/
1384             if (rp->r_type == R_PPN16B || rp->r_type == R_PPLN16B)
1385             {
1386                objval      = - objval;
1387                rp->r_type -= 010; /* CHANGE THE TYPE TO A NON NEG TYPE.     */
1388             }
1390             objval += reloc_amt;
1392             /*--------------------------------------------------------------*/
1393             /* IF THE ADDRESS STILL FALLS WITHIN AN APPROPRIATE RANGE       */
1394             /*--------------------------------------------------------------*/
1395             if ((objval >= 0x00000000 && objval <= 0x0000ffff) || 
1396                 (objval >= 0x01000000 && objval <= 0x010007ff) )
1397             {
1398                /*-----------------------------------------------------------*/
1399                /* RELOCATE THE 16TH BIT OF THE ADDRESS.                     */
1400                /*-----------------------------------------------------------*/
1401                repack(((objval&0x8000) >> 15), data, 1, 64, pp_local ? 28 : 6);
1402                break;
1403             }
1405             /*--------------------------------------------------------------*/
1406             /* ADDRESS IS OUT OF RANGE.                                     */
1407             /*--------------------------------------------------------------*/
1408             
1409             load_err = E_RELOCENT;
1410             return FALSE;
1411          }
1413       /*--------------------------------------------------------------------*/
1414       /* PP BASE ADDRESS RELOCATION.  BIT 0 IS 0 IF IN DATA RAM, 1 IF IN    */
1415       /* PARAMETER RAM.  THIS CODE ASSUMES THAT WE DO NOT RELOCATE FROM     */
1416       /* PRAM TO DRAM OR FROM DRAM TO PRAM AT LOAD TIME.                    */
1417       /*--------------------------------------------------------------------*/
1418       case R_PPLBASE: pp_local = TRUE;
1419       case R_PPBASE:
1420          {
1421            /*---------------------------------------------------------------*/
1422            /* IF WAS DRAM AND RELOC_AMT IS GREAT ENOUGH TO MOVE INTO PRAM,  */
1423            /* CHANGE TO PRAM                                                */
1424            /*---------------------------------------------------------------*/
1425            if (!objval && reloc_amt > (int)(0x01000000 - 0xC000)) objval = 1;
1427            /*---------------------------------------------------------------*/
1428            /* IF WAS PRAM AND RELOC_AMT IS NEGATIVE AND CAN MOVE INTO DRAM, */
1429            /* CHANGE TO DRAM                                                */
1430            /*---------------------------------------------------------------*/
1431            else if (objval && (-reloc_amt) > (int)(0x01000000 - 0xC000))
1432                objval = 0;
1434            break;
1435          }
1437       /*----------------------------------------------------------------------*/
1438       /* 34010 ONE'S COMPLEMENT RELOCATION.  SUBTRACT INSTEAD OF ADD.         */
1439       /*----------------------------------------------------------------------*/
1440       case R_OCRLONG:
1441          objval -= reloc_amt;
1442          break;
1444       /*----------------------------------------------------------------------*/
1445       /* 34020 WORD-SWAPPED RELOCATION.  SWAP BEFORE RELOCATING.              */
1446       /*----------------------------------------------------------------------*/
1447       case R_GSPOPR32:
1448       case R_OCBD32:
1449           objval  = ((objval >> 16) & 0xFFFF) | (objval << 16); 
1450           objval += (rp->r_type == R_GSPOPR32) ? reloc_amt : -reloc_amt; 
1451           objval  = ((objval >> 16) & 0xFFFF) | (objval << 16);
1452           break; 
1454       /*----------------------------------------------------------------------*/
1455       /* PC-RELATIVE RELOCATIONS.  IN THIS CASE THE RELOCATION AMOUNT         */
1456       /* IS ADJUSTED BY THE PC DIFFERENCE.   IF THIS IS AN INTERNAL           */
1457       /* RELOCATION TO THE CURRENT SECTION, NO ADJUSTMENT IS NEEDED.          */
1458       /*----------------------------------------------------------------------*/
1459       case R_PCRBYTE:
1460       case R_PCRWORD:
1461       case R_GSPPCR16:
1462       case R_GSPPCA16:
1463       case R_PCRLONG:
1464       case R_PCR24:
1465       case R_ANKPCR16:
1466       case R_ANKPCR8:
1467          {
1468             int           shift = 8 * (4 - fieldsz);
1469             unsigned int pcdif = RUN_RELOC_AMOUNT(s);
1471             /*----------------------------------------------------------------*/
1472             /* HANDLE SPECIAL CASES OF JUMPING FROM ABSOLUTE SECTIONS (SPECIAL*/
1473             /* RELOC TYPE) OR TO ABSOLUTE DESTINATION (SYMNDX == -1).  IN     */
1474             /* EITHER CASE, SET THE APPROPRIATE RELOCATION AMOUNT TO 0.       */
1475             /*----------------------------------------------------------------*/
1476             if( rp->r_symndx == -1 )      reloc_amt = 0;
1477             if( rp->r_type == R_GSPPCA16) pcdif = 0;
1479             /*----------------------------------------------------------------*/
1480             /* Handle ankoor's offset where upper 14 (PCR8) and upper 6(PCR16)*/
1481             /* bits of 22 bit address is held in r_disp field of reloc entry  */
1482             /*----------------------------------------------------------------*/
1483             if(rp->r_type == R_ANKPCR8 || rp->r_type == R_ANKPCR16)
1484             {
1485                 shift = 10;
1486                 objval |= rp->r_disp << ((rp->r_type == R_ANKPCR8) ? 8 : 16);
1487             }
1489             reloc_amt -= pcdif;
1491             if (rp->r_type == R_GSPPCR16 || rp->r_type == R_GSPPCA16)
1492                reloc_amt >>= 4;                              /* BITS TO WORDS */
1494             objval  = (int)(objval << shift) >> shift;      /* SIGN EXTEND   */
1495             objval += reloc_amt;
1496             break;
1497          }
1499       /*--------------------------------------------------------------------*/
1500       /* Ankoor page-addressing.  Calculate address from the 22-bit         */
1501       /* value in the relocation field plus the relocation amount. Shift    */
1502       /* out the lower 16 bits.                                             */
1503       /*--------------------------------------------------------------------*/
1504       case R_PARTMS6:
1505           objval = (objval & 0xC0) |
1506                    (((rp->r_disp += reloc_amt) >> 16) & 0x3F);
1507           break;
1509       /*----------------------------------------------------------------------*/
1510       /* 320C30 PAGE-ADDRESSING RELOCATION.  CALCULATE THE ADDRESS FROM       */
1511       /* THE 8-BIT PAGE VALUE IN THE FIELD, THE 16-BIT OFFSET IN THE RELOC    */
1512       /* ENTRY, AND THE RELOCATION AMOUNT.  THEN, STORE THE 8-BIT PAGE        */
1513       /* VALUE OF THE RESULT BACK IN THE FIELD.                               */
1514       /*----------------------------------------------------------------------*/
1515       case R_PARTMS8:
1516           objval = (int)((objval << 16) + rp->r_disp + reloc_amt) >> 16;
1517           break;
1519       /*----------------------------------------------------------------------*/
1520       /* DSP(320) PAGE-ADDRESSING.  CALCULATE ADDRESS FROM THE 16-BIT         */
1521       /* VALUE IN THE RELOCATION FIELD PLUS THE RELOCATION AMOUNT.  OR THE    */
1522       /* TOP 9 BITS OF THIS RESULT INTO THE RELOCATION FIELD.                 */
1523       /*----------------------------------------------------------------------*/
1524       case R_PARTMS9:
1525           objval = (objval & 0xFE00) | 
1526                    (((int)(rp->r_disp + reloc_amt) >> 7) & 0x1FF);
1527           break;
1529       /*----------------------------------------------------------------------*/
1530       /* DSP(320) PAGE-ADDRESSING.  CALCULATE ADDRESS AS ABOVE, AND OR THE    */
1531       /* 7-BIT DISPLACEMENT INTO THE FIELD.                                   */
1532       /*----------------------------------------------------------------------*/
1533       case R_PARTLS7:
1534           objval = (objval & 0x80) | ((rp->r_disp + reloc_amt) & 0x7F);
1535           break;
1537       /*--------------------------------------------------------------------*/
1538       /* Ankoor page-addressing.  Calculate address from the 22-bit         */
1539       /* value in the relocation field plus the relocation amount. Mask off */
1540       /* bits [21:16] and [5:0] to extract a data page within a 64K page    */
1541       /*--------------------------------------------------------------------*/
1542       case R_PARTMID10:
1543           objval = (objval & 0xFC00) |
1544                    (((rp->r_disp += reloc_amt) >> 6) & 0x3FF);
1545           break;
1547       /*--------------------------------------------------------------------*/
1548       /* RR(370) MSB RELOCATION.  CALCULATE ADDRESS FROM THE 16-BIT VALUE   */
1549       /* IN THE RELOCATION ENTRY PLUS THE RELOCATION AMOUNT.  PATCH THE     */
1550       /* MSB OF THE RESULT INTO THE RELOCATION FIELD.                       */
1551       /*--------------------------------------------------------------------*/
1552       case R_HIWORD:
1553           objval += (rp->r_disp += (unsigned short)reloc_amt) >> 8;
1554           break;
1556       /*--------------------------------------------------------------------*/
1557       /* C8+ High byte of 24-bit address.  Calculate address from 24-bit    */
1558       /* value in the relocation entry plus the relocation amount.  Patch   */
1559       /* the MSB of the result into the relocation field.                   */
1560       /*--------------------------------------------------------------------*/
1561       case R_C8PHIBYTE:
1562           objval = (int)((objval << 16) + rp->r_disp + reloc_amt) >> 16;
1563           break;
1565       /*--------------------------------------------------------------------*/
1566       /* C8+ Middle byte of 24-bit address.  Calculate address from 24-bit  */
1567       /* value in the relocation entry plus the relocation amount.  Patch   */
1568       /* the middle byte of the result into the relocation field.           */
1569       /*--------------------------------------------------------------------*/
1570       case R_C8PMIDBYTE:
1571           objval = (int)((objval << 16) + rp->r_disp + reloc_amt) >> 8;
1572           break;
1574       /*--------------------------------------------------------------------*/
1575       /* C8+ Vector Address.  Calculate address from 24-bit value in the    */
1576       /* relocation entry plus the relocation amount.  MSB must be 0xFF     */
1577       /* since interrupt and trap handlers must be programmed in the top-   */
1578       /* most segment of memory.  Patch bottom 16-bits of the result into   */
1579       /* the relocation field.                                              */
1580       /*--------------------------------------------------------------------*/
1581       case R_C8PVECADR:
1582           objval += reloc_amt;
1583           if ((objval & 0xFF0000) != 0xFF0000)
1584           {
1585              /* ERROR */
1586           }
1587           objval &= 0xFFFF;
1588           break;
1590       /*----------------------------------------------------------------------*/
1591       /* C8+ 24-bit Address.  The byte ordering for 24-bit addresses on the   */
1592       /* C8+ is reversed (low, middle, high).  Needs to be unordered, add     */
1593       /* in reloc_amt, then re-ordered.                                       */
1594       /*----------------------------------------------------------------------*/
1595       case R_C8PADR24:
1596           objval = ((objval>>16) | (objval&0xff00) | ((objval&0xff)<<16));
1597           objval += reloc_amt;
1598           objval = ((objval>>16) | (objval&0xff00) | ((objval&0xff)<<16));
1599           break;
1601       /*----------------------------------------------------------------------*/
1602       /* DSP(320) 13-BIT CONSTANT.  RELOCATE ONLY THE LOWER 13 BITS OF THE    */
1603       /* FIELD.                                                               */
1604       /*----------------------------------------------------------------------*/
1605       case R_REL13:
1606           objval = (objval & 0xE000) | ((objval + reloc_amt) & 0x1FFF);
1607           break;
1609       /*--------------------------------------------------------------------*/
1610       /* ANKOOR 22-bit extended address.  Calculate address by masking      */
1611       /* off the opcode and OR in the lower 16-bit constant + the           */
1612       /* amount.                                                            */
1613       /*--------------------------------------------------------------------*/
1614       case R_REL22:
1615          {
1616             unsigned int obj_hi = unpack(data  , 16, 16, 0);
1617             unsigned int obj_lo = unpack(data+2, 16, 16, 0);
1619             /*--------------------------------------------------------------*/
1620             /* BUILD THE OFFSET TO BE RELOCATED.                            */
1621             /*--------------------------------------------------------------*/
1622             objval = ((obj_hi & 0x003F) << 16) | (obj_lo & 0xFFFF);
1624             /*--------------------------------------------------------------*/
1625             /* Calculate displacement                                       */
1626             /*--------------------------------------------------------------*/
1627             objval += reloc_amt;
1629             /*--------------------------------------------------------------*/
1630             /* REPACK THE RELOCATED VALUE BACK IN THE OBJECT VALUE.         */
1631             /*--------------------------------------------------------------*/
1632             obj_hi = (obj_hi & 0xFFC0) | ((objval & 0x3F0000) >> 16);
1633             obj_lo = objval & 0xFFFF;
1634             repack(obj_hi, data  , 16, 16, 0);
1635             repack(obj_lo, data+2, 16, 16, 0);
1637             return TRUE;
1638          }
1640       /*--------------------------------------------------------------------*/
1641       /* DSP, LEAD 23-bit extended address.  Calculate address by masking   */
1642       /* off the opcode and OR in the lower 16-bit constant + the           */
1643       /* amount.                                                            */
1644       /*--------------------------------------------------------------------*/
1645       case R_REL23:
1646          {
1647             unsigned int obj_hi = unpack(data  , 16, 16, 0);
1648             unsigned int obj_lo = unpack(data+2, 16, 16, 0);
1650             /*--------------------------------------------------------------*/
1651             /* BUILD THE OFFSET TO BE RELOCATED.                            */
1652             /*--------------------------------------------------------------*/
1653             objval = ((obj_hi & 0x007F) << 16) | (obj_lo & 0xFFFF);
1655             /*--------------------------------------------------------------*/
1656             /* Calculate displacement                                       */
1657             /*--------------------------------------------------------------*/
1658             objval += reloc_amt;
1660             /*--------------------------------------------------------------*/
1661             /* REPACK THE RELOCATED VALUE BACK IN THE OBJECT VALUE.         */
1662             /*--------------------------------------------------------------*/
1663             obj_hi = (obj_hi & 0xFF80) | ((objval & 0x7F0000) >> 16);
1664             obj_lo = objval & 0xFFFF;
1665             repack(obj_hi, data  , 16, 16, 0);
1666             repack(obj_lo, data+2, 16, 16, 0);
1668             return TRUE;
1669          }
1672       /*----------------------------------------------------------------------*/
1673       /* PRISM (370/16) code label relocation.  Convert word address to byte  */
1674       /* address, add in relocation, convert back to word address.            */
1675       /*----------------------------------------------------------------------*/
1676       case R_LABCOD:
1677           objval = ((objval << 1) + reloc_amt) >> 1;
1678           break;
1679    }
1681    /*-------------------------------------------------------------------------*/
1682    /* PACK THE RELOCATED FIELD BACK INTO THE OBJECT DATA.                     */
1683    /*-------------------------------------------------------------------------*/
1684    repack(objval, data, fieldsz, wordsz, offset + BIT_OFFSET(rp->r_vaddr));
1685    return TRUE;
1686
1689 /******************************************************************************/
1690 /*                                                                            */
1691 /* RELOC_READ() - Read a single relocation entry.                             */
1692 /*                                                                            */
1693 /******************************************************************************/
1694 #if FILE_BASED
1695 int reloc_read(RELOC *rptr)
1696 #else
1697 int reloc_read(RELOC *rptr, unsigned int offset)
1698 #endif
1700 #if COFF_VERSION_1 || COFF_VERSION_2
1701    /*------------------------------------------------------------------------*/
1702    /* THE FOLLOWING UNION IS USED TO READ IN VERSION 0 OR 1 RELOC ENTRIES    */
1703    /*------------------------------------------------------------------------*/
1704    /* THE FORMAT OF RELOCATION ENTRIES CHANGED BETWEEN COFF VERSIONS 0 AND 1.*/
1705    /* VERSION 0 HAS A 16 BIT SYMBOL INDEX, WHILE VERSION 1 HAS A 32 BIT INDX.*/
1706    /*------------------------------------------------------------------------*/
1707    union { RELOC new_c; RELOC_OLD old; } input_entry;
1708 #if FILE_BASED
1709    if (fread(&input_entry, RELSZ_IN(coff_version), 1, fin) != 1)
1710       { load_err = E_FILE; return FALSE; }
1711 #else
1712         mem_copy((void*)&input_entry, (void*)&gRxBuffer[offset], RELSZ_IN(coff_version));
1713 #endif
1714    /*------------------------------------------------------------------------*/
1715    /* IF LOADING A VERSION 0 FILE, TRANSLATE ENTRY TO VERSION 1 FORMAT.      */
1716    /* (THIS COULD BE SIMPLER - ALL THE SWAPS EXCEPT FOR THE SYMBOL INDEX     */
1717    /* COULD BE DONE AFTER THE TRANSLATION - BUT THIS SEEMS TO BE CLEARER)    */
1718    /*------------------------------------------------------------------------*/
1719    if (ISCOFF_0(coff_version))
1720    {
1721       if (byte_swapped)
1722       {
1723          swap4byte(&input_entry.old.r_vaddr);
1724          swap2byte(&input_entry.old.r_type);
1726          /* if a field reloc, fields are chars, so don't swap */
1727          if (!isfldrel(input_entry.old.r_type))
1728          {
1729              swap2byte(&input_entry.old.r_symndx);
1730              swap2byte(&input_entry.old.r_disp);
1731          }
1732       }
1734       rptr->r_vaddr  = input_entry.old.r_vaddr;
1735       rptr->r_symndx = input_entry.old.r_symndx;
1736       rptr->r_disp   = input_entry.old.r_disp;
1737       rptr->r_type   = input_entry.old.r_type;
1738    }
1739    else
1740    {
1741       *rptr = input_entry.new_c;
1743       if (byte_swapped)
1744       {
1745          swap4byte(&rptr->r_vaddr); 
1746          swap2byte(&rptr->r_type);
1748          /* Again, if a field reloc, fields are chars, so don't swap */
1749          if (!isfldrel(rptr->r_type))
1750          {
1751              swap4byte(&rptr->r_symndx);
1752              swap2byte(&rptr->r_disp);  
1753          }
1754       }
1755    }
1757 #else
1758    /*-------------------------------------------------------------------------*/
1759    /* READ IN AND BYTE SWAP AN VERSION 0 RELOC ENTRY                          */
1760    /*-------------------------------------------------------------------------*/
1761    if (fread(rptr, RELSZ, 1, fin) != 1) { load_err = E_FILE; return FALSE; }
1763    if (byte_swapped)
1764    {
1765       swap4byte(&rptr->r_vaddr);
1766       swap2byte(&rptr->r_type);  
1768       /* If a field reloc, fields are chars, so don't swap */
1769       if (!isfldrel(rptr->r_type))
1770       {
1771           swap2byte(&rptr->r_symndx);
1772           swap2byte(&rptr->r_disp);
1773       }
1774    }
1775 #endif
1777    return TRUE;
1781 /*************************************************************************/
1782 /*                                                                       */
1783 /*   RELOC_SIZE()-                                                       */
1784 /*      Return the field size of a relocation type.                      */
1785 /*                                                                       */
1786 /*************************************************************************/
1788 int reloc_size(int type)
1790    switch (type)
1791    {
1792        case R_PPBASE:
1793        case R_PPLBASE:      return 1;
1795        case R_HIWORD:
1796        case R_C8PHIBYTE:
1797        case R_C8PMIDBYTE:
1798        case R_RELBYTE:
1799        case R_PCRBYTE:
1800        case R_RRNREG:
1801        case R_RRRELREG:
1802        case R_ANKPCR8:
1803        case R_PARTLS6:
1804        case R_PARTMS6:
1805        case R_PARTLS7:      return 8;
1807        case R_PP15:
1808        case R_PP15W:
1809        case R_PP15H:
1810        case R_PP16B:
1811        case R_PPN15:
1812        case R_PPN15W:
1813        case R_PPN15H:
1814        case R_PPN16B:
1815        case R_PPL15:
1816        case R_PPL15W:
1817        case R_PPL15H:
1818        case R_PPL16B:
1819        case R_PPLN15:
1820        case R_PPLN15W:
1821        case R_PPLN15H:
1822        case R_PPLN16B:      return 15;
1824        case R_LABCOD:
1825        case R_RELWORD:
1826        case R_PCRWORD:
1827        case R_ANKPCR16:
1828        case R_GSPPCR16:
1829        case R_GSPPCA16:
1830        case R_PARTLS16:
1831        case R_PARTMS8:
1832        case R_PARTMS9:
1833        case R_PARTMID10:
1834        case R_PARTMS16:
1835        case R_REL22:
1836        case R_REL13:        
1837        case R_C8PVECADR:    return 16;
1839        case R_REL24:
1840        case R_PCR24:
1841        case R_PCR24W:
1842       case R_C8PADR24:      return 24;
1844        case R_MPPCR:
1845        case R_GSPOPR32:
1846        case R_RELLONG:
1847        case R_PCRLONG:
1848        case R_OCBD32:
1849        case R_OCRLONG:
1850        case R_DIR32:        return 32;
1852        default:             return 0;
1853    }
1857 /*************************************************************************/
1858 /*                                                                       */
1859 /*   RELOC_OFFSET()-                                                     */
1860 /*      Return the offset of a relocation type field.  The value of      */
1861 /*      offset should be the bit offset of the LSB of the field in       */
1862 /*      little-endian mode.                                              */
1863 /*                                                                       */
1864 /*************************************************************************/
1866 int reloc_offset(int type)
1868    switch (type)
1869    {
1870        case R_PP15    :
1871        case R_PP15W   :
1872        case R_PP15H   :
1873        case R_PP16B   :
1874        case R_PPN15   :
1875        case R_PPN15W  :
1876        case R_PPN15H  :
1877        case R_PPN16B  :
1878        case R_PPLBASE :     return 22;
1880        case R_PPL15   :
1881        case R_PPL15W  :
1882        case R_PPL15H  :
1883        case R_PPL16B  :
1884        case R_PPLN15  :
1885        case R_PPLN15W :
1886        case R_PPLN15H :
1887        case R_PPLN16B :
1888        case R_PPBASE  :     return 0;
1890        default        :     return 0;
1891    }
1895 /*************************************************************************/
1896 /*                                                                       */
1897 /*   RELOC_STOP() -                                                      */
1898 /*      Return the number of bits to read for a relocation type.         */
1899 /*                                                                       */
1900 /*************************************************************************/
1902 int reloc_stop(int type)
1904    switch (type)
1905    {
1906        case R_PPBASE  :
1907        case R_PPLBASE :
1909        case R_PP15    :
1910        case R_PP15W   :
1911        case R_PP15H   :
1912        case R_PP16B   :
1914        case R_PPL15   :
1915        case R_PPL15W  :
1916        case R_PPL15H  :
1917        case R_PPL16B  :
1919        case R_PPN15   :
1920        case R_PPN15W  :
1921        case R_PPN15H  :
1922        case R_PPN16B  :
1924        case R_PPLN15  :
1925        case R_PPLN15W :
1926        case R_PPLN15H :
1927        case R_PPLN16B :   return 64;
1929        default       :    return WORDSZ * 8;
1930    }
1934 /******************************************************************************/
1935 /*                                                                            */
1936 /* SYM_RELOC_AMOUNT() - Determine the amount of relocation for a particular   */
1937 /*                      relocation entry.  Search the relocation symbol table */
1938 /*                      for the referenced symbol, and return the amount from */
1939 /*                      the table.                                            */
1940 /*                                                                            */
1941 /******************************************************************************/
1942 int sym_reloc_amount(RELOC *rp)
1944    int index = rp->r_symndx;
1946    int i = 0,
1947        j = reloc_sym_index - 1;
1949    /*-------------------------------------------------------------------------*/
1950    /* THIS IS A SIMPLE BINARY SEARCH (THE RELOC TABLE IS ALWAYS SORTED).      */
1951    /*-------------------------------------------------------------------------*/
1952    while (i <= j)
1953    {
1954       int m = (i + j) / 2;
1955       if      (reloc_tab[m].rt_index < index) i = m + 1;
1956       else if (reloc_tab[m].rt_index > index) j = m - 1;
1957       else return reloc_tab[m].rt_disp;                              /* FOUND */
1958    }
1960    /*-------------------------------------------------------------------------*/
1961    /* IF NOT FOUND, SYMBOL WAS NOT RELOCATED.                                 */
1962    /*-------------------------------------------------------------------------*/
1963    return 0;
1967 /******************************************************************************/
1968 /*                                                                            */
1969 /*  UNPACK() - Extract a relocation field from object bytes and convert into  */
1970 /*             a int so it can be relocated.                                 */
1971 /*                                                                            */
1972 /******************************************************************************/
1973 unsigned int unpack(unsigned char *data, int fieldsz, int wordsz, int bit_offset)
1975    register int  i;
1976    unsigned int objval;
1977    int           start;                       /* MS byte with reloc data      */
1978    int           stop;                        /* LS byte with reloc data      */
1979    int           r  = bit_offset & 7;         /* num unused LS bits in stop   */
1980    int           l  = 8 - r;                  /* num used   MS bits in stop   */
1981    int           tr = ((bit_offset+fieldsz-1) & 7)+1; /* # LS bits in strt*/
1982    int           tl = 8 - tr;                 /* num unused MS bits in start  */
1984    start = (big_e_target ? (wordsz-fieldsz-bit_offset) : 
1985                            (bit_offset+fieldsz-1)) >>3;
1986    stop  = (big_e_target ? (wordsz-bit_offset-1) : bit_offset) >>3;
1988    if (start == stop) return (data[stop] >> r) & ((0x1 << fieldsz) - 0x1);
1990    objval = (unsigned)((data[start] << tl) & 0xFF) >> tl;
1991    
1992    if (big_e_target) 
1993          for (i=start+1; i<stop; ++i) objval = (objval << 8) | data[i];
1994    else  for (i=start-1; i>stop; --i) objval = (objval << 8) | data[i];
1995    
1996    return (objval << l) | (data[stop] >> r);
2001 /******************************************************************************/
2002 /*                                                                            */
2003 /* REPACK() - Encode a binary relocated field back into the object data.      */
2004 /*                                                                            */
2005 /******************************************************************************/
2006 void repack(unsigned int objval, unsigned char *data, int fieldsz,
2007             int  wordsz, int bit_offset)
2009    register int  i;
2010    int           start;                      /* MS byte with reloc data       */
2011    int           stop;                       /* LS byte with reloc data       */
2012    int           r     = bit_offset & 7;     /* num unused LS bits in stop    */
2013    int           l     = 8 - r;              /* num used   MS bits in stop    */
2014    int           tr    = ((bit_offset+fieldsz-1) & 7)+1; /* # LS bits in strt */
2015    unsigned int mask  = (1ul << fieldsz) - 1ul;
2017    if (fieldsz < sizeof(objval)) objval &= mask;
2018    
2019    start = (big_e_target ? (wordsz-fieldsz-bit_offset) : 
2020                            (bit_offset+fieldsz-1)) >>3;
2021    stop  = (big_e_target ? (wordsz-bit_offset-1) : bit_offset) >>3;
2023    if (start == stop)
2024    {
2025        data[stop] &= ~(mask << r);
2026        data[stop] |= (objval << r); 
2027        return;
2028    }
2030    data[start] &= ~((1<<tr)-1);
2031    data[stop]  &=  ((1<< r)-1);
2032    data[stop]  |= (objval << r); 
2033    objval     >>= l;
2035    if (big_e_target) 
2036         for (i = stop - 1; i > start; objval >>= 8) data[i--] = objval;
2037    else for (i = stop + 1; i < start; objval >>= 8) data[i++] = objval;
2038    
2039    data[start] |= objval; 
2043 /******************************************************************************/
2044 /*                                                                            */
2045 /* CLOAD_LINENO() - Read in, swap, and relocate line number entries.  This    */
2046 /*                  function is not called directly by the loader, but by the */
2047 /*                  application when it needs to read in line number entries. */
2048 /*                                                                            */
2049 /******************************************************************************/
2050 int cload_lineno(int filptr, int count, LINENO *lptr, int scnum) 
2052 /*   int    filptr;                      WHERE TO READ FROM                  */
2053 /*   int     count;                       HOW MANY TO READ                    */
2054 /*   LINENO *lptr;                        WHERE TO PUT THEM                   */
2055 /*   int     scnum;                       SECTION NUMBER OF THESE ENTRIES     */
2057     int i;
2059     /*------------------------------------------------------------------------*/
2060     /* READ IN THE REQUESTED NUMBER OF LINE NUMBER ENTRIES AS A BLOCK.        */
2061     /*------------------------------------------------------------------------*/
2062 #if FILE_BASED
2063     if (fseek(fin, filptr, 0) != 0) { load_err = E_FILE; return FALSE; }
2064     for (i = 0; i < count; i++)
2065         if (fread(lptr + i, 1, LINESZ, fin) != LINESZ) 
2066                                     { load_err = E_FILE; return FALSE; }
2067 #else
2068         for (i = 0; i < count; i++)
2069         mem_copy((void*)(lptr+i), (void*)&gRxBuffer[filptr + i*LINESZ], LINESZ);
2070 #endif
2071     /*------------------------------------------------------------------------*/
2072     /* SWAP AND RELOCATE EACH ENTRY, AS NECESSARY.                            */
2073     /*------------------------------------------------------------------------*/
2074     if (byte_swapped || RUN_RELOC_AMOUNT(scnum - 1))
2075        for (i = 0; i < count; i++, lptr++)
2076        {
2077           if (byte_swapped)
2078           {
2079               swap2byte(&lptr->l_lnno);
2080               swap4byte(&lptr->l_addr.l_paddr);
2081           }
2083           if (lptr->l_lnno != 0) 
2084              lptr->l_addr.l_paddr += RUN_RELOC_AMOUNT(scnum - 1);
2085        }
2086     
2087     return TRUE;
2091 /******************************************************************************/
2092 /*                                                                            */
2093 /*  SWAP4BYTE() - Swap the order of bytes in a int.                          */
2094 /*                                                                            */
2095 /******************************************************************************/
2096 void swap4byte(void *addr)
2098    unsigned int *value = (unsigned int *)addr;
2099    unsigned int temp1, temp2, temp3, temp4;
2101    temp1 = (*value)       & 0xFF;
2102    temp2 = (*value >> 8)  & 0xFF;
2103    temp3 = (*value >> 16) & 0xFF;
2104    temp4 = (*value >> 24) & 0xFF;
2106    *value = (temp1 << 24) | (temp2 << 16) | (temp3 << 8) | temp4;
2110 /******************************************************************************/
2111 /*                                                                            */
2112 /*  SWAP2BYTE() - Swap the order of bytes in a short.                         */
2113 /*                                                                            */
2114 /******************************************************************************/
2115 void swap2byte(void *addr)
2117    unsigned short *value = (unsigned short *)addr;
2118    unsigned short temp1,temp2;
2120    temp1 = temp2 = *value;
2121    *value = ((temp2 & 0xFF) << 8) | ((temp1 >> 8) & 0xFF);