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.
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.
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 */
51 rdffile f
; /* the RDOFF file structure */
52 struct segment_infonode seginfo
[RDF_MAXSEGS
]; /* what are we doing
56 struct modulenode
* next
;
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 */
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
;
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
];
113 /* global options which affect how the program behaves */
114 struct ldrdfoptions
{
125 int errorcount
= 0; /* determines main program exit status */
128 /* =========================================================================
136 * sets up segments 0, 1, and 2, the initial code data and bss segments
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;
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
)
168 printf("loading `%s'\n", filename
);
170 /* allocate a new module entry on the end of the modules list */
173 modules
= malloc (sizeof(*modules
));
174 lastmodule
= modules
;
178 lastmodule
->next
= malloc (sizeof(*modules
));
179 lastmodule
= lastmodule
->next
;
184 fprintf(stderr
, "ldrdf: out of memory\n");
188 /* open the file using 'rdfopen', which returns nonzero on error */
190 if (rdfopen(&lastmodule
->f
, filename
) != 0)
192 rdfperror("ldrdf", filename
);
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
);
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
;
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
) {
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");
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
);
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
303 header
= malloc(mod
->f
.header_len
);
305 fprintf(stderr
, "ldrdf: not enough memory\n");
308 if (rdfloadseg(&mod
->f
, RDOFF_HEADER
, header
)) {
309 rdfperror("ldrdf", filename
);
313 while ((hr
= rdfgetheaderrec (&mod
->f
))) {
315 case RDFREC_IMPORT
: /* imported symbol */
316 case RDFREC_FARIMPORT
:
317 /* Define with seg = -1 */
318 symtab_add(hr
->i
.label
, -1, 0);
321 case RDFREC_GLOBAL
: { /* exported symbol */
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
);
332 if ((destseg
= mod
->seginfo
[(int)hr
->e
.segment
].dest_seg
) == -1)
334 destreloc
= mod
->seginfo
[(int)hr
->e
.segment
].reloc
;
336 symtab_add(hr
->e
.label
, destseg
, destreloc
+ hr
->e
.offset
);
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
;
348 case RDFREC_COMMON
: { /* Common variable */
349 symtabEnt
*ste
= symtabFind(symtab
, hr
->c
.label
);
351 /* Is the symbol already in the table? */
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
;
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
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
;
390 * we free the header buffer here, to save memory later.
391 * this isn't efficient, but probably halves the memory usage
394 mod
->f
.header_loc
= NULL
;
403 * Look in the list for module by its name.
405 int lookformodule(const char *name
)
407 struct modulenode
*curr
=modules
;
410 if (!strcmp(name
,curr
->name
)) return 1;
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
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
;
439 int findsegment(int16 type
,int16 reserved
)
443 for (i
= 0; i
< nsegs
; i
++)
444 if (outputseg
[i
].type
== type
) return i
;
446 return allocnewseg(type
,reserved
);
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
)
471 ste
= symtabFind(symtab
, symbol
);
474 if (ste
->segment
>= 0) {
476 * symbol previously defined
478 if (segment
< 0) return;
479 fprintf (error_file
, "warning: `%s' redefined\n", symbol
);
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
;
497 * this is the first declaration of this symbol
499 ste
= malloc(sizeof(symtabEnt
));
501 fprintf(stderr
, "ldrdf: out of memory\n");
504 ste
->name
= strdup(symbol
);
505 ste
->segment
= segment
;
506 ste
->offset
= offset
;
508 symtabInsert(symtab
, ste
);
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
);
529 *segment
= ste
->segment
;
530 *offset
= ste
->offset
;
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
);
551 lastlib
= libraries
= malloc(sizeof(*libraries
));
553 fprintf(stderr
, "ldrdf: out of memory\n");
559 lastlib
->next
= malloc(sizeof(*libraries
));
560 if (!lastlib
->next
) {
561 fprintf(stderr
, "ldrdf: out of memory\n");
564 lastlib
= lastlib
->next
;
566 lastlib
->next
= NULL
;
567 if (rdl_open(lastlib
, name
)) {
568 rdl_perror("ldrdf", name
);
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
;
593 int doneanything
= 0, pass
= 1, keepfile
;
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
);
612 fprintf(stderr
, "ldrdf: not enough memory\n");
615 if (rdfloadseg(&f
, RDOFF_HEADER
, header
)) {
616 rdfperror("ldrdf", f
.name
);
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)
650 * as there are undefined symbols, we can assume that
651 * there are modules on the module list by the time
654 lastmodule
->next
= malloc(sizeof(*lastmodule
->next
));
655 if (!lastmodule
->next
) {
656 fprintf(stderr
, "ldrdf: not enough memory\n");
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
);
672 if (rdl_error
!= 0 && rdl_error
!= RDL_ENOTFOUND
)
673 rdl_perror("ldrdf", cur
->name
);
676 if (cur
== NULL
&& pass
== 1) {
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
692 void write_output(const char * filename
)
695 rdf_headerbuf
* rdfheader
;
696 struct modulenode
* cur
;
697 int i
, availableseg
, seg
, localseg
, isrelative
;
699 rdfheaderrec
* hr
, newrec
;
705 if ((f
= fopen(filename
, "wb"))==NULL
) {
706 fprintf(stderr
, "ldrdf: couldn't open %s for output\n", filename
);
709 if ((rdfheader
=rdfnewheader())==NULL
) {
710 fprintf(stderr
, "ldrdf: out of memory\n");
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
720 if (generic_rec_file
) {
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
);
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
));
740 rdfaddheader(rdfheader
,hr
);
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");
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
);
794 * Perform fixups, and add new header records where required
797 header
= malloc(cur
->f
.header_len
);
799 fprintf(stderr
, "ldrdf: out of memory\n");
803 if (cur
->f
.header_loc
)
804 rdfheaderrewind(&cur
->f
);
806 if (rdfloadseg(&cur
->f
, RDOFF_HEADER
, header
))
808 rdfperror("ldrdf", cur
->name
);
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
)))
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
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
);
852 isrelative
= (hr
->r
.segment
& 64) == 64;
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",
860 hr
->r
.segment
== 2 ? "BSS" : "unknown",
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
);
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.
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
)
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
;
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
;
912 * (long *)data
+= offset
;
913 /* we can't easily detect overflow on this one */
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
;
931 rdfaddheader(rdfheader
, hr
);
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
942 se
= symtabFind(symtab
, hr
->i
.label
);
943 if (!se
|| se
->segment
== -1) {
944 if (options
.warnUnresolved
) {
945 switch (options
.warnUnresolved
) {
947 fprintf(error_file
, "warning");
950 fprintf(error_file
, "error");
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
962 se
=malloc(sizeof(*se
));
964 fprintf(stderr
, "ldrdf: out of memory\n");
967 se
->name
= strdup(hr
->i
.label
);
969 se
->segment
= availableseg
++;
971 symtabInsert(symtab
, se
);
974 se
->segment
= availableseg
++;
978 * output a header record that imports it to the
979 * recently allocated segment number...
982 newrec
.i
.segment
= se
->segment
;
983 rdfaddheader(rdfheader
, &newrec
);
986 add_seglocation(&segs
, hr
->i
.segment
, se
->segment
, se
->offset
);
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
))
999 if (hr
->e
.segment
== 2) {
1001 offset
= cur
->bss_reloc
;
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
,
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
);
1021 case RDFREC_MODNAME
: /* module name */
1023 * Insert module name record if export symbols
1025 * If module name begins with '$' - insert it anyway.
1027 if (options
.strip
&& hr
->m
.modname
[0] != '$') break;
1028 rdfaddheader(rdfheader
, hr
);
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
);
1039 case RDFREC_SEGRELOC
: /* segment fixup */
1041 * modify the segment numbers if necessary, and
1042 * pass straight through to the output module header
1046 if (hr
->r
.segment
== 2) {
1047 fprintf(stderr
, "%s: segment fixup in BSS section\n",
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
);
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
);
1070 rdfaddheader(rdfheader
, hr
);
1073 case RDFREC_COMMON
: /* Common variable */
1074 /* Is this symbol already in the table? */
1075 se
= symtabFind(symtab
, hr
->c
.label
);
1077 printf("%s is not in symtab yet\n", hr
->c
.label
);
1080 /* Add segment location */
1081 add_seglocation(&segs
, hr
->c
.segment
, se
->segment
, se
->offset
);
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
);
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
1115 for (i
= 0; i
< nsegs
; i
++)
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 /* =========================================================================
1144 " ldrdf [options] object modules ... [-llibrary ...]\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");
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;
1166 options
.warnUnresolved
= 0;
1169 error_file
= stderr
;
1172 if (argc
== 0) usage();
1173 while (argc
&& *argv
&& **argv
== '-' && argv
[0][1] != 'l')
1175 switch(argv
[0][1]) {
1177 printf("ldrdf (linker for RDF files) version " LDRDF_VERSION
"\n");
1178 printf( _RDOFF_H
"\n");
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");
1193 options
.align
= atoi(argv
[1]);
1194 if (options
.align
<= 0) {
1196 "ldrdf: -a expects a positive number argument\n");
1205 options
.warnUnresolved
= 1;
1206 if (argv
[0][2]=='e')
1207 options
.warnUnresolved
++;
1215 options
.objpath
= 1;
1220 fprintf(stderr
,"ldrdf: more than one objects search path specified\n");
1225 options
.libpath
= 1;
1230 fprintf(stderr
,"ldrdf: more than one libraries search path specified\n");
1238 options
.respfile
= 1;
1239 if (argv
[1] != NULL
) f
= fopen(argv
[1],"r");
1241 fprintf(stderr
,"ldrdf: no response file name specified\n");
1246 fprintf(stderr
,"ldrdf: unable to open response file\n");
1251 while (fgets(buf
, sizeof(buf
), f
) != NULL
) {
1253 if (buf
[0]=='\n') continue;
1254 if ((p
= strchr(buf
,'\n')) != NULL
) *p
= '\0';
1256 fprintf(stderr
,"ldrdf: too many input files\n");
1259 *(respstrings
+i
) = newstr(buf
);
1265 options
.stderr_redir
= 1;
1266 error_file
= stdout
;
1269 generic_rec_file
= argv
[1];
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
);
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
);
1295 symtab
= symtabNew();
1299 fprintf(stderr
, "ldrdf: out of memory\n");
1304 if (!*argv
) argv
= respstrings
;
1306 if (!strncmp(*argv
, "-l", 2)) /* library */
1308 if(libpath
) add_library(newstrcat(libpath
,*argv
+ 2));
1309 else add_library(*argv
+ 2);
1312 if(objpath
) loadmodule(newstrcat(objpath
,*argv
));
1313 else loadmodule(*argv
);
1319 if (! moduleloaded
) {
1320 printf("ldrdf: nothing to do. ldrdf -h for usage\n");
1326 if (options
.verbose
> 2)
1328 printf ("symbol table:\n");
1329 symtabDump(symtab
, stdout
);
1332 write_output(outname
);
1334 if (errorcount
> 0) exit(1);