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 */
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
143 {
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
175 {
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)
199 {
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 }
215 }
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)
224 {
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
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 *)§_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 }
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;
393 }
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)
402 {
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 = §_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;
440 }
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)
449 {
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;
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 }
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 */
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);
592 }
594 } else {
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;
611 }
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)
620 {
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 */
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 {
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;
693 }
695 #if 0
696 /******************************************************************************/
697 /* */
698 /* CLOAD_SYMBOLS() - Read in the symbol table. */
699 /* */
700 /******************************************************************************/
701 int cload_symbols()
702 {
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;
750 }
753 /******************************************************************************/
754 /* */
755 /* CLOAD_STRINGS() - Read in the string table. */
756 /* */
757 /******************************************************************************/
758 int cload_strings()
759 {
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;
858 }
860 \f
861 /******************************************************************************/
862 /* */
863 /* STR_FREE() - Free the list of string table buffers. */
864 /* */
865 /******************************************************************************/
866 void str_free(STRTAB *head)
867 {
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 }
874 }
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)
885 {
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 }
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);
1016 }
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)
1026 {
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 }
1060 strn_copy(temp, symptr->n_name, 8);
1061 temp[8] = 0;
1062 return temp;
1063 }
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)
1074 {
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;
1117 }
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)
1127 {
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;
1167 }
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)
1175 {
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;
1228 if (objval & ((-1L >> 8*fieldsz) << 8*fieldsz))
1229 {
1230 /* ERROR */
1231 }
1233 break;
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);
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 }
1289 /*--------------------------------------------------------------*/
1290 /* ERROR, THE OFFSET WILL NOT FIT SCALED OR UNSCALED. */
1291 /*--------------------------------------------------------------*/
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 /*--------------------------------------------------------------*/
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 /*--------------------------------------------------------------*/
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
1699 {
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;
1778 }
1781 /*************************************************************************/
1782 /* */
1783 /* RELOC_SIZE()- */
1784 /* Return the field size of a relocation type. */
1785 /* */
1786 /*************************************************************************/
1788 int reloc_size(int type)
1789 {
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 }
1854 }
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)
1867 {
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 }
1892 }
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)
1903 {
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 }
1931 }
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)
1943 {
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;
1964 }
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)
1974 {
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;
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];
1996 return (objval << l) | (data[stop] >> r);
1997 }
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)
2008 {
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;
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;
2039 data[start] |= objval;
2040 }
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)
2051 {
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 }
2087 return TRUE;
2088 }
2091 /******************************************************************************/
2092 /* */
2093 /* SWAP4BYTE() - Swap the order of bytes in a int. */
2094 /* */
2095 /******************************************************************************/
2096 void swap4byte(void *addr)
2097 {
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;
2107 }
2110 /******************************************************************************/
2111 /* */
2112 /* SWAP2BYTE() - Swap the order of bytes in a short. */
2113 /* */
2114 /******************************************************************************/
2115 void swap2byte(void *addr)
2116 {
2117 unsigned short *value = (unsigned short *)addr;
2118 unsigned short temp1,temp2;
2120 temp1 = temp2 = *value;
2121 *value = ((temp2 & 0xFF) << 8) | ((temp1 >> 8) & 0xFF);
2122 }