ldrdf.c
上传用户:yuppie_zhu
上传日期:2007-01-08
资源大小:535k
文件大小:20k
源码类别:

编译器/解释器

开发平台:

C/C++

  1. /* ldrdf.c RDOFF Object File linker/loader main program
  2.  *
  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.
  7.  */
  8. /* TODO: Make the system skip a module (other than the first) if none
  9.  * of the other specified modules contain a reference to it.
  10.  * May require the system to make an extra pass of the modules to be
  11.  * loaded eliminating those that aren't required.
  12.  *
  13.  * Support all the existing documented options...
  14.  *
  15.  * Support libaries (.a files - requires a 'ranlib' type utility)
  16.  * (I think I've got this working, so I've upped the version)
  17.  *
  18.  * -s option to strip resolved symbols from exports. (Could make this an
  19.  * external utility)
  20.  */
  21. #include <stdio.h>
  22. #include <stdlib.h>
  23. #include <string.h>
  24. #include "rdoff.h"
  25. #include "nasmlib.h"
  26. #include "symtab.h"
  27. #include "collectn.h"
  28. #include "rdlib.h"
  29. #define LDRDF_VERSION "0.30"
  30. /* global variables - those to set options: */
  31. int  verbose = 0; /* reflects setting of command line switch */
  32. int align = 16;
  33. int errors = 0; /* set by functions to cause halt after current
  34.    stage of processing */
  35. /* the linked list of modules that must be loaded & linked */
  36. struct modulenode {
  37.     rdffile f; /* the file */
  38.     long coderel; /* module's code relocation factor */
  39.     long datarel; /* module's data relocation factor */
  40.     long bssrel; /* module's bss data reloc. factor */
  41.     void * header; /* header location, if loaded */
  42.     char * name; /* filename */
  43.     struct modulenode *next;
  44. };
  45. #define newstr(str) strcpy(malloc(strlen(str) + 1),str)
  46. #define newstrcat(s1,s2) strcat(strcpy(malloc(strlen(s1)+strlen(s2)+1),s1),s2)
  47. struct modulenode *modules = NULL,*lastmodule = NULL;
  48. /* the linked list of libraries to be searched for missing imported
  49.    symbols */
  50. struct librarynode * libraries = NULL, * lastlib = NULL;
  51. void *symtab; /* The symbol table */
  52. rdf_headerbuf * newheader ; /* New header to be written to output */
  53. /* loadmodule - find the characteristics of a module and add it to the
  54.  * list of those being linked together */
  55. void loadmodule(char *filename)
  56. {
  57.   struct modulenode *prev;
  58.   if (! modules) {
  59.     modules = malloc(sizeof(struct modulenode));
  60.     lastmodule = modules;
  61.     prev = NULL;
  62.   }
  63.   else {
  64.     lastmodule->next = malloc(sizeof(struct modulenode));
  65.     prev = lastmodule;
  66.     lastmodule = lastmodule->next;
  67.   }
  68.   if (! lastmodule) {
  69.     fputs("ldrdf: not enough memoryn",stderr);
  70.     exit(1);
  71.   }
  72.   if (rdfopen(&lastmodule->f,filename)) {
  73.     rdfperror("ldrdf",filename);
  74.     exit(1);
  75.   }
  76.   lastmodule->header = NULL; /* header hasn't been loaded */
  77.   lastmodule->name = filename;
  78.   lastmodule->next = NULL;
  79.   if (prev) {
  80.     lastmodule->coderel = prev->coderel + prev->f.code_len;
  81.     if (lastmodule->coderel % align != 0)
  82.       lastmodule->coderel += align - (lastmodule->coderel % align);
  83.     lastmodule->datarel = prev->datarel + prev->f.data_len;
  84.     if (lastmodule->datarel % align != 0)
  85.       lastmodule->datarel += align - (lastmodule->datarel % align);
  86.   }
  87.   else {
  88.     lastmodule->coderel = 0;
  89.     lastmodule->datarel = 0;
  90.   }
  91.   if (verbose)
  92.     printf("%s code = %08lx (+%04lx), data = %08lx (+%04lx)n",filename,
  93.    lastmodule->coderel,lastmodule->f.code_len,
  94.    lastmodule->datarel,lastmodule->f.data_len);
  95.   lastmodule->header = malloc(lastmodule->f.header_len);
  96.   if (!lastmodule->header) {
  97.       fprintf(stderr,"ldrdf: out of memoryn");
  98.       exit(1);
  99.   }
  100.   if (rdfloadseg(&lastmodule->f,RDOFF_HEADER,lastmodule->header))
  101.   {
  102.       rdfperror("ldrdf",filename);
  103.       exit(1);
  104.   }
  105. }
  106. /* load_library add a library to list of libraries to search
  107.  *                      for undefined symbols
  108.  */
  109. void load_library(char * name)
  110. {
  111.     if (verbose)
  112. printf("adding library %s to search pathn",name);
  113.     if (! lastlib) {
  114. lastlib = libraries = malloc(sizeof(struct librarynode));
  115.     }
  116.     else
  117.     {
  118. lastlib->next = malloc(sizeof(struct librarynode));
  119. lastlib = lastlib->next;
  120.     }
  121.     if (! lastlib) {
  122. fprintf(stderr, "ldrdf: out of memoryn");
  123. exit(1);
  124.     }
  125.     strcpy (lastlib->name = malloc (1+strlen(name)), name);
  126.     lastlib->fp = NULL;
  127.     lastlib->referenced = 0;
  128.     lastlib->next = NULL;
  129. }
  130. /* build_symbols() step through each module's header, and locate
  131.  * exported symbols, placing them in a global table
  132.  */
  133. long bsslength;
  134. void mod_addsymbols(struct modulenode * mod)
  135. {
  136.     rdfheaderrec *r;
  137.     symtabEnt e;
  138.     long cbBss;
  139.     mod->bssrel = bsslength;
  140.     cbBss = 0;
  141.     rdfheaderrewind(&mod->f);
  142.     while ((r = rdfgetheaderrec(&mod->f)))
  143.     {
  144. if (r->type == 5) /* Allocate BSS */
  145.     cbBss += r->b.amount;
  146. if (r->type != 3) continue; /* ignore all but export recs */
  147. e.segment = r->e.segment;
  148. e.offset = r->e.offset + 
  149.     (e.segment == 0 ? mod->coderel : /* 0 -> code */
  150.      e.segment == 1 ? mod->datarel : /* 1 -> data */
  151.      mod->bssrel) ; /* 2 -> bss  */
  152. e.flags = 0;
  153. e.name = malloc(strlen(r->e.label) + 1);
  154. if (! e.name)
  155. {
  156.     fprintf(stderr,"ldrdf: out of memoryn");
  157.     exit(1);
  158. }
  159. strcpy(e.name,r->e.label);
  160. symtabInsert(symtab,&e);
  161.     }
  162.     bsslength += cbBss;
  163. }
  164. void build_symbols()
  165. {
  166.   struct modulenode *mod;
  167.   if (verbose) printf("building global symbol table:n");
  168.   newheader = rdfnewheader();
  169.   symtab = symtabNew();
  170.   bsslength = 0;   /* keep track of location of BSS symbols */
  171.   for (mod = modules; mod; mod = mod->next)
  172.   {
  173.       mod_addsymbols( mod );
  174.   }
  175.   if (verbose)
  176.   {
  177.       symtabDump(symtab,stdout);
  178.       printf("BSS length = %ld bytesnn",bsslength);
  179.   }
  180. }
  181. /* scan_libraries() search through headers of modules for undefined
  182.  * symbols, and scan libraries for those symbols,
  183.  * adding library modules found to list of modules
  184.  * to load. */
  185. void scan_libraries(void)
  186. {
  187.     struct modulenode  * mod, * nm;
  188.     struct librarynode * lib;
  189.     rdfheaderrec * r;
  190.     int found;
  191.     char * tmp;
  192.     if (verbose) printf("Scanning libraries for unresolved symbols...n");
  193.     mod = modules;
  194.     while (mod)
  195.     {
  196. rdfheaderrewind(&mod->f);
  197. while ((r = rdfgetheaderrec(&mod->f)))
  198. {
  199.     if (r->type != 2) continue; /* not an import record */
  200.     if ( symtabFind (symtab,r->i.label) )
  201. continue; /* symbol already defined */
  202.     
  203.     /* okay, we have an undefined symbol... step through
  204.        the libraries now */
  205.     if (verbose >= 2) {
  206. printf("undefined symbol '%s'...",r->i.label);
  207. fflush(stdout);
  208.     }
  209.     lib = libraries;
  210.     found = 0;
  211.     tmp = newstr(r->i.label);
  212.     while (! found && lib)
  213.     {
  214. /* move this to an outer loop...! */
  215. nm = malloc(sizeof(struct modulenode));
  216. if (rdl_searchlib(lib,tmp,&nm->f))
  217. { /* found a module in the library */
  218.     /* create a modulenode for it */
  219.     if (! nm) {
  220. fprintf(stderr,"ldrdf: out of memoryn");
  221. exit(1);
  222.     }
  223.     nm->name = newstrcat(lib->name,nm->f.name);
  224.     if (verbose >= 2) printf("found in '%s'n",nm->name);
  225.     nm->coderel = lastmodule->coderel + lastmodule->f.code_len;
  226.     if (nm->coderel % align != 0)
  227. nm->coderel += align - (nm->coderel % align);
  228.     nm->datarel = lastmodule->datarel + lastmodule->f.data_len;
  229.     if (nm->datarel % align != 0)
  230. nm->datarel += align - (nm->datarel % align);
  231.     nm->header = malloc(nm->f.header_len);
  232.     if (! nm->header)
  233.     {
  234. fprintf(stderr,"ldrdf: out of memoryn");
  235. exit(1);
  236.     }
  237.     if (rdfloadseg(&nm->f,RDOFF_HEADER,nm->header))
  238.     {
  239. rdfperror("ldrdf",nm->name);
  240. exit(1);
  241.     }
  242.     nm->next = NULL;
  243.     found = 1;
  244.     lastmodule->next = nm;
  245.     lastmodule = nm;
  246.     if (verbose)
  247. printf("%s code = %08lx (+%04lx), data = %08lx "
  248.        "(+%04lx)n",lastmodule->name,
  249.        lastmodule->coderel,lastmodule->f.code_len,
  250.        lastmodule->datarel,lastmodule->f.data_len);
  251.     /* add the module's info to the symbol table */
  252.     mod_addsymbols(nm);
  253. }
  254. else
  255. {
  256.     if (rdl_error) {
  257. rdl_perror("ldrdf",lib->name);
  258. exit(1);
  259.     }
  260.     free(nm);
  261. }
  262. lib = lib->next;
  263.     }
  264.     free(tmp);
  265.     if (!found && verbose >= 2) printf("not foundn");
  266. }
  267. mod = mod->next;
  268.     }
  269. }
  270. /* load_segments() allocates memory for & loads the code & data segs
  271.  * from the RDF modules
  272.  */
  273. char *text,*data;
  274. long textlength,datalength;
  275. void load_segments(void)
  276. {
  277.   struct modulenode *mod;
  278.   if (!modules) {
  279.     fprintf(stderr,"ldrdf: nothing to don");
  280.     exit(0);
  281.   }
  282.   if (!lastmodule) {
  283.     fprintf(stderr,"ldrdf: panic: module list exists, but lastmodule=NULLn");
  284.     exit(3);
  285.   }
  286.   if (verbose)
  287.     printf("loading modules into memoryn");
  288.   /* The following stops 16 bit DOS from crashing whilst attempting to
  289.      work using segments > 64K */
  290.   if (sizeof(int) == 2) { /* expect a 'code has no effect' warning on 32 bit
  291.     platforms... */
  292.     if (lastmodule->coderel + lastmodule->f.code_len > 65535 ||
  293. lastmodule->datarel + lastmodule->f.data_len > 65535) {
  294.       fprintf(stderr,"ldrdf: segment length has exceeded 64K; use a 32 bit "
  295.       "version.nldrdf: code size = %05lx, data size = %05lxn",
  296.       lastmodule->coderel + lastmodule->f.code_len,
  297.       lastmodule->datarel + lastmodule->f.data_len);
  298.       exit(1);
  299.     }
  300.   }
  301.   text = malloc(textlength = lastmodule->coderel + lastmodule->f.code_len);
  302.   data = malloc(datalength = lastmodule->datarel + lastmodule->f.data_len);
  303.   if (!text || !data) {
  304.     fprintf(stderr,"ldrdf: out of memoryn");
  305.     exit(1);
  306.   }
  307.   mod = modules;
  308.   while (mod) { /* load the segments for each module */
  309.       if (verbose >= 2) printf("  loading %sn",mod->name);
  310.       if (rdfloadseg(&mod->f,RDOFF_CODE,&text[mod->coderel]) ||
  311.   rdfloadseg(&mod->f,RDOFF_DATA,&data[mod->datarel])) {
  312.   rdfperror("ldrdf",mod->name);
  313.   exit(1);
  314.       }
  315.       rdfclose(&mod->f); /* close file; segments remain */
  316.       mod = mod->next;
  317.   }
  318. }
  319.     
  320. /* link_segments() step through relocation records in each module's
  321.  * header, fixing up references.
  322.  */
  323. void link_segments(void)
  324. {
  325.   struct modulenode *mod;
  326.   Collection imports;
  327.   symtabEnt *s;
  328.   long  rel,relto;
  329.   char  *seg;
  330.   rdfheaderrec *r;
  331.   int bRelative;
  332.   if (verbose) printf("linking segmentsn");
  333.   collection_init(&imports);
  334.   for (mod = modules; mod; mod = mod->next) {
  335.     if (verbose >= 2) printf("* processing %sn",mod->name);
  336.     rdfheaderrewind(&mod->f);
  337.     while((r = rdfgetheaderrec(&mod->f))) {
  338. if (verbose >= 3) printf("record type: %dn",r->type);
  339. switch(r->type) {
  340. case 1: /* relocation record */
  341.     if (r->r.segment >= 64) {      /* Relative relocation; */
  342. bRelative = 1; /* need to find location relative */
  343. r->r.segment -= 64; /* to start of this segment */
  344. relto = r->r.segment == 0 ? mod->coderel : mod->datarel;
  345.     }
  346.     else
  347.     {
  348. bRelative = 0; /* non-relative - need to relocate
  349.  * at load time */
  350. relto = 0;        /* placate optimiser warnings */
  351.     }
  352.     /* calculate absolute offset of reference, not rel to beginning of
  353.        segment */
  354.     r->r.offset += r->r.segment == 0 ? mod->coderel : mod->datarel;
  355.     /* calculate the relocation factor to apply to the operand -
  356.        the base address of one of this modules segments if referred
  357.        segment is 0 - 2, or the address of an imported symbol
  358.        otherwise. */
  359.     if (r->r.refseg == 0) rel = mod->coderel;
  360.     else if (r->r.refseg == 1) rel = mod->datarel;
  361.     else if (r->r.refseg == 2) rel = mod->bssrel;
  362.     else { /* cross module link - find reference */
  363. s = *colln(&imports,r->r.refseg - 2);
  364. if (!s) {
  365.     fprintf(stderr,"ldrdf: link to undefined segment %04x in"
  366.     " %s:%dn", r->r.refseg,mod->name,r->r.segment);
  367.     errors = 1;
  368.     break;
  369. }
  370. rel = s->offset;
  371.   
  372. r->r.refseg = s->segment; /* change referred segment, 
  373.    so that new header is
  374.    correct */
  375.     }
  376.     if (bRelative) /* Relative - subtract current segment start */
  377. rel -= relto; 
  378.     else  
  379.     { /* Add new relocation header */
  380. rdfaddheader(newheader,r);
  381.     }
  382.     
  383.     /* Work out which segment we're making changes to ... */
  384.     if (r->r.segment == 0) seg = text;
  385.     else if (r->r.segment == 1) seg = data;
  386.     else {
  387. fprintf(stderr,"ldrdf: relocation in unknown segment %d in "
  388. "%sn", r->r.segment,mod->name);
  389. errors = 1;
  390. break;
  391.     }
  392.     /* Add the relocation factor to the datum specified: */
  393.     if (verbose >= 3)
  394. printf("  - relocating %d:%08lx by %08lxn",r->r.segment,
  395.        r->r.offset,rel);
  396.     /**** The following code is non-portable. Rewrite it... ****/
  397.     switch(r->r.length) {
  398.     case 1:
  399. seg[r->r.offset] += (char) rel;
  400. break;
  401.     case 2:
  402. *(int16 *)(seg + r->r.offset) += (int16) rel;
  403. break;
  404.     case 4:
  405. *(long *)(seg + r->r.offset) += rel;
  406. break;
  407.     }
  408.     break;
  409. case 2: /* import record */
  410.     s = symtabFind(symtab, r->i.label);
  411.     if (s == NULL) {
  412. /* Need to add support for dynamic linkage */
  413. fprintf(stderr,"ldrdf: undefined symbol %s in module %sn",
  414. r->i.label,mod->name);
  415. errors = 1;
  416.     }
  417.     else 
  418.     {
  419. *colln(&imports,r->i.segment - 2) = s;
  420. if (verbose >= 2)
  421.     printf("imported %s as %04xn", r->i.label, r->i.segment);
  422.     }
  423.     break;
  424. case 3: /* export; dump to output new version */
  425.     s = symtabFind(symtab, r->e.label);
  426.     if (! s) {
  427. fprintf(stderr,"ldrdf: internal error - undefined symbol %s "
  428. "exported in header of '%s'n",r->e.label,mod->name);
  429. continue;
  430.     }
  431.     r->e.offset = s->offset;
  432.     rdfaddheader(newheader,r);
  433.     break;
  434. case 4: /* DLL record */
  435.     rdfaddheader(newheader,r); /* copy straight to output */
  436.     break;
  437. }
  438.     }
  439.     if (rdf_errno != 0) {
  440. rdfperror("ldrdf",mod->name);
  441. exit(1);
  442.     }
  443.     collection_reset(&imports);
  444.   }
  445. }
  446.     
  447. /* write_output() write linked program out to a file */
  448. void write_output(char *filename)
  449. {
  450.     FILE * fp;
  451.     rdfheaderrec r;
  452.     if (verbose) printf("writing output to '%s'n",filename);
  453.     fp = fopen(filename,"wb");
  454.     if (! fp)
  455.     {
  456. fprintf(stderr,"ldrdf: could not open '%s' for writingn",filename);
  457. exit(1);
  458.     }
  459.   
  460.     
  461.     /* add BSS length count to header... */
  462.     if (bsslength)
  463.     {
  464. r.type = 5;
  465. r.b.amount = bsslength;
  466. rdfaddheader(newheader,&r);
  467.     }
  468.     /* Write header */
  469.     rdfwriteheader(fp,newheader);
  470.     rdfdoneheader(newheader);
  471.     newheader = NULL;
  472.     /* Write text */
  473.     if (fwrite(&textlength,1,4,fp) != 4
  474. || fwrite(text,1,textlength,fp) !=textlength)
  475.     {
  476. fprintf(stderr,"ldrdf: error writing %sn",filename);
  477. exit(1);
  478.     }
  479.     /* Write data */
  480.     if (fwrite(&datalength,1,4,fp) != 4 ||
  481. fwrite(data,1,datalength,fp) != datalength)
  482.     {
  483. fprintf (stderr,"ldrdf: error writing %sn", filename);
  484. exit(1);
  485.     }
  486.     fclose(fp);
  487. }
  488. /* main program: interpret command line, and pass parameters on to
  489.  * individual module loaders & the linker
  490.  *
  491.  * Command line format:
  492.  * ldrdf [-o outfile | -x] [-r xxxx] [-v] [--] infile [infile ...]
  493.  *
  494.  * Default action is to output a file named 'aout.rdx'. -x specifies
  495.  * that the linked object program should be executed, rather than
  496.  * written to a file. -r specifies that the object program should
  497.  * be prelocated at address 'xxxx'. This option cannot be used
  498.  * in conjunction with -x.
  499.  */
  500. const char *usagemsg = "usage:n"
  501. " ldrdf [-o outfile | -x] [-a x] [-v] [-p x] [--] infile [infile ...]n"
  502. "       [-l<libname> ...]nn"
  503. " ldrdf -h displays this messagen"
  504. " ldrdf -r displays version informationnn"
  505. "   -o selects output filename (default is aout.rdx)n"
  506. "   -x causes ldrdx to link & execute rather than write to filen"
  507. "   -a x causes object program to be statically relocated to address 'x'n"
  508. "   -v turns on verbose moden"
  509. "   -p x causes segments to be aligned (padded) to x byte boundariesn"
  510. "      (default is 16 bytes)n"
  511. "   -l<name> causes 'name' to be linked in as a library. Note no search isn"
  512. "      performed - the entire pathname MUST be specified.n";
  513. void usage(void)
  514. {
  515.   fputs(usagemsg,stderr);
  516. }
  517. int main(int argc,char **argv)
  518. {
  519.   char *ofilename = "aout.rdx";
  520.   long relocateaddr = -1; /* -1 if no relocation is to occur */
  521.   int execute = 0; /* 1 to execute after linking, 0 otherwise */
  522.   int procsw = 1; /* set to 0 by '--' */
  523.   int tmp;
  524.   if (argc == 1) {
  525.     usage();
  526.     exit(1);
  527.   }
  528.   /* process command line switches, and add modules specified to linked list
  529.      of modules, keeping track of total memory required to load them */
  530.   while(argv++,--argc) {
  531.     if (procsw && !strcmp(*argv,"-h")) { /* Help command */
  532.       usage(); exit(1);
  533.     }
  534.     else if (procsw && !strcmp(*argv,"-r")) {
  535.       printf("ldrdf version %s (%s) (%s)n",LDRDF_VERSION,_RDOFF_H,
  536.      sizeof(int) == 2 ? "16 bit" : "32 bit");
  537.       exit(1);
  538.     }
  539.     else if (procsw && !strcmp(*argv,"-o")) {
  540.       ofilename = *++argv;
  541.       --argc;
  542.       if (execute) {
  543. fprintf(stderr,"ldrdf: -o and -x switches incompatiblen");
  544. exit(1);
  545.       }
  546.       if (verbose > 1) printf("output filename set to '%s'n",ofilename);
  547.     }
  548.     else if (procsw && !strcmp(*argv,"-x")) {
  549.       execute++;
  550.       if (verbose > 1) printf("will execute linked objectn");
  551.     }
  552.     else if (procsw && !strcmp(*argv,"-a")) {
  553.       relocateaddr = readnum(*++argv,&tmp);
  554.       --argc;
  555.       if (tmp) {
  556. fprintf(stderr,"ldrdf: error in parameter to '-a' switch: '%s'n",
  557. *argv);
  558. exit(1);
  559.       }
  560.       if (execute) {
  561. fprintf(stderr,"ldrdf: -a and -x switches incompatiblen");
  562. exit(1);
  563.       }
  564.       if (verbose) printf("will relocate to %08lxn",relocateaddr);
  565.     }
  566.     else if (procsw && !strcmp(*argv,"-v")) {
  567.       verbose++;
  568.       if (verbose == 1) printf("verbose mode selectedn");
  569.     }
  570.     else if (procsw && !strcmp(*argv,"-p")) {
  571.       align = readnum(*++argv,&tmp);
  572.       --argc;
  573.       if (tmp) {
  574. fprintf(stderr,"ldrdf: error in parameter to '-p' switch: '%s'n",
  575. *argv);
  576. exit(1);
  577.       }
  578.       if (align != 1 && align != 2 && align != 4 && align != 8 && align != 16
  579.   && align != 32 && align != 256) {
  580. fprintf(stderr,"ldrdf: %d is an invalid alignment factor - must be"
  581. "1,2,4,8,16 or 256n",align);
  582. exit(1);
  583.       }
  584.       if (verbose > 1) printf("alignment %d selectedn",align);
  585.     }
  586.     else if (procsw && !strncmp(*argv,"-l",2)) {
  587. load_library(*argv + 2);
  588.     }
  589.     else if (procsw && !strcmp(*argv,"--")) {
  590.       procsw = 0;
  591.     }
  592.     else { /* is a filename */
  593.       if (verbose > 1) printf("processing module %sn",*argv);
  594.       loadmodule(*argv);
  595.     }
  596.   }
  597.   /* we should be scanning for unresolved references, and removing
  598.      unreferenced modules from the list of modules here, so that
  599.      we know about the final size once libraries have been linked in */
  600.   build_symbols(); /* build a global symbol table...           */
  601.   scan_libraries(); /* check for imported symbols not in table,
  602.    and ensure the relevant library modules
  603.    are loaded */
  604.   load_segments(); /* having calculated size of reqd segments, load
  605.    each rdoff module's segments into memory */
  606.   link_segments(); /* step through each module's header, and resolve
  607.    references to the global symbol table.
  608.    This also does local address fixups. */
  609.   if (errors) {
  610.     fprintf(stderr,"ldrdf: there were errors - abortedn");
  611.     exit(errors);
  612.   }
  613.   if (execute) {
  614.     fprintf(stderr,"ldrdf: module execution not yet supportedn");
  615.     exit(1);
  616.   }
  617.   if (relocateaddr != -1) {
  618.     fprintf(stderr,"ldrdf: static relocation not yet supportedn");
  619.     exit(1);
  620.   }
  621.   write_output(ofilename);
  622.   return 0;
  623. }