NASM 0.98bf
[nasm/avx512.git] / rdoff / ldrdf.c
blob72f87255091bd52d60529af390bcd2baf4f74267
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: actually get this new version working!
11 * - finish off write_output() - appears to be done
12 * - implement library searching - appears to be done
13 * - maybe we only want to do one pass, for performance reasons?
14 * this makes things a little harder, but unix 'ld' copes...
15 * - implement command line options - appears to be done
16 * - improve symbol table implementation - done, thanks to Graeme Defty
17 * - keep a cache of symbol names in each library module so
18 * we don't have to constantly recheck the file
19 * - general performance improvements
21 * BUGS & LIMITATIONS: this program doesn't support multiple code, data
22 * or bss segments, therefore for 16 bit programs whose code, data or BSS
23 * segment exceeds 64K in size, it will not work. This program probably
24 * wont work if compiled by a 16 bit compiler. Try DJGPP if you're running
25 * under DOS. '#define STINGY_MEMORY' may help a little.
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
32 #include "rdoff.h"
33 #include "symtab.h"
34 #include "collectn.h"
35 #include "rdlib.h"
36 #include "segtab.h"
38 #define LDRDF_VERSION "1.00 alpha 1"
40 #define RDF_MAXSEGS 64
41 /* #define STINGY_MEMORY */
43 /* =======================================================================
44 * Types & macros that are private to this program
47 struct segment_infonode {
48 int dest_seg; /* output segment to be placed into, -1 to
49 skip linking this segment */
50 long reloc; /* segment's relocation factor */
54 struct modulenode {
55 rdffile f; /* the RDOFF file structure */
56 struct segment_infonode seginfo[RDF_MAXSEGS]; /* what are we doing
57 with each segment? */
58 void * header;
59 char * name;
60 struct modulenode * next;
61 long bss_reloc;
64 #include "ldsegs.h"
66 #define newstr(str) strcpy(malloc(strlen(str) + 1),str)
67 #define newstrcat(s1,s2) strcat(strcpy(malloc(strlen(s1)+strlen(s2)+1),s1),s2)
69 /* ==========================================================================
70 * Function prototypes of private utility functions
73 void processmodule(const char * filename, struct modulenode * mod);
74 int allocnewseg(int16 type,int16 reserved);
75 int findsegment(int16 type,int16 reserved);
76 void symtab_add(const char * symbol, int segment, long offset);
77 int symtab_get(const char * symbol, int * segment, long * offset);
79 /* =========================================================================
80 * Global data structures.
83 /* a linked list of modules that will be included in the output */
84 struct modulenode * modules = NULL;
85 struct modulenode * lastmodule = NULL;
87 /* a linked list of libraries to be searched for unresolved imported symbols */
88 struct librarynode * libraries = NULL;
89 struct librarynode * lastlib = NULL;
91 /* the symbol table */
92 void * symtab = NULL;
94 /* the header of the output file, built up stage by stage */
95 rdf_headerbuf * newheader = NULL;
97 /* The current state of segment allocation, including information about
98 * which output segment numbers have been allocated, and their types and
99 * amount of data which has already been allocated inside them.
101 struct SegmentHeaderRec outputseg[RDF_MAXSEGS];
102 int nsegs = 0;
103 long bss_length;
105 /* global options which affect how the program behaves */
106 struct ldrdfoptions {
107 int verbose;
108 int align;
109 int warnUnresolved;
110 int strip;
111 } options;
113 int errorcount = 0; /* determines main program exit status */
115 /* =========================================================================
116 * Utility functions
121 * initsegments()
123 * sets up segments 0, 1, and 2, the initial code data and bss segments
126 void initsegments()
128 nsegs = 3;
129 outputseg[0].type = 1;
130 outputseg[0].number = 0;
131 outputseg[0].reserved = 0;
132 outputseg[0].length = 0;
133 outputseg[1].type = 2;
134 outputseg[1].number = 1;
135 outputseg[1].reserved = 0;
136 outputseg[1].length = 0;
137 outputseg[2].type = 0xFFFF; /* reserved segment type */
138 outputseg[2].number = 2;
139 outputseg[2].reserved = 0;
140 outputseg[2].length = 0;
141 bss_length = 0;
145 * loadmodule
147 * Determine the characteristics of a module, and decide what to do with
148 * each segment it contains (including determining destination segments and
149 * relocation factors for segments that are kept).
152 void loadmodule(const char * filename)
154 if (options.verbose)
155 printf("loading `%s'\n", filename);
157 /* allocate a new module entry on the end of the modules list */
158 if (!modules)
160 modules = malloc (sizeof(*modules));
161 lastmodule = modules;
163 else
165 lastmodule->next = malloc (sizeof(*modules));
166 lastmodule = lastmodule->next;
169 if ( ! lastmodule)
171 fprintf(stderr, "ldrdf: out of memory\n");
172 exit(1);
175 /* open the file using 'rdfopen', which returns nonzero on error */
177 if (rdfopen(&lastmodule->f, filename) != 0)
179 rdfperror("ldrdf", filename);
180 exit(1);
184 * store information about the module, and determine what segments
185 * it contains, and what we should do with them (determine relocation
186 * factor if we decide to keep them)
189 lastmodule->header = NULL;
190 lastmodule->name = strdup(filename);
191 lastmodule->next = NULL;
193 processmodule(filename, lastmodule);
197 * processmodule()
199 * step through each segment, determine what exactly we're doing with
200 * it, and if we intend to keep it, determine (a) which segment to
201 * put it in and (b) whereabouts in that segment it will end up.
202 * (b) is fairly easy, cos we're now keeping track of how big each segment
203 * in our output file is...
206 void processmodule(const char * filename, struct modulenode * mod)
208 struct segconfig sconf;
209 int seg, outseg;
210 void * header;
211 rdfheaderrec * hr;
212 long bssamount = 0;
214 for (seg = 0; seg < mod->f.nsegs; seg++)
217 * get the segment configuration for this type from the segment
218 * table. getsegconfig() is a macro, defined in ldsegs.h.
220 getsegconfig(sconf, mod->f.seg[seg].type);
222 if (options.verbose > 1) {
223 printf ("%s %04x [%04x:%10s] ", filename, mod->f.seg[seg].number,
224 mod->f.seg[seg].type, sconf.typedesc);
227 * sconf->dowhat tells us what to do with a segment of this type.
229 switch (sconf.dowhat) {
230 case SEG_IGNORE:
232 * Set destination segment to -1, to indicate that this segment
233 * should be ignored for the purpose of output, ie it is left
234 * out of the linked executable.
236 mod->seginfo[seg].dest_seg = -1;
237 if (options.verbose > 1) printf("IGNORED\n");
238 break;
240 case SEG_NEWSEG:
242 * The configuration tells us to create a new segment for
243 * each occurrence of this segment type.
245 outseg = allocnewseg(sconf.mergetype,
246 mod->f.seg[seg].reserved);
247 mod->seginfo[seg].dest_seg = outseg;
248 mod->seginfo[seg].reloc = 0;
249 outputseg[outseg].length = mod->f.seg[seg].length;
250 if (options.verbose > 1)
251 printf ("=> %04x:%08lx (+%04lx)\n", outseg,
252 mod->seginfo[seg].reloc,
253 mod->f.seg[seg].length);
254 break;
256 case SEG_MERGE:
258 * The configuration tells us to merge the segment with
259 * a previously existing segment of type 'sconf.mergetype',
260 * if one exists. Otherwise a new segment is created.
261 * This is handled transparently by 'findsegment()'.
263 outseg = findsegment(sconf.mergetype,
264 mod->f.seg[seg].reserved);
265 mod->seginfo[seg].dest_seg = outseg;
268 * We need to add alignment to these segments.
270 if (outputseg[outseg].length % options.align != 0)
271 outputseg[outseg].length +=
272 options.align - (outputseg[outseg].length % options.align);
274 mod->seginfo[seg].reloc = outputseg[outseg].length;
275 outputseg[outseg].length += mod->f.seg[seg].length;
277 if (options.verbose > 1)
278 printf ("=> %04x:%08lx (+%04lx)\n", outseg,
279 mod->seginfo[seg].reloc,
280 mod->f.seg[seg].length);
286 * extract symbols from the header, and dump them into the
287 * symbol table
289 header = malloc(mod->f.header_len);
290 if (!header) {
291 fprintf(stderr, "ldrdf: not enough memory\n");
292 exit(1);
294 if (rdfloadseg(&mod->f, RDOFF_HEADER, header)) {
295 rdfperror("ldrdf", filename);
296 exit(1);
299 while ((hr = rdfgetheaderrec (&mod->f)))
301 switch(hr->type) {
302 case 2: /* imported symbol - define with seg = -1 */
303 case 7:
304 symtab_add(hr->i.label, -1, 0);
305 break;
307 case 3: /* exported symbol */
308 if (mod->seginfo[(int)hr->e.segment].dest_seg == -1)
309 continue;
310 symtab_add(hr->e.label, mod->seginfo[(int)hr->e.segment].dest_seg,
311 mod->seginfo[(int)hr->e.segment].reloc + hr->e.offset);
312 break;
314 case 5: /* BSS reservation */
316 * first, amalgamate all BSS reservations in this module
317 * into one, because we allow this in the output format.
319 bssamount += hr->b.amount;
320 break;
324 if (bssamount != 0)
327 * handle the BSS segment - first pad the existing bss length
328 * to the correct alignment, then store the length in bss_reloc
329 * for this module. Then add this module's BSS length onto
330 * bss_length.
332 if (bss_length % options.align != 0)
333 bss_length += options.align - (bss_length % options.align);
335 mod->bss_reloc = bss_length;
336 if (options.verbose > 1) {
337 printf ("%s 0002 [ BSS] => 0002:%08lx (+%04lx)\n",
338 filename, bss_length, bssamount);
340 bss_length += bssamount;
343 #ifdef STINGY_MEMORY
345 * we free the header buffer here, to save memory later.
346 * this isn't efficient, but probably halves the memory usage
347 * of this program...
349 mod->f.header_loc = NULL;
350 free(header);
352 #endif
357 * allocnewseg()
358 * findsegment()
360 * These functions manipulate the array of output segments, and are used
361 * by processmodule(). allocnewseg() allocates a segment in the array,
362 * initialising it to be empty. findsegment() first scans the array for
363 * a segment of the type requested, and if one isn't found allocates a
364 * new one.
366 int allocnewseg(int16 type,int16 reserved)
368 outputseg[nsegs].type = type;
369 outputseg[nsegs].number = nsegs;
370 outputseg[nsegs].reserved = reserved;
371 outputseg[nsegs].length = 0;
372 outputseg[nsegs].offset = 0;
373 outputseg[nsegs].data = NULL;
375 return nsegs++;
378 int findsegment(int16 type,int16 reserved)
380 int i;
382 for (i = 0; i < nsegs; i++)
383 if (outputseg[i].type == type) return i;
385 return allocnewseg(type,reserved);
389 * symtab_add()
391 * inserts a symbol into the global symbol table, which associates symbol
392 * names either with addresses, or a marker that the symbol hasn't been
393 * resolved yet, or possibly that the symbol has been defined as
394 * contained in a dynamic [load time/run time] linked library.
396 * segment = -1 => not yet defined
397 * segment = -2 => defined as dll symbol
399 * If the symbol is already defined, and the new segment >= 0, then
400 * if the original segment was < 0 the symbol is redefined, otherwise
401 * a duplicate symbol warning is issued. If new segment == -1, this
402 * routine won't change a previously existing symbol. It will change
403 * to segment = -2 only if the segment was previously < 0.
406 void symtab_add(const char * symbol, int segment, long offset)
408 symtabEnt * ste;
410 ste = symtabFind(symtab, symbol);
411 if (ste)
413 if (ste->segment >= 0) {
415 * symbol previously defined
417 if (segment < 0) return;
418 fprintf (stderr, "warning: `%s' redefined\n", symbol);
419 return;
423 * somebody wanted the symbol, and put an undefined symbol
424 * marker into the table
426 if (segment == -1) return;
428 * we have more information now - update the symbol's entry
430 ste->segment = segment;
431 ste->offset = offset;
432 ste->flags = 0;
433 return;
436 * this is the first declaration of this symbol
438 ste = malloc(sizeof(symtabEnt));
439 if (!ste) {
440 fprintf(stderr, "ldrdf: out of memory\n");
441 exit(1);
443 ste->name = strdup(symbol);
444 ste->segment = segment;
445 ste->offset = offset;
446 ste->flags = 0;
447 symtabInsert(symtab, ste);
451 * symtab_get()
453 * Retrieves the values associated with a symbol. Undefined symbols
454 * are assumed to have -1:0 associated. Returns 1 if the symbol was
455 * successfully located.
458 int symtab_get(const char * symbol, int * segment, long * offset)
460 symtabEnt * ste = symtabFind(symtab, symbol);
461 if (!ste) {
462 *segment = -1;
463 *offset = 0;
464 return 0;
466 else
468 *segment = ste->segment;
469 *offset = ste->offset;
470 return 1;
475 * add_library()
477 * checks that a library can be opened and is in the correct format,
478 * then adds it to the linked list of libraries.
481 void add_library(const char * name)
483 if (rdl_verify(name)) {
484 rdl_perror("ldrdf", name);
485 errorcount++;
486 return;
488 if (! libraries)
490 lastlib = libraries = malloc(sizeof(*libraries));
491 if (! libraries) {
492 fprintf(stderr, "ldrdf: out of memory\n");
493 exit(1);
496 else
498 lastlib->next = malloc(sizeof(*libraries));
499 if (!lastlib->next) {
500 fprintf(stderr, "ldrdf: out of memory\n");
501 exit(1);
503 lastlib = lastlib->next;
505 if (rdl_open(lastlib, name)) {
506 rdl_perror("ldrdf", name);
507 errorcount++;
508 return;
513 * search_libraries()
515 * scans through the list of libraries, attempting to match symbols
516 * defined in library modules against symbols that are referenced but
517 * not defined (segment = -1 in the symbol table)
519 * returns 1 if any extra library modules are included, indicating that
520 * another pass through the library list should be made (possibly).
523 int search_libraries()
525 struct librarynode * cur;
526 rdffile f;
527 int i;
528 void * header;
529 int segment;
530 long offset;
531 int doneanything = 0, keepfile;
532 rdfheaderrec * hr;
534 cur = libraries;
536 while (cur)
538 if (options.verbose > 2)
539 printf("scanning library `%s'...\n", cur->name);
541 for (i = 0; rdl_openmodule(cur, i, &f) == 0; i++)
543 if (options.verbose > 3)
544 printf(" looking in module `%s'\n", f.name);
546 header = malloc(f.header_len);
547 if (!header) {
548 fprintf(stderr, "ldrdf: not enough memory\n");
549 exit(1);
551 if (rdfloadseg(&f, RDOFF_HEADER, header)) {
552 rdfperror("ldrdf", f.name);
553 errorcount++;
554 return 0;
557 keepfile = 0;
559 while ((hr = rdfgetheaderrec (&f)))
561 /* we're only interested in exports, so skip others: */
562 if (hr->type != 3) continue;
565 * Find the symbol in the symbol table. If the symbol isn't
566 * defined, we aren't interested, so go on to the next.
567 * If it is defined as anything but -1, we're also not
568 * interested. But if it is defined as -1, insert this
569 * module into the list of modules to use, and go
570 * immediately on to the next module...
572 if (! symtab_get(hr->e.label, &segment, &offset)
573 || segment != -1)
575 continue;
578 doneanything = 1;
579 keepfile = 1;
582 * as there are undefined symbols, we can assume that
583 * there are modules on the module list by the time
584 * we get here.
586 lastmodule->next = malloc(sizeof(*lastmodule->next));
587 if (!lastmodule->next) {
588 fprintf(stderr, "ldrdf: not enough memory\n");
589 exit(1);
591 lastmodule = lastmodule->next;
592 memcpy(&lastmodule->f, &f, sizeof(f));
593 lastmodule->name = strdup(f.name);
594 processmodule(f.name, lastmodule);
595 break;
597 if (!keepfile)
598 rdfclose(&f);
600 if (rdl_error != 0 && rdl_error != RDL_ENOTFOUND)
601 rdl_perror("ldrdf", cur->name);
602 cur = cur->next;
605 return doneanything;
609 * write_output()
611 * this takes the linked list of modules, and walks through it, merging
612 * all the modules into a single output module, and then writes this to a
613 * file.
615 void write_output(const char * filename)
617 FILE * f = fopen(filename, "wb");
618 rdf_headerbuf * rdfheader = rdfnewheader();
619 struct modulenode * cur;
620 int i, availableseg, seg, localseg, isrelative;
621 void * header;
622 rdfheaderrec * hr, newrec;
623 symtabEnt * se;
624 segtab segs;
625 long offset;
626 byte * data;
628 if (!f) {
629 fprintf(stderr, "ldrdf: couldn't open %s for output\n", filename);
630 exit(1);
632 if (!rdfheader) {
633 fprintf(stderr, "ldrdf: out of memory\n");
634 exit(1);
637 if (options.verbose)
638 printf ("\nbuilding output module (%d segments)\n", nsegs);
641 * Allocate the memory for the segments. We may be better off
642 * building the output module one segment at a time when running
643 * under 16 bit DOS, but that would be a slower way of doing this.
644 * And you could always use DJGPP...
646 for (i = 0; i < nsegs; i++)
648 outputseg[i].data = malloc(outputseg[i].length);
649 if (!outputseg[i].data) {
650 fprintf(stderr, "ldrdf: out of memory\n");
651 exit(1);
656 * initialise availableseg, used to allocate segment numbers for
657 * imported and exported labels...
659 availableseg = nsegs;
662 * Step through the modules, performing required actions on each one
664 for (cur = modules; cur; cur=cur->next)
667 * Read the actual segment contents into the correct places in
668 * the newly allocated segments
671 for (i = 0; i < cur->f.nsegs; i++)
673 int dest = cur->seginfo[i].dest_seg;
675 if (dest == -1) continue;
676 if (rdfloadseg(&cur->f, i,
677 outputseg[dest].data + cur->seginfo[i].reloc))
679 rdfperror("ldrdf", cur->name);
680 exit(1);
685 * Perform fixups, and add new header records where required
688 header = malloc(cur->f.header_len);
689 if (!header) {
690 fprintf(stderr, "ldrdf: out of memory\n");
691 exit(1);
694 if (cur->f.header_loc)
695 rdfheaderrewind(&cur->f);
696 else
697 if (rdfloadseg(&cur->f, RDOFF_HEADER, header))
699 rdfperror("ldrdf", cur->name);
700 exit(1);
704 * we need to create a local segment number -> location
705 * table for the segments in this module.
707 init_seglocations(&segs);
708 for (i = 0; i < cur->f.nsegs; i++)
710 add_seglocation(&segs, cur->f.seg[i].number,
711 cur->seginfo[i].dest_seg, cur->seginfo[i].reloc);
714 * and the BSS segment (doh!)
716 add_seglocation (&segs, 2, 2, cur->bss_reloc);
718 while ((hr = rdfgetheaderrec(&cur->f)))
720 switch(hr->type) {
721 case 1: /* relocation record - need to do a fixup */
723 * First correct the offset stored in the segment from
724 * the start of the segment (which may well have changed).
726 * To do this we add to the number stored the relocation
727 * factor associated with the segment that contains the
728 * target segment.
730 * The relocation could be a relative relocation, in which
731 * case we have to first subtract the amount we've relocated
732 * the containing segment by.
735 if (!get_seglocation(&segs, hr->r.refseg, &seg, &offset))
737 fprintf(stderr, "%s: reloc to undefined segment %04x\n",
738 cur->name, (int) hr->r.refseg);
739 errorcount++;
740 break;
743 isrelative = (hr->r.segment & 64) == 64;
744 hr->r.segment &= 63;
746 if (hr->r.segment == 2 ||
747 (localseg = rdffindsegment(&cur->f, hr->r.segment)) == -1)
749 fprintf(stderr, "%s: reloc from %s segment (%d)\n",
750 cur->name,
751 hr->r.segment == 2 ? "BSS" : "unknown",
752 hr->r.segment);
753 errorcount++;
754 break;
757 if (hr->r.length != 1 && hr->r.length != 2 && hr->r.length!=4)
759 fprintf(stderr, "%s: nonstandard length reloc "
760 "(%d bytes)\n", cur->name, hr->r.length);
761 errorcount++;
762 break;
766 * okay, now the relocation is in the segment pointed to by
767 * cur->seginfo[localseg], and we know everything else is
768 * okay to go ahead and do the relocation
770 data = outputseg[cur->seginfo[localseg].dest_seg].data;
771 data += cur->seginfo[localseg].reloc + hr->r.offset;
774 * data now points to the reference that needs
775 * relocation. Calculate the relocation factor.
776 * Factor is:
777 * offset of referred object in segment [in offset]
778 * (- relocation of localseg, if ref is relative)
779 * For simplicity, the result is stored in 'offset'.
780 * Then add 'offset' onto the value at data.
783 if (isrelative) offset -= cur->seginfo[localseg].reloc;
784 switch (hr->r.length)
786 case 1:
787 offset += *data;
788 if (offset < -127 || offset > 128)
789 fprintf(stderr, "warning: relocation out of range "
790 "at %s(%02x:%08lx)\n", cur->name,
791 (int)hr->r.segment, hr->r.offset);
792 *data = (char) offset;
793 break;
794 case 2:
795 offset += * (short *)data;
796 if (offset < -32767 || offset > 32768)
797 fprintf(stderr, "warning: relocation out of range "
798 "at %s(%02x:%08lx)\n", cur->name,
799 (int)hr->r.segment, hr->r.offset);
800 * (short *)data = (short) offset;
801 break;
802 case 4:
803 * (long *)data += offset;
804 /* we can't easily detect overflow on this one */
805 break;
809 * If the relocation was relative between two symbols in
810 * the same segment, then we're done.
812 * Otherwise, we need to output a new relocation record
813 * with the references updated segment and offset...
815 if (! isrelative
816 || cur->seginfo[localseg].dest_seg != seg)
818 hr->r.segment = cur->seginfo[localseg].dest_seg;
819 hr->r.offset += cur->seginfo[localseg].reloc;
820 hr->r.refseg = seg;
821 rdfaddheader(rdfheader, hr);
823 break;
825 case 2: /* import symbol */
826 case 7:
828 * scan the global symbol table for the symbol
829 * and associate its location with the segment number
830 * for this module
832 se = symtabFind(symtab, hr->i.label);
833 if (!se || se->segment == -1) {
834 if (options.warnUnresolved) {
835 fprintf(stderr, "warning: unresolved reference to `%s'"
836 " in module `%s'\n", hr->i.label, cur->name);
839 * we need to allocate a segment number for this
840 * symbol, and store it in the symbol table for
841 * future reference
843 if (!se) {
844 se=malloc(sizeof(*se));
845 if (!se) {
846 fprintf(stderr, "ldrdf: out of memory\n");
847 exit(1);
849 se->name = strdup(hr->i.label);
850 se->flags = 0;
851 se->segment = availableseg++;
852 se->offset = 0;
853 symtabInsert(symtab, se);
855 else {
856 se->segment = availableseg++;
857 se->offset = 0;
860 * output a header record that imports it to the
861 * recently allocated segment number...
863 newrec = *hr;
864 newrec.i.segment = se->segment;
865 rdfaddheader(rdfheader, &newrec);
868 add_seglocation(&segs, hr->i.segment, se->segment, se->offset);
870 break;
872 case 3: /* export symbol */
874 * need to insert an export for this symbol into the new
875 * header, unless we're stripping symbols [unless this
876 * symbol is in an explicit keep list]. *** FIXME ***
878 if (options.strip)
879 break;
881 if (hr->e.segment == 2) {
882 seg = 2;
883 offset = cur->bss_reloc;
885 else {
886 localseg = rdffindsegment(&cur->f, hr->e.segment);
887 if (localseg == -1) {
888 fprintf(stderr, "%s: exported symbol `%s' from "
889 "unrecognised segment\n", cur->name,
890 hr->e.label);
891 errorcount++;
892 break;
894 offset = cur->seginfo[localseg].reloc;
895 seg = cur->seginfo[localseg].dest_seg;
898 hr->e.segment = seg;
899 hr->e.offset += offset;
900 rdfaddheader(rdfheader, hr);
901 break;
903 case 6: /* segment fixup */
905 * modify the segment numbers if necessary, and
906 * pass straight through to the output module header
908 * *** FIXME ***
910 if (hr->r.segment == 2) {
911 fprintf(stderr, "%s: segment fixup in BSS section\n",
912 cur->name);
913 errorcount++;
914 break;
916 localseg = rdffindsegment(&cur->f, hr->r.segment);
917 if (localseg == -1) {
918 fprintf(stderr, "%s: segment fixup in unrecognised"
919 " segment (%d)\n", cur->name, hr->r.segment);
920 errorcount++;
921 break;
923 hr->r.segment = cur->seginfo[localseg].dest_seg;
924 hr->r.offset += cur->seginfo[localseg].reloc;
926 if (!get_seglocation(&segs, hr->r.refseg, &seg, &offset))
928 fprintf(stderr, "%s: segment fixup to undefined "
929 "segment %04x\n", cur->name, (int)hr->r.refseg);
930 errorcount++;
931 break;
933 hr->r.refseg = seg;
934 rdfaddheader(rdfheader, hr);
935 break;
939 free(header);
940 done_seglocations(&segs);
945 * combined BSS reservation for the entire results
947 newrec.type = 5;
948 newrec.b.reclen = 4;
949 newrec.b.amount = bss_length;
950 rdfaddheader(rdfheader, &newrec);
953 * Write the header
955 for (i = 0; i < nsegs; i++)
957 if (i == 2) continue;
958 rdfaddsegment (rdfheader, outputseg[i].length);
960 rdfwriteheader(f, rdfheader);
961 rdfdoneheader(rdfheader);
963 * Step through the segments, one at a time, writing out into
964 * the output file
967 for (i = 0; i < nsegs; i++)
969 int16 s;
970 long l;
972 if (i == 2) continue;
974 s = translateshort(outputseg[i].type);
975 fwrite(&s, 2, 1, f);
976 s = translateshort(outputseg[i].number);
977 fwrite(&s, 2, 1, f);
978 s = translateshort(outputseg[i].reserved);
979 fwrite(&s, 2, 1, f);
980 l = translatelong(outputseg[i].length);
981 fwrite(&l, 4, 1, f);
983 fwrite(outputseg[i].data, outputseg[i].length, 1, f);
986 fwrite("\0\0\0\0\0\0\0\0\0\0", 10, 1, f);
989 /* =========================================================================
990 * Main program
993 void usage()
995 printf("usage:\n");
996 printf(" ldrdf [options] object modules ... [-llibrary ...]\n");
997 printf(" ldrdf -r\n");
998 printf("options:\n");
999 printf(" -v[=n] increases verbosity by 1, or sets it to n\n");
1000 printf(" -a nn sets segment alignment value (default 16)\n");
1001 printf(" -s strips exported symbols\n");
1002 printf(" -x warn about unresolved symbols\n");
1003 printf(" -o name write output in file 'name'\n");
1004 printf("\n");
1005 printf("Note: no library searching is performed. Please specify full\n");
1006 printf("paths to all files referenced.\n");
1007 exit(0);
1010 int main(int argc, char ** argv)
1012 char * outname = "aout.rdf";
1013 int moduleloaded = 0;
1015 options.verbose = 0;
1016 options.align = 16;
1017 options.warnUnresolved = 0;
1018 options.strip = 0;
1020 argc --, argv ++;
1021 if (argc == 0) usage();
1022 while (argc && **argv == '-' && argv[0][1] != 'l')
1024 switch(argv[0][1]) {
1025 case 'r':
1026 printf("ldrdf (linker for RDF files) version " LDRDF_VERSION "\n");
1027 printf( _RDOFF_H "\n");
1028 exit(0);
1029 case 'v':
1030 if (argv[0][2] == '=') {
1031 options.verbose = argv[0][3] - '0';
1032 if (options.verbose < 0 || options.verbose > 9) {
1033 fprintf(stderr, "ldrdf: verbosity level must be a number"
1034 " between 0 and 9\n");
1035 exit(1);
1038 else
1039 options.verbose++;
1040 break;
1041 case 'a':
1042 options.align = atoi(argv[1]);
1043 if (options.align <= 0) {
1044 fprintf(stderr,
1045 "ldrdf: -a expects a positive number argument\n");
1046 exit(1);
1048 argv++, argc--;
1049 break;
1050 case 's':
1051 options.strip = 1;
1052 break;
1053 case 'x':
1054 options.warnUnresolved = 1;
1055 break;
1056 case 'o':
1057 outname = argv[1];
1058 argv++, argc--;
1059 break;
1060 default:
1061 usage();
1063 argv++, argc--;
1066 if (options.verbose > 4) {
1067 printf("ldrdf invoked with options:\n");
1068 printf(" section alignment: %d bytes\n", options.align);
1069 printf(" output name: `%s'\n", outname);
1070 if (options.strip)
1071 printf(" strip symbols\n");
1072 if (options.warnUnresolved)
1073 printf(" warn about unresolved symbols\n");
1074 printf("\n");
1077 symtab = symtabNew();
1078 initsegments();
1080 if (!symtab) {
1081 fprintf(stderr, "ldrdf: out of memory\n");
1082 exit(1);
1085 while (argc)
1087 if (!strncmp(*argv, "-l", 2)) /* library */
1088 add_library(*argv + 2);
1089 else {
1090 loadmodule(*argv);
1091 moduleloaded = 1;
1093 argv++, argc--;
1096 if (! moduleloaded) {
1097 printf("ldrdf: nothing to do. ldrdf -h for usage\n");
1098 return 0;
1102 search_libraries();
1104 if (options.verbose > 2)
1106 printf ("symbol table:\n");
1107 symtabDump(symtab, stdout);
1110 write_output(outname);
1112 if (errorcount > 0)
1113 exit(1);
1115 return 0;