outrdf2.c now uses the same definitions of RDOFF2 format that RDOFF utils.

Export/import/common label size is increased from 33 to 64. Fixed the bug
that caused wrong behavior of rdfgetheaderrec() if label length was 32.
Changed error codes from numeric values to symbolic constants.
Moved some routines from rdfdump.c to rdoff.c. They will be utilized also
by rdfdisasm, which is being developed.
This commit is contained in:
Yuri Zaporogets 2004-09-15 06:54:34 +00:00
parent 7549d14998
commit e0c059ab4e
22 changed files with 873 additions and 851 deletions

View file

@ -1,10 +1,9 @@
/* outrdf2.c output routines for the Netwide Assembler to produce /*
* RDOFF version 2 format object files (which are intended * outrdf2.c output routines for the Netwide Assembler to produce
* mainly for use in proprietary projects, as the code to * RDOFF version 2 format object files, which is used as a
* load and execute them is very simple). They will also be * main binary format in the RadiOS (http://radios.sf.net).
* used for device drivers and possibly some executable files * Originally Julian planned to use it in his MOSCOW
* in the MOSCOW operating system. See Rdoff.txt for * operating system.
* details.
* *
* The Netwide Assembler is copyright (C) 1996-1998 Simon Tatham and * The Netwide Assembler is copyright (C) 1996-1998 Simon Tatham and
* Julian Hall. All rights reserved. The software is * Julian Hall. All rights reserved. The software is
@ -23,19 +22,15 @@
#include "outform.h" #include "outform.h"
/* VERBOSE_WARNINGS: define this to add some extra warnings... */ /* VERBOSE_WARNINGS: define this to add some extra warnings... */
#define VERBOSE_WARNINGS #define VERBOSE_WARNINGS
#ifdef OF_RDF2 #ifdef OF_RDF2
#define RDF_MAXSEGS 64 /* maximum number of segments - user configurable */ #include "rdoff/rdoff.h"
typedef unsigned short int16; /* This signature is written to start of RDOFF files */
typedef unsigned char byte; static const char *RDOFF2Id = RDOFF2_SIGNATURE;
static const char *RDOFF2Id = "RDOFF2"; /* written to start of RDOFF files */
/* the records that can be found in the RDOFF header */
/* Note that whenever a segment is referred to in the RDOFF file, its number /* Note that whenever a segment is referred to in the RDOFF file, its number
* is always half of the segment number that NASM uses to refer to it; this * is always half of the segment number that NASM uses to refer to it; this
@ -44,86 +39,16 @@ static const char *RDOFF2Id = "RDOFF2"; /* written to start of RDOFF files */
* allows up to 65533 external labels to be defined; otherwise it would be * allows up to 65533 external labels to be defined; otherwise it would be
* 32764. */ * 32764. */
#define RDFREC_RELOC 1
#define RDFREC_IMPORT 2
#define RDFREC_GLOBAL 3
#define RDFREC_DLL 4
#define RDFREC_BSS 5
#define RDFREC_SEGRELOC 6
#define RDFREC_FARIMPORT 7
#define RDFREC_MODNAME 8
#define RDFREC_COMMON 10
#define RDFREC_GENERIC 0
struct RelocRec {
byte type; /* must be 1, or 6 for segment base ref */
byte reclen; /* set to 8 */
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, or 7 for FAR import */
byte reclen; /* equals 3+label length */
byte flags; /* SYM_* flags (see below) */
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; /* equals 7+label length */
byte flags; /* SYM_* flags (see below) */
byte segment; /* segment referred to (0/1) */
long offset; /* offset within segment */
char label[33]; /* zero terminated as above. max len = 32 chars */
};
struct BSSRec {
byte type; /* must be 5 */
byte reclen; /* equals 4 */
long amount; /* number of bytes BSS to reserve */
};
struct DLLModRec {
byte type; /* 4 for DLLRec, 8 for ModRec */
byte reclen; /* 1+lib name length for DLLRec, 1+mod name length */
char name[128]; /* library to link at load time or module name */
};
struct CommonRec {
byte type; /* must be 10 */
byte reclen; /* equals 9+label length */
int16 segment; /* segment number */
long size; /* size of common variable */
int16 align; /* alignment (power of two) */
char label[33]; /* zero terminated as above. max len = 32 chars */
};
/* Flags for ExportRec */
#define SYM_DATA 1
#define SYM_FUNCTION 2
#define SYM_GLOBAL 4
#define SYM_IMPORT 8
#define COUNT_SEGTYPES 9 #define COUNT_SEGTYPES 9
static char * segmenttypes[COUNT_SEGTYPES] = { static char * segmenttypes[COUNT_SEGTYPES] = {
"null", "text", "code", "data", "comment", "lcomment", "pcomment", "null", "text", "code", "data",
"symdebug", "linedebug" "comment", "lcomment", "pcomment",
"symdebug", "linedebug"
}; };
static int segmenttypenumbers[COUNT_SEGTYPES] = { static int segmenttypenumbers[COUNT_SEGTYPES] = {
0, 1, 1, 2, 3, 4, 5, 6, 7 0, 1, 1, 2, 3, 4, 5, 6, 7
}; };
/* code for managing buffers needed to separate code and data into individual /* code for managing buffers needed to separate code and data into individual
@ -147,11 +72,11 @@ static FILE *ofile;
static efunc error; static efunc error;
static struct seginfo { static struct seginfo {
char *segname; char *segname;
int segnumber; int segnumber;
int16 segtype; uint16 segtype;
int16 segreserved; uint16 segreserved;
long seglength; long seglength;
} segments[RDF_MAXSEGS]; } segments[RDF_MAXSEGS];
static int nsegments; static int nsegments;
@ -290,11 +215,15 @@ static long rdf2_section_names(char *name, int pass, int *bits)
return i; return i;
} }
/*
* Write relocation record
*/
static void write_reloc_rec(struct RelocRec *r) static void write_reloc_rec(struct RelocRec *r)
{ {
char buf[4],*b; char buf[4],*b;
if (r->refseg != (int16)NO_SEG && (r->refseg & 1)) /* segment base ref */ if (r->refseg != (uint16)NO_SEG && (r->refseg & 1)) /* segment base ref */
r->type = RDFREC_SEGRELOC; r->type = RDFREC_SEGRELOC;
r->refseg >>= 1; /* adjust segment nos to RDF rather than NASM */ r->refseg >>= 1; /* adjust segment nos to RDF rather than NASM */
@ -310,37 +239,45 @@ static void write_reloc_rec(struct RelocRec *r)
headerlength += r->reclen + 2; headerlength += r->reclen + 2;
} }
/*
* Write export record
*/
static void write_export_rec(struct ExportRec *r) static void write_export_rec(struct ExportRec *r)
{ {
char buf[4], *b; char buf[4], *b;
r->segment >>= 1; r->segment >>= 1;
saa_wbytes(header,&r->type,1); saa_wbytes(header, &r->type, 1);
saa_wbytes(header,&r->reclen,1); saa_wbytes(header, &r->reclen, 1);
saa_wbytes(header,&r->flags,1); saa_wbytes(header, &r->flags, 1);
saa_wbytes(header,&r->segment,1); saa_wbytes(header, &r->segment, 1);
b = buf; WRITELONG(b,r->offset); b = buf; WRITELONG(b, r->offset);
saa_wbytes(header,buf,4); saa_wbytes(header, buf, 4);
saa_wbytes(header,r->label,strlen(r->label) + 1); saa_wbytes(header, r->label, strlen(r->label) + 1);
headerlength += r->reclen + 2; headerlength += r->reclen + 2;
} }
static void write_import_rec(struct ImportRec *r) static void write_import_rec(struct ImportRec *r)
{ {
char buf[4], *b; char buf[4], *b;
r->segment >>= 1; r->segment >>= 1;
saa_wbytes(header,&r->type,1); saa_wbytes(header, &r->type, 1);
saa_wbytes(header,&r->reclen,1); saa_wbytes(header, &r->reclen, 1);
saa_wbytes(header,&r->flags,1); saa_wbytes(header, &r->flags, 1);
b = buf; WRITESHORT(b,r->segment); b = buf; WRITESHORT(b,r->segment);
saa_wbytes(header,buf,2); saa_wbytes(header, buf, 2);
saa_wbytes(header,r->label,strlen(r->label) + 1); saa_wbytes(header, r->label, strlen(r->label) + 1);
headerlength += r->reclen + 2; headerlength += r->reclen + 2;
} }
/*
* Write BSS record
*/
static void write_bss_rec(struct BSSRec *r) static void write_bss_rec(struct BSSRec *r)
{ {
char buf[4], *b; char buf[4], *b;
@ -353,139 +290,160 @@ static void write_bss_rec(struct BSSRec *r)
} }
/* /*
* Write common variable record. * Write common variable record
*/ */
static void write_common_rec(struct CommonRec *r) static void write_common_rec(struct CommonRec *r)
{ {
char buf[4], *b; char buf[4], *b;
r->segment >>= 1; r->segment >>= 1;
saa_wbytes(header,&r->type,1); saa_wbytes(header, &r->type, 1);
saa_wbytes(header,&r->reclen,1); saa_wbytes(header, &r->reclen, 1);
b = buf; WRITESHORT(b,r->segment); b = buf; WRITESHORT(b,r->segment);
saa_wbytes(header,buf,2); saa_wbytes(header, buf, 2);
b = buf; WRITELONG(b,r->size); b = buf; WRITELONG(b, r->size);
saa_wbytes(header,buf,4); saa_wbytes(header,buf,4);
b = buf; WRITESHORT(b,r->align); b = buf; WRITESHORT(b, r->align);
saa_wbytes(header,buf,2); saa_wbytes(header, buf, 2);
saa_wbytes(header,r->label,strlen(r->label) + 1); saa_wbytes(header, r->label, strlen(r->label) + 1);
headerlength += r->reclen + 2;
}
/*
* Write library record. Also used for module name records.
*/
static void write_dllmod_rec(struct DLLModRec *r)
{
saa_wbytes(header,&r->type,1);
saa_wbytes(header,&r->reclen,1);
saa_wbytes(header,r->name,strlen(r->name) + 1);
headerlength += r->reclen + 2; headerlength += r->reclen + 2;
} }
/*
* Write library record
*/
static void write_dll_rec(struct DLLRec *r)
{
saa_wbytes(header,&r->type,1);
saa_wbytes(header,&r->reclen,1);
saa_wbytes(header, r->libname, strlen(r->libname) + 1);
headerlength += r->reclen + 2;
}
/*
* Write module name record
*/
static void write_modname_rec(struct ModRec *r)
{
saa_wbytes(header,&r->type,1);
saa_wbytes(header,&r->reclen,1);
saa_wbytes(header, r->modname, strlen(r->modname) + 1);
headerlength += r->reclen + 2;
}
/*
* Handle export, import and common records.
*/
static void rdf2_deflabel(char *name, long segment, long offset, static void rdf2_deflabel(char *name, long segment, long offset,
int is_global, char *special) int is_global, char *special)
{ {
struct ExportRec r; struct ExportRec r;
struct ImportRec ri; struct ImportRec ri;
struct CommonRec ci; struct CommonRec ci;
static int farsym = 0; static int farsym = 0;
static int i; static int i;
byte symflags = 0; byte symflags = 0;
int len;
if (is_global == 2) { /* Check if the label length is OK */
/* Common variable */ if ((len = strlen(name)) >= EXIM_LABEL_MAX) {
ci.type = RDFREC_COMMON; error(ERR_NONFATAL, "label size exceeds %d bytes", EXIM_LABEL_MAX);
ci.size = offset; return;
ci.segment = segment; }
strncpy(ci.label, name, 32); if (!len) {
ci.label[32] = 0; error(ERR_NONFATAL, "zero-length label");
ci.reclen = 9 + strlen(ci.label); return;
ci.align = 0; }
if (is_global == 2) {
/* Common variable */
ci.type = RDFREC_COMMON;
ci.size = offset;
ci.segment = segment;
strcpy(ci.label, name);
ci.reclen = 9 + len;
ci.align = 0;
/* /*
* Check the special text to see if it's a valid number and power * Check the special text to see if it's a valid number and power
* of two; if so, store it as the alignment for the common variable. * of two; if so, store it as the alignment for the common variable.
*/ */
if (special) {
int err;
ci.align = readnum(special, &err);
if (err)
error(ERR_NONFATAL, "alignment constraint `%s' is not a"
" valid number", special);
else if ( (ci.align | (ci.align-1)) != 2*ci.align - 1)
error(ERR_NONFATAL, "alignment constraint `%s' is not a"
" power of two", special);
}
write_common_rec(&ci);
}
/* We don't care about local labels or fix-up hints */
if (is_global != 1) return;
if (special) { if (special) {
int err; while(*special == ' ' || *special == '\t') special++;
ci.align = readnum(special, &err);
if (err) error(ERR_NONFATAL, "alignment constraint `%s' is not a"
" valid number", special);
else if ( (ci.align | (ci.align-1)) != 2*ci.align - 1)
error(ERR_NONFATAL, "alignment constraint `%s' is not a"
" power of two", special);
}
write_common_rec(&ci);
}
/* We don't care about local labels or fix-up hints */
if (is_global != 1) return;
if (special) {
while(*special == ' ' || *special == '\t') special++;
if (!nasm_strnicmp(special, "export", 6)) { if (!nasm_strnicmp(special, "export", 6)) {
special += 6; special += 6;
symflags |= SYM_GLOBAL; symflags |= SYM_GLOBAL;
} } else if (!nasm_strnicmp(special, "import", 6)) {
else if (!nasm_strnicmp(special, "import", 6)) { special += 6;
special += 6; symflags |= SYM_IMPORT;
symflags |= SYM_IMPORT; }
if (*special) {
while (isspace(*special)) special++;
if (!nasm_stricmp(special, "far")) {
farsym = 1;
} else if (!nasm_stricmp(special, "near")) {
farsym = 0;
} else if (!nasm_stricmp(special, "proc") ||
!nasm_stricmp(special, "function")) {
symflags |= SYM_FUNCTION;
} else if (!nasm_stricmp(special, "data") ||
!nasm_stricmp(special, "object")) {
symflags |= SYM_DATA;
} else
error(ERR_NONFATAL, "unrecognised symbol type `%s'", special);
}
} }
if (*special) { if (name[0] == '.' && name[1] == '.' && name[2] != '@') {
while(isspace(*special)) special++; error (ERR_NONFATAL, "unrecognised special symbol `%s'", name);
if (!nasm_stricmp(special, "far")) { return;
farsym = 1; }
}
else if (!nasm_stricmp(special, "near")) {
farsym = 0;
}
else if (!nasm_stricmp(special, "proc") ||
!nasm_stricmp(special, "function")) {
symflags |= SYM_FUNCTION;
}
else if (!nasm_stricmp(special, "data") ||
!nasm_stricmp(special, "object")) {
symflags |= SYM_DATA;
}
else
error(ERR_NONFATAL, "unrecognised symbol type `%s'", special);
}
}
if (name[0] == '.' && name[1] == '.' && name[2] != '@') { for (i = 0; i < nsegments; i++) {
error (ERR_NONFATAL, "unrecognised special symbol `%s'", name); if (segments[i].segnumber == segment>>1) break;
return; }
}
for (i = 0; i < nsegments; i++) { if (i >= nsegments) { /* EXTERN declaration */
if (segments[i].segnumber == segment>>1) break; ri.type = farsym ? RDFREC_FARIMPORT : RDFREC_IMPORT;
} if (symflags & SYM_GLOBAL)
if (i >= nsegments) { /* EXTERN declaration */ error(ERR_NONFATAL, "symbol type conflict - EXTERN cannot be EXPORT");
ri.type = farsym ? RDFREC_FARIMPORT : RDFREC_IMPORT; ri.flags = symflags;
if (symflags & SYM_GLOBAL) ri.segment = segment;
error(ERR_NONFATAL, "symbol type conflict - EXTERN cannot be EXPORT"); strcpy(ri.label, name);
ri.flags = symflags; ri.reclen = 4 + len;
ri.segment = segment; write_import_rec(&ri);
strncpy(ri.label,name,32); } else if (is_global) {
ri.label[32] = 0; r.type = RDFREC_GLOBAL; /* GLOBAL declaration */
ri.reclen = 4 + strlen(ri.label); if (symflags & SYM_IMPORT)
write_import_rec(&ri); error(ERR_NONFATAL, "symbol type conflict - GLOBAL cannot be IMPORT");
} else if (is_global) { r.flags = symflags;
r.type = RDFREC_GLOBAL; r.segment = segment;
if (symflags & SYM_IMPORT) r.offset = offset;
error(ERR_NONFATAL, "symbol type conflict - GLOBAL cannot be IMPORT"); strcpy(r.label, name);
r.flags = symflags; r.reclen = 7 + len;
r.segment = segment; write_export_rec(&r);
r.offset = offset; }
strncpy(r.label,name,32);
r.label[32] = 0;
r.reclen = 7 + strlen(r.label);
write_export_rec(&r);
}
} }
static void membufwrite(int segment, const void * data, int bytes) static void membufwrite(int segment, const void * data, int bytes)
@ -681,8 +639,7 @@ static void rdf2_cleanup (int debuginfo) {
/* generate the output file... */ /* generate the output file... */
fwrite(RDOFF2Id,6,1,ofile); /* file type magic number */ fwrite(RDOFF2Id,6,1,ofile); /* file type magic number */
if (bsslength != 0) /* reserve BSS */ if (bsslength != 0) { /* reserve BSS */
{
bs.type = RDFREC_BSS; bs.type = RDFREC_BSS;
bs.amount = bsslength; bs.amount = bsslength;
bs.reclen = 4; bs.reclen = 4;
@ -730,25 +687,38 @@ static long rdf2_segbase (long segment) {
return segment; return segment;
} }
static int rdf2_directive (char *directive, char *value, int pass) {
struct DLLModRec r; /*
* Handle RDOFF2 specific directives
*/
static int rdf2_directive (char *directive, char *value, int pass)
{
int n;
/* Check if the name length is OK */
if ((n = strlen(value)) >= MODLIB_NAME_MAX) {
error(ERR_NONFATAL, "name size exceeds %d bytes", MODLIB_NAME_MAX);
return 0;
}
if (! strcmp(directive, "library")) { if (! strcmp(directive, "library")) {
if (pass == 1) { if (pass == 1) {
struct DLLRec r;
r.type = RDFREC_DLL; r.type = RDFREC_DLL;
r.reclen=strlen(value)+1; r.reclen = n+1;
strcpy(r.name, value); strcpy(r.libname, value);
write_dllmod_rec(&r); write_dll_rec(&r);
} }
return 1; return 1;
} }
if (! strcmp(directive, "module")) { if (! strcmp(directive, "module")) {
if (pass == 1) { if (pass == 1) {
struct ModRec r;
r.type = RDFREC_MODNAME; r.type = RDFREC_MODNAME;
r.reclen=strlen(value)+1; r.reclen = n+1;
strcpy(r.name, value); strcpy(r.modname, value);
write_dllmod_rec(&r); write_modname_rec(&r);
} }
return 1; return 1;
} }

View file

@ -42,8 +42,8 @@ PROGRAMS = rdfdump$(X) ldrdf$(X) rdx$(X) rdflib$(X) \
all: $(PROGRAMS) all: $(PROGRAMS)
rdfdump$(X): rdfdump.$(O) rdfdump$(X): rdfdump.$(O) rdoff.$(O)
$(CC) $(LDFLAGS) -o rdfdump$(X) rdfdump.$(O) $(CC) $(LDFLAGS) -o rdfdump$(X) rdfdump.$(O) rdoff.$(O)
ldrdf$(X): ldrdf.$(O) $(LDRDFLIBS) ldrdf$(X): ldrdf.$(O) $(LDRDFLIBS)
$(CC) $(LDFLAGS) -o ldrdf$(X) ldrdf.$(O) $(LDRDFLIBS) $(CC) $(LDFLAGS) -o ldrdf$(X) ldrdf.$(O) $(LDRDFLIBS)
rdx$(X): rdx.$(O) $(RDXLIBS) rdx$(X): rdx.$(O) $(RDXLIBS)

View file

@ -33,8 +33,8 @@ RDXLIBS = rdoff.o rdfload.o symtab.o hash.o collectn.o
all: rdfdump ldrdf rdx rdflib rdf2bin rdf2com all: rdfdump ldrdf rdx rdflib rdf2bin rdf2com
rdfdump: rdfdump.o rdfdump: rdfdump.o rdoff.o
$(CC) -o rdfdump rdfdump.o $(CC) -o rdfdump rdfdump.o rdoff.o
ldrdf: ldrdf.o $(LDRDFLIBS) ldrdf: ldrdf.o $(LDRDFLIBS)
$(CC) -o ldrdf ldrdf.o $(LDRDFLIBS) $(CC) -o ldrdf ldrdf.o $(LDRDFLIBS)

View file

@ -33,8 +33,8 @@ RDXLIBS = rdoff.o rdfload.o symtab.o collectn.o hash.o
all: rdfdump ldrdf rdx rdflib rdf2bin all: rdfdump ldrdf rdx rdflib rdf2bin
rdfdump: rdfdump.o rdfdump: rdfdump.o rdoff.o
$(CC) $(LDFLAGS) -o rdfdump rdfdump.o $(LIBS) $(CC) $(LDFLAGS) -o rdfdump rdfdump.o rdoff.o $(LIBS)
ldrdf: ldrdf.o $(LDRDFLIBS) ldrdf: ldrdf.o $(LDRDFLIBS)
$(CC) $(LDFLAGS) -o ldrdf ldrdf.o $(LDRDFLIBS) $(LIBS) $(CC) $(LDFLAGS) -o ldrdf ldrdf.o $(LDRDFLIBS) $(LIBS)
rdx: rdx.o $(RDXLIBS) rdx: rdx.o $(RDXLIBS)

View file

@ -33,8 +33,8 @@ RDXLIBS = rdoff.o rdfload.o symtab.o hash.o collectn.o
all: rdfdump ldrdf rdx rdflib rdf2bin rdf2com all: rdfdump ldrdf rdx rdflib rdf2bin rdf2com
rdfdump: rdfdump.o rdfdump: rdfdump.o rdoff.o
$(CC) -o rdfdump rdfdump.o $(CC) -o rdfdump rdfdump.o rdoff.o
ldrdf: ldrdf.o $(LDRDFLIBS) ldrdf: ldrdf.o $(LDRDFLIBS)
$(CC) -o ldrdf ldrdf.o $(LDRDFLIBS) $(CC) -o ldrdf ldrdf.o $(LDRDFLIBS)

View file

@ -181,5 +181,5 @@ file for a comment containing the word 'TODO'. A brief list is given here:
MAINTAINERS MAINTAINERS
=========== ===========
Yuri Zaporogets <yuriz@ukr.net> - primary maintainer Yuri Zaporogets <yuriz@users.sf.net> - primary maintainer
Julian Hall <jules@dsf.org.uk> - original designer and author Julian Hall <jules@dsf.org.uk> - original designer and author

View file

@ -1,4 +1,5 @@
/* collectn.c Implements variable length pointer arrays [collections] /*
* collectn.c - implements variable length pointer arrays [collections].
* *
* This file is public domain. * This file is public domain.
*/ */
@ -8,33 +9,36 @@
void collection_init(Collection * c) void collection_init(Collection * c)
{ {
int i; int i;
for (i = 0; i < 32; i++) c->p[i] = NULL; for (i = 0; i < 32; i++)
c->next = NULL; c->p[i] = NULL;
c->next = NULL;
} }
void ** colln(Collection * c, int index) void **colln(Collection * c, int index)
{ {
while (index >= 32) { while (index >= 32) {
index -= 32; index -= 32;
if (c->next == NULL) { if (c->next == NULL) {
c->next = malloc(sizeof(Collection)); c->next = malloc(sizeof(Collection));
collection_init(c->next); collection_init(c->next);
}
c = c->next;
} }
c = c->next; return &(c->p[index]);
}
return &(c->p[index]);
} }
void collection_reset(Collection *c) void collection_reset(Collection * c)
{ {
int i; int i;
if (c->next) {
collection_reset(c->next);
free(c->next);
}
c->next = NULL; if (c->next) {
for (i = 0; i < 32; i++) c->p[i] = NULL; collection_reset(c->next);
free(c->next);
}
c->next = NULL;
for (i = 0; i < 32; i++)
c->p[i] = NULL;
} }

View file

@ -1,17 +1,18 @@
/* collectn.h Header file for 'collection' abstract data type /*
* collectn.h - header file for 'collection' abstract data type.
* *
* This file is public domain, and does not come under the NASM license. * This file is public domain, and does not come under the NASM license.
* It, along with 'collectn.c' implements what is basically a variable * It, along with 'collectn.c' implements what is basically a variable
* length array (of pointers) * length array (of pointers).
*/ */
#ifndef _COLLECTN_H #ifndef _COLLECTN_H
#define _COLLECTN_H #define _COLLECTN_H
typedef struct tagCollection { typedef struct tagCollection {
void *p[32]; /* array of pointers to objects */ void *p[32]; /* array of pointers to objects */
struct tagCollection *next; struct tagCollection *next;
} Collection; } Collection;
void collection_init(Collection * c); void collection_init(Collection * c);
@ -19,4 +20,3 @@ void ** colln(Collection * c, int index);
void collection_reset(Collection * c); void collection_reset(Collection * c);
#endif #endif

View file

@ -12,8 +12,8 @@
@end titlepage @end titlepage
@ifinfo @ifinfo
Copyright @copyright{} 2002-2003 Netwide Assembler Project. Copyright @copyright{} 2002-2004 Netwide Assembler Project.
Written by Yuri Zaporogets @email{yuriz@@ukr.net} Written by Yuri Zaporogets @email{yuriz@@users.sf.net}
Based on various sources and notes written by Julian Hall @email{jules@@dsf.org.uk} Based on various sources and notes written by Julian Hall @email{jules@@dsf.org.uk}
Distributed under GNU documentation license. Distributed under GNU documentation license.
@end ifinfo @end ifinfo

View file

@ -92,4 +92,3 @@ hash (const char *name)
return (hashval); return (hashval);
} }

View file

@ -2,7 +2,7 @@
* ldrdf.c - RDOFF Object File linker/loader main program. * ldrdf.c - RDOFF Object File linker/loader main program.
* *
* Copyright (c) 1996,99 Julian Hall. All rights reserved. * Copyright (c) 1996,99 Julian Hall. All rights reserved.
* Copyright (c) 2000-2003 RET & COM Research. * Improvements and fixes (c) 1999-2004 RET & COM Research.
* *
* This file is distributed under the terms and conditions of the * This file is distributed under the terms and conditions of the
* GNU Lesser Public License (LGPL), version 2.1. * GNU Lesser Public License (LGPL), version 2.1.
@ -28,6 +28,8 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#define RDOFF_UTILS
#include "rdoff.h" #include "rdoff.h"
#include "symtab.h" #include "symtab.h"
#include "collectn.h" #include "collectn.h"
@ -36,7 +38,6 @@
#define LDRDF_VERSION "1.07" #define LDRDF_VERSION "1.07"
#define RDF_MAXSEGS 64
/* #define STINGY_MEMORY */ /* #define STINGY_MEMORY */
/* ======================================================================= /* =======================================================================
@ -70,8 +71,8 @@ struct modulenode {
*/ */
void processmodule(const char * filename, struct modulenode * mod); void processmodule(const char * filename, struct modulenode * mod);
int allocnewseg(int16 type,int16 reserved); int allocnewseg(uint16 type,uint16 reserved);
int findsegment(int16 type,int16 reserved); int findsegment(uint16 type,uint16 reserved);
void symtab_add(const char * symbol, int segment, long offset); void symtab_add(const char * symbol, int segment, long offset);
int symtab_get(const char * symbol, int * segment, long * offset); int symtab_get(const char * symbol, int * segment, long * offset);
@ -219,8 +220,7 @@ void processmodule(const char * filename, struct modulenode * mod)
long bssamount = 0; long bssamount = 0;
int bss_was_referenced = 0; int bss_was_referenced = 0;
for (seg = 0; seg < mod->f.nsegs; seg++) for (seg = 0; seg < mod->f.nsegs; seg++) {
{
/* /*
* get the segment configuration for this type from the segment * get the segment configuration for this type from the segment
* table. getsegconfig() is a macro, defined in ldsegs.h. * table. getsegconfig() is a macro, defined in ldsegs.h.
@ -418,7 +418,7 @@ int lookformodule(const char *name)
* a segment of the type requested, and if one isn't found allocates a * a segment of the type requested, and if one isn't found allocates a
* new one. * new one.
*/ */
int allocnewseg(int16 type,int16 reserved) int allocnewseg(uint16 type,uint16 reserved)
{ {
outputseg[nsegs].type = type; outputseg[nsegs].type = type;
outputseg[nsegs].number = nsegs; outputseg[nsegs].number = nsegs;
@ -430,7 +430,7 @@ int allocnewseg(int16 type,int16 reserved)
return nsegs++; return nsegs++;
} }
int findsegment(int16 type,int16 reserved) int findsegment(uint16 type,uint16 reserved)
{ {
int i; int i;
@ -463,8 +463,7 @@ void symtab_add(const char * symbol, int segment, long offset)
symtabEnt * ste; symtabEnt * ste;
ste = symtabFind(symtab, symbol); ste = symtabFind(symtab, symbol);
if (ste) if (ste) {
{
if (ste->segment >= 0) { if (ste->segment >= 0) {
/* /*
* symbol previously defined * symbol previously defined
@ -516,9 +515,7 @@ int symtab_get(const char * symbol, int * segment, long * offset)
*segment = -1; *segment = -1;
*offset = 0; *offset = 0;
return 0; return 0;
} } else {
else
{
*segment = ste->segment; *segment = ste->segment;
*offset = ste->offset; *offset = ste->offset;
return 1; return 1;
@ -539,16 +536,13 @@ void add_library(const char * name)
errorcount++; errorcount++;
return; return;
} }
if (! libraries) if (!libraries) {
{
lastlib = libraries = malloc(sizeof(*libraries)); lastlib = libraries = malloc(sizeof(*libraries));
if (! libraries) { if (! libraries) {
fprintf(stderr, "ldrdf: out of memory\n"); fprintf(stderr, "ldrdf: out of memory\n");
exit(1); exit(1);
} }
} } else {
else
{
lastlib->next = malloc(sizeof(*libraries)); lastlib->next = malloc(sizeof(*libraries));
if (!lastlib->next) { if (!lastlib->next) {
fprintf(stderr, "ldrdf: out of memory\n"); fprintf(stderr, "ldrdf: out of memory\n");
@ -588,13 +582,11 @@ int search_libraries()
cur = libraries; cur = libraries;
while (cur) while (cur) {
{
if (options.verbose > 2) if (options.verbose > 2)
printf("scanning library `%s', pass %d...\n", cur->name, pass); printf("scanning library `%s', pass %d...\n", cur->name, pass);
for (i = 0; rdl_openmodule(cur, i, &f) == 0; i++) for (i = 0; rdl_openmodule(cur, i, &f) == 0; i++) {
{
if (pass == 2 && lookformodule(f.name)) continue; if (pass == 2 && lookformodule(f.name)) continue;
if (options.verbose > 3) if (options.verbose > 3)
@ -613,8 +605,7 @@ int search_libraries()
keepfile = 0; keepfile = 0;
while ((hr = rdfgetheaderrec (&f))) while ((hr = rdfgetheaderrec (&f))) {
{
/* We're only interested in exports, so skip others */ /* We're only interested in exports, so skip others */
if (hr->type != RDFREC_GLOBAL) continue; if (hr->type != RDFREC_GLOBAL) continue;
@ -744,8 +735,7 @@ void write_output(const char * filename)
* under 16 bit DOS, but that would be a slower way of doing this. * under 16 bit DOS, but that would be a slower way of doing this.
* And you could always use DJGPP... * And you could always use DJGPP...
*/ */
for (i = 0; i < nsegs; i++) for (i = 0; i < nsegs; i++) {
{
outputseg[i].data=NULL; outputseg[i].data=NULL;
if(!outputseg[i].length) continue; if(!outputseg[i].length) continue;
outputseg[i].data = malloc(outputseg[i].length); outputseg[i].data = malloc(outputseg[i].length);
@ -764,21 +754,18 @@ void write_output(const char * filename)
/* /*
* Step through the modules, performing required actions on each one * Step through the modules, performing required actions on each one
*/ */
for (cur = modules; cur; cur=cur->next) for (cur = modules; cur; cur=cur->next) {
{
/* /*
* Read the actual segment contents into the correct places in * Read the actual segment contents into the correct places in
* the newly allocated segments * the newly allocated segments
*/ */
for (i = 0; i < cur->f.nsegs; i++) for (i = 0; i < cur->f.nsegs; i++) {
{
int dest = cur->seginfo[i].dest_seg; int dest = cur->seginfo[i].dest_seg;
if (dest == -1) continue; if (dest == -1) continue;
if (rdfloadseg(&cur->f, i, if (rdfloadseg(&cur->f, i,
outputseg[dest].data + cur->seginfo[i].reloc)) outputseg[dest].data + cur->seginfo[i].reloc)) {
{
rdfperror("ldrdf", cur->name); rdfperror("ldrdf", cur->name);
exit(1); exit(1);
} }
@ -797,8 +784,7 @@ void write_output(const char * filename)
if (cur->f.header_loc) if (cur->f.header_loc)
rdfheaderrewind(&cur->f); rdfheaderrewind(&cur->f);
else else
if (rdfloadseg(&cur->f, RDOFF_HEADER, header)) if (rdfloadseg(&cur->f, RDOFF_HEADER, header)) {
{
rdfperror("ldrdf", cur->name); rdfperror("ldrdf", cur->name);
exit(1); exit(1);
} }
@ -808,18 +794,16 @@ void write_output(const char * filename)
* table for the segments in this module. * table for the segments in this module.
*/ */
init_seglocations(&segs); init_seglocations(&segs);
for (i = 0; i < cur->f.nsegs; i++) for (i = 0; i < cur->f.nsegs; i++) {
{
add_seglocation(&segs, cur->f.seg[i].number, add_seglocation(&segs, cur->f.seg[i].number,
cur->seginfo[i].dest_seg, cur->seginfo[i].reloc); cur->seginfo[i].dest_seg, cur->seginfo[i].reloc);
} }
/* /*
* and the BSS segment (doh!) * and the BSS segment (doh!)
*/ */
add_seglocation (&segs, 2, 2, cur->bss_reloc); add_seglocation(&segs, 2, 2, cur->bss_reloc);
while ((hr = rdfgetheaderrec(&cur->f))) while ((hr = rdfgetheaderrec(&cur->f))) {
{
switch(hr->type) { switch(hr->type) {
case RDFREC_RELOC: /* relocation record - need to do a fixup */ case RDFREC_RELOC: /* relocation record - need to do a fixup */
/* /*
@ -834,21 +818,18 @@ void write_output(const char * filename)
* case we have to first subtract the amount we've relocated * case we have to first subtract the amount we've relocated
* the containing segment by. * the containing segment by.
*/ */
if (!get_seglocation(&segs, hr->r.refseg, &seg, &offset)) {
if (!get_seglocation(&segs, hr->r.refseg, &seg, &offset))
{
fprintf(stderr, "%s: reloc to undefined segment %04x\n", fprintf(stderr, "%s: reloc to undefined segment %04x\n",
cur->name, (int) hr->r.refseg); cur->name, (int) hr->r.refseg);
errorcount++; errorcount++;
break; break;
} }
isrelative = (hr->r.segment & 64) == 64; isrelative = (hr->r.segment & RDOFF_RELATIVEMASK) == RDOFF_RELATIVEMASK;
hr->r.segment &= 63; hr->r.segment &= (RDOFF_RELATIVEMASK-1);
if (hr->r.segment == 2 || if (hr->r.segment == 2 ||
(localseg = rdffindsegment(&cur->f, hr->r.segment)) == -1) (localseg = rdffindsegment(&cur->f, hr->r.segment)) == -1) {
{
fprintf(stderr, "%s: reloc from %s segment (%d)\n", fprintf(stderr, "%s: reloc from %s segment (%d)\n",
cur->name, cur->name,
hr->r.segment == 2 ? "BSS" : "unknown", hr->r.segment == 2 ? "BSS" : "unknown",
@ -857,8 +838,8 @@ void write_output(const char * filename)
break; break;
} }
if (hr->r.length != 1 && hr->r.length != 2 && hr->r.length!=4) if (hr->r.length != 1 && hr->r.length != 2 &&
{ hr->r.length != 4 ) {
fprintf(stderr, "%s: nonstandard length reloc " fprintf(stderr, "%s: nonstandard length reloc "
"(%d bytes)\n", cur->name, hr->r.length); "(%d bytes)\n", cur->name, hr->r.length);
errorcount++; errorcount++;
@ -883,10 +864,10 @@ void write_output(const char * filename)
* Then add 'offset' onto the value at data. * Then add 'offset' onto the value at data.
*/ */
if (isrelative) offset -= cur->seginfo[localseg].reloc; if (isrelative)
switch (hr->r.length) offset -= cur->seginfo[localseg].reloc;
{ switch (hr->r.length) {
case 1: case 1:
offset += *data; offset += *data;
if (offset < -127 || offset > 128) if (offset < -127 || offset > 128)
fprintf(error_file, "warning: relocation out of range " fprintf(error_file, "warning: relocation out of range "
@ -894,7 +875,7 @@ void write_output(const char * filename)
(int)hr->r.segment, hr->r.offset); (int)hr->r.segment, hr->r.offset);
*data = (char) offset; *data = (char) offset;
break; break;
case 2: case 2:
offset += * (short *)data; offset += * (short *)data;
if (offset < -32767 || offset > 32768) if (offset < -32767 || offset > 32768)
fprintf(error_file, "warning: relocation out of range " fprintf(error_file, "warning: relocation out of range "
@ -902,7 +883,7 @@ void write_output(const char * filename)
(int)hr->r.segment, hr->r.offset); (int)hr->r.segment, hr->r.offset);
* (short *)data = (short) offset; * (short *)data = (short) offset;
break; break;
case 4: case 4:
* (long *)data += offset; * (long *)data += offset;
/* we can't easily detect overflow on this one */ /* we can't easily detect overflow on this one */
break; break;
@ -915,13 +896,12 @@ void write_output(const char * filename)
* Otherwise, we need to output a new relocation record * Otherwise, we need to output a new relocation record
* with the references updated segment and offset... * 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; hr->r.segment = cur->seginfo[localseg].dest_seg;
hr->r.offset += cur->seginfo[localseg].reloc; hr->r.offset += cur->seginfo[localseg].reloc;
hr->r.refseg = seg; hr->r.refseg = seg;
if (isrelative) if (isrelative)
hr->r.segment += 64; hr->r.segment += RDOFF_RELATIVEMASK;
rdfaddheader(rdfheader, hr); rdfaddheader(rdfheader, hr);
} }
break; break;
@ -1045,8 +1025,7 @@ void write_output(const char * filename)
hr->r.segment = cur->seginfo[localseg].dest_seg; hr->r.segment = cur->seginfo[localseg].dest_seg;
hr->r.offset += cur->seginfo[localseg].reloc; hr->r.offset += cur->seginfo[localseg].reloc;
if (!get_seglocation(&segs, hr->r.refseg, &seg, &offset)) if (!get_seglocation(&segs, hr->r.refseg, &seg, &offset)) {
{
fprintf(stderr, "%s: segment fixup to undefined " fprintf(stderr, "%s: segment fixup to undefined "
"segment %04x\n", cur->name, (int)hr->r.refseg); "segment %04x\n", cur->name, (int)hr->r.refseg);
errorcount++; errorcount++;
@ -1085,8 +1064,7 @@ void write_output(const char * filename)
/* /*
* Write the header * Write the header
*/ */
for (i = 0; i < nsegs; i++) for (i = 0; i < nsegs; i++) {
{
if (i == 2) continue; if (i == 2) continue;
rdfaddsegment (rdfheader, outputseg[i].length); rdfaddsegment (rdfheader, outputseg[i].length);
} }
@ -1098,9 +1076,8 @@ void write_output(const char * filename)
* Step through the segments, one at a time, writing out into * Step through the segments, one at a time, writing out into
* the output file * the output file
*/ */
for (i = 0; i < nsegs; i++) for (i = 0; i < nsegs; i++) {
{ uint16 s;
int16 s;
long l; long l;
if (i == 2) continue; if (i == 2) continue;
@ -1154,14 +1131,13 @@ int main(int argc, char ** argv)
error_file = stderr; error_file = stderr;
argc --, argv ++; argc--, argv++;
if (argc == 0) usage(); if (argc == 0) usage();
while (argc && *argv && **argv == '-' && argv[0][1] != 'l') while (argc && *argv && **argv == '-' && argv[0][1] != 'l') {
{
switch(argv[0][1]) { switch(argv[0][1]) {
case 'r': case 'r':
printf("ldrdf (linker for RDF files) version " LDRDF_VERSION "\n"); printf("ldrdf (linker for RDF files) version " LDRDF_VERSION "\n");
printf( _RDOFF_H "\n"); printf("RDOFF2 revision %s\n", RDOFF2_REVISION);
exit(0); exit(0);
case 'v': case 'v':
if (argv[0][2] == '=') { if (argv[0][2] == '=') {
@ -1318,3 +1294,4 @@ int main(int argc, char ** argv)
if (errorcount > 0) exit(1); if (errorcount > 0) exit(1);
return 0; return 0;
} }

View file

@ -1,11 +1,12 @@
/* rdf2bin: convert an RDOFF object file to flat binary */ /*
* rdf2bin.c - convert an RDOFF object file to flat binary
*/
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include "rdfload.h" #include "rdfload.h"
#include "rdoff.h"
#include "nasmlib.h" #include "nasmlib.h"
long origin = 0; long origin = 0;

View file

@ -1,12 +1,14 @@
/* rdf2ihx: convert an RDOFF object file to Intel Hex format. This is based /*
on rdf2bin. Note that this program only writes 16-bit HEX. */ * rdf2ihx.c - convert an RDOFF object file to Intel Hex format.
* This is based on rdf2bin.
* Note that this program only writes 16-bit HEX.
*/
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include "rdfload.h" #include "rdfload.h"
#include "rdoff.h"
#include "nasmlib.h" #include "nasmlib.h"
#include "symtab.h" #include "symtab.h"
@ -186,4 +188,3 @@ int main(int argc, char **argv)
fclose(of); fclose(of);
return 0; return 0;
} }

View file

@ -6,74 +6,52 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#define RDOFF_UTILS
#include "rdoff.h" #include "rdoff.h"
#define PROGRAM_VERSION "2.3"
FILE *infile; FILE *infile;
/* Translate from little endian to local representation */
long translatelong(long in)
{
long r;
unsigned char *i;
i = (unsigned char *)&in;
r = i[3];
r = (r << 8) + i[2];
r = (r << 8) + i[1];
r = (r << 8) + *i;
return r;
}
int16 translateshort(int16 in)
{
int r;
unsigned char *i;
i = (unsigned char *)&in;
r = (i[1] << 8) + *i;
return r;
}
void print_header(long length, int rdf_version) void print_header(long length, int rdf_version)
{ {
char buf[129],t,l,s,flags; char buf[129], t, l, s, flags;
unsigned char reclen; unsigned char reclen;
long o,ll; long o, ll;
int16 rs; uint16 rs;
while (length > 0) { while (length > 0) {
fread(&t,1,1,infile); fread(&t, 1, 1, infile);
if (rdf_version >= 2) { if (rdf_version >= 2) {
fread(&reclen,1,1,infile); fread(&reclen, 1, 1, infile);
} }
switch(t) { switch (t) {
case RDFREC_GENERIC: /* generic record */ case RDFREC_GENERIC: /* generic record */
printf(" generic record (length=%d)\n", (int)reclen); printf(" generic record (length=%d)\n", (int) reclen);
fseek(infile, reclen, SEEK_CUR); fseek(infile, reclen, SEEK_CUR);
break; break;
case RDFREC_RELOC: /* relocation record */ case RDFREC_RELOC: /* relocation record */
case RDFREC_SEGRELOC: /* segment relocation */ case RDFREC_SEGRELOC: /* segment relocation */
fread(&s,1,1,infile); fread(&s, 1, 1, infile);
fread(&o,4,1,infile); fread(&o, 4, 1, infile);
fread(&l,1,1,infile); fread(&l, 1, 1, infile);
fread(&rs,2,1,infile); fread(&rs, 2, 1, infile);
printf(" %s: location (%04x:%08lx), length %d, " printf(" %s: location (%04x:%08lx), length %d, "
"referred seg %04x\n", t == 1 ? "relocation" : "seg relocation", "referred seg %04x\n", t == 1 ? "relocation" : "seg relocation",
(int)s,translatelong(o),(int)l, (int) s, translatelong(o), (int) l, translateshort(rs));
translateshort(rs)); if (rdf_version >= 2 && reclen != 8)
if (rdf_version >= 2 && reclen != 8)
printf(" warning: reclen != 8\n"); printf(" warning: reclen != 8\n");
if (rdf_version == 1) length -= 9; if (rdf_version == 1)
length -= 9;
if (rdf_version == 1 && t == 6) if (rdf_version == 1 && t == 6)
printf(" warning: seg relocation not supported in RDOFF1\n"); printf(" warning: seg relocation not supported in RDOFF1\n");
break; break;
case RDFREC_IMPORT: /* import record */ case RDFREC_IMPORT: /* import record */
case RDFREC_FARIMPORT: /* import far symbol */ case RDFREC_FARIMPORT: /* import far symbol */
fread(&flags, 1, 1, infile); fread(&flags, 1, 1, infile);
fread(&rs, 2, 1, infile); fread(&rs, 2, 1, infile);
ll = 0; ll = 0;
@ -82,22 +60,25 @@ void print_header(long length, int rdf_version)
fread(&buf[ll], 1, 1, infile); fread(&buf[ll], 1, 1, infile);
} while (buf[ll++]); } while (buf[ll++]);
} else { } else {
for (;ll < reclen - 3; ll++) for (; ll < reclen - 3; ll++)
fread(&buf[ll], 1, 1, infile); fread(&buf[ll], 1, 1, infile);
} }
if (t == 7) if (t == 7)
printf("far "); printf("far ");
printf((flags & SYM_IMPORT) ? " import" : " extern"); printf((flags & SYM_IMPORT) ? " import" : " extern");
if (flags & SYM_FUNCTION) printf(" proc"); if (flags & SYM_FUNCTION)
if (flags & SYM_DATA) printf(" data"); printf(" proc");
if (flags & SYM_DATA)
printf(" data");
printf(": segment %04x = %s\n", translateshort(rs), buf); printf(": segment %04x = %s\n", translateshort(rs), buf);
if (rdf_version == 1) length -= ll + 3; if (rdf_version == 1)
length -= ll + 3;
if (rdf_version == 1 && t == 7) if (rdf_version == 1 && t == 7)
printf (" warning: far import not supported in RDOFF1\n"); printf(" warning: far import not supported in RDOFF1\n");
break; break;
case RDFREC_GLOBAL: /* export record */ case RDFREC_GLOBAL: /* export record */
fread(&flags, 1, 1, infile); fread(&flags, 1, 1, infile);
fread(&s, 1, 1, infile); fread(&s, 1, 1, infile);
fread(&o, 4, 1, infile); fread(&o, 4, 1, infile);
@ -105,228 +86,218 @@ void print_header(long length, int rdf_version)
if (rdf_version == 1) { if (rdf_version == 1) {
do { do {
fread(&buf[ll], 1, 1, infile); fread(&buf[ll], 1, 1, infile);
} while (buf[ll++]); } while (buf[ll++]);
} else { } else {
for (; ll < reclen - 6; ll ++) for (; ll < reclen - 6; ll++)
fread(&buf[ll], 1, 1, infile); fread(&buf[ll], 1, 1, infile);
} }
printf((flags & SYM_GLOBAL) ? " export" : " public"); printf((flags & SYM_GLOBAL) ? " export" : " public");
if (flags & SYM_FUNCTION) printf(" proc"); if (flags & SYM_FUNCTION)
if (flags & SYM_DATA) printf(" data"); printf(" proc");
printf(": (%04x:%08lx) = %s\n", (int)s, translatelong(o), buf); if (flags & SYM_DATA)
if (rdf_version == 1) length -= ll + 6; printf(" data");
printf(": (%04x:%08lx) = %s\n", (int) s, translatelong(o), buf);
if (rdf_version == 1)
length -= ll + 6;
break; break;
case RDFREC_DLL: /* DLL and Module records */ case RDFREC_DLL: /* DLL and Module records */
case RDFREC_MODNAME: case RDFREC_MODNAME:
ll = 0; ll = 0;
if (rdf_version == 1) { if (rdf_version == 1) {
do { do {
fread(&buf[ll],1,1,infile); fread(&buf[ll], 1, 1, infile);
} while (buf[ll++]); } while (buf[ll++]);
} else { } else {
for (; ll < reclen; ll++) for (; ll < reclen; ll++)
fread(&buf[ll], 1, 1, infile); fread(&buf[ll], 1, 1, infile);
} }
if (t==4) printf(" dll: %s\n",buf); if (t == 4)
else printf(" module: %s\n",buf); printf(" dll: %s\n", buf);
else
printf(" module: %s\n", buf);
if (rdf_version == 1) if (rdf_version == 1)
length -= ll + 1; length -= ll + 1;
break; break;
case RDFREC_BSS: /* BSS reservation */ case RDFREC_BSS: /* BSS reservation */
fread(&ll,4,1,infile); fread(&ll, 4, 1, infile);
printf(" bss reservation: %08lx bytes\n",translatelong(ll)); printf(" bss reservation: %08lx bytes\n", translatelong(ll));
if (rdf_version == 1) length -= 5; if (rdf_version == 1)
length -= 5;
if (rdf_version > 1 && reclen != 4) if (rdf_version > 1 && reclen != 4)
printf(" warning: reclen != 4\n"); printf(" warning: reclen != 4\n");
break; break;
case RDFREC_COMMON: { case RDFREC_COMMON: {
unsigned short seg, align; unsigned short seg, align;
unsigned long size; unsigned long size;
fread(&seg, 2, 1, infile); fread(&seg, 2, 1, infile);
fread(&size, 4, 1, infile); fread(&size, 4, 1, infile);
fread(&align, 2, 1, infile); fread(&align, 2, 1, infile);
for (ll = 0; ll < reclen - 8; ll++) for (ll = 0; ll < reclen - 8; ll++)
fread(buf+ll, 1, 1, infile); fread(buf + ll, 1, 1, infile);
printf(" common: segment %04x = %s, %ld:%d\n", translateshort(seg), printf(" common: segment %04x = %s, %ld:%d\n", translateshort(seg),
buf, translatelong(size), translateshort(align)); buf, translatelong(size), translateshort(align));
break; break;
} }
default: default:
printf(" unrecognized record (type %d", (int)t); printf(" unrecognized record (type %d", (int) t);
if (rdf_version > 1) { if (rdf_version > 1) {
printf(", length %d",(int)reclen); printf(", length %d", (int) reclen);
fseek(infile,reclen,SEEK_CUR); fseek(infile, reclen, SEEK_CUR);
} else length --; } else
printf(")\n"); length--;
printf(")\n");
} }
if (rdf_version != 1) length -= 2 + reclen; if (rdf_version != 1)
length -= 2 + reclen;
} }
} }
char * knowntypes[8] = {"NULL", "text", "data", "object comment", int main(int argc, char **argv)
"linked comment", "loader comment", {
"symbolic debug", "line number debug"}; char id[7];
long l;
uint16 s;
int verbose = 0;
long offset;
int foundnullsegment = 0;
int version;
long segmentcontentlength = 0;
int nsegments = 0;
long headerlength = 0;
long objectlength = 0;
char * translatesegmenttype(int16 type) { printf("RDOFF dump utility, version %s\n", PROGRAM_VERSION);
if (type < 8) return knowntypes[type]; printf("RDOFF2 revision %s\n", RDOFF2_REVISION);
if (type < 0x0020) return "reserved"; puts("Copyright (c) 1996,99 Julian R Hall\n"
if (type < 0x1000) return "reserved - moscow"; "Improvements and fixes (c) 2002-2004 RET & COM Research.");
if (type < 0x8000) return "reserved - system dependant";
if (type < 0xFFFF) return "reserved - other";
if (type == 0xFFFF) return "invalid type code";
return "type code out of range";
}
int main(int argc,char **argv) { if (argc < 2) {
char id[7]; fputs("Usage: rdfdump [-v] <filename>\n", stderr);
long l; exit(1);
int16 s;
int verbose = 0;
long offset;
int foundnullsegment = 0;
int version;
long segmentcontentlength = 0;
int nsegments = 0;
long headerlength = 0;
long objectlength = 0;
puts("RDOFF Dump utility v2.2\n"\
"Copyright (c) 1996,99 Julian R Hall\n"
"Copyright (c) 2000-2002 RET & COM Research.");
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 (!strcmp(argv[1], "-v")) {
if (! infile) { verbose = 1;
fprintf(stderr,"rdfdump: Could not open %s\n",argv[1]); if (argc < 3) {
exit(1); fputs("required parameter missing\n", stderr);
} exit(1);
}
argv++;
}
fread(id,6,1,infile); infile = fopen(argv[1], "rb");
if (strncmp(id,"RDOFF",5)) { if (!infile) {
fputs("rdfdump: File does not contain valid RDOFF header\n",stderr); fprintf(stderr, "rdfdump: Could not open %s\n", argv[1]);
exit(1); exit(1);
} }
printf("File %s: RDOFF version %c\n\n",argv[1],id[5]); fread(id, 6, 1, infile);
if (id[5] < '1' || id[5] > '2') { if (strncmp(id, "RDOFF", 5)) {
fprintf(stderr,"rdfdump: unknown RDOFF version '%c'\n",id[5]); fputs("rdfdump: File does not contain valid RDOFF header\n", stderr);
exit(1); exit(1);
} }
version = id[5] - '0';
if (version > 1) { printf("File %s: RDOFF version %c\n\n", argv[1], id[5]);
fread(&l, 4, 1, infile); if (id[5] < '1' || id[5] > '2') {
objectlength = translatelong(l); fprintf(stderr, "rdfdump: unknown RDOFF version '%c'\n", id[5]);
printf("Object content size: %ld bytes\n", objectlength); exit(1);
} }
version = id[5] - '0';
fread(&l,4,1,infile); if (version > 1) {
headerlength = translatelong(l); fread(&l, 4, 1, infile);
printf("Header (%ld bytes):\n",headerlength); objectlength = translatelong(l);
print_header(headerlength, version); printf("Object content size: %ld bytes\n", objectlength);
}
if (version == 1) { fread(&l, 4, 1, infile);
fread(&l,4,1,infile); headerlength = translatelong(l);
l = translatelong(l); printf("Header (%ld bytes):\n", headerlength);
printf("\nText segment length = %ld bytes\n",l); print_header(headerlength, version);
offset = 0;
while(l--) {
fread(id,1,1,infile);
if (verbose) {
if (offset % 16 == 0)
printf("\n%08lx ", offset);
printf(" %02x",(int) (unsigned char)id[0]);
offset++;
}
}
if (verbose) printf("\n\n");
fread(&l,4,1,infile);
l = translatelong(l);
printf("Data segment length = %ld bytes\n",l);
if (verbose) if (version == 1) {
{ fread(&l, 4, 1, infile);
offset = 0; l = translatelong(l);
while (l--) { printf("\nText segment length = %ld bytes\n", l);
fread(id,1,1,infile); offset = 0;
if (offset % 16 == 0) while (l--) {
printf("\n%08lx ", offset); fread(id, 1, 1, infile);
printf(" %02x",(int) (unsigned char) id[0]); if (verbose) {
offset++; if (offset % 16 == 0)
} printf("\n%08lx ", offset);
printf("\n"); printf(" %02x", (int) (unsigned char) id[0]);
} offset++;
} }
else }
{ if (verbose)
do { printf("\n\n");
fread(&s,2,1,infile);
s = translateshort(s);
if (!s) {
printf("\nNULL segment\n");
foundnullsegment = 1;
break;
}
printf("\nSegment:\n Type = %04X (%s)\n",(int)s,
translatesegmenttype(s));
nsegments++;
fread(&s,2,1,infile); fread(&l, 4, 1, infile);
printf(" Number = %04X\n",(int)translateshort(s)); l = translatelong(l);
fread(&s,2,1,infile); printf("Data segment length = %ld bytes\n", l);
printf(" Resrvd = %04X\n",(int)translateshort(s));
fread(&l,4,1,infile);
l = translatelong(l);
printf(" Length = %ld bytes\n",l);
segmentcontentlength += l;
offset = 0; if (verbose) {
while(l--) { offset = 0;
fread(id,1,1,infile); while (l--) {
if (verbose) { fread(id, 1, 1, infile);
if (offset % 16 == 0) if (offset % 16 == 0)
printf("\n%08lx ", offset); printf("\n%08lx ", offset);
printf(" %02x",(int) (unsigned char)id[0]); printf(" %02x", (int) (unsigned char) id[0]);
offset++; offset++;
} }
} printf("\n");
if (verbose) printf("\n"); }
} while (!feof(infile)); } else {
if (! foundnullsegment) do {
printf("\nWarning: unexpected end of file - " fread(&s, 2, 1, infile);
"NULL segment not found\n"); s = translateshort(s);
if (!s) {
printf("\nNULL segment\n");
foundnullsegment = 1;
break;
}
printf("\nSegment:\n Type = %04X (%s)\n", (int) s, translatesegmenttype(s));
nsegments++;
printf("\nTotal number of segments: %d\n", nsegments); fread(&s, 2, 1, infile);
printf("Total segment content length: %ld bytes\n",segmentcontentlength); printf(" Number = %04X\n", (int) translateshort(s));
fread(&s, 2, 1, infile);
printf(" Resrvd = %04X\n", (int) translateshort(s));
fread(&l, 4, 1, infile);
l = translatelong(l);
printf(" Length = %ld bytes\n", l);
segmentcontentlength += l;
/* calculate what the total object content length should have been */ offset = 0;
l = segmentcontentlength + 10 * (nsegments+1) + headerlength + 4; while (l--) {
if (l != objectlength) fread(id, 1, 1, infile);
printf("Warning: actual object length (%ld) != " if (verbose) {
"stored object length (%ld)\n", l, objectlength); if (offset % 16 == 0)
} printf("\n%08lx ", offset);
fclose(infile); printf(" %02x", (int) (unsigned char) id[0]);
return 0; offset++;
}
}
if (verbose)
printf("\n");
} while (!feof(infile));
if (!foundnullsegment)
printf("\nWarning: unexpected end of file - " "NULL segment not found\n");
printf("\nTotal number of segments: %d\n", nsegments);
printf("Total segment content length: %ld bytes\n", segmentcontentlength);
/* calculate what the total object content length should have been */
l = segmentcontentlength + 10 * (nsegments + 1) + headerlength + 4;
if (l != objectlength)
printf("Warning: actual object length (%ld) != " "stored object length (%ld)\n", l, objectlength);
}
fclose(infile);
return 0;
} }

View file

@ -23,7 +23,6 @@
#include "rdfload.h" #include "rdfload.h"
#include "symtab.h" #include "symtab.h"
#include "rdoff.h"
#include "collectn.h" #include "collectn.h"
extern int rdf_errno; extern int rdf_errno;
@ -36,17 +35,15 @@ rdfmodule * rdfload(const char *filename)
rdfheaderrec *r; rdfheaderrec *r;
f = malloc(sizeof(rdfmodule)); f = malloc(sizeof(rdfmodule));
if (f == NULL) if (f == NULL) {
{ rdf_errno = RDF_ERR_NOMEM;
rdf_errno = 6; /* out of memory */
return NULL; return NULL;
} }
f->symtab = symtabNew(); f->symtab = symtabNew();
if (!f->symtab) if (!f->symtab) {
{
free(f); free(f);
rdf_errno = 6; rdf_errno = RDF_ERR_NOMEM;
return NULL; return NULL;
} }
@ -63,7 +60,7 @@ rdfmodule * rdfload(const char *filename)
hdr = malloc (f->f.header_len); hdr = malloc (f->f.header_len);
if (! f->t || ! f->d || !hdr) { if (! f->t || ! f->d || !hdr) {
rdf_errno = 6; rdf_errno = RDF_ERR_NOMEM;
rdfclose(&f->f); rdfclose(&f->f);
if (f->t) free(f->t); if (f->t) free(f->t);
if (f->d) free(f->d); if (f->d) free(f->d);
@ -87,20 +84,18 @@ rdfmodule * rdfload(const char *filename)
/* Allocate BSS segment; step through header and count BSS records */ /* Allocate BSS segment; step through header and count BSS records */
while ( ( r = rdfgetheaderrec (&f->f) ) ) while ((r = rdfgetheaderrec(&f->f))) {
{
if (r->type == 5) if (r->type == 5)
bsslength += r->b.amount; bsslength += r->b.amount;
} }
f->b = malloc ( bsslength ); f->b = malloc ( bsslength );
if (bsslength && (!f->b)) if (bsslength && (!f->b)) {
{
free(f->t); free(f->t);
free(f->d); free(f->d);
free(f); free(f);
free(hdr); free(hdr);
rdf_errno = 6; rdf_errno = RDF_ERR_NOMEM;
return NULL; return NULL;
} }
@ -121,13 +116,11 @@ int rdf_relocate(rdfmodule * m)
long rel; long rel;
unsigned char * seg; unsigned char * seg;
rdfheaderrewind ( & m->f ); rdfheaderrewind (&m->f);
collection_init(&imports); collection_init(&imports);
while ( (r = rdfgetheaderrec ( & m->f ) ) ) while ((r = rdfgetheaderrec(&m->f))) {
{ switch (r->type) {
switch (r->type)
{
case 1: /* Relocation record */ case 1: /* Relocation record */
/* calculate relocation factor */ /* calculate relocation factor */
@ -154,7 +147,7 @@ int rdf_relocate(rdfmodule * m)
seg[r->r.offset] += (char) rel; seg[r->r.offset] += (char) rel;
break; break;
case 2: case 2:
*(int16 *)(seg + r->r.offset) += (int16) rel; *(uint16 *)(seg + r->r.offset) += (uint16) rel;
break; break;
case 4: case 4:
*(long *)(seg + r->r.offset) += rel; *(long *)(seg + r->r.offset) += rel;

View file

@ -12,6 +12,8 @@
#ifndef _RDFLOAD_H #ifndef _RDFLOAD_H
#define _RDFLOAD_H #define _RDFLOAD_H
#define RDOFF_UTILS
#include "rdoff.h" #include "rdoff.h"
typedef struct RDFModuleStruct { typedef struct RDFModuleStruct {

View file

@ -6,6 +6,8 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#define RDOFF_UTILS
#include "rdoff.h" #include "rdoff.h"
#include "rdlib.h" #include "rdlib.h"
#include "rdlar.h" #include "rdlar.h"
@ -264,6 +266,3 @@ void rdl_perror(const char *apname, const char *filename)
else else
fprintf(stderr,"%s:%s:%s\n",apname,filename,rdl_errors[rdl_error]); fprintf(stderr,"%s:%s:%s\n",apname,filename,rdl_errors[rdl_error]);
} }

View file

@ -1,4 +1,6 @@
/* rdlib.h Functions for manipulating librarys of RDOFF object files */ /*
* rdlib.h Functions for manipulating libraries of RDOFF object files.
*/
struct librarynode { struct librarynode {
@ -23,5 +25,3 @@ int rdl_searchlib (struct librarynode * lib,
int rdl_openmodule (struct librarynode * lib, int module, rdffile * f); int rdl_openmodule (struct librarynode * lib, int module, rdffile * f);
void rdl_perror(const char *apname, const char *filename); void rdl_perror(const char *apname, const char *filename);

View file

@ -19,6 +19,9 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <errno.h> #include <errno.h>
#define RDOFF_UTILS
#include "rdoff.h" #include "rdoff.h"
#define newstr(str) strcpy(malloc(strlen(str) + 1),str) #define newstr(str) strcpy(malloc(strlen(str) + 1),str)
@ -53,7 +56,7 @@ memorybuffer * newmembuf()
void membufwrite(memorybuffer *const b, void *data, int bytes) void membufwrite(memorybuffer *const b, void *data, int bytes)
{ {
int16 w; uint16 w;
long l; long l;
if (b->next) { /* memory buffer full - use next buffer */ if (b->next) { /* memory buffer full - use next buffer */
@ -85,7 +88,7 @@ void membufwrite(memorybuffer *const b, void *data, int bytes)
break; break;
case -2: case -2:
w = * (int16 *) data ; w = * (uint16 *) data ;
b->buffer[b->length++] = w & 0xFF; b->buffer[b->length++] = w & 0xFF;
w >>= 8 ; w >>= 8 ;
b->buffer[b->length++] = w & 0xFF; b->buffer[b->length++] = w & 0xFF;
@ -146,9 +149,9 @@ long translatelong(long in)
return r; return r;
} }
int16 translateshort(int16 in) uint16 translateshort(uint16 in)
{ {
int16 r; uint16 r;
unsigned char * i; unsigned char * i;
i = (unsigned char *)&in; i = (unsigned char *)&in;
@ -157,15 +160,48 @@ int16 translateshort(int16 in)
return r; return r;
} }
const char *RDOFFId = "RDOFF2"; /* written to the start of RDOFF files */ /* Segment types */
static char *knownsegtypes[8] = {
"NULL", "text", "data", "object comment",
"linked comment", "loader comment",
"symbolic debug", "line number debug"
};
/* Get a textual string describing the segment type */
char *translatesegmenttype(uint16 type)
{
if (type < 8)
return knownsegtypes[type];
if (type < 0x0020)
return "reserved";
if (type < 0x1000)
return "reserved - Moscow";
if (type < 0x8000)
return "reserved - system dependant";
if (type < 0xFFFF)
return "reserved - other";
if (type == 0xFFFF)
return "invalid type code";
return "type code out of range";
}
/* This signature is written to the start of RDOFF files */
const char *RDOFFId = RDOFF2_SIGNATURE;
/* Error messages. Must correspond to the codes defined in rdoff.h */
const char *rdf_errors[11] = { const char *rdf_errors[11] = {
"no error occurred","could not open file","invalid file format", /* 0 */ "no error occurred",
"error reading file","unknown error","header not read", /* 1 */ "could not open file",
"out of memory", "RDOFF v1 not supported", /* 2 */ "invalid file format",
"unknown extended header record", /* 3 */ "error reading file",
"header record of known type but unknown length", /* 4 */ "unknown error",
"no such segment"}; /* 5 */ "header not read",
/* 6 */ "out of memory",
/* 7 */ "RDOFF v1 not supported",
/* 8 */ "unknown extended header record",
/* 9 */ "header record of known type but unknown length",
/* 10 */ "no such segment"
};
int rdf_errno = 0; int rdf_errno = 0;
@ -178,119 +214,120 @@ int rdfopen(rdffile *f, const char *name)
FILE * fp; FILE * fp;
fp = fopen(name,"rb"); fp = fopen(name,"rb");
if (!fp) return rdf_errno = 1; /* error 1: file open error */ if (!fp)
return rdf_errno = RDF_ERR_OPEN;
return rdfopenhere(f,fp,NULL,name); return rdfopenhere(f,fp,NULL,name);
} }
int rdfopenhere(rdffile *f, FILE *fp, int *refcount, const char *name) int rdfopenhere(rdffile *f, FILE *fp, int *refcount, const char *name)
{ {
char buf[8]; char buf[8];
long initpos; long initpos;
long l; long l;
int16 s; uint16 s;
if (translatelong(0x01020304) != 0x01020304) if (translatelong(0x01020304) != 0x01020304) {
{ /* fix this to be portable! */ /* fix this to be portable! */
fputs("*** this program requires a little endian machine\n",stderr); fputs("*** this program requires a little endian machine\n",stderr);
fprintf(stderr,"01020304h = %08lxh\n",translatelong(0x01020304)); fprintf(stderr,"01020304h = %08lxh\n",translatelong(0x01020304));
exit(3); exit(3);
} }
f->fp = fp; f->fp = fp;
initpos = ftell(fp); initpos = ftell(fp);
fread(buf,6,1,f->fp); /* read header */ fread(buf,6,1,f->fp); /* read header */
buf[6] = 0; buf[6] = 0;
if (strcmp(buf,RDOFFId)) { if (strcmp(buf,RDOFFId)) {
fclose(f->fp); fclose(f->fp);
if (!strcmp(buf,"RDOFF1")) if (!strcmp(buf,"RDOFF1"))
return rdf_errno = 7; /* error 7: RDOFF 1 not supported */ return rdf_errno = RDF_ERR_VER;
return rdf_errno = 2; /* error 2: invalid file format */ return rdf_errno = RDF_ERR_FORMAT;
} }
if (fread(&l,1,4,f->fp) != 4 || if (fread(&l,1,4,f->fp) != 4 || fread(&f->header_len,1,4,f->fp) != 4) {
fread(&f->header_len,1,4,f->fp) != 4) { fclose(f->fp);
fclose(f->fp); return rdf_errno = RDF_ERR_READ;
return rdf_errno = 3; /* error 3: file read error */ }
}
f->header_ofs = ftell(f->fp); f->header_ofs = ftell(f->fp);
f->eof_offset = f->header_ofs + translatelong(l) - 4; f->eof_offset = f->header_ofs + translatelong(l) - 4;
if (fseek(f->fp,f->header_len,SEEK_CUR)) { if (fseek(f->fp,f->header_len,SEEK_CUR)) {
fclose(f->fp); fclose(f->fp);
return rdf_errno = 2; /* seek past end of file...? */ return rdf_errno = RDF_ERR_FORMAT; /* seek past end of file...? */
} }
if (fread(&s,1,2,f->fp) != 2) { if (fread(&s,1,2,f->fp) != 2) {
fclose(f->fp); fclose(f->fp);
return rdf_errno = 3; return rdf_errno = RDF_ERR_READ;
} }
f->nsegs = 0; f->nsegs = 0;
while (s != 0) while (s != 0) {
{ f->seg[f->nsegs].type = s;
f->seg[f->nsegs].type = s; if (fread(&f->seg[f->nsegs].number,1,2,f->fp) != 2 ||
if (fread(&f->seg[f->nsegs].number,1,2,f->fp) != 2 || fread(&f->seg[f->nsegs].reserved,1,2,f->fp) != 2 ||
fread(&f->seg[f->nsegs].reserved,1,2,f->fp) != 2 || fread(&f->seg[f->nsegs].length,1,4,f->fp) != 4) {
fread(&f->seg[f->nsegs].length,1,4,f->fp) != 4) fclose(f->fp);
{ return rdf_errno = RDF_ERR_READ;
fclose(f->fp); }
return rdf_errno = 3;
}
f->seg[f->nsegs].offset = ftell(f->fp); f->seg[f->nsegs].offset = ftell(f->fp);
if (fseek(f->fp,f->seg[f->nsegs].length,SEEK_CUR)) { if (fseek(f->fp,f->seg[f->nsegs].length,SEEK_CUR)) {
fclose(f->fp); fclose(f->fp);
return rdf_errno = 2; return rdf_errno = RDF_ERR_FORMAT;
} }
f->nsegs++; f->nsegs++;
if (fread(&s,1,2,f->fp) != 2) { if (fread(&s,1,2,f->fp) != 2) {
fclose(f->fp); fclose(f->fp);
return rdf_errno = 3; return rdf_errno = RDF_ERR_READ;
} }
} }
if (f->eof_offset != ftell(f->fp) + 8) /* +8 = skip null segment header */ if (f->eof_offset != ftell(f->fp) + 8) { /* +8 = skip null segment header */
{ fprintf(stderr, "warning: eof_offset [%ld] and actual eof offset "
fprintf(stderr, "warning: eof_offset [%ld] and actual eof offset "
"[%ld] don't match\n", f->eof_offset, ftell(f->fp) + 8); "[%ld] don't match\n", f->eof_offset, ftell(f->fp) + 8);
} }
fseek(f->fp,initpos,SEEK_SET); fseek(f->fp,initpos,SEEK_SET);
f->header_loc = NULL; f->header_loc = NULL;
f->name = newstr(name); f->name = newstr(name);
f->refcount = refcount; f->refcount = refcount;
if (refcount) (*refcount)++; if (refcount) (*refcount)++;
return 0; return RDF_OK;
} }
int rdfclose(rdffile *f) int rdfclose(rdffile *f)
{ {
if (! f->refcount || ! --(*f->refcount)) if (! f->refcount || ! --(*f->refcount)) {
{ fclose(f->fp);
fclose(f->fp); f->fp = NULL;
f->fp = NULL; }
}
free(f->name); free(f->name);
return 0; return 0;
} }
void rdfperror(const char *app,const char *name) /*
* Print the message for last error (from rdf_errno)
*/
void rdfperror(const char *app, const char *name)
{ {
fprintf(stderr,"%s:%s: %s\n",app,name,rdf_errors[rdf_errno]); fprintf(stderr,"%s:%s: %s\n",app,name,rdf_errors[rdf_errno]);
if (rdf_errno == 1 || rdf_errno == 3) if (rdf_errno == RDF_ERR_OPEN || rdf_errno == RDF_ERR_READ) {
{ perror(app);
perror(app); }
}
} }
/*
* Find the segment by its number.
* Returns segment array index, or -1 if segment with such number was not found.
*/
int rdffindsegment(rdffile * f, int segno) int rdffindsegment(rdffile * f, int segno)
{ {
int i; int i;
@ -299,36 +336,37 @@ int rdffindsegment(rdffile * f, int segno)
return -1; return -1;
} }
/*
* Load the segment. Returns status.
*/
int rdfloadseg(rdffile *f,int segment,void *buffer) int rdfloadseg(rdffile *f,int segment,void *buffer)
{ {
long fpos; long fpos, slen;
long slen;
switch(segment) { switch(segment) {
case RDOFF_HEADER: case RDOFF_HEADER:
fpos = f->header_ofs; fpos = f->header_ofs;
slen = f->header_len; slen = f->header_len;
f->header_loc = (byte *)buffer; f->header_loc = (byte *)buffer;
f->header_fp = 0; f->header_fp = 0;
break; break;
default: default:
if (segment < f->nsegs) { if (segment < f->nsegs) {
fpos = f->seg[segment].offset; fpos = f->seg[segment].offset;
slen = f->seg[segment].length; slen = f->seg[segment].length;
f->seg[segment].data = (byte *)buffer; f->seg[segment].data = (byte *)buffer;
} } else {
else { return rdf_errno = RDF_ERR_SEGMENT;
return rdf_errno = 10; /* no such segment */ }
} }
}
if (fseek(f->fp,fpos,SEEK_SET)) if (fseek(f->fp,fpos,SEEK_SET))
return rdf_errno = 4; return rdf_errno = RDF_ERR_UNKNOWN;
if (fread(buffer,1,slen,f->fp) != slen) if (fread(buffer,1,slen,f->fp) != slen)
return rdf_errno = 3; return rdf_errno = RDF_ERR_READ;
return 0; return RDF_OK;
} }
/* Macros for reading integers from header in memory */ /* Macros for reading integers from header in memory */
@ -347,86 +385,93 @@ int rdfloadseg(rdffile *f,int segment,void *buffer)
#define RS(str,max) { for(i=0;i<max;i++){\ #define RS(str,max) { for(i=0;i<max;i++){\
RI8(str[i]); if (!str[i]) break;} str[i]=0; } RI8(str[i]); if (!str[i]) break;} str[i]=0; }
/*
* Read a header record.
* Returns the address of record, or NULL in case of error.
*/
rdfheaderrec *rdfgetheaderrec(rdffile *f) rdfheaderrec *rdfgetheaderrec(rdffile *f)
{ {
static rdfheaderrec r; static rdfheaderrec r;
int i; int i;
if (!f->header_loc) { if (!f->header_loc) {
rdf_errno = 5; rdf_errno = RDF_ERR_HEADER;
return NULL; return NULL;
} }
if (f->header_fp >= f->header_len) return 0; if (f->header_fp >= f->header_len) return 0;
RI8(r.type); RI8(r.type);
RI8(r.g.reclen); RI8(r.g.reclen);
switch(r.type) { switch(r.type) {
case RDFREC_RELOC: /* Relocation record */ case RDFREC_RELOC: /* Relocation record */
case RDFREC_SEGRELOC: case RDFREC_SEGRELOC:
if (r.r.reclen != 8) { if (r.r.reclen != 8) {
rdf_errno = 9; rdf_errno = RDF_ERR_RECLEN;
return NULL; return NULL;
} }
RI8(r.r.segment); RI8(r.r.segment);
RI32(r.r.offset); RI32(r.r.offset);
RI8(r.r.length); RI8(r.r.length);
RI16(r.r.refseg); RI16(r.r.refseg);
break; break;
case RDFREC_IMPORT: /* Imported symbol record */ case RDFREC_IMPORT: /* Imported symbol record */
case RDFREC_FARIMPORT: case RDFREC_FARIMPORT:
RI8(r.i.flags); RI8(r.i.flags);
RI16(r.i.segment); RI16(r.i.segment);
RS(r.i.label,32); RS(r.i.label, EXIM_LABEL_MAX);
break; break;
case RDFREC_GLOBAL: /* Exported symbol record */ case RDFREC_GLOBAL: /* Exported symbol record */
RI8(r.e.flags); RI8(r.e.flags);
RI8(r.e.segment); RI8(r.e.segment);
RI32(r.e.offset); RI32(r.e.offset);
RS(r.e.label,32); RS(r.e.label, EXIM_LABEL_MAX);
break; break;
case RDFREC_DLL: /* DLL record */ case RDFREC_DLL: /* DLL record */
RS(r.d.libname,127); RS(r.d.libname, MODLIB_NAME_MAX);
break; break;
case RDFREC_BSS: /* BSS reservation record */ case RDFREC_BSS: /* BSS reservation record */
if (r.r.reclen != 4) { if (r.r.reclen != 4) {
rdf_errno = 9; rdf_errno = RDF_ERR_RECLEN;
return NULL; return NULL;
} }
RI32(r.b.amount); RI32(r.b.amount);
break; break;
case RDFREC_MODNAME: /* Module name record */ case RDFREC_MODNAME: /* Module name record */
RS(r.m.modname,127); RS(r.m.modname, MODLIB_NAME_MAX);
break; break;
case RDFREC_COMMON: /* Common variable */ case RDFREC_COMMON: /* Common variable */
RI16(r.c.segment); RI16(r.c.segment);
RI32(r.c.size); RI32(r.c.size);
RI16(r.c.align); RI16(r.c.align);
RS(r.c.label,32); RS(r.c.label, EXIM_LABEL_MAX);
break; break;
default: default:
#ifdef STRICT_ERRORS #ifdef STRICT_ERRORS
rdf_errno = 8; /* unknown header record */ rdf_errno = RDF_ERR_RECTYPE; /* unknown header record */
return NULL; return NULL;
#else #else
for (i = 0; i < r.g.reclen; i++) for (i = 0; i < r.g.reclen; i++)
RI8(r.g.data[i]); RI8(r.g.data[i]);
#endif #endif
} }
return &r; return &r;
} }
/*
* Rewind to the beginning of the file
*/
void rdfheaderrewind(rdffile *f) void rdfheaderrewind(rdffile *f)
{ {
f->header_fp = 0; f->header_fp = 0;
} }
@ -450,8 +495,7 @@ int rdfaddheader(rdf_headerbuf * h, rdfheaderrec * r)
membufwrite(h->buf,&r->type,1); membufwrite(h->buf,&r->type,1);
membufwrite(h->buf,&r->g.reclen,1); membufwrite(h->buf,&r->g.reclen,1);
switch (r->type) switch (r->type) {
{
case RDFREC_GENERIC: /* generic */ case RDFREC_GENERIC: /* generic */
membufwrite(h->buf, &r->g.data, r->g.reclen); membufwrite(h->buf, &r->g.data, r->g.reclen);
break; break;
@ -491,7 +535,7 @@ int rdfaddheader(rdf_headerbuf * h, rdfheaderrec * r)
default: default:
#ifdef STRICT_ERRORS #ifdef STRICT_ERRORS
return (rdf_errno = 8); return rdf_errno = RDF_ERR_RECTYPE;
#else #else
for (i = 0; i < r->g.reclen; i++) for (i = 0; i < r->g.reclen; i++)
membufwrite(h->buf, r->g.data[i], 1); membufwrite(h->buf, r->g.data[i], 1);
@ -530,4 +574,3 @@ void rdfdoneheader(rdf_headerbuf * h)
freemembuf(h->buf); freemembuf(h->buf);
free(h); free(h);
} }

View file

@ -1,4 +1,5 @@
/* rdoff.h RDOFF Object File manipulation routines header file /*
* rdoff.h RDOFF Object File manipulation routines header file
* *
* The Netwide Assembler is copyright (C) 1996 Simon Tatham and * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
* Julian Hall. All rights reserved. The software is * Julian Hall. All rights reserved. The software is
@ -11,17 +12,37 @@
*/ */
#ifndef _RDOFF_H #ifndef _RDOFF_H
#define _RDOFF_H "RDOFF2 support routines v0.3" #define _RDOFF_H
/* Some systems don't define this automatically */ /*
extern char *strdup(const char *); * RDOFF definitions. They are used by RDOFF utilities and by NASM's
* 'outrdf2.c' output module.
*/
typedef unsigned short int16; /* Type definitions */
typedef unsigned long uint32;
typedef unsigned short uint16;
typedef unsigned char byte; typedef unsigned char byte;
typedef unsigned int bool;
#define RDF_MAXSEGS 64 /* RDOFF format revision (currently used only when printing the version) */
#define RDOFF2_REVISION "0.6.1"
/* the records that can be found in the RDOFF header */ /* RDOFF2 file signature */
#define RDOFF2_SIGNATURE "RDOFF2"
/* Maximum size of an import/export label (including trailing zero) */
#define EXIM_LABEL_MAX 64
/* Maximum size of library or module name (including trailing zero) */
#define MODLIB_NAME_MAX 128
/* Maximum number of segments that we can handle in one file */
#define RDF_MAXSEGS 64
/* Record types that may present the RDOFF header */
#define RDFREC_GENERIC 0
#define RDFREC_RELOC 1 #define RDFREC_RELOC 1
#define RDFREC_IMPORT 2 #define RDFREC_IMPORT 2
#define RDFREC_GLOBAL 3 #define RDFREC_GLOBAL 3
@ -31,8 +52,21 @@ typedef unsigned char byte;
#define RDFREC_FARIMPORT 7 #define RDFREC_FARIMPORT 7
#define RDFREC_MODNAME 8 #define RDFREC_MODNAME 8
#define RDFREC_COMMON 10 #define RDFREC_COMMON 10
#define RDFREC_GENERIC 0
/*
* Generic record - contains the type and length field, plus a 128 byte
* char array 'data'
*/
struct GenericRec {
byte type;
byte reclen;
char data[128];
};
/*
* Relocation record
*/
struct RelocRec { struct RelocRec {
byte type; /* must be 1 */ byte type; /* must be 1 */
byte reclen; /* content length */ byte reclen; /* content length */
@ -41,55 +75,73 @@ struct RelocRec {
reloc @ loadtime, only linkage) */ reloc @ loadtime, only linkage) */
long offset; /* from start of segment in which reference is loc'd */ long offset; /* from start of segment in which reference is loc'd */
byte length; /* 1 2 or 4 bytes */ byte length; /* 1 2 or 4 bytes */
int16 refseg; /* segment to which reference refers to */ uint16 refseg; /* segment to which reference refers to */
}; };
/*
* Extern/import record
*/
struct ImportRec { struct ImportRec {
byte type; /* must be 2 */ byte type; /* must be 2 */
byte reclen; /* content length */ byte reclen; /* content length */
byte flags; /* SYM_* flags (see below) */ byte flags; /* SYM_* flags (see below) */
int16 segment; /* segment number allocated to the label for reloc uint16 segment; /* segment number allocated to the label for reloc
records - label is assumed to be at offset zero records - label is assumed to be at offset zero
in this segment, so linker must fix up with offset in this segment, so linker must fix up with offset
of segment and of offset within segment */ of segment and of offset within segment */
char label[33]; /* zero terminated... should be written to file until char label[EXIM_LABEL_MAX]; /* zero terminated, should be written to file
the zero, but not after it - max len = 32 chars */ until the zero, but not after it */
}; };
/*
* Public/export record
*/
struct ExportRec { struct ExportRec {
byte type; /* must be 3 */ byte type; /* must be 3 */
byte reclen; /* content length */ byte reclen; /* content length */
byte flags; /* SYM_* flags (see below) */ byte flags; /* SYM_* flags (see below) */
byte segment; /* segment referred to (0/1/2) */ byte segment; /* segment referred to (0/1/2) */
long offset; /* offset within segment */ long offset; /* offset within segment */
char label[33]; /* zero terminated as above. max len = 32 chars */ char label[EXIM_LABEL_MAX]; /* zero terminated as in import */
}; };
/*
* DLL record
*/
struct DLLRec { struct DLLRec {
byte type; /* must be 4 */ byte type; /* must be 4 */
byte reclen; /* content length */ byte reclen; /* content length */
char libname[128]; /* name of library to link with at load time */ char libname[MODLIB_NAME_MAX]; /* name of library to link with at load time */
}; };
/*
* BSS record
*/
struct BSSRec { struct BSSRec {
byte type; /* must be 5 */ byte type; /* must be 5 */
byte reclen; /* content length */ byte reclen; /* content length */
long amount; /* number of bytes BSS to reserve */ long amount; /* number of bytes BSS to reserve */
}; };
/*
* Module name record
*/
struct ModRec { struct ModRec {
byte type; /* must be 8 */ byte type; /* must be 8 */
byte reclen; /* content length */ byte reclen; /* content length */
char modname[128]; /* module name */ char modname[MODLIB_NAME_MAX]; /* module name */
}; };
/*
* Common variable record
*/
struct CommonRec { struct CommonRec {
byte type; /* must be 10 */ byte type; /* must be 10 */
byte reclen; /* equals 7+label length */ byte reclen; /* equals 7+label length */
int16 segment; /* segment number */ uint16 segment; /* segment number */
long size; /* size of common variable */ long size; /* size of common variable */
int16 align; /* alignment (power of two) */ uint16 align; /* alignment (power of two) */
char label[33]; /* zero terminated as above. max len = 32 chars */ char label[EXIM_LABEL_MAX]; /* zero terminated as in import */
}; };
/* Flags for ExportRec */ /* Flags for ExportRec */
@ -98,15 +150,13 @@ struct CommonRec {
#define SYM_GLOBAL 4 #define SYM_GLOBAL 4
#define SYM_IMPORT 8 #define SYM_IMPORT 8
/*
* GenericRec - contains the type and length field, plus a 128 byte /*** The following part is used only by the utilities *************************/
* char array 'data'
*/ #ifdef RDOFF_UTILS
struct GenericRec {
byte type; /* Some systems don't define this automatically */
byte reclen; extern char *strdup(const char *);
char data[128];
};
typedef union RDFHeaderRec { typedef union RDFHeaderRec {
char type; /* invariant throughout all below */ char type; /* invariant throughout all below */
@ -122,9 +172,9 @@ typedef union RDFHeaderRec {
struct SegmentHeaderRec { struct SegmentHeaderRec {
/* information from file */ /* information from file */
int16 type; uint16 type;
int16 number; uint16 number;
int16 reserved; uint16 reserved;
long length; long length;
/* information built up here */ /* information built up here */
@ -133,30 +183,30 @@ struct SegmentHeaderRec {
}; };
typedef struct RDFFileInfo { typedef struct RDFFileInfo {
FILE *fp; /* file descriptor; must be open to use this struct */ FILE *fp; /* file descriptor; must be open to use this struct */
int rdoff_ver; /* should be 1; any higher => not guaranteed to work */ int rdoff_ver; /* should be 1; any higher => not guaranteed to work */
long header_len; long header_len;
long header_ofs; long header_ofs;
byte *header_loc; /* keep location of header */ byte *header_loc; /* keep location of header */
long header_fp; /* current location within header for reading */ long header_fp; /* current location within header for reading */
struct SegmentHeaderRec seg[RDF_MAXSEGS]; struct SegmentHeaderRec seg[RDF_MAXSEGS];
int nsegs; int nsegs;
long eof_offset; /* offset of the first byte beyond the end of this long eof_offset; /* offset of the first byte beyond the end of this
module */ module */
char *name; /* name of module in libraries */ char *name; /* name of module in libraries */
int *refcount; /* pointer to reference count on file, or NULL */ int *refcount; /* pointer to reference count on file, or NULL */
} rdffile; } rdffile;
#define BUF_BLOCK_LEN 4088 /* selected to match page size (4096) #define BUF_BLOCK_LEN 4088 /* selected to match page size (4096)
* on 80x86 machines for efficiency */ * on 80x86 machines for efficiency */
typedef struct memorybuffer { typedef struct memorybuffer {
int length; int length;
byte buffer[BUF_BLOCK_LEN]; byte buffer[BUF_BLOCK_LEN];
struct memorybuffer *next; struct memorybuffer *next;
} memorybuffer; } memorybuffer;
typedef struct { typedef struct {
@ -166,9 +216,9 @@ typedef struct {
} rdf_headerbuf; } rdf_headerbuf;
/* segments used by RDOFF, understood by rdoffloadseg */ /* segments used by RDOFF, understood by rdoffloadseg */
#define RDOFF_CODE 0 #define RDOFF_CODE 0
#define RDOFF_DATA 1 #define RDOFF_DATA 1
#define RDOFF_HEADER -1 #define RDOFF_HEADER -1
/* mask for 'segment' in relocation records to find if relative relocation */ /* mask for 'segment' in relocation records to find if relative relocation */
#define RDOFF_RELATIVEMASK 64 #define RDOFF_RELATIVEMASK 64
/* mask to find actual segment value in relocation records */ /* mask to find actual segment value in relocation records */
@ -176,9 +226,25 @@ typedef struct {
extern int rdf_errno; extern int rdf_errno;
/* rdf_errno can hold these error codes */
enum {
/* 0 */ RDF_OK,
/* 1 */ RDF_ERR_OPEN,
/* 2 */ RDF_ERR_FORMAT,
/* 3 */ RDF_ERR_READ,
/* 4 */ RDF_ERR_UNKNOWN,
/* 5 */ RDF_ERR_HEADER,
/* 6 */ RDF_ERR_NOMEM,
/* 7 */ RDF_ERR_VER,
/* 8 */ RDF_ERR_RECTYPE,
/* 9 */ RDF_ERR_RECLEN,
/* 10 */ RDF_ERR_SEGMENT
};
/* utility functions */ /* utility functions */
int16 translateshort(int16 in);
long translatelong(long in); long translatelong(long in);
uint16 translateshort(uint16 in);
char *translatesegmenttype(uint16 type);
/* RDOFF file manipulation functions */ /* RDOFF file manipulation functions */
int rdfopen(rdffile *f,const char *name); int rdfopen(rdffile *f,const char *name);
@ -203,4 +269,6 @@ int rdfaddsegment(rdf_headerbuf *h, long seglength);
int rdfwriteheader(FILE *fp,rdf_headerbuf *h); int rdfwriteheader(FILE *fp,rdf_headerbuf *h);
void rdfdoneheader(rdf_headerbuf *h); void rdfdoneheader(rdf_headerbuf *h);
#endif /* RDOFF_UTILS */
#endif /* _RDOFF_H */ #endif /* _RDOFF_H */

View file

@ -16,7 +16,6 @@
#include <stdlib.h> #include <stdlib.h>
#include "rdfload.h" #include "rdfload.h"
#include "rdoff.h"
#include "symtab.h" #include "symtab.h"
typedef int (*main_fn) (int,char**); /* Main function prototype */ typedef int (*main_fn) (int,char**); /* Main function prototype */
@ -27,16 +26,14 @@ int main(int argc, char **argv)
main_fn code; main_fn code;
symtabEnt * s; symtabEnt * s;
if (argc < 2) if (argc < 2) {
{
puts("usage: rdx <rdoff-executable> [params]\n"); puts("usage: rdx <rdoff-executable> [params]\n");
exit(255); exit(255);
} }
m = rdfload(argv[1]); m = rdfload(argv[1]);
if (! m) if (! m) {
{
rdfperror("rdx",argv[1]); rdfperror("rdx",argv[1]);
exit(255); exit(255);
} }
@ -46,8 +43,7 @@ int main(int argc, char **argv)
in other cases... */ in other cases... */
s = symtabFind(m->symtab, "_main"); s = symtabFind(m->symtab, "_main");
if (! s) if (! s) {
{
fprintf(stderr,"rdx: could not find symbol '_main' in '%s'\n",argv[1]); fprintf(stderr,"rdx: could not find symbol '_main' in '%s'\n",argv[1]);
exit(255); exit(255);
} }
@ -58,4 +54,3 @@ int main(int argc, char **argv)
return code(argc,argv); /* execute */ return code(argc,argv); /* execute */
} }

View file

@ -4,4 +4,3 @@ void init_seglocations(segtab * r);
void add_seglocation(segtab * r, int localseg, int destseg, long offset); void add_seglocation(segtab * r, int localseg, int destseg, long offset);
int get_seglocation(segtab * r, int localseg, int * destseg, long * offset); int get_seglocation(segtab * r, int localseg, int * destseg, long * offset);
void done_seglocations(segtab * r); void done_seglocations(segtab * r);