diff options
Diffstat (limited to 'rdoff/ldrdf.c')
-rw-r--r-- | rdoff/ldrdf.c | 1705 |
1 files changed, 868 insertions, 837 deletions
diff --git a/rdoff/ldrdf.c b/rdoff/ldrdf.c index 22e077e..977aeb8 100644 --- a/rdoff/ldrdf.c +++ b/rdoff/ldrdf.c @@ -45,20 +45,19 @@ */ struct segment_infonode { - int dest_seg; /* output segment to be placed into, -1 to - skip linking this segment */ - long reloc; /* segment's relocation factor */ + int dest_seg; /* output segment to be placed into, -1 to + skip linking this segment */ + long reloc; /* segment's relocation factor */ }; - struct modulenode { - rdffile f; /* the RDOFF file structure */ - struct segment_infonode seginfo[RDF_MAXSEGS]; /* what are we doing - with each segment? */ - void * header; - char * name; - struct modulenode * next; - long bss_reloc; + rdffile f; /* the RDOFF file structure */ + struct segment_infonode seginfo[RDF_MAXSEGS]; /* what are we doing + with each segment? */ + void *header; + char *name; + struct modulenode *next; + long bss_reloc; }; #include "ldsegs.h" @@ -70,64 +69,63 @@ struct modulenode { * Function prototypes of private utility functions */ -void processmodule(const char * filename, struct modulenode * mod); -int allocnewseg(uint16 type,uint16 reserved); -int findsegment(uint16 type,uint16 reserved); -void symtab_add(const char * symbol, int segment, long offset); -int symtab_get(const char * symbol, int * segment, long * offset); +void processmodule(const char *filename, struct modulenode *mod); +int allocnewseg(uint16 type, uint16 reserved); +int findsegment(uint16 type, uint16 reserved); +void symtab_add(const char *symbol, int segment, long offset); +int symtab_get(const char *symbol, int *segment, long *offset); /* ========================================================================= * Global data structures. */ /* a linked list of modules that will be included in the output */ -struct modulenode * modules = NULL; -struct modulenode * lastmodule = NULL; +struct modulenode *modules = NULL; +struct modulenode *lastmodule = NULL; /* a linked list of libraries to be searched for unresolved imported symbols */ -struct librarynode * libraries = NULL; -struct librarynode * lastlib = NULL; +struct librarynode *libraries = NULL; +struct librarynode *lastlib = NULL; /* the symbol table */ -void * symtab = NULL; +void *symtab = NULL; /* objects search path */ -char * objpath = NULL; +char *objpath = NULL; /* libraries search path */ -char * libpath = NULL; +char *libpath = NULL; /* file to embed as a generic record */ -char * generic_rec_file = NULL; +char *generic_rec_file = NULL; /* error file */ -static FILE * error_file; +static FILE *error_file; /* the header of the output file, built up stage by stage */ -rdf_headerbuf * newheader = NULL; +rdf_headerbuf *newheader = NULL; /* The current state of segment allocation, including information about * which output segment numbers have been allocated, and their types and * amount of data which has already been allocated inside them. */ -struct SegmentHeaderRec outputseg[RDF_MAXSEGS]; -int nsegs = 0; -long bss_length; +struct SegmentHeaderRec outputseg[RDF_MAXSEGS]; +int nsegs = 0; +long bss_length; /* global options which affect how the program behaves */ struct ldrdfoptions { - int verbose; - int align; - int dynalink; - int strip; - int respfile; - int stderr_redir; - int objpath; - int libpath; + int verbose; + int align; + int dynalink; + int strip; + int respfile; + int stderr_redir; + int objpath; + int libpath; } options; -int errorcount = 0; /* determines main program exit status */ - +int errorcount = 0; /* determines main program exit status */ /* ========================================================================= * Utility functions @@ -149,14 +147,13 @@ void initsegments() outputseg[1].number = 1; outputseg[1].reserved = 0; outputseg[1].length = 0; - outputseg[2].type = 0xFFFF; /* reserved segment type */ + outputseg[2].type = 0xFFFF; /* reserved segment type */ outputseg[2].number = 2; outputseg[2].reserved = 0; outputseg[2].length = 0; bss_length = 0; } - /* * loadmodule * @@ -164,29 +161,29 @@ void initsegments() * each segment it contains (including determining destination segments and * relocation factors for segments that are kept). */ -void loadmodule(const char * filename) +void loadmodule(const char *filename) { if (options.verbose) - printf("loading `%s'\n", filename); + printf("loading `%s'\n", filename); /* allocate a new module entry on the end of the modules list */ if (!modules) { - modules = malloc (sizeof(*modules)); - lastmodule = modules; + modules = malloc(sizeof(*modules)); + lastmodule = modules; } else { - lastmodule->next = malloc (sizeof(*modules)); - lastmodule = lastmodule->next; + lastmodule->next = malloc(sizeof(*modules)); + lastmodule = lastmodule->next; } if (!lastmodule) { - fprintf(stderr, "ldrdf: out of memory\n"); - exit(1); + fprintf(stderr, "ldrdf: out of memory\n"); + exit(1); } /* open the file using 'rdfopen', which returns nonzero on error */ if (rdfopen(&lastmodule->f, filename) != 0) { - rdfperror("ldrdf", filename); - exit(1); + rdfperror("ldrdf", filename); + exit(1); } /* @@ -201,7 +198,6 @@ void loadmodule(const char * filename) processmodule(filename, lastmodule); } - /* * processmodule() * @@ -211,82 +207,83 @@ void loadmodule(const char * filename) * (b) is fairly easy, because we're now keeping track of how big each * segment in our output file is... */ -void processmodule(const char * filename, struct modulenode * mod) +void processmodule(const char *filename, struct modulenode *mod) { struct segconfig sconf; - int seg, outseg; - void * header; - rdfheaderrec * hr; - long bssamount = 0; - int bss_was_referenced = 0; + int seg, outseg; + void *header; + rdfheaderrec *hr; + long bssamount = 0; + int bss_was_referenced = 0; for (seg = 0; seg < mod->f.nsegs; seg++) { - /* - * get the segment configuration for this type from the segment - * table. getsegconfig() is a macro, defined in ldsegs.h. - */ - getsegconfig(sconf, mod->f.seg[seg].type); - - if (options.verbose > 1) { - printf ("%s %04x [%04x:%10s] ", filename, mod->f.seg[seg].number, - mod->f.seg[seg].type, sconf.typedesc); - } - /* - * sconf->dowhat tells us what to do with a segment of this type. - */ - switch (sconf.dowhat) { - case SEG_IGNORE: - /* - * Set destination segment to -1, to indicate that this segment - * should be ignored for the purpose of output, ie it is left - * out of the linked executable. - */ - mod->seginfo[seg].dest_seg = -1; - if (options.verbose > 1) printf("IGNORED\n"); - break; - - case SEG_NEWSEG: - /* - * The configuration tells us to create a new segment for - * each occurrence of this segment type. - */ - outseg = allocnewseg(sconf.mergetype, - mod->f.seg[seg].reserved); - mod->seginfo[seg].dest_seg = outseg; - mod->seginfo[seg].reloc = 0; - outputseg[outseg].length = mod->f.seg[seg].length; - if (options.verbose > 1) - printf ("=> %04x:%08lx (+%04lx)\n", outseg, - mod->seginfo[seg].reloc, - mod->f.seg[seg].length); - break; - - case SEG_MERGE: - /* - * The configuration tells us to merge the segment with - * a previously existing segment of type 'sconf.mergetype', - * if one exists. Otherwise a new segment is created. - * This is handled transparently by 'findsegment()'. - */ - outseg = findsegment(sconf.mergetype, - mod->f.seg[seg].reserved); - mod->seginfo[seg].dest_seg = outseg; - - /* - * We need to add alignment to these segments. - */ - if (outputseg[outseg].length % options.align != 0) - outputseg[outseg].length += - options.align - (outputseg[outseg].length % options.align); - - mod->seginfo[seg].reloc = outputseg[outseg].length; - outputseg[outseg].length += mod->f.seg[seg].length; - - if (options.verbose > 1) - printf ("=> %04x:%08lx (+%04lx)\n", outseg, - mod->seginfo[seg].reloc, - mod->f.seg[seg].length); - } + /* + * get the segment configuration for this type from the segment + * table. getsegconfig() is a macro, defined in ldsegs.h. + */ + getsegconfig(sconf, mod->f.seg[seg].type); + + if (options.verbose > 1) { + printf("%s %04x [%04x:%10s] ", filename, + mod->f.seg[seg].number, mod->f.seg[seg].type, + sconf.typedesc); + } + /* + * sconf->dowhat tells us what to do with a segment of this type. + */ + switch (sconf.dowhat) { + case SEG_IGNORE: + /* + * Set destination segment to -1, to indicate that this segment + * should be ignored for the purpose of output, ie it is left + * out of the linked executable. + */ + mod->seginfo[seg].dest_seg = -1; + if (options.verbose > 1) + printf("IGNORED\n"); + break; + + case SEG_NEWSEG: + /* + * The configuration tells us to create a new segment for + * each occurrence of this segment type. + */ + outseg = allocnewseg(sconf.mergetype, + mod->f.seg[seg].reserved); + mod->seginfo[seg].dest_seg = outseg; + mod->seginfo[seg].reloc = 0; + outputseg[outseg].length = mod->f.seg[seg].length; + if (options.verbose > 1) + printf("=> %04x:%08lx (+%04lx)\n", outseg, + mod->seginfo[seg].reloc, mod->f.seg[seg].length); + break; + + case SEG_MERGE: + /* + * The configuration tells us to merge the segment with + * a previously existing segment of type 'sconf.mergetype', + * if one exists. Otherwise a new segment is created. + * This is handled transparently by 'findsegment()'. + */ + outseg = findsegment(sconf.mergetype, + mod->f.seg[seg].reserved); + mod->seginfo[seg].dest_seg = outseg; + + /* + * We need to add alignment to these segments. + */ + if (outputseg[outseg].length % options.align != 0) + outputseg[outseg].length += + options.align - + (outputseg[outseg].length % options.align); + + mod->seginfo[seg].reloc = outputseg[outseg].length; + outputseg[outseg].length += mod->f.seg[seg].length; + + if (options.verbose > 1) + printf("=> %04x:%08lx (+%04lx)\n", outseg, + mod->seginfo[seg].reloc, mod->f.seg[seg].length); + } } @@ -296,89 +293,92 @@ void processmodule(const char * filename, struct modulenode * mod) */ header = malloc(mod->f.header_len); if (!header) { - fprintf(stderr, "ldrdf: not enough memory\n"); - exit(1); + fprintf(stderr, "ldrdf: not enough memory\n"); + exit(1); } if (rdfloadseg(&mod->f, RDOFF_HEADER, header)) { - rdfperror("ldrdf", filename); - exit(1); + rdfperror("ldrdf", filename); + exit(1); } - while ((hr = rdfgetheaderrec (&mod->f))) { - switch(hr->type) { - case RDFREC_IMPORT: /* imported symbol */ - case RDFREC_FARIMPORT: - /* Define with seg = -1 */ - symtab_add(hr->i.label, -1, 0); - break; - - case RDFREC_GLOBAL: { /* exported symbol */ - int destseg; - long destreloc; - - if (hr->e.segment == 2) { - bss_was_referenced = 1; - destreloc = bss_length; - if (destreloc % options.align != 0) - destreloc += options.align - (destreloc % options.align); - destseg = 2; + while ((hr = rdfgetheaderrec(&mod->f))) { + switch (hr->type) { + case RDFREC_IMPORT: /* imported symbol */ + case RDFREC_FARIMPORT: + /* Define with seg = -1 */ + symtab_add(hr->i.label, -1, 0); + break; + + case RDFREC_GLOBAL:{ /* exported symbol */ + int destseg; + long destreloc; + + if (hr->e.segment == 2) { + bss_was_referenced = 1; + destreloc = bss_length; + if (destreloc % options.align != 0) + destreloc += + options.align - (destreloc % options.align); + destseg = 2; } else { - if ((destseg = mod->seginfo[(int)hr->e.segment].dest_seg) == -1) - continue; - destreloc = mod->seginfo[(int)hr->e.segment].reloc; + if ((destseg = + mod->seginfo[(int)hr->e.segment].dest_seg) == -1) + continue; + destreloc = mod->seginfo[(int)hr->e.segment].reloc; } - symtab_add(hr->e.label, destseg, destreloc + hr->e.offset); - break; - } - - case RDFREC_BSS: /* BSS reservation */ - /* - * first, amalgamate all BSS reservations in this module - * into one, because we allow this in the output format. - */ - bssamount += hr->b.amount; - break; - - case RDFREC_COMMON: { /* Common variable */ - symtabEnt *ste = symtabFind(symtab, hr->c.label); - - /* Is the symbol already in the table? */ - if (ste) break; - - /* Align the variable */ - if (bss_length % hr->c.align != 0) - bss_length += hr->c.align - (bss_length % hr->c.align); - if (options.verbose > 1) { - printf ("%s %04x common '%s' => 0002:%08lx (+%04lx)\n", - filename, hr->c.segment, hr->c.label, bss_length, hr->c.size); - } - - symtab_add(hr->c.label, 2, bss_length); - mod->bss_reloc = bss_length; - bss_length += hr->c.size; - break; - } - } + symtab_add(hr->e.label, destseg, destreloc + hr->e.offset); + break; + } + + case RDFREC_BSS: /* BSS reservation */ + /* + * first, amalgamate all BSS reservations in this module + * into one, because we allow this in the output format. + */ + bssamount += hr->b.amount; + break; + + case RDFREC_COMMON:{ /* Common variable */ + symtabEnt *ste = symtabFind(symtab, hr->c.label); + + /* Is the symbol already in the table? */ + if (ste) + break; + + /* Align the variable */ + if (bss_length % hr->c.align != 0) + bss_length += hr->c.align - (bss_length % hr->c.align); + if (options.verbose > 1) { + printf("%s %04x common '%s' => 0002:%08lx (+%04lx)\n", + filename, hr->c.segment, hr->c.label, + bss_length, hr->c.size); + } + + symtab_add(hr->c.label, 2, bss_length); + mod->bss_reloc = bss_length; + bss_length += hr->c.size; + break; + } + } } - + if (bssamount != 0 || bss_was_referenced) { - /* - * handle the BSS segment - first pad the existing bss length - * to the correct alignment, then store the length in bss_reloc - * for this module. Then add this module's BSS length onto - * bss_length. - */ - if (bss_length % options.align != 0) - bss_length += options.align - (bss_length % options.align); - - mod->bss_reloc = bss_length; - if (options.verbose > 1) { - printf ("%s 0002 [ BSS] => 0002:%08lx (+%04lx)\n", - filename, bss_length, bssamount); - } - bss_length += bssamount; + /* + * handle the BSS segment - first pad the existing bss length + * to the correct alignment, then store the length in bss_reloc + * for this module. Then add this module's BSS length onto + * bss_length. + */ + if (bss_length % options.align != 0) + bss_length += options.align - (bss_length % options.align); + + mod->bss_reloc = bss_length; + if (options.verbose > 1) { + printf("%s 0002 [ BSS] => 0002:%08lx (+%04lx)\n", + filename, bss_length, bssamount); + } + bss_length += bssamount; } - #ifdef STINGY_MEMORY /* * we free the header buffer here, to save memory later. @@ -392,7 +392,6 @@ void processmodule(const char * filename, struct modulenode * mod) } - /* * Return 1 if a given module is in the list, 0 otherwise. */ @@ -400,14 +399,14 @@ int lookformodule(const char *name) { struct modulenode *curr = modules; - while(curr) { - if (!strcmp(name, curr->name)) return 1; - curr = curr->next; + while (curr) { + if (!strcmp(name, curr->name)) + return 1; + curr = curr->next; } return 0; } - /* * allocnewseg() * findsegment() @@ -418,7 +417,7 @@ int lookformodule(const char *name) * a segment of the type requested, and if one isn't found allocates a * new one. */ -int allocnewseg(uint16 type,uint16 reserved) +int allocnewseg(uint16 type, uint16 reserved) { outputseg[nsegs].type = type; outputseg[nsegs].number = nsegs; @@ -430,17 +429,17 @@ int allocnewseg(uint16 type,uint16 reserved) return nsegs++; } -int findsegment(uint16 type,uint16 reserved) +int findsegment(uint16 type, uint16 reserved) { int i; for (i = 0; i < nsegs; i++) - if (outputseg[i].type == type) return i; + if (outputseg[i].type == type) + return i; - return allocnewseg(type,reserved); + return allocnewseg(type, reserved); } - /* * symtab_add() * @@ -458,41 +457,43 @@ int findsegment(uint16 type,uint16 reserved) * routine won't change a previously existing symbol. It will change * to segment = -2 only if the segment was previously < 0. */ -void symtab_add(const char * symbol, int segment, long offset) +void symtab_add(const char *symbol, int segment, long offset) { - symtabEnt * ste; + symtabEnt *ste; ste = symtabFind(symtab, symbol); if (ste) { - if (ste->segment >= 0) { - /* - * symbol previously defined - */ - if (segment < 0) return; - fprintf (error_file, "warning: `%s' redefined\n", symbol); - return; - } - - /* - * somebody wanted the symbol, and put an undefined symbol - * marker into the table - */ - if (segment == -1) return; - /* - * we have more information now - update the symbol's entry - */ - ste->segment = segment; - ste->offset = offset; - ste->flags = 0; - return; + if (ste->segment >= 0) { + /* + * symbol previously defined + */ + if (segment < 0) + return; + fprintf(error_file, "warning: `%s' redefined\n", symbol); + return; + } + + /* + * somebody wanted the symbol, and put an undefined symbol + * marker into the table + */ + if (segment == -1) + return; + /* + * we have more information now - update the symbol's entry + */ + ste->segment = segment; + ste->offset = offset; + ste->flags = 0; + return; } /* * this is the first declaration of this symbol */ ste = malloc(sizeof(symtabEnt)); if (!ste) { - fprintf(stderr, "ldrdf: out of memory\n"); - exit(1); + fprintf(stderr, "ldrdf: out of memory\n"); + exit(1); } ste->name = strdup(symbol); ste->segment = segment; @@ -508,57 +509,55 @@ void symtab_add(const char * symbol, int segment, long offset) * are assumed to have -1:0 associated. Returns 1 if the symbol was * successfully located. */ -int symtab_get(const char * symbol, int * segment, long * offset) +int symtab_get(const char *symbol, int *segment, long *offset) { - symtabEnt * ste = symtabFind(symtab, symbol); + symtabEnt *ste = symtabFind(symtab, symbol); if (!ste) { - *segment = -1; - *offset = 0; - return 0; + *segment = -1; + *offset = 0; + return 0; } else { - *segment = ste->segment; - *offset = ste->offset; - return 1; + *segment = ste->segment; + *offset = ste->offset; + return 1; } } - /* * add_library() * * checks that a library can be opened and is in the correct format, * then adds it to the linked list of libraries. */ -void add_library(const char * name) +void add_library(const char *name) { if (rdl_verify(name)) { - rdl_perror("ldrdf", name); - errorcount++; - return; + rdl_perror("ldrdf", name); + errorcount++; + return; } if (!libraries) { - lastlib = libraries = malloc(sizeof(*libraries)); - if (! libraries) { - fprintf(stderr, "ldrdf: out of memory\n"); - exit(1); - } + lastlib = libraries = malloc(sizeof(*libraries)); + if (!libraries) { + fprintf(stderr, "ldrdf: out of memory\n"); + exit(1); + } } else { - lastlib->next = malloc(sizeof(*libraries)); - if (!lastlib->next) { - fprintf(stderr, "ldrdf: out of memory\n"); - exit(1); - } - lastlib = lastlib->next; + lastlib->next = malloc(sizeof(*libraries)); + if (!lastlib->next) { + fprintf(stderr, "ldrdf: out of memory\n"); + exit(1); + } + lastlib = lastlib->next; } lastlib->next = NULL; if (rdl_open(lastlib, name)) { - rdl_perror("ldrdf", name); - errorcount++; - return; + rdl_perror("ldrdf", name); + errorcount++; + return; } } - /* * search_libraries() * @@ -571,102 +570,104 @@ void add_library(const char * name) */ int search_libraries() { - struct librarynode * cur; + struct librarynode *cur; rdffile f; - int i; - void * header; - int segment; - long offset; - int doneanything = 0, pass = 1, keepfile; - rdfheaderrec * hr; + int i; + void *header; + int segment; + long offset; + int doneanything = 0, pass = 1, keepfile; + rdfheaderrec *hr; cur = libraries; while (cur) { - if (options.verbose > 2) - printf("scanning library `%s', pass %d...\n", cur->name, pass); - - for (i = 0; rdl_openmodule(cur, i, &f) == 0; i++) { - if (pass == 2 && lookformodule(f.name)) continue; - - if (options.verbose > 3) - printf(" looking in module `%s'\n", f.name); - - header = malloc(f.header_len); - if (!header) { - fprintf(stderr, "ldrdf: not enough memory\n"); - exit(1); - } - if (rdfloadseg(&f, RDOFF_HEADER, header)) { - rdfperror("ldrdf", f.name); - errorcount++; - return 0; - } - - keepfile = 0; - - while ((hr = rdfgetheaderrec (&f))) { + if (options.verbose > 2) + printf("scanning library `%s', pass %d...\n", cur->name, pass); + + for (i = 0; rdl_openmodule(cur, i, &f) == 0; i++) { + if (pass == 2 && lookformodule(f.name)) + continue; + + if (options.verbose > 3) + printf(" looking in module `%s'\n", f.name); + + header = malloc(f.header_len); + if (!header) { + fprintf(stderr, "ldrdf: not enough memory\n"); + exit(1); + } + if (rdfloadseg(&f, RDOFF_HEADER, header)) { + rdfperror("ldrdf", f.name); + errorcount++; + return 0; + } + + keepfile = 0; + + while ((hr = rdfgetheaderrec(&f))) { /* We're only interested in exports, so skip others */ - if (hr->type != RDFREC_GLOBAL) continue; - - /* - * If the symbol is marked as SYM_GLOBAL, somebody will be - * definitely interested in it.. - */ - if ((hr->e.flags & SYM_GLOBAL) == 0) { - /* - * otherwise the symbol is just public. Find it in - * the symbol table. If the symbol isn't defined, we - * aren't interested, so go on to the next. - * If it is defined as anything but -1, we're also not - * interested. But if it is defined as -1, insert this - * module into the list of modules to use, and go - * immediately on to the next module... - */ - if (!symtab_get(hr->e.label, &segment, &offset) || segment != -1) - continue; - } - - doneanything = 1; - keepfile = 1; - - /* - * as there are undefined symbols, we can assume that - * there are modules on the module list by the time - * we get here. - */ - lastmodule->next = malloc(sizeof(*lastmodule->next)); - if (!lastmodule->next) { - fprintf(stderr, "ldrdf: not enough memory\n"); - exit(1); - } - lastmodule = lastmodule->next; - memcpy(&lastmodule->f, &f, sizeof(f)); - lastmodule->name = strdup(f.name); + if (hr->type != RDFREC_GLOBAL) + continue; + + /* + * If the symbol is marked as SYM_GLOBAL, somebody will be + * definitely interested in it.. + */ + if ((hr->e.flags & SYM_GLOBAL) == 0) { + /* + * otherwise the symbol is just public. Find it in + * the symbol table. If the symbol isn't defined, we + * aren't interested, so go on to the next. + * If it is defined as anything but -1, we're also not + * interested. But if it is defined as -1, insert this + * module into the list of modules to use, and go + * immediately on to the next module... + */ + if (!symtab_get(hr->e.label, &segment, &offset) + || segment != -1) + continue; + } + + doneanything = 1; + keepfile = 1; + + /* + * as there are undefined symbols, we can assume that + * there are modules on the module list by the time + * we get here. + */ + lastmodule->next = malloc(sizeof(*lastmodule->next)); + if (!lastmodule->next) { + fprintf(stderr, "ldrdf: not enough memory\n"); + exit(1); + } + lastmodule = lastmodule->next; + memcpy(&lastmodule->f, &f, sizeof(f)); + lastmodule->name = strdup(f.name); lastmodule->next = NULL; - processmodule(f.name, lastmodule); - break; - } - if (!keepfile) { - free(f.name); - f.name = NULL; - f.fp = NULL; + processmodule(f.name, lastmodule); + break; + } + if (!keepfile) { + free(f.name); + f.name = NULL; + f.fp = NULL; } - } - if (rdl_error != 0 && rdl_error != RDL_ENOTFOUND) - rdl_perror("ldrdf", cur->name); - - cur = cur->next; - if (cur == NULL && pass == 1) { - cur = libraries; - pass++; - } + } + if (rdl_error != 0 && rdl_error != RDL_ENOTFOUND) + rdl_perror("ldrdf", cur->name); + + cur = cur->next; + if (cur == NULL && pass == 1) { + cur = libraries; + pass++; + } } return doneanything; } - /* * write_output() * @@ -674,28 +675,28 @@ int search_libraries() * all the modules into a single output module, and then writes this to a * file. */ -void write_output(const char * filename) +void write_output(const char *filename) { - FILE * f; - rdf_headerbuf * rdfheader; - struct modulenode * cur; - int i, availableseg, seg, localseg, isrelative; - void * header; - rdfheaderrec * hr, newrec; - symtabEnt * se; - segtab segs; - long offset; - byte * data; - - if ((f = fopen(filename, "wb"))==NULL) { - fprintf(stderr, "ldrdf: couldn't open %s for output\n", filename); - exit(1); + FILE *f; + rdf_headerbuf *rdfheader; + struct modulenode *cur; + int i, availableseg, seg, localseg, isrelative; + void *header; + rdfheaderrec *hr, newrec; + symtabEnt *se; + segtab segs; + long offset; + byte *data; + + if ((f = fopen(filename, "wb")) == NULL) { + fprintf(stderr, "ldrdf: couldn't open %s for output\n", filename); + exit(1); } - if ((rdfheader=rdfnewheader())==NULL) { - fprintf(stderr, "ldrdf: out of memory\n"); - exit(1); + if ((rdfheader = rdfnewheader()) == NULL) { + fprintf(stderr, "ldrdf: out of memory\n"); + exit(1); } - + /* * If '-g' option was given, first record in output file will be a * `generic' record, filled with a given file content. @@ -703,31 +704,35 @@ void write_output(const char * filename) * compliant kernels. */ if (generic_rec_file) { - FILE *ff; - - if (options.verbose) - printf("\nadding generic record from binary file %s\n", generic_rec_file); - + FILE *ff; + + if (options.verbose) + printf("\nadding generic record from binary file %s\n", + generic_rec_file); + hr = (rdfheaderrec *) malloc(sizeof(struct GenericRec)); - if ((ff = fopen(generic_rec_file, "r")) == NULL) { - fprintf(stderr, "ldrdf: couldn't open %s for input\n", generic_rec_file); - exit(1); - } - i = fread(hr->g.data, 1, sizeof(hr->g.data), ff); - fseek(ff, 0, SEEK_END); - if (ftell(ff) > sizeof(hr->g.data)) { - fprintf (error_file, "warning: maximum generic record size is %d, rest of file ignored\n", sizeof(hr->g.data)); - } - fclose(ff); - + if ((ff = fopen(generic_rec_file, "r")) == NULL) { + fprintf(stderr, "ldrdf: couldn't open %s for input\n", + generic_rec_file); + exit(1); + } + i = fread(hr->g.data, 1, sizeof(hr->g.data), ff); + fseek(ff, 0, SEEK_END); + if (ftell(ff) > sizeof(hr->g.data)) { + fprintf(error_file, + "warning: maximum generic record size is %d, rest of file ignored\n", + sizeof(hr->g.data)); + } + fclose(ff); + hr->g.type = 0; hr->g.reclen = i; - rdfaddheader(rdfheader, hr); + rdfaddheader(rdfheader, hr); free(hr); } if (options.verbose) - printf ("\nbuilding output module (%d segments)\n", nsegs); + printf("\nbuilding output module (%d segments)\n", nsegs); /* * Allocate the memory for the segments. We may be better off @@ -736,13 +741,14 @@ void write_output(const char * filename) * And you could always use DJGPP... */ for (i = 0; i < nsegs; i++) { - outputseg[i].data=NULL; - if(!outputseg[i].length) continue; - outputseg[i].data = malloc(outputseg[i].length); - if (!outputseg[i].data) { - fprintf(stderr, "ldrdf: out of memory\n"); - exit(1); - } + outputseg[i].data = NULL; + if (!outputseg[i].length) + continue; + outputseg[i].data = malloc(outputseg[i].length); + if (!outputseg[i].data) { + fprintf(stderr, "ldrdf: out of memory\n"); + exit(1); + } } /* @@ -754,302 +760,314 @@ void write_output(const char * filename) /* * Step through the modules, performing required actions on each one */ - for (cur = modules; cur; cur=cur->next) { - /* - * Read the actual segment contents into the correct places in - * the newly allocated segments - */ - - for (i = 0; i < cur->f.nsegs; i++) { - int dest = cur->seginfo[i].dest_seg; - - if (dest == -1) continue; - if (rdfloadseg(&cur->f, i, - outputseg[dest].data + cur->seginfo[i].reloc)) { - rdfperror("ldrdf", cur->name); - exit(1); - } - } - - /* - * Perform fixups, and add new header records where required - */ - - header = malloc(cur->f.header_len); - if (!header) { - fprintf(stderr, "ldrdf: out of memory\n"); - exit(1); - } - - if (cur->f.header_loc) - rdfheaderrewind(&cur->f); - else - if (rdfloadseg(&cur->f, RDOFF_HEADER, header)) { - rdfperror("ldrdf", cur->name); - exit(1); - } - - /* - * we need to create a local segment number -> location - * table for the segments in this module. - */ - init_seglocations(&segs); - for (i = 0; i < cur->f.nsegs; i++) { - add_seglocation(&segs, cur->f.seg[i].number, - cur->seginfo[i].dest_seg, cur->seginfo[i].reloc); - } - /* - * and the BSS segment (doh!) - */ - add_seglocation(&segs, 2, 2, cur->bss_reloc); - - while ((hr = rdfgetheaderrec(&cur->f))) { - switch(hr->type) { - case RDFREC_RELOC: /* relocation record - need to do a fixup */ - /* - * First correct the offset stored in the segment from - * the start of the segment (which may well have changed). - * - * To do this we add to the number stored the relocation - * factor associated with the segment that contains the - * target segment. - * - * The relocation could be a relative relocation, in which - * case we have to first subtract the amount we've relocated - * the containing segment by. - */ - if (!get_seglocation(&segs, hr->r.refseg, &seg, &offset)) { - fprintf(stderr, "%s: reloc to undefined segment %04x\n", - cur->name, (int) hr->r.refseg); - errorcount++; - break; - } - - isrelative = (hr->r.segment & RDOFF_RELATIVEMASK) == RDOFF_RELATIVEMASK; - hr->r.segment &= (RDOFF_RELATIVEMASK-1); - - if (hr->r.segment == 2 || - (localseg = rdffindsegment(&cur->f, hr->r.segment)) == -1) { - fprintf(stderr, "%s: reloc from %s segment (%d)\n", - cur->name, - hr->r.segment == 2 ? "BSS" : "unknown", - hr->r.segment); - errorcount++; - break; - } - - if (hr->r.length != 1 && hr->r.length != 2 && - hr->r.length != 4 ) { - fprintf(stderr, "%s: nonstandard length reloc " - "(%d bytes)\n", cur->name, hr->r.length); - errorcount++; - break; - } - - /* - * okay, now the relocation is in the segment pointed to by - * cur->seginfo[localseg], and we know everything else is - * okay to go ahead and do the relocation - */ - data = outputseg[cur->seginfo[localseg].dest_seg].data; - data += cur->seginfo[localseg].reloc + hr->r.offset; - - /* - * data now points to the reference that needs - * relocation. Calculate the relocation factor. - * Factor is: - * offset of referred object in segment [in offset] - * (- relocation of localseg, if ref is relative) - * For simplicity, the result is stored in 'offset'. - * Then add 'offset' onto the value at data. - */ - - if (isrelative) - offset -= cur->seginfo[localseg].reloc; - switch (hr->r.length) { - case 1: - offset += *data; - if (offset < -127 || offset > 128) - fprintf(error_file, "warning: relocation out of range " - "at %s(%02x:%08lx)\n", cur->name, - (int)hr->r.segment, hr->r.offset); - *data = (char) offset; - break; - case 2: - offset += * (short *)data; - if (offset < -32767 || offset > 32768) - fprintf(error_file, "warning: relocation out of range " - "at %s(%02x:%08lx)\n", cur->name, - (int)hr->r.segment, hr->r.offset); - * (short *)data = (short) offset; - break; - case 4: - * (long *)data += offset; - /* we can't easily detect overflow on this one */ - break; - } - - /* - * If the relocation was relative between two symbols in - * the same segment, then we're done. - * - * Otherwise, we need to output a new relocation record - * with the references updated segment and offset... - */ - if (!isrelative || cur->seginfo[localseg].dest_seg != seg) { - hr->r.segment = cur->seginfo[localseg].dest_seg; - hr->r.offset += cur->seginfo[localseg].reloc; - hr->r.refseg = seg; - if (isrelative) - hr->r.segment += RDOFF_RELATIVEMASK; - rdfaddheader(rdfheader, hr); - } - break; - - case RDFREC_IMPORT: /* import symbol */ - case RDFREC_FARIMPORT: - /* - * scan the global symbol table for the symbol - * and associate its location with the segment number - * for this module - */ - se = symtabFind(symtab, hr->i.label); - if (!se || se->segment == -1) { - if (!options.dynalink && !(hr->i.flags & SYM_IMPORT)) { - fprintf(error_file, "error: unresolved reference to `%s'" - " in module `%s'\n", hr->i.label, cur->name); - errorcount++; - } - /* - * we need to allocate a segment number for this - * symbol, and store it in the symbol table for - * future reference - */ - if (!se) { - se=malloc(sizeof(*se)); - if (!se) { - fprintf(stderr, "ldrdf: out of memory\n"); - exit(1); - } - se->name = strdup(hr->i.label); - se->flags = 0; - se->segment = availableseg++; - se->offset = 0; - symtabInsert(symtab, se); - } - else { - se->segment = availableseg++; - se->offset = 0; - } - /* - * output a header record that imports it to the - * recently allocated segment number... - */ - newrec = *hr; - newrec.i.segment = se->segment; - rdfaddheader(rdfheader, &newrec); - } - - add_seglocation(&segs, hr->i.segment, se->segment, se->offset); - break; - - case RDFREC_GLOBAL: /* export symbol */ - /* - * need to insert an export for this symbol into the new - * header, unless we're stripping symbols. Even if we're - * stripping, put the symbol if it's marked as SYM_GLOBAL. - */ - if (options.strip && !(hr->e.flags & SYM_GLOBAL)) - break; - - if (hr->e.segment == 2) { - seg = 2; - offset = cur->bss_reloc; - } - else { - localseg = rdffindsegment(&cur->f, hr->e.segment); - if (localseg == -1) { - fprintf(stderr, "%s: exported symbol `%s' from " - "unrecognised segment\n", cur->name, - hr->e.label); - errorcount++; - break; - } - offset = cur->seginfo[localseg].reloc; - seg = cur->seginfo[localseg].dest_seg; - } - - hr->e.segment = seg; - hr->e.offset += offset; - rdfaddheader(rdfheader, hr); - break; - - case RDFREC_MODNAME: /* module name */ - /* - * Insert module name record if export symbols - * are not stripped. - * If module name begins with '$' - insert it anyway. - */ - if (options.strip && hr->m.modname[0] != '$') break; - rdfaddheader(rdfheader, hr); - break; - - case RDFREC_DLL: /* DLL name */ - /* - * Insert DLL name if it begins with '$' - */ - if (hr->d.libname[0] != '$') break; - rdfaddheader(rdfheader, hr); - break; - - case RDFREC_SEGRELOC: /* segment fixup */ - /* - * modify the segment numbers if necessary, and - * pass straight through to the output module header - * - * *** FIXME *** - */ - if (hr->r.segment == 2) { - fprintf(stderr, "%s: segment fixup in BSS section\n", - cur->name); - errorcount++; - break; - } - localseg = rdffindsegment(&cur->f, hr->r.segment); - if (localseg == -1) { - fprintf(stderr, "%s: segment fixup in unrecognised" - " segment (%d)\n", cur->name, hr->r.segment); - errorcount++; - break; - } - hr->r.segment = cur->seginfo[localseg].dest_seg; - hr->r.offset += cur->seginfo[localseg].reloc; - - if (!get_seglocation(&segs, hr->r.refseg, &seg, &offset)) { - fprintf(stderr, "%s: segment fixup to undefined " - "segment %04x\n", cur->name, (int)hr->r.refseg); - errorcount++; - break; - } - hr->r.refseg = seg; - rdfaddheader(rdfheader, hr); - break; - - case RDFREC_COMMON: /* Common variable */ - /* Is this symbol already in the table? */ - se = symtabFind(symtab, hr->c.label); - if (!se) { - printf("%s is not in symtab yet\n", hr->c.label); - break; - } - /* Add segment location */ - add_seglocation(&segs, hr->c.segment, se->segment, se->offset); - break; - } - } - - free(header); - done_seglocations(&segs); + for (cur = modules; cur; cur = cur->next) { + /* + * Read the actual segment contents into the correct places in + * the newly allocated segments + */ + + for (i = 0; i < cur->f.nsegs; i++) { + int dest = cur->seginfo[i].dest_seg; + + if (dest == -1) + continue; + if (rdfloadseg(&cur->f, i, + outputseg[dest].data + cur->seginfo[i].reloc)) { + rdfperror("ldrdf", cur->name); + exit(1); + } + } + + /* + * Perform fixups, and add new header records where required + */ + + header = malloc(cur->f.header_len); + if (!header) { + fprintf(stderr, "ldrdf: out of memory\n"); + exit(1); + } + + if (cur->f.header_loc) + rdfheaderrewind(&cur->f); + else if (rdfloadseg(&cur->f, RDOFF_HEADER, header)) { + rdfperror("ldrdf", cur->name); + exit(1); + } + + /* + * we need to create a local segment number -> location + * table for the segments in this module. + */ + init_seglocations(&segs); + for (i = 0; i < cur->f.nsegs; i++) { + add_seglocation(&segs, cur->f.seg[i].number, + cur->seginfo[i].dest_seg, + cur->seginfo[i].reloc); + } + /* + * and the BSS segment (doh!) + */ + add_seglocation(&segs, 2, 2, cur->bss_reloc); + + while ((hr = rdfgetheaderrec(&cur->f))) { + switch (hr->type) { + case RDFREC_RELOC: /* relocation record - need to do a fixup */ + /* + * First correct the offset stored in the segment from + * the start of the segment (which may well have changed). + * + * To do this we add to the number stored the relocation + * factor associated with the segment that contains the + * target segment. + * + * The relocation could be a relative relocation, in which + * case we have to first subtract the amount we've relocated + * the containing segment by. + */ + if (!get_seglocation(&segs, hr->r.refseg, &seg, &offset)) { + fprintf(stderr, + "%s: reloc to undefined segment %04x\n", + cur->name, (int)hr->r.refseg); + errorcount++; + break; + } + + isrelative = + (hr->r.segment & RDOFF_RELATIVEMASK) == + RDOFF_RELATIVEMASK; + hr->r.segment &= (RDOFF_RELATIVEMASK - 1); + + if (hr->r.segment == 2 || + (localseg = + rdffindsegment(&cur->f, hr->r.segment)) == -1) { + fprintf(stderr, "%s: reloc from %s segment (%d)\n", + cur->name, + hr->r.segment == 2 ? "BSS" : "unknown", + hr->r.segment); + errorcount++; + break; + } + + if (hr->r.length != 1 && hr->r.length != 2 && + hr->r.length != 4) { + fprintf(stderr, "%s: nonstandard length reloc " + "(%d bytes)\n", cur->name, hr->r.length); + errorcount++; + break; + } + + /* + * okay, now the relocation is in the segment pointed to by + * cur->seginfo[localseg], and we know everything else is + * okay to go ahead and do the relocation + */ + data = outputseg[cur->seginfo[localseg].dest_seg].data; + data += cur->seginfo[localseg].reloc + hr->r.offset; + + /* + * data now points to the reference that needs + * relocation. Calculate the relocation factor. + * Factor is: + * offset of referred object in segment [in offset] + * (- relocation of localseg, if ref is relative) + * For simplicity, the result is stored in 'offset'. + * Then add 'offset' onto the value at data. + */ + + if (isrelative) + offset -= cur->seginfo[localseg].reloc; + switch (hr->r.length) { + case 1: + offset += *data; + if (offset < -127 || offset > 128) + fprintf(error_file, + "warning: relocation out of range " + "at %s(%02x:%08lx)\n", cur->name, + (int)hr->r.segment, hr->r.offset); + *data = (char)offset; + break; + case 2: + offset += *(short *)data; + if (offset < -32767 || offset > 32768) + fprintf(error_file, + "warning: relocation out of range " + "at %s(%02x:%08lx)\n", cur->name, + (int)hr->r.segment, hr->r.offset); + *(short *)data = (short)offset; + break; + case 4: + *(long *)data += offset; + /* we can't easily detect overflow on this one */ + break; + } + + /* + * If the relocation was relative between two symbols in + * the same segment, then we're done. + * + * Otherwise, we need to output a new relocation record + * with the references updated segment and offset... + */ + if (!isrelative || cur->seginfo[localseg].dest_seg != seg) { + hr->r.segment = cur->seginfo[localseg].dest_seg; + hr->r.offset += cur->seginfo[localseg].reloc; + hr->r.refseg = seg; + if (isrelative) + hr->r.segment += RDOFF_RELATIVEMASK; + rdfaddheader(rdfheader, hr); + } + break; + + case RDFREC_IMPORT: /* import symbol */ + case RDFREC_FARIMPORT: + /* + * scan the global symbol table for the symbol + * and associate its location with the segment number + * for this module + */ + se = symtabFind(symtab, hr->i.label); + if (!se || se->segment == -1) { + if (!options.dynalink && !(hr->i.flags & SYM_IMPORT)) { + fprintf(error_file, + "error: unresolved reference to `%s'" + " in module `%s'\n", hr->i.label, + cur->name); + errorcount++; + } + /* + * we need to allocate a segment number for this + * symbol, and store it in the symbol table for + * future reference + */ + if (!se) { + se = malloc(sizeof(*se)); + if (!se) { + fprintf(stderr, "ldrdf: out of memory\n"); + exit(1); + } + se->name = strdup(hr->i.label); + se->flags = 0; + se->segment = availableseg++; + se->offset = 0; + symtabInsert(symtab, se); + } else { + se->segment = availableseg++; + se->offset = 0; + } + /* + * output a header record that imports it to the + * recently allocated segment number... + */ + newrec = *hr; + newrec.i.segment = se->segment; + rdfaddheader(rdfheader, &newrec); + } + + add_seglocation(&segs, hr->i.segment, se->segment, + se->offset); + break; + + case RDFREC_GLOBAL: /* export symbol */ + /* + * need to insert an export for this symbol into the new + * header, unless we're stripping symbols. Even if we're + * stripping, put the symbol if it's marked as SYM_GLOBAL. + */ + if (options.strip && !(hr->e.flags & SYM_GLOBAL)) + break; + + if (hr->e.segment == 2) { + seg = 2; + offset = cur->bss_reloc; + } else { + localseg = rdffindsegment(&cur->f, hr->e.segment); + if (localseg == -1) { + fprintf(stderr, "%s: exported symbol `%s' from " + "unrecognised segment\n", cur->name, + hr->e.label); + errorcount++; + break; + } + offset = cur->seginfo[localseg].reloc; + seg = cur->seginfo[localseg].dest_seg; + } + + hr->e.segment = seg; + hr->e.offset += offset; + rdfaddheader(rdfheader, hr); + break; + + case RDFREC_MODNAME: /* module name */ + /* + * Insert module name record if export symbols + * are not stripped. + * If module name begins with '$' - insert it anyway. + */ + if (options.strip && hr->m.modname[0] != '$') + break; + rdfaddheader(rdfheader, hr); + break; + + case RDFREC_DLL: /* DLL name */ + /* + * Insert DLL name if it begins with '$' + */ + if (hr->d.libname[0] != '$') + break; + rdfaddheader(rdfheader, hr); + break; + + case RDFREC_SEGRELOC: /* segment fixup */ + /* + * modify the segment numbers if necessary, and + * pass straight through to the output module header + * + * *** FIXME *** + */ + if (hr->r.segment == 2) { + fprintf(stderr, "%s: segment fixup in BSS section\n", + cur->name); + errorcount++; + break; + } + localseg = rdffindsegment(&cur->f, hr->r.segment); + if (localseg == -1) { + fprintf(stderr, "%s: segment fixup in unrecognised" + " segment (%d)\n", cur->name, hr->r.segment); + errorcount++; + break; + } + hr->r.segment = cur->seginfo[localseg].dest_seg; + hr->r.offset += cur->seginfo[localseg].reloc; + + if (!get_seglocation(&segs, hr->r.refseg, &seg, &offset)) { + fprintf(stderr, "%s: segment fixup to undefined " + "segment %04x\n", cur->name, + (int)hr->r.refseg); + errorcount++; + break; + } + hr->r.refseg = seg; + rdfaddheader(rdfheader, hr); + break; + + case RDFREC_COMMON: /* Common variable */ + /* Is this symbol already in the table? */ + se = symtabFind(symtab, hr->c.label); + if (!se) { + printf("%s is not in symtab yet\n", hr->c.label); + break; + } + /* Add segment location */ + add_seglocation(&segs, hr->c.segment, se->segment, + se->offset); + break; + } + } + + free(header); + done_seglocations(&segs); } @@ -1065,33 +1083,35 @@ void write_output(const char * filename) * Write the header */ for (i = 0; i < nsegs; i++) { - if (i == 2) continue; - rdfaddsegment (rdfheader, outputseg[i].length); + if (i == 2) + continue; + rdfaddsegment(rdfheader, outputseg[i].length); } - + rdfwriteheader(f, rdfheader); rdfdoneheader(rdfheader); - + /* * Step through the segments, one at a time, writing out into * the output file */ for (i = 0; i < nsegs; i++) { - uint16 s; - long l; - - if (i == 2) continue; - - s = translateshort(outputseg[i].type); - fwrite(&s, 2, 1, f); - s = translateshort(outputseg[i].number); - fwrite(&s, 2, 1, f); - s = translateshort(outputseg[i].reserved); - fwrite(&s, 2, 1, f); - l = translatelong(outputseg[i].length); - fwrite(&l, 4, 1, f); - - fwrite(outputseg[i].data, outputseg[i].length, 1, f); + uint16 s; + long l; + + if (i == 2) + continue; + + s = translateshort(outputseg[i].type); + fwrite(&s, 2, 1, f); + s = translateshort(outputseg[i].number); + fwrite(&s, 2, 1, f); + s = translateshort(outputseg[i].reserved); + fwrite(&s, 2, 1, f); + l = translatelong(outputseg[i].length); + fwrite(&l, 4, 1, f); + + fwrite(outputseg[i].data, outputseg[i].length, 1, f); } fwrite("\0\0\0\0\0\0\0\0\0\0", 10, 1, f); @@ -1118,11 +1138,11 @@ void usage() exit(0); } -int main(int argc, char ** argv) +int main(int argc, char **argv) { - char * outname = "aout.rdf"; - int moduleloaded = 0; - char *respstrings[128] = {0, }; + char *outname = "aout.rdf"; + int moduleloaded = 0; + char *respstrings[128] = { 0, }; options.verbose = 0; options.align = 16; @@ -1132,166 +1152,177 @@ int main(int argc, char ** argv) error_file = stderr; argc--, argv++; - if (argc == 0) usage(); + if (argc == 0) + usage(); while (argc && *argv && **argv == '-' && argv[0][1] != 'l') { - switch(argv[0][1]) { - case 'r': - printf("ldrdf (linker for RDF files) version " LDRDF_VERSION "\n"); - printf("RDOFF2 revision %s\n", RDOFF2_REVISION); - exit(0); - case 'v': - if (argv[0][2] == '=') { - options.verbose = argv[0][3] - '0'; - if (options.verbose < 0 || options.verbose > 9) { - fprintf(stderr, "ldrdf: verbosity level must be a number" - " between 0 and 9\n"); - exit(1); - } - } - else - options.verbose++; - break; - case 'a': - options.align = atoi(argv[1]); - if (options.align <= 0) { - fprintf(stderr, - "ldrdf: -a expects a positive number argument\n"); - exit(1); - } - argv++, argc--; - break; - case 's': - options.strip = 1; - break; - case 'd': - if (argv[0][2] == 'y') options.dynalink = 1; - break; - case 'o': - outname = argv[1]; - argv++, argc--; - break; - case 'j': - if (!objpath) { - options.objpath = 1; - objpath = argv[1]; - argv++, argc--; - break; - } else { - fprintf(stderr,"ldrdf: more than one objects search path specified\n"); - exit(1); - } - case 'L': - if (!libpath) { - options.libpath = 1; - libpath = argv[1]; - argv++, argc--; - break; - } else { - fprintf(stderr,"ldrdf: more than one libraries search path specified\n"); - exit(1); - } - case '@': { - int i=0; - char buf[256]; - FILE *f; - - options.respfile = 1; - if (argv[1] != NULL) f = fopen(argv[1],"r"); - else { - fprintf(stderr,"ldrdf: no response file name specified\n"); - exit(1); - } - - if (f == NULL) { - fprintf(stderr,"ldrdf: unable to open response file\n"); - exit(1); - } - - argv++, argc--; - while (fgets(buf, sizeof(buf), f) != NULL) { - char *p; - if (buf[0]=='\n') continue; - if ((p = strchr(buf,'\n')) != NULL) *p = '\0'; - if (i >= 128) { - fprintf(stderr,"ldrdf: too many input files\n"); - exit(1); - } - *(respstrings + i) = newstr(buf); - argc++, i++; - } + switch (argv[0][1]) { + case 'r': + printf("ldrdf (linker for RDF files) version " LDRDF_VERSION + "\n"); + printf("RDOFF2 revision %s\n", RDOFF2_REVISION); + exit(0); + case 'v': + if (argv[0][2] == '=') { + options.verbose = argv[0][3] - '0'; + if (options.verbose < 0 || options.verbose > 9) { + fprintf(stderr, + "ldrdf: verbosity level must be a number" + " between 0 and 9\n"); + exit(1); + } + } else + options.verbose++; + break; + case 'a': + options.align = atoi(argv[1]); + if (options.align <= 0) { + fprintf(stderr, + "ldrdf: -a expects a positive number argument\n"); + exit(1); + } + argv++, argc--; + break; + case 's': + options.strip = 1; break; - } - case '2': + case 'd': + if (argv[0][2] == 'y') + options.dynalink = 1; + break; + case 'o': + outname = argv[1]; + argv++, argc--; + break; + case 'j': + if (!objpath) { + options.objpath = 1; + objpath = argv[1]; + argv++, argc--; + break; + } else { + fprintf(stderr, + "ldrdf: more than one objects search path specified\n"); + exit(1); + } + case 'L': + if (!libpath) { + options.libpath = 1; + libpath = argv[1]; + argv++, argc--; + break; + } else { + fprintf(stderr, + "ldrdf: more than one libraries search path specified\n"); + exit(1); + } + case '@':{ + int i = 0; + char buf[256]; + FILE *f; + + options.respfile = 1; + if (argv[1] != NULL) + f = fopen(argv[1], "r"); + else { + fprintf(stderr, + "ldrdf: no response file name specified\n"); + exit(1); + } + + if (f == NULL) { + fprintf(stderr, + "ldrdf: unable to open response file\n"); + exit(1); + } + + argv++, argc--; + while (fgets(buf, sizeof(buf), f) != NULL) { + char *p; + if (buf[0] == '\n') + continue; + if ((p = strchr(buf, '\n')) != NULL) + *p = '\0'; + if (i >= 128) { + fprintf(stderr, "ldrdf: too many input files\n"); + exit(1); + } + *(respstrings + i) = newstr(buf); + argc++, i++; + } + break; + } + case '2': options.stderr_redir = 1; - error_file = stdout; - break; - case 'g': - generic_rec_file = argv[1]; - argv++, argc--; - break; - default: - usage(); - } - argv++, argc--; + error_file = stdout; + break; + case 'g': + generic_rec_file = argv[1]; + argv++, argc--; + break; + default: + usage(); + } + argv++, argc--; } if (options.verbose > 4) { - printf("ldrdf invoked with options:\n"); - printf(" section alignment: %d bytes\n", options.align); - printf(" output name: `%s'\n", outname); - if (options.strip) - printf(" strip symbols\n"); - if (options.dynalink) - printf(" Unix-style dynamic linking\n"); + printf("ldrdf invoked with options:\n"); + printf(" section alignment: %d bytes\n", options.align); + printf(" output name: `%s'\n", outname); + if (options.strip) + printf(" strip symbols\n"); + if (options.dynalink) + printf(" Unix-style dynamic linking\n"); if (options.objpath) printf(" objects search path: %s\n", objpath); if (options.libpath) printf(" libraries search path: %s\n", libpath); - printf("\n"); + printf("\n"); } symtab = symtabNew(); initsegments(); if (!symtab) { - fprintf(stderr, "ldrdf: out of memory\n"); - exit(1); + fprintf(stderr, "ldrdf: out of memory\n"); + exit(1); } while (argc) { - if (!*argv) argv = respstrings; - if (!*argv) break; - if (!strncmp(*argv, "-l", 2)) { - if(libpath && (argv[0][2] != '/')) - add_library(newstrcat(libpath,*argv + 2)); + if (!*argv) + argv = respstrings; + if (!*argv) + break; + if (!strncmp(*argv, "-l", 2)) { + if (libpath && (argv[0][2] != '/')) + add_library(newstrcat(libpath, *argv + 2)); else - add_library(*argv + 2); + add_library(*argv + 2); } else { - if(objpath && (argv[0][0] != '/')) - loadmodule(newstrcat(objpath, *argv)); - else - loadmodule(*argv); - moduleloaded = 1; - } - argv++, argc--; + if (objpath && (argv[0][0] != '/')) + loadmodule(newstrcat(objpath, *argv)); + else + loadmodule(*argv); + moduleloaded = 1; + } + argv++, argc--; } - if (! moduleloaded) { - printf("ldrdf: nothing to do. ldrdf -h for usage\n"); - return 0; + if (!moduleloaded) { + printf("ldrdf: nothing to do. ldrdf -h for usage\n"); + return 0; } search_libraries(); - if (options.verbose > 2) - { - printf ("symbol table:\n"); - symtabDump(symtab, stdout); + if (options.verbose > 2) { + printf("symbol table:\n"); + symtabDump(symtab, stdout); } write_output(outname); - if (errorcount > 0) exit(1); + if (errorcount > 0) + exit(1); return 0; } - |