From 27cf503e03f4765e0eaaffa6aaef6d75ff1de226 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Sat, 4 May 2002 05:42:30 +0000 Subject: [PATCH] RDOFF patch from Yuri Zaporogets: - Panos Minos's LDRDF fix (correct export of relocation records); - Panos Minos's symtab.c verbose dump fix; - Librarian (rdflib) now puts a signature block when creating a library (instead of creating an empty file). In theory it doesn't break binary compatibility, but due to a bug in the original 'rdlib.c' you can't use old LDRDF with new libraries. Fix this bug as well. - Other minor changes in LDRDF. --- rdoff/ldrdf.c | 91 +++++++++++++++++++++++++-------------------------- rdoff/rdflib.c | 28 ++++++++++++---- rdoff/rdlib.c | 31 ++++++++++-------- rdoff/rdoff.c | 2 +- rdoff/rdoff.h | 9 +++-- rdoff/symtab.c | 12 ++++--- rdoff/test/makelib.sh | 2 +- 7 files changed, 100 insertions(+), 75 deletions(-) diff --git a/rdoff/ldrdf.c b/rdoff/ldrdf.c index b7070fe..2226fef 100644 --- a/rdoff/ldrdf.c +++ b/rdoff/ldrdf.c @@ -7,13 +7,9 @@ */ /* - * 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 + * TODO: + * enhance search of required export symbols in libraries (now depends + * on modules order in library) * - keep a cache of symbol names in each library module so * we don't have to constantly recheck the file * - general performance improvements @@ -21,11 +17,8 @@ * 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 + * won't work if compiled by a 16 bit compiler. Try DJGPP if you're running * under DOS. '#define STINGY_MEMORY' may help a little. - * - * TO FIX: enhance search of required export symbols in libraries (now depends - * on modules order in library). */ #include @@ -39,7 +32,7 @@ #include "rdlib.h" #include "segtab.h" -#define LDRDF_VERSION "1.03" +#define LDRDF_VERSION "1.04" #define RDF_MAXSEGS 64 /* #define STINGY_MEMORY */ @@ -104,35 +97,6 @@ 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; @@ -160,6 +124,29 @@ struct ldrdfoptions { int errorcount = 0; /* determines main program exit status */ +/* + * Multiboot header support. + */ + +/* loading address for multiboot header */ +unsigned MBHloadAddr; + +#define RDFLDR_LENGTH 4096 /* Loader size is 4K */ +#define RDFLDR_DESTLOC 0x100000 /* and its absolute address */ + +/* + * Tiny code that moves RDF setup code to its working memory region + */ +unsigned char trampoline_code[] = { + 0xBE, 0, 0, 0, 0, /* mov esi,SOURCE_ADDR */ + 0xBF, 0, 0, 0, 0, /* mov edi,DEST_ADDR */ + 0x89, 0xFA, /* mov edx,edi */ + 0xB9, 0, 4, 0, 0, /* mov ecx,RDFLDR_LENGTH/4 */ + 0xFC, /* cld */ + 0xF3, 0xA5, /* rep movsd */ + 0xFF, 0xE2 /* jmp edx */ +}; + /* ========================================================================= * Utility functions */ @@ -736,7 +723,7 @@ void write_output(const char * filename) hr = (rdfheaderrec *) malloc(sizeof(struct MultiBootHdrRec)); hr->mbh.type = 9; - hr->mbh.reclen = sizeof(struct tMultiBootHeader)+RDFLDRMOVER_SIZE; + hr->mbh.reclen = sizeof(struct tMultiBootHeader)+TRAMPOLINESIZE; hr->mbh.mb.Magic = MB_MAGIC; hr->mbh.mb.Flags = MB_FL_KLUDGE; @@ -745,7 +732,7 @@ void write_output(const char * filename) hr->mbh.mb.LoadAddr = MBHloadAddr; hr->mbh.mb.Entry = MBHloadAddr+16+sizeof(struct tMultiBootHeader); - memcpy(hr->mbh.mover,RDFloaderMover,RDFLDRMOVER_SIZE); + memcpy(hr->mbh.trampoline,trampoline_code,TRAMPOLINESIZE); rdfaddheader(rdfheader,hr); free(hr); @@ -931,8 +918,17 @@ void write_output(const char * filename) * Otherwise, we need to output a new relocation record * with the references updated segment and offset... */ - if (! isrelative - || cur->seginfo[localseg].dest_seg != seg) + + if (isrelative && cur->seginfo[localseg].dest_seg != seg) + { + hr->r.segment = cur->seginfo[localseg].dest_seg+64; + hr->r.offset += cur->seginfo[localseg].reloc; + hr->r.refseg = seg; + rdfaddheader(rdfheader, hr); + break; + } + + if (! isrelative || cur->seginfo[localseg].dest_seg != seg) { hr->r.segment = cur->seginfo[localseg].dest_seg; hr->r.offset += cur->seginfo[localseg].reloc; @@ -1094,11 +1090,14 @@ void write_output(const char * filename) 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); + unsigned *ldraddr = (unsigned *)(mbhrec->trampoline+1); + unsigned *ldrdest = (unsigned *)(mbhrec->trampoline+6); mbhrec->mb.LoadEndAddr = MBHloadAddr+l+10+RDFLDR_LENGTH; mbhrec->mb.BSSendAddr = mbhrec->mb.LoadEndAddr; + *ldraddr = MBHloadAddr+l+10; + *ldrdest = RDFLDR_DESTLOC; } rdfwriteheader(f, rdfheader); diff --git a/rdoff/rdflib.c b/rdoff/rdflib.c index c8bab74..1f19913 100644 --- a/rdoff/rdflib.c +++ b/rdoff/rdflib.c @@ -3,7 +3,13 @@ /* * an rdoff library is simply a sequence of RDOFF object files, each * preceded by the name of the module, an ASCII string of up to 255 - * characters, terminated by a zero. + * characters, terminated by a zero. + * + * When a library is being created, special signature block is placed + * in the beginning of the file. It is a string 'RDLIB' followed by a + * version number, then long content size and a long time stamp. + * The module name of the signature block is '.sig'. + * * * There may be an optional directory placed on the end of the file. * The format of the directory will be 'RDLDD' followed by a version @@ -11,16 +17,17 @@ * directory, the format of which has not yet been designed. * The module name of the directory must be '.dir'. * - * All module names beginning with '.' are reserved - * for possible future extensions. The linker ignores all such modules, - * assuming they have the format of a six byte type & version identifier - * followed by long content size, followed by data. + * All module names beginning with '.' are reserved for possible future + * extensions. The linker ignores all such modules, assuming they have + * the format of a six byte type & version identifier followed by long + * content size, followed by data. */ #include #include #include #include +#include /* functions supported: * create a library (no extra operands required) @@ -41,6 +48,9 @@ const char *usage = " r - replace (module-name filename)\n" " d - delete (module-name)\n" " t - list\n"; + +/* Library signature */ +const char *rdl_signature = "RDLIB2", *sig_modname = ".sig"; char **_argv; @@ -114,10 +124,11 @@ long copylong(FILE *fp, FILE *fp2) int main(int argc, char **argv) { - FILE *fp, *fp2, *fptmp; + FILE *fp, *fp2 = NULL, *fptmp; char *p, buf[256], c; int i; long l; + time_t t; char tmptempl[L_tmpnam], rdbuf[10]; _argv = argv; @@ -137,6 +148,11 @@ int main(int argc, char **argv) perror("rdflib"); exit(1); } + fwrite(sig_modname, 1, strlen(sig_modname)+1, fp); + fwrite(rdl_signature, 1, strlen(rdl_signature), fp); + l = sizeof(t = time(NULL)); + fwrite(&l, sizeof(l), 1, fp); + fwrite(&t, 1, l, fp); fclose(fp); break; diff --git a/rdoff/rdlib.c b/rdoff/rdlib.c index ed78a00..6eee5a9 100644 --- a/rdoff/rdlib.c +++ b/rdoff/rdlib.c @@ -6,11 +6,13 @@ #include "rdlib.h" /* - * format of rdoff library files: + * format of RDOFF library files: + * optional signature ('.sig') * repeat * null terminated module name (max 255 chars) * RDOFF module * until eof + * optional directory ('.dir') */ /* @@ -54,26 +56,27 @@ int rdl_verify(const char * filename) i++; if (feof(fp)) break; - fread(buf, 6, 1, fp); - buf[6] = 0; if (buf[0] == '.') { /* - * a special module, eg a directory. + * A special module, eg a signature block or a directory. * Format of such a module is defined to be: - * six char type identifier (which we've already read) + * six char type identifier * long count bytes content * content - * so we can handle it uniformaly with RDOFF2 modules... - * do nothing here. :-) + * so we can handle it uniformaly with RDOFF2 modules. */ + fread(buf, 6, 1, fp); + buf[6] = 0; + /* Currently, nothing useful to do with signature block.. */ + } else { + fread(buf, 6, 1, fp); + buf[6] = 0; + if (strncmp(buf, "RDOFF", 5)) { + return rdl_error = lastresult = 2; + } else if (buf[5] != '2') { + return rdl_error = lastresult = 3; + } } - else if (strncmp(buf, "RDOFF", 5)) { - return rdl_error = lastresult = 2; - } - else if (buf[5] != '2') { - return rdl_error = lastresult = 3; - } - fread(&length, 4, 1, fp); fseek(fp, length, SEEK_CUR); /* skip over the module */ } diff --git a/rdoff/rdoff.c b/rdoff/rdoff.c index 80b96cc..30d2c03 100644 --- a/rdoff/rdoff.c +++ b/rdoff/rdoff.c @@ -481,7 +481,7 @@ int rdfaddheader(rdf_headerbuf * h, rdfheaderrec * r) #ifdef _MULTBOOT_H case 9: /* MultiBoot header */ - membufwrite(h->buf,&r->mbh.mb,sizeof(struct tMultiBootHeader)+RDFLDRMOVER_SIZE); + membufwrite(h->buf,&r->mbh.mb,sizeof(struct tMultiBootHeader)+TRAMPOLINESIZE); break ; #endif diff --git a/rdoff/rdoff.h b/rdoff/rdoff.h index 4a81017..e9b9594 100644 --- a/rdoff/rdoff.h +++ b/rdoff/rdoff.h @@ -77,9 +77,11 @@ struct ModRec { #define SYM_FUNCTION 0x02 #define SYM_GLOBAL 0x04 +/* Multiboot record */ + #ifdef _MULTBOOT_H -#define RDFLDRMOVER_SIZE 22 +#define TRAMPOLINESIZE 22 struct MultiBootHdrRec { byte type; /* must be 9 */ @@ -88,9 +90,10 @@ struct MultiBootHdrRec { struct tMultiBootHeader mb __attribute__ ((packed)); /* MultiBoot header */ #else struct tMultiBootHeader mb; -#endif - byte mover[RDFLDRMOVER_SIZE]; /* Mover of RDF loader */ +#endif + byte trampoline[TRAMPOLINESIZE]; }; + #endif /* GenericRec - contains the type and length field, plus a 128 byte diff --git a/rdoff/symtab.c b/rdoff/symtab.c index 8570f98..4999176 100644 --- a/rdoff/symtab.c +++ b/rdoff/symtab.c @@ -117,10 +117,14 @@ symtabDump(void *stab, FILE* of) fprintf(of, " ... slot %d ...\n", i); } while(l) { - fprintf(of, "%-32s %s:%08lx (%ld)\n",l->ent.name, - SegNames[l->ent.segment], - l->ent.offset, l->ent.flags); - l = l->next; + if ((l->ent.segment) == -1) { + fprintf(of,"%-32s Unresolved reference\n",l->ent.name); + } else { + fprintf(of, "%-32s %s:%08lx (%ld)\n",l->ent.name, + SegNames[l->ent.segment], + l->ent.offset, l->ent.flags); + } + l = l->next; } } fprintf(of, "........... end of Symbol table.\n"); diff --git a/rdoff/test/makelib.sh b/rdoff/test/makelib.sh index 91bffa5..520bb19 100644 --- a/rdoff/test/makelib.sh +++ b/rdoff/test/makelib.sh @@ -1,5 +1,5 @@ #! /bin/sh - + [ $1 ] || { echo "Usage: $0 [...]" exit 1 -- 2.7.4