1 /* ----------------------------------------------------------------------- *
3 * Copyright 1996-2014 The NASM Authors - All Rights Reserved
4 * See the file AUTHORS included with the NASM distribution for
5 * the specific copyright holders.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
19 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
20 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 * ----------------------------------------------------------------------- */
35 * ldrdf.c - RDOFF Object File linker/loader main program.
40 * - enhance search of required export symbols in libraries (now depends
41 * on modules order in library)
42 * - keep a cache of symbol names in each library module so
43 * we don't have to constantly recheck the file
44 * - general performance improvements
46 * BUGS & LIMITATIONS: this program doesn't support multiple code, data
47 * or bss segments, therefore for 16 bit programs whose code, data or BSS
48 * segment exceeds 64K in size, it will not work. This program probably
49 * won't work if compiled by a 16 bit compiler. Try DJGPP if you're running
50 * under DOS. '#define STINGY_MEMORY' may help a little.
66 #define LDRDF_VERSION "1.08"
68 /* #define STINGY_MEMORY */
70 /* =======================================================================
71 * Types & macros that are private to this program
74 struct segment_infonode
{
75 int dest_seg
; /* output segment to be placed into, -1 to
76 skip linking this segment */
77 int32_t reloc
; /* segment's relocation factor */
81 rdffile f
; /* the RDOFF file structure */
82 struct segment_infonode seginfo
[RDF_MAXSEGS
]; /* what are we doing
86 struct modulenode
*next
;
92 /* ==========================================================================
93 * Function prototypes of private utility functions
96 void processmodule(const char *filename
, struct modulenode
*mod
);
97 int allocnewseg(uint16_t type
, uint16_t reserved
);
98 int findsegment(uint16_t type
, uint16_t reserved
);
99 void symtab_add(const char *symbol
, int segment
, int32_t offset
);
100 int symtab_get(const char *symbol
, int *segment
, int32_t *offset
);
102 /* =========================================================================
103 * Global data structures.
106 /* a linked list of modules that will be included in the output */
107 struct modulenode
*modules
= NULL
;
108 struct modulenode
*lastmodule
= NULL
;
110 /* a linked list of libraries to be searched for unresolved imported symbols */
111 struct librarynode
*libraries
= NULL
;
112 struct librarynode
*lastlib
= NULL
;
114 /* the symbol table */
117 /* objects search path */
118 char *objpath
= NULL
;
120 /* libraries search path */
121 char *libpath
= NULL
;
123 /* file to embed as a generic record */
124 char *generic_rec_file
= NULL
;
126 /* module name to be added at the beginning of output file */
127 char *modname_specified
= NULL
;
130 static FILE *error_file
;
132 /* the header of the output file, built up stage by stage */
133 rdf_headerbuf
*newheader
= NULL
;
135 /* The current state of segment allocation, including information about
136 * which output segment numbers have been allocated, and their types and
137 * amount of data which has already been allocated inside them.
139 struct SegmentHeaderRec outputseg
[RDF_MAXSEGS
];
143 /* global options which affect how the program behaves */
144 struct ldrdfoptions
{
155 int errorcount
= 0; /* determines main program exit status */
157 /* =========================================================================
164 * sets up segments 0, 1, and 2, the initial code data and bss segments
166 static void initsegments(void)
169 outputseg
[0].type
= 1;
170 outputseg
[0].number
= 0;
171 outputseg
[0].reserved
= 0;
172 outputseg
[0].length
= 0;
173 outputseg
[1].type
= 2;
174 outputseg
[1].number
= 1;
175 outputseg
[1].reserved
= 0;
176 outputseg
[1].length
= 0;
177 outputseg
[2].type
= 0xFFFF; /* reserved segment type */
178 outputseg
[2].number
= 2;
179 outputseg
[2].reserved
= 0;
180 outputseg
[2].length
= 0;
187 * Determine the characteristics of a module, and decide what to do with
188 * each segment it contains (including determining destination segments and
189 * relocation factors for segments that are kept).
191 static void loadmodule(const char *filename
)
194 printf("loading `%s'\n", filename
);
196 /* allocate a new module entry on the end of the modules list */
198 modules
= nasm_malloc(sizeof(*modules
));
199 lastmodule
= modules
;
201 lastmodule
->next
= nasm_malloc(sizeof(*modules
));
202 lastmodule
= lastmodule
->next
;
206 fprintf(stderr
, "ldrdf: out of memory\n");
210 /* open the file using 'rdfopen', which returns nonzero on error */
211 if (rdfopen(&lastmodule
->f
, filename
) != 0) {
212 rdfperror("ldrdf", filename
);
217 * store information about the module, and determine what segments
218 * it contains, and what we should do with them (determine relocation
219 * factor if we decide to keep them)
221 lastmodule
->header
= NULL
;
222 lastmodule
->name
= nasm_strdup(filename
);
223 lastmodule
->next
= NULL
;
225 processmodule(filename
, lastmodule
);
231 * step through each segment, determine what exactly we're doing with
232 * it, and if we intend to keep it, determine (a) which segment to
233 * put it in and (b) whereabouts in that segment it will end up.
234 * (b) is fairly easy, because we're now keeping track of how big each
235 * segment in our output file is...
237 void processmodule(const char *filename
, struct modulenode
*mod
)
239 struct segconfig sconf
;
243 int32_t bssamount
= 0;
244 int bss_was_referenced
= 0;
246 memset(&sconf
, 0, sizeof sconf
);
248 for (seg
= 0; seg
< mod
->f
.nsegs
; seg
++) {
250 * get the segment configuration for this type from the segment
251 * table. getsegconfig() is a macro, defined in ldsegs.h.
253 getsegconfig(sconf
, mod
->f
.seg
[seg
].type
);
255 if (options
.verbose
> 1) {
256 printf("%s %04x [%04x:%10s] ", filename
,
257 mod
->f
.seg
[seg
].number
, mod
->f
.seg
[seg
].type
,
261 * sconf->dowhat tells us what to do with a segment of this type.
263 switch (sconf
.dowhat
) {
266 * Set destination segment to -1, to indicate that this segment
267 * should be ignored for the purpose of output, ie it is left
268 * out of the linked executable.
270 mod
->seginfo
[seg
].dest_seg
= -1;
271 if (options
.verbose
> 1)
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:%08"PRIx32
" (+%04"PRIx32
")\n", outseg
,
287 mod
->seginfo
[seg
].reloc
, mod
->f
.seg
[seg
].length
);
292 * The configuration tells us to merge the segment with
293 * a previously existing segment of type 'sconf.mergetype',
294 * if one exists. Otherwise a new segment is created.
295 * This is handled transparently by 'findsegment()'.
297 outseg
= findsegment(sconf
.mergetype
,
298 mod
->f
.seg
[seg
].reserved
);
299 mod
->seginfo
[seg
].dest_seg
= outseg
;
302 * We need to add alignment to these segments.
304 if (outputseg
[outseg
].length
% options
.align
!= 0)
305 outputseg
[outseg
].length
+=
307 (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:%08"PRIx32
" (+%04"PRIx32
")\n", outseg
,
314 mod
->seginfo
[seg
].reloc
, mod
->f
.seg
[seg
].length
);
320 * extract symbols from the header, and dump them into the
323 header
= nasm_malloc(mod
->f
.header_len
);
325 fprintf(stderr
, "ldrdf: not enough memory\n");
328 if (rdfloadseg(&mod
->f
, RDOFF_HEADER
, header
)) {
329 rdfperror("ldrdf", filename
);
333 while ((hr
= rdfgetheaderrec(&mod
->f
))) {
335 case RDFREC_IMPORT
: /* imported symbol */
336 case RDFREC_FARIMPORT
:
337 /* Define with seg = -1 */
338 symtab_add(hr
->i
.label
, -1, 0);
341 case RDFREC_GLOBAL
:{ /* exported symbol */
345 if (hr
->e
.segment
== 2) {
346 bss_was_referenced
= 1;
347 destreloc
= bss_length
;
348 if (destreloc
% options
.align
!= 0)
350 options
.align
- (destreloc
% options
.align
);
354 mod
->seginfo
[(int)hr
->e
.segment
].dest_seg
) == -1)
356 destreloc
= mod
->seginfo
[(int)hr
->e
.segment
].reloc
;
358 symtab_add(hr
->e
.label
, destseg
, destreloc
+ hr
->e
.offset
);
362 case RDFREC_BSS
: /* BSS reservation */
364 * first, amalgamate all BSS reservations in this module
365 * into one, because we allow this in the output format.
367 bssamount
+= hr
->b
.amount
;
370 case RDFREC_COMMON
:{ /* Common variable */
371 symtabEnt
*ste
= symtabFind(symtab
, hr
->c
.label
);
373 /* Is the symbol already in the table? */
377 /* Align the variable */
378 if (bss_length
% hr
->c
.align
!= 0)
379 bss_length
+= hr
->c
.align
- (bss_length
% hr
->c
.align
);
380 if (options
.verbose
> 1) {
381 printf("%s %04x common '%s' => 0002:%08"PRIx32
" (+%04"PRIx32
")\n",
382 filename
, hr
->c
.segment
, hr
->c
.label
,
383 bss_length
, hr
->c
.size
);
386 symtab_add(hr
->c
.label
, 2, bss_length
);
387 mod
->bss_reloc
= bss_length
;
388 bss_length
+= hr
->c
.size
;
394 if (bssamount
!= 0 || bss_was_referenced
) {
396 * handle the BSS segment - first pad the existing bss length
397 * to the correct alignment, then store the length in bss_reloc
398 * for this module. Then add this module's BSS length onto
401 if (bss_length
% options
.align
!= 0)
402 bss_length
+= options
.align
- (bss_length
% options
.align
);
404 mod
->bss_reloc
= bss_length
;
405 if (options
.verbose
> 1) {
406 printf("%s 0002 [ BSS] => 0002:%08"PRIx32
" (+%04"PRIx32
")\n",
407 filename
, bss_length
, bssamount
);
409 bss_length
+= bssamount
;
413 * we free the header buffer here, to save memory later.
414 * this isn't efficient, but probably halves the memory usage
417 mod
->f
.header_loc
= NULL
;
425 * Return 1 if a given module is in the list, 0 otherwise.
427 static int lookformodule(const char *name
)
429 struct modulenode
*curr
= modules
;
432 if (!strcmp(name
, curr
->name
))
443 * These functions manipulate the array of output segments, and are used
444 * by processmodule(). allocnewseg() allocates a segment in the array,
445 * initialising it to be empty. findsegment() first scans the array for
446 * a segment of the type requested, and if one isn't found allocates a
449 int allocnewseg(uint16_t type
, uint16_t reserved
)
451 outputseg
[nsegs
].type
= type
;
452 outputseg
[nsegs
].number
= nsegs
;
453 outputseg
[nsegs
].reserved
= reserved
;
454 outputseg
[nsegs
].length
= 0;
455 outputseg
[nsegs
].offset
= 0;
456 outputseg
[nsegs
].data
= NULL
;
461 int findsegment(uint16_t type
, uint16_t reserved
)
465 for (i
= 0; i
< nsegs
; i
++)
466 if (outputseg
[i
].type
== type
)
469 return allocnewseg(type
, reserved
);
475 * inserts a symbol into the global symbol table, which associates symbol
476 * names either with addresses, or a marker that the symbol hasn't been
477 * resolved yet, or possibly that the symbol has been defined as
478 * contained in a dynamic [load time/run time] linked library.
480 * segment = -1 => not yet defined
481 * segment = -2 => defined as dll symbol
483 * If the symbol is already defined, and the new segment >= 0, then
484 * if the original segment was < 0 the symbol is redefined, otherwise
485 * a duplicate symbol warning is issued. If new segment == -1, this
486 * routine won't change a previously existing symbol. It will change
487 * to segment = -2 only if the segment was previously < 0.
489 void symtab_add(const char *symbol
, int segment
, int32_t offset
)
493 ste
= symtabFind(symtab
, symbol
);
495 if (ste
->segment
>= 0) {
497 * symbol previously defined
501 fprintf(error_file
, "warning: `%s' redefined\n", symbol
);
506 * somebody wanted the symbol, and put an undefined symbol
507 * marker into the table
512 * we have more information now - update the symbol's entry
514 ste
->segment
= segment
;
515 ste
->offset
= offset
;
520 * this is the first declaration of this symbol
522 ste
= nasm_malloc(sizeof(symtabEnt
));
524 fprintf(stderr
, "ldrdf: out of memory\n");
527 ste
->name
= nasm_strdup(symbol
);
528 ste
->segment
= segment
;
529 ste
->offset
= offset
;
531 symtabInsert(symtab
, ste
);
537 * Retrieves the values associated with a symbol. Undefined symbols
538 * are assumed to have -1:0 associated. Returns 1 if the symbol was
539 * successfully located.
541 int symtab_get(const char *symbol
, int *segment
, int32_t *offset
)
543 symtabEnt
*ste
= symtabFind(symtab
, symbol
);
549 *segment
= ste
->segment
;
550 *offset
= ste
->offset
;
558 * checks that a library can be opened and is in the correct format,
559 * then adds it to the linked list of libraries.
561 static void add_library(const char *name
)
563 if (rdl_verify(name
)) {
564 rdl_perror("ldrdf", name
);
569 lastlib
= libraries
= nasm_malloc(sizeof(*libraries
));
571 fprintf(stderr
, "ldrdf: out of memory\n");
575 lastlib
->next
= nasm_malloc(sizeof(*libraries
));
576 if (!lastlib
->next
) {
577 fprintf(stderr
, "ldrdf: out of memory\n");
580 lastlib
= lastlib
->next
;
582 lastlib
->next
= NULL
;
583 if (rdl_open(lastlib
, name
)) {
584 rdl_perror("ldrdf", name
);
593 * scans through the list of libraries, attempting to match symbols
594 * defined in library modules against symbols that are referenced but
595 * not defined (segment = -1 in the symbol table)
597 * returns 1 if any extra library modules are included, indicating that
598 * another pass through the library list should be made (possibly).
600 static int search_libraries(void)
602 struct librarynode
*cur
;
608 int doneanything
= 0, pass
= 1, keepfile
;
614 if (options
.verbose
> 2)
615 printf("scanning library `%s', pass %d...\n", cur
->name
, pass
);
617 for (i
= 0; rdl_openmodule(cur
, i
, &f
) == 0; i
++) {
618 if (pass
== 2 && lookformodule(f
.name
))
621 if (options
.verbose
> 3)
622 printf(" looking in module `%s'\n", f
.name
);
624 header
= nasm_malloc(f
.header_len
);
626 fprintf(stderr
, "ldrdf: not enough memory\n");
629 if (rdfloadseg(&f
, RDOFF_HEADER
, header
)) {
630 rdfperror("ldrdf", f
.name
);
637 while ((hr
= rdfgetheaderrec(&f
))) {
638 /* We're only interested in exports, so skip others */
639 if (hr
->type
!= RDFREC_GLOBAL
)
643 * If the symbol is marked as SYM_GLOBAL, somebody will be
644 * definitely interested in it..
646 if ((hr
->e
.flags
& SYM_GLOBAL
) == 0) {
648 * otherwise the symbol is just public. Find it in
649 * the symbol table. If the symbol isn't defined, we
650 * aren't interested, so go on to the next.
651 * If it is defined as anything but -1, we're also not
652 * interested. But if it is defined as -1, insert this
653 * module into the list of modules to use, and go
654 * immediately on to the next module...
656 if (!symtab_get(hr
->e
.label
, &segment
, &offset
)
665 * as there are undefined symbols, we can assume that
666 * there are modules on the module list by the time
669 lastmodule
->next
= nasm_malloc(sizeof(*lastmodule
->next
));
670 if (!lastmodule
->next
) {
671 fprintf(stderr
, "ldrdf: not enough memory\n");
674 lastmodule
= lastmodule
->next
;
675 memcpy(&lastmodule
->f
, &f
, sizeof(f
));
676 lastmodule
->name
= nasm_strdup(f
.name
);
677 lastmodule
->next
= NULL
;
678 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 static void write_output(const char *filename
)
710 rdf_headerbuf
*rdfheader
;
711 struct modulenode
*cur
;
712 int i
, n
, 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 * If '-g' option was given, first record in output file will be a
731 * `generic' record, filled with a given file content.
732 * This can be useful, for example, when constructing multiboot
735 if (generic_rec_file
) {
739 printf("\nadding generic record from binary file %s\n",
742 hr
= (rdfheaderrec
*) nasm_malloc(sizeof(struct GenericRec
));
743 if ((ff
= fopen(generic_rec_file
, "r")) == NULL
) {
744 fprintf(stderr
, "ldrdf: couldn't open %s for input\n",
748 n
= fread(hr
->g
.data
, 1, sizeof(hr
->g
.data
), ff
);
749 fseek(ff
, 0, SEEK_END
);
750 if (ftell(ff
) > (long)sizeof(hr
->g
.data
)) {
752 "warning: maximum generic record size is %u, "
753 "rest of file ignored\n",
754 (unsigned int)sizeof(hr
->g
.data
));
758 hr
->g
.type
= RDFREC_GENERIC
;
760 rdfaddheader(rdfheader
, hr
);
765 * Add module name record if `-mn' option was given
767 if (modname_specified
) {
768 n
= strlen(modname_specified
);
770 if ((n
< 1) || (n
>= MODLIB_NAME_MAX
)) {
771 fprintf(stderr
, "ldrdf: invalid length of module name `%s'\n",
777 printf("\nadding module name record %s\n", modname_specified
);
779 hr
= (rdfheaderrec
*) nasm_malloc(sizeof(struct ModRec
));
780 hr
->m
.type
= RDFREC_MODNAME
;
781 hr
->m
.reclen
= n
+ 1;
782 strcpy(hr
->m
.modname
, modname_specified
);
783 rdfaddheader(rdfheader
, hr
);
789 printf("\nbuilding output module (%d segments)\n", nsegs
);
792 * Allocate the memory for the segments. We may be better off
793 * building the output module one segment at a time when running
794 * under 16 bit DOS, but that would be a slower way of doing this.
795 * And you could always use DJGPP...
797 for (i
= 0; i
< nsegs
; i
++) {
798 outputseg
[i
].data
= NULL
;
799 if (!outputseg
[i
].length
)
801 outputseg
[i
].data
= nasm_malloc(outputseg
[i
].length
);
802 if (!outputseg
[i
].data
) {
803 fprintf(stderr
, "ldrdf: out of memory\n");
809 * initialise availableseg, used to allocate segment numbers for
810 * imported and exported labels...
812 availableseg
= nsegs
;
815 * Step through the modules, performing required actions on each one
817 for (cur
= modules
; cur
; cur
= cur
->next
) {
819 * Read the actual segment contents into the correct places in
820 * the newly allocated segments
823 for (i
= 0; i
< cur
->f
.nsegs
; i
++) {
824 int dest
= cur
->seginfo
[i
].dest_seg
;
828 if (rdfloadseg(&cur
->f
, i
,
829 outputseg
[dest
].data
+ cur
->seginfo
[i
].reloc
)) {
830 rdfperror("ldrdf", cur
->name
);
836 * Perform fixups, and add new header records where required
839 header
= nasm_malloc(cur
->f
.header_len
);
841 fprintf(stderr
, "ldrdf: out of memory\n");
845 if (cur
->f
.header_loc
)
846 rdfheaderrewind(&cur
->f
);
847 else if (rdfloadseg(&cur
->f
, RDOFF_HEADER
, header
)) {
848 rdfperror("ldrdf", cur
->name
);
853 * we need to create a local segment number -> location
854 * table for the segments in this module.
856 init_seglocations(&segs
);
857 for (i
= 0; i
< cur
->f
.nsegs
; i
++) {
858 add_seglocation(&segs
, cur
->f
.seg
[i
].number
,
859 cur
->seginfo
[i
].dest_seg
,
860 cur
->seginfo
[i
].reloc
);
863 * and the BSS segment (doh!)
865 add_seglocation(&segs
, 2, 2, cur
->bss_reloc
);
867 while ((hr
= rdfgetheaderrec(&cur
->f
))) {
869 case RDFREC_RELOC
: /* relocation record - need to do a fixup */
871 * First correct the offset stored in the segment from
872 * the start of the segment (which may well have changed).
874 * To do this we add to the number stored the relocation
875 * factor associated with the segment that contains the
878 * The relocation could be a relative relocation, in which
879 * case we have to first subtract the amount we've relocated
880 * the containing segment by.
882 if (!get_seglocation(&segs
, hr
->r
.refseg
, &seg
, &offset
)) {
884 "%s: reloc to undefined segment %04x\n",
885 cur
->name
, (int)hr
->r
.refseg
);
891 (hr
->r
.segment
& RDOFF_RELATIVEMASK
) ==
893 hr
->r
.segment
&= (RDOFF_RELATIVEMASK
- 1);
895 if (hr
->r
.segment
== 2 ||
897 rdffindsegment(&cur
->f
, hr
->r
.segment
)) == -1) {
898 fprintf(stderr
, "%s: reloc from %s segment (%d)\n",
900 hr
->r
.segment
== 2 ? "BSS" : "unknown",
906 if (hr
->r
.length
!= 1 && hr
->r
.length
!= 2 &&
908 fprintf(stderr
, "%s: nonstandard length reloc "
909 "(%d bytes)\n", cur
->name
, hr
->r
.length
);
915 * okay, now the relocation is in the segment pointed to by
916 * cur->seginfo[localseg], and we know everything else is
917 * okay to go ahead and do the relocation
919 data
= outputseg
[cur
->seginfo
[localseg
].dest_seg
].data
;
920 data
+= cur
->seginfo
[localseg
].reloc
+ hr
->r
.offset
;
923 * data now points to the reference that needs
924 * relocation. Calculate the relocation factor.
926 * offset of referred object in segment [in offset]
927 * (- relocation of localseg, if ref is relative)
928 * For simplicity, the result is stored in 'offset'.
929 * Then add 'offset' onto the value at data.
933 offset
-= cur
->seginfo
[localseg
].reloc
;
934 switch (hr
->r
.length
) {
937 if (offset
< -127 || offset
> 128)
939 "warning: relocation out of range "
940 "at %s(%02x:%08"PRIx32
")\n", cur
->name
,
941 (int)hr
->r
.segment
, hr
->r
.offset
);
942 *data
= (char)offset
;
945 offset
+= *(int16_t *)data
;
946 if (offset
< -32767 || offset
> 32768)
948 "warning: relocation out of range "
949 "at %s(%02x:%08"PRIx32
")\n", cur
->name
,
950 (int)hr
->r
.segment
, hr
->r
.offset
);
951 *(int16_t *)data
= (int16_t)offset
;
954 *(int32_t *)data
+= offset
;
955 /* we can't easily detect overflow on this one */
960 * If the relocation was relative between two symbols in
961 * the same segment, then we're done.
963 * Otherwise, we need to output a new relocation record
964 * with the references updated segment and offset...
966 if (!isrelative
|| cur
->seginfo
[localseg
].dest_seg
!= seg
) {
967 hr
->r
.segment
= cur
->seginfo
[localseg
].dest_seg
;
968 hr
->r
.offset
+= cur
->seginfo
[localseg
].reloc
;
971 hr
->r
.segment
+= RDOFF_RELATIVEMASK
;
972 rdfaddheader(rdfheader
, hr
);
976 case RDFREC_IMPORT
: /* import symbol */
977 case RDFREC_FARIMPORT
:
979 * scan the global symbol table for the symbol
980 * and associate its location with the segment number
983 se
= symtabFind(symtab
, hr
->i
.label
);
984 if (!se
|| se
->segment
== -1) {
985 if (!options
.dynalink
&& !(hr
->i
.flags
& SYM_IMPORT
)) {
987 "error: unresolved reference to `%s'"
988 " in module `%s'\n", hr
->i
.label
,
993 * we need to allocate a segment number for this
994 * symbol, and store it in the symbol table for
998 se
= nasm_malloc(sizeof(*se
));
1000 fprintf(stderr
, "ldrdf: out of memory\n");
1003 se
->name
= nasm_strdup(hr
->i
.label
);
1005 se
->segment
= availableseg
++;
1007 symtabInsert(symtab
, se
);
1009 se
->segment
= availableseg
++;
1013 * output a header record that imports it to the
1014 * recently allocated segment number...
1017 newrec
.i
.segment
= se
->segment
;
1018 rdfaddheader(rdfheader
, &newrec
);
1021 add_seglocation(&segs
, hr
->i
.segment
, se
->segment
,
1025 case RDFREC_GLOBAL
: /* export symbol */
1027 * need to insert an export for this symbol into the new
1028 * header, unless we're stripping symbols. Even if we're
1029 * stripping, put the symbol if it's marked as SYM_GLOBAL.
1031 if (options
.strip
&& !(hr
->e
.flags
& SYM_GLOBAL
))
1034 if (hr
->e
.segment
== 2) {
1036 offset
= cur
->bss_reloc
;
1038 localseg
= rdffindsegment(&cur
->f
, hr
->e
.segment
);
1039 if (localseg
== -1) {
1040 fprintf(stderr
, "%s: exported symbol `%s' from "
1041 "unrecognised segment\n", cur
->name
,
1046 offset
= cur
->seginfo
[localseg
].reloc
;
1047 seg
= cur
->seginfo
[localseg
].dest_seg
;
1050 hr
->e
.segment
= seg
;
1051 hr
->e
.offset
+= offset
;
1052 rdfaddheader(rdfheader
, hr
);
1055 case RDFREC_MODNAME
: /* module name */
1057 * Insert module name record if export symbols
1059 * If module name begins with '$' - insert it anyway.
1061 if (options
.strip
&& hr
->m
.modname
[0] != '$')
1063 rdfaddheader(rdfheader
, hr
);
1066 case RDFREC_DLL
: /* DLL name */
1068 * Insert DLL name if it begins with '$'
1070 if (hr
->d
.libname
[0] != '$')
1072 rdfaddheader(rdfheader
, hr
);
1075 case RDFREC_SEGRELOC
: /* segment fixup */
1077 * modify the segment numbers if necessary, and
1078 * pass straight through to the output module header
1082 if (hr
->r
.segment
== 2) {
1083 fprintf(stderr
, "%s: segment fixup in BSS section\n",
1088 localseg
= rdffindsegment(&cur
->f
, hr
->r
.segment
);
1089 if (localseg
== -1) {
1090 fprintf(stderr
, "%s: segment fixup in unrecognised"
1091 " segment (%d)\n", cur
->name
, hr
->r
.segment
);
1095 hr
->r
.segment
= cur
->seginfo
[localseg
].dest_seg
;
1096 hr
->r
.offset
+= cur
->seginfo
[localseg
].reloc
;
1098 if (!get_seglocation(&segs
, hr
->r
.refseg
, &seg
, &offset
)) {
1099 fprintf(stderr
, "%s: segment fixup to undefined "
1100 "segment %04x\n", cur
->name
,
1106 rdfaddheader(rdfheader
, hr
);
1109 case RDFREC_COMMON
: /* Common variable */
1110 /* Is this symbol already in the table? */
1111 se
= symtabFind(symtab
, hr
->c
.label
);
1113 printf("%s is not in symtab yet\n", hr
->c
.label
);
1116 /* Add segment location */
1117 add_seglocation(&segs
, hr
->c
.segment
, se
->segment
,
1124 done_seglocations(&segs
);
1129 * combined BSS reservation for the entire results
1131 newrec
.type
= RDFREC_BSS
;
1132 newrec
.b
.reclen
= 4;
1133 newrec
.b
.amount
= bss_length
;
1134 rdfaddheader(rdfheader
, &newrec
);
1139 for (i
= 0; i
< nsegs
; i
++) {
1142 rdfaddsegment(rdfheader
, outputseg
[i
].length
);
1145 rdfwriteheader(f
, rdfheader
);
1146 rdfdoneheader(rdfheader
);
1149 * Step through the segments, one at a time, writing out into
1152 for (i
= 0; i
< nsegs
; i
++) {
1156 fwriteint16_t(outputseg
[i
].type
, f
);
1157 fwriteint16_t(outputseg
[i
].number
, f
);
1158 fwriteint16_t(outputseg
[i
].reserved
, f
);
1159 fwriteint32_t(outputseg
[i
].length
, f
);
1160 nasm_write(outputseg
[i
].data
, outputseg
[i
].length
, f
);
1166 /* =========================================================================
1170 static void usage(void)
1173 " ldrdf [options] object modules ... [-llibrary ...]\n"
1176 " -v[=n] increase verbosity by 1, or set it to n\n"
1177 " -a nn set segment alignment value (default 16)\n"
1178 " -s strip public symbols\n"
1179 " -dy Unix-style dynamic linking\n"
1180 " -o name write output in file 'name'\n"
1181 " -j path specify objects search path\n"
1182 " -L path specify libraries search path\n"
1183 " -g file embed 'file' as a first header record with type 'generic'\n"
1184 " -mn name add module name record at the beginning of output file\n");
1188 int main(int argc
, char **argv
)
1190 char *outname
= "aout.rdf";
1191 int moduleloaded
= 0;
1192 char *respstrings
[128] = { 0, };
1196 options
.verbose
= 0;
1198 options
.dynalink
= 0;
1201 error_file
= stderr
;
1206 while (argc
&& *argv
&& **argv
== '-' && argv
[0][1] != 'l') {
1207 switch (argv
[0][1]) {
1209 printf("ldrdf (linker for RDF files) version " LDRDF_VERSION
1211 printf("RDOFF2 revision %s\n", RDOFF2_REVISION
);
1214 if (argv
[0][2] == '=') {
1215 options
.verbose
= argv
[0][3] - '0';
1216 if (options
.verbose
< 0 || options
.verbose
> 9) {
1218 "ldrdf: verbosity level must be a number"
1219 " between 0 and 9\n");
1226 options
.align
= atoi(argv
[1]);
1227 if (options
.align
<= 0) {
1229 "ldrdf: -a expects a positive number argument\n");
1238 if (argv
[0][2] == 'y')
1239 options
.dynalink
= 1;
1242 if (argv
[0][2] == 'n') {
1243 modname_specified
= argv
[1];
1246 fprintf(stderr
, "ldrdf: -mn expects a module name\n");
1257 options
.objpath
= 1;
1263 "ldrdf: more than one objects search path specified\n");
1268 options
.libpath
= 1;
1274 "ldrdf: more than one libraries search path specified\n");
1282 options
.respfile
= 1;
1283 if (argv
[1] != NULL
)
1284 f
= fopen(argv
[1], "r");
1287 "ldrdf: no response file name specified\n");
1293 "ldrdf: unable to open response file\n");
1298 while (fgets(buf
, sizeof(buf
), f
) != NULL
) {
1302 if ((p
= strchr(buf
, '\n')) != NULL
)
1306 fprintf(stderr
, "ldrdf: too many input files\n");
1309 *(respstrings
+ i
) = nasm_strdup(buf
);
1316 options
.stderr_redir
= 1;
1317 error_file
= stdout
;
1320 generic_rec_file
= argv
[1];
1323 fprintf(stderr
, "ldrdf: -g expects a file name\n");
1333 if (options
.verbose
> 4) {
1334 printf("ldrdf invoked with options:\n");
1335 printf(" section alignment: %d bytes\n", options
.align
);
1336 printf(" output name: `%s'\n", outname
);
1338 printf(" strip symbols\n");
1339 if (options
.dynalink
)
1340 printf(" Unix-style dynamic linking\n");
1341 if (options
.objpath
)
1342 printf(" objects search path: %s\n", objpath
);
1343 if (options
.libpath
)
1344 printf(" libraries search path: %s\n", libpath
);
1348 symtab
= symtabNew();
1352 fprintf(stderr
, "ldrdf: out of memory\n");
1361 if (!strncmp(*argv
, "-l", 2)) {
1362 if (libpath
&& (argv
[0][2] != '/'))
1363 add_library(nasm_strcat(libpath
, *argv
+ 2));
1365 add_library(*argv
+ 2);
1367 if (objpath
&& (argv
[0][0] != '/'))
1368 loadmodule(nasm_strcat(objpath
, *argv
));
1376 if (!moduleloaded
) {
1377 printf("ldrdf: nothing to do. ldrdf -h for usage\n");
1383 if (options
.verbose
> 2) {
1384 printf("symbol table:\n");
1385 symtabDump(symtab
, stdout
);
1388 write_output(outname
);
1390 if (errorcount
> 0) {