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.
35 #define LDRDF_VERSION "1.04"
37 #define RDF_MAXSEGS 64
38 /* #define STINGY_MEMORY */
40 /* =======================================================================
41 * Types & macros that are private to this program
44 struct segment_infonode
{
45 int dest_seg
; /* output segment to be placed into, -1 to
46 skip linking this segment */
47 long reloc
; /* segment's relocation factor */
52 rdffile f
; /* the RDOFF file structure */
53 struct segment_infonode seginfo
[RDF_MAXSEGS
]; /* what are we doing
57 struct modulenode
* next
;
63 #define newstr(str) strcpy(malloc(strlen(str) + 1),str)
64 #define newstrcat(s1,s2) strcat(strcpy(malloc(strlen(s1)+strlen(s2)+1),s1),s2)
66 /* ==========================================================================
67 * Function prototypes of private utility functions
70 void processmodule(const char * filename
, struct modulenode
* mod
);
71 int allocnewseg(int16 type
,int16 reserved
);
72 int findsegment(int16 type
,int16 reserved
);
73 void symtab_add(const char * symbol
, int segment
, long offset
);
74 int symtab_get(const char * symbol
, int * segment
, long * offset
);
76 /* =========================================================================
77 * Global data structures.
80 /* a linked list of modules that will be included in the output */
81 struct modulenode
* modules
= NULL
;
82 struct modulenode
* lastmodule
= NULL
;
84 /* a linked list of libraries to be searched for unresolved imported symbols */
85 struct librarynode
* libraries
= NULL
;
86 struct librarynode
* lastlib
= NULL
;
88 /* the symbol table */
91 /* objects search path */
92 char * objpath
= NULL
;
94 /* libraries search path */
95 char * libpath
= NULL
;
98 static FILE * error_file
;
100 /* the header of the output file, built up stage by stage */
101 rdf_headerbuf
* newheader
= NULL
;
103 /* The current state of segment allocation, including information about
104 * which output segment numbers have been allocated, and their types and
105 * amount of data which has already been allocated inside them.
107 struct SegmentHeaderRec outputseg
[RDF_MAXSEGS
];
111 /* global options which affect how the program behaves */
112 struct ldrdfoptions
{
125 int errorcount
= 0; /* determines main program exit status */
128 * Multiboot header support.
131 /* loading address for multiboot header */
132 unsigned MBHloadAddr
;
134 #define RDFLDR_LENGTH 4096 /* Loader size is 4K */
135 #define RDFLDR_DESTLOC 0x100000 /* and its absolute address */
138 * Tiny code that moves RDF setup code to its working memory region
140 unsigned char trampoline_code
[] = {
141 0xBE, 0, 0, 0, 0, /* mov esi,SOURCE_ADDR */
142 0xBF, 0, 0, 0, 0, /* mov edi,DEST_ADDR */
143 0x89, 0xFA, /* mov edx,edi */
144 0xB9, 0, 4, 0, 0, /* mov ecx,RDFLDR_LENGTH/4 */
146 0xF3, 0xA5, /* rep movsd */
147 0xFF, 0xE2 /* jmp edx */
150 /* =========================================================================
158 * sets up segments 0, 1, and 2, the initial code data and bss segments
164 outputseg
[0].type
= 1;
165 outputseg
[0].number
= 0;
166 outputseg
[0].reserved
= 0;
167 outputseg
[0].length
= 0;
168 outputseg
[1].type
= 2;
169 outputseg
[1].number
= 1;
170 outputseg
[1].reserved
= 0;
171 outputseg
[1].length
= 0;
172 outputseg
[2].type
= 0xFFFF; /* reserved segment type */
173 outputseg
[2].number
= 2;
174 outputseg
[2].reserved
= 0;
175 outputseg
[2].length
= 0;
182 * Determine the characteristics of a module, and decide what to do with
183 * each segment it contains (including determining destination segments and
184 * relocation factors for segments that are kept).
187 void loadmodule(const char * filename
)
190 printf("loading `%s'\n", filename
);
192 /* allocate a new module entry on the end of the modules list */
195 modules
= malloc (sizeof(*modules
));
196 lastmodule
= modules
;
200 lastmodule
->next
= malloc (sizeof(*modules
));
201 lastmodule
= lastmodule
->next
;
206 fprintf(stderr
, "ldrdf: out of memory\n");
210 /* open the file using 'rdfopen', which returns nonzero on error */
212 if (rdfopen(&lastmodule
->f
, filename
) != 0)
214 rdfperror("ldrdf", filename
);
219 * store information about the module, and determine what segments
220 * it contains, and what we should do with them (determine relocation
221 * factor if we decide to keep them)
224 lastmodule
->header
= NULL
;
225 lastmodule
->name
= strdup(filename
);
226 lastmodule
->next
= NULL
;
228 processmodule(filename
, lastmodule
);
234 * step through each segment, determine what exactly we're doing with
235 * it, and if we intend to keep it, determine (a) which segment to
236 * put it in and (b) whereabouts in that segment it will end up.
237 * (b) is fairly easy, cos we're now keeping track of how big each segment
238 * in our output file is...
241 void processmodule(const char * filename
, struct modulenode
* mod
)
243 struct segconfig sconf
;
249 for (seg
= 0; seg
< mod
->f
.nsegs
; seg
++)
252 * get the segment configuration for this type from the segment
253 * table. getsegconfig() is a macro, defined in ldsegs.h.
255 getsegconfig(sconf
, mod
->f
.seg
[seg
].type
);
257 if (options
.verbose
> 1) {
258 printf ("%s %04x [%04x:%10s] ", filename
, mod
->f
.seg
[seg
].number
,
259 mod
->f
.seg
[seg
].type
, sconf
.typedesc
);
262 * sconf->dowhat tells us what to do with a segment of this type.
264 switch (sconf
.dowhat
) {
267 * Set destination segment to -1, to indicate that this segment
268 * should be ignored for the purpose of output, ie it is left
269 * out of the linked executable.
271 mod
->seginfo
[seg
].dest_seg
= -1;
272 if (options
.verbose
> 1) printf("IGNORED\n");
277 * The configuration tells us to create a new segment for
278 * each occurrence of this segment type.
280 outseg
= allocnewseg(sconf
.mergetype
,
281 mod
->f
.seg
[seg
].reserved
);
282 mod
->seginfo
[seg
].dest_seg
= outseg
;
283 mod
->seginfo
[seg
].reloc
= 0;
284 outputseg
[outseg
].length
= mod
->f
.seg
[seg
].length
;
285 if (options
.verbose
> 1)
286 printf ("=> %04x:%08lx (+%04lx)\n", outseg
,
287 mod
->seginfo
[seg
].reloc
,
288 mod
->f
.seg
[seg
].length
);
293 * The configuration tells us to merge the segment with
294 * a previously existing segment of type 'sconf.mergetype',
295 * if one exists. Otherwise a new segment is created.
296 * This is handled transparently by 'findsegment()'.
298 outseg
= findsegment(sconf
.mergetype
,
299 mod
->f
.seg
[seg
].reserved
);
300 mod
->seginfo
[seg
].dest_seg
= outseg
;
303 * We need to add alignment to these segments.
305 if (outputseg
[outseg
].length
% options
.align
!= 0)
306 outputseg
[outseg
].length
+=
307 options
.align
- (outputseg
[outseg
].length
% options
.align
);
309 mod
->seginfo
[seg
].reloc
= outputseg
[outseg
].length
;
310 outputseg
[outseg
].length
+= mod
->f
.seg
[seg
].length
;
312 if (options
.verbose
> 1)
313 printf ("=> %04x:%08lx (+%04lx)\n", outseg
,
314 mod
->seginfo
[seg
].reloc
,
315 mod
->f
.seg
[seg
].length
);
321 * extract symbols from the header, and dump them into the
324 header
= malloc(mod
->f
.header_len
);
326 fprintf(stderr
, "ldrdf: not enough memory\n");
329 if (rdfloadseg(&mod
->f
, RDOFF_HEADER
, header
)) {
330 rdfperror("ldrdf", filename
);
334 while ((hr
= rdfgetheaderrec (&mod
->f
)))
337 case 2: /* imported symbol - define with seg = -1 */
339 symtab_add(hr
->i
.label
, -1, 0);
342 case 3: /* exported symbol */
347 if (hr
->e
.segment
== 2)
349 destreloc
= bss_length
;
350 if (destreloc
% options
.align
!= 0)
351 destreloc
+= options
.align
- (destreloc
% options
.align
);
356 if ((destseg
= mod
->seginfo
[(int)hr
->e
.segment
].dest_seg
) == -1)
358 destreloc
= mod
->seginfo
[(int)hr
->e
.segment
].reloc
;
360 symtab_add(hr
->e
.label
, destseg
, destreloc
+ hr
->e
.offset
);
364 case 5: /* BSS reservation */
366 * first, amalgamate all BSS reservations in this module
367 * into one, because we allow this in the output format.
369 bssamount
+= hr
->b
.amount
;
377 * handle the BSS segment - first pad the existing bss length
378 * to the correct alignment, then store the length in bss_reloc
379 * for this module. Then add this module's BSS length onto
382 if (bss_length
% options
.align
!= 0)
383 bss_length
+= options
.align
- (bss_length
% options
.align
);
385 mod
->bss_reloc
= bss_length
;
386 if (options
.verbose
> 1) {
387 printf ("%s 0002 [ BSS] => 0002:%08lx (+%04lx)\n",
388 filename
, bss_length
, bssamount
);
390 bss_length
+= bssamount
;
395 * we free the header buffer here, to save memory later.
396 * this isn't efficient, but probably halves the memory usage
399 mod
->f
.header_loc
= NULL
;
408 * Look in list for module by its name.
410 int lookformodule(const char *name
)
412 struct modulenode
*curr
=modules
;
415 if (!strcmp(name
,curr
->name
)) return 1;
426 * These functions manipulate the array of output segments, and are used
427 * by processmodule(). allocnewseg() allocates a segment in the array,
428 * initialising it to be empty. findsegment() first scans the array for
429 * a segment of the type requested, and if one isn't found allocates a
432 int allocnewseg(int16 type
,int16 reserved
)
434 outputseg
[nsegs
].type
= type
;
435 outputseg
[nsegs
].number
= nsegs
;
436 outputseg
[nsegs
].reserved
= reserved
;
437 outputseg
[nsegs
].length
= 0;
438 outputseg
[nsegs
].offset
= 0;
439 outputseg
[nsegs
].data
= NULL
;
444 int findsegment(int16 type
,int16 reserved
)
448 for (i
= 0; i
< nsegs
; i
++)
449 if (outputseg
[i
].type
== type
) return i
;
451 return allocnewseg(type
,reserved
);
457 * inserts a symbol into the global symbol table, which associates symbol
458 * names either with addresses, or a marker that the symbol hasn't been
459 * resolved yet, or possibly that the symbol has been defined as
460 * contained in a dynamic [load time/run time] linked library.
462 * segment = -1 => not yet defined
463 * segment = -2 => defined as dll symbol
465 * If the symbol is already defined, and the new segment >= 0, then
466 * if the original segment was < 0 the symbol is redefined, otherwise
467 * a duplicate symbol warning is issued. If new segment == -1, this
468 * routine won't change a previously existing symbol. It will change
469 * to segment = -2 only if the segment was previously < 0.
472 void symtab_add(const char * symbol
, int segment
, long offset
)
476 ste
= symtabFind(symtab
, symbol
);
479 if (ste
->segment
>= 0) {
481 * symbol previously defined
483 if (segment
< 0) return;
484 fprintf (error_file
, "warning: `%s' redefined\n", symbol
);
489 * somebody wanted the symbol, and put an undefined symbol
490 * marker into the table
492 if (segment
== -1) return;
494 * we have more information now - update the symbol's entry
496 ste
->segment
= segment
;
497 ste
->offset
= offset
;
502 * this is the first declaration of this symbol
504 ste
= malloc(sizeof(symtabEnt
));
506 fprintf(stderr
, "ldrdf: out of memory\n");
509 ste
->name
= strdup(symbol
);
510 ste
->segment
= segment
;
511 ste
->offset
= offset
;
513 symtabInsert(symtab
, ste
);
519 * Retrieves the values associated with a symbol. Undefined symbols
520 * are assumed to have -1:0 associated. Returns 1 if the symbol was
521 * successfully located.
524 int symtab_get(const char * symbol
, int * segment
, long * offset
)
526 symtabEnt
* ste
= symtabFind(symtab
, symbol
);
534 *segment
= ste
->segment
;
535 *offset
= ste
->offset
;
543 * checks that a library can be opened and is in the correct format,
544 * then adds it to the linked list of libraries.
547 void add_library(const char * name
)
549 if (rdl_verify(name
)) {
550 rdl_perror("ldrdf", name
);
556 lastlib
= libraries
= malloc(sizeof(*libraries
));
558 fprintf(stderr
, "ldrdf: out of memory\n");
564 lastlib
->next
= malloc(sizeof(*libraries
));
565 if (!lastlib
->next
) {
566 fprintf(stderr
, "ldrdf: out of memory\n");
569 lastlib
= lastlib
->next
;
571 lastlib
->next
= NULL
;
572 if (rdl_open(lastlib
, name
)) {
573 rdl_perror("ldrdf", name
);
582 * scans through the list of libraries, attempting to match symbols
583 * defined in library modules against symbols that are referenced but
584 * not defined (segment = -1 in the symbol table)
586 * returns 1 if any extra library modules are included, indicating that
587 * another pass through the library list should be made (possibly).
590 int search_libraries()
592 struct librarynode
* cur
;
598 int doneanything
= 0, pass
= 1, keepfile
;
605 if (options
.verbose
> 2)
606 printf("scanning library `%s', pass %d...\n", cur
->name
, pass
);
608 for (i
= 0; rdl_openmodule(cur
, i
, &f
) == 0; i
++)
610 if (pass
== 2 && lookformodule(f
.name
)) continue;
612 if (options
.verbose
> 3)
613 printf(" looking in module `%s'\n", f
.name
);
615 header
= malloc(f
.header_len
);
617 fprintf(stderr
, "ldrdf: not enough memory\n");
620 if (rdfloadseg(&f
, RDOFF_HEADER
, header
)) {
621 rdfperror("ldrdf", f
.name
);
628 while ((hr
= rdfgetheaderrec (&f
)))
630 /* we're only interested in exports, so skip others: */
631 if (hr
->type
!= 3) continue;
634 * Find the symbol in the symbol table. If the symbol isn't
635 * defined, we aren't interested, so go on to the next.
636 * If it is defined as anything but -1, we're also not
637 * interested. But if it is defined as -1, insert this
638 * module into the list of modules to use, and go
639 * immediately on to the next module...
641 if (! symtab_get(hr
->e
.label
, &segment
, &offset
)
651 * as there are undefined symbols, we can assume that
652 * there are modules on the module list by the time
655 lastmodule
->next
= malloc(sizeof(*lastmodule
->next
));
656 if (!lastmodule
->next
) {
657 fprintf(stderr
, "ldrdf: not enough memory\n");
660 lastmodule
= lastmodule
->next
;
661 memcpy(&lastmodule
->f
, &f
, sizeof(f
));
662 lastmodule
->name
= strdup(f
.name
);
663 lastmodule
->next
= NULL
;
664 processmodule(f
.name
, lastmodule
);
674 if (rdl_error
!= 0 && rdl_error
!= RDL_ENOTFOUND
)
675 rdl_perror("ldrdf", cur
->name
);
678 if (cur
== NULL
&& pass
== 1) {
690 * this takes the linked list of modules, and walks through it, merging
691 * all the modules into a single output module, and then writes this to a
694 void write_output(const char * filename
)
697 rdf_headerbuf
* rdfheader
;
698 struct modulenode
* cur
;
699 int i
, availableseg
, seg
, localseg
, isrelative
;
701 rdfheaderrec
* hr
, newrec
;
707 if ((f
= fopen(filename
, "wb"))==NULL
) {
708 fprintf(stderr
, "ldrdf: couldn't open %s for output\n", filename
);
711 if ((rdfheader
=rdfnewheader())==NULL
) {
712 fprintf(stderr
, "ldrdf: out of memory\n");
717 * Add multiboot header if appropriate option is specified.
718 * Multiboot record *MUST* be the first record in output file.
720 if (options
.addMBheader
) {
722 puts("\nadding multiboot header record");
724 hr
= (rdfheaderrec
*) malloc(sizeof(struct MultiBootHdrRec
));
726 hr
->mbh
.reclen
= sizeof(struct tMultiBootHeader
)+TRAMPOLINESIZE
;
728 hr
->mbh
.mb
.Magic
= MB_MAGIC
;
729 hr
->mbh
.mb
.Flags
= MB_FL_KLUDGE
;
730 hr
->mbh
.mb
.Checksum
= ~(MB_MAGIC
+MB_FL_KLUDGE
-1);
731 hr
->mbh
.mb
.HeaderAddr
= MBHloadAddr
+16;
732 hr
->mbh
.mb
.LoadAddr
= MBHloadAddr
;
733 hr
->mbh
.mb
.Entry
= MBHloadAddr
+16+sizeof(struct tMultiBootHeader
);
735 memcpy(hr
->mbh
.trampoline
,trampoline_code
,TRAMPOLINESIZE
);
737 rdfaddheader(rdfheader
,hr
);
742 printf ("\nbuilding output module (%d segments)\n", nsegs
);
745 * Allocate the memory for the segments. We may be better off
746 * building the output module one segment at a time when running
747 * under 16 bit DOS, but that would be a slower way of doing this.
748 * And you could always use DJGPP...
750 for (i
= 0; i
< nsegs
; i
++)
752 outputseg
[i
].data
=NULL
;
753 if(!outputseg
[i
].length
) continue;
754 outputseg
[i
].data
= malloc(outputseg
[i
].length
);
755 if (!outputseg
[i
].data
) {
756 fprintf(stderr
, "ldrdf: out of memory\n");
762 * initialise availableseg, used to allocate segment numbers for
763 * imported and exported labels...
765 availableseg
= nsegs
;
768 * Step through the modules, performing required actions on each one
770 for (cur
= modules
; cur
; cur
=cur
->next
)
773 * Read the actual segment contents into the correct places in
774 * the newly allocated segments
777 for (i
= 0; i
< cur
->f
.nsegs
; i
++)
779 int dest
= cur
->seginfo
[i
].dest_seg
;
781 if (dest
== -1) continue;
782 if (rdfloadseg(&cur
->f
, i
,
783 outputseg
[dest
].data
+ cur
->seginfo
[i
].reloc
))
785 rdfperror("ldrdf", cur
->name
);
791 * Perform fixups, and add new header records where required
794 header
= malloc(cur
->f
.header_len
);
796 fprintf(stderr
, "ldrdf: out of memory\n");
800 if (cur
->f
.header_loc
)
801 rdfheaderrewind(&cur
->f
);
803 if (rdfloadseg(&cur
->f
, RDOFF_HEADER
, header
))
805 rdfperror("ldrdf", cur
->name
);
810 * we need to create a local segment number -> location
811 * table for the segments in this module.
813 init_seglocations(&segs
);
814 for (i
= 0; i
< cur
->f
.nsegs
; i
++)
816 add_seglocation(&segs
, cur
->f
.seg
[i
].number
,
817 cur
->seginfo
[i
].dest_seg
, cur
->seginfo
[i
].reloc
);
820 * and the BSS segment (doh!)
822 add_seglocation (&segs
, 2, 2, cur
->bss_reloc
);
824 while ((hr
= rdfgetheaderrec(&cur
->f
)))
827 case 1: /* relocation record - need to do a fixup */
829 * First correct the offset stored in the segment from
830 * the start of the segment (which may well have changed).
832 * To do this we add to the number stored the relocation
833 * factor associated with the segment that contains the
836 * The relocation could be a relative relocation, in which
837 * case we have to first subtract the amount we've relocated
838 * the containing segment by.
841 if (!get_seglocation(&segs
, hr
->r
.refseg
, &seg
, &offset
))
843 fprintf(stderr
, "%s: reloc to undefined segment %04x\n",
844 cur
->name
, (int) hr
->r
.refseg
);
849 isrelative
= (hr
->r
.segment
& 64) == 64;
852 if (hr
->r
.segment
== 2 ||
853 (localseg
= rdffindsegment(&cur
->f
, hr
->r
.segment
)) == -1)
855 fprintf(stderr
, "%s: reloc from %s segment (%d)\n",
857 hr
->r
.segment
== 2 ? "BSS" : "unknown",
863 if (hr
->r
.length
!= 1 && hr
->r
.length
!= 2 && hr
->r
.length
!=4)
865 fprintf(stderr
, "%s: nonstandard length reloc "
866 "(%d bytes)\n", cur
->name
, hr
->r
.length
);
872 * okay, now the relocation is in the segment pointed to by
873 * cur->seginfo[localseg], and we know everything else is
874 * okay to go ahead and do the relocation
876 data
= outputseg
[cur
->seginfo
[localseg
].dest_seg
].data
;
877 data
+= cur
->seginfo
[localseg
].reloc
+ hr
->r
.offset
;
880 * data now points to the reference that needs
881 * relocation. Calculate the relocation factor.
883 * offset of referred object in segment [in offset]
884 * (- relocation of localseg, if ref is relative)
885 * For simplicity, the result is stored in 'offset'.
886 * Then add 'offset' onto the value at data.
889 if (isrelative
) offset
-= cur
->seginfo
[localseg
].reloc
;
890 switch (hr
->r
.length
)
894 if (offset
< -127 || offset
> 128)
895 fprintf(error_file
, "warning: relocation out of range "
896 "at %s(%02x:%08lx)\n", cur
->name
,
897 (int)hr
->r
.segment
, hr
->r
.offset
);
898 *data
= (char) offset
;
901 offset
+= * (short *)data
;
902 if (offset
< -32767 || offset
> 32768)
903 fprintf(error_file
, "warning: relocation out of range "
904 "at %s(%02x:%08lx)\n", cur
->name
,
905 (int)hr
->r
.segment
, hr
->r
.offset
);
906 * (short *)data
= (short) offset
;
909 * (long *)data
+= offset
;
910 /* we can't easily detect overflow on this one */
915 * If the relocation was relative between two symbols in
916 * the same segment, then we're done.
918 * Otherwise, we need to output a new relocation record
919 * with the references updated segment and offset...
922 if (isrelative
&& cur
->seginfo
[localseg
].dest_seg
!= seg
)
924 hr
->r
.segment
= cur
->seginfo
[localseg
].dest_seg
+64;
925 hr
->r
.offset
+= cur
->seginfo
[localseg
].reloc
;
927 rdfaddheader(rdfheader
, hr
);
931 if (! isrelative
|| cur
->seginfo
[localseg
].dest_seg
!= seg
)
933 hr
->r
.segment
= cur
->seginfo
[localseg
].dest_seg
;
934 hr
->r
.offset
+= cur
->seginfo
[localseg
].reloc
;
936 rdfaddheader(rdfheader
, hr
);
940 case 2: /* import symbol */
943 * scan the global symbol table for the symbol
944 * and associate its location with the segment number
947 se
= symtabFind(symtab
, hr
->i
.label
);
948 if (!se
|| se
->segment
== -1) {
949 if (options
.warnUnresolved
) {
950 fprintf(error_file
, "warning: unresolved reference to `%s'"
951 " in module `%s'\n", hr
->i
.label
, cur
->name
);
952 if (options
.errorUnresolved
==1) errorcount
++;
955 * we need to allocate a segment number for this
956 * symbol, and store it in the symbol table for
960 se
=malloc(sizeof(*se
));
962 fprintf(stderr
, "ldrdf: out of memory\n");
965 se
->name
= strdup(hr
->i
.label
);
967 se
->segment
= availableseg
++;
969 symtabInsert(symtab
, se
);
972 se
->segment
= availableseg
++;
976 * output a header record that imports it to the
977 * recently allocated segment number...
980 newrec
.i
.segment
= se
->segment
;
981 rdfaddheader(rdfheader
, &newrec
);
984 add_seglocation(&segs
, hr
->i
.segment
, se
->segment
, se
->offset
);
988 case 3: /* export symbol */
990 * need to insert an export for this symbol into the new
991 * header, unless we're stripping symbols. Even if we're
992 * stripping, put the symbol if it's marked as SYM_GLOBAL.
994 if (options
.strip
&& !(hr
->e
.flags
& SYM_GLOBAL
))
997 if (hr
->e
.segment
== 2) {
999 offset
= cur
->bss_reloc
;
1002 localseg
= rdffindsegment(&cur
->f
, hr
->e
.segment
);
1003 if (localseg
== -1) {
1004 fprintf(stderr
, "%s: exported symbol `%s' from "
1005 "unrecognised segment\n", cur
->name
,
1010 offset
= cur
->seginfo
[localseg
].reloc
;
1011 seg
= cur
->seginfo
[localseg
].dest_seg
;
1014 hr
->e
.segment
= seg
;
1015 hr
->e
.offset
+= offset
;
1016 rdfaddheader(rdfheader
, hr
);
1019 case 8: /* module name */
1021 * Insert module name record if export symbols
1023 * If module name begins with '$' - insert it anyway.
1026 if (options
.strip
&& hr
->m
.modname
[0] != '$') break;
1028 rdfaddheader(rdfheader
, hr
);
1031 case 6: /* segment fixup */
1033 * modify the segment numbers if necessary, and
1034 * pass straight through to the output module header
1038 if (hr
->r
.segment
== 2) {
1039 fprintf(stderr
, "%s: segment fixup in BSS section\n",
1044 localseg
= rdffindsegment(&cur
->f
, hr
->r
.segment
);
1045 if (localseg
== -1) {
1046 fprintf(stderr
, "%s: segment fixup in unrecognised"
1047 " segment (%d)\n", cur
->name
, hr
->r
.segment
);
1051 hr
->r
.segment
= cur
->seginfo
[localseg
].dest_seg
;
1052 hr
->r
.offset
+= cur
->seginfo
[localseg
].reloc
;
1054 if (!get_seglocation(&segs
, hr
->r
.refseg
, &seg
, &offset
))
1056 fprintf(stderr
, "%s: segment fixup to undefined "
1057 "segment %04x\n", cur
->name
, (int)hr
->r
.refseg
);
1062 rdfaddheader(rdfheader
, hr
);
1068 done_seglocations(&segs
);
1073 * combined BSS reservation for the entire results
1076 newrec
.b
.reclen
= 4;
1077 newrec
.b
.amount
= bss_length
;
1078 rdfaddheader(rdfheader
, &newrec
);
1083 for (i
= 0; i
< nsegs
; i
++)
1085 if (i
== 2) continue;
1086 rdfaddsegment (rdfheader
, outputseg
[i
].length
);
1089 if (options
.addMBheader
) {
1090 struct MultiBootHdrRec
*mbhrec
= (struct MultiBootHdrRec
*)(rdfheader
->buf
->buffer
);
1091 unsigned l
= membuflength(rdfheader
->buf
) + 14 +
1092 10*rdfheader
->nsegments
+ rdfheader
->seglength
;
1093 unsigned *ldraddr
= (unsigned *)(mbhrec
->trampoline
+1);
1094 unsigned *ldrdest
= (unsigned *)(mbhrec
->trampoline
+6);
1096 mbhrec
->mb
.LoadEndAddr
= MBHloadAddr
+l
+10+RDFLDR_LENGTH
;
1097 mbhrec
->mb
.BSSendAddr
= mbhrec
->mb
.LoadEndAddr
;
1099 *ldraddr
= MBHloadAddr
+l
+10;
1100 *ldrdest
= RDFLDR_DESTLOC
;
1103 rdfwriteheader(f
, rdfheader
);
1104 rdfdoneheader(rdfheader
);
1106 * Step through the segments, one at a time, writing out into
1110 for (i
= 0; i
< nsegs
; i
++)
1115 if (i
== 2) continue;
1117 s
= translateshort(outputseg
[i
].type
);
1118 fwrite(&s
, 2, 1, f
);
1119 s
= translateshort(outputseg
[i
].number
);
1120 fwrite(&s
, 2, 1, f
);
1121 s
= translateshort(outputseg
[i
].reserved
);
1122 fwrite(&s
, 2, 1, f
);
1123 l
= translatelong(outputseg
[i
].length
);
1124 fwrite(&l
, 4, 1, f
);
1126 fwrite(outputseg
[i
].data
, outputseg
[i
].length
, 1, f
);
1129 fwrite("\0\0\0\0\0\0\0\0\0\0", 10, 1, f
);
1132 /* =========================================================================
1139 printf(" ldrdf [options] object modules ... [-llibrary ...]\n");
1140 printf(" ldrdf -r\n");
1141 printf("options:\n");
1142 printf(" -v[=n] increases verbosity by 1, or sets it to n\n");
1143 printf(" -a nn sets segment alignment value (default 16)\n");
1144 printf(" -s strips exported symbols\n");
1145 printf(" -x warn about unresolved symbols\n");
1146 printf(" -o name write output in file 'name'\n");
1147 printf(" -j path specify objects search path\n");
1148 printf(" -L path specify libraries search path\n");
1149 printf(" -mbh [address] add multiboot header to output file. Default\n");
1150 printf(" loading address is 0x110000\n");
1154 int main(int argc
, char ** argv
)
1156 char * outname
= "aout.rdf";
1157 int moduleloaded
= 0;
1158 char *respstrings
[128] = {0, };
1160 options
.verbose
= 0;
1162 options
.warnUnresolved
= 0;
1165 error_file
= stderr
;
1168 if (argc
== 0) usage();
1169 while (argc
&& **argv
== '-' && argv
[0][1] != 'l')
1171 switch(argv
[0][1]) {
1173 printf("ldrdf (linker for RDF files) version " LDRDF_VERSION
"\n");
1174 printf( _RDOFF_H
"\n");
1177 if (argv
[0][2] == '=') {
1178 options
.verbose
= argv
[0][3] - '0';
1179 if (options
.verbose
< 0 || options
.verbose
> 9) {
1180 fprintf(stderr
, "ldrdf: verbosity level must be a number"
1181 " between 0 and 9\n");
1189 options
.align
= atoi(argv
[1]);
1190 if (options
.align
<= 0) {
1192 "ldrdf: -a expects a positive number argument\n");
1201 options
.warnUnresolved
= 1;
1202 if (argv
[0][2]=='e')
1203 options
.errorUnresolved
= 1;
1212 options
.objpath
= 1;
1219 fprintf(stderr
,"ldrdf: more than one objects search path specified\n");
1225 options
.libpath
= 1;
1232 fprintf(stderr
,"ldrdf: more than one libraries search path specified\n");
1240 options
.respfile
= 1;
1241 if (argv
[1] != NULL
) f
= fopen(argv
[1],"r");
1244 fprintf(stderr
,"ldrdf: no response file name specified\n");
1250 fprintf(stderr
,"ldrdf: unable to open response file\n");
1254 while(fgets(buf
,sizeof(buf
)-1,f
)!=NULL
)
1257 if (buf
[0]=='\n') continue;
1258 if ((p
= strchr(buf
,'\n')) != 0)
1262 fprintf(stderr
,"ldrdf: too many input files\n");
1265 *(respstrings
+i
) = newstr(buf
);
1271 options
.stderr_redir
= 1;
1272 error_file
= stdout
;
1275 if (argv
[0][2] == 'b' && argv
[0][3] == 'h') {
1276 if (argv
[1][0] != '-') {
1277 MBHloadAddr
= atoi(argv
[1]);
1279 MBHloadAddr
= MB_DEFAULTLOADADDR
;
1281 options
.addMBheader
= 1;
1290 if (options
.verbose
> 4) {
1291 printf("ldrdf invoked with options:\n");
1292 printf(" section alignment: %d bytes\n", options
.align
);
1293 printf(" output name: `%s'\n", outname
);
1295 printf(" strip symbols\n");
1296 if (options
.warnUnresolved
)
1297 printf(" warn about unresolved symbols\n");
1298 if (options
.errorUnresolved
)
1299 printf(" error if unresolved symbols\n");
1300 if (options
.objpath
)
1301 printf(" objects search path: %s\n",objpath
);
1302 if (options
.libpath
)
1303 printf(" libraries search path: %s\n",libpath
);
1304 if (options
.addMBheader
)
1305 printf(" loading address for multiboot header: 0x%X\n",MBHloadAddr
);
1309 symtab
= symtabNew();
1313 fprintf(stderr
, "ldrdf: out of memory\n");
1317 if (*respstrings
) argv
= respstrings
;
1320 if (!strncmp(*argv
, "-l", 2)) /* library */
1322 if(libpath
) add_library(newstrcat(libpath
,*argv
+ 2));
1323 else add_library(*argv
+ 2);
1326 if(objpath
) loadmodule(newstrcat(objpath
,*argv
));
1327 else loadmodule(*argv
);
1333 if (! moduleloaded
) {
1334 printf("ldrdf: nothing to do. ldrdf -h for usage\n");
1341 if (options
.verbose
> 2)
1343 printf ("symbol table:\n");
1344 symtabDump(symtab
, stdout
);
1347 write_output(outname
);
1349 if (errorcount
> 0) exit(1);