diff options
Diffstat (limited to 'rdoff/ldrdf1.c')
-rw-r--r-- | rdoff/ldrdf1.c | 728 |
1 files changed, 0 insertions, 728 deletions
diff --git a/rdoff/ldrdf1.c b/rdoff/ldrdf1.c deleted file mode 100644 index 9e4a215..0000000 --- a/rdoff/ldrdf1.c +++ /dev/null @@ -1,728 +0,0 @@ -/* ldrdf.c RDOFF Object File linker/loader main program - * - * The Netwide Assembler is copyright (C) 1996 Simon Tatham and - * Julian Hall. All rights reserved. The software is - * redistributable under the licence given in the file "Licence" - * distributed in the NASM archive. - */ - -/* TODO: Make the system skip a module (other than the first) if none - * of the other specified modules contain a reference to it. - * May require the system to make an extra pass of the modules to be - * loaded eliminating those that aren't required. - * - * Support all the existing documented options... - * - * Support libaries (.a files - requires a 'ranlib' type utility) - * (I think I've got this working, so I've upped the version) - * - * -s option to strip resolved symbols from exports. (Could make this an - * external utility) - */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include "rdoff.h" -#include "nasmlib.h" -#include "symtab.h" -#include "collectn.h" -#include "rdlib.h" - -#define LDRDF_VERSION "0.30" - -/* global variables - those to set options: */ - -int verbose = 0; /* reflects setting of command line switch */ -int align = 16; -int errors = 0; /* set by functions to cause halt after current - stage of processing */ - -/* the linked list of modules that must be loaded & linked */ - -struct modulenode { - rdffile f; /* the file */ - long coderel; /* module's code relocation factor */ - long datarel; /* module's data relocation factor */ - long bssrel; /* module's bss data reloc. factor */ - void * header; /* header location, if loaded */ - char * name; /* filename */ - struct modulenode *next; -}; - -#define newstr(str) strcpy(malloc(strlen(str) + 1),str) -#define newstrcat(s1,s2) strcat(strcpy(malloc(strlen(s1)+strlen(s2)+1),s1),s2) - - -struct modulenode *modules = NULL,*lastmodule = NULL; - -/* the linked list of libraries to be searched for missing imported - symbols */ - -struct librarynode * libraries = NULL, * lastlib = NULL; - -void *symtab; /* The symbol table */ - -rdf_headerbuf * newheader ; /* New header to be written to output */ - -/* loadmodule - find the characteristics of a module and add it to the - * list of those being linked together */ - -void loadmodule(char *filename) -{ - struct modulenode *prev; - if (! modules) { - modules = malloc(sizeof(struct modulenode)); - lastmodule = modules; - prev = NULL; - } - else { - lastmodule->next = malloc(sizeof(struct modulenode)); - prev = lastmodule; - lastmodule = lastmodule->next; - } - - if (! lastmodule) { - fputs("ldrdf: not enough memory\n",stderr); - exit(1); - } - - if (rdfopen(&lastmodule->f,filename)) { - rdfperror("ldrdf",filename); - exit(1); - } - - lastmodule->header = NULL; /* header hasn't been loaded */ - lastmodule->name = filename; - lastmodule->next = NULL; - - if (prev) { - lastmodule->coderel = prev->coderel + prev->f.code_len; - if (lastmodule->coderel % align != 0) - lastmodule->coderel += align - (lastmodule->coderel % align); - lastmodule->datarel = prev->datarel + prev->f.data_len; - if (lastmodule->datarel % align != 0) - lastmodule->datarel += align - (lastmodule->datarel % align); - } - else { - lastmodule->coderel = 0; - lastmodule->datarel = 0; - } - - if (verbose) - printf("%s code = %08lx (+%04lx), data = %08lx (+%04lx)\n",filename, - lastmodule->coderel,lastmodule->f.code_len, - lastmodule->datarel,lastmodule->f.data_len); - - lastmodule->header = malloc(lastmodule->f.header_len); - if (!lastmodule->header) { - fprintf(stderr,"ldrdf: out of memory\n"); - exit(1); - } - - if (rdfloadseg(&lastmodule->f,RDOFF_HEADER,lastmodule->header)) - { - rdfperror("ldrdf",filename); - exit(1); - } -} - -/* load_library add a library to list of libraries to search - * for undefined symbols - */ - -void load_library(char * name) -{ - if (verbose) - printf("adding library %s to search path\n",name); - - if (! lastlib) { - lastlib = libraries = malloc(sizeof(struct librarynode)); - } - else - { - lastlib->next = malloc(sizeof(struct librarynode)); - lastlib = lastlib->next; - } - - if (! lastlib) { - fprintf(stderr, "ldrdf: out of memory\n"); - exit(1); - } - strcpy (lastlib->name = malloc (1+strlen(name)), name); - lastlib->fp = NULL; - lastlib->referenced = 0; - lastlib->next = NULL; -} - - -/* build_symbols() step through each module's header, and locate - * exported symbols, placing them in a global table - */ - -long bsslength; - -void mod_addsymbols(struct modulenode * mod) -{ - rdfheaderrec *r; - symtabEnt e; - long cbBss; - - mod->bssrel = bsslength; - cbBss = 0; - rdfheaderrewind(&mod->f); - while ((r = rdfgetheaderrec(&mod->f))) - { - - if (r->type == 5) /* Allocate BSS */ - cbBss += r->b.amount; - - if (r->type != 3) continue; /* ignore all but export recs */ - - e.segment = r->e.segment; - e.offset = r->e.offset + - (e.segment == 0 ? mod->coderel : /* 0 -> code */ - e.segment == 1 ? mod->datarel : /* 1 -> data */ - mod->bssrel) ; /* 2 -> bss */ - - e.flags = 0; - e.name = malloc(strlen(r->e.label) + 1); - if (! e.name) - { - fprintf(stderr,"ldrdf: out of memory\n"); - exit(1); - } - strcpy(e.name,r->e.label); - symtabInsert(symtab,&e); - } - bsslength += cbBss; -} - -void build_symbols() -{ - struct modulenode *mod; - - if (verbose) printf("building global symbol table:\n"); - newheader = rdfnewheader(); - - symtab = symtabNew(); - bsslength = 0; /* keep track of location of BSS symbols */ - - for (mod = modules; mod; mod = mod->next) - { - mod_addsymbols( mod ); - } - if (verbose) - { - symtabDump(symtab,stdout); - printf("BSS length = %ld bytes\n\n",bsslength); - } -} - - -/* scan_libraries() search through headers of modules for undefined - * symbols, and scan libraries for those symbols, - * adding library modules found to list of modules - * to load. */ - -void scan_libraries(void) -{ - struct modulenode * mod, * nm; - struct librarynode * lib; - rdfheaderrec * r; - int found; - char * tmp; - - if (verbose) printf("Scanning libraries for unresolved symbols...\n"); - - mod = modules; - - while (mod) - { - rdfheaderrewind(&mod->f); - - while ((r = rdfgetheaderrec(&mod->f))) - { - if (r->type != 2) continue; /* not an import record */ - if ( symtabFind (symtab,r->i.label) ) - continue; /* symbol already defined */ - - /* okay, we have an undefined symbol... step through - the libraries now */ - if (verbose >= 2) { - printf("undefined symbol '%s'...",r->i.label); - fflush(stdout); - } - - lib = libraries; - found = 0; - - tmp = newstr(r->i.label); - while (! found && lib) - { - /* move this to an outer loop...! */ - nm = malloc(sizeof(struct modulenode)); - - if (rdl_searchlib(lib,tmp,&nm->f)) - { /* found a module in the library */ - - /* create a modulenode for it */ - - if (! nm) { - fprintf(stderr,"ldrdf: out of memory\n"); - exit(1); - } - - nm->name = newstrcat(lib->name,nm->f.name); - if (verbose >= 2) printf("found in '%s'\n",nm->name); - - nm->coderel = lastmodule->coderel + lastmodule->f.code_len; - if (nm->coderel % align != 0) - nm->coderel += align - (nm->coderel % align); - - nm->datarel = lastmodule->datarel + lastmodule->f.data_len; - if (nm->datarel % align != 0) - nm->datarel += align - (nm->datarel % align); - - nm->header = malloc(nm->f.header_len); - if (! nm->header) - { - fprintf(stderr,"ldrdf: out of memory\n"); - exit(1); - } - - if (rdfloadseg(&nm->f,RDOFF_HEADER,nm->header)) - { - rdfperror("ldrdf",nm->name); - exit(1); - } - - nm->next = NULL; - found = 1; - lastmodule->next = nm; - lastmodule = nm; - - if (verbose) - printf("%s code = %08lx (+%04lx), data = %08lx " - "(+%04lx)\n",lastmodule->name, - lastmodule->coderel,lastmodule->f.code_len, - lastmodule->datarel,lastmodule->f.data_len); - - /* add the module's info to the symbol table */ - mod_addsymbols(nm); - } - else - { - if (rdl_error) { - rdl_perror("ldrdf",lib->name); - exit(1); - } - free(nm); - } - lib = lib->next; - } - free(tmp); - if (!found && verbose >= 2) printf("not found\n"); - } - mod = mod->next; - } -} - -/* load_segments() allocates memory for & loads the code & data segs - * from the RDF modules - */ - -char *text,*data; -long textlength,datalength; - -void load_segments(void) -{ - struct modulenode *mod; - - if (!modules) { - fprintf(stderr,"ldrdf: nothing to do\n"); - exit(0); - } - if (!lastmodule) { - fprintf(stderr,"ldrdf: panic: module list exists, but lastmodule=NULL\n"); - exit(3); - } - - if (verbose) - printf("loading modules into memory\n"); - - /* The following stops 16 bit DOS from crashing whilst attempting to - work using segments > 64K */ - if (sizeof(int) == 2) { /* expect a 'code has no effect' warning on 32 bit - platforms... */ - if (lastmodule->coderel + lastmodule->f.code_len > 65535 || - lastmodule->datarel + lastmodule->f.data_len > 65535) { - fprintf(stderr,"ldrdf: segment length has exceeded 64K; use a 32 bit " - "version.\nldrdf: code size = %05lx, data size = %05lx\n", - lastmodule->coderel + lastmodule->f.code_len, - lastmodule->datarel + lastmodule->f.data_len); - exit(1); - } - } - - text = malloc(textlength = lastmodule->coderel + lastmodule->f.code_len); - data = malloc(datalength = lastmodule->datarel + lastmodule->f.data_len); - - if (!text || !data) { - fprintf(stderr,"ldrdf: out of memory\n"); - exit(1); - } - - mod = modules; - while (mod) { /* load the segments for each module */ - if (verbose >= 2) printf(" loading %s\n",mod->name); - if (rdfloadseg(&mod->f,RDOFF_CODE,&text[mod->coderel]) || - rdfloadseg(&mod->f,RDOFF_DATA,&data[mod->datarel])) { - rdfperror("ldrdf",mod->name); - exit(1); - } - rdfclose(&mod->f); /* close file; segments remain */ - mod = mod->next; - } -} - -/* link_segments() step through relocation records in each module's - * header, fixing up references. - */ - -void link_segments(void) -{ - struct modulenode *mod; - Collection imports; - symtabEnt *s; - long rel,relto; - char *seg; - rdfheaderrec *r; - int bRelative; - - if (verbose) printf("linking segments\n"); - - collection_init(&imports); - - for (mod = modules; mod; mod = mod->next) { - if (verbose >= 2) printf("* processing %s\n",mod->name); - rdfheaderrewind(&mod->f); - while((r = rdfgetheaderrec(&mod->f))) { - if (verbose >= 3) printf("record type: %d\n",r->type); - switch(r->type) { - case 1: /* relocation record */ - if (r->r.segment >= 64) { /* Relative relocation; */ - bRelative = 1; /* need to find location relative */ - r->r.segment -= 64; /* to start of this segment */ - relto = r->r.segment == 0 ? mod->coderel : mod->datarel; - } - else - { - bRelative = 0; /* non-relative - need to relocate - * at load time */ - relto = 0; /* placate optimiser warnings */ - } - - /* calculate absolute offset of reference, not rel to beginning of - segment */ - r->r.offset += r->r.segment == 0 ? mod->coderel : mod->datarel; - - /* calculate the relocation factor to apply to the operand - - the base address of one of this modules segments if referred - segment is 0 - 2, or the address of an imported symbol - otherwise. */ - - if (r->r.refseg == 0) rel = mod->coderel; - else if (r->r.refseg == 1) rel = mod->datarel; - else if (r->r.refseg == 2) rel = mod->bssrel; - else { /* cross module link - find reference */ - s = *colln(&imports,r->r.refseg - 2); - if (!s) { - fprintf(stderr,"ldrdf: link to undefined segment %04x in" - " %s:%d\n", r->r.refseg,mod->name,r->r.segment); - errors = 1; - break; - } - rel = s->offset; - - r->r.refseg = s->segment; /* change referred segment, - so that new header is - correct */ - } - - if (bRelative) /* Relative - subtract current segment start */ - rel -= relto; - else - { /* Add new relocation header */ - rdfaddheader(newheader,r); - } - - /* Work out which segment we're making changes to ... */ - if (r->r.segment == 0) seg = text; - else if (r->r.segment == 1) seg = data; - else { - fprintf(stderr,"ldrdf: relocation in unknown segment %d in " - "%s\n", r->r.segment,mod->name); - errors = 1; - break; - } - - /* Add the relocation factor to the datum specified: */ - - if (verbose >= 3) - printf(" - relocating %d:%08lx by %08lx\n",r->r.segment, - r->r.offset,rel); - - /**** The following code is non-portable. Rewrite it... ****/ - switch(r->r.length) { - case 1: - seg[r->r.offset] += (char) rel; - break; - case 2: - *(int16 *)(seg + r->r.offset) += (int16) rel; - break; - case 4: - *(long *)(seg + r->r.offset) += rel; - break; - } - break; - - case 2: /* import record */ - s = symtabFind(symtab, r->i.label); - if (s == NULL) { - /* Need to add support for dynamic linkage */ - fprintf(stderr,"ldrdf: undefined symbol %s in module %s\n", - r->i.label,mod->name); - errors = 1; - } - else - { - *colln(&imports,r->i.segment - 2) = s; - if (verbose >= 2) - printf("imported %s as %04x\n", r->i.label, r->i.segment); - } - break; - - case 3: /* export; dump to output new version */ - s = symtabFind(symtab, r->e.label); - if (! s) { - fprintf(stderr,"ldrdf: internal error - undefined symbol %s " - "exported in header of '%s'\n",r->e.label,mod->name); - continue; - } - r->e.offset = s->offset; - rdfaddheader(newheader,r); - break; - - case 4: /* DLL record */ - rdfaddheader(newheader,r); /* copy straight to output */ - break; - } - } - if (rdf_errno != 0) { - rdfperror("ldrdf",mod->name); - exit(1); - } - collection_reset(&imports); - } -} - -/* write_output() write linked program out to a file */ - -void write_output(char *filename) -{ - FILE * fp; - rdfheaderrec r; - - if (verbose) printf("writing output to '%s'\n",filename); - - fp = fopen(filename,"wb"); - if (! fp) - { - fprintf(stderr,"ldrdf: could not open '%s' for writing\n",filename); - exit(1); - } - - - /* add BSS length count to header... */ - if (bsslength) - { - r.type = 5; - r.b.amount = bsslength; - rdfaddheader(newheader,&r); - } - - /* Write header */ - rdfwriteheader(fp,newheader); - rdfdoneheader(newheader); - newheader = NULL; - - /* Write text */ - if (fwrite(&textlength,1,4,fp) != 4 - || fwrite(text,1,textlength,fp) !=textlength) - { - fprintf(stderr,"ldrdf: error writing %s\n",filename); - exit(1); - } - - /* Write data */ - if (fwrite(&datalength,1,4,fp) != 4 || - fwrite(data,1,datalength,fp) != datalength) - { - fprintf (stderr,"ldrdf: error writing %s\n", filename); - exit(1); - } - fclose(fp); -} - - -/* main program: interpret command line, and pass parameters on to - * individual module loaders & the linker - * - * Command line format: - * ldrdf [-o outfile | -x] [-r xxxx] [-v] [--] infile [infile ...] - * - * Default action is to output a file named 'aout.rdx'. -x specifies - * that the linked object program should be executed, rather than - * written to a file. -r specifies that the object program should - * be prelocated at address 'xxxx'. This option cannot be used - * in conjunction with -x. - */ - -const char *usagemsg = "usage:\n" -" ldrdf [-o outfile | -x] [-a x] [-v] [-p x] [--] infile [infile ...]\n" -" [-l<libname> ...]\n\n" -" ldrdf -h displays this message\n" -" ldrdf -r displays version information\n\n" -" -o selects output filename (default is aout.rdx)\n" -" -x causes ldrdx to link & execute rather than write to file\n" -" -a x causes object program to be statically relocated to address 'x'\n" -" -v turns on verbose mode\n" -" -p x causes segments to be aligned (padded) to x byte boundaries\n" -" (default is 16 bytes)\n" -" -l<name> causes 'name' to be linked in as a library. Note no search is\n" -" performed - the entire pathname MUST be specified.\n"; - -void usage(void) -{ - fputs(usagemsg,stderr); -} - -int main(int argc,char **argv) -{ - char *ofilename = "aout.rdx"; - long relocateaddr = -1; /* -1 if no relocation is to occur */ - int execute = 0; /* 1 to execute after linking, 0 otherwise */ - int procsw = 1; /* set to 0 by '--' */ - int tmp; - - if (argc == 1) { - usage(); - exit(1); - } - - /* process command line switches, and add modules specified to linked list - of modules, keeping track of total memory required to load them */ - - while(argv++,--argc) { - if (procsw && !strcmp(*argv,"-h")) { /* Help command */ - usage(); exit(1); - } - else if (procsw && !strcmp(*argv,"-r")) { - printf("ldrdf version %s (%s) (%s)\n",LDRDF_VERSION,_RDOFF_H, - sizeof(int) == 2 ? "16 bit" : "32 bit"); - exit(1); - } - else if (procsw && !strcmp(*argv,"-o")) { - ofilename = *++argv; - --argc; - if (execute) { - fprintf(stderr,"ldrdf: -o and -x switches incompatible\n"); - exit(1); - } - if (verbose > 1) printf("output filename set to '%s'\n",ofilename); - } - else if (procsw && !strcmp(*argv,"-x")) { - execute++; - if (verbose > 1) printf("will execute linked object\n"); - } - else if (procsw && !strcmp(*argv,"-a")) { - relocateaddr = readnum(*++argv,&tmp); - --argc; - if (tmp) { - fprintf(stderr,"ldrdf: error in parameter to '-a' switch: '%s'\n", - *argv); - exit(1); - } - if (execute) { - fprintf(stderr,"ldrdf: -a and -x switches incompatible\n"); - exit(1); - } - if (verbose) printf("will relocate to %08lx\n",relocateaddr); - } - else if (procsw && !strcmp(*argv,"-v")) { - verbose++; - if (verbose == 1) printf("verbose mode selected\n"); - } - else if (procsw && !strcmp(*argv,"-p")) { - align = readnum(*++argv,&tmp); - --argc; - if (tmp) { - fprintf(stderr,"ldrdf: error in parameter to '-p' switch: '%s'\n", - *argv); - exit(1); - } - if (align != 1 && align != 2 && align != 4 && align != 8 && align != 16 - && align != 32 && align != 256) { - fprintf(stderr,"ldrdf: %d is an invalid alignment factor - must be" - "1,2,4,8,16 or 256\n",align); - exit(1); - } - if (verbose > 1) printf("alignment %d selected\n",align); - } - else if (procsw && !strncmp(*argv,"-l",2)) { - load_library(*argv + 2); - } - else if (procsw && !strcmp(*argv,"--")) { - procsw = 0; - } - else { /* is a filename */ - if (verbose > 1) printf("processing module %s\n",*argv); - loadmodule(*argv); - } - } - - /* we should be scanning for unresolved references, and removing - unreferenced modules from the list of modules here, so that - we know about the final size once libraries have been linked in */ - - build_symbols(); /* build a global symbol table... */ - - scan_libraries(); /* check for imported symbols not in table, - and ensure the relevant library modules - are loaded */ - - load_segments(); /* having calculated size of reqd segments, load - each rdoff module's segments into memory */ - - link_segments(); /* step through each module's header, and resolve - references to the global symbol table. - This also does local address fixups. */ - - if (errors) { - fprintf(stderr,"ldrdf: there were errors - aborted\n"); - exit(errors); - } - if (execute) { - fprintf(stderr,"ldrdf: module execution not yet supported\n"); - exit(1); - } - if (relocateaddr != -1) { - fprintf(stderr,"ldrdf: static relocation not yet supported\n"); - exit(1); - } - - write_output(ofilename); - return 0; -} |