summaryrefslogtreecommitdiff
path: root/rdoff
diff options
context:
space:
mode:
authorAnas Nashif <anas.nashif@intel.com>2012-05-15 22:27:48 +0100
committerAnas Nashif <anas.nashif@intel.com>2012-05-15 22:27:48 +0100
commitb9fad1ab2ad3bd87bff05c4688c978d582ada438 (patch)
tree4a373f8dd867d20e67510de7cfe447a4b58c1a70 /rdoff
parent65c26d26fb72cec0d43d199c72ed27513d17f4c9 (diff)
downloadnasm-b9fad1ab2ad3bd87bff05c4688c978d582ada438.tar.gz
nasm-b9fad1ab2ad3bd87bff05c4688c978d582ada438.tar.bz2
nasm-b9fad1ab2ad3bd87bff05c4688c978d582ada438.zip
Upstream version 2.08rc7
Diffstat (limited to 'rdoff')
-rw-r--r--rdoff/Makefile.in105
-rw-r--r--rdoff/Mkfiles/Makefile.dj75
-rw-r--r--rdoff/Mkfiles/Makefile.emx76
-rw-r--r--rdoff/Mkfiles/Makefile.sc56
-rw-r--r--rdoff/Mkfiles/Makefile.unx75
-rw-r--r--rdoff/Mkfiles/README4
-rw-r--r--rdoff/README185
-rw-r--r--rdoff/collectn.c45
-rw-r--r--rdoff/collectn.h22
-rw-r--r--rdoff/doc/Makefile37
-rw-r--r--rdoff/doc/rdoff.texi137
-rw-r--r--rdoff/doc/v1-v2.txt62
-rw-r--r--rdoff/hash.c122
-rw-r--r--rdoff/hash.h18
-rw-r--r--rdoff/ldrdf.141
-rw-r--r--rdoff/ldrdf.c1360
-rw-r--r--rdoff/ldsegs.h60
-rw-r--r--rdoff/rdf2bin.165
-rw-r--r--rdoff/rdf2bin.c430
-rw-r--r--rdoff/rdf2com.11
-rw-r--r--rdoff/rdf2ihx.11
-rw-r--r--rdoff/rdf2ith.11
-rw-r--r--rdoff/rdf2srec.11
-rw-r--r--rdoff/rdfdump.124
-rw-r--r--rdoff/rdfdump.c347
-rw-r--r--rdoff/rdflib.139
-rw-r--r--rdoff/rdflib.c428
-rw-r--r--rdoff/rdfload.c212
-rw-r--r--rdoff/rdfload.h31
-rw-r--r--rdoff/rdlar.c490
-rw-r--r--rdoff/rdlar.h38
-rw-r--r--rdoff/rdlib.c296
-rw-r--r--rdoff/rdlib.h62
-rw-r--r--rdoff/rdoff.c611
-rw-r--r--rdoff/rdoff.h293
-rw-r--r--rdoff/rdx.121
-rw-r--r--rdoff/rdx.c88
-rw-r--r--rdoff/segtab.c175
-rw-r--r--rdoff/segtab.h46
-rw-r--r--rdoff/symtab.c159
-rw-r--r--rdoff/symtab.h56
-rw-r--r--rdoff/test/Makefile10
-rw-r--r--rdoff/test/makelib.sh14
-rw-r--r--rdoff/test/rdfseg.asm20
-rw-r--r--rdoff/test/rdfseg2.asm12
-rw-r--r--rdoff/test/rdftest1.asm54
-rw-r--r--rdoff/test/rdftest2.asm33
-rw-r--r--rdoff/test/rdtlib.asm48
-rw-r--r--rdoff/test/rdtmain.asm47
-rw-r--r--rdoff/test/testlib.asm18
50 files changed, 6651 insertions, 0 deletions
diff --git a/rdoff/Makefile.in b/rdoff/Makefile.in
new file mode 100644
index 0000000..93f2e2a
--- /dev/null
+++ b/rdoff/Makefile.in
@@ -0,0 +1,105 @@
+#
+# Auto-configuring Makefile for RDOFF object file utils; part of the
+# Netwide Assembler
+#
+# The Netwide Assembler is copyright (C) 1996 Simon Tatham and
+# Julian Hall. All rights reserved. The software is
+# redistributable under the license given in the file "LICENSE"
+# distributed in the NASM archive.
+
+top_srcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+bindir = @bindir@
+mandir = @mandir@
+datarootdir = @datarootdir@
+
+CC = @CC@
+CFLAGS = @CFLAGS@
+BUILD_CFLAGS = $(CFLAGS) @DEFS@
+INTERNAL_CFLAGS = -I$(srcdir) -I$(top_srcdir)
+ALL_CFLAGS = $(BUILD_CFLAGS) $(INTERNAL_CFLAGS)
+LDFLAGS = @LDFLAGS@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+LN_S = @LN_S@
+MKDIR = mkdir
+
+LDRDFLIBS = rdoff.o nasmlib.o symtab.o collectn.o rdlib.o segtab.o hash.o
+RDXLIBS = rdoff.o rdfload.o symtab.o collectn.o hash.o
+
+# Binary suffixes
+O = @OBJEXT@
+X = @EXEEXT@
+
+PROGRAMS = rdfdump$(X) ldrdf$(X) rdx$(X) rdflib$(X) \
+ rdf2bin$(X) rdf2com$(X) rdf2ith$(X) rdf2ihx$(X) rdf2srec$(X)
+
+.SUFFIXES: .c .i .s .$(O) .1 .man
+
+.c.$(O):
+ $(CC) -c $(ALL_CFLAGS) $<
+
+all: $(PROGRAMS)
+
+rdfdump$(X): rdfdump.$(O) rdoff.$(O)
+ $(CC) $(LDFLAGS) -o rdfdump$(X) rdfdump.$(O) rdoff.$(O)
+ldrdf$(X): ldrdf.$(O) $(LDRDFLIBS)
+ $(CC) $(LDFLAGS) -o ldrdf$(X) ldrdf.$(O) $(LDRDFLIBS)
+rdx$(X): rdx.$(O) $(RDXLIBS)
+ $(CC) $(LDFLAGS) -o rdx$(X) rdx.$(O) $(RDXLIBS)
+rdflib$(X): rdflib.$(O)
+ $(CC) $(LDFLAGS) -o rdflib$(X) rdflib.$(O)
+rdf2bin$(X): rdf2bin.$(O) $(RDXLIBS) nasmlib.$(O)
+ $(CC) $(LDFLAGS) -o rdf2bin$(X) rdf2bin.$(O) $(RDXLIBS) nasmlib.$(O)
+rdf2com$(X):
+ rm -f rdf2com$(X) && $(LN_S) rdf2bin$(X) rdf2com$(X)
+rdf2ith$(X):
+ rm -f rdf2ith$(X) && $(LN_S) rdf2bin$(X) rdf2ith$(X)
+rdf2ihx$(X):
+ rm -f rdf2ihx$(X) && $(LN_S) rdf2bin$(X) rdf2ihx$(X)
+rdf2srec$(X):
+ rm -f rdf2srec$(X) && $(LN_S) rdf2bin$(X) rdf2srec$(X)
+
+rdf2ihx.$(O): rdf2ihx.c
+rdf2bin.$(O): rdf2bin.c
+rdfdump.$(O): rdfdump.c
+rdoff.$(O): rdoff.c rdoff.h
+ldrdf.$(O): ldrdf.c rdoff.h ../nasmlib.h symtab.h collectn.h rdlib.h
+symtab.$(O): symtab.c symtab.h
+collectn.$(O): collectn.c collectn.h
+rdx.$(O): rdx.c rdoff.h rdfload.h symtab.h
+rdfload.$(O): rdfload.c rdfload.h rdoff.h collectn.h symtab.h
+rdlib.$(O): rdlib.c rdlib.h
+rdflib.$(O): rdflib.c
+segtab.$(O): segtab.c
+
+nasmlib.$(O): $(top_srcdir)/nasmlib.c
+ cd .. && $(MAKE) nasmlib.$(O)
+ cp ../nasmlib.$(O) .
+
+clean:
+ rm -f *.$(O) $(PROGRAMS)
+
+spotless: clean
+ rm -f Makefile
+
+distclean: spotless
+
+install: all
+ $(MKDIR) -p $(INSTALLROOT)$(bindir)
+ $(INSTALL_PROGRAM) rdfdump$(X) $(INSTALLROOT)$(bindir)/rdfdump$(X)
+ $(INSTALL_PROGRAM) ldrdf$(X) $(INSTALLROOT)$(bindir)/ldrdf$(X)
+ $(INSTALL_PROGRAM) rdx$(X) $(INSTALLROOT)$(bindir)/rdx$(X)
+ $(INSTALL_PROGRAM) rdflib$(X) $(INSTALLROOT)$(bindir)/rdflib$(X)
+ $(INSTALL_PROGRAM) rdf2bin$(X) $(INSTALLROOT)$(bindir)/rdf2bin$(X)
+ cd $(INSTALLROOT)$(bindir) && rm -f rdf2com$(X) && $(LN_S) rdf2bin$(X) rdf2com$(X)
+ cd $(INSTALLROOT)$(bindir) && rm -f rdf2ith$(X) && $(LN_S) rdf2bin$(X) rdf2ith$(X)
+ cd $(INSTALLROOT)$(bindir) && rm -f rdf2ihx$(X) && $(LN_S) rdf2bin$(X) rdf2ihx$(X)
+ cd $(INSTALLROOT)$(bindir) && rm -f rdf2srec$(X) && $(LN_S) rdf2bin$(X) rdf2srec$(X)
+ $(MKDIR) -p $(INSTALLROOT)$(mandir)/man1
+ $(INSTALL_DATA) $(srcdir)/*.1 $(INSTALLROOT)$(mandir)/man1/
diff --git a/rdoff/Mkfiles/Makefile.dj b/rdoff/Mkfiles/Makefile.dj
new file mode 100644
index 0000000..5621ed6
--- /dev/null
+++ b/rdoff/Mkfiles/Makefile.dj
@@ -0,0 +1,75 @@
+# Generated automatically from Makefile.in by configure.
+#
+# Auto-configuring Makefile for RDOFF object file utils; part of the
+# Netwide Assembler
+#
+# The Netwide Assembler is copyright (C) 1996 Simon Tatham and
+# Julian Hall. All rights reserved. The software is
+# redistributable under the license given in the file "LICENSE"
+# distributed in the NASM archive.
+
+# You may need to adjust these values.
+
+prefix = /djgpp
+CC = gcc -s
+CFLAGS = -O2 -I..
+
+# You _shouldn't_ need to adjust anything below this line.
+
+exec_prefix = ${prefix}
+bindir = ${exec_prefix}/bin
+mandir = ${prefix}/man
+
+INSTALL = /usr/bin/install -c
+INSTALL_PROGRAM = ${INSTALL}
+INSTALL_DATA = ${INSTALL} -m 644
+LN_S = ln -s
+
+LDRDFLIBS = rdoff.o ../nasmlib.o symtab.o hash.o collectn.o rdlib.o segtab.o
+RDXLIBS = rdoff.o rdfload.o symtab.o hash.o collectn.o
+
+.c.o:
+ $(CC) -c $(CFLAGS) $*.c
+
+all: rdfdump ldrdf rdx rdflib rdf2bin rdf2com
+
+rdfdump: rdfdump.o rdoff.o
+ $(CC) -o rdfdump rdfdump.o rdoff.o
+
+ldrdf: ldrdf.o $(LDRDFLIBS)
+ $(CC) -o ldrdf ldrdf.o $(LDRDFLIBS)
+rdx: rdx.o $(RDXLIBS)
+ $(CC) -o rdx rdx.o $(RDXLIBS)
+rdflib: rdflib.o
+ $(CC) -o rdflib rdflib.o
+rdf2bin: rdf2bin.o $(RDXLIBS) nasmlib.o
+ $(CC) -o rdf2bin rdf2bin.o $(RDXLIBS) nasmlib.o
+rdf2com:
+ $(LN_S) rdf2bin rdf2com
+
+rdf2bin.o: rdf2bin.c
+rdfdump.o: rdfdump.c
+rdoff.o: rdoff.c rdoff.h
+ldrdf.o: ldrdf.c rdoff.h ../nasmlib.h symtab.h collectn.h rdlib.h
+symtab.o: symtab.c symtab.h hash.h
+collectn.o: collectn.c collectn.h
+rdx.o: rdx.c rdoff.h rdfload.h symtab.h
+rdfload.o: rdfload.c rdfload.h rdoff.h collectn.h symtab.h
+rdlib.o: rdlib.c rdlib.h
+rdflib.o: rdflib.c
+hash.o: hash.c hash.h
+segtab.o: segtab.c segtab.h
+
+nasmlib.o: ../nasmlib.c ../nasmlib.h ../names.c ../nasm.h
+ $(CC) -c $(CFLAGS) ../nasmlib.c
+
+clean:
+ rm -f *.o rdfdump ldrdf rdx rdflib rdf2bin rdf2com
+
+install: rdfdump ldrdf rdx rdflib rdf2bin rdf2com
+ $(INSTALL_PROGRAM) rdfdump $(bindir)/rdfdump
+ $(INSTALL_PROGRAM) ldrdf $(bindir)/ldrdf
+ $(INSTALL_PROGRAM) rdx $(bindir)/rdx
+ $(INSTALL_PROGRAM) rdflib $(bindir)/rdflib
+ $(INSTALL_PROGRAM) rdf2bin $(bindir)/rdf2bin
+ cd $(bindir); $(LN_S) rdf2bin rdf2com
diff --git a/rdoff/Mkfiles/Makefile.emx b/rdoff/Mkfiles/Makefile.emx
new file mode 100644
index 0000000..aa53588
--- /dev/null
+++ b/rdoff/Mkfiles/Makefile.emx
@@ -0,0 +1,76 @@
+# Generated automatically from Makefile.in by configure.
+# $Id$
+#
+# Auto-configuring Makefile for RDOFF object file utils; part of the
+# Netwide Assembler
+#
+# The Netwide Assembler is copyright (C) 1996 Simon Tatham and
+# Julian Hall. All rights reserved. The software is
+# redistributable under the license given in the file "LICENSE"
+# distributed in the NASM archive.
+
+top_srcdir = ..
+srcdir = .
+prefix = /usr/local
+exec_prefix = ${prefix}
+bindir = ${exec_prefix}/bin
+mandir = ${prefix}/man
+
+CC = gcc
+CFLAGS = -s -Zomf -O2 -fomit-frame-pointer -Wall -ansi -pedantic -I$(srcdir) -I$(top_srcdir)
+LDFLAGS = -s -Zomf -Zexe -Zcrtdll
+LIBS = -lgcc
+
+INSTALL = .././install-sh -c
+INSTALL_PROGRAM = ${INSTALL}
+INSTALL_DATA = ${INSTALL} -m 644
+
+LDRDFLIBS = rdoff.o nasmlib.o symtab.o collectn.o rdlib.o segtab.o hash.o
+RDXLIBS = rdoff.o rdfload.o symtab.o collectn.o hash.o
+
+.c.o:
+ $(CC) -c $(CFLAGS) -o $@ $<
+
+all: rdfdump ldrdf rdx rdflib rdf2bin
+
+rdfdump: rdfdump.o rdoff.o
+ $(CC) $(LDFLAGS) -o rdfdump rdfdump.o rdoff.o $(LIBS)
+ldrdf: ldrdf.o $(LDRDFLIBS)
+ $(CC) $(LDFLAGS) -o ldrdf ldrdf.o $(LDRDFLIBS) $(LIBS)
+rdx: rdx.o $(RDXLIBS)
+ $(CC) $(LDFLAGS) -o rdx rdx.o $(RDXLIBS) $(LIBS)
+rdflib: rdflib.o
+ $(CC) $(LDFLAGS) -o rdflib rdflib.o $(LIBS)
+rdf2bin: rdf2bin.o $(RDXLIBS) nasmlib.o
+ $(CC) $(LDFLAGS) -o rdf2bin rdf2bin.o $(RDXLIBS) nasmlib.o $(LIBS)
+
+rdf2bin.o: rdf2bin.c
+rdfdump.o: rdfdump.c
+rdoff.o: rdoff.c rdoff.h
+ldrdf.o: ldrdf.c rdoff.h $(top_srcdir)/nasmlib.h symtab.h collectn.h rdlib.h
+symtab.o: symtab.c symtab.h
+collectn.o: collectn.c collectn.h
+rdx.o: rdx.c rdoff.h rdfload.h symtab.h
+rdfload.o: rdfload.c rdfload.h rdoff.h collectn.h symtab.h
+rdlib.o: rdlib.c rdlib.h
+rdflib.o: rdflib.c
+segtab.o: segtab.c
+
+nasmlib.o: $(top_srcdir)/nasmlib.c
+ $(CC) -c $(CFLAGS) -o $@ $(top_srcdir)/nasmlib.c
+
+clean:
+ rm -f *.o rdfdump ldrdf rdx rdflib rdf2bin rdf2com
+
+spotless: clean
+ rm -f Makefile
+
+distclean: spotless
+
+install: rdfdump ldrdf rdx rdflib rdf2bin rdf2com
+ $(INSTALL_PROGRAM) rdfdump $(INSTALLROOT)$(bindir)/rdfdump
+ $(INSTALL_PROGRAM) ldrdf $(INSTALLROOT)$(bindir)/ldrdf
+ $(INSTALL_PROGRAM) rdx $(INSTALLROOT)$(bindir)/rdx
+ $(INSTALL_PROGRAM) rdflib $(INSTALLROOT)$(bindir)/rdflib
+ $(INSTALL_PROGRAM) rdf2bin $(INSTALLROOT)$(bindir)/rdf2bin
+ cd $(INSTALLROOT)$(bindir) && rm -f rdf2com && $(LN_S) rdf2bin rdf2com
diff --git a/rdoff/Mkfiles/Makefile.sc b/rdoff/Mkfiles/Makefile.sc
new file mode 100644
index 0000000..501d487
--- /dev/null
+++ b/rdoff/Mkfiles/Makefile.sc
@@ -0,0 +1,56 @@
+# Makefile for RDOFF object file utils; part of the Netwide Assembler
+#
+# The Netwide Assembler is copyright (C) 1996 Simon Tatham and
+# Julian Hall. All rights reserved. The software is
+# redistributable under the license given in the file "LICENSE"
+# distributed in the NASM archive.
+#
+# This Makefile is designed for use under Unix (probably fairly
+# portably).
+
+CC = sc
+CCFLAGS = -I..\ -c -a1 -mn -Nc -w2 -w7 -o+time -5
+LINK = link
+LINKFLAGS = /noi /exet:NT /su:console
+
+OBJ=obj
+EXE=.exe
+
+NASMLIB = ..\nasmlib.$(OBJ)
+NASMLIB_H = ..\nasmlib.h
+LDRDFLIBS = rdoff.$(OBJ) $(NASMLIB) symtab.$(OBJ) collectn.$(OBJ) rdlib.$(OBJ)
+RDXLIBS = rdoff.$(OBJ) rdfload.$(OBJ) symtab.$(OBJ) collectn.$(OBJ)
+
+.c.$(OBJ):
+ $(CC) $(CCFLAGS) $*.c
+
+all : rdfdump$(EXE) ldrdf$(EXE) rdx$(EXE) rdflib$(EXE) rdf2bin$(EXE) rdf2com$(EXE)
+
+rdfdump$(EXE) : rdfdump.$(OBJ)
+ $(LINK) $(LINKFLAGS) rdfdump.$(OBJ), rdfdump$(EXE);
+ldrdf$(EXE) : ldrdf.$(OBJ) $(LDRDFLIBS)
+ $(LINK) $(LINKFLAGS) ldrdf.$(OBJ) $(LDRDFLIBS), ldrdf$(EXE);
+rdx$(EXE) : rdx.$(OBJ) $(RDXLIBS)
+ $(LINK) $(LINKFLAGS) rdx.$(OBJ) $(RDXLIBS), rdx$(EXE);
+rdflib$(EXE) : rdflib.$(OBJ)
+ $(LINK) $(LINKFLAGS) rdflib.$(OBJ), rdflib$(EXE);
+rdf2bin$(EXE) : rdf2bin.$(OBJ) $(RDXLIBS) $(NASMLIB)
+ $(LINK) $(LINKFLAGS) rdf2bin.$(OBJ) $(RDXLIBS) $(NASMLIB), rdf2bin$(EXE);
+rdf2com$(EXE) : rdf2bin$(EXE)
+ copy rdf2bin$(EXE) rdf2com$(EXE)
+
+rdf2bin.$(OBJ) : rdf2bin.c
+rdfdump.$(OBJ) : rdfdump.c
+rdoff.$(OBJ) : rdoff.c rdoff.h
+ldrdf.$(OBJ) : ldrdf.c rdoff.h $(NASMLIB_H) symtab.h collectn.h rdlib.h
+symtab.$(OBJ) : symtab.c symtab.h
+collectn.$(OBJ) : collectn.c collectn.h
+rdx.$(OBJ) : rdx.c rdoff.h rdfload.h symtab.h
+rdfload.$(OBJ) : rdfload.c rdfload.h rdoff.h collectn.h symtab.h
+rdlib.$(OBJ) : rdlib.c rdlib.h
+rdflib.$(OBJ) : rdflib.c
+
+clean :
+ del *.$(OBJ) rdfdump$(EXE) ldrdf$(EXE) rdx$(EXE) rdflib$(EXE) rdf2bin$(EXE)
+
+
diff --git a/rdoff/Mkfiles/Makefile.unx b/rdoff/Mkfiles/Makefile.unx
new file mode 100644
index 0000000..9041b41
--- /dev/null
+++ b/rdoff/Mkfiles/Makefile.unx
@@ -0,0 +1,75 @@
+# Generated automatically from Makefile.in by configure.
+#
+# Auto-configuring Makefile for RDOFF object file utils; part of the
+# Netwide Assembler
+#
+# The Netwide Assembler is copyright (C) 1996 Simon Tatham and
+# Julian Hall. All rights reserved. The software is
+# redistributable under the license given in the file "LICENSE"
+# distributed in the NASM archive.
+
+# You may need to adjust these values.
+
+prefix = /usr/local
+CC = cc
+CFLAGS = -O -I..
+
+# You _shouldn't_ need to adjust anything below this line.
+
+exec_prefix = ${prefix}
+bindir = ${exec_prefix}/bin
+mandir = ${prefix}/man
+
+INSTALL = /usr/bin/install -c
+INSTALL_PROGRAM = ${INSTALL}
+INSTALL_DATA = ${INSTALL} -m 644
+LN_S = ln -s
+
+LDRDFLIBS = rdoff.o ../nasmlib.o symtab.o hash.o collectn.o rdlib.o segtab.o
+RDXLIBS = rdoff.o rdfload.o symtab.o hash.o collectn.o
+
+.c.o:
+ $(CC) -c $(CFLAGS) $*.c
+
+all: rdfdump ldrdf rdx rdflib rdf2bin rdf2com
+
+rdfdump: rdfdump.o rdoff.o
+ $(CC) -o rdfdump rdfdump.o rdoff.o
+
+ldrdf: ldrdf.o $(LDRDFLIBS)
+ $(CC) -o ldrdf ldrdf.o $(LDRDFLIBS)
+rdx: rdx.o $(RDXLIBS)
+ $(CC) -o rdx rdx.o $(RDXLIBS)
+rdflib: rdflib.o
+ $(CC) -o rdflib rdflib.o
+rdf2bin: rdf2bin.o $(RDXLIBS) nasmlib.o
+ $(CC) -o rdf2bin rdf2bin.o $(RDXLIBS) nasmlib.o
+rdf2com:
+ $(LN_S) rdf2bin rdf2com
+
+rdf2bin.o: rdf2bin.c
+rdfdump.o: rdfdump.c
+rdoff.o: rdoff.c rdoff.h
+ldrdf.o: ldrdf.c rdoff.h ../nasmlib.h symtab.h collectn.h rdlib.h
+symtab.o: symtab.c symtab.h hash.h
+collectn.o: collectn.c collectn.h
+rdx.o: rdx.c rdoff.h rdfload.h symtab.h
+rdfload.o: rdfload.c rdfload.h rdoff.h collectn.h symtab.h
+rdlib.o: rdlib.c rdlib.h
+rdflib.o: rdflib.c
+hash.o: hash.c hash.h
+segtab.o: segtab.c segtab.h
+
+nasmlib.o: ../nasmlib.c ../nasmlib.h ../names.c ../nasm.h
+ $(CC) -c $(CFLAGS) ../nasmlib.c
+
+clean:
+ rm -f *.o rdfdump ldrdf rdx rdflib rdf2bin rdf2com
+
+install: rdfdump ldrdf rdx rdflib rdf2bin rdf2com
+ $(INSTALL_PROGRAM) rdfdump $(bindir)/rdfdump
+ $(INSTALL_PROGRAM) ldrdf $(bindir)/ldrdf
+ $(INSTALL_PROGRAM) rdx $(bindir)/rdx
+ $(INSTALL_PROGRAM) rdflib $(bindir)/rdflib
+ $(INSTALL_PROGRAM) rdf2bin $(bindir)/rdf2bin
+ cd $(bindir); $(LN_S) rdf2bin rdf2com
diff --git a/rdoff/Mkfiles/README b/rdoff/Mkfiles/README
new file mode 100644
index 0000000..7e68499
--- /dev/null
+++ b/rdoff/Mkfiles/README
@@ -0,0 +1,4 @@
+These are pre-created Makefiles for various platforms, use them if
+GNU autoconf/automake packages are not supported on your system.
+
+Copy appropriate Makefile to ../Makefile and run make.
diff --git a/rdoff/README b/rdoff/README
new file mode 100644
index 0000000..a5a6fd1
--- /dev/null
+++ b/rdoff/README
@@ -0,0 +1,185 @@
+*******
+This file is getting obsolete. RDOFF documentation is written in Texinfo now.
+Directory doc/ contains Texinfo source (rdoff.texi) and makefile for creating
+different output formats (info, HTML, PostScript and PDF).
+*******
+
+RDOFF Utilities, version 0.3.2
+==============================
+
+The files contained in this directory are the C source code of a set
+of tools (and general purpose library files) for the manipulation of
+RDOFF version 2 object files. Note that these programs (with the
+exception of 'rdfdump') will NOT work with version 1 object files.
+Version 1 of RDOFF is no longer supported.
+
+There is also a 'doc' directory with 'v1-v2' file, which documents the
+differences between RDOFF 1 and 2, and an 'rdoff2.texi' (texinfo source),
+with complete documentation for the new format.
+
+Here is a brief summary of the programs' usage:
+
+
+rdfdump
+=======
+
+This tool prints a list of the header records in an RDOFF object in
+human-readable form, and optionally prints a hex dump of the contents
+of the segments.
+
+Usage:
+ rdfdump [-v] filename
+
+The -v flag specifies that the hex dump (see above) should be printed.
+
+Changes from previous versions:
+
+* rdfdump supports both version 1 and 2 of RDOFF.
+* rdfdump now gives warnings if the RDOFF2 format is violated (it
+ looks for incorrect lengths for header records, and checks the
+ overall length count at the start of the file)
+
+
+ldrdf
+=====
+
+This tool is a version of unix 'ld' (or DOS 'link') for use with RDOFF
+files. It is capable of linking RDOFF objects, and libraries produced
+with the 'rdlib' utility discussed below.
+
+In normal usage, its command line takes the form:
+
+ ldrdf [-o output-file] object files [-llibrary ...]
+
+Modules in libraries are not linked to the program unless they are
+referred to.
+
+Most of its options are not implemented, but those that are are listed here:
+
+ -2 redirect all output from stderr to stdout. It is useful for some
+ systems which don't have such a redirection in shell (e.g. DOS).
+
+ -v increase verbosity level. Currently 4 verbosity levels are
+ available: default (which only prints error information), normal
+ (which prints information about the produced object, -v), medium
+ (which prints information about what the program is doing, -v -v)
+ and high (which prints all available information, -v -v -v).
+
+ -a change alignment value to which multiple segments combigned into
+ a single segment should be aligned (must be either 1, 2, 4, 8,
+ 16, 32 or 256. Default is 16).
+
+ -s strip exported symbols from output file. Symbols marked as
+ SYM_GLOBAL are never stripped.
+
+ -x warn about unresolved symbols.
+
+ -xe issue an error when at least one symbol is unresolved.
+
+ -o name write output to file <name>. The default output filename
+ is 'aout.rdx'.
+
+ -j path specify search path for object files. Default path is a
+ current directory.
+
+ -L path specify search path for libraries. Default path is a
+ current directory.
+
+ -g file embed 'file' as a first header record with type 'generic'.
+
+
+rdx
+===
+
+This program simply loads and executes an RDOFF object, by calling
+'_main', which it expects to be a C-style function, which will accept
+two parameters, argc and argv in normal C style.
+
+
+rdflib
+======
+
+This program creates a library file for use with ldrdf.
+
+It is supplied with a shell script 'makelib' which should probably be used
+to create libraries.
+
+Usage:
+ rdflib command library [optional arguments]
+
+Valid commands are:
+
+ c Create (or truncate) the library
+ a Add a module (requires a filename and a name to give the
+ module, ie 'rdflib a libc.rdl strcpy.rdf strcpy' puts the
+ file 'strcpy.rdf' into 'libc.rdl', and calls it 'strcpy'.
+ x Extract (arguments are the opposite to the 'a' command,
+ ie you'd do 'rdflib x libc.rdl strcpy strcpy.rdf to get
+ a copy of strcpy.rdf back out again...)
+ t List modules in the library
+ d Delete modules from library
+ r Replace a module in library with a new file
+
+
+Library functions
+=================
+
+The files 'rdoff.c', 'rdoff.h', 'rdfload.c' and 'rdfload.h' contain
+code which you may find useful. They retain the same interface as
+the previous version, so any code that used them previously should
+still work OK (maybe). 'rdoff.c' contains at the top a line:
+
+#define STRICT_ERRORS
+
+Comment this line out if you wish to use record types other than the
+7 predefined types; it will then not report such records as an error,
+but accept them gracefully, and read them byte for byte into
+a 'generic record' (see the definition of GenericRec in 'rdoff.h').
+
+If you are using these functions to write RDF modules (rather than
+just reading them), then please note the existance of a new function
+'rdfaddsegment(rdf_headerbuf,long)'. This must be called once for
+each segment in your object, to tell the header writing functions
+how long the segment is.
+
+
+BUGS
+====
+
+This product has recently undergone a major revision, and as such there
+are probably several bugs left over from the testing phase (although the
+previous version had quite a few that have now been fixed!). Could you
+please report any bugs to maintainers at the addresses below, including the
+following information:
+
+ - A description of the bug
+ - What you think the program should be doing
+ - Which programs you are using
+ - Which operating system you are using, and which C compiler was used to
+ compile the programs (or state that the pre-compiled versions were used).
+ - If appropriate, any of the following:
+ * source code (preferably cut down to a minimum that will still assemble
+ and show the bug)
+ * the output of rdfdump on produced modules (or send the module if the
+ problem is in code generated)
+ * exact descriptions of error messages/symptoms/etc
+
+
+TODO
+====
+
+There are still various things unimplemented that we would like to add.
+If you want to find out what these are, search near the top of each *.c
+file for a comment containing the word 'TODO'. A brief list is given here:
+
+- Improve the performace of ldrdf (there are several enhancements I can think
+ of that wouldn't be too hard to add)
+- Stop assuming that we're on a little endian machine
+- Check for more bugs
+
+
+MAINTAINERS
+===========
+
+Yuri Zaporogets <yuriz@users.sf.net> - primary maintainer
+Julian Hall <jules@dsf.org.uk> - original designer and author
diff --git a/rdoff/collectn.c b/rdoff/collectn.c
new file mode 100644
index 0000000..317c528
--- /dev/null
+++ b/rdoff/collectn.c
@@ -0,0 +1,45 @@
+/*
+ * collectn.c - implements variable length pointer arrays [collections].
+ *
+ * This file is public domain.
+ */
+
+#include "compiler.h"
+#include <stdlib.h>
+#include "collectn.h"
+
+void collection_init(Collection * c)
+{
+ int i;
+
+ for (i = 0; i < 32; i++)
+ c->p[i] = NULL;
+ c->next = NULL;
+}
+
+void **colln(Collection * c, int index)
+{
+ while (index >= 32) {
+ index -= 32;
+ if (c->next == NULL) {
+ c->next = malloc(sizeof(Collection));
+ collection_init(c->next);
+ }
+ c = c->next;
+ }
+ return &(c->p[index]);
+}
+
+void collection_reset(Collection * c)
+{
+ int i;
+
+ if (c->next) {
+ collection_reset(c->next);
+ free(c->next);
+ }
+
+ c->next = NULL;
+ for (i = 0; i < 32; i++)
+ c->p[i] = NULL;
+}
diff --git a/rdoff/collectn.h b/rdoff/collectn.h
new file mode 100644
index 0000000..bcd75b8
--- /dev/null
+++ b/rdoff/collectn.h
@@ -0,0 +1,22 @@
+/*
+ * collectn.h - header file for 'collection' abstract data type.
+ *
+ * This file is public domain, and does not come under the NASM license.
+ * It, aint32_t with 'collectn.c' implements what is basically a variable
+ * length array (of pointers).
+ */
+
+#ifndef RDOFF_COLLECTN_H
+#define RDOFF_COLLECTN_H 1
+
+typedef struct tagCollection {
+ void *p[32]; /* array of pointers to objects */
+
+ struct tagCollection *next;
+} Collection;
+
+void collection_init(Collection * c);
+void **colln(Collection * c, int index);
+void collection_reset(Collection * c);
+
+#endif
diff --git a/rdoff/doc/Makefile b/rdoff/doc/Makefile
new file mode 100644
index 0000000..e4f24f5
--- /dev/null
+++ b/rdoff/doc/Makefile
@@ -0,0 +1,37 @@
+#
+# Make info documentation
+#
+
+AUXFILES = *.aux *.cp *.fn *.ky *.log *.pg *.toc *.tp *.vr *.dvi
+
+SRCS = rdoff.texi
+OUTS = rdoff.info rdoff.html rdoff.ps rdoff.pdf
+
+
+## Implicit rules
+%.html : %.texi
+ makeinfo --html $<
+
+%.dvi : %.texi
+ texi2dvi $<
+
+%.ps: %.dvi
+ dvips $<
+
+%.pdf: %.dvi
+ dvipdf $<
+
+
+## Explicit rules
+all: info
+
+info: rdoff.info
+
+html: rdoff.html
+
+ps: rdoff.ps
+
+pdf: rdoff.pdf
+
+clean:
+ rm -f $(OUTS) $(AUXFILES)
diff --git a/rdoff/doc/rdoff.texi b/rdoff/doc/rdoff.texi
new file mode 100644
index 0000000..4431287
--- /dev/null
+++ b/rdoff/doc/rdoff.texi
@@ -0,0 +1,137 @@
+\input texinfo @c -*-texinfo-*-
+@c %**start of header
+@setfilename rdoff.info
+@settitle Relocatable Dynamic Object File Format (RDOFF)
+@afourpaper
+@c %**end of header
+
+@titlepage
+@title Relocatable Dynamic Object File Format (RDOFF)
+@author Yuri Zaporogets @email{yuriz@@ukr.net}
+@author Julian Hall @email{jules@@dsf.org.uk}
+@end titlepage
+
+@ifinfo
+Copyright @copyright{} 2002-2004 Netwide Assembler Project.
+Written by Yuri Zaporogets @email{yuriz@@users.sf.net}
+Based on various sources and notes written by Julian Hall @email{jules@@dsf.org.uk}
+Distributed under GNU documentation license.
+@end ifinfo
+
+@ifnottex
+@node Top, Overview, (dir), (dir)
+@top RDOFF
+
+RDOFF is a Relocatable Dynamic Object File Format.
+
+@end ifnottex
+
+@menu
+* Overview:: Introduction.
+* Structure:: Structure of RDOFF file.
+* Utilities:: Description of RDOFF utilities.
+@end menu
+
+@node Overview
+@chapter Introduction
+
+RDOFF was designed initially to test the object-file production
+interface to NASM. It soon became apparent that it could be enhanced
+for use in serious applications due to its simplicity; code to load
+and execute an RDOFF object module is very simple. It also contains
+enhancements to allow it to be linked with a dynamic link library at
+either run- or load- time, depending on how complex you wish to make
+your loader.
+
+@node Structure
+@chapter Structure of RDOFF file
+
+RDOFF module consists of three parts:
+
+@itemize
+@item Master header
+@item Header (may be omited)
+@item Sections
+@end itemize
+
+@dfn{Master header} contains signature, version and size information.
+
+@dfn{Header} consists of zero or more @ref{Records, records}.
+
+@dfn{Sections} represent actual contents of the file. Each section is prepended
+by a section header.
+
+@node Records, , ,Structure
+@section Records that may appear in RDOFF header
+
+@menu
+* Relocation:: Relocation records.
+* Import:: Declaring external symbols.
+* Export:: Declaring public and exported symbols.
+* DLL:: Specifying a run-time library name.
+* BSS:: Reserving space in BSS section.
+* Segment relocation:: Complexity of relocation in segmented systems.
+* Far import:: External 'far' symbols.
+* Module name:: Specifying module name.
+* Common variable:: Declaring common variables.
+* Generic record:: Embedding general-purpose data into the header.
+@end menu
+
+@node Relocation
+@subsection Relocation records
+
+@node Import
+@subsection Declaring external and imported symbols
+
+@node Export
+@subsection Declaring public and exported symbols
+
+@node DLL
+@subsection Specifying a run-time library name
+
+@node BSS
+@subsection Reserving space in BSS section
+
+@node Segment relocation
+@subsection Complexity of relocation in segmented systems
+
+@node Far import
+@subsection External 'far' symbols.
+
+@node Module name
+@subsection Specifying module name.
+
+@node Common variable
+@subsection Declaring common variables.
+
+@node Generic record
+@subsection Embedding general-purpose data into the header.
+
+
+@node Utilities
+@chapter RDOFF utilities
+
+@menu
+* rdfdump:: Dump the contents of RDOFF file.
+* ldrdf:: RDOFF linker.
+* rdflib:: RDOFF librarian.
+* rdlar:: New RDOFF librarian/archiver.
+* rdx:: Load and execute RDOFF module.
+@end menu
+
+@node rdfdump
+@section @command{rdfdump} - dump the contents of RDOFF file
+
+@node ldrdf
+@section @command{ldrdf} - RDOFF linker
+
+@node rdflib
+@section @command{rdflib} - RDOFF librarian
+
+@node rdlar
+@section @command{rdlar} - new RDOFF librarian/archiver
+
+@node rdx
+@section @command{rdx} - load and execute RDOFF module
+
+@bye
diff --git a/rdoff/doc/v1-v2.txt b/rdoff/doc/v1-v2.txt
new file mode 100644
index 0000000..800896b
--- /dev/null
+++ b/rdoff/doc/v1-v2.txt
@@ -0,0 +1,62 @@
+Differences between RDOFF versions 1 & 2
+========================================
+
+This document is designed primarily for people maintaining code which
+uses RDOFF version 1, and would like to upgrade that code to work
+with version 2.
+
+The main changes are summarised here:
+
+Overall format
+==============
+
+The overall format has changed somewhat since version 1, in order
+to make RDOFF more flexible. After the file type identifier (which
+has been changed to 'RDOFF2', obviously), there is now a 4 byte
+integer describing the length of the object module. This allows
+multiple objects to be concatenated, while the loader can easily
+build an index of the locations of each object. This isn't as
+pointless as it sounds; I'm using RDOFF in a microkernel operating
+system, and this is the ideal way of loading multiple driver modules
+at boot time.
+
+There are also no longer a fixed number of segments; instead there
+is a list of segments, immediately following the header.
+Each segment is preceded by a 10 byte header giving information about
+that segment. This header has the following format:
+
+Length Description
+2 Type
+2 Number
+2 Reserved
+4 Length
+
+'Type' is a number describing what sort of segment it is (eg text, data,
+comment, debug info). See 'rdoff2.txt' for a list of the segment types.
+'Number' is the number used to refer to the segment in the header records.
+Not all segments will be loaded; it is only intended that one code
+and one data segment will be loaded into memory. It is possible, however,
+for a loaded segment to contain a reference to an unloaded segment.
+This is an error, and should be flagged at load time. Or maybe you should
+load the segment... its up to you, really.
+
+The segment's data immediately follows the end of the segment header.
+
+HEADER RECORDS
+==============
+
+All of the header records have changed in this version, but not
+substantially. Each record type has had a content-length code added,
+a single byte immediately following the type byte. This contains the
+length of the rest of the record (excluding the type and length bytes,
+but including the terminating nulls on any strings in the record).
+
+There are two new record types, Segment Relocation (6), and FAR import (7).
+The record formats are identical to Relocation (1) and import (2). They are
+only of real use on systems using segmented architectures. Systems using
+a flat model should treat FAR import (7) exactly the same as an import (2),
+and should either flag segment relocation as an error, or attempt to figure
+out whether it is a reference to a code or data symbol, and set the value
+referenced to the according selector value. I am opting for the former
+approach, and would recommend that others working on 32 bit flat systems
+do the same.
diff --git a/rdoff/hash.c b/rdoff/hash.c
new file mode 100644
index 0000000..ad2b568
--- /dev/null
+++ b/rdoff/hash.c
@@ -0,0 +1,122 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 1996-2009 The NASM Authors - All Rights Reserved
+ * See the file AUTHORS included with the NASM distribution for
+ * the specific copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * hash.h Routines to calculate a CRC32 hash value
+ *
+ * These routines donated to the NASM effort by Graeme Defty.
+ */
+
+#include "compiler.h"
+
+#include "hash.h"
+
+const uint32_t consttab[] = {
+ 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA,
+ 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
+ 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
+ 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
+ 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE,
+ 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
+ 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,
+ 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
+ 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
+ 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
+ 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940,
+ 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
+ 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116,
+ 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
+ 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
+ 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
+ 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A,
+ 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
+ 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818,
+ 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
+ 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
+ 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
+ 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C,
+ 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
+ 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2,
+ 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
+ 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
+ 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
+ 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086,
+ 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
+ 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4,
+ 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
+ 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
+ 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
+ 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8,
+ 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
+ 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE,
+ 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
+ 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
+ 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
+ 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252,
+ 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
+ 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60,
+ 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
+ 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
+ 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
+ 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04,
+ 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
+ 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A,
+ 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
+ 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
+ 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
+ 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E,
+ 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
+ 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C,
+ 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
+ 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
+ 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
+ 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0,
+ 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
+ 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6,
+ 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
+ 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
+ 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
+};
+
+uint32_t hash(const char *name)
+{
+ register const char *n;
+ register uint32_t hashval = 0xffffffff;
+
+ for (n = name; *n; n++)
+ hashval = (hashval >> 8) ^ consttab[(hashval ^ *n) & 0xff];
+
+ hashval ^= 0xffffffff;
+
+ return hashval;
+}
diff --git a/rdoff/hash.h b/rdoff/hash.h
new file mode 100644
index 0000000..a6920e7
--- /dev/null
+++ b/rdoff/hash.h
@@ -0,0 +1,18 @@
+/* hash.h Routines to calculate a CRC32 hash value
+ *
+ * These routines donated to the NASM effort by Graeme Defty.
+ *
+ * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
+ * Julian Hall. All rights reserved. The software is
+ * redistributable under the license given in the file "LICENSE"
+ * distributed in the NASM archive.
+ */
+
+#ifndef RDOFF_HASH_H
+#define RDOFF_HASH_H 1
+
+#include <inttypes.h>
+
+uint32_t hash(const char *name);
+
+#endif
diff --git a/rdoff/ldrdf.1 b/rdoff/ldrdf.1
new file mode 100644
index 0000000..d0a2c21
--- /dev/null
+++ b/rdoff/ldrdf.1
@@ -0,0 +1,41 @@
+.TH LDRDF 1 "September 6, 1999" "Debian Project" "Debian Manual"
+.SH NAME
+ldrdf \- link RDOFF objects and libraries produced by rdflib(1)
+.SH SYNOPSIS
+.B ldrdf
+.RI "[-o " output-file ]
+.I object-file\c
+.RI "... [-l" library "...]"
+.SH DESCRIPTION
+.B ldrdf
+is a version of unix
+.BR ld (1)
+(or DOS LINK) for use with RDOFF files. It is capable of linking RDOFF
+objects, and libraries produced with the
+.BR rdflib (1)
+utility.
+.PP
+Libraries must be specified with their path as no search is performed.
+Modules in libraries are not linked to the program unless they are
+referred to.
+.SH OPTIONS
+.TP
+.RI "-o " output-file
+Specify an output file. The default output filename is
+.RI ' aout.rdx '.
+.TP
+-v
+Increase verbosity level. Currently 4 verbosity levels are available:
+default (which only prints error information), normal (which prints
+information about the produced object, -v), medium (which prints information
+about what the program is doing, -v -v) and high (which prints all available
+information, -v -v -v).
+.TP
+-p
+Change alignment value to which multiple segments combigned into a single
+segment should be aligned (must be either 1, 2, 4, 8, 16, 32 or 256; default
+is 16).
+.SH AUTHORS
+Julian Hall <jules@earthcorp.com>.
+.PP
+This manual page was written by Matej Vela <vela@debian.org>.
diff --git a/rdoff/ldrdf.c b/rdoff/ldrdf.c
new file mode 100644
index 0000000..2ddada3
--- /dev/null
+++ b/rdoff/ldrdf.c
@@ -0,0 +1,1360 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 1996-2009 The NASM Authors - All Rights Reserved
+ * See the file AUTHORS included with the NASM distribution for
+ * the specific copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * ldrdf.c - RDOFF Object File linker/loader main program.
+ */
+
+/*
+ * 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
+ *
+ * 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
+ * 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.
+ */
+
+#include "compiler.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define RDOFF_UTILS
+
+#include "rdoff.h"
+#include "symtab.h"
+#include "collectn.h"
+#include "rdlib.h"
+#include "segtab.h"
+#include "nasmlib.h"
+
+#define LDRDF_VERSION "1.07"
+
+/* #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 */
+ int32_t 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;
+ int32_t 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(uint16_t type, uint16_t reserved);
+int findsegment(uint16_t type, uint16_t reserved);
+void symtab_add(const char *symbol, int segment, int32_t offset);
+int symtab_get(const char *symbol, int *segment, int32_t *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;
+
+/* file to embed as a generic record */
+char *generic_rec_file = NULL;
+
+/* error file */
+static FILE *error_file;
+
+/* 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;
+int32_t bss_length;
+
+/* global options which affect how the program behaves */
+struct ldrdfoptions {
+ int verbose;
+ int align;
+ int dynalink;
+ int strip;
+ int respfile;
+ int stderr_redir;
+ int objpath;
+ int libpath;
+} 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, because 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;
+ int32_t bssamount = 0;
+ int bss_was_referenced = 0;
+
+ memset(&sconf, 0, sizeof sconf);
+
+ 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:%08"PRIx32" (+%04"PRIx32")\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:%08"PRIx32" (+%04"PRIx32")\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 RDFREC_IMPORT: /* imported symbol */
+ case RDFREC_FARIMPORT:
+ /* Define with seg = -1 */
+ symtab_add(hr->i.label, -1, 0);
+ break;
+
+ case RDFREC_GLOBAL:{ /* exported symbol */
+ int destseg;
+ int32_t destreloc;
+
+ if (hr->e.segment == 2) {
+ bss_was_referenced = 1;
+ 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 RDFREC_BSS: /* 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;
+
+ case RDFREC_COMMON:{ /* Common variable */
+ symtabEnt *ste = symtabFind(symtab, hr->c.label);
+
+ /* Is the symbol already in the table? */
+ if (ste)
+ break;
+
+ /* Align the variable */
+ if (bss_length % hr->c.align != 0)
+ bss_length += hr->c.align - (bss_length % hr->c.align);
+ if (options.verbose > 1) {
+ printf("%s %04x common '%s' => 0002:%08"PRIx32" (+%04"PRIx32")\n",
+ filename, hr->c.segment, hr->c.label,
+ bss_length, hr->c.size);
+ }
+
+ symtab_add(hr->c.label, 2, bss_length);
+ mod->bss_reloc = bss_length;
+ bss_length += hr->c.size;
+ break;
+ }
+ }
+ }
+
+ if (bssamount != 0 || bss_was_referenced) {
+ /*
+ * 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:%08"PRIx32" (+%04"PRIx32")\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
+
+}
+
+/*
+ * Return 1 if a given module is in the list, 0 otherwise.
+ */
+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(uint16_t type, uint16_t 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(uint16_t type, uint16_t 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, int32_t 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, int32_t *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;
+ int32_t 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 != RDFREC_GLOBAL)
+ continue;
+
+ /*
+ * If the symbol is marked as SYM_GLOBAL, somebody will be
+ * definitely interested in it..
+ */
+ if ((hr->e.flags & SYM_GLOBAL) == 0) {
+ /*
+ * otherwise the symbol is just public. Find it 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;
+ int32_t offset;
+ uint8_t *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);
+ }
+
+ /*
+ * If '-g' option was given, first record in output file will be a
+ * `generic' record, filled with a given file content.
+ * This can be useful, for example, when constructing multiboot
+ * compliant kernels.
+ */
+ if (generic_rec_file) {
+ FILE *ff;
+
+ if (options.verbose)
+ printf("\nadding generic record from binary file %s\n",
+ generic_rec_file);
+
+ hr = (rdfheaderrec *) malloc(sizeof(struct GenericRec));
+ if ((ff = fopen(generic_rec_file, "r")) == NULL) {
+ fprintf(stderr, "ldrdf: couldn't open %s for input\n",
+ generic_rec_file);
+ exit(1);
+ }
+ i = fread(hr->g.data, 1, sizeof(hr->g.data), ff);
+ fseek(ff, 0, SEEK_END);
+ if (ftell(ff) > (long)sizeof(hr->g.data)) {
+ fprintf(error_file,
+ "warning: maximum generic record size is %u, "
+ "rest of file ignored\n",
+ (unsigned int)sizeof(hr->g.data));
+ }
+ fclose(ff);
+
+ hr->g.type = 0;
+ hr->g.reclen = i;
+ 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 RDFREC_RELOC: /* 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 & RDOFF_RELATIVEMASK) ==
+ RDOFF_RELATIVEMASK;
+ hr->r.segment &= (RDOFF_RELATIVEMASK - 1);
+
+ 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:%08"PRIx32")\n", cur->name,
+ (int)hr->r.segment, hr->r.offset);
+ *data = (char)offset;
+ break;
+ case 2:
+ offset += *(int16_t *)data;
+ if (offset < -32767 || offset > 32768)
+ fprintf(error_file,
+ "warning: relocation out of range "
+ "at %s(%02x:%08"PRIx32")\n", cur->name,
+ (int)hr->r.segment, hr->r.offset);
+ *(int16_t *)data = (int16_t)offset;
+ break;
+ case 4:
+ *(int32_t *)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;
+ if (isrelative)
+ hr->r.segment += RDOFF_RELATIVEMASK;
+ rdfaddheader(rdfheader, hr);
+ }
+ break;
+
+ case RDFREC_IMPORT: /* import symbol */
+ case RDFREC_FARIMPORT:
+ /*
+ * 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.dynalink && !(hr->i.flags & SYM_IMPORT)) {
+ fprintf(error_file,
+ "error: unresolved reference to `%s'"
+ " in module `%s'\n", hr->i.label,
+ cur->name);
+ 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 RDFREC_GLOBAL: /* export symbol */
+ /*
+ * need to insert an export for this symbol into the new
+ * header, unless we're stripping symbols. Even if we're
+ * stripping, put the symbol if it's marked as SYM_GLOBAL.
+ */
+ if (options.strip && !(hr->e.flags & SYM_GLOBAL))
+ 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 RDFREC_MODNAME: /* module name */
+ /*
+ * Insert module name record if export symbols
+ * are not stripped.
+ * If module name begins with '$' - insert it anyway.
+ */
+ if (options.strip && hr->m.modname[0] != '$')
+ break;
+ rdfaddheader(rdfheader, hr);
+ break;
+
+ case RDFREC_DLL: /* DLL name */
+ /*
+ * Insert DLL name if it begins with '$'
+ */
+ if (hr->d.libname[0] != '$')
+ break;
+ rdfaddheader(rdfheader, hr);
+ break;
+
+ case RDFREC_SEGRELOC: /* 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;
+
+ case RDFREC_COMMON: /* Common variable */
+ /* Is this symbol already in the table? */
+ se = symtabFind(symtab, hr->c.label);
+ if (!se) {
+ printf("%s is not in symtab yet\n", hr->c.label);
+ break;
+ }
+ /* Add segment location */
+ add_seglocation(&segs, hr->c.segment, se->segment,
+ se->offset);
+ break;
+ }
+ }
+
+ free(header);
+ done_seglocations(&segs);
+
+ }
+
+ /*
+ * combined BSS reservation for the entire results
+ */
+ newrec.type = RDFREC_BSS;
+ 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);
+ }
+
+ 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++) {
+ uint16_t s;
+ int32_t l;
+
+ if (i == 2)
+ continue;
+
+ s = translateint16_t(outputseg[i].type);
+ fwrite(&s, 2, 1, f);
+ s = translateint16_t(outputseg[i].number);
+ fwrite(&s, 2, 1, f);
+ s = translateint16_t(outputseg[i].reserved);
+ fwrite(&s, 2, 1, f);
+ l = translateint32_t(outputseg[i].length);
+ fwrite(&l, 4, 1, f);
+
+ fwrite(outputseg[i].data, outputseg[i].length, 1, f);
+ }
+
+ fwritezero(10, f);
+}
+
+/* =========================================================================
+ * Main program
+ */
+
+void usage()
+{
+ printf("usage:\n"
+ " ldrdf [options] object modules ... [-llibrary ...]\n"
+ " ldrdf -r\n"
+ "options:\n"
+ " -v[=n] increase verbosity by 1, or set it to n\n"
+ " -a nn set segment alignment value (default 16)\n"
+ " -s strip public symbols\n"
+ " -dy Unix-style dynamic linking\n"
+ " -o name write output in file 'name'\n"
+ " -j path specify objects search path\n"
+ " -L path specify libraries search path\n"
+ " -g file embed 'file' as a first header record with type 'generic'\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.dynalink = 0;
+ options.strip = 0;
+
+ error_file = stderr;
+
+ argc--, argv++;
+ if (argc == 0)
+ usage();
+ while (argc && *argv && **argv == '-' && argv[0][1] != 'l') {
+ switch (argv[0][1]) {
+ case 'r':
+ printf("ldrdf (linker for RDF files) version " LDRDF_VERSION
+ "\n");
+ printf("RDOFF2 revision %s\n", RDOFF2_REVISION);
+ 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 'd':
+ if (argv[0][2] == 'y')
+ options.dynalink = 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);
+ }
+
+ argv++, argc--;
+ while (fgets(buf, sizeof(buf), f) != NULL) {
+ char *p;
+ if (buf[0] == '\n')
+ continue;
+ if ((p = strchr(buf, '\n')) != NULL)
+ *p = '\0';
+ if (i >= 128) {
+ fprintf(stderr, "ldrdf: too many input files\n");
+ exit(1);
+ }
+ *(respstrings + i) = newstr(buf);
+ argc++, i++;
+ }
+ break;
+ }
+ case '2':
+ options.stderr_redir = 1;
+ error_file = stdout;
+ break;
+ case 'g':
+ generic_rec_file = argv[1];
+ argv++, argc--;
+ break;
+ default:
+ usage();
+ }
+ argv++, argc--;
+ }
+
+ 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.dynalink)
+ printf(" Unix-style dynamic linking\n");
+ if (options.objpath)
+ printf(" objects search path: %s\n", objpath);
+ if (options.libpath)
+ printf(" libraries search path: %s\n", libpath);
+ printf("\n");
+ }
+
+ symtab = symtabNew();
+ initsegments();
+
+ if (!symtab) {
+ fprintf(stderr, "ldrdf: out of memory\n");
+ exit(1);
+ }
+
+ while (argc) {
+ if (!*argv)
+ argv = respstrings;
+ if (!*argv)
+ break;
+ if (!strncmp(*argv, "-l", 2)) {
+ if (libpath && (argv[0][2] != '/'))
+ add_library(newstrcat(libpath, *argv + 2));
+ else
+ add_library(*argv + 2);
+ } else {
+ if (objpath && (argv[0][0] != '/'))
+ 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/ldsegs.h b/rdoff/ldsegs.h
new file mode 100644
index 0000000..fcecdf6
--- /dev/null
+++ b/rdoff/ldsegs.h
@@ -0,0 +1,60 @@
+/*
+ * ldsegs.h Data for 'ldrdf' to determine what to do with different
+ * types of segment. This may be useful in other contexts also.
+ */
+
+#ifndef RDOFF_LDSEGS_H
+#define RDOFF_LDSEGS_H 1
+
+#include <inttypes.h>
+
+struct segconfig {
+ uint16_t typelow, typehi; /* range of seg nos for which this is valid */
+ char *typedesc; /* a description of the segment type */
+ uint16_t dowhat; /* one of the SEG_xxxx values below */
+ uint16_t mergetype; /* if SEG_MERGE what type segment do we merge
+ with?
+ 0 -> same type of segment. This type is also
+ used with SEG_NEWSEG. */
+};
+
+#define SEG_IGNORE 0
+#define SEG_NEWSEG 1
+#define SEG_MERGE 2
+
+#define SEGCONFIGMAX 11
+
+struct segconfig sconft[SEGCONFIGMAX] = {
+ {0x0000, 0x0000, "NULL segment", 0, 0},
+ {0x0001, 0x0001, "text", 2, 0},
+ {0x0002, 0x0002, "data", 2, 0},
+ {0x0003, 0x0003, "comment(ignored)", 0, 0},
+ {0x0004, 0x0005, "comment(kept)", 2, 0},
+ {0x0006, 0x0007, "debug information", 2, 0},
+ {0x0008, 0x001F, "reserved(general extensions)", 1, 0},
+ {0x0020, 0x0FFF, "reserved(MOSCOW)", 1, 0},
+ {0x1000, 0x7FFF, "reserved(system dependant)", 1, 0},
+ {0x8000, 0xFFFE, "reserved(other)", 1, 0},
+ {0xFFFF, 0xFFFF, "invalid segment", 0, 0}
+};
+
+#define getsegconfig(target,number) \
+ { \
+ int _i; \
+ int _t = number; \
+ for (_i = 0; _i < SEGCONFIGMAX; _i++) \
+ if (_t >= sconft[_i].typelow && _t <= sconft[_i].typehi) \
+ { \
+ target = sconft[_i]; \
+ if (target.mergetype == 0) target.mergetype = _t; \
+ break; \
+ } \
+ if (_i == SEGCONFIGMAX) \
+ { \
+ fprintf(stderr, "PANIC: can't find segment %04X in segconfig\n",\
+ _t); \
+ exit(1); \
+ } \
+ }
+
+#endif
diff --git a/rdoff/rdf2bin.1 b/rdoff/rdf2bin.1
new file mode 100644
index 0000000..d274d58
--- /dev/null
+++ b/rdoff/rdf2bin.1
@@ -0,0 +1,65 @@
+.TH RDF2BIN 1 "September 6, 1999" "Debian Project" "Debian Manual"
+.SH NAME
+rdf2bin, rdf2com \- convert an RDOFF object file to flat binary
+.SH SYNOPSIS
+.B rdf2bin
+.RI "[\-o " relocation-origin ]
+.RI "[\-p " segment-alignment ]
+.RI "[\-f " format ]
+.I input-file
+.I output-file
+.br
+.B rdf2com
+.RI "[\-p " segment-alignment ]
+.I input-file
+.I output-file
+.br
+.B rdf2ith
+.RI "[\-o " relocation-origin ]
+.RI "[\-p " segment-alignment ]
+.I input-file
+.I output-file
+.br
+.B rdf2srec
+.RI "[\-o " relocation-origin ]
+.RI "[\-p " segment-alignment ]
+.I input-file
+.I output-file
+.SH OPTIONS
+.TP
+.RI "\-o " relocation-origin
+Relocate at origin
+.IR relocation-origin .
+If invoked as
+.BR rdf2com ,
+the default relocation origin will be 0x100. Else, the default origin is 0.
+.TP
+.RI "\-p " segment-alignment
+Pad segments until their size is a multiple of
+.IR segment-alignment .
+By default, 16 is used.
+.TP
+.RI "\-f " format
+Specify the output format. The currently supported formats are binary
+.RI ( bin ),
+DOS COM (binary with origin 0x100)
+.RI ( com )
+Intel hex
+.RI ( ith
+or
+.IR ihx ),
+and
+Motorola S-Records
+.RI ( srec ).
+If not specified, the format is set by the command name.
+.SH AUTHORS
+Julian Hall <jules@earthcorp.com>, H. Peter Anvin <hpa@zytor.com>.
+.PP
+This manual page was written by Matej Vela <vela@debian.org>.
+.SH BUGS
+This utility currently only supports the classic segments
+.IR .text ,
+.I .data
+and
+.IR .bss .
+
diff --git a/rdoff/rdf2bin.c b/rdoff/rdf2bin.c
new file mode 100644
index 0000000..72e5104
--- /dev/null
+++ b/rdoff/rdf2bin.c
@@ -0,0 +1,430 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 1996-2009 The NASM Authors - All Rights Reserved
+ * See the file AUTHORS included with the NASM distribution for
+ * the specific copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * rdf2bin.c - convert an RDOFF object file to flat binary
+ */
+
+#include "compiler.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+
+#include "rdfload.h"
+#include "nasmlib.h"
+
+const char *progname;
+
+static uint32_t origin = 0;
+static bool origin_def = false;
+static uint32_t align = 16;
+static bool align_def = false;
+
+struct output_format {
+ const char *name;
+ const char *mode;
+ int (*init)(FILE *f);
+ int (*output)(FILE *f, void *data, uint32_t bytes, uint32_t where);
+ int (*fini)(FILE *f);
+};
+
+static int null_init_fini(FILE *f)
+{
+ (void)f;
+ return 0;
+}
+
+static int com_init(FILE *f)
+{
+ (void)f;
+ if (!origin_def)
+ origin = 0x100;
+ return 0;
+}
+
+static int output_bin(FILE *f, void *data, uint32_t bytes, uint32_t where)
+{
+ static uint32_t offset = 0; /* Current file offset, if applicable */
+ size_t pad;
+
+ if (where-origin < offset) {
+ fprintf(stderr, "%s: internal error: backwards movement\n", progname);
+ exit(1);
+ }
+
+ pad = (where-origin) - offset;
+ if (fwritezero(pad, f) != pad)
+ return -1;
+ offset += pad;
+
+ if (fwrite(data, 1, bytes, f) != bytes)
+ return -1;
+ offset += bytes;
+
+ return 0;
+}
+
+static int write_ith_record(FILE *f, unsigned int len, uint16_t addr,
+ uint8_t type, void *data)
+{
+ char buf[1+2+4+2+255*2+2+2];
+ char *p = buf;
+ uint8_t csum, *dptr = data;
+ unsigned int i;
+
+ if (len > 255) {
+ fprintf(stderr, "%s: internal error: invalid ith record size\n",
+ progname);
+ exit(1);
+ }
+
+ csum = len + addr + (addr >> 8) + type;
+ for (i = 0; i < len; i++)
+ csum += dptr[i];
+ csum = -csum;
+
+ p += sprintf(p, ":%02X%04X%02X", len, addr, type);
+ for (i = 0; i < len; i++)
+ p += sprintf(p, "%02X", dptr[i]);
+ p += sprintf(p, "%02X\n", csum);
+
+ if (fwrite(buf, 1, p-buf, f) != (size_t)(p-buf))
+ return -1;
+
+ return 0;
+}
+
+static int output_ith(FILE *f, void *data, uint32_t bytes, uint32_t where)
+{
+ static uint32_t last = 0; /* Last address written */
+ uint8_t abuf[2];
+ uint8_t *dbuf = data;
+ uint32_t chunk;
+
+ while (bytes) {
+ if ((where ^ last) & ~0xffff) {
+ abuf[0] = where >> 24;
+ abuf[1] = where >> 16;
+ if (write_ith_record(f, 2, 0, 4, abuf))
+ return -1;
+ }
+
+ /* Output up to 32 bytes, but always end on an aligned boundary */
+ chunk = 32 - (where & 31);
+ if (bytes < chunk)
+ chunk = bytes;
+
+ if (write_ith_record(f, chunk, (uint16_t)where, 0, dbuf))
+ return -1;
+
+ dbuf += chunk;
+ last = where + chunk - 1;
+ where += chunk;
+ bytes -= chunk;
+ }
+ return 0;
+}
+
+static int fini_ith(FILE *f)
+{
+ /* XXX: entry point? */
+ return write_ith_record(f, 0, 0, 1, NULL);
+}
+
+static int write_srecord(FILE *f, unsigned int len, unsigned int alen,
+ uint32_t addr, uint8_t type, void *data)
+{
+ char buf[2+2+8+255*2+2+2];
+ char *p = buf;
+ uint8_t csum, *dptr = data;
+ unsigned int i;
+
+ if (len > 255) {
+ fprintf(stderr, "%s: internal error: invalid srec record size\n",
+ progname);
+ exit(1);
+ }
+
+ switch (alen) {
+ case 2:
+ addr &= 0xffff;
+ break;
+ case 3:
+ addr &= 0xffffff;
+ break;
+ case 4:
+ break;
+ default:
+ fprintf(stderr, "%s: internal error: invalid srec address length\n",
+ progname);
+ exit(1);
+ }
+
+ csum = (len+alen+1) + addr + (addr >> 8) + (addr >> 16) + (addr >> 24);
+ for (i = 0; i < len; i++)
+ csum += dptr[i];
+ csum = 0xff-csum;
+
+ p += sprintf(p, "S%c%02X%0*X", type, len+alen+1, alen*2, addr);
+ for (i = 0; i < len; i++)
+ p += sprintf(p, "%02X", dptr[i]);
+ p += sprintf(p, "%02X\n", csum);
+
+ if (fwrite(buf, 1, p-buf, f) != (size_t)(p-buf))
+ return -1;
+
+ return 0;
+}
+
+static int init_srec(FILE *f)
+{
+ return write_srecord(f, 0, 2, 0, '0', NULL);
+}
+
+static int fini_srec(FILE *f)
+{
+ /* XXX: entry point? */
+ return write_srecord(f, 0, 4, 0, '7', NULL);
+}
+
+static int output_srec(FILE *f, void *data, uint32_t bytes, uint32_t where)
+{
+ uint8_t *dbuf = data;
+ unsigned int chunk;
+
+ while (bytes) {
+ /* Output up to 32 bytes, but always end on an aligned boundary */
+ chunk = 32 - (where & 31);
+ if (bytes < chunk)
+ chunk = bytes;
+
+ if (write_srecord(f, chunk, 4, where, '3', dbuf))
+ return -1;
+
+ dbuf += chunk;
+ where += chunk;
+ bytes -= chunk;
+ }
+ return 0;
+}
+
+static struct output_format output_formats[] = {
+ { "bin", "wb", null_init_fini, output_bin, null_init_fini },
+ { "com", "wb", com_init, output_bin, null_init_fini },
+ { "ith", "wt", null_init_fini, output_ith, fini_ith },
+ { "ihx", "wt", null_init_fini, output_ith, fini_ith },
+ { "srec", "wt", init_srec, output_srec, fini_srec },
+ { NULL, NULL, NULL, NULL, NULL }
+};
+
+static const char *getformat(const char *pathname)
+{
+ const char *p;
+ static char fmt_buf[16];
+
+ /*
+ * Search backwards for the string "rdf2" followed by a string
+ * of alphanumeric characters. This should handle path prefixes,
+ * as well as extensions (e.g. C:\FOO\RDF2SREC.EXE).
+ */
+ for (p = strchr(pathname, '\0')-1 ; p >= pathname ; p--) {
+ if (!nasm_stricmp(p, "rdf2")) {
+ const char *q = p+4;
+ char *r = fmt_buf;
+ while (isalnum(*q) && r < fmt_buf+sizeof fmt_buf-1)
+ *r++ = *q++;
+ *r = '\0';
+ if (fmt_buf[0])
+ return fmt_buf;
+ }
+ }
+ return NULL;
+}
+
+static void usage(void)
+{
+ fprintf(stderr,
+ "Usage: %s [options] input-file output-file\n"
+ "Options:\n"
+ " -o origin Specify the relocation origin\n"
+ " -p alignment Specify minimum segment alignment\n"
+ " -f format Select format (bin, com, ith, srec)\n"
+ " -q Run quiet\n"
+ " -v Run verbose\n",
+ progname);
+}
+
+int main(int argc, char **argv)
+{
+ rdfmodule *m;
+ bool err;
+ FILE *of;
+ int codepad, datapad;
+ const char *format = NULL;
+ const struct output_format *fmt;
+ bool quiet = false;
+
+ progname = argv[0];
+
+ if (argc < 2) {
+ usage();
+ return 1;
+ }
+
+ argv++, argc--;
+
+ while (argc > 2) {
+ if (argv[0][0] == '-' && argv[0][1] && !argv[0][2]) {
+ switch (argv[0][1]) {
+ case 'o':
+ argv++, argc--;
+ origin = readnum(*argv, &err);
+ if (err) {
+ fprintf(stderr, "%s: invalid parameter: %s\n",
+ progname, *argv);
+ return 1;
+ }
+ origin_def = true;
+ break;
+ case 'p':
+ argv++, argc--;
+ align = readnum(*argv, &err);
+ if (err) {
+ fprintf(stderr, "%s: invalid parameter: %s\n",
+ progname, *argv);
+ return 1;
+ }
+ align_def = true;
+ break;
+ case 'f':
+ argv++, argc--;
+ format = *argv;
+ break;
+ case 'q':
+ quiet = true;
+ break;
+ case 'v':
+ quiet = false;
+ break;
+ case 'h':
+ usage();
+ return 0;
+ default:
+ fprintf(stderr, "%s: unknown option: %s\n",
+ progname, *argv);
+ return 1;
+ }
+ }
+ argv++, argc--;
+ }
+
+ if (argc < 2) {
+ usage();
+ return 1;
+ }
+
+ if (!format)
+ format = getformat(progname);
+
+ if (!format) {
+ fprintf(stderr, "%s: unable to determine desired output format\n",
+ progname);
+ return 1;
+ }
+
+ for (fmt = output_formats; fmt->name; fmt++) {
+ if (!nasm_stricmp(format, fmt->name))
+ break;
+ }
+
+ if (!fmt->name) {
+ fprintf(stderr, "%s: unknown output format: %s\n", progname, format);
+ return 1;
+ }
+
+ m = rdfload(*argv);
+
+ if (!m) {
+ rdfperror(progname, *argv);
+ return 1;
+ }
+
+ if (!quiet)
+ printf("relocating %s: origin=%"PRIx32", align=%d\n",
+ *argv, origin, align);
+
+ m->textrel = origin;
+ m->datarel = origin + m->f.seg[0].length;
+ if (m->datarel % align != 0) {
+ codepad = align - (m->datarel % align);
+ m->datarel += codepad;
+ } else
+ codepad = 0;
+
+ m->bssrel = m->datarel + m->f.seg[1].length;
+ if (m->bssrel % align != 0) {
+ datapad = align - (m->bssrel % align);
+ m->bssrel += datapad;
+ } else
+ datapad = 0;
+
+ if (!quiet)
+ printf("code: %08"PRIx32"\ndata: %08"PRIx32"\nbss: %08"PRIx32"\n",
+ m->textrel, m->datarel, m->bssrel);
+
+ rdf_relocate(m);
+
+ argv++;
+
+ of = fopen(*argv, fmt->mode);
+ if (!of) {
+ fprintf(stderr, "%s: could not open output file %s: %s\n",
+ progname, *argv, strerror(errno));
+ return 1;
+ }
+
+ if (fmt->init(of) ||
+ fmt->output(of, m->t, m->f.seg[0].length, m->textrel) ||
+ fmt->output(of, m->d, m->f.seg[1].length, m->datarel) ||
+ fmt->fini(of)) {
+ fprintf(stderr, "%s: error writing to %s: %s\n",
+ progname, *argv, strerror(errno));
+ return 1;
+ }
+
+ fclose(of);
+ return 0;
+}
diff --git a/rdoff/rdf2com.1 b/rdoff/rdf2com.1
new file mode 100644
index 0000000..43b3307
--- /dev/null
+++ b/rdoff/rdf2com.1
@@ -0,0 +1 @@
+.so man1/rdf2bin.1
diff --git a/rdoff/rdf2ihx.1 b/rdoff/rdf2ihx.1
new file mode 100644
index 0000000..43b3307
--- /dev/null
+++ b/rdoff/rdf2ihx.1
@@ -0,0 +1 @@
+.so man1/rdf2bin.1
diff --git a/rdoff/rdf2ith.1 b/rdoff/rdf2ith.1
new file mode 100644
index 0000000..43b3307
--- /dev/null
+++ b/rdoff/rdf2ith.1
@@ -0,0 +1 @@
+.so man1/rdf2bin.1
diff --git a/rdoff/rdf2srec.1 b/rdoff/rdf2srec.1
new file mode 100644
index 0000000..43b3307
--- /dev/null
+++ b/rdoff/rdf2srec.1
@@ -0,0 +1 @@
+.so man1/rdf2bin.1
diff --git a/rdoff/rdfdump.1 b/rdoff/rdfdump.1
new file mode 100644
index 0000000..cf61484
--- /dev/null
+++ b/rdoff/rdfdump.1
@@ -0,0 +1,24 @@
+.TH RDFDUMP 1 "September 6, 1999" "Debian Project" "Debian Manual"
+.SH NAME
+rdfdump \- dumps an RDOFF object in human-readable form
+.SH SYNOPSIS
+.B rdfdump
+[-v]
+.RI < filename >
+.SH DESCRIPTION
+.B rdfdump
+prints a list of the header records in an RDOFF object in human-readable
+form, and optionally prints a hex dump of the contents of the segments.
+.PP
+.B rdfdump
+supports both version 1 and 2 of RDOFF. It will give warnings if the RDOFF2
+format is violated (it looks for incorrect lengths for header records, and
+checks the overall length count at the start of the file).
+.SH OPTIONS
+.TP
+-v
+Print a hex dump of the contents of the segments.
+.SH AUTHORS
+Julian Hall <jules@earthcorp.com>.
+.PP
+This manual page was written by Matej Vela <vela@debian.org>.
diff --git a/rdoff/rdfdump.c b/rdoff/rdfdump.c
new file mode 100644
index 0000000..0e55c67
--- /dev/null
+++ b/rdoff/rdfdump.c
@@ -0,0 +1,347 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 1996-2009 The NASM Authors - All Rights Reserved
+ * See the file AUTHORS included with the NASM distribution for
+ * the specific copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * rdfdump.c - dump RDOFF file header.
+ */
+
+#include "compiler.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define RDOFF_UTILS
+
+#include "rdoff.h"
+
+#define PROGRAM_VERSION "2.3"
+
+FILE *infile;
+
+void print_header(int32_t length, int rdf_version)
+{
+ char buf[129], t, l, s, flags;
+ uint8_t reclen;
+ int32_t o, ll;
+ uint16_t rs;
+
+ while (length > 0) {
+ fread(&t, 1, 1, infile);
+ if (rdf_version >= 2) {
+ fread(&reclen, 1, 1, infile);
+ }
+ switch (t) {
+ case RDFREC_GENERIC: /* generic record */
+ printf(" generic record (length=%d)\n", (int)reclen);
+ fseek(infile, reclen, SEEK_CUR);
+ break;
+
+ case RDFREC_RELOC: /* relocation record */
+ case RDFREC_SEGRELOC: /* segment relocation */
+ fread(&s, 1, 1, infile);
+ fread(&o, 4, 1, infile);
+ fread(&l, 1, 1, infile);
+ fread(&rs, 2, 1, infile);
+ printf(" %s: location (%04x:%08"PRIx32"), length %d, "
+ "referred seg %04x\n",
+ t == 1 ? "relocation" : "seg relocation", (int)s,
+ translateint32_t(o), (int)l, translateint16_t(rs));
+ if (rdf_version >= 2 && reclen != 8)
+ printf(" warning: reclen != 8\n");
+ if (rdf_version == 1)
+ length -= 9;
+ if (rdf_version == 1 && t == 6)
+ printf
+ (" warning: seg relocation not supported in RDOFF1\n");
+ break;
+
+ case RDFREC_IMPORT: /* import record */
+ case RDFREC_FARIMPORT: /* import far symbol */
+ fread(&flags, 1, 1, infile);
+ fread(&rs, 2, 1, infile);
+ ll = 0;
+
+ if (rdf_version == 1) {
+ do {
+ fread(&buf[ll], 1, 1, infile);
+ } while (buf[ll++]);
+ } else {
+ for (; ll < reclen - 3; ll++)
+ fread(&buf[ll], 1, 1, infile);
+ }
+
+ if (t == 7)
+ printf("far ");
+ printf((flags & SYM_IMPORT) ? " import" : " extern");
+ if (flags & SYM_FUNCTION)
+ printf(" proc");
+ if (flags & SYM_DATA)
+ printf(" data");
+ printf(": segment %04x = %s\n", translateint16_t(rs), buf);
+ if (rdf_version == 1)
+ length -= ll + 3;
+ if (rdf_version == 1 && t == 7)
+ printf
+ (" warning: far import not supported in RDOFF1\n");
+ break;
+
+ case RDFREC_GLOBAL: /* export record */
+ fread(&flags, 1, 1, infile);
+ fread(&s, 1, 1, infile);
+ fread(&o, 4, 1, infile);
+ ll = 0;
+
+ if (rdf_version == 1) {
+ do {
+ fread(&buf[ll], 1, 1, infile);
+ } while (buf[ll++]);
+ } else {
+ for (; ll < reclen - 6; ll++)
+ fread(&buf[ll], 1, 1, infile);
+ }
+ printf((flags & SYM_GLOBAL) ? " export" : " public");
+ if (flags & SYM_FUNCTION)
+ printf(" proc");
+ if (flags & SYM_DATA)
+ printf(" data");
+ printf(": (%04x:%08"PRIx32") = %s\n", (int)s, translateint32_t(o), buf);
+ if (rdf_version == 1)
+ length -= ll + 6;
+ break;
+
+ case RDFREC_DLL: /* DLL and Module records */
+ case RDFREC_MODNAME:
+ ll = 0;
+ if (rdf_version == 1) {
+ do {
+ fread(&buf[ll], 1, 1, infile);
+ } while (buf[ll++]);
+ } else {
+ for (; ll < reclen; ll++)
+ fread(&buf[ll], 1, 1, infile);
+ }
+ if (t == 4)
+ printf(" dll: %s\n", buf);
+ else
+ printf(" module: %s\n", buf);
+ if (rdf_version == 1)
+ length -= ll + 1;
+ break;
+
+ case RDFREC_BSS: /* BSS reservation */
+ fread(&ll, 4, 1, infile);
+ printf(" bss reservation: %08"PRIx32" bytes\n", translateint32_t(ll));
+ if (rdf_version == 1)
+ length -= 5;
+ if (rdf_version > 1 && reclen != 4)
+ printf(" warning: reclen != 4\n");
+ break;
+
+ case RDFREC_COMMON:{
+ uint16_t seg, align;
+ uint32_t size;
+
+ fread(&seg, 2, 1, infile);
+ fread(&size, 4, 1, infile);
+ fread(&align, 2, 1, infile);
+ for (ll = 0; ll < reclen - 8; ll++)
+ fread(buf + ll, 1, 1, infile);
+ printf(" common: segment %04x = %s, %"PRId32":%d\n",
+ translateint16_t(seg), buf, translateint32_t(size),
+ translateint16_t(align));
+ break;
+ }
+
+ default:
+ printf(" unrecognized record (type %d", (int)t);
+ if (rdf_version > 1) {
+ printf(", length %d", (int)reclen);
+ fseek(infile, reclen, SEEK_CUR);
+ } else
+ length--;
+ printf(")\n");
+ }
+ if (rdf_version != 1)
+ length -= 2 + reclen;
+ }
+}
+
+int main(int argc, char **argv)
+{
+ char id[7];
+ int32_t l;
+ uint16_t s;
+ int verbose = 0;
+ int32_t offset;
+ int foundnullsegment = 0;
+ int version;
+ int32_t segmentcontentlength = 0;
+ int nsegments = 0;
+ int32_t headerlength = 0;
+ int32_t objectlength = 0;
+
+ printf("RDOFF dump utility, version %s\n", PROGRAM_VERSION);
+ printf("RDOFF2 revision %s\n", RDOFF2_REVISION);
+ puts("Copyright (c) 1996,99 Julian R Hall\n"
+ "Improvements and fixes (c) 2002-2004 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 (!infile) {
+ fprintf(stderr, "rdfdump: Could not open %s\n", argv[1]);
+ exit(1);
+ }
+
+ fread(id, 6, 1, infile);
+ if (strncmp(id, "RDOFF", 5)) {
+ fputs("rdfdump: File does not contain valid RDOFF header\n",
+ stderr);
+ exit(1);
+ }
+
+ printf("File %s: RDOFF version %c\n\n", argv[1], id[5]);
+ if (id[5] < '1' || id[5] > '2') {
+ fprintf(stderr, "rdfdump: unknown RDOFF version '%c'\n", id[5]);
+ exit(1);
+ }
+ version = id[5] - '0';
+
+ if (version > 1) {
+ fread(&l, 4, 1, infile);
+ objectlength = translateint32_t(l);
+ printf("Object content size: %"PRId32" bytes\n", objectlength);
+ }
+
+ fread(&l, 4, 1, infile);
+ headerlength = translateint32_t(l);
+ printf("Header (%"PRId32" bytes):\n", headerlength);
+ print_header(headerlength, version);
+
+ if (version == 1) {
+ fread(&l, 4, 1, infile);
+ l = translateint32_t(l);
+ printf("\nText segment length = %"PRId32" bytes\n", l);
+ offset = 0;
+ while (l--) {
+ fread(id, 1, 1, infile);
+ if (verbose) {
+ if (offset % 16 == 0)
+ printf("\n%08"PRIx32" ", offset);
+ printf(" %02x", (int)(uint8_t)id[0]);
+ offset++;
+ }
+ }
+ if (verbose)
+ printf("\n\n");
+
+ fread(&l, 4, 1, infile);
+ l = translateint32_t(l);
+ printf("Data segment length = %"PRId32" bytes\n", l);
+
+ if (verbose) {
+ offset = 0;
+ while (l--) {
+ fread(id, 1, 1, infile);
+ if (offset % 16 == 0)
+ printf("\n%08"PRIx32" ", offset);
+ printf(" %02x", (int)(uint8_t)id[0]);
+ offset++;
+ }
+ printf("\n");
+ }
+ } else {
+ do {
+ fread(&s, 2, 1, infile);
+ s = translateint16_t(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);
+ printf(" Number = %04X\n", (int)translateint16_t(s));
+ fread(&s, 2, 1, infile);
+ printf(" Resrvd = %04X\n", (int)translateint16_t(s));
+ fread(&l, 4, 1, infile);
+ l = translateint32_t(l);
+ printf(" Length = %"PRId32" bytes\n", l);
+ segmentcontentlength += l;
+
+ offset = 0;
+ while (l--) {
+ fread(id, 1, 1, infile);
+ if (verbose) {
+ if (offset % 16 == 0)
+ printf("\n%08"PRIx32" ", offset);
+ printf(" %02x", (int)(uint8_t)id[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: %"PRId32" 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 (%"PRId32") != "
+ "stored object length (%"PRId32")\n", l, objectlength);
+ }
+ fclose(infile);
+ return 0;
+}
diff --git a/rdoff/rdflib.1 b/rdoff/rdflib.1
new file mode 100644
index 0000000..bba1032
--- /dev/null
+++ b/rdoff/rdflib.1
@@ -0,0 +1,39 @@
+.TH RDFLIB 1 "September 6, 1999" "Debian Project" "Debian Manual"
+.SH NAME
+rdflib \- manage a library file for use with ldrdf(1)
+.SH SYNOPSIS
+.B rdflib
+.I command
+.I arguments
+.SH DESCRIPTION
+.B rdflib
+manages a library file which can be used by
+.BR ldrdf (1).
+It is supplied with a shell script
+.B makelib
+which should probably be used to create libraries.
+.SH COMMANDS
+.TP
+.BI c " library-file"
+Create (or truncate) a library.
+.TP
+.BI a " library-file object-file module"
+Add the
+.I object-file
+to the library under the name
+.IR module .
+.TP
+.BI x " library-file module object-file"
+Extract a
+.I module
+from the library to the file
+.IR object-file .
+.TP
+.B t " library-file"
+Display a list of modules in the library.
+.SH NOTES
+A remove command will be added soon.
+.SH AUTHORS
+Julian Hall <jules@earthcorp.com>.
+.PP
+This manual page was written by Matej Vela <vela@debian.org>.
diff --git a/rdoff/rdflib.c b/rdoff/rdflib.c
new file mode 100644
index 0000000..1213bea
--- /dev/null
+++ b/rdoff/rdflib.c
@@ -0,0 +1,428 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 1996-2009 The NASM Authors - All Rights Reserved
+ * See the file AUTHORS included with the NASM distribution for
+ * the specific copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * ----------------------------------------------------------------------- */
+
+/* rdflib - manipulate RDOFF library files (.rdl) */
+
+/*
+ * 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.
+ *
+ * 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 int32_t content size and a int32_t 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
+ * number, followed by the length of the directory, and then the
+ * 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 uint8_t type & version identifier followed by int32_t
+ * content size, followed by data.
+ */
+
+#include "compiler.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <inttypes.h>
+#include <time.h>
+#include <inttypes.h>
+
+/* functions supported:
+ * create a library (no extra operands required)
+ * add a module from a library (requires filename and name to give mod.)
+ * replace a module in a library (requires given name and filename)
+ * delete a module from a library (requires given name)
+ * extract a module from the library (requires given name and filename)
+ * list modules
+ */
+
+const char *usage =
+ "usage:\n"
+ " rdflib x libname [extra operands]\n\n"
+ " where x is one of:\n"
+ " c - create library\n"
+ " a - add module (operands = filename module-name)\n"
+ " x - extract (module-name filename)\n"
+ " 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;
+
+#define _ENDIANNESS 0 /* 0 for little, 1 for big */
+
+static void int32_ttolocal(int32_t *l)
+{
+#if _ENDIANNESS
+ uint8_t t;
+ uint8_t *p = (uint8_t *)l;
+
+ t = p[0];
+ p[0] = p[3];
+ p[3] = t;
+ t = p[1];
+ p[1] = p[2];
+ p[2] = p[1];
+#else
+ (void)l; /* placate optimizers */
+#endif
+}
+
+char copybytes(FILE * fp, FILE * fp2, int n)
+{
+ int i, t = 0;
+
+ for (i = 0; i < n; i++) {
+ t = fgetc(fp);
+ if (t == EOF) {
+ fprintf(stderr, "rdflib: premature end of file in '%s'\n",
+ _argv[2]);
+ exit(1);
+ }
+ if (fp2)
+ if (fputc(t, fp2) == EOF) {
+ fprintf(stderr, "rdflib: write error\n");
+ exit(1);
+ }
+ }
+ return (char)t; /* return last char read */
+}
+
+int32_t copyint32_t(FILE * fp, FILE * fp2)
+{
+ int32_t l;
+ int i, t;
+ uint8_t *p = (uint8_t *)&l;
+
+ for (i = 0; i < 4; i++) { /* skip magic no */
+ t = fgetc(fp);
+ if (t == EOF) {
+ fprintf(stderr, "rdflib: premature end of file in '%s'\n",
+ _argv[2]);
+ exit(1);
+ }
+ if (fp2)
+ if (fputc(t, fp2) == EOF) {
+ fprintf(stderr, "rdflib: write error\n");
+ exit(1);
+ }
+ *p++ = t;
+ }
+ int32_ttolocal(&l);
+ return l;
+}
+
+int main(int argc, char **argv)
+{
+ FILE *fp, *fp2 = NULL, *fptmp;
+ char *p, buf[256], c;
+ int i;
+ int32_t l;
+ time_t t;
+ char rdbuf[10];
+
+ _argv = argv;
+
+ if (argc < 3 || !strncmp(argv[1], "-h", 2)
+ || !strncmp(argv[1], "--h", 3)) {
+ fputs(usage, stdout);
+ exit(1);
+ }
+
+ switch (argv[1][0]) {
+ case 'c': /* create library */
+ fp = fopen(argv[2], "wb");
+ if (!fp) {
+ fprintf(stderr, "rdflib: could not open '%s'\n", argv[2]);
+ 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;
+
+ case 'a': /* add module */
+ if (argc < 5) {
+ fprintf(stderr, "rdflib: required parameter missing\n");
+ exit(1);
+ }
+ fp = fopen(argv[2], "ab");
+ if (!fp) {
+ fprintf(stderr, "rdflib: could not open '%s'\n", argv[2]);
+ perror("rdflib");
+ exit(1);
+ }
+
+ fp2 = fopen(argv[3], "rb");
+ if (!fp2) {
+ fprintf(stderr, "rdflib: could not open '%s'\n", argv[3]);
+ perror("rdflib");
+ exit(1);
+ }
+
+ p = argv[4];
+ do {
+ if (fputc(*p, fp) == EOF) {
+ fprintf(stderr, "rdflib: write error\n");
+ exit(1);
+ }
+ } while (*p++);
+
+ while (!feof(fp2)) {
+ i = fgetc(fp2);
+ if (i == EOF) {
+ break;
+ }
+
+ if (fputc(i, fp) == EOF) {
+ fprintf(stderr, "rdflib: write error\n");
+ exit(1);
+ }
+ }
+ fclose(fp2);
+ fclose(fp);
+ break;
+
+ case 'x':
+ if (argc < 5) {
+ fprintf(stderr, "rdflib: required parameter missing\n");
+ exit(1);
+ }
+ case 't':
+ fp = fopen(argv[2], "rb");
+ if (!fp) {
+ fprintf(stderr, "rdflib: could not open '%s'\n", argv[2]);
+ perror("rdflib");
+ exit(1);
+ }
+
+ fp2 = NULL;
+ while (!feof(fp)) {
+ /* read name */
+ p = buf;
+ while ((*(p++) = (char)fgetc(fp)))
+ if (feof(fp))
+ break;
+
+ if (feof(fp))
+ break;
+
+ fp2 = NULL;
+ if (argv[1][0] == 'x') {
+ /* check against desired name */
+ if (!strcmp(buf, argv[3])) {
+ fp2 = fopen(argv[4], "wb");
+ if (!fp2) {
+ fprintf(stderr, "rdflib: could not open '%s'\n",
+ argv[4]);
+ perror("rdflib");
+ exit(1);
+ }
+ }
+ } else
+ printf("%-40s ", buf);
+
+ /* step over the RDOFF file, extracting type information for
+ * the listing, and copying it if fp2 != NULL */
+
+ if (buf[0] == '.') {
+
+ if (argv[1][0] == 't')
+ for (i = 0; i < 6; i++)
+ printf("%c", copybytes(fp, fp2, 1));
+ else
+ copybytes(fp, fp2, 6);
+
+ l = copyint32_t(fp, fp2);
+
+ if (argv[1][0] == 't')
+ printf(" %"PRId32" bytes content\n", l);
+
+ copybytes(fp, fp2, l);
+ } else if ((c = copybytes(fp, fp2, 6)) >= '2') { /* version 2 or above */
+ l = copyint32_t(fp, fp2);
+
+ if (argv[1][0] == 't')
+ printf("RDOFF%c %"PRId32" bytes content\n", c, l);
+ copybytes(fp, fp2, l); /* entire object */
+ } else {
+ if (argv[1][0] == 't')
+ printf("RDOFF1\n");
+ /*
+ * version 1 object, so we don't have an object content
+ * length field.
+ */
+ copybytes(fp, fp2, copyint32_t(fp, fp2)); /* header */
+ copybytes(fp, fp2, copyint32_t(fp, fp2)); /* text */
+ copybytes(fp, fp2, copyint32_t(fp, fp2)); /* data */
+ }
+
+ if (fp2)
+ break;
+ }
+ fclose(fp);
+ if (fp2)
+ fclose(fp2);
+ else if (argv[1][0] == 'x') {
+ fprintf(stderr, "rdflib: module '%s' not found in '%s'\n",
+ argv[3], argv[2]);
+ exit(1);
+ }
+ break;
+
+ case 'r': /* replace module */
+ argc--;
+ case 'd': /* delete module */
+ if (argc < 4) {
+ fprintf(stderr, "rdflib: required parameter missing\n");
+ exit(1);
+ }
+
+ fp = fopen(argv[2], "rb");
+ if (!fp) {
+ fprintf(stderr, "rdflib: could not open '%s'\n", argv[2]);
+ perror("rdflib");
+ exit(1);
+ }
+
+ if (argv[1][0] == 'r') {
+ fp2 = fopen(argv[4], "rb");
+ if (!fp2) {
+ fprintf(stderr, "rdflib: could not open '%s'\n", argv[4]);
+ perror("rdflib");
+ exit(1);
+ }
+ }
+
+ fptmp = tmpfile();
+ if (!fptmp) {
+ fprintf(stderr, "rdflib: could not open temporary file\n");
+ perror("rdflib");
+ exit(1);
+ }
+
+ /* copy library into temporary file */
+ fseek(fp, 0, SEEK_END); /* get file length */
+ l = ftell(fp);
+ fseek(fp, 0, SEEK_SET);
+ copybytes(fp, fptmp, l);
+ rewind(fptmp);
+ freopen(argv[2], "wb", fp);
+
+ while (!feof(fptmp)) {
+ /* read name */
+ p = buf;
+ while ((*(p++) = (char)fgetc(fptmp)))
+ if (feof(fptmp))
+ break;
+
+ if (feof(fptmp))
+ break;
+
+ /* check against desired name */
+ if (!strcmp(buf, argv[3])) {
+ fread(p = rdbuf, 1, sizeof(rdbuf), fptmp);
+ l = *(int32_t *)(p + 6);
+ fseek(fptmp, l, SEEK_CUR);
+ break;
+ } else {
+ fwrite(buf, 1, strlen(buf) + 1, fp); /* module name */
+ if ((c = copybytes(fptmp, fp, 6)) >= '2') {
+ l = copyint32_t(fptmp, fp); /* version 2 or above */
+ copybytes(fptmp, fp, l); /* entire object */
+ }
+ }
+ }
+
+ if (argv[1][0] == 'r') {
+ /* copy new module into library */
+ p = argv[3];
+ do {
+ if (fputc(*p, fp) == EOF) {
+ fprintf(stderr, "rdflib: write error\n");
+ exit(1);
+ }
+ } while (*p++);
+
+ while (!feof(fp2)) {
+ i = fgetc(fp2);
+ if (i == EOF) {
+ break;
+ }
+ if (fputc(i, fp) == EOF) {
+ fprintf(stderr, "rdflib: write error\n");
+ exit(1);
+ }
+ }
+ fclose(fp2);
+ }
+
+ /* copy rest of library if any */
+ while (!feof(fptmp)) {
+ i = fgetc(fptmp);
+ if (i == EOF) {
+ break;
+ }
+
+ if (fputc(i, fp) == EOF) {
+ fprintf(stderr, "rdflib: write error\n");
+ exit(1);
+ }
+ }
+
+ fclose(fp);
+ fclose(fptmp);
+ break;
+
+ default:
+ fprintf(stderr, "rdflib: command '%c' not recognized\n",
+ argv[1][0]);
+ exit(1);
+ }
+ return 0;
+}
diff --git a/rdoff/rdfload.c b/rdoff/rdfload.c
new file mode 100644
index 0000000..4fd3dbd
--- /dev/null
+++ b/rdoff/rdfload.c
@@ -0,0 +1,212 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 1996-2009 The NASM Authors - All Rights Reserved
+ * See the file AUTHORS included with the NASM distribution for
+ * the specific copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * rdfload.c RDOFF Object File loader library
+ */
+
+/*
+ * TODO: this has been modified from previous version only in very
+ * simplistic ways. Needs to be improved drastically, especially:
+ * - support for more than the 2 standard segments
+ * - support for segment relocations (hard to do in ANSI C)
+ */
+
+#include "compiler.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "rdfload.h"
+#include "symtab.h"
+#include "collectn.h"
+
+extern int rdf_errno;
+
+rdfmodule *rdfload(const char *filename)
+{
+ rdfmodule *f;
+ int32_t bsslength = 0;
+ char *hdr;
+ rdfheaderrec *r;
+
+ f = malloc(sizeof(rdfmodule));
+ if (f == NULL) {
+ rdf_errno = RDF_ERR_NOMEM;
+ return NULL;
+ }
+
+ f->symtab = symtabNew();
+ if (!f->symtab) {
+ free(f);
+ rdf_errno = RDF_ERR_NOMEM;
+ return NULL;
+ }
+
+ /* open the file */
+ if (rdfopen(&(f->f), filename)) {
+ free(f);
+ return NULL;
+ }
+
+ /* read in text and data segments, and header */
+
+ f->t = malloc(f->f.seg[0].length);
+ f->d = malloc(f->f.seg[1].length); /* BSS seg allocated later */
+ hdr = malloc(f->f.header_len);
+
+ if (!f->t || !f->d || !hdr) {
+ rdf_errno = RDF_ERR_NOMEM;
+ rdfclose(&f->f);
+ if (f->t)
+ free(f->t);
+ if (f->d)
+ free(f->d);
+ free(f);
+ return NULL;
+ }
+
+ if (rdfloadseg(&f->f, RDOFF_HEADER, hdr) ||
+ rdfloadseg(&f->f, RDOFF_CODE, f->t) ||
+ rdfloadseg(&f->f, RDOFF_DATA, f->d)) {
+ rdfclose(&f->f);
+ free(f->t);
+ free(f->d);
+ free(f);
+ free(hdr);
+ return NULL;
+ }
+
+ rdfclose(&f->f);
+
+ /* Allocate BSS segment; step through header and count BSS records */
+
+ while ((r = rdfgetheaderrec(&f->f))) {
+ if (r->type == 5)
+ bsslength += r->b.amount;
+ }
+
+ f->b = malloc(bsslength);
+ if (bsslength && (!f->b)) {
+ free(f->t);
+ free(f->d);
+ free(f);
+ free(hdr);
+ rdf_errno = RDF_ERR_NOMEM;
+ return NULL;
+ }
+
+ rdfheaderrewind(&f->f);
+
+ f->textrel = (int32_t)(size_t)f->t;
+ f->datarel = (int32_t)(size_t)f->d;
+ f->bssrel = (int32_t)(size_t)f->b;
+
+ return f;
+}
+
+int rdf_relocate(rdfmodule * m)
+{
+ rdfheaderrec *r;
+ Collection imports;
+ symtabEnt e;
+ int32_t rel;
+ uint8_t *seg;
+
+ rdfheaderrewind(&m->f);
+ collection_init(&imports);
+
+ while ((r = rdfgetheaderrec(&m->f))) {
+ switch (r->type) {
+ case 1: /* Relocation record */
+
+ /* calculate relocation factor */
+
+ if (r->r.refseg == 0)
+ rel = m->textrel;
+ else if (r->r.refseg == 1)
+ rel = m->datarel;
+ else if (r->r.refseg == 2)
+ rel = m->bssrel;
+ else
+ /* We currently do not support load-time linkage.
+ This should be added some time soon... */
+
+ return 1; /* return error code */
+
+ if ((r->r.segment & 63) == 0)
+ seg = m->t;
+ else if ((r->r.segment & 63) == 1)
+ seg = m->d;
+ else
+ continue; /* relocation not in a loaded segment */
+
+ /* it doesn't matter in this case that the code is non-portable,
+ as the entire concept of executing a module like this is
+ non-portable */
+ switch (r->r.length) {
+ case 1:
+ seg[r->r.offset] += (char)rel;
+ break;
+ case 2:
+ *(uint16_t *) (seg + r->r.offset) += (uint16_t) rel;
+ break;
+ case 4:
+ *(int32_t *)(seg + r->r.offset) += rel;
+ break;
+ }
+ break;
+
+ case 3: /* export record - add to symtab */
+ e.segment = r->e.segment;
+ e.offset = r->e.offset + (e.segment == 0 ? m->textrel : /* 0 -> code */
+ e.segment == 1 ? m->datarel : /* 1 -> data */
+ m->bssrel); /* 2 -> bss */
+ e.flags = 0;
+ e.name = malloc(strlen(r->e.label) + 1);
+ if (!e.name)
+ return 1;
+
+ strcpy(e.name, r->e.label);
+ symtabInsert(m->symtab, &e);
+ break;
+
+ case 6: /* segment relocation */
+ fprintf(stderr, "%s: segment relocation not supported by this "
+ "loader\n", m->f.name);
+ return 1;
+ }
+ }
+ return 0;
+}
diff --git a/rdoff/rdfload.h b/rdoff/rdfload.h
new file mode 100644
index 0000000..87d7ecc
--- /dev/null
+++ b/rdoff/rdfload.h
@@ -0,0 +1,31 @@
+/* rdfload.h RDOFF Object File loader library header file
+ *
+ * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
+ * Julian Hall. All rights reserved. The software is
+ * redistributable under the license given in the file "LICENSE"
+ * distributed in the NASM archive.
+ *
+ * See the file 'rdfload.c' for special license information for this
+ * file.
+ */
+
+#ifndef RDOFF_RDFLOAD_H
+#define RDOFF_RDFLOAD_H 1
+
+#define RDOFF_UTILS
+
+#include "rdoff.h"
+
+typedef struct RDFModuleStruct {
+ rdffile f; /* file structure */
+ uint8_t *t, *d, *b; /* text, data, and bss segments */
+ uint32_t textrel;
+ uint32_t datarel;
+ uint32_t bssrel;
+ void *symtab;
+} rdfmodule;
+
+rdfmodule *rdfload(const char *filename);
+int rdf_relocate(rdfmodule * m);
+
+#endif
diff --git a/rdoff/rdlar.c b/rdoff/rdlar.c
new file mode 100644
index 0000000..98b0f8f
--- /dev/null
+++ b/rdoff/rdlar.c
@@ -0,0 +1,490 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 1996-2009 The NASM Authors - All Rights Reserved
+ * See the file AUTHORS included with the NASM distribution for
+ * the specific copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * rdlar.c - new librarian/archiver for RDOFF2.
+ */
+
+#include "compiler.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <stdarg.h>
+#include <string.h>
+#include <errno.h>
+#include <time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "rdlar.h"
+
+#define PROGRAM_VERSION "0.1"
+
+/** Constants **/
+const char commands[] = "adnrtx";
+const char modifiers[] = "cflouvV";
+
+/** Global variables **/
+char *progname = "rdlar";
+char **_argv = NULL;
+struct {
+ bool createok;
+ bool usefname;
+ bool align;
+ bool odate;
+ bool fresh;
+ int verbose;
+} options = {
+0, 0, 0, 0, 0, 0};
+
+#define _ENDIANNESS 0 /* 0 for little, 1 for big */
+
+/*
+ * Convert int32_t to little endian (if we were compiled on big-endian machine)
+ */
+static void int32_ttolocal(int32_t *l)
+{
+#if _ENDIANNESS
+ uint8_t t;
+ uint8_t *p = (uint8_t *)l;
+
+ t = p[0];
+ p[0] = p[3];
+ p[3] = t;
+ t = p[1];
+ p[1] = p[2];
+ p[2] = p[1];
+#endif
+}
+
+/*
+ * Print version information
+ */
+void show_version(void)
+{
+ puts("New RDOFF2 librarian/archiver, version " PROGRAM_VERSION);
+}
+
+/*
+ * Print usage instructions
+ */
+void usage(void)
+{
+ printf("Usage: %s [-]{%s}[%s] libfile [module-name] [files]\n",
+ progname, commands, modifiers);
+ puts(" commands:\n"
+ " a - add module(s) to the library\n"
+ " d - delete module(s) from the library\n"
+ " n - create the library\n"
+ " r - replace module(s)\n"
+ " t - display contents of library\n"
+ " x - extract module(s)\n"
+ " command specific modifiers:\n"
+ " o - preserve original dates\n"
+ " u - only replace modules that are newer than library contents\n"
+ " generic modifiers:\n"
+ " c - do not warn if the library had to be created\n"
+ " f - use file name as a module name\n"
+ " v - be verbose\n"
+ " V - display version information");
+}
+
+/*
+ * Print an error message and exit
+ */
+void error_exit(int errcode, bool useperror, const char *fmt, ...)
+{
+ va_list ap;
+
+ fprintf(stderr, "%s: ", progname);
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ putc('\n', stderr);
+ if (useperror)
+ perror(progname);
+ exit(errcode);
+}
+
+/*
+ * Fill in and write a header
+ */
+void put_header(struct rdlm_hdr *hdr, FILE * libfp, char *modname)
+{
+ int n = 0;
+
+ hdr->hdrsize = sizeof(*hdr);
+ if (modname)
+ hdr->hdrsize += (n = strlen(modname) + 1);
+ if (libfp == NULL)
+ return;
+ if (fwrite(hdr, 1, sizeof(*hdr), libfp) != sizeof(*hdr) ||
+ (modname && (fwrite(modname, 1, n, libfp) != n)))
+ error_exit(3, true, "could not write header");
+}
+
+/*
+ * Copy n bytes from one file to another and return last character read.
+ */
+char copybytes(FILE * fp, FILE * fp2, int n)
+{
+ int i, t = 0;
+
+ for (i = 0; i < n; i++) {
+ t = fgetc(fp);
+ if (t == EOF)
+ error_exit(1, false, "premature end of file in '%s'",
+ _argv[2]);
+ if (fp2)
+ if (fputc(t, fp2) == EOF)
+ error_exit(1, false, "write error");
+ }
+ return (char)t;
+}
+
+/*
+ * Copy uint32_t from one file to another.
+ * Return local presentation of int32_t.
+ */
+int32_t copyint32_t(FILE * fp, FILE * fp2)
+{
+ int32_t l;
+ int i, t;
+ uint8_t *p = (uint8_t *)&l;
+
+ for (i = 0; i < 4; i++) {
+ t = fgetc(fp);
+ if (t == EOF)
+ error_exit(1, false, "premature end of file in '%s'",
+ _argv[2]);
+ if (fp2)
+ if (fputc(t, fp2) == EOF)
+ error_exit(1, false, "write error");
+ *p++ = t;
+ }
+ int32_ttolocal(&l);
+ return l;
+}
+
+/*
+ * Create a new library
+ */
+int create_library(char *libname)
+{
+ FILE *libfp;
+ struct rdlm_hdr hdr;
+
+ hdr.magic = RDLAMAG;
+ hdr.hdrsize = 0;
+ hdr.date = time(NULL);
+ hdr.owner = getuid();
+ hdr.group = getgid();
+ hdr.mode = umask(022);
+ hdr.size = 0;
+
+ libfp = fopen(libname, "wb");
+ if (!libfp)
+ error_exit(1, true, "could not open '%s'\n", libname);
+
+ /* Write library header */
+ put_header(&hdr, libfp, NULL);
+
+ fclose(libfp);
+ return true;
+}
+
+/*
+ * Add a module to the library
+ */
+int add_module(FILE * libfp, const char *fname, char *modname)
+{
+ FILE *modfp;
+ struct rdlm_hdr hdr = { RDLMMAG, 0, 0, 0, 0, 0, 0 };
+ struct stat finfo;
+ int i;
+
+ if (options.verbose)
+ fprintf(stderr, "adding module %s\n", modname);
+
+ /* Initialize some fields in the module header */
+ if (stat(fname, &finfo) < 0)
+ error_exit(1, true, "could not stat '%s'", fname);
+ hdr.date = finfo.st_mtime;
+ hdr.owner = finfo.st_uid;
+ hdr.group = finfo.st_gid;
+ hdr.size = finfo.st_size;
+
+ modfp = fopen(fname, "rb");
+ if (!modfp)
+ error_exit(1, true, "could not open '%s'", fname);
+
+ /* Write module header */
+ put_header(&hdr, libfp, modname);
+
+ /* Put the module itself */
+ while (!feof(modfp)) {
+ i = fgetc(modfp);
+ if (i == EOF)
+ break;
+ if (fputc(i, libfp) == EOF)
+ error_exit(1, false, "write error");
+ }
+
+ fclose(modfp);
+ return true;
+}
+
+/*
+ * Main
+ */
+int main(int argc, char **argv)
+{
+ FILE *libfp, *tmpfp, *modfp = NULL;
+ struct stat finfo;
+ struct rdlm_hdr hdr;
+ char buf[MAXMODNAMELEN], *p = NULL;
+ char c;
+ int i;
+
+ progname = argv[0];
+ _argv = argv;
+
+ if (argc < 2) {
+ usage();
+ exit(1);
+ }
+
+ /* Check whether some modifiers were specified */
+ for (i = 1; i < strlen(argv[1]); i++) {
+ switch (c = argv[1][i]) {
+ case 'c':
+ options.createok = true;
+ break;
+ case 'f':
+ options.usefname = true;
+ break;
+ case 'l':
+ options.align = true;
+ break;
+ case 'o':
+ options.odate = true;
+ break;
+ case 'u':
+ options.fresh = true;
+ break;
+ case 'v':
+ options.verbose++;
+ break;
+ case 'V':
+ show_version();
+ exit(0);
+ default:
+ if (strchr(commands, c) == NULL)
+ error_exit(2, false, "invalid command or modifier '%c'",
+ c);
+ }
+ }
+
+ if (argc < 3)
+ error_exit(2, false, "missing library name");
+
+ /* Process the command */
+ if (argv[1][0] == '-')
+ argv[1]++;
+ switch (c = argv[1][0]) {
+ case 'a': /* add a module */
+ if (argc < 4 || (!options.usefname && argc != 5))
+ error_exit(2, false, "invalid number of arguments");
+
+ /* Check if a library already exists. If not - create it */
+ if (access(argv[2], F_OK) < 0) {
+ if (!options.createok)
+ fprintf(stderr, "creating library %s\n", argv[2]);
+ create_library(argv[2]);
+ }
+
+ libfp = fopen(argv[2], "ab");
+ if (!libfp)
+ error_exit(1, true, "could not open '%s'", argv[2]);
+
+ if (!options.usefname)
+ add_module(libfp, argv[4], argv[3]);
+ else
+ for (i = 3; i < argc; i++)
+ add_module(libfp, argv[i], argv[i]);
+
+ fclose(libfp);
+ break;
+
+ case 'n': /* create library */
+ create_library(argv[2]);
+ break;
+
+ case 'x': /* extract module(s) */
+ if (!options.usefname)
+ argc--;
+ if (argc < 4)
+ error_exit(2, false, "required parameter missing");
+ p = options.usefname ? argv[3] : argv[4];
+ case 't': /* list library contents */
+ libfp = fopen(argv[2], "rb");
+ if (!libfp)
+ error_exit(1, true, "could not open '%s'\n", argv[2]);
+
+ /* Read library header */
+ if (fread(&hdr, 1, sizeof(hdr), libfp) != sizeof(hdr) ||
+ hdr.magic != RDLAMAG)
+ error_exit(1, false, "invalid library format");
+
+ /* Walk through the library looking for requested module */
+ while (!feof(libfp)) {
+ /* Read module header */
+ i = fread(&hdr, 1, sizeof(hdr), libfp);
+ if (feof(libfp))
+ break;
+ if (i != sizeof(hdr) || hdr.magic != RDLMMAG)
+ error_exit(1, false, "invalid module header");
+ /* Read module name */
+ i = hdr.hdrsize - sizeof(hdr);
+ if (i > sizeof(buf) || fread(buf, 1, i, libfp) != i)
+ error_exit(1, false, "invalid module name");
+ if (c == 'x') {
+ /* Check against desired name */
+ if (!strcmp(buf, argv[3])) {
+ if (options.verbose)
+ fprintf(stderr,
+ "extracting module %s to file %s\n", buf,
+ p);
+ modfp = fopen(p, "wb");
+ if (!modfp)
+ error_exit(1, true, "could not open '%s'", p);
+ }
+ } else {
+ printf("%-40s ", buf);
+ if (options.verbose) {
+ printf("%ld bytes", hdr.size);
+ }
+ putchar('\n');
+ }
+
+ copybytes(libfp, modfp, hdr.size);
+ if (modfp)
+ break;
+ }
+
+ fclose(libfp);
+ if (modfp)
+ fclose(modfp);
+ else if (c == 'x')
+ error_exit(1, false, "module '%s' not found in '%s'",
+ argv[3], argv[2]);
+ break;
+
+ case 'r': /* replace module(s) */
+ argc--;
+ if (stat(argv[4], &finfo) < 0)
+ error_exit(1, true, "could not stat '%s'", argv[4]);
+ case 'd': /* delete module(s) */
+ if (argc < 4)
+ error_exit(2, false, "required parameter missing");
+
+ libfp = fopen(argv[2], "rb");
+ if (!libfp)
+ error_exit(1, true, "could not open '%s'", argv[2]);
+
+ /* Copy the library into a temporary file */
+ tmpfp = tmpfile();
+ if (!tmpfp)
+ error_exit(1, true, "could not open temporary file");
+
+ stat(argv[2], &finfo);
+ copybytes(libfp, tmpfp, finfo.st_size);
+ rewind(tmpfp);
+ freopen(argv[2], "wb", libfp);
+
+ /* Read library header and write it to a new file */
+ if (fread(&hdr, 1, sizeof(hdr), tmpfp) != sizeof(hdr) ||
+ hdr.magic != RDLAMAG)
+ error_exit(1, false, "invalid library format");
+ put_header(&hdr, libfp, NULL);
+
+ /* Walk through the library looking for requested module */
+ while (!feof(tmpfp)) {
+ /* Read module header */
+ if (fread(&hdr, 1, sizeof(hdr), tmpfp) != sizeof(hdr) ||
+ hdr.magic != RDLMMAG)
+ error_exit(1, false, "invalid module header");
+ /* Read module name */
+ i = hdr.hdrsize - sizeof(hdr);
+ if (i > sizeof(buf) || fread(buf, 1, i, tmpfp) != i)
+ error_exit(1, false, "invalid module name");
+ /* Check against desired name */
+ if (!strcmp(buf, argv[3]) &&
+ (c == 'd' || !options.odate
+ || finfo.st_mtime <= hdr.date)) {
+ if (options.verbose)
+ fprintf(stderr, "deleting module %s\n", buf);
+ fseek(tmpfp, hdr.size, SEEK_CUR);
+ break;
+ } else {
+ put_header(&hdr, libfp, buf);
+ copybytes(tmpfp, libfp, hdr.size);
+ }
+ }
+
+ if (c == 'r') {
+ /* Copy new module into library */
+ p = options.usefname ? argv[4] : argv[3];
+ add_module(libfp, argv[4], p);
+ }
+
+ /* Copy rest of library if any */
+ while (!feof(tmpfp)) {
+ if ((i = fgetc(tmpfp)) == EOF)
+ break;
+
+ if (fputc(i, libfp) == EOF)
+ error_exit(1, false, "write error");
+ }
+
+ fclose(libfp);
+ fclose(tmpfp);
+ break;
+
+ default:
+ error_exit(2, false, "invalid command '%c'\n", c);
+ }
+
+ return 0;
+}
diff --git a/rdoff/rdlar.h b/rdoff/rdlar.h
new file mode 100644
index 0000000..ee00f2e
--- /dev/null
+++ b/rdoff/rdlar.h
@@ -0,0 +1,38 @@
+/*
+ * rdlar.h - definitions of new RDOFF library/archive format.
+ */
+
+#ifndef RDOFF_RDLAR_H
+#define RDOFF_RDLAR_H 1
+
+#include <inttypes.h>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/* For non-POSIX operating systems */
+#ifndef HAVE_GETUID
+# define getuid() 0
+#endif
+#ifndef HAVE_GETGID
+# define getgid() 0
+#endif
+
+#define RDLAMAG 0x414C4452 /* Archive magic */
+#define RDLMMAG 0x4D4C4452 /* Member magic */
+
+#define MAXMODNAMELEN 256 /* Maximum length of module name */
+
+struct rdlm_hdr {
+ uint32_t magic; /* Must be RDLAMAG */
+ uint32_t hdrsize; /* Header size + sizeof(module_name) */
+ uint32_t date; /* Creation date */
+ uint32_t owner; /* UID */
+ uint32_t group; /* GID */
+ uint32_t mode; /* File mode */
+ uint32_t size; /* File size */
+ /* NULL-terminated module name immediately follows */
+};
+
+#endif
diff --git a/rdoff/rdlib.c b/rdoff/rdlib.c
new file mode 100644
index 0000000..31dbdb4
--- /dev/null
+++ b/rdoff/rdlib.c
@@ -0,0 +1,296 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 1996-2009 The NASM Authors - All Rights Reserved
+ * See the file AUTHORS included with the NASM distribution for
+ * the specific copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * rdlib.c - routines for manipulating RDOFF libraries (.rdl)
+ */
+
+#include "compiler.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define RDOFF_UTILS
+
+#include "rdoff.h"
+#include "rdlib.h"
+#include "rdlar.h"
+
+/* See Texinfo documentation about new RDOFF libraries format */
+
+int rdl_error = 0;
+
+char *rdl_errors[5] = {
+ "no error", "could not open file", "invalid file structure",
+ "file contains modules of an unsupported RDOFF version",
+ "module not found"
+};
+
+int rdl_verify(const char *filename)
+{
+ FILE *fp = fopen(filename, "rb");
+ char buf[257];
+ int i;
+ int32_t length;
+ static char lastverified[256];
+ static int lastresult = -1;
+
+ if (lastresult != -1 && !strcmp(filename, lastverified))
+ return lastresult;
+
+ strcpy(lastverified, filename);
+
+ if (!fp)
+ return (rdl_error = lastresult = 1);
+
+ while (!feof(fp)) {
+ i = 0;
+
+ while (fread(buf + i, 1, 1, fp) == 1 && buf[i] && i < 257)
+ i++;
+ if (feof(fp))
+ break;
+
+ if (buf[0] == '.') {
+ /*
+ * A special module, eg a signature block or a directory.
+ * Format of such a module is defined to be:
+ * six char type identifier
+ * int32_t count bytes content
+ * content
+ * 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;
+ }
+ }
+ fread(&length, 4, 1, fp);
+ fseek(fp, length, SEEK_CUR); /* skip over the module */
+ }
+ fclose(fp);
+ return lastresult = 0; /* library in correct format */
+}
+
+int rdl_open(struct librarynode *lib, const char *name)
+{
+ int i = rdl_verify(name);
+ if (i)
+ return i;
+
+ lib->fp = NULL;
+ lib->name = strdup(name);
+ lib->referenced = 0;
+ lib->next = NULL;
+ return 0;
+}
+
+void rdl_close(struct librarynode *lib)
+{
+ if (lib->fp)
+ fclose(lib->fp);
+ free(lib->name);
+}
+
+int rdl_searchlib(struct librarynode *lib, const char *label, rdffile * f)
+{
+ char buf[512];
+ int i, t;
+ void *hdr;
+ rdfheaderrec *r;
+ int32_t l;
+
+ rdl_error = 0;
+ lib->referenced++;
+
+ if (!lib->fp) {
+ lib->fp = fopen(lib->name, "rb");
+
+ if (!lib->fp) {
+ rdl_error = 1;
+ return 0;
+ }
+ } else
+ rewind(lib->fp);
+
+ while (!feof(lib->fp)) {
+ /*
+ * read the module name from the file, and prepend
+ * the library name and '.' to it.
+ */
+ strcpy(buf, lib->name);
+
+ i = strlen(lib->name);
+ buf[i++] = '.';
+ t = i;
+ while (fread(buf + i, 1, 1, lib->fp) == 1 && buf[i] && i < 512)
+ i++;
+
+ buf[i] = 0;
+
+ if (feof(lib->fp))
+ break;
+ if (!strcmp(buf + t, ".dir")) { /* skip over directory */
+ fread(&l, 4, 1, lib->fp);
+ fseek(lib->fp, l, SEEK_CUR);
+ continue;
+ }
+ /*
+ * open the RDOFF module
+ */
+ if (rdfopenhere(f, lib->fp, &lib->referenced, buf)) {
+ rdl_error = 16 * rdf_errno;
+ return 0;
+ }
+ /*
+ * read in the header, and scan for exported symbols
+ */
+ hdr = malloc(f->header_len);
+ rdfloadseg(f, RDOFF_HEADER, hdr);
+
+ while ((r = rdfgetheaderrec(f))) {
+ if (r->type != 3) /* not an export */
+ continue;
+
+ if (!strcmp(r->e.label, label)) { /* match! */
+ free(hdr); /* reset to 'just open' */
+ f->header_loc = NULL; /* state... */
+ f->header_fp = 0;
+ return 1;
+ }
+ }
+
+ /* find start of next module... */
+ i = f->eof_offset;
+ rdfclose(f);
+ fseek(lib->fp, i, SEEK_SET);
+ }
+
+ /*
+ * close the file if nobody else is using it
+ */
+ lib->referenced--;
+ if (!lib->referenced) {
+ fclose(lib->fp);
+ lib->fp = NULL;
+ }
+ return 0;
+}
+
+int rdl_openmodule(struct librarynode *lib, int moduleno, rdffile * f)
+{
+ char buf[512];
+ int i, cmod, t;
+ int32_t length;
+
+ lib->referenced++;
+
+ if (!lib->fp) {
+ lib->fp = fopen(lib->name, "rb");
+ if (!lib->fp) {
+ lib->referenced--;
+ return (rdl_error = 1);
+ }
+ } else
+ rewind(lib->fp);
+
+ cmod = -1;
+ while (!feof(lib->fp)) {
+ strcpy(buf, lib->name);
+ i = strlen(buf);
+ buf[i++] = '.';
+ t = i;
+ while (fread(buf + i, 1, 1, lib->fp) == 1 && buf[i] && i < 512)
+ i++;
+ buf[i] = 0;
+ if (feof(lib->fp))
+ break;
+
+ if (buf[t] != '.') /* special module - not counted in the numbering */
+ cmod++; /* of RDOFF modules - must be referred to by name */
+
+ if (cmod == moduleno) {
+ rdl_error = 16 *
+ rdfopenhere(f, lib->fp, &lib->referenced, buf);
+ lib->referenced--;
+ if (!lib->referenced) {
+ fclose(lib->fp);
+ lib->fp = NULL;
+ }
+ return rdl_error;
+ }
+
+ fread(buf, 6, 1, lib->fp);
+ buf[6] = 0;
+ if (buf[t] == '.') {
+ /* do nothing */
+ } else if (strncmp(buf, "RDOFF", 5)) {
+ if (!--lib->referenced) {
+ fclose(lib->fp);
+ lib->fp = NULL;
+ }
+ return rdl_error = 2;
+ } else if (buf[5] != '2') {
+ if (!--lib->referenced) {
+ fclose(lib->fp);
+ lib->fp = NULL;
+ }
+ return rdl_error = 3;
+ }
+
+ fread(&length, 4, 1, lib->fp);
+ fseek(lib->fp, length, SEEK_CUR); /* skip over the module */
+ }
+ if (!--lib->referenced) {
+ fclose(lib->fp);
+ lib->fp = NULL;
+ }
+ return rdl_error = 4; /* module not found */
+}
+
+void rdl_perror(const char *apname, const char *filename)
+{
+ if (rdl_error >= 16)
+ rdfperror(apname, filename);
+ else
+ fprintf(stderr, "%s:%s:%s\n", apname, filename,
+ rdl_errors[rdl_error]);
+}
diff --git a/rdoff/rdlib.h b/rdoff/rdlib.h
new file mode 100644
index 0000000..e1b3c5a
--- /dev/null
+++ b/rdoff/rdlib.h
@@ -0,0 +1,62 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 1996-2009 The NASM Authors - All Rights Reserved
+ * See the file AUTHORS included with the NASM distribution for
+ * the specific copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * rdlib.h Functions for manipulating libraries of RDOFF object files.
+ */
+
+#ifndef RDOFF_RDLIB_H
+#define RDOFF_RDLIB_H 1
+
+struct librarynode {
+ char *name;
+ FILE *fp; /* initialised to NULL - always check */
+ int referenced; /* & open if required. Close afterwards */
+ struct librarynode *next; /* if ! referenced. */
+};
+
+extern int rdl_error;
+
+#define RDL_EOPEN 1
+#define RDL_EINVALID 2
+#define RDL_EVERSION 3
+#define RDL_ENOTFOUND 4
+
+int rdl_verify(const char *filename);
+int rdl_open(struct librarynode *lib, const char *filename);
+int rdl_searchlib(struct librarynode *lib, const char *label, rdffile * f);
+int rdl_openmodule(struct librarynode *lib, int module, rdffile * f);
+
+void rdl_perror(const char *apname, const char *filename);
+
+#endif
diff --git a/rdoff/rdoff.c b/rdoff/rdoff.c
new file mode 100644
index 0000000..3c7b336
--- /dev/null
+++ b/rdoff/rdoff.c
@@ -0,0 +1,611 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 1996-2009 The NASM Authors - All Rights Reserved
+ * See the file AUTHORS included with the NASM distribution for
+ * the specific copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * rdoff.c library of routines for manipulating rdoff files
+ */
+
+/* TODO: The functions in this module assume they are running
+ * on a little-endian machine. This should be fixed to
+ * make it portable.
+ */
+
+#include "compiler.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <inttypes.h>
+
+#define RDOFF_UTILS
+
+#include "rdoff.h"
+
+#define newstr(str) strcpy(malloc(strlen(str) + 1),str)
+#define newstrcat(s1,s2) strcat(strcpy(malloc(strlen(s1) + strlen(s2) + 1), \
+ s1),s2)
+
+/*
+ * Comment this out to allow the module to read & write header record types
+ * that it isn't aware of. With this defined, unrecognised header records
+ * will generate error number 8, reported as 'unknown extended header record'.
+ */
+
+#define STRICT_ERRORS
+
+/* ========================================================================
+ * Code for memory buffers (for delayed writing of header until we know
+ * how int32_t it is).
+ * ======================================================================== */
+
+memorybuffer *newmembuf()
+{
+ memorybuffer *t;
+
+ t = malloc(sizeof(memorybuffer));
+ if (!t)
+ return NULL;
+
+ t->length = 0;
+ t->next = NULL;
+ return t;
+}
+
+void membufwrite(memorybuffer * const b, void *data, int bytes)
+{
+ uint16_t w;
+ int32_t l;
+ char *c;
+
+ if (b->next) { /* memory buffer full - use next buffer */
+ membufwrite(b->next, data, bytes);
+ return;
+ }
+
+ if ((bytes < 0 && b->length - bytes > BUF_BLOCK_LEN)
+ || (bytes > 0 && b->length + bytes > BUF_BLOCK_LEN)) {
+
+ /* buffer full and no next allocated... allocate and initialise next
+ * buffer */
+ b->next = newmembuf();
+ membufwrite(b->next, data, bytes);
+ return;
+ }
+
+ switch (bytes) {
+ case -4: /* convert to little-endian */
+ l = *(int32_t *)data;
+ b->buffer[b->length++] = l & 0xFF;
+ l >>= 8;
+ b->buffer[b->length++] = l & 0xFF;
+ l >>= 8;
+ b->buffer[b->length++] = l & 0xFF;
+ l >>= 8;
+ b->buffer[b->length++] = l & 0xFF;
+ break;
+
+ case -2:
+ w = *(uint16_t *) data;
+ b->buffer[b->length++] = w & 0xFF;
+ w >>= 8;
+ b->buffer[b->length++] = w & 0xFF;
+ break;
+
+ default:
+ c = data;
+ while (bytes--)
+ b->buffer[b->length++] = *c++;
+ break;
+ }
+}
+
+void membufdump(memorybuffer * b, FILE * fp)
+{
+ if (!b)
+ return;
+
+ fwrite(b->buffer, 1, b->length, fp);
+
+ membufdump(b->next, fp);
+}
+
+int membuflength(memorybuffer * b)
+{
+ if (!b)
+ return 0;
+ return b->length + membuflength(b->next);
+}
+
+void freemembuf(memorybuffer * b)
+{
+ if (!b)
+ return;
+ freemembuf(b->next);
+ free(b);
+}
+
+/* =========================================================================
+ General purpose routines and variables used by the library functions
+ ========================================================================= */
+
+/*
+ * translateint32_t() and translateint16_t()
+ *
+ * translate from little endian to local representation
+ */
+int32_t translateint32_t(int32_t in)
+{
+ int32_t r;
+ uint8_t *i;
+
+ i = (uint8_t *)&in;
+ r = i[3];
+ r = (r << 8) + i[2];
+ r = (r << 8) + i[1];
+ r = (r << 8) + *i;
+
+ return r;
+}
+
+uint16_t translateint16_t(uint16_t in)
+{
+ uint16_t r;
+ uint8_t *i;
+
+ i = (uint8_t *)&in;
+ r = (i[1] << 8) + i[0];
+
+ return r;
+}
+
+/* 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_t 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] = {
+ /* 0 */ "no error occurred",
+ /* 1 */ "could not open file",
+ /* 2 */ "invalid file format",
+ /* 3 */ "error reading file",
+ /* 4 */ "unknown error",
+ /* 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;
+
+/* ========================================================================
+ The library functions
+ ======================================================================== */
+
+int rdfopen(rdffile * f, const char *name)
+{
+ FILE *fp;
+
+ fp = fopen(name, "rb");
+ if (!fp)
+ return rdf_errno = RDF_ERR_OPEN;
+
+ return rdfopenhere(f, fp, NULL, name);
+}
+
+int rdfopenhere(rdffile * f, FILE * fp, int *refcount, const char *name)
+{
+ char buf[8];
+ int32_t initpos;
+ int32_t l;
+ uint16_t s;
+
+ if (translateint32_t(0x01020304) != 0x01020304) {
+ /* fix this to be portable! */
+ fputs("*** this program requires a little endian machine\n",
+ stderr);
+ fprintf(stderr, "01020304h = %08"PRIx32"h\n", translateint32_t(0x01020304));
+ exit(3);
+ }
+
+ f->fp = fp;
+ initpos = ftell(fp);
+
+ fread(buf, 6, 1, f->fp); /* read header */
+ buf[6] = 0;
+
+ if (strcmp(buf, RDOFFId)) {
+ fclose(f->fp);
+ if (!strcmp(buf, "RDOFF1"))
+ return rdf_errno = RDF_ERR_VER;
+ return rdf_errno = RDF_ERR_FORMAT;
+ }
+
+ if (fread(&l, 1, 4, f->fp) != 4
+ || fread(&f->header_len, 1, 4, f->fp) != 4) {
+ fclose(f->fp);
+ return rdf_errno = RDF_ERR_READ;
+ }
+
+ f->header_ofs = ftell(f->fp);
+ f->eof_offset = f->header_ofs + translateint32_t(l) - 4;
+
+ if (fseek(f->fp, f->header_len, SEEK_CUR)) {
+ fclose(f->fp);
+ return rdf_errno = RDF_ERR_FORMAT; /* seek past end of file...? */
+ }
+
+ if (fread(&s, 1, 2, f->fp) != 2) {
+ fclose(f->fp);
+ return rdf_errno = RDF_ERR_READ;
+ }
+
+ f->nsegs = 0;
+
+ while (s != 0) {
+ f->seg[f->nsegs].type = s;
+ 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].length, 1, 4, f->fp) != 4) {
+ fclose(f->fp);
+ return rdf_errno = RDF_ERR_READ;
+ }
+
+ f->seg[f->nsegs].offset = ftell(f->fp);
+ if (fseek(f->fp, f->seg[f->nsegs].length, SEEK_CUR)) {
+ fclose(f->fp);
+ return rdf_errno = RDF_ERR_FORMAT;
+ }
+ f->nsegs++;
+
+ if (fread(&s, 1, 2, f->fp) != 2) {
+ fclose(f->fp);
+ return rdf_errno = RDF_ERR_READ;
+ }
+ }
+
+ if (f->eof_offset != ftell(f->fp) + 8) { /* +8 = skip null segment header */
+ fprintf(stderr, "warning: eof_offset [%"PRId32"] and actual eof offset "
+ "[%ld] don't match\n", f->eof_offset, ftell(f->fp) + 8);
+ }
+ fseek(f->fp, initpos, SEEK_SET);
+ f->header_loc = NULL;
+
+ f->name = newstr(name);
+ f->refcount = refcount;
+ if (refcount)
+ (*refcount)++;
+ return RDF_OK;
+}
+
+int rdfclose(rdffile * f)
+{
+ if (!f->refcount || !--(*f->refcount)) {
+ fclose(f->fp);
+ f->fp = NULL;
+ }
+ free(f->name);
+
+ return 0;
+}
+
+/*
+ * 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]);
+ if (rdf_errno == RDF_ERR_OPEN || rdf_errno == RDF_ERR_READ) {
+ 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 i;
+ for (i = 0; i < f->nsegs; i++)
+ if (f->seg[i].number == segno)
+ return i;
+ return -1;
+}
+
+/*
+ * Load the segment. Returns status.
+ */
+int rdfloadseg(rdffile * f, int segment, void *buffer)
+{
+ int32_t fpos;
+ size_t slen;
+
+ switch (segment) {
+ case RDOFF_HEADER:
+ fpos = f->header_ofs;
+ slen = f->header_len;
+ f->header_loc = (uint8_t *) buffer;
+ f->header_fp = 0;
+ break;
+ default:
+ if (segment < f->nsegs) {
+ fpos = f->seg[segment].offset;
+ slen = f->seg[segment].length;
+ f->seg[segment].data = (uint8_t *) buffer;
+ } else {
+ return rdf_errno = RDF_ERR_SEGMENT;
+ }
+ }
+
+ if (fseek(f->fp, fpos, SEEK_SET))
+ return rdf_errno = RDF_ERR_UNKNOWN;
+
+ if (fread(buffer, 1, slen, f->fp) != slen)
+ return rdf_errno = RDF_ERR_READ;
+
+ return RDF_OK;
+}
+
+/* Macros for reading integers from header in memory */
+
+#define RI8(v) v = f->header_loc[f->header_fp++]
+#define RI16(v) { v = (f->header_loc[f->header_fp] + \
+ (f->header_loc[f->header_fp+1] << 8)); \
+ f->header_fp += 2; }
+
+#define RI32(v) { v = (f->header_loc[f->header_fp] + \
+ (f->header_loc[f->header_fp+1] << 8) + \
+ (f->header_loc[f->header_fp+2] << 16) + \
+ (f->header_loc[f->header_fp+3] << 24)); \
+ f->header_fp += 4; }
+
+#define RS(str,max) { for(i=0;i<max;i++){\
+ RI8(str[i]); if (!str[i]) break;} str[i]=0; }
+
+/*
+ * Read a header record.
+ * Returns the address of record, or NULL in case of error.
+ */
+rdfheaderrec *rdfgetheaderrec(rdffile * f)
+{
+ static rdfheaderrec r;
+ int i;
+
+ if (!f->header_loc) {
+ rdf_errno = RDF_ERR_HEADER;
+ return NULL;
+ }
+
+ if (f->header_fp >= f->header_len)
+ return 0;
+
+ RI8(r.type);
+ RI8(r.g.reclen);
+
+ switch (r.type) {
+ case RDFREC_RELOC: /* Relocation record */
+ case RDFREC_SEGRELOC:
+ if (r.r.reclen != 8) {
+ rdf_errno = RDF_ERR_RECLEN;
+ return NULL;
+ }
+ RI8(r.r.segment);
+ RI32(r.r.offset);
+ RI8(r.r.length);
+ RI16(r.r.refseg);
+ break;
+
+ case RDFREC_IMPORT: /* Imported symbol record */
+ case RDFREC_FARIMPORT:
+ RI8(r.i.flags);
+ RI16(r.i.segment);
+ RS(r.i.label, EXIM_LABEL_MAX);
+ break;
+
+ case RDFREC_GLOBAL: /* Exported symbol record */
+ RI8(r.e.flags);
+ RI8(r.e.segment);
+ RI32(r.e.offset);
+ RS(r.e.label, EXIM_LABEL_MAX);
+ break;
+
+ case RDFREC_DLL: /* DLL record */
+ RS(r.d.libname, MODLIB_NAME_MAX);
+ break;
+
+ case RDFREC_BSS: /* BSS reservation record */
+ if (r.r.reclen != 4) {
+ rdf_errno = RDF_ERR_RECLEN;
+ return NULL;
+ }
+ RI32(r.b.amount);
+ break;
+
+ case RDFREC_MODNAME: /* Module name record */
+ RS(r.m.modname, MODLIB_NAME_MAX);
+ break;
+
+ case RDFREC_COMMON: /* Common variable */
+ RI16(r.c.segment);
+ RI32(r.c.size);
+ RI16(r.c.align);
+ RS(r.c.label, EXIM_LABEL_MAX);
+ break;
+
+ default:
+#ifdef STRICT_ERRORS
+ rdf_errno = RDF_ERR_RECTYPE; /* unknown header record */
+ return NULL;
+#else
+ for (i = 0; i < r.g.reclen; i++)
+ RI8(r.g.data[i]);
+#endif
+ }
+ return &r;
+}
+
+/*
+ * Rewind to the beginning of the file
+ */
+void rdfheaderrewind(rdffile * f)
+{
+ f->header_fp = 0;
+}
+
+rdf_headerbuf *rdfnewheader(void)
+{
+ rdf_headerbuf *hb = malloc(sizeof(rdf_headerbuf));
+ if (hb == NULL)
+ return NULL;
+
+ hb->buf = newmembuf();
+ hb->nsegments = 0;
+ hb->seglength = 0;
+
+ return hb;
+}
+
+int rdfaddheader(rdf_headerbuf * h, rdfheaderrec * r)
+{
+#ifndef STRICT_ERRORS
+ int i;
+#endif
+ membufwrite(h->buf, &r->type, 1);
+ membufwrite(h->buf, &r->g.reclen, 1);
+
+ switch (r->type) {
+ case RDFREC_GENERIC: /* generic */
+ membufwrite(h->buf, &r->g.data, r->g.reclen);
+ break;
+ case RDFREC_RELOC:
+ case RDFREC_SEGRELOC:
+ membufwrite(h->buf, &r->r.segment, 1);
+ membufwrite(h->buf, &r->r.offset, -4);
+ membufwrite(h->buf, &r->r.length, 1);
+ membufwrite(h->buf, &r->r.refseg, -2); /* 9 bytes written */
+ break;
+
+ case RDFREC_IMPORT: /* import */
+ case RDFREC_FARIMPORT:
+ membufwrite(h->buf, &r->i.flags, 1);
+ membufwrite(h->buf, &r->i.segment, -2);
+ membufwrite(h->buf, &r->i.label, strlen(r->i.label) + 1);
+ break;
+
+ case RDFREC_GLOBAL: /* export */
+ membufwrite(h->buf, &r->e.flags, 1);
+ membufwrite(h->buf, &r->e.segment, 1);
+ membufwrite(h->buf, &r->e.offset, -4);
+ membufwrite(h->buf, &r->e.label, strlen(r->e.label) + 1);
+ break;
+
+ case RDFREC_DLL: /* DLL */
+ membufwrite(h->buf, &r->d.libname, strlen(r->d.libname) + 1);
+ break;
+
+ case RDFREC_BSS: /* BSS */
+ membufwrite(h->buf, &r->b.amount, -4);
+ break;
+
+ case RDFREC_MODNAME: /* Module name */
+ membufwrite(h->buf, &r->m.modname, strlen(r->m.modname) + 1);
+ break;
+
+ default:
+#ifdef STRICT_ERRORS
+ return rdf_errno = RDF_ERR_RECTYPE;
+#else
+ for (i = 0; i < r->g.reclen; i++)
+ membufwrite(h->buf, r->g.data[i], 1);
+#endif
+ }
+ return 0;
+}
+
+int rdfaddsegment(rdf_headerbuf * h, int32_t seglength)
+{
+ h->nsegments++;
+ h->seglength += seglength;
+ return 0;
+}
+
+int rdfwriteheader(FILE * fp, rdf_headerbuf * h)
+{
+ int32_t l, l2;
+
+ fwrite(RDOFFId, 1, strlen(RDOFFId), fp);
+
+ l = membuflength(h->buf);
+ l2 = l + 14 + 10 * h->nsegments + h->seglength;
+ l = translateint32_t(l);
+ l2 = translateint32_t(l2);
+ fwrite(&l2, 4, 1, fp); /* object length */
+ fwrite(&l, 4, 1, fp); /* header length */
+
+ membufdump(h->buf, fp);
+
+ return 0; /* no error handling in here... CHANGE THIS! */
+}
+
+void rdfdoneheader(rdf_headerbuf * h)
+{
+ freemembuf(h->buf);
+ free(h);
+}
diff --git a/rdoff/rdoff.h b/rdoff/rdoff.h
new file mode 100644
index 0000000..a161733
--- /dev/null
+++ b/rdoff/rdoff.h
@@ -0,0 +1,293 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 1996-2009 The NASM Authors - All Rights Reserved
+ * See the file AUTHORS included with the NASM distribution for
+ * the specific copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * rdoff.h RDOFF Object File manipulation routines header file
+ */
+
+#ifndef RDOFF_RDOFF_H
+#define RDOFF_RDOFF_H 1
+
+#include <inttypes.h>
+
+/*
+ * RDOFF definitions. They are used by RDOFF utilities and by NASM's
+ * 'outrdf2.c' output module.
+ */
+
+/* RDOFF format revision (currently used only when printing the version) */
+#define RDOFF2_REVISION "0.6.1"
+
+/* 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_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
+
+/*
+ * Generic record - contains the type and length field, plus a 128 byte
+ * array 'data'
+ */
+struct GenericRec {
+ uint8_t type;
+ uint8_t reclen;
+ char data[128];
+};
+
+/*
+ * Relocation record
+ */
+struct RelocRec {
+ uint8_t type; /* must be 1 */
+ uint8_t reclen; /* content length */
+ uint8_t segment; /* only 0 for code, or 1 for data supported,
+ but add 64 for relative refs (ie do not require
+ reloc @ loadtime, only linkage) */
+ int32_t offset; /* from start of segment in which reference is loc'd */
+ uint8_t length; /* 1 2 or 4 bytes */
+ uint16_t refseg; /* segment to which reference refers to */
+};
+
+/*
+ * Extern/import record
+ */
+struct ImportRec {
+ uint8_t type; /* must be 2 */
+ uint8_t reclen; /* content length */
+ uint8_t flags; /* SYM_* flags (see below) */
+ uint16_t 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[EXIM_LABEL_MAX]; /* zero terminated, should be written to file
+ until the zero, but not after it */
+};
+
+/*
+ * Public/export record
+ */
+struct ExportRec {
+ uint8_t type; /* must be 3 */
+ uint8_t reclen; /* content length */
+ uint8_t flags; /* SYM_* flags (see below) */
+ uint8_t segment; /* segment referred to (0/1/2) */
+ int32_t offset; /* offset within segment */
+ char label[EXIM_LABEL_MAX]; /* zero terminated as in import */
+};
+
+/*
+ * DLL record
+ */
+struct DLLRec {
+ uint8_t type; /* must be 4 */
+ uint8_t reclen; /* content length */
+ char libname[MODLIB_NAME_MAX]; /* name of library to link with at load time */
+};
+
+/*
+ * BSS record
+ */
+struct BSSRec {
+ uint8_t type; /* must be 5 */
+ uint8_t reclen; /* content length */
+ int32_t amount; /* number of bytes BSS to reserve */
+};
+
+/*
+ * Module name record
+ */
+struct ModRec {
+ uint8_t type; /* must be 8 */
+ uint8_t reclen; /* content length */
+ char modname[MODLIB_NAME_MAX]; /* module name */
+};
+
+/*
+ * Common variable record
+ */
+struct CommonRec {
+ uint8_t type; /* must be 10 */
+ uint8_t reclen; /* equals 7+label length */
+ uint16_t segment; /* segment number */
+ int32_t size; /* size of common variable */
+ uint16_t align; /* alignment (power of two) */
+ char label[EXIM_LABEL_MAX]; /* zero terminated as in import */
+};
+
+/* Flags for ExportRec */
+#define SYM_DATA 1
+#define SYM_FUNCTION 2
+#define SYM_GLOBAL 4
+#define SYM_IMPORT 8
+
+/*** The following part is used only by the utilities *************************/
+
+#ifdef RDOFF_UTILS
+
+/* Some systems don't define this automatically */
+#if !defined(strdup)
+extern char *strdup(const char *);
+#endif
+
+typedef union RDFHeaderRec {
+ char type; /* invariant throughout all below */
+ struct GenericRec g; /* type 0 */
+ 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 */
+ struct CommonRec c; /* type == 10 */
+} rdfheaderrec;
+
+struct SegmentHeaderRec {
+ /* information from file */
+ uint16_t type;
+ uint16_t number;
+ uint16_t reserved;
+ int32_t length;
+
+ /* information built up here */
+ int32_t offset;
+ uint8_t *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 */
+ int32_t header_len;
+ int32_t header_ofs;
+
+ uint8_t *header_loc; /* keep location of header */
+ int32_t header_fp; /* current location within header for reading */
+
+ struct SegmentHeaderRec seg[RDF_MAXSEGS];
+ int nsegs;
+
+ int32_t eof_offset; /* offset of the first uint8_t 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;
+ uint8_t buffer[BUF_BLOCK_LEN];
+ struct memorybuffer *next;
+} memorybuffer;
+
+typedef struct {
+ memorybuffer *buf; /* buffer containing header records */
+ int nsegments; /* number of segments to be written */
+ int32_t 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;
+
+/* 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 */
+int32_t translateint32_t(int32_t in);
+uint16_t translateint16_t(uint16_t in);
+char *translatesegmenttype(uint16_t type);
+
+/* 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 int32_t 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, int32_t seglength);
+int rdfwriteheader(FILE * fp, rdf_headerbuf * h);
+void rdfdoneheader(rdf_headerbuf * h);
+
+#endif /* RDOFF_UTILS */
+
+#endif /* RDOFF_RDOFF_H */
diff --git a/rdoff/rdx.1 b/rdoff/rdx.1
new file mode 100644
index 0000000..a864056
--- /dev/null
+++ b/rdoff/rdx.1
@@ -0,0 +1,21 @@
+.TH RDX 1 "September 6, 1999" "Debian Project" "Debian Manual"
+.SH NAME
+rdx \- load and execute an RDOFF object
+.SH SYNOPSIS
+.B rdx
+.I object
+.SH DESCRIPTION
+.B rdx
+loads an RDOFF
+.IR object ,
+and then calls
+.RB ` _main ',
+which it expects to be a C-style function, accepting two parameters,
+.I argc
+and
+.I argv
+in normal C style.
+.SH AUTHORS
+Julian Hall <jules@earthcorp.com>.
+.PP
+This manual page was written by Matej Vela <vela@debian.org>.
diff --git a/rdoff/rdx.c b/rdoff/rdx.c
new file mode 100644
index 0000000..240ab59
--- /dev/null
+++ b/rdoff/rdx.c
@@ -0,0 +1,88 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 1996-2009 The NASM Authors - All Rights Reserved
+ * See the file AUTHORS included with the NASM distribution for
+ * the specific copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * rdx.c RDOFF Object File loader program
+ */
+
+/* note: most of the actual work of this program is done by the modules
+ "rdfload.c", which loads and relocates the object file, and by "rdoff.c",
+ which contains general purpose routines to manipulate RDOFF object
+ files. You can use these files in your own program to load RDOFF objects
+ and execute the code in them in a similar way to what is shown here. */
+
+#include "compiler.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "rdfload.h"
+#include "symtab.h"
+
+typedef int (*main_fn) (int, char **); /* Main function prototype */
+
+int main(int argc, char **argv)
+{
+ rdfmodule *m;
+ main_fn code;
+ symtabEnt *s;
+
+ if (argc < 2) {
+ puts("usage: rdx <rdoff-executable> [params]\n");
+ exit(255);
+ }
+
+ m = rdfload(argv[1]);
+
+ if (!m) {
+ rdfperror("rdx", argv[1]);
+ exit(255);
+ }
+
+ rdf_relocate(m); /* in this instance, the default relocation
+ values will work fine, but they may need changing
+ in other cases... */
+
+ s = symtabFind(m->symtab, "_main");
+ if (!s) {
+ fprintf(stderr, "rdx: could not find symbol '_main' in '%s'\n",
+ argv[1]);
+ exit(255);
+ }
+
+ code = (main_fn)(size_t) s->offset;
+
+ argv++, argc--; /* remove 'rdx' from command line */
+
+ return code(argc, argv); /* execute */
+}
diff --git a/rdoff/segtab.c b/rdoff/segtab.c
new file mode 100644
index 0000000..4a4c5b8
--- /dev/null
+++ b/rdoff/segtab.c
@@ -0,0 +1,175 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 1996-2009 The NASM Authors - All Rights Reserved
+ * See the file AUTHORS included with the NASM distribution for
+ * the specific copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * ----------------------------------------------------------------------- */
+
+#include "compiler.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "segtab.h"
+
+struct segtabnode {
+ int localseg;
+ int destseg;
+ int32_t offset;
+
+ struct segtabnode *left;
+ struct segtabnode *right;
+ /*
+ * counts of how many are left or right, for use in reorganising
+ * the tree
+ */
+ int leftcount;
+ int rightcount;
+};
+
+/*
+ * init_seglocations()
+ * add_seglocation()
+ * get_seglocation()
+ * done_seglocation()
+ *
+ * functions used by write_output() to manipulate associations
+ * between segment numbers and locations (which are built up on a per
+ * module basis, but we only need one module at a time...)
+ *
+ * implementation: we build a binary tree.
+ */
+
+void init_seglocations(segtab * root)
+{
+ *root = NULL;
+}
+
+void descend_tree_add(struct segtabnode **node,
+ int localseg, int destseg, int32_t offset)
+{
+ struct segtabnode *n;
+
+ if (*node == NULL) {
+ *node = malloc(sizeof(**node));
+ if (!*node) {
+ fprintf(stderr, "segment table: out of memory\n");
+ exit(1);
+ }
+ (*node)->localseg = localseg;
+ (*node)->offset = offset;
+ (*node)->left = NULL;
+ (*node)->leftcount = 0;
+ (*node)->right = NULL;
+ (*node)->rightcount = 0;
+ (*node)->destseg = destseg;
+ return;
+ }
+
+ if (localseg < (*node)->localseg) {
+ (*node)->leftcount++;
+ descend_tree_add(&(*node)->left, localseg, destseg, offset);
+
+ if ((*node)->leftcount > (*node)->rightcount + 2) {
+ n = *node;
+ *node = n->left;
+ n->left = (*node)->right;
+ n->leftcount = (*node)->rightcount;
+ (*node)->right = n;
+ (*node)->rightcount = n->leftcount + n->rightcount + 1;
+ }
+ } else {
+ (*node)->rightcount++;
+ descend_tree_add(&(*node)->right, localseg, destseg, offset);
+
+ if ((*node)->rightcount > (*node)->leftcount + 2) {
+ n = *node;
+ *node = n->right;
+ n->right = (*node)->left;
+ n->rightcount = (*node)->leftcount;
+ (*node)->left = n;
+ (*node)->leftcount = n->leftcount + n->rightcount + 1;
+ }
+ }
+}
+
+void add_seglocation(segtab * root, int localseg, int destseg, int32_t offset)
+{
+ descend_tree_add((struct segtabnode **)root, localseg, destseg,
+ offset);
+}
+
+int get_seglocation(segtab * root, int localseg, int *destseg,
+ int32_t *offset)
+{
+ struct segtabnode *n = (struct segtabnode *)*root;
+
+ while (n && n->localseg != localseg) {
+ if (localseg < n->localseg)
+ n = n->left;
+ else
+ n = n->right;
+ }
+ if (n) {
+ *destseg = n->destseg;
+ *offset = n->offset;
+ return 1;
+ } else
+ return 0;
+}
+
+void freenode(struct segtabnode *n)
+{
+ if (!n)
+ return;
+ freenode(n->left);
+ freenode(n->right);
+ free(n);
+}
+
+void done_seglocations(segtab * root)
+{
+ freenode(*root);
+ *root = NULL;
+}
+
+#if 0
+void printnode(int i, struct segtabnode *n)
+{
+ if (!n)
+ return;
+ printnode(i + 1, n->left);
+ printf("%*s%d %d %ld\n", i, "", n->localseg, n->destseg, n->offset);
+ printnode(i + 1, n->right);
+}
+
+void printtable()
+{
+ printnode(0, root);
+}
+#endif
diff --git a/rdoff/segtab.h b/rdoff/segtab.h
new file mode 100644
index 0000000..87ef017
--- /dev/null
+++ b/rdoff/segtab.h
@@ -0,0 +1,46 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 1996-2009 The NASM Authors - All Rights Reserved
+ * See the file AUTHORS included with the NASM distribution for
+ * the specific copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * ----------------------------------------------------------------------- */
+
+#ifndef RDOFF_SEGTAB_H
+#define RDOFF_SEGTAB_H 1
+
+#include <inttypes.h>
+
+typedef void *segtab;
+
+void init_seglocations(segtab * r);
+void add_seglocation(segtab * r, int localseg, int destseg, int32_t offset);
+int get_seglocation(segtab * r, int localseg, int *destseg, int32_t *offset);
+void done_seglocations(segtab * r);
+
+#endif
diff --git a/rdoff/symtab.c b/rdoff/symtab.c
new file mode 100644
index 0000000..1dfee1a
--- /dev/null
+++ b/rdoff/symtab.c
@@ -0,0 +1,159 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 1996-2009 The NASM Authors - All Rights Reserved
+ * See the file AUTHORS included with the NASM distribution for
+ * the specific copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * symtab.c Routines to maintain and manipulate a symbol table
+ *
+ * These routines donated to the NASM effort by Graeme Defty.
+ */
+
+#include "compiler.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "symtab.h"
+#include "hash.h"
+
+#define SYMTABSIZE 64
+#define slotnum(x) (hash((x)) % SYMTABSIZE)
+
+/* ------------------------------------- */
+/* Private data types */
+
+typedef struct tagSymtabNode {
+ struct tagSymtabNode *next;
+ symtabEnt ent;
+} symtabNode;
+
+typedef symtabNode *(symtabTab[SYMTABSIZE]);
+
+typedef symtabTab *symtab;
+
+/* ------------------------------------- */
+void *symtabNew(void)
+{
+ symtab mytab;
+
+ mytab = (symtabTab *) calloc(SYMTABSIZE, sizeof(symtabNode *));
+ if (mytab == NULL) {
+ fprintf(stderr, "symtab: out of memory\n");
+ exit(3);
+ }
+
+ return mytab;
+}
+
+/* ------------------------------------- */
+void symtabDone(void *stab)
+{
+ symtab mytab = (symtab) stab;
+ int i;
+ symtabNode *this, *next;
+
+ for (i = 0; i < SYMTABSIZE; ++i) {
+
+ for (this = (*mytab)[i]; this; this = next) {
+ next = this->next;
+ free(this);
+ }
+
+ }
+ free(*mytab);
+}
+
+/* ------------------------------------- */
+void symtabInsert(void *stab, symtabEnt * ent)
+{
+ symtab mytab = (symtab) stab;
+ symtabNode *node;
+ int slot;
+
+ node = malloc(sizeof(symtabNode));
+ if (node == NULL) {
+ fprintf(stderr, "symtab: out of memory\n");
+ exit(3);
+ }
+
+ slot = slotnum(ent->name);
+
+ node->ent = *ent;
+ node->next = (*mytab)[slot];
+ (*mytab)[slot] = node;
+}
+
+/* ------------------------------------- */
+symtabEnt *symtabFind(void *stab, const char *name)
+{
+ symtab mytab = (symtab) stab;
+ int slot = slotnum(name);
+ symtabNode *node = (*mytab)[slot];
+
+ while (node) {
+ if (!strcmp(node->ent.name, name)) {
+ return &(node->ent);
+ }
+ node = node->next;
+ }
+
+ return NULL;
+}
+
+/* ------------------------------------- */
+void symtabDump(void *stab, FILE * of)
+{
+ symtab mytab = (symtab) stab;
+ int i;
+ char *SegNames[3] = { "code", "data", "bss" };
+
+ fprintf(of, "Symbol table is ...\n");
+ for (i = 0; i < SYMTABSIZE; ++i) {
+ symtabNode *l = (symtabNode *) (*mytab)[i];
+
+ if (l) {
+ fprintf(of, " ... slot %d ...\n", i);
+ }
+ while (l) {
+ if ((l->ent.segment) == -1) {
+ fprintf(of, "%-32s Unresolved reference\n", l->ent.name);
+ } else {
+ fprintf(of, "%-32s %s:%08"PRIx32" (%"PRId32")\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/symtab.h b/rdoff/symtab.h
new file mode 100644
index 0000000..0dc8c7b
--- /dev/null
+++ b/rdoff/symtab.h
@@ -0,0 +1,56 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 1996-2009 The NASM Authors - All Rights Reserved
+ * See the file AUTHORS included with the NASM distribution for
+ * the specific copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * symtab.h Header file for symbol table manipulation routines
+ */
+
+#ifndef RDOFF_SYMTAB_H
+#define RDOFF_SYMTAB_H 1
+
+#include <inttypes.h>
+
+typedef struct {
+ char *name;
+ int segment;
+ int32_t offset;
+ int32_t flags;
+} symtabEnt;
+
+void *symtabNew(void);
+void symtabDone(void *symtab);
+void symtabInsert(void *symtab, symtabEnt * ent);
+symtabEnt *symtabFind(void *symtab, const char *name);
+void symtabDump(void *symtab, FILE * of);
+
+#endif
diff --git a/rdoff/test/Makefile b/rdoff/test/Makefile
new file mode 100644
index 0000000..658a6d4
--- /dev/null
+++ b/rdoff/test/Makefile
@@ -0,0 +1,10 @@
+RDT = $(patsubst %.asm,%.rdf,$(wildcard *.asm))
+NASM = ../../nasm
+
+all: $(RDT)
+
+%.rdf: %.asm
+ $(NASM) -f rdf -o $@ -l $*.lst $<
+
+clean:
+ rm -f *.rdf *.rdx *.lst
diff --git a/rdoff/test/makelib.sh b/rdoff/test/makelib.sh
new file mode 100644
index 0000000..520bb19
--- /dev/null
+++ b/rdoff/test/makelib.sh
@@ -0,0 +1,14 @@
+#! /bin/sh
+
+[ $1 ] || {
+ echo "Usage: $0 <library name> <module> [...]"
+ exit 1
+}
+
+libname=$1; shift
+
+rdflib c $libname
+
+for f in $*; do
+ rdflib a $libname $f $f
+done
diff --git a/rdoff/test/rdfseg.asm b/rdoff/test/rdfseg.asm
new file mode 100644
index 0000000..4c6f587
--- /dev/null
+++ b/rdoff/test/rdfseg.asm
@@ -0,0 +1,20 @@
+ ;; program to test inter-segment production and linkage of RDF objects
+
+ ;; [1] should produce segment base ref
+ ;; [2] should produce standard relocation
+
+[GLOBAL _main]
+[EXTERN _puts: far]
+[BITS 16]
+
+_main:
+ mov ax, seg _message ; 0000 [1]
+ mov ds, ax ; 0003
+ mov dx, _message ; 0005 [2]
+ call far _puts ; 0008 [2][1]
+ xor ax,ax ; 000D
+ int 21h ; 000F
+
+[SECTION .data]
+_message: db 'Hello, World', 10, 13, 0
+ \ No newline at end of file
diff --git a/rdoff/test/rdfseg2.asm b/rdoff/test/rdfseg2.asm
new file mode 100644
index 0000000..2b9e4fd
--- /dev/null
+++ b/rdoff/test/rdfseg2.asm
@@ -0,0 +1,12 @@
+ ;; library function for rdfseg - this file is linked as a far segment
+
+[BITS 16]
+[GLOBAL _puts]
+_puts:
+ ;; can't remember how to print a string in DOS, but if anyone wants
+ ;; to actually test this program, it should be fairly easy to put
+ ;; in here!
+
+ retf
+
+ \ No newline at end of file
diff --git a/rdoff/test/rdftest1.asm b/rdoff/test/rdftest1.asm
new file mode 100644
index 0000000..76f1e43
--- /dev/null
+++ b/rdoff/test/rdftest1.asm
@@ -0,0 +1,54 @@
+ ;; program to test RDOFF production and linkage
+
+ ;; items to test include:
+ ;; [1] relocation within the same segment in each module
+ ;; [2] relocation to different segments in same module
+ ;; [3] relocation to same segment in different module
+ ;; [4] relocation to different segment in different module
+ ;; [5] relative relocation to same module
+ ;; [6] relative relocation to different module
+ ;; [7] correct generation of BSS addresses
+
+[SECTION .text]
+[BITS 32]
+
+_main:
+ mov ax,localdata ; [2] (16 bit) => 66 b8 0000
+ mov eax,localdata2 ; [2] (32 bit) => b8 0000000a
+
+[EXTERN _fardata]
+
+ mov eax,[_fardata] ; [4] => a1 00000000 (+20)
+ mov cx,next ; [1] => 66 b9 0012
+next:
+ call localproc ; [5] => e8 00000019
+
+[EXTERN _farproc]
+ mov eax,_farproc ; [3] => b8 00000000 (+40+0)
+ call _farproc ; [6] => e8 -$ (-0+40+0) (=1f)
+
+ mov eax,localbss ; [7] => b8 00000000
+
+[GLOBAL _term]
+_term: xor ax,ax ; => 66 31 c0
+ int 21h ; => cd 21
+ jmp _term ; => e9 -0a (=fffffff6)
+
+localproc:
+ ret ; => c3
+
+[GLOBAL _test1proc]
+_test1proc:
+ call localproc ; [5] => e8 -$ (-0+0+?) (=-6=fffffffa)
+ ret ; => c3
+
+[SECTION .data]
+[GLOBAL localdata2]
+localdata: db 'localdata',0
+localdata2: db 'localdata2',0
+farref: dd _fardata ; [3] => 0 (+20)
+localref: dd _main ; [2] => 0 (+0)
+
+[SECTION .bss]
+localbss: resw 4 ; reserve 8 bytes BSS
+ \ No newline at end of file
diff --git a/rdoff/test/rdftest2.asm b/rdoff/test/rdftest2.asm
new file mode 100644
index 0000000..25b8c18
--- /dev/null
+++ b/rdoff/test/rdftest2.asm
@@ -0,0 +1,33 @@
+ ;; rdftest2.asm - test linkage and generation of RDOFF files
+
+[SECTION .text]
+[BITS 32]
+
+[GLOBAL _farproc]
+[EXTERN _test1proc]
+[EXTERN localdata2]
+[EXTERN _term]
+_farproc:
+
+ mov bx,localdata2 ; [4] 0 => 66 bb 000a(+0)
+ mov eax,_term ; [3] 5 => b8 00000000(+26+0)
+ call _test1proc ; [6] A => e8 fffffff2(-40+0+31)(=ffffffe3)
+
+ mov eax,_farproc ; [1] => b8 00000000(+40)
+ add eax,[_fardata] ; [2] => 03 05 00000000(+20)
+
+ mov ebx,mybssdata ; [7] => bb 00000000(+08)
+ call myproc ; [5] => e8 00000001
+ ret
+
+myproc:
+ add eax,ebx
+ ret
+
+[SECTION .data]
+[GLOBAL _fardata]
+_fardata: dw _term ; [4]
+_localref: dd _farproc ; [2]
+
+[SECTION .bss]
+mybssdata: resw 1
diff --git a/rdoff/test/rdtlib.asm b/rdoff/test/rdtlib.asm
new file mode 100644
index 0000000..6c2b8ec
--- /dev/null
+++ b/rdoff/test/rdtlib.asm
@@ -0,0 +1,48 @@
+ ;; library functions for rdtmain - test of rdx linking and execution
+
+ ;; library function = _strcmp, defined as in C
+
+[SECTION .text]
+[BITS 32]
+
+[GLOBAL _strcmp]
+_strcmp:
+ push ebp
+ mov ebp,esp
+
+ ;; ebp+8 = first paramater, ebp+12 = second
+
+ mov esi,[ebp+8]
+ mov edi,[ebp+12]
+
+.loop:
+ mov cl,byte [esi]
+ mov dl,byte [edi]
+ cmp cl,dl
+ jb .below
+ ja .above
+ or cl,cl
+ jz .match
+ inc esi
+ inc edi
+ jmp .loop
+
+.below:
+ mov eax,-1
+ pop ebp
+ ret
+
+.above:
+ mov eax,1
+ pop ebp
+ ret
+
+.match:
+ xor eax,eax
+ pop ebp
+ ret
+
+[SECTION .data]
+[GLOBAL _message]
+
+_message: db 'hello',0 \ No newline at end of file
diff --git a/rdoff/test/rdtmain.asm b/rdoff/test/rdtmain.asm
new file mode 100644
index 0000000..626a2e2
--- /dev/null
+++ b/rdoff/test/rdtmain.asm
@@ -0,0 +1,47 @@
+ ;; rdtmain - main part of test program for RDX execution.
+ ;; returns true (0) if its parameter equals the phrase "hello"
+ ;; "hello" is stored in the library part, to complicate the
+ ;; linkage.
+
+ ;; assemble and link with the following commands:
+ ;; nasm -f rdf rdtmain.asm
+ ;; nasm -f rdf rdtlib.asm
+ ;; ldrdf rdtmain.rdf rdtlib.rdf -o rdxtest.rdx
+
+ ;; run with 'rdx rdxtest.rdx [parameters]' on a Linux (or possibly
+ ;; other 32 bit OS) systems (x86 architectures only!)
+ ;; try using '&& echo Yes' afterwards to find out when it returns 0.
+
+[EXTERN _strcmp] ; strcmp is an imported function
+[EXTERN _message] ; imported data
+[SECTION .text]
+[BITS 32]
+
+ ;; main(int argc,char **argv)
+[GLOBAL _main]
+_main:
+ push ebp
+ mov ebp,esp
+
+ ;; ebp+8 = argc, ebp+12 = argv
+
+ cmp dword [ebp+8],2
+ jb error ; cause error if < 1 parameters
+
+ mov eax, [ebp+12] ; eax = argv
+
+ mov ebx, [eax+4] ; ebx = argv[1]
+ mov ecx, _message ; ecx = "hello"
+
+ push ecx
+ push ebx
+ call _strcmp ; compare strings
+ add esp,8 ; caller clears stack
+
+ pop ebp
+ ret ; return return value of _strcmp
+
+error:
+ mov eax,2 ; return 2 on error
+ pop ebp
+ ret
diff --git a/rdoff/test/testlib.asm b/rdoff/test/testlib.asm
new file mode 100644
index 0000000..6ee3d89
--- /dev/null
+++ b/rdoff/test/testlib.asm
@@ -0,0 +1,18 @@
+; program to test retrieval of and linkage to modules in libraries by
+; ldrdf
+
+[SECTION .text]
+[GLOBAL _main]
+[EXTERN _strcmp]
+
+_main:
+ push dword string1
+ push dword string2
+ call _strcmp
+ add esp,8 ; doh! clear up stack ;-)
+ ret
+
+[SECTION .data]
+
+string1: db 'abc',0 ; try changing these strings and see
+string2: db 'abd',0 ; what happens!