output: macho -- Add support for N_PEXT in macho output
[nasm.git] / rdoff / ldrdf.c
blobdd80d70e852bbebf9a2df91333b0bf8f0e6ee5ff
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
9 * conditions are met:
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.
39 * TODO:
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.
53 #include "compiler.h"
55 #include <stdio.h>
56 #include <stdlib.h>
57 #include <string.h>
59 #include "rdfutils.h"
60 #include "symtab.h"
61 #include "collectn.h"
62 #include "rdlib.h"
63 #include "segtab.h"
64 #include "nasmlib.h"
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 */
80 struct modulenode {
81 rdffile f; /* the RDOFF file structure */
82 struct segment_infonode seginfo[RDF_MAXSEGS]; /* what are we doing
83 with each segment? */
84 void *header;
85 char *name;
86 struct modulenode *next;
87 int32_t bss_reloc;
90 #include "ldsegs.h"
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 */
115 void *symtab = NULL;
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;
129 /* error file */
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];
140 int nsegs = 0;
141 int32_t bss_length;
143 /* global options which affect how the program behaves */
144 struct ldrdfoptions {
145 int verbose;
146 int align;
147 int dynalink;
148 int strip;
149 int respfile;
150 int stderr_redir;
151 int objpath;
152 int libpath;
153 } options;
155 int errorcount = 0; /* determines main program exit status */
157 /* =========================================================================
158 * Utility functions
162 * initsegments()
164 * sets up segments 0, 1, and 2, the initial code data and bss segments
166 static void initsegments(void)
168 nsegs = 3;
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;
181 bss_length = 0;
185 * loadmodule()
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)
193 if (options.verbose)
194 printf("loading `%s'\n", filename);
196 /* allocate a new module entry on the end of the modules list */
197 if (!modules) {
198 modules = nasm_malloc(sizeof(*modules));
199 lastmodule = modules;
200 } else {
201 lastmodule->next = nasm_malloc(sizeof(*modules));
202 lastmodule = lastmodule->next;
205 if (!lastmodule) {
206 fprintf(stderr, "ldrdf: out of memory\n");
207 exit(1);
210 /* open the file using 'rdfopen', which returns nonzero on error */
211 if (rdfopen(&lastmodule->f, filename) != 0) {
212 rdfperror("ldrdf", filename);
213 exit(1);
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);
229 * processmodule()
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;
240 int seg, outseg;
241 void *header;
242 rdfheaderrec *hr;
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,
258 sconf.typedesc);
261 * sconf->dowhat tells us what to do with a segment of this type.
263 switch (sconf.dowhat) {
264 case SEG_IGNORE:
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)
272 printf("IGNORED\n");
273 break;
275 case SEG_NEWSEG:
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);
288 break;
290 case SEG_MERGE:
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 +=
306 options.align -
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
321 * symbol table
323 header = nasm_malloc(mod->f.header_len);
324 if (!header) {
325 fprintf(stderr, "ldrdf: not enough memory\n");
326 exit(1);
328 if (rdfloadseg(&mod->f, RDOFF_HEADER, header)) {
329 rdfperror("ldrdf", filename);
330 exit(1);
333 while ((hr = rdfgetheaderrec(&mod->f))) {
334 switch (hr->type) {
335 case RDFREC_IMPORT: /* imported symbol */
336 case RDFREC_FARIMPORT:
337 /* Define with seg = -1 */
338 symtab_add(hr->i.label, -1, 0);
339 break;
341 case RDFREC_GLOBAL:{ /* exported symbol */
342 int destseg;
343 int32_t destreloc;
345 if (hr->e.segment == 2) {
346 bss_was_referenced = 1;
347 destreloc = bss_length;
348 if (destreloc % options.align != 0)
349 destreloc +=
350 options.align - (destreloc % options.align);
351 destseg = 2;
352 } else {
353 if ((destseg =
354 mod->seginfo[(int)hr->e.segment].dest_seg) == -1)
355 continue;
356 destreloc = mod->seginfo[(int)hr->e.segment].reloc;
358 symtab_add(hr->e.label, destseg, destreloc + hr->e.offset);
359 break;
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;
368 break;
370 case RDFREC_COMMON:{ /* Common variable */
371 symtabEnt *ste = symtabFind(symtab, hr->c.label);
373 /* Is the symbol already in the table? */
374 if (ste)
375 break;
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;
389 break;
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
399 * bss_length.
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;
411 #ifdef STINGY_MEMORY
413 * we free the header buffer here, to save memory later.
414 * this isn't efficient, but probably halves the memory usage
415 * of this program...
417 mod->f.header_loc = NULL;
418 nasm_free(header);
420 #endif
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;
431 while (curr) {
432 if (!strcmp(name, curr->name))
433 return 1;
434 curr = curr->next;
436 return 0;
440 * allocnewseg()
441 * findsegment()
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
447 * new one.
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;
458 return nsegs++;
461 int findsegment(uint16_t type, uint16_t reserved)
463 int i;
465 for (i = 0; i < nsegs; i++)
466 if (outputseg[i].type == type)
467 return i;
469 return allocnewseg(type, reserved);
473 * symtab_add()
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)
491 symtabEnt *ste;
493 ste = symtabFind(symtab, symbol);
494 if (ste) {
495 if (ste->segment >= 0) {
497 * symbol previously defined
499 if (segment < 0)
500 return;
501 fprintf(error_file, "warning: `%s' redefined\n", symbol);
502 return;
506 * somebody wanted the symbol, and put an undefined symbol
507 * marker into the table
509 if (segment == -1)
510 return;
512 * we have more information now - update the symbol's entry
514 ste->segment = segment;
515 ste->offset = offset;
516 ste->flags = 0;
517 return;
520 * this is the first declaration of this symbol
522 ste = nasm_malloc(sizeof(symtabEnt));
523 if (!ste) {
524 fprintf(stderr, "ldrdf: out of memory\n");
525 exit(1);
527 ste->name = nasm_strdup(symbol);
528 ste->segment = segment;
529 ste->offset = offset;
530 ste->flags = 0;
531 symtabInsert(symtab, ste);
535 * symtab_get()
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);
544 if (!ste) {
545 *segment = -1;
546 *offset = 0;
547 return 0;
548 } else {
549 *segment = ste->segment;
550 *offset = ste->offset;
551 return 1;
556 * add_library()
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);
565 errorcount++;
566 return;
568 if (!libraries) {
569 lastlib = libraries = nasm_malloc(sizeof(*libraries));
570 if (!libraries) {
571 fprintf(stderr, "ldrdf: out of memory\n");
572 exit(1);
574 } else {
575 lastlib->next = nasm_malloc(sizeof(*libraries));
576 if (!lastlib->next) {
577 fprintf(stderr, "ldrdf: out of memory\n");
578 exit(1);
580 lastlib = lastlib->next;
582 lastlib->next = NULL;
583 if (rdl_open(lastlib, name)) {
584 rdl_perror("ldrdf", name);
585 errorcount++;
586 return;
591 * search_libraries()
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;
603 rdffile f;
604 int i;
605 void *header;
606 int segment;
607 int32_t offset;
608 int doneanything = 0, pass = 1, keepfile;
609 rdfheaderrec *hr;
611 cur = libraries;
613 while (cur) {
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))
619 continue;
621 if (options.verbose > 3)
622 printf(" looking in module `%s'\n", f.name);
624 header = nasm_malloc(f.header_len);
625 if (!header) {
626 fprintf(stderr, "ldrdf: not enough memory\n");
627 exit(1);
629 if (rdfloadseg(&f, RDOFF_HEADER, header)) {
630 rdfperror("ldrdf", f.name);
631 errorcount++;
632 return 0;
635 keepfile = 0;
637 while ((hr = rdfgetheaderrec(&f))) {
638 /* We're only interested in exports, so skip others */
639 if (hr->type != RDFREC_GLOBAL)
640 continue;
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)
657 || segment != -1)
658 continue;
661 doneanything = 1;
662 keepfile = 1;
665 * as there are undefined symbols, we can assume that
666 * there are modules on the module list by the time
667 * we get here.
669 lastmodule->next = nasm_malloc(sizeof(*lastmodule->next));
670 if (!lastmodule->next) {
671 fprintf(stderr, "ldrdf: not enough memory\n");
672 exit(1);
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);
679 break;
681 if (!keepfile) {
682 nasm_free(f.name);
683 f.name = NULL;
684 f.fp = NULL;
687 if (rdl_error != 0 && rdl_error != RDL_ENOTFOUND)
688 rdl_perror("ldrdf", cur->name);
690 cur = cur->next;
691 if (cur == NULL && pass == 1) {
692 cur = libraries;
693 pass++;
697 return doneanything;
701 * write_output()
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
705 * file.
707 static void write_output(const char *filename)
709 FILE *f;
710 rdf_headerbuf *rdfheader;
711 struct modulenode *cur;
712 int i, n, availableseg, seg, localseg, isrelative;
713 void *header;
714 rdfheaderrec *hr, newrec;
715 symtabEnt *se;
716 segtab segs;
717 int32_t offset;
718 uint8_t *data;
720 if ((f = fopen(filename, "wb")) == NULL) {
721 fprintf(stderr, "ldrdf: couldn't open %s for output\n", filename);
722 exit(1);
724 if ((rdfheader = rdfnewheader()) == NULL) {
725 fprintf(stderr, "ldrdf: out of memory\n");
726 exit(1);
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
733 * compliant kernels.
735 if (generic_rec_file) {
736 FILE *ff;
738 if (options.verbose)
739 printf("\nadding generic record from binary file %s\n",
740 generic_rec_file);
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",
745 generic_rec_file);
746 exit(1);
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)) {
751 fprintf(error_file,
752 "warning: maximum generic record size is %u, "
753 "rest of file ignored\n",
754 (unsigned int)sizeof(hr->g.data));
756 fclose(ff);
758 hr->g.type = RDFREC_GENERIC;
759 hr->g.reclen = n;
760 rdfaddheader(rdfheader, hr);
761 nasm_free(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",
772 modname_specified);
773 exit(1);
776 if (options.verbose)
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);
784 nasm_free(hr);
788 if (options.verbose)
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)
800 continue;
801 outputseg[i].data = nasm_malloc(outputseg[i].length);
802 if (!outputseg[i].data) {
803 fprintf(stderr, "ldrdf: out of memory\n");
804 exit(1);
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;
826 if (dest == -1)
827 continue;
828 if (rdfloadseg(&cur->f, i,
829 outputseg[dest].data + cur->seginfo[i].reloc)) {
830 rdfperror("ldrdf", cur->name);
831 exit(1);
836 * Perform fixups, and add new header records where required
839 header = nasm_malloc(cur->f.header_len);
840 if (!header) {
841 fprintf(stderr, "ldrdf: out of memory\n");
842 exit(1);
845 if (cur->f.header_loc)
846 rdfheaderrewind(&cur->f);
847 else if (rdfloadseg(&cur->f, RDOFF_HEADER, header)) {
848 rdfperror("ldrdf", cur->name);
849 exit(1);
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))) {
868 switch (hr->type) {
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
876 * target segment.
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)) {
883 fprintf(stderr,
884 "%s: reloc to undefined segment %04x\n",
885 cur->name, (int)hr->r.refseg);
886 errorcount++;
887 break;
890 isrelative =
891 (hr->r.segment & RDOFF_RELATIVEMASK) ==
892 RDOFF_RELATIVEMASK;
893 hr->r.segment &= (RDOFF_RELATIVEMASK - 1);
895 if (hr->r.segment == 2 ||
896 (localseg =
897 rdffindsegment(&cur->f, hr->r.segment)) == -1) {
898 fprintf(stderr, "%s: reloc from %s segment (%d)\n",
899 cur->name,
900 hr->r.segment == 2 ? "BSS" : "unknown",
901 hr->r.segment);
902 errorcount++;
903 break;
906 if (hr->r.length != 1 && hr->r.length != 2 &&
907 hr->r.length != 4) {
908 fprintf(stderr, "%s: nonstandard length reloc "
909 "(%d bytes)\n", cur->name, hr->r.length);
910 errorcount++;
911 break;
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.
925 * Factor is:
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.
932 if (isrelative)
933 offset -= cur->seginfo[localseg].reloc;
934 switch (hr->r.length) {
935 case 1:
936 offset += *data;
937 if (offset < -127 || offset > 128)
938 fprintf(error_file,
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;
943 break;
944 case 2:
945 offset += *(int16_t *)data;
946 if (offset < -32767 || offset > 32768)
947 fprintf(error_file,
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;
952 break;
953 case 4:
954 *(int32_t *)data += offset;
955 /* we can't easily detect overflow on this one */
956 break;
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;
969 hr->r.refseg = seg;
970 if (isrelative)
971 hr->r.segment += RDOFF_RELATIVEMASK;
972 rdfaddheader(rdfheader, hr);
974 break;
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
981 * for this module
983 se = symtabFind(symtab, hr->i.label);
984 if (!se || se->segment == -1) {
985 if (!options.dynalink && !(hr->i.flags & SYM_IMPORT)) {
986 fprintf(error_file,
987 "error: unresolved reference to `%s'"
988 " in module `%s'\n", hr->i.label,
989 cur->name);
990 errorcount++;
993 * we need to allocate a segment number for this
994 * symbol, and store it in the symbol table for
995 * future reference
997 if (!se) {
998 se = nasm_malloc(sizeof(*se));
999 if (!se) {
1000 fprintf(stderr, "ldrdf: out of memory\n");
1001 exit(1);
1003 se->name = nasm_strdup(hr->i.label);
1004 se->flags = 0;
1005 se->segment = availableseg++;
1006 se->offset = 0;
1007 symtabInsert(symtab, se);
1008 } else {
1009 se->segment = availableseg++;
1010 se->offset = 0;
1013 * output a header record that imports it to the
1014 * recently allocated segment number...
1016 newrec = *hr;
1017 newrec.i.segment = se->segment;
1018 rdfaddheader(rdfheader, &newrec);
1021 add_seglocation(&segs, hr->i.segment, se->segment,
1022 se->offset);
1023 break;
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))
1032 break;
1034 if (hr->e.segment == 2) {
1035 seg = 2;
1036 offset = cur->bss_reloc;
1037 } else {
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,
1042 hr->e.label);
1043 errorcount++;
1044 break;
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);
1053 break;
1055 case RDFREC_MODNAME: /* module name */
1057 * Insert module name record if export symbols
1058 * are not stripped.
1059 * If module name begins with '$' - insert it anyway.
1061 if (options.strip && hr->m.modname[0] != '$')
1062 break;
1063 rdfaddheader(rdfheader, hr);
1064 break;
1066 case RDFREC_DLL: /* DLL name */
1068 * Insert DLL name if it begins with '$'
1070 if (hr->d.libname[0] != '$')
1071 break;
1072 rdfaddheader(rdfheader, hr);
1073 break;
1075 case RDFREC_SEGRELOC: /* segment fixup */
1077 * modify the segment numbers if necessary, and
1078 * pass straight through to the output module header
1080 * *** FIXME ***
1082 if (hr->r.segment == 2) {
1083 fprintf(stderr, "%s: segment fixup in BSS section\n",
1084 cur->name);
1085 errorcount++;
1086 break;
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);
1092 errorcount++;
1093 break;
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,
1101 (int)hr->r.refseg);
1102 errorcount++;
1103 break;
1105 hr->r.refseg = seg;
1106 rdfaddheader(rdfheader, hr);
1107 break;
1109 case RDFREC_COMMON: /* Common variable */
1110 /* Is this symbol already in the table? */
1111 se = symtabFind(symtab, hr->c.label);
1112 if (!se) {
1113 printf("%s is not in symtab yet\n", hr->c.label);
1114 break;
1116 /* Add segment location */
1117 add_seglocation(&segs, hr->c.segment, se->segment,
1118 se->offset);
1119 break;
1123 nasm_free(header);
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);
1137 * Write the header
1139 for (i = 0; i < nsegs; i++) {
1140 if (i == 2)
1141 continue;
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
1150 * the output file
1152 for (i = 0; i < nsegs; i++) {
1153 if (i == 2)
1154 continue;
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);
1163 fwritezero(10, f);
1166 /* =========================================================================
1167 * Main program
1170 static void usage(void)
1172 printf("usage:\n"
1173 " ldrdf [options] object modules ... [-llibrary ...]\n"
1174 " ldrdf -r\n"
1175 "options:\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");
1185 exit(0);
1188 int main(int argc, char **argv)
1190 char *outname = "aout.rdf";
1191 int moduleloaded = 0;
1192 char *respstrings[128] = { 0, };
1194 rdoff_init();
1196 options.verbose = 0;
1197 options.align = 16;
1198 options.dynalink = 0;
1199 options.strip = 0;
1201 error_file = stderr;
1203 argc--, argv++;
1204 if (argc == 0)
1205 usage();
1206 while (argc && *argv && **argv == '-' && argv[0][1] != 'l') {
1207 switch (argv[0][1]) {
1208 case 'r':
1209 printf("ldrdf (linker for RDF files) version " LDRDF_VERSION
1210 "\n");
1211 printf("RDOFF2 revision %s\n", RDOFF2_REVISION);
1212 exit(0);
1213 case 'v':
1214 if (argv[0][2] == '=') {
1215 options.verbose = argv[0][3] - '0';
1216 if (options.verbose < 0 || options.verbose > 9) {
1217 fprintf(stderr,
1218 "ldrdf: verbosity level must be a number"
1219 " between 0 and 9\n");
1220 exit(1);
1222 } else
1223 options.verbose++;
1224 break;
1225 case 'a':
1226 options.align = atoi(argv[1]);
1227 if (options.align <= 0) {
1228 fprintf(stderr,
1229 "ldrdf: -a expects a positive number argument\n");
1230 exit(1);
1232 argv++, argc--;
1233 break;
1234 case 's':
1235 options.strip = 1;
1236 break;
1237 case 'd':
1238 if (argv[0][2] == 'y')
1239 options.dynalink = 1;
1240 break;
1241 case 'm':
1242 if (argv[0][2] == 'n') {
1243 modname_specified = argv[1];
1244 argv++, argc--;
1245 if (!argc) {
1246 fprintf(stderr, "ldrdf: -mn expects a module name\n");
1247 exit(1);
1250 break;
1251 case 'o':
1252 outname = argv[1];
1253 argv++, argc--;
1254 break;
1255 case 'j':
1256 if (!objpath) {
1257 options.objpath = 1;
1258 objpath = argv[1];
1259 argv++, argc--;
1260 break;
1261 } else {
1262 fprintf(stderr,
1263 "ldrdf: more than one objects search path specified\n");
1264 exit(1);
1266 case 'L':
1267 if (!libpath) {
1268 options.libpath = 1;
1269 libpath = argv[1];
1270 argv++, argc--;
1271 break;
1272 } else {
1273 fprintf(stderr,
1274 "ldrdf: more than one libraries search path specified\n");
1275 exit(1);
1277 case '@':{
1278 int i = 0;
1279 char buf[256];
1280 FILE *f;
1282 options.respfile = 1;
1283 if (argv[1] != NULL)
1284 f = fopen(argv[1], "r");
1285 else {
1286 fprintf(stderr,
1287 "ldrdf: no response file name specified\n");
1288 exit(1);
1291 if (f == NULL) {
1292 fprintf(stderr,
1293 "ldrdf: unable to open response file\n");
1294 exit(1);
1297 argv++, argc--;
1298 while (fgets(buf, sizeof(buf), f) != NULL) {
1299 char *p;
1300 if (buf[0] == '\n')
1301 continue;
1302 if ((p = strchr(buf, '\n')) != NULL)
1303 *p = '\0';
1304 if (i >= 128) {
1305 fclose(f);
1306 fprintf(stderr, "ldrdf: too many input files\n");
1307 exit(1);
1309 *(respstrings + i) = nasm_strdup(buf);
1310 argc++, i++;
1312 fclose(f);
1313 break;
1315 case '2':
1316 options.stderr_redir = 1;
1317 error_file = stdout;
1318 break;
1319 case 'g':
1320 generic_rec_file = argv[1];
1321 argv++, argc--;
1322 if (!argc) {
1323 fprintf(stderr, "ldrdf: -g expects a file name\n");
1324 exit(1);
1326 break;
1327 default:
1328 usage();
1330 argv++, argc--;
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);
1337 if (options.strip)
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);
1345 printf("\n");
1348 symtab = symtabNew();
1349 initsegments();
1351 if (!symtab) {
1352 fprintf(stderr, "ldrdf: out of memory\n");
1353 exit(1);
1356 while (argc) {
1357 if (!*argv)
1358 argv = respstrings;
1359 if (!*argv)
1360 break;
1361 if (!strncmp(*argv, "-l", 2)) {
1362 if (libpath && (argv[0][2] != '/'))
1363 add_library(nasm_strcat(libpath, *argv + 2));
1364 else
1365 add_library(*argv + 2);
1366 } else {
1367 if (objpath && (argv[0][0] != '/'))
1368 loadmodule(nasm_strcat(objpath, *argv));
1369 else
1370 loadmodule(*argv);
1371 moduleloaded = 1;
1373 argv++, argc--;
1376 if (!moduleloaded) {
1377 printf("ldrdf: nothing to do. ldrdf -h for usage\n");
1378 return 0;
1381 search_libraries();
1383 if (options.verbose > 2) {
1384 printf("symbol table:\n");
1385 symtabDump(symtab, stdout);
1388 write_output(outname);
1390 if (errorcount > 0) {
1391 remove(outname);
1392 exit(1);
1394 return 0;