diff options
author | H. Peter Anvin <hpa@zytor.com> | 2002-04-30 20:51:32 +0000 |
---|---|---|
committer | H. Peter Anvin <hpa@zytor.com> | 2002-04-30 20:51:32 +0000 |
commit | ea6e34db64c7da7cb885197316c6b5e7d048bdb9 (patch) | |
tree | 78e728348f8fe09e394a51c3617e6261de0f4001 /rdoff | |
download | nasm-ea6e34db64c7da7cb885197316c6b5e7d048bdb9.tar.gz nasm-ea6e34db64c7da7cb885197316c6b5e7d048bdb9.tar.bz2 nasm-ea6e34db64c7da7cb885197316c6b5e7d048bdb9.zip |
NASM 0.91
Diffstat (limited to 'rdoff')
-rw-r--r-- | rdoff/Makefile | 43 | ||||
-rw-r--r-- | rdoff/collectn.c | 40 | ||||
-rw-r--r-- | rdoff/collectn.h | 22 | ||||
-rw-r--r-- | rdoff/ldrdf.c | 540 | ||||
-rw-r--r-- | rdoff/rdf.doc | 99 | ||||
-rw-r--r-- | rdoff/rdfdump.c | 156 | ||||
-rw-r--r-- | rdoff/rdfload.c | 173 | ||||
-rw-r--r-- | rdoff/rdfload.h | 29 | ||||
-rw-r--r-- | rdoff/rdoff.c | 367 | ||||
-rw-r--r-- | rdoff/rdoff.h | 112 | ||||
-rw-r--r-- | rdoff/rdx.c | 61 | ||||
-rw-r--r-- | rdoff/symtab.c | 80 | ||||
-rw-r--r-- | rdoff/symtab.h | 22 |
13 files changed, 1744 insertions, 0 deletions
diff --git a/rdoff/Makefile b/rdoff/Makefile new file mode 100644 index 0000000..2e55dde --- /dev/null +++ b/rdoff/Makefile @@ -0,0 +1,43 @@ +# Makefile for RDOFF object file utils; part of the Netwide Assembler +# +# 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. +# +# This Makefile is designed for use under Unix (probably fairly +# portably). + +CC = gcc +CCFLAGS = -c -O -g -Wall -ansi -pedantic -I.. +LINK = gcc +LINKFLAGS = -o +DLINKFLAGS = -o +LIBRARIES = +STRIP = strip +LDRDFLIBS = rdoff.o ../nasmlib.o symtab.o collectn.o +RDXLIBS = rdoff.o rdfload.o symtab.o collectn.o + +.c.o: + $(CC) $(CCFLAGS) $*.c + +all : rdfdump ldrdf rdx + +rdfdump : rdfdump.o + $(LINK) $(LINKFLAGS) rdfdump rdfdump.o +ldrdf : ldrdf.o $(LDRDFLIBS) + $(LINK) $(LINKFLAGS) ldrdf ldrdf.o $(LDRDFLIBS) +rdx : rdx.o $(RDXLIBS) + $(LINK) $(LINKFLAGS) rdx rdx.o $(RDXLIBS) + +rdfdump.o : rdfdump.c +rdoff.o : rdoff.c rdoff.h +ldrdf.o : ldrdf.c rdoff.h ../nasmlib.h symtab.h collectn.h +symtab.o : symtab.c symtab.h +collectn.o : collectn.c collectn.h +rdx.o : rdx.c rdoff.h rdfload.h symtab.h +rdfload.o : rdfload.c rdfload.h rdoff.h collectn.h symtab.h + +clean : + rm -f *.o *~ rdfdump ldrdf rdx + make -C test clean diff --git a/rdoff/collectn.c b/rdoff/collectn.c new file mode 100644 index 0000000..c265c95 --- /dev/null +++ b/rdoff/collectn.c @@ -0,0 +1,40 @@ +/* collectn.c Implements variable length pointer arrays [collections] + * + * This file is public domain. + */ + +#include "collectn.h" +#include <stdlib.h> + +void collection_init(Collection * c) +{ + int i; + + for (i = 0; i < 32; i++) c->p[i] = NULL; + c->next = NULL; +} + +void ** colln(Collection * c, int index) +{ + while (index >= 32) { + index -= 32; + if (c->next == NULL) { + c->next = malloc(sizeof(Collection)); + collection_init(c->next); + } + c = c->next; + } + return &(c->p[index]); +} + +void collection_reset(Collection *c) +{ + int i; + if (c->next) { + collection_reset(c->next); + free(c->next); + } + + c->next = NULL; + for (i = 0; i < 32; i++) c->p[i] = NULL; +} diff --git a/rdoff/collectn.h b/rdoff/collectn.h new file mode 100644 index 0000000..b3f2d52 --- /dev/null +++ b/rdoff/collectn.h @@ -0,0 +1,22 @@ +/* collectn.h Header file for 'collection' abstract data type + * + * This file is public domain, and does not come under the NASM license. + * It, along with 'collectn.c' implements what is basically a variable + * length array (of pointers) + */ + +#ifndef _COLLECTN_H +#define _COLLECTN_H + +typedef struct tagCollection { + void *p[32]; /* array of pointers to objects */ + + struct tagCollection *next; +} Collection; + +void collection_init(Collection * c); +void ** colln(Collection * c, int index); +void collection_reset(Collection * c); + +#endif + diff --git a/rdoff/ldrdf.c b/rdoff/ldrdf.c new file mode 100644 index 0000000..ce86b7e --- /dev/null +++ b/rdoff/ldrdf.c @@ -0,0 +1,540 @@ +/* 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 libaries (.a files - requires a 'ranlib' type utility) + * + * -s option to strip resolved symbols from exports. + */ + +#include <stdio.h> +#include <stdlib.h> + +#include "nasm.h" +#include "rdoff.h" +#include "nasmlib.h" +#include "symtab.h" +#include "collectn.h" + +#define LDRDF_VERSION "0.11" + +/* 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; +}; + +struct modulenode *modules = NULL,*lastmodule = 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); + +} + +/* load_segments() allocates memory for & loads the code & data segs + * from the RDF modules + */ + +char *text,*data; +long textlength,datalength,bsslength; + +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 */ + mod->header = malloc(mod->f.header_len); + if (!mod->header) { + fprintf(stderr,"ldrdf: out of memory\n"); + exit(1); + } + if (rdfloadseg(&mod->f,RDOFF_HEADER,mod->header) || + 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; + } +} + +/* build_symbols() step through each module's header, and locate + * exported symbols, placing them in a global table + */ + +void build_symbols() +{ + struct modulenode *mod; + rdfheaderrec *r; + symtabEnt e; + long bssloc,cbBss; + + if (verbose) printf("building global symbol table:\n"); + newheader = rdfnewheader(); + + symtab = symtabNew(); + bssloc = 0; /* keep track of location of BSS symbols */ + + for (mod = modules; mod; mod = mod->next) + { + mod->bssrel = bssloc; + 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); + } + bssloc += cbBss; + } + if (verbose) + { + symtabDump(symtab,stdout); + printf("BSS length = %ld bytes\n\n",bssloc); + } + bsslength = bssloc; +} + +/* 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 = 0; /* placate gcc */ + 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))) { + 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 */ + + /* 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) continue; /* eh? probably doesn't matter... */ + + r->e.offset = s->offset; + rdfaddheader(newheader,r); + break; + + case 4: /* DLL record */ + rdfaddheader(newheader,r); /* copy straight to output */ + break; + } + } + collection_reset(&imports); + } +} + +/* write_output() write linked program out to a file */ + +void write_output(char *filename) +{ + FILE * fp; + rdfheaderrec r; + + 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\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"; + +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 && !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 */ + + load_segments(); /* having calculated size of reqd segments, load + each rdoff module's segments into memory */ + + build_symbols(); /* build a global symbol table... + perhaps this should be done before load_segs? */ + + 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; +} diff --git a/rdoff/rdf.doc b/rdoff/rdf.doc new file mode 100644 index 0000000..300c2bc --- /dev/null +++ b/rdoff/rdf.doc @@ -0,0 +1,99 @@ +RDOFF: Relocatable Dynamically-linked Object File Format +======================================================== + +RDOFF was designed initially to test the object-file production +interface to NASM. It soon became apparent that it could be enhanced +for use in serious applications due to its simplicity; code to load +and execute an RDOFF object module is very simple. It also contains +enhancements to allow it to be linked with a dynamic link library at +either run- or load- time, depending on how complex you wish to make +your loader. + +The RDOFF format (version 1.1, as produced by NASM v0.91) is defined +as follows: + +The first six bytes of the file contain the string 'RDOFF1'. Other +versions of the format may contain other last characters other than +'1' - all little endian versions of the file will always contain an +ASCII character with value greater than 32. If RDOFF is used on a +big-endian machine at some point in the future, the version will be +encoded in decimal rather than ASCII, so will be below 32. + +All multi-byte fields follwing this are encoded in either little- or +big-endian format depending on the system described by this version +information. Object files should be encoded in the endianness of +their target machine; files of incorrect endianness will be rejected +by the loader - this means that loaders do not need to convert +endianness, as RDOFF has been designed with simplicity of loading at +the forefront of the design requirements. + +The next 4 byte field is the length of the header in bytes. The +header consists of a sequence of variable length records. Each +record's type is identified by the first byte of the record. Record +types 1-4 are currently supported. Record type 5 will be added in +the near future, when I implement BSS segments. Record type 6 may be +to do with debugging, when I get debugging implemented. + +Type 1: Relocation +================== + +Offset Length Description +0 1 Type (contains 1) +1 1 Segment that contains reference (0 = text, 1 = data) + Add 64 to this number to indicate a relative linkage + to an external symbol (see notes) +2 4 Offset of reference +6 1 Length of reference (1,2 or 4 bytes) +7 2 Segment to which reference is made (0 = text, 1 = + data, 2 = BSS [when implemented]) others are external + symbols. + +Total length = 9 bytes + +Type 2: Symbol Import +===================== + +0 1 Type (2) +1 2 Segment number that will be used in references to this + symbol. +3 ? Null terminated string containing label (up to 32 + chars) to match against exports in linkage. + +Type 3: Symbol Export +===================== + +0 1 Type (3) +1 1 Segment containing object to be exported (0/1/2) +2 4 Offset within segment +6 ? Null terminate string containing label to export (32 + char maximum length) + +Type 4: Dynamic Link Library +============================ + +0 1 Type (4) +1 ? Library name (up to 128 chars) + +Type 5: Reserve BSS +=================== + +0 1 Type (5) +1 4 Amount of BSS space to reserve in bytes + +Total length: 5 bytes + +----------------------------------------------------------------------------- + +Following the header is the text (code) segment. This is preceded by +a 4-byte integer, which is its length in bytes. This is followed by +the length of the data segment (also 4 bytes), and finally the data +segment. + +Notes +===== + +Relative linking: The number stored at the address is offset +required from the imported symbol, with the address of the end of +the instruction subtracted from it. This means that the linker can +simply add the address of the label relative to the beginning of the +current segment to it. diff --git a/rdoff/rdfdump.c b/rdoff/rdfdump.c new file mode 100644 index 0000000..4d4f4df --- /dev/null +++ b/rdoff/rdfdump.c @@ -0,0 +1,156 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +FILE *infile; + +long translatelong(long in) { /* translate from little endian to + local representation */ + long r; + unsigned char *i; + + i = (unsigned char *)∈ + r = i[3]; + r = (r << 8) + i[2]; + r = (r << 8) + i[1]; + r = (r << 8) + *i; + + return r; +} + +int translateshort(short in) { + int r; + unsigned char *i; + + i = (unsigned char *)∈ + r = (i[1] << 8) + *i; + + return r; +} +void print_header(long length) { + unsigned char buf[129],t,s,l; + long o; + short rs; + + while (length > 0) { + fread(&t,1,1,infile); + switch(t) { + case 1: /* relocation record */ + fread(&s,1,1,infile); + fread(&o,4,1,infile); + fread(&l,1,1,infile); + fread(&rs,2,1,infile); + printf(" relocation: location (%04x:%08lx), length %d, " + "referred seg %04x\n",(int)s,translatelong(o),(int)l, + translateshort(rs)); + length -= 9; + break; + case 2: /* import record */ + fread(&rs,2,1,infile); + l = 0; + do { + fread(&buf[l],1,1,infile); + } while (buf[l++]); + printf(" import: segment %04x = %s\n",translateshort(rs),buf); + length -= l + 3; + break; + case 3: /* export record */ + fread(&s,1,1,infile); + fread(&o,4,1,infile); + l = 0; + do { + fread(&buf[l],1,1,infile); + } while (buf[l++]); + printf(" export: (%04x:%08lx) = %s\n",(int)s,translatelong(o),buf); + length -= l + 6; + break; + case 4: /* DLL record */ + l = 0; + do { + fread(&buf[l],1,1,infile); + } while (buf[l++]); + printf(" dll: %s\n",buf); + length -= l + 1; + break; + case 5: /* BSS reservation */ + fread(&l,4,1,infile); + printf(" bss reservation: %08lx bytes\n",translatelong(l)); + length -= 5; + break; + default: + printf(" unrecognised record (type %d)\n",(int)t); + length --; + } + } +} + +int main(int argc,char **argv) { + char id[7]; + long l; + int verbose = 0; + + puts("RDOFF Dump utility v1.1 (C) Copyright 1996 Julian R Hall"); + + if (argc < 2) { + fputs("Usage: rdfdump [-v] <filename>\n",stderr); + exit(1); + } + + if (! strcmp (argv[1], "-v") ) + { + verbose = 1; + if (argc < 3) + { + fputs("required parameter missing\n",stderr); + exit(1); + } + argv++; + } + + infile = fopen(argv[1],"rb"); + if (! infile) { + fprintf(stderr,"rdfdump: Could not open %s",argv[1]); + exit(1); + } + + fread(id,6,1,infile); + if (strncmp(id,"RDOFF",5)) { + fputs("rdfdump: File does not contain valid RDOFF header\n",stderr); + exit(1); + } + + printf("File %s: RDOFF version %c\n\n",argv[1],id[5]); + if (id[5] < '1' || id[5] > '1') { + fprintf(stderr,"rdfdump: unknown RDOFF version '%c'\n",id[5]); + exit(1); + } + + fread(&l,4,1,infile); + l = translatelong(l); + printf("Header (%ld bytes):\n",l); + print_header(l); + + fread(&l,4,1,infile); + l = translatelong(l); + printf("\nText segment length = %ld bytes\n",l); + while(l--) { + fread(id,1,1,infile); + if (verbose) printf(" %02x",(int) (unsigned char)id[0]); + } + if (verbose) printf("\n\n"); + + fread(&l,4,1,infile); + l = translatelong(l); + printf("Data segment length = %ld bytes\n",l); + + if (verbose) + { + while (l--) { + fread(id,1,1,infile); + printf(" %02x",(int) (unsigned char) id[0]); + } + printf("\n"); + } + fclose(infile); + return 0; +} diff --git a/rdoff/rdfload.c b/rdoff/rdfload.c new file mode 100644 index 0000000..ad340b3 --- /dev/null +++ b/rdoff/rdfload.c @@ -0,0 +1,173 @@ +/* rdfload.c RDOFF Object File loader library + * + * 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. + * + * Permission to use this file in your own projects is granted, as long + * as acknowledgement is given in an appropriate manner to its authors, + * with instructions of how to obtain a copy via ftp. + */ + +#include <stdlib.h> +#include <stdio.h> + +#include "rdfload.h" +#include "symtab.h" +#include "rdoff.h" +#include "collectn.h" + +extern int rdf_errno; + +rdfmodule * rdfload(const char *filename) +{ + rdfmodule * f = malloc(sizeof(rdfmodule)); + long bsslength = 0; + char * hdr; + rdfheaderrec *r; + + if (f == NULL) + { + rdf_errno = 6; /* out of memory */ + return NULL; + } + + f->symtab = symtabNew(); + if (!f->symtab) + { + free(f); + rdf_errno = 6; + return NULL; + } + + /* open the file */ + if ( rdfopen( &(f->f), filename ) ) { + free(f); + return NULL; + } + + /* read in text and data segments, and header */ + + f->t = malloc (f->f.code_len); + f->d = malloc (f->f.data_len); /* BSS seg allocated later */ + hdr = malloc (f->f.header_len); + + if (! f->t || ! f->d || !hdr) { + rdf_errno = 6; + rdfclose(&f->f); + if (f->t) free(f->t); + if (f->d) free(f->d); + free(f); + return NULL; + } + + if ( rdfloadseg (&f->f,RDOFF_HEADER,hdr) || + rdfloadseg (&f->f,RDOFF_CODE,f->t) || + rdfloadseg (&f->f,RDOFF_DATA,f->d) ) + { + rdfclose(&f->f); + free(f->t); + free(f->d); + free(f); + free(hdr); + return NULL; + } + + rdfclose(&f->f); + + /* Allocate BSS segment; step through header and count BSS records */ + + while ( ( r = rdfgetheaderrec (&f->f) ) ) + { + if (r->type == 5) + bsslength += r->b.amount; + } + + f->b = malloc ( bsslength ); + if (! f->b ) + { + free(f->t); + free(f->d); + free(f); + free(hdr); + rdf_errno = 6; + return NULL; + } + + rdfheaderrewind (&f->f); + + f->textrel = (long)f->t; + f->datarel = (long)f->d; + f->bssrel = (long)f->b; + + return f; +} + +int rdf_relocate(rdfmodule * m) +{ + rdfheaderrec * r; + Collection imports; + symtabEnt e; + long rel; + unsigned char * seg; + + rdfheaderrewind ( & m->f ); + collection_init(&imports); + + while ( (r = rdfgetheaderrec ( & m->f ) ) ) + { + switch (r->type) + { + case 1: /* Relocation record */ + + /* calculate relocation factor */ + + if (r->r.refseg == 0) rel = m->textrel; + else if (r->r.refseg == 1) rel = m->datarel; + else if (r->r.refseg == 2) rel = m->bssrel; + else + /* We currently do not support load-time linkage. + This should be added some time soon... */ + + return 1; /* return error code */ + + if ((r->r.segment & 63) == 0) seg = m->t; + else if ((r->r.segment & 63) == 1) seg = m->d; + else + return 1; + + /* it doesn't matter in this case that the code is non-portable, + as the entire concept of executing a module like this is + non-portable */ + 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 3: /* export record - add to symtab */ + e.segment = r->e.segment; + e.offset = r->e.offset + + (e.segment == 0 ? m->textrel : /* 0 -> code */ + e.segment == 1 ? m->datarel : /* 1 -> data */ + m->bssrel) ; /* 2 -> bss */ + e.flags = 0; + e.name = malloc(strlen(r->e.label) + 1); + if (! e.name) + return 1; + + strcpy(e.name,r->e.label); + symtabInsert(m->symtab,&e); + break; + } + } + return 0; +} diff --git a/rdoff/rdfload.h b/rdoff/rdfload.h new file mode 100644 index 0000000..5e264b9 --- /dev/null +++ b/rdoff/rdfload.h @@ -0,0 +1,29 @@ +/* rdfload.h RDOFF Object File loader library header file + * + * 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. + * + * See the file 'rdfload.c' for special license information for this + * file. + */ + +#ifndef _RDFLOAD_H +#define _RDFLOAD_H + +#include "rdoff.h" + +typedef struct RDFModuleStruct { + rdffile f; /* file structure */ + unsigned char * t, * d, * b; /* text, data, and bss segments */ + long textrel; + long datarel; + long bssrel; + void * symtab; +} rdfmodule; + +rdfmodule * rdfload(const char * filename); +int rdf_relocate(rdfmodule * m); + +#endif diff --git a/rdoff/rdoff.c b/rdoff/rdoff.c new file mode 100644 index 0000000..9a969ad --- /dev/null +++ b/rdoff/rdoff.c @@ -0,0 +1,367 @@ +/* rdoff.c library of routines for manipulating rdoff files + * + * 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: The functions in this module assume they are running + * on a little-endian machine. This should be fixed to + * make it portable. + */ + +#include <stdio.h> +#include <stdlib.h> + +#include "rdoff.h" + +/* ======================================================================== + * Code for memory buffers (for delayed writing of header until we know + * how long it is). + * ======================================================================== */ + + +memorybuffer * newmembuf(){ + memorybuffer * t; + + t = malloc(sizeof(memorybuffer)); + + t->length = 0; + t->next = NULL; + return t; +} + +void membufwrite(memorybuffer *b, void *data, int bytes) { + int16 w; + long l; + + if (b->next) { /* memory buffer full - use next buffer */ + membufwrite(b->next,data,bytes); + return; + } + if ((bytes < 0 && b->length - bytes > BUF_BLOCK_LEN) + || (bytes > 0 && b->length + bytes > BUF_BLOCK_LEN)) { + + /* buffer full and no next allocated... allocate and initialise next + * buffer */ + + b->next = newmembuf(); + membufwrite(b->next,data,bytes); + } + + switch(bytes) { + case -4: /* convert to little-endian */ + l = * (long *) data ; + b->buffer[b->length++] = l & 0xFF; + l >>= 8 ; + b->buffer[b->length++] = l & 0xFF; + l >>= 8 ; + b->buffer[b->length++] = l & 0xFF; + l >>= 8 ; + b->buffer[b->length++] = l & 0xFF; + break; + + case -2: + w = * (int16 *) data ; + b->buffer[b->length++] = w & 0xFF; + w >>= 8 ; + b->buffer[b->length++] = w & 0xFF; + break; + + default: + while(bytes--) { + b->buffer[b->length++] = *(* (unsigned char **) &data); + + (* (unsigned char **) &data)++ ; + } + break; + } +} + +void membufdump(memorybuffer *b,FILE *fp) +{ + if (!b) return; + + fwrite (b->buffer, 1, b->length, fp); + + membufdump(b->next,fp); +} + +int membuflength(memorybuffer *b) +{ + if (!b) return 0; + return b->length + membuflength(b->next); +} + +void freemembuf(memorybuffer *b) +{ + if (!b) return; + freemembuf(b->next); + free(b); +} + +/* ========================================================================= + General purpose routines and variables used by the library functions + ========================================================================= */ + +long translatelong(long in) { /* translate from little endian to + local representation */ + long r; + unsigned char *i; + + i = (unsigned char *)∈ + r = i[3]; + r = (r << 8) + i[2]; + r = (r << 8) + i[1]; + r = (r << 8) + *i; + + return r; +} + +const char *RDOFFId = "RDOFF1"; /* written to the start of RDOFF files */ + +const char *rdf_errors[7] = { + "no error occurred","could not open file","invalid file format", + "error reading file","unknown error","header not read", + "out of memory"}; + +int rdf_errno = 0; + +/* ======================================================================== + The library functions + ======================================================================== */ + +int rdfopen(rdffile *f, const char *name) +{ + char buf[8]; + + if (translatelong(0x01020304) != 0x01020304) + { /* fix this to be portable! */ + fputs("*** this program requires a little endian machine\n",stderr); + fprintf(stderr,"01020304h = %08lxh\n",translatelong(0x01020304)); + exit(3); + } + + + f->fp = fopen(name,"rb"); + if (!f->fp) return rdf_errno = 1; /* error 1: file open error */ + + fread(buf,6,1,f->fp); /* read header */ + buf[6] = 0; + + if (strcmp(buf,RDOFFId)) { + fclose(f->fp); + return rdf_errno = 2; /* error 2: invalid file format */ + } + + if (fread(&f->header_len,1,4,f->fp) != 4) { + fclose(f->fp); + return rdf_errno = 3; /* error 3: file read error */ + } + + if (fseek(f->fp,f->header_len,SEEK_CUR)) { + fclose(f->fp); + return rdf_errno = 2; /* seek past end of file...? */ + } + + if (fread(&f->code_len,1,4,f->fp) != 4) { + fclose(f->fp); + return rdf_errno = 3; + } + + f->code_ofs = ftell(f->fp); + if (fseek(f->fp,f->code_len,SEEK_CUR)) { + fclose(f->fp); + return rdf_errno = 2; + } + + if (fread(&f->data_len,1,4,f->fp) != 4) { + fclose(f->fp); + return rdf_errno = 3; + } + + f->data_ofs = ftell(f->fp); + rewind(f->fp); + f->header_loc = NULL; + return 0; +} + +int rdfclose(rdffile *f) +{ + fclose(f->fp); + return 0; +} + +void rdfperror(const char *app,const char *name) +{ + fprintf(stderr,"%s:%s: %s\n",app,name,rdf_errors[rdf_errno]); +} + +int rdfloadseg(rdffile *f,int segment,void *buffer) +{ + long fpos; + long slen; + + switch(segment) { + case RDOFF_HEADER: + fpos = 10; + slen = f->header_len; + f->header_loc = (char *)buffer; + f->header_fp = 0; + break; + case RDOFF_CODE: + fpos = f->code_ofs; + slen = f->code_len; + break; + case RDOFF_DATA: + fpos = f->data_ofs; + slen = f->data_len; + break; + default: + fpos = 0; + slen = 0; + } + + if (fseek(f->fp,fpos,SEEK_SET)) + return rdf_errno = 4; + + if (fread(buffer,1,slen,f->fp) != slen) + return rdf_errno = 3; + + return 0; +} + +/* Macros for reading integers from header in memory */ + +#define RI8(v) v = f->header_loc[f->header_fp++] +#define RI16(v) { v = (f->header_loc[f->header_fp] + \ + (f->header_loc[f->header_fp+1] << 8)); \ + f->header_fp += 2; } + +#define RI32(v) { v = (f->header_loc[f->header_fp] + \ + (f->header_loc[f->header_fp+1] << 8) + \ + (f->header_loc[f->header_fp+2] << 16) + \ + (f->header_loc[f->header_fp+3] << 24)); \ + f->header_fp += 4; } + +#define RS(str,max) { for(i=0;i<max;i++){\ + RI8(str[i]); if (!str[i]) break;} str[i]=0; } + +rdfheaderrec *rdfgetheaderrec(rdffile *f) +{ + static rdfheaderrec r; + int i; + + if (!f->header_loc) { + rdf_errno = 5; + return NULL; + } + + if (f->header_fp >= f->header_len) return 0; + + RI8(r.type); + switch(r.type) { + case 1: /* Relocation record */ + RI8(r.r.segment); + RI32(r.r.offset); + RI8(r.r.length); + RI16(r.r.refseg); + break; + + case 2: /* Imported symbol record */ + RI16(r.i.segment); + RS(r.i.label,32); + break; + + case 3: /* Exported symbol record */ + RI8(r.e.segment); + RI32(r.e.offset); + RS(r.e.label,32); + break; + + case 4: /* DLL record */ + RS(r.d.libname,127); + break; + + case 5: /* BSS reservation record */ + RI32(r.b.amount); + break; + + default: + rdf_errno = 2; /* invalid file */ + return NULL; + } + return &r; +} + +void rdfheaderrewind(rdffile *f) +{ + f->header_fp = 0; +} + + +rdf_headerbuf * rdfnewheader(void) +{ + return newmembuf(); +} + +int rdfaddheader(rdf_headerbuf * h, rdfheaderrec * r) +{ + switch (r->type) + { + case 1: + membufwrite(h,&r->type,1); + membufwrite(h,&r->r.segment,1); + membufwrite(h,&r->r.offset,-4); + membufwrite(h,&r->r.length,1); + membufwrite(h,&r->r.refseg,-2); /* 9 bytes written */ + break; + + case 2: /* import */ + membufwrite(h,&r->type,1); + membufwrite(h,&r->i.segment,-2); + membufwrite(h,&r->i.label,strlen(r->i.label) + 1); + break ; + + case 3: /* export */ + membufwrite(h,&r->type,1); + membufwrite(h,&r->e.segment,1); + membufwrite(h,&r->e.offset,-4); + membufwrite(h,&r->e.label,strlen(r->e.label) + 1); + break ; + + case 4: /* DLL */ + membufwrite(h,&r->type,1); + membufwrite(h,&r->d.libname,strlen(r->d.libname) + 1); + break ; + + case 5: /* BSS */ + membufwrite(h,&r->type,1); + membufwrite(h,&r->b.amount,-4); + break ; + + default: + return (rdf_errno = 2); + } + return 0; +} + +int rdfwriteheader(FILE * fp, rdf_headerbuf * h) +{ + long l; + + fwrite (RDOFFId, 1, strlen(RDOFFId), fp) ; + + l = translatelong ( membuflength (h) ); + fwrite (&l, 4, 1, fp); + + membufdump(h, fp); + + return 0; /* no error handling in here... CHANGE THIS! */ +} + +void rdfdoneheader(rdf_headerbuf * h) +{ + freemembuf(h); +} diff --git a/rdoff/rdoff.h b/rdoff/rdoff.h new file mode 100644 index 0000000..b022400 --- /dev/null +++ b/rdoff/rdoff.h @@ -0,0 +1,112 @@ +/* rdoff.h RDOFF Object File manipulation routines header file + * + * 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. + */ + +#ifndef _RDOFF_H +#define _RDOFF_H "RDOFF1 support routines v0.1" + +typedef short int16; /* not sure if this will be required to be altered + at all... best to typedef it just in case */ + +/* the records that can be found in the RDOFF header */ + +struct RelocRec { + char type; /* must be 1 */ + char segment; /* only 0 for code, or 1 for data supported, + but add 64 for relative refs (ie do not require + reloc @ loadtime, only linkage) */ + long offset; /* from start of segment in which reference is loc'd */ + char length; /* 1 2 or 4 bytes */ + int16 refseg; /* segment to which reference refers to */ +}; + +struct ImportRec { + char type; /* must be 2 */ + int16 segment; /* segment number allocated to the label for reloc + records - label is assumed to be at offset zero + in this segment, so linker must fix up with offset + of segment and of offset within segment */ + char label[33]; /* zero terminated... should be written to file until + the zero, but not after it - max len = 32 chars */ +}; + +struct ExportRec { + char type; /* must be 3 */ + char segment; /* segment referred to (0/1) */ + long offset; /* offset within segment */ + char label[33]; /* zero terminated as above. max len = 32 chars */ +}; + +struct DLLRec { + char type; /* must be 4 */ + char libname[128]; /* name of library to link with at load time */ +}; + +struct BSSRec { + char type; /* must be 5 */ + long amount; /* number of bytes BSS to reserve */ +}; + +typedef union RDFHeaderRec { + char type; /* invariant throughout all below */ + struct RelocRec r; /* type == 1 */ + struct ImportRec i; /* type == 2 */ + struct ExportRec e; /* type == 3 */ + struct DLLRec d; /* type == 4 */ + struct BSSRec b; /* type == 5 */ +} rdfheaderrec; + +typedef struct RDFFileInfo { + FILE *fp; /* file descriptor; must be open to use this struct */ + int rdoff_ver; /* should be 1; any higher => not guaranteed to work */ + long header_len; + long code_len; + long data_len; + long code_ofs; + long data_ofs; + char *header_loc; /* keep location of header */ + long header_fp; /* current location within header for reading */ +} rdffile; + +#define BUF_BLOCK_LEN 4088 /* selected to match page size (4096) + * on 80x86 machines for efficiency */ +typedef struct memorybuffer { + int length; + char buffer[BUF_BLOCK_LEN]; + struct memorybuffer *next; +} memorybuffer; + +typedef memorybuffer rdf_headerbuf; + +/* segments used by RDOFF, understood by rdoffloadseg */ +#define RDOFF_CODE 0 +#define RDOFF_DATA 1 +#define RDOFF_HEADER -1 +/* mask for 'segment' in relocation records to find if relative relocation */ +#define RDOFF_RELATIVEMASK 64 +/* mask to find actual segment value in relocation records */ +#define RDOFF_SEGMENTMASK 63 + +/* RDOFF file manipulation functions */ +int rdfopen(rdffile *f,const char *name); +int rdfclose(rdffile *f); +int rdfloadseg(rdffile *f,int segment,void *buffer); +rdfheaderrec *rdfgetheaderrec(rdffile *f); /* returns static storage */ +void rdfheaderrewind(rdffile *f); /* back to start of header */ +void rdfperror(const char *app,const char *name); + +/* functions to write a new RDOFF header to a file - + use rdfnewheader to allocate a header, rdfaddheader to add records to it, + rdfwriteheader to write 'RDOFF1', length of header, and the header itself + to a file, and then rdfdoneheader to dispose of the header */ + +rdf_headerbuf *rdfnewheader(void); +int rdfaddheader(rdf_headerbuf *h,rdfheaderrec *r); +int rdfwriteheader(FILE *fp,rdf_headerbuf *h); +void rdfdoneheader(rdf_headerbuf *h); + +#endif /* _RDOFF_H */ diff --git a/rdoff/rdx.c b/rdoff/rdx.c new file mode 100644 index 0000000..28ffc42 --- /dev/null +++ b/rdoff/rdx.c @@ -0,0 +1,61 @@ +/* rdx.c RDOFF Object File loader 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. + */ + +/* note: most of the actual work of this program is done by the modules + "rdfload.c", which loads and relocates the object file, and by "rdoff.c", + which contains general purpose routines to manipulate RDOFF object + files. You can use these files in your own program to load RDOFF objects + and execute the code in them in a similar way to what is shown here. */ + +#include <stdio.h> +#include <stdlib.h> + +#include "rdfload.h" +#include "rdoff.h" +#include "symtab.h" + +typedef int (*main_fn) (int,char**); /* Main function prototype */ + +int main(int argc, char **argv) +{ + rdfmodule * m; + main_fn code; + symtabEnt * s; + + if (argc < 2) + { + puts("usage: rdf <rdoff-executable> [params]\n"); + exit(255); + } + + m = rdfload(argv[1]); + + if (! m) + { + rdfperror("rdf",argv[1]); + exit(255); + } + + rdf_relocate(m); /* in this instance, the default relocation + values will work fine, but they may need changing + in other cases... */ + + s = symtabFind(m->symtab, "_main"); + if (! s) + { + fprintf(stderr,"rdx: could not find symbol '_main' in '%s'\n",argv[1]); + exit(255); + } + + code = (main_fn) s->offset; + + argv++, argc--; /* remove 'rdx' from command line */ + + return code(argc,argv); /* execute */ +} + diff --git a/rdoff/symtab.c b/rdoff/symtab.c new file mode 100644 index 0000000..c0ff3e5 --- /dev/null +++ b/rdoff/symtab.c @@ -0,0 +1,80 @@ +/* symtab.c Routines to maintain and manipulate a symbol table + * + * 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. + */ +#include <stdio.h> +#include <stdlib.h> + +#include "symtab.h" + +/* TODO: Implement a hash table, not this stupid implementation which + is too slow to be of practical use */ + +/* Private data types */ + +typedef struct tagSymtab { + symtabEnt ent; + struct tagSymtab * next; +} symtabList; + +typedef symtabList * _symtab; + +void *symtabNew(void) +{ + void *p = malloc(sizeof(_symtab)); + if (p == NULL) { + fprintf(stderr,"symtab: out of memory\n"); + exit(3); + } + *(_symtab *)p = NULL; + + return p; +} + +void symtabDone(void *symtab) +{ + /* DO SOMETHING HERE! */ +} + +void symtabInsert(void *symtab,symtabEnt *ent) +{ + symtabList *l = malloc(sizeof(symtabList)); + + if (l == NULL) { + fprintf(stderr,"symtab: out of memory\n"); + exit(3); + } + + l->ent = *ent; + l->next = *(_symtab *)symtab; + *(_symtab *)symtab = l; +} + +symtabEnt *symtabFind(void *symtab,char *name) +{ + symtabList *l = *(_symtab *)symtab; + + while (l) { + if (!strcmp(l->ent.name,name)) { + return &(l->ent); + } + l = l->next; + } + return NULL; +} + +void symtabDump(void *symtab,FILE *of) +{ + symtabList *l = *(_symtab *)symtab; + + while(l) { + fprintf(of,"%32s %s:%08lx (%ld)\n",l->ent.name, + l->ent.segment ? "data" : "code" , + l->ent.offset, l->ent.flags); + l = l->next; + } +} + diff --git a/rdoff/symtab.h b/rdoff/symtab.h new file mode 100644 index 0000000..5780d44 --- /dev/null +++ b/rdoff/symtab.h @@ -0,0 +1,22 @@ +/* symtab.h Header file for symbol table manipulation routines + * + * 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. + */ + +typedef struct { + char *name; + long segment; + long offset; + long flags; +} symtabEnt; + +void *symtabNew(void); +void symtabDone(void *symtab); +void symtabInsert(void *symtab,symtabEnt *ent); +symtabEnt *symtabFind(void *symtab,char *name); +void symtabDump(void *symtab,FILE *of); + + |