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.
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.
27 * TO FIX: enhance search of required export symbols in libraries (now depends
28 * on modules order in library).
42 #define LDRDF_VERSION "1.03"
44 #define RDF_MAXSEGS 64
45 /* #define STINGY_MEMORY */
47 /* =======================================================================
48 * Types & macros that are private to this program
51 struct segment_infonode
{
52 int dest_seg
; /* output segment to be placed into, -1 to
53 skip linking this segment */
54 long reloc
; /* segment's relocation factor */
59 rdffile f
; /* the RDOFF file structure */
60 struct segment_infonode seginfo
[RDF_MAXSEGS
]; /* what are we doing
64 struct modulenode
* next
;
70 #define newstr(str) strcpy(malloc(strlen(str) + 1),str)
71 #define newstrcat(s1,s2) strcat(strcpy(malloc(strlen(s1)+strlen(s2)+1),s1),s2)
73 /* ==========================================================================
74 * Function prototypes of private utility functions
77 void processmodule(const char * filename
, struct modulenode
* mod
);
78 int allocnewseg(int16 type
,int16 reserved
);
79 int findsegment(int16 type
,int16 reserved
);
80 void symtab_add(const char * symbol
, int segment
, long offset
);
81 int symtab_get(const char * symbol
, int * segment
, long * offset
);
83 /* =========================================================================
84 * Global data structures.
87 /* a linked list of modules that will be included in the output */
88 struct modulenode
* modules
= NULL
;
89 struct modulenode
* lastmodule
= NULL
;
91 /* a linked list of libraries to be searched for unresolved imported symbols */
92 struct librarynode
* libraries
= NULL
;
93 struct librarynode
* lastlib
= NULL
;
95 /* the symbol table */
98 /* objects search path */
99 char * objpath
= NULL
;
101 /* libraries search path */
102 char * libpath
= NULL
;
105 static FILE * error_file
;
109 /* loading address for multiboot header */
110 unsigned MBHloadAddr
;
113 * Tiny code that moves RDF loader to its working memory region:
114 * mov esi,SOURCE_ADDR ; BE xx xx xx xx
115 * mov edi,DEST_ADDR ; BF xx xx xx xx
116 * mov esp,edi ; 89 FC
118 * mov ecx,RDFLDR_LENGTH/4 ; B9 xx xx xx xx
124 #define RDFLDR_LENGTH 4096 /* Loader will be moved to unused */
125 #define RDFLDR_DESTLOC 0xBF000 /* video page */
127 unsigned char RDFloaderMover
[]={
128 0xBE, 0, 0, 0, 0, 0xBF, 0, 0xF0, 0xB, 0,
131 0xFC, 0xF3, 0xA5, 0xC3
136 /* the header of the output file, built up stage by stage */
137 rdf_headerbuf
* newheader
= NULL
;
139 /* The current state of segment allocation, including information about
140 * which output segment numbers have been allocated, and their types and
141 * amount of data which has already been allocated inside them.
143 struct SegmentHeaderRec outputseg
[RDF_MAXSEGS
];
147 /* global options which affect how the program behaves */
148 struct ldrdfoptions
{
161 int errorcount
= 0; /* determines main program exit status */
163 /* =========================================================================
171 * sets up segments 0, 1, and 2, the initial code data and bss segments
177 outputseg
[0].type
= 1;
178 outputseg
[0].number
= 0;
179 outputseg
[0].reserved
= 0;
180 outputseg
[0].length
= 0;
181 outputseg
[1].type
= 2;
182 outputseg
[1].number
= 1;
183 outputseg
[1].reserved
= 0;
184 outputseg
[1].length
= 0;
185 outputseg
[2].type
= 0xFFFF; /* reserved segment type */
186 outputseg
[2].number
= 2;
187 outputseg
[2].reserved
= 0;
188 outputseg
[2].length
= 0;
195 * Determine the characteristics of a module, and decide what to do with
196 * each segment it contains (including determining destination segments and
197 * relocation factors for segments that are kept).
200 void loadmodule(const char * filename
)
203 printf("loading `%s'\n", filename
);
205 /* allocate a new module entry on the end of the modules list */
208 modules
= malloc (sizeof(*modules
));
209 lastmodule
= modules
;
213 lastmodule
->next
= malloc (sizeof(*modules
));
214 lastmodule
= lastmodule
->next
;
219 fprintf(stderr
, "ldrdf: out of memory\n");
223 /* open the file using 'rdfopen', which returns nonzero on error */
225 if (rdfopen(&lastmodule
->f
, filename
) != 0)
227 rdfperror("ldrdf", filename
);
232 * store information about the module, and determine what segments
233 * it contains, and what we should do with them (determine relocation
234 * factor if we decide to keep them)
237 lastmodule
->header
= NULL
;
238 lastmodule
->name
= strdup(filename
);
239 lastmodule
->next
= NULL
;
241 processmodule(filename
, lastmodule
);
247 * step through each segment, determine what exactly we're doing with
248 * it, and if we intend to keep it, determine (a) which segment to
249 * put it in and (b) whereabouts in that segment it will end up.
250 * (b) is fairly easy, cos we're now keeping track of how big each segment
251 * in our output file is...
254 void processmodule(const char * filename
, struct modulenode
* mod
)
256 struct segconfig sconf
;
262 for (seg
= 0; seg
< mod
->f
.nsegs
; seg
++)
265 * get the segment configuration for this type from the segment
266 * table. getsegconfig() is a macro, defined in ldsegs.h.
268 getsegconfig(sconf
, mod
->f
.seg
[seg
].type
);
270 if (options
.verbose
> 1) {
271 printf ("%s %04x [%04x:%10s] ", filename
, mod
->f
.seg
[seg
].number
,
272 mod
->f
.seg
[seg
].type
, sconf
.typedesc
);
275 * sconf->dowhat tells us what to do with a segment of this type.
277 switch (sconf
.dowhat
) {
280 * Set destination segment to -1, to indicate that this segment
281 * should be ignored for the purpose of output, ie it is left
282 * out of the linked executable.
284 mod
->seginfo
[seg
].dest_seg
= -1;
285 if (options
.verbose
> 1) printf("IGNORED\n");
290 * The configuration tells us to create a new segment for
291 * each occurrence of this segment type.
293 outseg
= allocnewseg(sconf
.mergetype
,
294 mod
->f
.seg
[seg
].reserved
);
295 mod
->seginfo
[seg
].dest_seg
= outseg
;
296 mod
->seginfo
[seg
].reloc
= 0;
297 outputseg
[outseg
].length
= mod
->f
.seg
[seg
].length
;
298 if (options
.verbose
> 1)
299 printf ("=> %04x:%08lx (+%04lx)\n", outseg
,
300 mod
->seginfo
[seg
].reloc
,
301 mod
->f
.seg
[seg
].length
);
306 * The configuration tells us to merge the segment with
307 * a previously existing segment of type 'sconf.mergetype',
308 * if one exists. Otherwise a new segment is created.
309 * This is handled transparently by 'findsegment()'.
311 outseg
= findsegment(sconf
.mergetype
,
312 mod
->f
.seg
[seg
].reserved
);
313 mod
->seginfo
[seg
].dest_seg
= outseg
;
316 * We need to add alignment to these segments.
318 if (outputseg
[outseg
].length
% options
.align
!= 0)
319 outputseg
[outseg
].length
+=
320 options
.align
- (outputseg
[outseg
].length
% options
.align
);
322 mod
->seginfo
[seg
].reloc
= outputseg
[outseg
].length
;
323 outputseg
[outseg
].length
+= mod
->f
.seg
[seg
].length
;
325 if (options
.verbose
> 1)
326 printf ("=> %04x:%08lx (+%04lx)\n", outseg
,
327 mod
->seginfo
[seg
].reloc
,
328 mod
->f
.seg
[seg
].length
);
334 * extract symbols from the header, and dump them into the
337 header
= malloc(mod
->f
.header_len
);
339 fprintf(stderr
, "ldrdf: not enough memory\n");
342 if (rdfloadseg(&mod
->f
, RDOFF_HEADER
, header
)) {
343 rdfperror("ldrdf", filename
);
347 while ((hr
= rdfgetheaderrec (&mod
->f
)))
350 case 2: /* imported symbol - define with seg = -1 */
352 symtab_add(hr
->i
.label
, -1, 0);
355 case 3: /* exported symbol */
360 if (hr
->e
.segment
== 2)
362 destreloc
= bss_length
;
363 if (destreloc
% options
.align
!= 0)
364 destreloc
+= options
.align
- (destreloc
% options
.align
);
369 if ((destseg
= mod
->seginfo
[(int)hr
->e
.segment
].dest_seg
) == -1)
371 destreloc
= mod
->seginfo
[(int)hr
->e
.segment
].reloc
;
373 symtab_add(hr
->e
.label
, destseg
, destreloc
+ hr
->e
.offset
);
377 case 5: /* BSS reservation */
379 * first, amalgamate all BSS reservations in this module
380 * into one, because we allow this in the output format.
382 bssamount
+= hr
->b
.amount
;
390 * handle the BSS segment - first pad the existing bss length
391 * to the correct alignment, then store the length in bss_reloc
392 * for this module. Then add this module's BSS length onto
395 if (bss_length
% options
.align
!= 0)
396 bss_length
+= options
.align
- (bss_length
% options
.align
);
398 mod
->bss_reloc
= bss_length
;
399 if (options
.verbose
> 1) {
400 printf ("%s 0002 [ BSS] => 0002:%08lx (+%04lx)\n",
401 filename
, bss_length
, bssamount
);
403 bss_length
+= bssamount
;
408 * we free the header buffer here, to save memory later.
409 * this isn't efficient, but probably halves the memory usage
412 mod
->f
.header_loc
= NULL
;
421 * Look in list for module by its name.
423 int lookformodule(const char *name
)
425 struct modulenode
*curr
=modules
;
428 if (!strcmp(name
,curr
->name
)) return 1;
439 * These functions manipulate the array of output segments, and are used
440 * by processmodule(). allocnewseg() allocates a segment in the array,
441 * initialising it to be empty. findsegment() first scans the array for
442 * a segment of the type requested, and if one isn't found allocates a
445 int allocnewseg(int16 type
,int16 reserved
)
447 outputseg
[nsegs
].type
= type
;
448 outputseg
[nsegs
].number
= nsegs
;
449 outputseg
[nsegs
].reserved
= reserved
;
450 outputseg
[nsegs
].length
= 0;
451 outputseg
[nsegs
].offset
= 0;
452 outputseg
[nsegs
].data
= NULL
;
457 int findsegment(int16 type
,int16 reserved
)
461 for (i
= 0; i
< nsegs
; i
++)
462 if (outputseg
[i
].type
== type
) return i
;
464 return allocnewseg(type
,reserved
);
470 * inserts a symbol into the global symbol table, which associates symbol
471 * names either with addresses, or a marker that the symbol hasn't been
472 * resolved yet, or possibly that the symbol has been defined as
473 * contained in a dynamic [load time/run time] linked library.
475 * segment = -1 => not yet defined
476 * segment = -2 => defined as dll symbol
478 * If the symbol is already defined, and the new segment >= 0, then
479 * if the original segment was < 0 the symbol is redefined, otherwise
480 * a duplicate symbol warning is issued. If new segment == -1, this
481 * routine won't change a previously existing symbol. It will change
482 * to segment = -2 only if the segment was previously < 0.
485 void symtab_add(const char * symbol
, int segment
, long offset
)
489 ste
= symtabFind(symtab
, symbol
);
492 if (ste
->segment
>= 0) {
494 * symbol previously defined
496 if (segment
< 0) return;
497 fprintf (error_file
, "warning: `%s' redefined\n", symbol
);
502 * somebody wanted the symbol, and put an undefined symbol
503 * marker into the table
505 if (segment
== -1) return;
507 * we have more information now - update the symbol's entry
509 ste
->segment
= segment
;
510 ste
->offset
= offset
;
515 * this is the first declaration of this symbol
517 ste
= malloc(sizeof(symtabEnt
));
519 fprintf(stderr
, "ldrdf: out of memory\n");
522 ste
->name
= strdup(symbol
);
523 ste
->segment
= segment
;
524 ste
->offset
= offset
;
526 symtabInsert(symtab
, ste
);
532 * Retrieves the values associated with a symbol. Undefined symbols
533 * are assumed to have -1:0 associated. Returns 1 if the symbol was
534 * successfully located.
537 int symtab_get(const char * symbol
, int * segment
, long * offset
)
539 symtabEnt
* ste
= symtabFind(symtab
, symbol
);
547 *segment
= ste
->segment
;
548 *offset
= ste
->offset
;
556 * checks that a library can be opened and is in the correct format,
557 * then adds it to the linked list of libraries.
560 void add_library(const char * name
)
562 if (rdl_verify(name
)) {
563 rdl_perror("ldrdf", name
);
569 lastlib
= libraries
= malloc(sizeof(*libraries
));
571 fprintf(stderr
, "ldrdf: out of memory\n");
577 lastlib
->next
= malloc(sizeof(*libraries
));
578 if (!lastlib
->next
) {
579 fprintf(stderr
, "ldrdf: out of memory\n");
582 lastlib
= lastlib
->next
;
584 lastlib
->next
= NULL
;
585 if (rdl_open(lastlib
, name
)) {
586 rdl_perror("ldrdf", name
);
595 * scans through the list of libraries, attempting to match symbols
596 * defined in library modules against symbols that are referenced but
597 * not defined (segment = -1 in the symbol table)
599 * returns 1 if any extra library modules are included, indicating that
600 * another pass through the library list should be made (possibly).
603 int search_libraries()
605 struct librarynode
* cur
;
611 int doneanything
= 0, pass
= 1, keepfile
;
618 if (options
.verbose
> 2)
619 printf("scanning library `%s', pass %d...\n", cur
->name
, pass
);
621 for (i
= 0; rdl_openmodule(cur
, i
, &f
) == 0; i
++)
623 if (pass
== 2 && lookformodule(f
.name
)) continue;
625 if (options
.verbose
> 3)
626 printf(" looking in module `%s'\n", f
.name
);
628 header
= malloc(f
.header_len
);
630 fprintf(stderr
, "ldrdf: not enough memory\n");
633 if (rdfloadseg(&f
, RDOFF_HEADER
, header
)) {
634 rdfperror("ldrdf", f
.name
);
641 while ((hr
= rdfgetheaderrec (&f
)))
643 /* we're only interested in exports, so skip others: */
644 if (hr
->type
!= 3) continue;
647 * Find the symbol in the symbol table. If the symbol isn't
648 * defined, we aren't interested, so go on to the next.
649 * If it is defined as anything but -1, we're also not
650 * interested. But if it is defined as -1, insert this
651 * module into the list of modules to use, and go
652 * immediately on to the next module...
654 if (! symtab_get(hr
->e
.label
, &segment
, &offset
)
664 * as there are undefined symbols, we can assume that
665 * there are modules on the module list by the time
668 lastmodule
->next
= malloc(sizeof(*lastmodule
->next
));
669 if (!lastmodule
->next
) {
670 fprintf(stderr
, "ldrdf: not enough memory\n");
673 lastmodule
= lastmodule
->next
;
674 memcpy(&lastmodule
->f
, &f
, sizeof(f
));
675 lastmodule
->name
= strdup(f
.name
);
676 lastmodule
->next
= NULL
;
677 processmodule(f
.name
, lastmodule
);
687 if (rdl_error
!= 0 && rdl_error
!= RDL_ENOTFOUND
)
688 rdl_perror("ldrdf", cur
->name
);
691 if (cur
== NULL
&& pass
== 1) {
703 * this takes the linked list of modules, and walks through it, merging
704 * all the modules into a single output module, and then writes this to a
707 void write_output(const char * filename
)
710 rdf_headerbuf
* rdfheader
;
711 struct modulenode
* cur
;
712 int i
, availableseg
, seg
, localseg
, isrelative
;
714 rdfheaderrec
* hr
, newrec
;
720 if ((f
= fopen(filename
, "wb"))==NULL
) {
721 fprintf(stderr
, "ldrdf: couldn't open %s for output\n", filename
);
724 if ((rdfheader
=rdfnewheader())==NULL
) {
725 fprintf(stderr
, "ldrdf: out of memory\n");
730 * Add multiboot header if appropriate option is specified.
731 * Multiboot record *MUST* be the first record in output file.
733 if (options
.addMBheader
) {
735 puts("\nadding multiboot header record");
737 hr
= (rdfheaderrec
*) malloc(sizeof(struct MultiBootHdrRec
));
739 hr
->mbh
.reclen
= sizeof(struct tMultiBootHeader
)+RDFLDRMOVER_SIZE
;
741 hr
->mbh
.mb
.Magic
= MB_MAGIC
;
742 hr
->mbh
.mb
.Flags
= MB_FL_KLUDGE
;
743 hr
->mbh
.mb
.Checksum
= ~(MB_MAGIC
+MB_FL_KLUDGE
-1);
744 hr
->mbh
.mb
.HeaderAddr
= MBHloadAddr
+16;
745 hr
->mbh
.mb
.LoadAddr
= MBHloadAddr
;
746 hr
->mbh
.mb
.Entry
= MBHloadAddr
+16+sizeof(struct tMultiBootHeader
);
748 memcpy(hr
->mbh
.mover
,RDFloaderMover
,RDFLDRMOVER_SIZE
);
750 rdfaddheader(rdfheader
,hr
);
755 printf ("\nbuilding output module (%d segments)\n", nsegs
);
758 * Allocate the memory for the segments. We may be better off
759 * building the output module one segment at a time when running
760 * under 16 bit DOS, but that would be a slower way of doing this.
761 * And you could always use DJGPP...
763 for (i
= 0; i
< nsegs
; i
++)
765 outputseg
[i
].data
=NULL
;
766 if(!outputseg
[i
].length
) continue;
767 outputseg
[i
].data
= malloc(outputseg
[i
].length
);
768 if (!outputseg
[i
].data
) {
769 fprintf(stderr
, "ldrdf: out of memory\n");
775 * initialise availableseg, used to allocate segment numbers for
776 * imported and exported labels...
778 availableseg
= nsegs
;
781 * Step through the modules, performing required actions on each one
783 for (cur
= modules
; cur
; cur
=cur
->next
)
786 * Read the actual segment contents into the correct places in
787 * the newly allocated segments
790 for (i
= 0; i
< cur
->f
.nsegs
; i
++)
792 int dest
= cur
->seginfo
[i
].dest_seg
;
794 if (dest
== -1) continue;
795 if (rdfloadseg(&cur
->f
, i
,
796 outputseg
[dest
].data
+ cur
->seginfo
[i
].reloc
))
798 rdfperror("ldrdf", cur
->name
);
804 * Perform fixups, and add new header records where required
807 header
= malloc(cur
->f
.header_len
);
809 fprintf(stderr
, "ldrdf: out of memory\n");
813 if (cur
->f
.header_loc
)
814 rdfheaderrewind(&cur
->f
);
816 if (rdfloadseg(&cur
->f
, RDOFF_HEADER
, header
))
818 rdfperror("ldrdf", cur
->name
);
823 * we need to create a local segment number -> location
824 * table for the segments in this module.
826 init_seglocations(&segs
);
827 for (i
= 0; i
< cur
->f
.nsegs
; i
++)
829 add_seglocation(&segs
, cur
->f
.seg
[i
].number
,
830 cur
->seginfo
[i
].dest_seg
, cur
->seginfo
[i
].reloc
);
833 * and the BSS segment (doh!)
835 add_seglocation (&segs
, 2, 2, cur
->bss_reloc
);
837 while ((hr
= rdfgetheaderrec(&cur
->f
)))
840 case 1: /* relocation record - need to do a fixup */
842 * First correct the offset stored in the segment from
843 * the start of the segment (which may well have changed).
845 * To do this we add to the number stored the relocation
846 * factor associated with the segment that contains the
849 * The relocation could be a relative relocation, in which
850 * case we have to first subtract the amount we've relocated
851 * the containing segment by.
854 if (!get_seglocation(&segs
, hr
->r
.refseg
, &seg
, &offset
))
856 fprintf(stderr
, "%s: reloc to undefined segment %04x\n",
857 cur
->name
, (int) hr
->r
.refseg
);
862 isrelative
= (hr
->r
.segment
& 64) == 64;
865 if (hr
->r
.segment
== 2 ||
866 (localseg
= rdffindsegment(&cur
->f
, hr
->r
.segment
)) == -1)
868 fprintf(stderr
, "%s: reloc from %s segment (%d)\n",
870 hr
->r
.segment
== 2 ? "BSS" : "unknown",
876 if (hr
->r
.length
!= 1 && hr
->r
.length
!= 2 && hr
->r
.length
!=4)
878 fprintf(stderr
, "%s: nonstandard length reloc "
879 "(%d bytes)\n", cur
->name
, hr
->r
.length
);
885 * okay, now the relocation is in the segment pointed to by
886 * cur->seginfo[localseg], and we know everything else is
887 * okay to go ahead and do the relocation
889 data
= outputseg
[cur
->seginfo
[localseg
].dest_seg
].data
;
890 data
+= cur
->seginfo
[localseg
].reloc
+ hr
->r
.offset
;
893 * data now points to the reference that needs
894 * relocation. Calculate the relocation factor.
896 * offset of referred object in segment [in offset]
897 * (- relocation of localseg, if ref is relative)
898 * For simplicity, the result is stored in 'offset'.
899 * Then add 'offset' onto the value at data.
902 if (isrelative
) offset
-= cur
->seginfo
[localseg
].reloc
;
903 switch (hr
->r
.length
)
907 if (offset
< -127 || offset
> 128)
908 fprintf(error_file
, "warning: relocation out of range "
909 "at %s(%02x:%08lx)\n", cur
->name
,
910 (int)hr
->r
.segment
, hr
->r
.offset
);
911 *data
= (char) offset
;
914 offset
+= * (short *)data
;
915 if (offset
< -32767 || offset
> 32768)
916 fprintf(error_file
, "warning: relocation out of range "
917 "at %s(%02x:%08lx)\n", cur
->name
,
918 (int)hr
->r
.segment
, hr
->r
.offset
);
919 * (short *)data
= (short) offset
;
922 * (long *)data
+= offset
;
923 /* we can't easily detect overflow on this one */
928 * If the relocation was relative between two symbols in
929 * the same segment, then we're done.
931 * Otherwise, we need to output a new relocation record
932 * with the references updated segment and offset...
935 || cur
->seginfo
[localseg
].dest_seg
!= seg
)
937 hr
->r
.segment
= cur
->seginfo
[localseg
].dest_seg
;
938 hr
->r
.offset
+= cur
->seginfo
[localseg
].reloc
;
940 rdfaddheader(rdfheader
, hr
);
944 case 2: /* import symbol */
947 * scan the global symbol table for the symbol
948 * and associate its location with the segment number
951 se
= symtabFind(symtab
, hr
->i
.label
);
952 if (!se
|| se
->segment
== -1) {
953 if (options
.warnUnresolved
) {
954 fprintf(error_file
, "warning: unresolved reference to `%s'"
955 " in module `%s'\n", hr
->i
.label
, cur
->name
);
956 if (options
.errorUnresolved
==1) errorcount
++;
959 * we need to allocate a segment number for this
960 * symbol, and store it in the symbol table for
964 se
=malloc(sizeof(*se
));
966 fprintf(stderr
, "ldrdf: out of memory\n");
969 se
->name
= strdup(hr
->i
.label
);
971 se
->segment
= availableseg
++;
973 symtabInsert(symtab
, se
);
976 se
->segment
= availableseg
++;
980 * output a header record that imports it to the
981 * recently allocated segment number...
984 newrec
.i
.segment
= se
->segment
;
985 rdfaddheader(rdfheader
, &newrec
);
988 add_seglocation(&segs
, hr
->i
.segment
, se
->segment
, se
->offset
);
992 case 3: /* export symbol */
994 * need to insert an export for this symbol into the new
995 * header, unless we're stripping symbols. Even if we're
996 * stripping, put the symbol if it's marked as SYM_GLOBAL.
998 if (options
.strip
&& !(hr
->e
.flags
& SYM_GLOBAL
))
1001 if (hr
->e
.segment
== 2) {
1003 offset
= cur
->bss_reloc
;
1006 localseg
= rdffindsegment(&cur
->f
, hr
->e
.segment
);
1007 if (localseg
== -1) {
1008 fprintf(stderr
, "%s: exported symbol `%s' from "
1009 "unrecognised segment\n", cur
->name
,
1014 offset
= cur
->seginfo
[localseg
].reloc
;
1015 seg
= cur
->seginfo
[localseg
].dest_seg
;
1018 hr
->e
.segment
= seg
;
1019 hr
->e
.offset
+= offset
;
1020 rdfaddheader(rdfheader
, hr
);
1023 case 8: /* module name */
1025 * Insert module name record if export symbols
1027 * If module name begins with '$' - insert it anyway.
1030 if (options
.strip
&& hr
->m
.modname
[0] != '$') break;
1032 rdfaddheader(rdfheader
, hr
);
1035 case 6: /* segment fixup */
1037 * modify the segment numbers if necessary, and
1038 * pass straight through to the output module header
1042 if (hr
->r
.segment
== 2) {
1043 fprintf(stderr
, "%s: segment fixup in BSS section\n",
1048 localseg
= rdffindsegment(&cur
->f
, hr
->r
.segment
);
1049 if (localseg
== -1) {
1050 fprintf(stderr
, "%s: segment fixup in unrecognised"
1051 " segment (%d)\n", cur
->name
, hr
->r
.segment
);
1055 hr
->r
.segment
= cur
->seginfo
[localseg
].dest_seg
;
1056 hr
->r
.offset
+= cur
->seginfo
[localseg
].reloc
;
1058 if (!get_seglocation(&segs
, hr
->r
.refseg
, &seg
, &offset
))
1060 fprintf(stderr
, "%s: segment fixup to undefined "
1061 "segment %04x\n", cur
->name
, (int)hr
->r
.refseg
);
1066 rdfaddheader(rdfheader
, hr
);
1072 done_seglocations(&segs
);
1077 * combined BSS reservation for the entire results
1080 newrec
.b
.reclen
= 4;
1081 newrec
.b
.amount
= bss_length
;
1082 rdfaddheader(rdfheader
, &newrec
);
1087 for (i
= 0; i
< nsegs
; i
++)
1089 if (i
== 2) continue;
1090 rdfaddsegment (rdfheader
, outputseg
[i
].length
);
1093 if (options
.addMBheader
) {
1094 struct MultiBootHdrRec
*mbhrec
= (struct MultiBootHdrRec
*)(rdfheader
->buf
->buffer
);
1095 unsigned l
= membuflength(rdfheader
->buf
) + 14 +
1096 10*rdfheader
->nsegments
+ rdfheader
->seglength
;
1097 unsigned *ldraddr
= (unsigned *)(mbhrec
->mover
+1);
1099 mbhrec
->mb
.LoadEndAddr
= MBHloadAddr
+l
+10+RDFLDR_LENGTH
;
1100 mbhrec
->mb
.BSSendAddr
= mbhrec
->mb
.LoadEndAddr
;
1101 *ldraddr
= MBHloadAddr
+l
+10;
1104 rdfwriteheader(f
, rdfheader
);
1105 rdfdoneheader(rdfheader
);
1107 * Step through the segments, one at a time, writing out into
1111 for (i
= 0; i
< nsegs
; i
++)
1116 if (i
== 2) continue;
1118 s
= translateshort(outputseg
[i
].type
);
1119 fwrite(&s
, 2, 1, f
);
1120 s
= translateshort(outputseg
[i
].number
);
1121 fwrite(&s
, 2, 1, f
);
1122 s
= translateshort(outputseg
[i
].reserved
);
1123 fwrite(&s
, 2, 1, f
);
1124 l
= translatelong(outputseg
[i
].length
);
1125 fwrite(&l
, 4, 1, f
);
1127 fwrite(outputseg
[i
].data
, outputseg
[i
].length
, 1, f
);
1130 fwrite("\0\0\0\0\0\0\0\0\0\0", 10, 1, f
);
1133 /* =========================================================================
1140 printf(" ldrdf [options] object modules ... [-llibrary ...]\n");
1141 printf(" ldrdf -r\n");
1142 printf("options:\n");
1143 printf(" -v[=n] increases verbosity by 1, or sets it to n\n");
1144 printf(" -a nn sets segment alignment value (default 16)\n");
1145 printf(" -s strips exported symbols\n");
1146 printf(" -x warn about unresolved symbols\n");
1147 printf(" -o name write output in file 'name'\n");
1148 printf(" -j path specify objects search path\n");
1149 printf(" -L path specify libraries search path\n");
1150 printf(" -mbh [address] add multiboot header to output file. Default\n");
1151 printf(" loading address is 0x110000\n");
1155 int main(int argc
, char ** argv
)
1157 char * outname
= "aout.rdf";
1158 int moduleloaded
= 0;
1159 char *respstrings
[128] = {0, };
1161 options
.verbose
= 0;
1163 options
.warnUnresolved
= 0;
1166 error_file
= stderr
;
1169 if (argc
== 0) usage();
1170 while (argc
&& **argv
== '-' && argv
[0][1] != 'l')
1172 switch(argv
[0][1]) {
1174 printf("ldrdf (linker for RDF files) version " LDRDF_VERSION
"\n");
1175 printf( _RDOFF_H
"\n");
1178 if (argv
[0][2] == '=') {
1179 options
.verbose
= argv
[0][3] - '0';
1180 if (options
.verbose
< 0 || options
.verbose
> 9) {
1181 fprintf(stderr
, "ldrdf: verbosity level must be a number"
1182 " between 0 and 9\n");
1190 options
.align
= atoi(argv
[1]);
1191 if (options
.align
<= 0) {
1193 "ldrdf: -a expects a positive number argument\n");
1202 options
.warnUnresolved
= 1;
1203 if (argv
[0][2]=='e')
1204 options
.errorUnresolved
= 1;
1213 options
.objpath
= 1;
1220 fprintf(stderr
,"ldrdf: more than one objects search path specified\n");
1226 options
.libpath
= 1;
1233 fprintf(stderr
,"ldrdf: more than one libraries search path specified\n");
1241 options
.respfile
= 1;
1242 if (argv
[1] != NULL
) f
= fopen(argv
[1],"r");
1245 fprintf(stderr
,"ldrdf: no response file name specified\n");
1251 fprintf(stderr
,"ldrdf: unable to open response file\n");
1255 while(fgets(buf
,sizeof(buf
)-1,f
)!=NULL
)
1258 if (buf
[0]=='\n') continue;
1259 if ((p
= strchr(buf
,'\n')) != 0)
1263 fprintf(stderr
,"ldrdf: too many input files\n");
1266 *(respstrings
+i
) = newstr(buf
);
1272 options
.stderr_redir
= 1;
1273 error_file
= stdout
;
1276 if (argv
[0][2] == 'b' && argv
[0][3] == 'h') {
1277 if (argv
[1][0] != '-') {
1278 MBHloadAddr
= atoi(argv
[1]);
1280 MBHloadAddr
= MB_DEFAULTLOADADDR
;
1282 options
.addMBheader
= 1;
1291 if (options
.verbose
> 4) {
1292 printf("ldrdf invoked with options:\n");
1293 printf(" section alignment: %d bytes\n", options
.align
);
1294 printf(" output name: `%s'\n", outname
);
1296 printf(" strip symbols\n");
1297 if (options
.warnUnresolved
)
1298 printf(" warn about unresolved symbols\n");
1299 if (options
.errorUnresolved
)
1300 printf(" error if unresolved symbols\n");
1301 if (options
.objpath
)
1302 printf(" objects search path: %s\n",objpath
);
1303 if (options
.libpath
)
1304 printf(" libraries search path: %s\n",libpath
);
1305 if (options
.addMBheader
)
1306 printf(" loading address for multiboot header: 0x%X\n",MBHloadAddr
);
1310 symtab
= symtabNew();
1314 fprintf(stderr
, "ldrdf: out of memory\n");
1318 if (*respstrings
) argv
= respstrings
;
1321 if (!strncmp(*argv
, "-l", 2)) /* library */
1323 if(libpath
) add_library(newstrcat(libpath
,*argv
+ 2));
1324 else add_library(*argv
+ 2);
1327 if(objpath
) loadmodule(newstrcat(objpath
,*argv
));
1328 else loadmodule(*argv
);
1334 if (! moduleloaded
) {
1335 printf("ldrdf: nothing to do. ldrdf -h for usage\n");
1342 if (options
.verbose
> 2)
1344 printf ("symbol table:\n");
1345 symtabDump(symtab
, stdout
);
1348 write_output(outname
);
1350 if (errorcount
> 0) exit(1);