%{_arch} doesn't work with newer RPMs; use %{_target_cpu} instead
[nasm/avx512.git] / rdoff / ldrdf.c
blob26c991ee81814656ee486e0c240e3d4ad372efcc
1 /* ldrdf.c RDOFF Object File linker/loader main program
3 * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
4 * Julian Hall. All rights reserved. The software is
5 * redistributable under the licence given in the file "Licence"
6 * distributed in the NASM archive.
7 */
9 /*
10 * TODO:
11 * - enhance search of required export symbols in libraries (now depends
12 * on modules order in library)
13 * - keep a cache of symbol names in each library module so
14 * we don't have to constantly recheck the file
15 * - general performance improvements
17 * BUGS & LIMITATIONS: this program doesn't support multiple code, data
18 * or bss segments, therefore for 16 bit programs whose code, data or BSS
19 * segment exceeds 64K in size, it will not work. This program probably
20 * won't work if compiled by a 16 bit compiler. Try DJGPP if you're running
21 * under DOS. '#define STINGY_MEMORY' may help a little.
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
28 #include "rdoff.h"
29 #include "symtab.h"
30 #include "collectn.h"
31 #include "rdlib.h"
32 #include "segtab.h"
34 #define LDRDF_VERSION "1.05"
36 #define RDF_MAXSEGS 64
37 /* #define STINGY_MEMORY */
39 /* =======================================================================
40 * Types & macros that are private to this program
43 struct segment_infonode {
44 int dest_seg; /* output segment to be placed into, -1 to
45 skip linking this segment */
46 long reloc; /* segment's relocation factor */
50 struct modulenode {
51 rdffile f; /* the RDOFF file structure */
52 struct segment_infonode seginfo[RDF_MAXSEGS]; /* what are we doing
53 with each segment? */
54 void * header;
55 char * name;
56 struct modulenode * next;
57 long bss_reloc;
60 #include "ldsegs.h"
62 #define newstr(str) strcpy(malloc(strlen(str) + 1),str)
63 #define newstrcat(s1,s2) strcat(strcpy(malloc(strlen(s1)+strlen(s2)+1),s1),s2)
65 /* ==========================================================================
66 * Function prototypes of private utility functions
69 void processmodule(const char * filename, struct modulenode * mod);
70 int allocnewseg(int16 type,int16 reserved);
71 int findsegment(int16 type,int16 reserved);
72 void symtab_add(const char * symbol, int segment, long offset);
73 int symtab_get(const char * symbol, int * segment, long * offset);
75 /* =========================================================================
76 * Global data structures.
79 /* a linked list of modules that will be included in the output */
80 struct modulenode * modules = NULL;
81 struct modulenode * lastmodule = NULL;
83 /* a linked list of libraries to be searched for unresolved imported symbols */
84 struct librarynode * libraries = NULL;
85 struct librarynode * lastlib = NULL;
87 /* the symbol table */
88 void * symtab = NULL;
90 /* objects search path */
91 char * objpath = NULL;
93 /* libraries search path */
94 char * libpath = NULL;
96 /* file to embed as a generic record */
97 char * generic_rec_file = NULL;
99 /* error file */
100 static FILE * error_file;
102 /* the header of the output file, built up stage by stage */
103 rdf_headerbuf * newheader = NULL;
105 /* The current state of segment allocation, including information about
106 * which output segment numbers have been allocated, and their types and
107 * amount of data which has already been allocated inside them.
109 struct SegmentHeaderRec outputseg[RDF_MAXSEGS];
110 int nsegs = 0;
111 long bss_length;
113 /* global options which affect how the program behaves */
114 struct ldrdfoptions {
115 int verbose;
116 int align;
117 int warnUnresolved;
118 int strip;
119 int respfile;
120 int stderr_redir;
121 int objpath;
122 int libpath;
123 } options;
125 int errorcount = 0; /* determines main program exit status */
128 /* =========================================================================
129 * Utility functions
134 * initsegments()
136 * sets up segments 0, 1, and 2, the initial code data and bss segments
139 void initsegments()
141 nsegs = 3;
142 outputseg[0].type = 1;
143 outputseg[0].number = 0;
144 outputseg[0].reserved = 0;
145 outputseg[0].length = 0;
146 outputseg[1].type = 2;
147 outputseg[1].number = 1;
148 outputseg[1].reserved = 0;
149 outputseg[1].length = 0;
150 outputseg[2].type = 0xFFFF; /* reserved segment type */
151 outputseg[2].number = 2;
152 outputseg[2].reserved = 0;
153 outputseg[2].length = 0;
154 bss_length = 0;
158 * loadmodule
160 * Determine the characteristics of a module, and decide what to do with
161 * each segment it contains (including determining destination segments and
162 * relocation factors for segments that are kept).
165 void loadmodule(const char * filename)
167 if (options.verbose)
168 printf("loading `%s'\n", filename);
170 /* allocate a new module entry on the end of the modules list */
171 if (!modules)
173 modules = malloc (sizeof(*modules));
174 lastmodule = modules;
176 else
178 lastmodule->next = malloc (sizeof(*modules));
179 lastmodule = lastmodule->next;
182 if ( ! lastmodule)
184 fprintf(stderr, "ldrdf: out of memory\n");
185 exit(1);
188 /* open the file using 'rdfopen', which returns nonzero on error */
190 if (rdfopen(&lastmodule->f, filename) != 0)
192 rdfperror("ldrdf", filename);
193 exit(1);
197 * store information about the module, and determine what segments
198 * it contains, and what we should do with them (determine relocation
199 * factor if we decide to keep them)
202 lastmodule->header = NULL;
203 lastmodule->name = strdup(filename);
204 lastmodule->next = NULL;
206 processmodule(filename, lastmodule);
210 * processmodule()
212 * step through each segment, determine what exactly we're doing with
213 * it, and if we intend to keep it, determine (a) which segment to
214 * put it in and (b) whereabouts in that segment it will end up.
215 * (b) is fairly easy, because we're now keeping track of how big each
216 * segment in our output file is...
219 void processmodule(const char * filename, struct modulenode * mod)
221 struct segconfig sconf;
222 int seg, outseg;
223 void * header;
224 rdfheaderrec * hr;
225 long bssamount = 0;
226 int bss_was_referenced = 0;
228 for (seg = 0; seg < mod->f.nsegs; seg++)
231 * get the segment configuration for this type from the segment
232 * table. getsegconfig() is a macro, defined in ldsegs.h.
234 getsegconfig(sconf, mod->f.seg[seg].type);
236 if (options.verbose > 1) {
237 printf ("%s %04x [%04x:%10s] ", filename, mod->f.seg[seg].number,
238 mod->f.seg[seg].type, sconf.typedesc);
241 * sconf->dowhat tells us what to do with a segment of this type.
243 switch (sconf.dowhat) {
244 case SEG_IGNORE:
246 * Set destination segment to -1, to indicate that this segment
247 * should be ignored for the purpose of output, ie it is left
248 * out of the linked executable.
250 mod->seginfo[seg].dest_seg = -1;
251 if (options.verbose > 1) printf("IGNORED\n");
252 break;
254 case SEG_NEWSEG:
256 * The configuration tells us to create a new segment for
257 * each occurrence of this segment type.
259 outseg = allocnewseg(sconf.mergetype,
260 mod->f.seg[seg].reserved);
261 mod->seginfo[seg].dest_seg = outseg;
262 mod->seginfo[seg].reloc = 0;
263 outputseg[outseg].length = mod->f.seg[seg].length;
264 if (options.verbose > 1)
265 printf ("=> %04x:%08lx (+%04lx)\n", outseg,
266 mod->seginfo[seg].reloc,
267 mod->f.seg[seg].length);
268 break;
270 case SEG_MERGE:
272 * The configuration tells us to merge the segment with
273 * a previously existing segment of type 'sconf.mergetype',
274 * if one exists. Otherwise a new segment is created.
275 * This is handled transparently by 'findsegment()'.
277 outseg = findsegment(sconf.mergetype,
278 mod->f.seg[seg].reserved);
279 mod->seginfo[seg].dest_seg = outseg;
282 * We need to add alignment to these segments.
284 if (outputseg[outseg].length % options.align != 0)
285 outputseg[outseg].length +=
286 options.align - (outputseg[outseg].length % options.align);
288 mod->seginfo[seg].reloc = outputseg[outseg].length;
289 outputseg[outseg].length += mod->f.seg[seg].length;
291 if (options.verbose > 1)
292 printf ("=> %04x:%08lx (+%04lx)\n", outseg,
293 mod->seginfo[seg].reloc,
294 mod->f.seg[seg].length);
300 * extract symbols from the header, and dump them into the
301 * symbol table
303 header = malloc(mod->f.header_len);
304 if (!header) {
305 fprintf(stderr, "ldrdf: not enough memory\n");
306 exit(1);
308 if (rdfloadseg(&mod->f, RDOFF_HEADER, header)) {
309 rdfperror("ldrdf", filename);
310 exit(1);
313 while ((hr = rdfgetheaderrec (&mod->f))) {
314 switch(hr->type) {
315 case RDFREC_IMPORT: /* imported symbol */
316 case RDFREC_FARIMPORT:
317 /* Define with seg = -1 */
318 symtab_add(hr->i.label, -1, 0);
319 break;
321 case RDFREC_GLOBAL: { /* exported symbol */
322 int destseg;
323 long destreloc;
325 if (hr->e.segment == 2) {
326 bss_was_referenced = 1;
327 destreloc = bss_length;
328 if (destreloc % options.align != 0)
329 destreloc += options.align - (destreloc % options.align);
330 destseg = 2;
331 } else {
332 if ((destseg = mod->seginfo[(int)hr->e.segment].dest_seg) == -1)
333 continue;
334 destreloc = mod->seginfo[(int)hr->e.segment].reloc;
336 symtab_add(hr->e.label, destseg, destreloc + hr->e.offset);
337 break;
340 case RDFREC_BSS: /* BSS reservation */
342 * first, amalgamate all BSS reservations in this module
343 * into one, because we allow this in the output format.
345 bssamount += hr->b.amount;
346 break;
348 case RDFREC_COMMON: { /* Common variable */
349 symtabEnt *ste = symtabFind(symtab, hr->c.label);
351 /* Is the symbol already in the table? */
352 if (ste) break;
354 /* Align the variable */
355 if (bss_length % hr->c.align != 0)
356 bss_length += hr->c.align - (bss_length % hr->c.align);
357 if (options.verbose > 1) {
358 printf ("%s %04x common '%s' => 0002:%08lx (+%04lx)\n",
359 filename, hr->c.segment, hr->c.label, bss_length, hr->c.size);
362 symtab_add(hr->c.label, 2, bss_length);
363 mod->bss_reloc = bss_length;
364 bss_length += hr->c.size;
365 break;
370 if (bssamount != 0 || bss_was_referenced) {
372 * handle the BSS segment - first pad the existing bss length
373 * to the correct alignment, then store the length in bss_reloc
374 * for this module. Then add this module's BSS length onto
375 * bss_length.
377 if (bss_length % options.align != 0)
378 bss_length += options.align - (bss_length % options.align);
380 mod->bss_reloc = bss_length;
381 if (options.verbose > 1) {
382 printf ("%s 0002 [ BSS] => 0002:%08lx (+%04lx)\n",
383 filename, bss_length, bssamount);
385 bss_length += bssamount;
388 #ifdef STINGY_MEMORY
390 * we free the header buffer here, to save memory later.
391 * this isn't efficient, but probably halves the memory usage
392 * of this program...
394 mod->f.header_loc = NULL;
395 free(header);
397 #endif
403 * Look in the list for module by its name.
405 int lookformodule(const char *name)
407 struct modulenode *curr=modules;
409 while(curr) {
410 if (!strcmp(name,curr->name)) return 1;
411 curr = curr->next;
413 return 0;
418 * allocnewseg()
419 * findsegment()
421 * These functions manipulate the array of output segments, and are used
422 * by processmodule(). allocnewseg() allocates a segment in the array,
423 * initialising it to be empty. findsegment() first scans the array for
424 * a segment of the type requested, and if one isn't found allocates a
425 * new one.
427 int allocnewseg(int16 type,int16 reserved)
429 outputseg[nsegs].type = type;
430 outputseg[nsegs].number = nsegs;
431 outputseg[nsegs].reserved = reserved;
432 outputseg[nsegs].length = 0;
433 outputseg[nsegs].offset = 0;
434 outputseg[nsegs].data = NULL;
436 return nsegs++;
439 int findsegment(int16 type,int16 reserved)
441 int i;
443 for (i = 0; i < nsegs; i++)
444 if (outputseg[i].type == type) return i;
446 return allocnewseg(type,reserved);
450 * symtab_add()
452 * inserts a symbol into the global symbol table, which associates symbol
453 * names either with addresses, or a marker that the symbol hasn't been
454 * resolved yet, or possibly that the symbol has been defined as
455 * contained in a dynamic [load time/run time] linked library.
457 * segment = -1 => not yet defined
458 * segment = -2 => defined as dll symbol
460 * If the symbol is already defined, and the new segment >= 0, then
461 * if the original segment was < 0 the symbol is redefined, otherwise
462 * a duplicate symbol warning is issued. If new segment == -1, this
463 * routine won't change a previously existing symbol. It will change
464 * to segment = -2 only if the segment was previously < 0.
467 void symtab_add(const char * symbol, int segment, long offset)
469 symtabEnt * ste;
471 ste = symtabFind(symtab, symbol);
472 if (ste)
474 if (ste->segment >= 0) {
476 * symbol previously defined
478 if (segment < 0) return;
479 fprintf (error_file, "warning: `%s' redefined\n", symbol);
480 return;
484 * somebody wanted the symbol, and put an undefined symbol
485 * marker into the table
487 if (segment == -1) return;
489 * we have more information now - update the symbol's entry
491 ste->segment = segment;
492 ste->offset = offset;
493 ste->flags = 0;
494 return;
497 * this is the first declaration of this symbol
499 ste = malloc(sizeof(symtabEnt));
500 if (!ste) {
501 fprintf(stderr, "ldrdf: out of memory\n");
502 exit(1);
504 ste->name = strdup(symbol);
505 ste->segment = segment;
506 ste->offset = offset;
507 ste->flags = 0;
508 symtabInsert(symtab, ste);
512 * symtab_get()
514 * Retrieves the values associated with a symbol. Undefined symbols
515 * are assumed to have -1:0 associated. Returns 1 if the symbol was
516 * successfully located.
519 int symtab_get(const char * symbol, int * segment, long * offset)
521 symtabEnt * ste = symtabFind(symtab, symbol);
522 if (!ste) {
523 *segment = -1;
524 *offset = 0;
525 return 0;
527 else
529 *segment = ste->segment;
530 *offset = ste->offset;
531 return 1;
536 * add_library()
538 * checks that a library can be opened and is in the correct format,
539 * then adds it to the linked list of libraries.
542 void add_library(const char * name)
544 if (rdl_verify(name)) {
545 rdl_perror("ldrdf", name);
546 errorcount++;
547 return;
549 if (! libraries)
551 lastlib = libraries = malloc(sizeof(*libraries));
552 if (! libraries) {
553 fprintf(stderr, "ldrdf: out of memory\n");
554 exit(1);
557 else
559 lastlib->next = malloc(sizeof(*libraries));
560 if (!lastlib->next) {
561 fprintf(stderr, "ldrdf: out of memory\n");
562 exit(1);
564 lastlib = lastlib->next;
566 lastlib->next = NULL;
567 if (rdl_open(lastlib, name)) {
568 rdl_perror("ldrdf", name);
569 errorcount++;
570 return;
575 * search_libraries()
577 * scans through the list of libraries, attempting to match symbols
578 * defined in library modules against symbols that are referenced but
579 * not defined (segment = -1 in the symbol table)
581 * returns 1 if any extra library modules are included, indicating that
582 * another pass through the library list should be made (possibly).
585 int search_libraries()
587 struct librarynode * cur;
588 rdffile f;
589 int i;
590 void * header;
591 int segment;
592 long offset;
593 int doneanything = 0, pass = 1, keepfile;
594 rdfheaderrec * hr;
596 cur = libraries;
598 while (cur)
600 if (options.verbose > 2)
601 printf("scanning library `%s', pass %d...\n", cur->name, pass);
603 for (i = 0; rdl_openmodule(cur, i, &f) == 0; i++)
605 if (pass == 2 && lookformodule(f.name)) continue;
607 if (options.verbose > 3)
608 printf(" looking in module `%s'\n", f.name);
610 header = malloc(f.header_len);
611 if (!header) {
612 fprintf(stderr, "ldrdf: not enough memory\n");
613 exit(1);
615 if (rdfloadseg(&f, RDOFF_HEADER, header)) {
616 rdfperror("ldrdf", f.name);
617 errorcount++;
618 return 0;
621 keepfile = 0;
623 while ((hr = rdfgetheaderrec (&f)))
625 /* We're only interested in exports, so skip others */
626 if (hr->type != RDFREC_GLOBAL) continue;
629 * If the symbol is marked as SYM_GLOBAL, somebody will be
630 * definitely interested in it..
632 if ((hr->e.flags & SYM_GLOBAL) == 0) {
634 * otherwise the symbol is just public. Find it in
635 * the symbol table. If the symbol isn't defined, we
636 * aren't interested, so go on to the next.
637 * If it is defined as anything but -1, we're also not
638 * interested. But if it is defined as -1, insert this
639 * module into the list of modules to use, and go
640 * immediately on to the next module...
642 if (!symtab_get(hr->e.label, &segment, &offset) || segment != -1)
643 continue;
646 doneanything = 1;
647 keepfile = 1;
650 * as there are undefined symbols, we can assume that
651 * there are modules on the module list by the time
652 * we get here.
654 lastmodule->next = malloc(sizeof(*lastmodule->next));
655 if (!lastmodule->next) {
656 fprintf(stderr, "ldrdf: not enough memory\n");
657 exit(1);
659 lastmodule = lastmodule->next;
660 memcpy(&lastmodule->f, &f, sizeof(f));
661 lastmodule->name = strdup(f.name);
662 lastmodule->next = NULL;
663 processmodule(f.name, lastmodule);
664 break;
666 if (!keepfile) {
667 free(f.name);
668 f.name = NULL;
669 f.fp = NULL;
672 if (rdl_error != 0 && rdl_error != RDL_ENOTFOUND)
673 rdl_perror("ldrdf", cur->name);
675 cur = cur->next;
676 if (cur == NULL && pass == 1) {
677 cur = libraries;
678 pass++;
682 return doneanything;
686 * write_output()
688 * this takes the linked list of modules, and walks through it, merging
689 * all the modules into a single output module, and then writes this to a
690 * file.
692 void write_output(const char * filename)
694 FILE * f;
695 rdf_headerbuf * rdfheader;
696 struct modulenode * cur;
697 int i, availableseg, seg, localseg, isrelative;
698 void * header;
699 rdfheaderrec * hr, newrec;
700 symtabEnt * se;
701 segtab segs;
702 long offset;
703 byte * data;
705 if ((f = fopen(filename, "wb"))==NULL) {
706 fprintf(stderr, "ldrdf: couldn't open %s for output\n", filename);
707 exit(1);
709 if ((rdfheader=rdfnewheader())==NULL) {
710 fprintf(stderr, "ldrdf: out of memory\n");
711 exit(1);
715 * If '-g' option was given, first record in output file will be a
716 * `generic' record, filled with a given file content.
717 * This can be useful, for example, when constructing multiboot
718 * compliant kernels.
720 if (generic_rec_file) {
721 FILE *ff;
723 if (options.verbose)
724 printf("\nadding generic record from binary file %s\n", generic_rec_file);
726 hr = (rdfheaderrec *) malloc(sizeof(struct GenericRec));
727 if ((ff = fopen(generic_rec_file, "r")) == NULL) {
728 fprintf(stderr, "ldrdf: couldn't open %s for input\n", generic_rec_file);
729 exit(1);
731 i = fread(hr->g.data, 1, sizeof(hr->g.data), ff);
732 fseek(ff, 0, SEEK_END);
733 if (ftell(ff) > sizeof(hr->g.data)) {
734 fprintf (error_file, "warning: maximum generic record size is %d, rest of file ignored\n", sizeof(hr->g.data));
736 fclose(ff);
738 hr->g.type = 0;
739 hr->g.reclen = i;
740 rdfaddheader(rdfheader,hr);
741 free(hr);
744 if (options.verbose)
745 printf ("\nbuilding output module (%d segments)\n", nsegs);
748 * Allocate the memory for the segments. We may be better off
749 * building the output module one segment at a time when running
750 * under 16 bit DOS, but that would be a slower way of doing this.
751 * And you could always use DJGPP...
753 for (i = 0; i < nsegs; i++)
755 outputseg[i].data=NULL;
756 if(!outputseg[i].length) continue;
757 outputseg[i].data = malloc(outputseg[i].length);
758 if (!outputseg[i].data) {
759 fprintf(stderr, "ldrdf: out of memory\n");
760 exit(1);
765 * initialise availableseg, used to allocate segment numbers for
766 * imported and exported labels...
768 availableseg = nsegs;
771 * Step through the modules, performing required actions on each one
773 for (cur = modules; cur; cur=cur->next)
776 * Read the actual segment contents into the correct places in
777 * the newly allocated segments
780 for (i = 0; i < cur->f.nsegs; i++)
782 int dest = cur->seginfo[i].dest_seg;
784 if (dest == -1) continue;
785 if (rdfloadseg(&cur->f, i,
786 outputseg[dest].data + cur->seginfo[i].reloc))
788 rdfperror("ldrdf", cur->name);
789 exit(1);
794 * Perform fixups, and add new header records where required
797 header = malloc(cur->f.header_len);
798 if (!header) {
799 fprintf(stderr, "ldrdf: out of memory\n");
800 exit(1);
803 if (cur->f.header_loc)
804 rdfheaderrewind(&cur->f);
805 else
806 if (rdfloadseg(&cur->f, RDOFF_HEADER, header))
808 rdfperror("ldrdf", cur->name);
809 exit(1);
813 * we need to create a local segment number -> location
814 * table for the segments in this module.
816 init_seglocations(&segs);
817 for (i = 0; i < cur->f.nsegs; i++)
819 add_seglocation(&segs, cur->f.seg[i].number,
820 cur->seginfo[i].dest_seg, cur->seginfo[i].reloc);
823 * and the BSS segment (doh!)
825 add_seglocation (&segs, 2, 2, cur->bss_reloc);
827 while ((hr = rdfgetheaderrec(&cur->f)))
829 switch(hr->type) {
830 case RDFREC_RELOC: /* relocation record - need to do a fixup */
832 * First correct the offset stored in the segment from
833 * the start of the segment (which may well have changed).
835 * To do this we add to the number stored the relocation
836 * factor associated with the segment that contains the
837 * target segment.
839 * The relocation could be a relative relocation, in which
840 * case we have to first subtract the amount we've relocated
841 * the containing segment by.
844 if (!get_seglocation(&segs, hr->r.refseg, &seg, &offset))
846 fprintf(stderr, "%s: reloc to undefined segment %04x\n",
847 cur->name, (int) hr->r.refseg);
848 errorcount++;
849 break;
852 isrelative = (hr->r.segment & 64) == 64;
853 hr->r.segment &= 63;
855 if (hr->r.segment == 2 ||
856 (localseg = rdffindsegment(&cur->f, hr->r.segment)) == -1)
858 fprintf(stderr, "%s: reloc from %s segment (%d)\n",
859 cur->name,
860 hr->r.segment == 2 ? "BSS" : "unknown",
861 hr->r.segment);
862 errorcount++;
863 break;
866 if (hr->r.length != 1 && hr->r.length != 2 && hr->r.length!=4)
868 fprintf(stderr, "%s: nonstandard length reloc "
869 "(%d bytes)\n", cur->name, hr->r.length);
870 errorcount++;
871 break;
875 * okay, now the relocation is in the segment pointed to by
876 * cur->seginfo[localseg], and we know everything else is
877 * okay to go ahead and do the relocation
879 data = outputseg[cur->seginfo[localseg].dest_seg].data;
880 data += cur->seginfo[localseg].reloc + hr->r.offset;
883 * data now points to the reference that needs
884 * relocation. Calculate the relocation factor.
885 * Factor is:
886 * offset of referred object in segment [in offset]
887 * (- relocation of localseg, if ref is relative)
888 * For simplicity, the result is stored in 'offset'.
889 * Then add 'offset' onto the value at data.
892 if (isrelative) offset -= cur->seginfo[localseg].reloc;
893 switch (hr->r.length)
895 case 1:
896 offset += *data;
897 if (offset < -127 || offset > 128)
898 fprintf(error_file, "warning: relocation out of range "
899 "at %s(%02x:%08lx)\n", cur->name,
900 (int)hr->r.segment, hr->r.offset);
901 *data = (char) offset;
902 break;
903 case 2:
904 offset += * (short *)data;
905 if (offset < -32767 || offset > 32768)
906 fprintf(error_file, "warning: relocation out of range "
907 "at %s(%02x:%08lx)\n", cur->name,
908 (int)hr->r.segment, hr->r.offset);
909 * (short *)data = (short) offset;
910 break;
911 case 4:
912 * (long *)data += offset;
913 /* we can't easily detect overflow on this one */
914 break;
918 * If the relocation was relative between two symbols in
919 * the same segment, then we're done.
921 * Otherwise, we need to output a new relocation record
922 * with the references updated segment and offset...
924 if (! isrelative || cur->seginfo[localseg].dest_seg != seg)
926 hr->r.segment = cur->seginfo[localseg].dest_seg;
927 hr->r.offset += cur->seginfo[localseg].reloc;
928 hr->r.refseg = seg;
929 if (isrelative)
930 hr->r.segment += 64;
931 rdfaddheader(rdfheader, hr);
933 break;
935 case RDFREC_IMPORT: /* import symbol */
936 case RDFREC_FARIMPORT:
938 * scan the global symbol table for the symbol
939 * and associate its location with the segment number
940 * for this module
942 se = symtabFind(symtab, hr->i.label);
943 if (!se || se->segment == -1) {
944 if (options.warnUnresolved) {
945 switch (options.warnUnresolved) {
946 case 1:
947 fprintf(error_file, "warning");
948 break;
949 case 2:
950 fprintf(error_file, "error");
951 errorcount++;
953 fprintf(error_file, ": unresolved reference to `%s'"
954 " in module `%s'\n", hr->i.label, cur->name);
957 * we need to allocate a segment number for this
958 * symbol, and store it in the symbol table for
959 * future reference
961 if (!se) {
962 se=malloc(sizeof(*se));
963 if (!se) {
964 fprintf(stderr, "ldrdf: out of memory\n");
965 exit(1);
967 se->name = strdup(hr->i.label);
968 se->flags = 0;
969 se->segment = availableseg++;
970 se->offset = 0;
971 symtabInsert(symtab, se);
973 else {
974 se->segment = availableseg++;
975 se->offset = 0;
978 * output a header record that imports it to the
979 * recently allocated segment number...
981 newrec = *hr;
982 newrec.i.segment = se->segment;
983 rdfaddheader(rdfheader, &newrec);
986 add_seglocation(&segs, hr->i.segment, se->segment, se->offset);
988 break;
990 case RDFREC_GLOBAL: /* export symbol */
992 * need to insert an export for this symbol into the new
993 * header, unless we're stripping symbols. Even if we're
994 * stripping, put the symbol if it's marked as SYM_GLOBAL.
996 if (options.strip && !(hr->e.flags & SYM_GLOBAL))
997 break;
999 if (hr->e.segment == 2) {
1000 seg = 2;
1001 offset = cur->bss_reloc;
1003 else {
1004 localseg = rdffindsegment(&cur->f, hr->e.segment);
1005 if (localseg == -1) {
1006 fprintf(stderr, "%s: exported symbol `%s' from "
1007 "unrecognised segment\n", cur->name,
1008 hr->e.label);
1009 errorcount++;
1010 break;
1012 offset = cur->seginfo[localseg].reloc;
1013 seg = cur->seginfo[localseg].dest_seg;
1016 hr->e.segment = seg;
1017 hr->e.offset += offset;
1018 rdfaddheader(rdfheader, hr);
1019 break;
1021 case RDFREC_MODNAME: /* module name */
1023 * Insert module name record if export symbols
1024 * are not stripped.
1025 * If module name begins with '$' - insert it anyway.
1027 if (options.strip && hr->m.modname[0] != '$') break;
1028 rdfaddheader(rdfheader, hr);
1029 break;
1031 case RDFREC_DLL: /* DLL name */
1033 * Insert DLL name if it begins with '$'
1035 if (hr->d.libname[0] != '$') break;
1036 rdfaddheader(rdfheader, hr);
1037 break;
1039 case RDFREC_SEGRELOC: /* segment fixup */
1041 * modify the segment numbers if necessary, and
1042 * pass straight through to the output module header
1044 * *** FIXME ***
1046 if (hr->r.segment == 2) {
1047 fprintf(stderr, "%s: segment fixup in BSS section\n",
1048 cur->name);
1049 errorcount++;
1050 break;
1052 localseg = rdffindsegment(&cur->f, hr->r.segment);
1053 if (localseg == -1) {
1054 fprintf(stderr, "%s: segment fixup in unrecognised"
1055 " segment (%d)\n", cur->name, hr->r.segment);
1056 errorcount++;
1057 break;
1059 hr->r.segment = cur->seginfo[localseg].dest_seg;
1060 hr->r.offset += cur->seginfo[localseg].reloc;
1062 if (!get_seglocation(&segs, hr->r.refseg, &seg, &offset))
1064 fprintf(stderr, "%s: segment fixup to undefined "
1065 "segment %04x\n", cur->name, (int)hr->r.refseg);
1066 errorcount++;
1067 break;
1069 hr->r.refseg = seg;
1070 rdfaddheader(rdfheader, hr);
1071 break;
1073 case RDFREC_COMMON: /* Common variable */
1074 /* Is this symbol already in the table? */
1075 se = symtabFind(symtab, hr->c.label);
1076 if (!se) {
1077 printf("%s is not in symtab yet\n", hr->c.label);
1078 break;
1080 /* Add segment location */
1081 add_seglocation(&segs, hr->c.segment, se->segment, se->offset);
1082 break;
1086 free(header);
1087 done_seglocations(&segs);
1092 * combined BSS reservation for the entire results
1094 newrec.type = RDFREC_BSS;
1095 newrec.b.reclen = 4;
1096 newrec.b.amount = bss_length;
1097 rdfaddheader(rdfheader, &newrec);
1100 * Write the header
1102 for (i = 0; i < nsegs; i++)
1104 if (i == 2) continue;
1105 rdfaddsegment (rdfheader, outputseg[i].length);
1108 rdfwriteheader(f, rdfheader);
1109 rdfdoneheader(rdfheader);
1112 * Step through the segments, one at a time, writing out into
1113 * the output file
1115 for (i = 0; i < nsegs; i++)
1117 int16 s;
1118 long l;
1120 if (i == 2) continue;
1122 s = translateshort(outputseg[i].type);
1123 fwrite(&s, 2, 1, f);
1124 s = translateshort(outputseg[i].number);
1125 fwrite(&s, 2, 1, f);
1126 s = translateshort(outputseg[i].reserved);
1127 fwrite(&s, 2, 1, f);
1128 l = translatelong(outputseg[i].length);
1129 fwrite(&l, 4, 1, f);
1131 fwrite(outputseg[i].data, outputseg[i].length, 1, f);
1134 fwrite("\0\0\0\0\0\0\0\0\0\0", 10, 1, f);
1137 /* =========================================================================
1138 * Main program
1141 void usage()
1143 printf("usage:\n"
1144 " ldrdf [options] object modules ... [-llibrary ...]\n"
1145 " ldrdf -r\n"
1146 "options:\n"
1147 " -v[=n] increases verbosity by 1, or sets it to n\n"
1148 " -a nn sets segment alignment value (default 16)\n"
1149 " -s strips exported symbols\n"
1150 " -x warn about unresolved symbols\n"
1151 " -o name write output in file 'name'\n"
1152 " -j path specify objects search path\n"
1153 " -L path specify libraries search path\n"
1154 " -g file embed 'file' as a first header record with type 'generic'\n");
1155 exit(0);
1158 int main(int argc, char ** argv)
1160 char * outname = "aout.rdf";
1161 int moduleloaded = 0;
1162 char *respstrings[128] = {0, };
1164 options.verbose = 0;
1165 options.align = 16;
1166 options.warnUnresolved = 0;
1167 options.strip = 0;
1169 error_file = stderr;
1171 argc --, argv ++;
1172 if (argc == 0) usage();
1173 while (argc && *argv && **argv == '-' && argv[0][1] != 'l')
1175 switch(argv[0][1]) {
1176 case 'r':
1177 printf("ldrdf (linker for RDF files) version " LDRDF_VERSION "\n");
1178 printf( _RDOFF_H "\n");
1179 exit(0);
1180 case 'v':
1181 if (argv[0][2] == '=') {
1182 options.verbose = argv[0][3] - '0';
1183 if (options.verbose < 0 || options.verbose > 9) {
1184 fprintf(stderr, "ldrdf: verbosity level must be a number"
1185 " between 0 and 9\n");
1186 exit(1);
1189 else
1190 options.verbose++;
1191 break;
1192 case 'a':
1193 options.align = atoi(argv[1]);
1194 if (options.align <= 0) {
1195 fprintf(stderr,
1196 "ldrdf: -a expects a positive number argument\n");
1197 exit(1);
1199 argv++, argc--;
1200 break;
1201 case 's':
1202 options.strip = 1;
1203 break;
1204 case 'x':
1205 options.warnUnresolved = 1;
1206 if (argv[0][2]=='e')
1207 options.warnUnresolved++;
1208 break;
1209 case 'o':
1210 outname = argv[1];
1211 argv++, argc--;
1212 break;
1213 case 'j':
1214 if (!objpath) {
1215 options.objpath = 1;
1216 objpath = argv[1];
1217 argv++, argc--;
1218 break;
1219 } else {
1220 fprintf(stderr,"ldrdf: more than one objects search path specified\n");
1221 exit(1);
1223 case 'L':
1224 if (!libpath) {
1225 options.libpath = 1;
1226 libpath = argv[1];
1227 argv++, argc--;
1228 break;
1229 } else {
1230 fprintf(stderr,"ldrdf: more than one libraries search path specified\n");
1231 exit(1);
1233 case '@': {
1234 int i=0;
1235 char buf[256];
1236 FILE *f;
1238 options.respfile = 1;
1239 if (argv[1] != NULL) f = fopen(argv[1],"r");
1240 else {
1241 fprintf(stderr,"ldrdf: no response file name specified\n");
1242 exit(1);
1245 if (f == NULL) {
1246 fprintf(stderr,"ldrdf: unable to open response file\n");
1247 exit(1);
1250 argv++, argc--;
1251 while (fgets(buf, sizeof(buf), f) != NULL) {
1252 char *p;
1253 if (buf[0]=='\n') continue;
1254 if ((p = strchr(buf,'\n')) != NULL) *p = '\0';
1255 if (i >= 128) {
1256 fprintf(stderr,"ldrdf: too many input files\n");
1257 exit(1);
1259 *(respstrings+i) = newstr(buf);
1260 argc++, i++;
1262 break;
1264 case '2':
1265 options.stderr_redir = 1;
1266 error_file = stdout;
1267 break;
1268 case 'g':
1269 generic_rec_file = argv[1];
1270 argv++, argc--;
1271 break;
1272 default:
1273 usage();
1275 argv++, argc--;
1278 if (options.verbose > 4) {
1279 printf("ldrdf invoked with options:\n");
1280 printf(" section alignment: %d bytes\n", options.align);
1281 printf(" output name: `%s'\n", outname);
1282 if (options.strip)
1283 printf(" strip symbols\n");
1284 if (options.warnUnresolved == 1)
1285 printf(" warn about unresolved symbols\n");
1286 if (options.warnUnresolved == 2)
1287 printf(" error if unresolved symbols\n");
1288 if (options.objpath)
1289 printf(" objects search path: %s\n",objpath);
1290 if (options.libpath)
1291 printf(" libraries search path: %s\n",libpath);
1292 printf("\n");
1295 symtab = symtabNew();
1296 initsegments();
1298 if (!symtab) {
1299 fprintf(stderr, "ldrdf: out of memory\n");
1300 exit(1);
1303 while (argc) {
1304 if (!*argv) argv = respstrings;
1305 if (!*argv) break;
1306 if (!strncmp(*argv, "-l", 2)) /* library */
1308 if(libpath) add_library(newstrcat(libpath,*argv + 2));
1309 else add_library(*argv + 2);
1311 else {
1312 if(objpath) loadmodule(newstrcat(objpath,*argv));
1313 else loadmodule(*argv);
1314 moduleloaded = 1;
1316 argv++, argc--;
1319 if (! moduleloaded) {
1320 printf("ldrdf: nothing to do. ldrdf -h for usage\n");
1321 return 0;
1324 search_libraries();
1326 if (options.verbose > 2)
1328 printf ("symbol table:\n");
1329 symtabDump(symtab, stdout);
1332 write_output(outname);
1334 if (errorcount > 0) exit(1);
1335 return 0;