From caa82a1e66f6b9517ba2199cdc4297bd7be8eaa2 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Tue, 30 Apr 2002 21:03:11 +0000 Subject: [PATCH] NASM 0.98.16 --- macros.c | 16 - misc/exasm.zip | Bin 491 -> 6058 bytes nasm.c | 18 +- nasm.h | 2 +- rdoff/ldrdf.c | 1378 +++++++++++++++++++++++++++++++++++++++++++++++-- rdoff/rdflib.c | 1 - rdoff/rdfload.c | 1 - rdoff/rdoff.h | 305 +++++++---- test/multisection.asm | 84 +-- 9 files changed, 1600 insertions(+), 205 deletions(-) diff --git a/macros.c b/macros.c index 38a7e0f..ed70a75 100644 --- a/macros.c +++ b/macros.c @@ -1,12 +1,6 @@ /* This file auto-generated from standard.mac by macros.pl - don't edit it */ static char *stdmac[] = { - "%idefine IDEAL", - "%idefine JUMPS", - "%idefine P386", - "%idefine P486", - "%idefine P586", - "%idefine END", "%define __NASM_MAJOR__ 0", "%define __NASM_MINOR__ 98", "%define __FILE__", @@ -63,12 +57,6 @@ static char *stdmac[] = { "%imacro bits 1+.nolist", "[bits %1]", "%endmacro", - "%imacro use16 0.nolist", - "[bits 16]", - "%endmacro", - "%imacro use32 0.nolist", - "[bits 32]", - "%endmacro", "%imacro global 1-*.nolist", "%rep %0", "[global %1]", @@ -81,9 +69,5 @@ static char *stdmac[] = { "%rotate 1", "%endrep", "%endmacro", - "%imacro cpu 1+.nolist", - "[cpu %1]", - "%endmacro", NULL }; -#define TASM_MACRO_COUNT 6 diff --git a/misc/exasm.zip b/misc/exasm.zip index e8130182cd7dd1393bd74504e130a99179491bd6..b4e9e58a0845696f5ba7f15b4d381d8899df3641 100644 GIT binary patch literal 6058 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 delta 7 OcmZ3b|C)KjYeoPLQ3GTE diff --git a/nasm.c b/nasm.c index 9e017fd..5479a73 100644 --- a/nasm.c +++ b/nasm.c @@ -269,7 +269,7 @@ int main(int argc, char **argv) assemble_file (inname); - if (!terminate_after_phase) { + if (!terminate_after_phase) { ofmt->cleanup (using_debug_info); cleanup_labels (); } else { @@ -279,10 +279,9 @@ int main(int argc, char **argv) * so we're leaving out the one here. * fclose (ofile); */ - remove(outname); - if (listname[0]) - remove(listname); + if (listname[0]) + remove(listname); } } break; @@ -493,7 +492,7 @@ static int process_arg (char *p, char *q) report_error (ERR_NONFATAL | ERR_NOFILE | ERR_USAGE, "invalid option to `-w'"); } else { - for (i=1; i<=ERR_WARN_MAX; i++) + for (i=1; i<=ERR_WARN_MAX; i++) if (!nasm_stricmp(p+3, suppressed_names[i])) break; if (i <= ERR_WARN_MAX) @@ -1262,7 +1261,7 @@ static void assemble_file (char *fname) nasmlist.cleanup(); #if 1 if (optimizing>0 && using_debug_info) /* -On and -g switches */ - fprintf(error_file, + fprintf(stdout, "info:: assembly required 1+%d+1 passes\n", pass_cnt-2); #endif } /* exit from assemble_file (...) */ @@ -1272,6 +1271,10 @@ static int getkw (char *buf, char **value) { char *p, *q; + /* allow leading spaces or tabs */ + while (*buf==' ' || *buf=='\t') + buf++; + if (*buf!='[') return 0; @@ -1384,7 +1387,8 @@ static void report_error (int severity, char *fmt, ...) /* no further action, by definition */ break; case ERR_NONFATAL: - terminate_after_phase = TRUE; +/* terminate_after_phase = TRUE; *//**//* hack enables listing(!) on errors */ + terminate_after_phase = TRUE; break; case ERR_FATAL: if (ofile) { diff --git a/nasm.h b/nasm.h index c9a8f06..0d0fa5b 100644 --- a/nasm.h +++ b/nasm.h @@ -13,7 +13,7 @@ #define NASM_MAJOR_VER 0 #define NASM_MINOR_VER 98 -#define NASM_VER "0.98.15" +#define NASM_VER "0.98.16" #ifndef NULL #define NULL 0 diff --git a/rdoff/ldrdf.c b/rdoff/ldrdf.c index d9aac2f..3d9d749 100644 --- a/rdoff/ldrdf.c +++ b/rdoff/ldrdf.c @@ -1,31 +1,1347 @@ -*************** -*** 29,42 **** - #include - #include - - #include "rdoff.h" - #include "symtab.h" - #include "collectn.h" - #include "rdlib.h" - #include "segtab.h" -- #include "multboot.h" - -- #define LDRDF_VERSION "1.01 alpha 2" - - #define RDF_MAXSEGS 64 - /* #define STINGY_MEMORY */ ---- 29,42 ---- - #include - #include - -+ #include "multboot.h" - #include "rdoff.h" - #include "symtab.h" - #include "collectn.h" - #include "rdlib.h" - #include "segtab.h" - -+ #define LDRDF_VERSION "1.02" - - #define RDF_MAXSEGS 64 - /* #define STINGY_MEMORY */ +/* 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: actually get this new version working! + * - finish off write_output() - appears to be done + * - implement library searching - appears to be done + * - maybe we only want to do one pass, for performance reasons? + * this makes things a little harder, but unix 'ld' copes... + * - implement command line options - appears to be done + * - improve symbol table implementation - done, thanks to Graeme Defty + * - keep a cache of symbol names in each library module so + * we don't have to constantly recheck the file + * - general performance improvements + * + * BUGS & LIMITATIONS: this program doesn't support multiple code, data + * or bss segments, therefore for 16 bit programs whose code, data or BSS + * segment exceeds 64K in size, it will not work. This program probably + * wont work if compiled by a 16 bit compiler. Try DJGPP if you're running + * under DOS. '#define STINGY_MEMORY' may help a little. + */ + +#include +#include +#include + +#include "multboot.h" +#include "rdoff.h" +#include "symtab.h" +#include "collectn.h" +#include "rdlib.h" +#include "segtab.h" + +#define LDRDF_VERSION "1.02" + +#define RDF_MAXSEGS 64 +/* #define STINGY_MEMORY */ + +/* ======================================================================= + * Types & macros that are private to this program + */ + +struct segment_infonode { + 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; +}; + +#include "ldsegs.h" + +#define newstr(str) strcpy(malloc(strlen(str) + 1),str) +#define newstrcat(s1,s2) strcat(strcpy(malloc(strlen(s1)+strlen(s2)+1),s1),s2) + +/* ========================================================================== + * Function prototypes of private utility functions + */ + +void processmodule(const char * filename, struct modulenode * mod); +int allocnewseg(int16 type,int16 reserved); +int findsegment(int16 type,int16 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; + +/* a linked list of libraries to be searched for unresolved imported symbols */ +struct librarynode * libraries = NULL; +struct librarynode * lastlib = NULL; + +/* the symbol table */ +void * symtab = NULL; + +/* objects search path */ +char * objpath = NULL; + +/* libraries search path */ +char * libpath = NULL; + +/* error file */ +static FILE * error_file; + +#ifdef _MULTBOOT_H + +/* loading address for multiboot header */ +unsigned MBHloadAddr; + +/* + * Tiny code that moves RDF loader to its working memory region: + * mov esi,SOURCE_ADDR ; BE xx xx xx xx + * mov edi,DEST_ADDR ; BF xx xx xx xx + * mov esp,edi ; 89 FC + * push edi ; 57 + * mov ecx,RDFLDR_LENGTH/4 ; B9 xx xx xx xx + * cld ; FC + * rep movsd ; F3 A5 + * ret ; C3 + */ + +#define RDFLDR_LENGTH 4096 /* Loader will be moved to unused */ +#define RDFLDR_DESTLOC 0xBF000 /* video page */ + +unsigned char RDFloaderMover[]={ + 0xBE, 0, 0, 0, 0, 0xBF, 0, 0xF0, 0xB, 0, + 0x89, 0xFC, 0x57, + 0xB9, 0, 4, 0, 0, + 0xFC, 0xF3, 0xA5, 0xC3 +}; + +#endif + +/* the header of the output file, built up stage by stage */ +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; + +/* global options which affect how the program behaves */ +struct ldrdfoptions { + int verbose; + int align; + int warnUnresolved; + int errorUnresolved; + int strip; + int respfile; + int stderr_redir; + int objpath; + int libpath; + int addMBheader; +} options; + +int errorcount = 0; /* determines main program exit status */ + +/* ========================================================================= + * Utility functions + */ + + +/* + * initsegments() + * + * sets up segments 0, 1, and 2, the initial code data and bss segments + */ + +void initsegments() +{ + nsegs = 3; + outputseg[0].type = 1; + outputseg[0].number = 0; + outputseg[0].reserved = 0; + outputseg[0].length = 0; + outputseg[1].type = 2; + outputseg[1].number = 1; + outputseg[1].reserved = 0; + outputseg[1].length = 0; + outputseg[2].type = 0xFFFF; /* reserved segment type */ + outputseg[2].number = 2; + outputseg[2].reserved = 0; + outputseg[2].length = 0; + bss_length = 0; +} + +/* + * loadmodule + * + * Determine the characteristics of a module, and decide what to do with + * each segment it contains (including determining destination segments and + * relocation factors for segments that are kept). + */ + +void loadmodule(const char * filename) +{ + if (options.verbose) + 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; + } + else + { + lastmodule->next = malloc (sizeof(*modules)); + lastmodule = lastmodule->next; + } + + if ( ! lastmodule) + { + 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); + } + + /* + * store information about the module, and determine what segments + * it contains, and what we should do with them (determine relocation + * factor if we decide to keep them) + */ + + lastmodule->header = NULL; + lastmodule->name = strdup(filename); + lastmodule->next = NULL; + + processmodule(filename, lastmodule); +} + +/* + * processmodule() + * + * step through each segment, determine what exactly we're doing with + * it, and if we intend to keep it, determine (a) which segment to + * put it in and (b) whereabouts in that segment it will end up. + * (b) is fairly easy, cos we're now keeping track of how big each segment + * in our output file is... + */ + +void processmodule(const char * filename, struct modulenode * mod) +{ + struct segconfig sconf; + int seg, outseg; + void * header; + rdfheaderrec * hr; + long bssamount = 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); + } + + } + + /* + * extract symbols from the header, and dump them into the + * symbol table + */ + header = malloc(mod->f.header_len); + if (!header) { + fprintf(stderr, "ldrdf: not enough memory\n"); + exit(1); + } + if (rdfloadseg(&mod->f, RDOFF_HEADER, header)) { + rdfperror("ldrdf", filename); + exit(1); + } + + while ((hr = rdfgetheaderrec (&mod->f))) + { + switch(hr->type) { + case 2: /* imported symbol - define with seg = -1 */ + case 7: + symtab_add(hr->i.label, -1, 0); + break; + + case 3: /* exported symbol */ + { + int destseg; + long destreloc; + + if (hr->e.segment == 2) + { + 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; + } + symtab_add(hr->e.label, destseg, destreloc + hr->e.offset); + break; + } + + case 5: /* 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; + } + } + + if (bssamount != 0) + { + /* + * 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. + * this isn't efficient, but probably halves the memory usage + * of this program... + */ + mod->f.header_loc = NULL; + free(header); + +#endif + +} + + +/* + * Look in list for module by its name. + */ +int lookformodule(const char *name) + { + struct modulenode *curr=modules; + + while(curr) { + if (!strcmp(name,curr->name)) return 1; + curr = curr->next; + } + return 0; + } + + +/* + * allocnewseg() + * findsegment() + * + * These functions manipulate the array of output segments, and are used + * by processmodule(). allocnewseg() allocates a segment in the array, + * initialising it to be empty. findsegment() first scans the array for + * a segment of the type requested, and if one isn't found allocates a + * new one. + */ +int allocnewseg(int16 type,int16 reserved) +{ + outputseg[nsegs].type = type; + outputseg[nsegs].number = nsegs; + outputseg[nsegs].reserved = reserved; + outputseg[nsegs].length = 0; + outputseg[nsegs].offset = 0; + outputseg[nsegs].data = NULL; + + return nsegs++; +} + +int findsegment(int16 type,int16 reserved) +{ + int i; + + for (i = 0; i < nsegs; i++) + if (outputseg[i].type == type) return i; + + return allocnewseg(type,reserved); +} + +/* + * symtab_add() + * + * inserts a symbol into the global symbol table, which associates symbol + * names either with addresses, or a marker that the symbol hasn't been + * resolved yet, or possibly that the symbol has been defined as + * contained in a dynamic [load time/run time] linked library. + * + * segment = -1 => not yet defined + * segment = -2 => defined as dll symbol + * + * If the symbol is already defined, and the new segment >= 0, then + * if the original segment was < 0 the symbol is redefined, otherwise + * a duplicate symbol warning is issued. If new segment == -1, this + * 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) +{ + 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; + } + /* + * this is the first declaration of this symbol + */ + ste = malloc(sizeof(symtabEnt)); + if (!ste) { + fprintf(stderr, "ldrdf: out of memory\n"); + exit(1); + } + ste->name = strdup(symbol); + ste->segment = segment; + ste->offset = offset; + ste->flags = 0; + symtabInsert(symtab, ste); +} + +/* + * symtab_get() + * + * Retrieves the values associated with a symbol. Undefined symbols + * 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) +{ + symtabEnt * ste = symtabFind(symtab, symbol); + if (!ste) { + *segment = -1; + *offset = 0; + return 0; + } + else + { + *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) +{ + if (rdl_verify(name)) { + rdl_perror("ldrdf", name); + errorcount++; + return; + } + if (! libraries) + { + 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 = NULL; + if (rdl_open(lastlib, name)) { + rdl_perror("ldrdf", name); + errorcount++; + return; + } +} + +/* + * search_libraries() + * + * scans through the list of libraries, attempting to match symbols + * defined in library modules against symbols that are referenced but + * not defined (segment = -1 in the symbol table) + * + * returns 1 if any extra library modules are included, indicating that + * another pass through the library list should be made (possibly). + */ + +int search_libraries() +{ + struct librarynode * cur; + rdffile f; + 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))) + { + /* we're only interested in exports, so skip others: */ + if (hr->type != 3) continue; + + /* + * Find the symbol 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; + } + } + 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() + * + * this takes the linked list of modules, and walks through it, merging + * all the modules into a single output module, and then writes this to a + * file. + */ +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); + } + if ((rdfheader=rdfnewheader())==NULL) { + fprintf(stderr, "ldrdf: out of memory\n"); + exit(1); + } + + /* + * Add multiboot header if appropriate option is specified. + * Multiboot record *MUST* be the first record in output file. + */ + if (options.addMBheader) { + if (options.verbose) + puts("\nadding multiboot header record"); + + hr = (rdfheaderrec *) malloc(sizeof(struct MultiBootHdrRec)); + hr->mbh.type = 9; + hr->mbh.reclen = sizeof(struct tMultiBootHeader)+RDFLDRMOVER_SIZE; + + hr->mbh.mb.Magic = MB_MAGIC; + hr->mbh.mb.Flags = MB_FL_KLUDGE; + hr->mbh.mb.Checksum = ~(MB_MAGIC+MB_FL_KLUDGE-1); + hr->mbh.mb.HeaderAddr = MBHloadAddr+16; + hr->mbh.mb.LoadAddr = MBHloadAddr; + hr->mbh.mb.Entry = MBHloadAddr+16+sizeof(struct tMultiBootHeader); + + memcpy(hr->mbh.mover,RDFloaderMover,RDFLDRMOVER_SIZE); + + rdfaddheader(rdfheader,hr); + free(hr); + } + + if (options.verbose) + printf ("\nbuilding output module (%d segments)\n", nsegs); + + /* + * Allocate the memory for the segments. We may be better off + * building the output module one segment at a time when running + * under 16 bit DOS, but that would be a slower way of doing this. + * 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); + } + } + + /* + * initialise availableseg, used to allocate segment numbers for + * imported and exported labels... + */ + availableseg = nsegs; + + /* + * 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 1: /* 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 & 64) == 64; + hr->r.segment &= 63; + + 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; + rdfaddheader(rdfheader, hr); + } + break; + + case 2: /* import symbol */ + case 7: + /* + * 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.warnUnresolved) { + fprintf(error_file, "warning: unresolved reference to `%s'" + " in module `%s'\n", hr->i.label, cur->name); + if (options.errorUnresolved==1) 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 3: /* export symbol */ + /* + * need to insert an export for this symbol into the new + * header, unless we're stripping symbols [unless this + * symbol is in an explicit keep list]. *** FIXME *** + */ + if (options.strip) + 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 8: /* module name */ + /* + * insert module name record if export symbols + * are not stripped. + */ + if (options.strip) break; + + rdfaddheader(rdfheader, hr); + break; + + case 6: /* 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; + } + } + + free(header); + done_seglocations(&segs); + + } + + /* + * combined BSS reservation for the entire results + */ + newrec.type = 5; + newrec.b.reclen = 4; + newrec.b.amount = bss_length; + rdfaddheader(rdfheader, &newrec); + + /* + * Write the header + */ + for (i = 0; i < nsegs; i++) + { + if (i == 2) continue; + rdfaddsegment (rdfheader, outputseg[i].length); + } + + if (options.addMBheader) { + struct MultiBootHdrRec *mbhrec = (struct MultiBootHdrRec *)(rdfheader->buf->buffer); + unsigned l = membuflength(rdfheader->buf) + 14 + + 10*rdfheader->nsegments + rdfheader->seglength; + unsigned *ldraddr = (unsigned *)(mbhrec->mover+1); + + mbhrec->mb.LoadEndAddr = MBHloadAddr+l+10+RDFLDR_LENGTH; + mbhrec->mb.BSSendAddr = mbhrec->mb.LoadEndAddr; + *ldraddr = MBHloadAddr+l+10; + } + + 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++) + { + int16 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); +} + +/* ========================================================================= + * Main program + */ + +void usage() +{ + printf("usage:\n"); + printf(" ldrdf [options] object modules ... [-llibrary ...]\n"); + printf(" ldrdf -r\n"); + printf("options:\n"); + printf(" -v[=n] increases verbosity by 1, or sets it to n\n"); + printf(" -a nn sets segment alignment value (default 16)\n"); + printf(" -s strips exported symbols\n"); + printf(" -x warn about unresolved symbols\n"); + printf(" -o name write output in file 'name'\n"); + printf(" -j path specify objects search path\n"); + printf(" -L path specify libraries search path\n"); + printf(" -mbh [address] add multiboot header to output file. Default\n"); + printf(" loading address is 0x110000\n"); + exit(0); +} + +int main(int argc, char ** argv) +{ + char * outname = "aout.rdf"; + int moduleloaded = 0; + char *respstrings[128] = {0, }; + + options.verbose = 0; + options.align = 16; + options.warnUnresolved = 0; + options.strip = 0; + + error_file = stderr; + + argc --, argv ++; + if (argc == 0) usage(); + while (argc && **argv == '-' && argv[0][1] != 'l') + { + switch(argv[0][1]) { + case 'r': + printf("ldrdf (linker for RDF files) version " LDRDF_VERSION "\n"); + printf( _RDOFF_H "\n"); + 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 'x': + options.warnUnresolved = 1; + if (argv[0][2]=='e') + options.errorUnresolved = 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); + } + argc-=2; + while(fgets(buf,sizeof(buf)-1,f)!=NULL) + { + char *p; + if (buf[0]=='\n') continue; + if ((p = strchr(buf,'\n')) != 0) + *p=0; + if (i >= 128) + { + fprintf(stderr,"ldrdf: too many input files\n"); + exit(1); + } + *(respstrings+i) = newstr(buf); + argc++, i++; + } + goto done; + } + case '2': + options.stderr_redir = 1; + error_file = stdout; + break; + case 'm': + if (argv[0][2] == 'b' && argv[0][3] == 'h') { + if (argv[1][0] != '-') { + MBHloadAddr = atoi(argv[1]); + } else { + MBHloadAddr = MB_DEFAULTLOADADDR; + } + options.addMBheader = 1; + break; + } + default: + usage(); + } + argv++, argc--; + } +done: + 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.warnUnresolved) + printf(" warn about unresolved symbols\n"); + if (options.errorUnresolved) + printf(" error if unresolved symbols\n"); + if (options.objpath) + printf(" objects search path: %s\n",objpath); + if (options.libpath) + printf(" libraries search path: %s\n",libpath); + if (options.addMBheader) + printf(" loading address for multiboot header: 0x%X\n",MBHloadAddr); + printf("\n"); + } + + symtab = symtabNew(); + initsegments(); + + if (!symtab) { + fprintf(stderr, "ldrdf: out of memory\n"); + exit(1); + } + + if (*respstrings) argv = respstrings; + while (argc) + { + if (!strncmp(*argv, "-l", 2)) /* library */ + { + if(libpath) add_library(newstrcat(libpath,*argv + 2)); + else add_library(*argv + 2); + } + else { + if(objpath) 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; + } + + + search_libraries(); + + if (options.verbose > 2) + { + printf ("symbol table:\n"); + symtabDump(symtab, stdout); + } + + write_output(outname); + + if (errorcount > 0) exit(1); + return 0; +} diff --git a/rdoff/rdflib.c b/rdoff/rdflib.c index 5a8cf69..7a00fc6 100644 --- a/rdoff/rdflib.c +++ b/rdoff/rdflib.c @@ -19,7 +19,6 @@ */ #include -#include #include #include diff --git a/rdoff/rdfload.c b/rdoff/rdfload.c index 6928ca2..4737282 100644 --- a/rdoff/rdfload.c +++ b/rdoff/rdfload.c @@ -19,7 +19,6 @@ #include #include -#include #include "rdfload.h" #include "symtab.h" diff --git a/rdoff/rdoff.h b/rdoff/rdoff.h index 15f26bc..0c57231 100644 --- a/rdoff/rdoff.h +++ b/rdoff/rdoff.h @@ -1,106 +1,199 @@ -*************** -*** 9,15 **** - * as acknowledgement is given in an appropriate manner to its authors, - * with instructions of how to obtain a copy via ftp. - */ -- - #ifndef _RDOFF_H - #define _RDOFF_H "RDOFF2 support routines v0.3" - ---- 9,15 ---- - * as acknowledgement is given in an appropriate manner to its authors, - * with instructions of how to obtain a copy via ftp. - */ -+ - #ifndef _RDOFF_H - #define _RDOFF_H "RDOFF2 support routines v0.3" - -*************** -*** 48,54 **** - struct ExportRec { - byte type; /* must be 3 */ - byte reclen; /* content length */ -- byte segment; /* segment referred to (0/1) */ - long offset; /* offset within segment */ - char label[33]; /* zero terminated as above. max len = 32 chars */ - }; ---- 48,54 ---- - struct ExportRec { - byte type; /* must be 3 */ - byte reclen; /* content length */ -+ byte segment; /* segment referred to (0/1/2) */ - long offset; /* offset within segment */ - char label[33]; /* zero terminated as above. max len = 32 chars */ - }; -*************** -*** 65,70 **** - long amount; /* number of bytes BSS to reserve */ - }; - - /* GenericRec - contains the type and length field, plus a 128 byte - char array 'data', which will probably never be used! */ - ---- 65,92 ---- - long amount; /* number of bytes BSS to reserve */ - }; - -+ struct ModRec { -+ byte type; /* must be 8 */ -+ byte reclen; /* content length */ -+ char modname[128]; /* module name */ -+ }; -+ -+ #ifdef _MULTBOOT_H -+ -+ #define RDFLDRMOVER_SIZE 22 -+ -+ struct MultiBootHdrRec { -+ byte type; /* must be 9 */ -+ byte reclen; /* content length */ -+ #ifdef __GNUC__ -+ struct tMultiBootHeader mb __attribute__ ((packed)); /* MultiBoot header */ -+ #else -+ struct tMultiBootHeader mb; -+ #endif -+ byte mover[RDFLDRMOVER_SIZE]; /* Mover of RDF loader */ -+ }; -+ #endif -+ - /* GenericRec - contains the type and length field, plus a 128 byte - char array 'data', which will probably never be used! */ - -*************** -*** 82,87 **** - struct ExportRec e; /* type == 3 */ - struct DLLRec d; /* type == 4 */ - struct BSSRec b; /* type == 5 */ - } rdfheaderrec; - - struct SegmentHeaderRec { ---- 104,113 ---- - struct ExportRec e; /* type == 3 */ - struct DLLRec d; /* type == 4 */ - struct BSSRec b; /* type == 5 */ -+ struct ModRec m; /* type == 8 */ -+ #ifdef _MULTBOOT_H -+ struct MultiBootHdrRec mbh; /* type == 9 */ -+ #endif - } rdfheaderrec; - - struct SegmentHeaderRec { -*************** -*** 166,170 **** - int rdfaddsegment(rdf_headerbuf *h, long seglength); - int rdfwriteheader(FILE *fp,rdf_headerbuf *h); - void rdfdoneheader(rdf_headerbuf *h); - - #endif /* _RDOFF_H */ ---- 192,199 ---- - int rdfaddsegment(rdf_headerbuf *h, long seglength); - int rdfwriteheader(FILE *fp,rdf_headerbuf *h); - void rdfdoneheader(rdf_headerbuf *h); -+ -+ /* This is needed by linker to write multiboot header record */ -+ int membuflength(memorybuffer *b); - - #endif /* _RDOFF_H */ +/* 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. + * + * 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. + */ + +#ifndef _RDOFF_H +#define _RDOFF_H "RDOFF2 support routines v0.3" + +/* Some systems don't define this automatically */ +extern char *strdup(const char *); + +typedef unsigned short int16; +typedef unsigned char byte; + +#define RDF_MAXSEGS 64 + +/* the records that can be found in the RDOFF header */ + +struct RelocRec { + byte type; /* must be 1 */ + byte reclen; /* content length */ + byte 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 */ + byte length; /* 1 2 or 4 bytes */ + int16 refseg; /* segment to which reference refers to */ +}; + +struct ImportRec { + byte type; /* must be 2 */ + byte reclen; /* content length */ + 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 { + byte type; /* must be 3 */ + byte reclen; /* content length */ + byte segment; /* segment referred to (0/1/2) */ + long offset; /* offset within segment */ + char label[33]; /* zero terminated as above. max len = 32 chars */ +}; + +struct DLLRec { + byte type; /* must be 4 */ + byte reclen; /* content length */ + char libname[128]; /* name of library to link with at load time */ +}; + +struct BSSRec { + byte type; /* must be 5 */ + byte reclen; /* content length */ + long amount; /* number of bytes BSS to reserve */ +}; + +struct ModRec { + byte type; /* must be 8 */ + byte reclen; /* content length */ + char modname[128]; /* module name */ +}; + +#ifdef _MULTBOOT_H + +#define RDFLDRMOVER_SIZE 22 + +struct MultiBootHdrRec { + byte type; /* must be 9 */ + byte reclen; /* content length */ +#ifdef __GNUC__ + struct tMultiBootHeader mb __attribute__ ((packed)); /* MultiBoot header */ +#else + struct tMultiBootHeader mb; +#endif + byte mover[RDFLDRMOVER_SIZE]; /* Mover of RDF loader */ +}; +#endif + +/* GenericRec - contains the type and length field, plus a 128 byte + char array 'data', which will probably never be used! */ + +struct GenericRec { + byte type; + byte reclen; + char data[128]; +}; + +typedef union RDFHeaderRec { + char type; /* invariant throughout all below */ + struct GenericRec g; + struct RelocRec r; /* type == 1 / 6 */ + struct ImportRec i; /* type == 2 / 7 */ + struct ExportRec e; /* type == 3 */ + struct DLLRec d; /* type == 4 */ + struct BSSRec b; /* type == 5 */ + struct ModRec m; /* type == 8 */ +#ifdef _MULTBOOT_H + struct MultiBootHdrRec mbh; /* type == 9 */ +#endif +} rdfheaderrec; + +struct SegmentHeaderRec { + /* information from file */ + int16 type; + int16 number; + int16 reserved; + long length; + + /* information built up here */ + long offset; + byte *data; /* pointer to segment data if it exists in memory */ +}; + +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 header_ofs; + + byte *header_loc; /* keep location of header */ + long header_fp; /* current location within header for reading */ + + struct SegmentHeaderRec seg[RDF_MAXSEGS]; + int nsegs; + + long eof_offset; /* offset of the first byte beyond the end of this + module */ + + char *name; /* name of module in libraries */ + int *refcount; /* pointer to reference count on file, or NULL */ +} rdffile; + +#define BUF_BLOCK_LEN 4088 /* selected to match page size (4096) + * on 80x86 machines for efficiency */ +typedef struct memorybuffer { + int length; + byte buffer[BUF_BLOCK_LEN]; + struct memorybuffer *next; +} memorybuffer; + +typedef struct { + memorybuffer * buf; /* buffer containing header records */ + int nsegments; /* number of segments to be written */ + long seglength; /* total length of all the segments */ +} 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 + +extern int rdf_errno; + +/* utility functions */ +int16 translateshort(int16 in); +long translatelong(long in); + +/* RDOFF file manipulation functions */ +int rdfopen(rdffile *f,const char *name); +int rdfopenhere(rdffile *f, FILE *fp, int *refcount, const char *name); +int rdfclose(rdffile *f); +int rdffindsegment(rdffile * f, int segno); +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, + rdfaddsegment to notify the header routines that a segment exists, and + to tell it how long the segment will be. + rdfwriteheader to write the file id, object length, and header + to a file, and then rdfdoneheader to dispose of the header */ + +rdf_headerbuf *rdfnewheader(void); +int rdfaddheader(rdf_headerbuf *h,rdfheaderrec *r); +int rdfaddsegment(rdf_headerbuf *h, long seglength); +int rdfwriteheader(FILE *fp,rdf_headerbuf *h); +void rdfdoneheader(rdf_headerbuf *h); + +/* This is needed by linker to write multiboot header record */ +int membuflength(memorybuffer *b); + +#endif /* _RDOFF_H */ diff --git a/test/multisection.asm b/test/multisection.asm index 327e518..ae84345 100644 --- a/test/multisection.asm +++ b/test/multisection.asm @@ -1,42 +1,42 @@ - -section .stringdata -mystr1: db "Hello, this is string 1", 13, 10, '$' - -section .extra_code -org 0x200 -bits 16 -more: - mov si, asciz1 - mov ah, 0x0E - xor bx, bx -.print: - lodsb - test al, al - jz .end - int 0x10 - jmp short .print -.end: - - xor ax, ax - int 0x16 - - mov ax, 0x4c00 - int 0x21 - -section .appspecific -asciz1: db "This is string 2", 0 - -section .code -org 0x100 -bits 16 - -start: - mov dx, mystr1 - mov ah, 9 - int 0x21 - - xor ax, ax - int 0x16 - - jmp more - + +section .stringdata +mystr1: db "Hello, this is string 1", 13, 10, '$' + +section .extra_code +org 0x200 +bits 16 +more: + mov si, asciz1 + mov ah, 0x0E + xor bx, bx +.print: + lodsb + test al, al + jz .end + int 0x10 + jmp short .print +.end: + + xor ax, ax + int 0x16 + + mov ax, 0x4c00 + int 0x21 + +section .appspecific +asciz1: db "This is string 2", 0 + +section .code +org 0x100 +bits 16 + +start: + mov dx, mystr1 + mov ah, 9 + int 0x21 + + xor ax, ax + int 0x16 + + jmp more + -- 2.7.4