aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2002-04-30 20:58:18 +0000
committerH. Peter Anvin <hpa@zytor.com>2002-04-30 20:58:18 +0000
commit41bf8002b2fa402bd344a290fcc9f65de328859c (patch)
treefa1638dfbf73e3a6b96ce99cda1cd5ad9c1adf61
parentef7468f4ec05f23e8d866493593d7c1f07df5e03 (diff)
downloadnasm-41bf8002b2fa402bd344a290fcc9f65de328859c.tar.gz
nasm-41bf8002b2fa402bd344a290fcc9f65de328859c.tar.xz
nasm-41bf8002b2fa402bd344a290fcc9f65de328859c.zip
-rw-r--r--Changes5
-rw-r--r--Licence13
-rw-r--r--MODIFIED42
-rw-r--r--Makefile.in88
-rw-r--r--Mkfiles/Makefile.b32275
-rw-r--r--Mkfiles/Makefile.bc22
-rw-r--r--Mkfiles/Makefile.bor2
-rw-r--r--Mkfiles/Makefile.dj2
-rw-r--r--Mkfiles/Makefile.djo2
-rw-r--r--Mkfiles/Makefile.dos2
-rw-r--r--Mkfiles/Makefile.lcc2
-rw-r--r--Mkfiles/Makefile.os22
-rw-r--r--Mkfiles/Makefile.sc2
-rw-r--r--Mkfiles/Makefile.scw2
-rw-r--r--Mkfiles/Makefile.unx4
-rw-r--r--Mkfiles/Makefile.vc2
-rw-r--r--Mkfiles/Makefile.wcw2
-rw-r--r--assemble.c3
-rw-r--r--changed.asm28
-rw-r--r--configure.in2
-rw-r--r--doc/Makefile29
-rw-r--r--doc/Makefile.in50
-rw-r--r--doc/nasmdoc.src143
-rw-r--r--doc/rdsrc.pl4
-rw-r--r--insns.dat7
-rw-r--r--insns.pl262
-rw-r--r--labels.c14
-rw-r--r--nasm.c27
-rw-r--r--nasm.h2
-rw-r--r--nasm.spec87
-rw-r--r--outform.h6
-rw-r--r--rdoff/Changes63
-rw-r--r--rdoff/Makefile.in66
-rw-r--r--rdoff/Makefile.sc169
-rw-r--r--rdoff/Makefile.unx8
-rw-r--r--rdoff/README100
-rw-r--r--rdoff/hash.c95
-rw-r--r--rdoff/hash.h12
-rw-r--r--rdoff/ldrdf.c1571
-rw-r--r--rdoff/ldrdf1.c728
-rw-r--r--rdoff/ldsegs.h55
-rw-r--r--rdoff/rdf2bin.c8
-rw-r--r--rdoff/rdfdump.c233
-rw-r--r--rdoff/rdflib.c143
-rw-r--r--rdoff/rdfload.c18
-rw-r--r--rdoff/rdlib.c211
-rw-r--r--rdoff/rdlib.h9
-rw-r--r--rdoff/rdoff.c356
-rw-r--r--rdoff/rdoff.h98
-rw-r--r--rdoff/rdx.c4
-rw-r--r--rdoff/segtab.c142
-rw-r--r--rdoff/segtab.h7
-rw-r--r--rdoff/symtab.c127
-rw-r--r--rdoff/symtab.h4
-rw-r--r--rdoff/test/rdfseg.asm20
-rw-r--r--rdoff/test/rdfseg2.asm12
-rw-r--r--rdoff/v1/README5
-rw-r--r--rdoff/v1/collectn.c40
-rw-r--r--rdoff/v1/collectn.h22
-rw-r--r--rdoff/v1/ldrdf.c728
-rw-r--r--rdoff/v1/rdf.doc (renamed from rdoff/rdf.doc)0
-rw-r--r--rdoff/v1/rdf2bin.c125
-rw-r--r--rdoff/v1/rdfdump.c167
-rw-r--r--rdoff/v1/rdflib.c235
-rw-r--r--rdoff/v1/rdfload.c173
-rw-r--r--rdoff/v1/rdfload.h29
-rw-r--r--rdoff/v1/rdlib.c88
-rw-r--r--rdoff/v1/rdlib.h18
-rw-r--r--rdoff/v1/rdoff.c397
-rw-r--r--rdoff/v1/rdoff.h118
-rw-r--r--rdoff/v1/rdoff.txt (renamed from rdoff/rdoff.txt)0
-rw-r--r--rdoff/v1/rdx.c61
-rw-r--r--rdoff/v1/symtab.c80
-rw-r--r--rdoff/v1/symtab.h22
74 files changed, 6231 insertions, 1449 deletions
diff --git a/Changes b/Changes
index a2a291d8..f383182e 100644
--- a/Changes
+++ b/Changes
@@ -446,8 +446,8 @@ corruption at ends of long PUBDEF records.
Separated DOS archives into main-program and documentation to reduce
download size.
-0.98 not released yet
----------------------
+0.98 released May 1999
+----------------------
Fixed a bug whereby STRUC didn't work at all in RDF.
@@ -539,3 +539,4 @@ help screen
fixed limit checking bug, 'OUT byte nn, reg' bug, and a couple of rdoff
related bugs, updated Wishlist; 0.98 Prerelease 3.
+See the file "MODIFIED" for changes after 0.98p3.
diff --git a/Licence b/Licence
index 467d3af1..c85c212e 100644
--- a/Licence
+++ b/Licence
@@ -1,3 +1,4 @@
+
Terms and Conditions for the use of the Netwide Assembler
=========================================================
@@ -52,7 +53,8 @@ which a fee is charged), as long as permission is granted from the
authors of the Software. The authors reserve the right to grant this
permission only for a fee, which may at our option take the form of
royalty payments. The authors also reserve the right to refuse to
-grant permission if they deem it necessary.
+grant permission if they deem it necessary. For further information
+about who exactly the authors are, see clause XI below.
V. The Software may be incorporated, in its original archive form,
into software collections or archives which are not freely
@@ -105,4 +107,13 @@ authors for the purpose of inclusion in the official release version
are considered cleared for release under the full terms of this
Licence.
+XI. The authors of NASM are the original authors (Simon Tatham and
+Julian Hall) and all those who the original authors feel have
+contributed significantly to the overall project. If you wish to
+contact the authors, Julian Hall (jules@earthcorp.com) should be your
+first port of call.
+
+XII. Should any part of this agreement be deemed unenforcable, it is
+intended that the remainder of the agreement be held in force.
+
END OF LICENCE AGREEMENT
diff --git a/MODIFIED b/MODIFIED
index 247aced7..58987e85 100644
--- a/MODIFIED
+++ b/MODIFIED
@@ -1,7 +1,41 @@
-This is a modified version of NASM, modified and released by H. Peter
-Anvin <hpa@zytor.com>; it is not the original form released by the
-NASM authors. However, as of 0.98p6 I have agreed to release the
-official 0.98 version, so this is now an "official pre-release".
+This file details changes since NASM 0.98p3. All the releases in this
+file have been produced by H. Peter Anvin <hpa@zytor.com>.
+
+For release 0.98:
+* The documentation comment delimiter is \# not #.
+* Allow EQU definitions to refer to external labels; reported by
+ Pedro Gimeno.
+* Re-enable support for RDOFF v1; reported by Pedro Gimeno.
+* Updated License file per OK from Simon and Julian.
+
+For release 0.98p9:
+* Update documentation (although the instruction set reference will
+ have to wait; I don't want to hold up the 0.98 release for it.)
+* Verified that the NASM implementation of the PEXTRW and PMOVMSKB
+ instructions is correct. The encoding differs from what the Intel
+ manuals document, but the Pentium III behaviour matches NASM, not
+ the Intel manuals.
+* Fix handling of implicit sizes in PSHUFW and PINSRW, reported by
+ Stefan Hoffmeister.
+* Resurrect the -s option, which was removed when changing the
+ diagnostic output to stdout.
+
+For release 0.98p8:
+* Fix for "DB" when NASM is running on a bigendian machine.
+* Invoke insns.pl once for each output script, making Makefile.in
+ legal for "make -j".
+* Improve the Unix configure-based makefiles to make package
+ creation easier.
+* Included an RPM .spec file for building RPM (RedHat Package Manager)
+ packages on Linux or Unix systems.
+* Fix Makefile dependency problems.
+* Change src/rdsrc.pl to include sectioning information in info
+ output; required for install-info to work.
+* Updated the RDOFF distribution to version 2 from Jules; minor
+ massaging to make it compile in my environment.
+* Split doc files that can be built by anyone with a Perl interpreter off
+ into a separate archive.
+* "Dress rehearsal" release!
For release 0.98p7:
diff --git a/Makefile.in b/Makefile.in
index a3963fd9..3a94ae3b 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -1,3 +1,4 @@
+# $Id$
#
# Auto-configuring Makefile for the Netwide Assembler.
#
@@ -6,26 +7,36 @@
# redistributable under the licence given in the file "Licence"
# distributed in the NASM archive.
-srcdir = @srcdir@
-VPATH = @srcdir@
-prefix = @prefix@
-exec_prefix = @exec_prefix@
-bindir = @bindir@
-mandir = @mandir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+bindir = @bindir@
+mandir = @mandir@
-CC = @CC@
-CFLAGS = @CFLAGS@ @GCCFLAGS@ -I$(srcdir) -I.
+CC = @CC@
+CFLAGS = @CFLAGS@ @GCCFLAGS@ -I$(srcdir) -I.
+LDFLAGS = @LDFLAGS@
-INSTALL = @INSTALL@
-INSTALL_PROGRAM = @INSTALL_PROGRAM@
-INSTALL_DATA = @INSTALL_DATA@
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
-NROFF = @NROFF@
+NROFF = @NROFF@
-.SUFFIXES: .c .o .1 .man
+.SUFFIXES: .c .i .s .o .1 .man
+
+.PHONY: all doc rdf install clean distclean cleaner spotless install_rdf
+.PHONY: install_doc everything install_everything
.c.o:
- $(CC) -c $(CFLAGS) $<
+ $(CC) -c $(CFLAGS) -o $@ $<
+
+.c.s:
+ $(CC) -S $(CFLAGS) -o $@ $<
+
+.c.i:
+ $(CC) -E $(CFLAGS) -o $@ $<
.1.man:
$(NROFF) -man $< > $@
@@ -38,12 +49,13 @@ NASM = nasm.o nasmlib.o float.o insnsa.o assemble.o labels.o \
NDISASM = ndisasm.o disasm.o sync.o nasmlib.o insnsd.o
all: nasm ndisasm nasm.man ndisasm.man
+ cd rdoff; $(MAKE) all
nasm: $(NASM)
- $(CC) -o nasm $(NASM)
+ $(CC) $(LDFLAGS) -o nasm $(NASM)
ndisasm: $(NDISASM)
- $(CC) -o ndisasm $(NDISASM)
+ $(CC) $(LDFLAGS) -o ndisasm $(NDISASM)
assemble.o: assemble.c nasm.h insnsi.h nasmlib.h assemble.h insns.h
disasm.o: disasm.c nasm.h insnsi.h disasm.h sync.h insns.h names.c insnsn.c
@@ -55,7 +67,7 @@ labels.o: labels.c nasm.h insnsi.h nasmlib.h
listing.o: listing.c nasm.h insnsi.h nasmlib.h listing.h
nasm.o: nasm.c nasm.h insnsi.h nasmlib.h preproc.h parser.h assemble.h labels.h \
outform.h listing.h
-nasmlib.o: nasmlib.c nasm.h insnsi.h nasmlib.h
+nasmlib.o: nasmlib.c nasm.h insnsi.h nasmlib.h names.c insnsn.c
ndisasm.o: ndisasm.c nasm.h insnsi.h nasmlib.h sync.h disasm.h
outaout.o: outaout.c nasm.h insnsi.h nasmlib.h outform.h
outas86.o: outas86.c nasm.h insnsi.h nasmlib.h outform.h
@@ -77,8 +89,14 @@ zoutieee.o: zoutieee.c nasm.h insnsi.h nasmlib.h outform.h
# though, so it isn't necessary to have Perl just to recompile NASM
# from the distribution.
-insnsa.c insnsd.c insnsi.h insnsn.c: insns.dat insns.pl
- perl $(srcdir)/insns.pl $(srcdir)/insns.dat
+insnsa.c: insns.dat insns.pl
+ perl $(srcdir)/insns.pl -a $(srcdir)/insns.dat
+insnsd.c: insns.dat insns.pl
+ perl $(srcdir)/insns.pl -d $(srcdir)/insns.dat
+insnsi.h: insns.dat insns.pl
+ perl $(srcdir)/insns.pl -i $(srcdir)/insns.dat
+insnsn.c: insns.dat insns.pl
+ perl $(srcdir)/insns.pl -n $(srcdir)/insns.dat
# This source file is generated from the standard macros file
# `standard.mac' by another Perl script. Again, it's part of the
@@ -88,26 +106,38 @@ macros.c: standard.mac macros.pl
perl $(srcdir)/macros.pl $(srcdir)/standard.mac
install: nasm ndisasm
- $(INSTALL_PROGRAM) nasm $(bindir)/nasm
- $(INSTALL_PROGRAM) ndisasm $(bindir)/ndisasm
- $(INSTALL_DATA) $(srcdir)/nasm.1 $(mandir)/man1/nasm.1
- $(INSTALL_DATA) $(srcdir)/ndisasm.1 $(mandir)/man1/ndisasm.1
+ $(INSTALL_PROGRAM) nasm $(INSTALLROOT)$(bindir)/nasm
+ $(INSTALL_PROGRAM) ndisasm $(INSTALLROOT)$(bindir)/ndisasm
+ $(INSTALL_DATA) $(srcdir)/nasm.1 $(INSTALLROOT)$(mandir)/man1/nasm.1
+ $(INSTALL_DATA) $(srcdir)/ndisasm.1 $(INSTALLROOT)$(mandir)/man1/ndisasm.1
clean:
- rm -f *.o nasm ndisasm
- cd rdoff; $(MAKE) clean
+ rm -f *.o *.s *.i nasm ndisasm
+ cd rdoff && $(MAKE) clean
distclean: clean
- rm -f config.* Makefile *~ *.bak changed.lst changed.bin
- cd rdoff; $(MAKE) distclean
+ rm -f config.* Makefile *~ *.bak *.lst *.bin
+ cd rdoff && $(MAKE) distclean
cleaner: clean
rm -f insnsa.c insnsd.c insnsi.h insnsn.c macros.c *.man
+ cd doc && $(MAKE) clean
spotless: distclean cleaner
rdf:
- cd rdoff; $(MAKE)
+ cd rdoff && $(MAKE)
rdf_install install_rdf:
- cd rdoff; $(MAKE) install
+ cd rdoff && $(MAKE) install
+
+doc:
+ cd doc && $(MAKE) all
+
+doc_install install_doc:
+ cd doc && $(MAKE) install
+
+everything: all doc rdf
+
+install_everything: everything install install_doc install_rdf
+
diff --git a/Mkfiles/Makefile.b32 b/Mkfiles/Makefile.b32
index d4422386..2e642d0f 100644
--- a/Mkfiles/Makefile.b32
+++ b/Mkfiles/Makefile.b32
@@ -1,138 +1,137 @@
-# Makefile for the Netwide Assembler under 32 bit NT console
-#
-# The Netwide Assembler is copyright (C) 1996 Simon Tatham and
-# Julian Hall. All rights reserved. The software is
-# redistributable under the licence given in the file "Licence"
-# distributed in the NASM archive.
-#
-# This Makefile is designed to build NASM with the latest
-# version of Borland C++Builder and has been tested with
-# Borland C++ 5.3 (Borland C++Builder 3.0) and Borland C++ 5.4
-# (Borland C++Builder 4.0) in combination with
-# Borland MAKE versions 5.1 and 5.2
-#
-# MAKEFILE is maintained by Stefan.Hoffmeister@Econos.de
-#
-
-
-# If "BINDIR=C:\...." has not been defined on the command line
-# assume that the binary files are in the same directory as the
-# MAKE utility
-!message ****************************************************
-!message Note:
-!message -----
-!if $d(BINDIR)
- !message Path to tools set to $(BINDIR)
-!else
- BINDIR=$(MAKEDIR)
- !message Assuming path to tools to be $(BINDIR)
- !message
- !message You can change this assumption by specifying
- !message -DBINDIR=C:\my_path
- !message as a command line paramter for MAKE
-!endif
-!message ****************************************************
-
-
-CC=$(BINDIR)\bcc32
-CCFLAGS=-tWC -c -O2 -A
- # /-tWC: Windows console mode application
- # /c: Compile, do not link
- # /O2: Optimize for speed
- # /A: ANSI compatible code only
-
-LINK=$(BINDIR)\ilink32
-LINKFLAGS=/V4.0 /x /c /ap /L$(BINDIR)\..\LIB # /L -> default LIB directory
- # /V4.0: marked as Win95 / NT application in PE header
- # /x: no map file
- # /c: case sensitive link
- # /ap: link for 32-bit console application
- # /L...: path to .lib directory
-
-
-# default libraries for Win32 console applications
-LIBRARIES=cw32.lib import32.lib
-# default startup code for Win32 console applications
-STARTUP=c0x32.obj
-
-# default extension for our EXE
-EXE=.exe
-# default extension for OBJ files
-OBJ=obj
-
-
-SUFFIX= w# # by default, this makefile produces nasmw.exe and ndisasmw.exe
-
-
-# Builds C files to OBJ
-.c.$(OBJ):
- $(CC) $(CCFLAGS) $*.c
-
-
-NASMOBJS = nasm.$(OBJ) nasmlib.$(OBJ) float.$(OBJ) insnsa.$(OBJ) \
- assemble.$(OBJ) labels.$(OBJ) parser.$(OBJ) outform.$(OBJ) \
- outbin.$(OBJ) outaout.$(OBJ) outcoff.$(OBJ) outelf.$(OBJ) \
- outobj.$(OBJ) outas86.$(OBJ) outrdf.$(OBJ) outdbg.$(OBJ) \
- outrdf2.$(OBJ) zoutieee.$(OBJ) \
- preproc.$(OBJ) listing.$(OBJ) eval.$(OBJ)
-
-NDISASMOBJS = ndisasm.$(OBJ) disasm.$(OBJ) sync.$(OBJ) nasmlib.$(OBJ) \
- insnsd.$(OBJ)
-
-
-BuildAll: nasm$(SUFFIX)$(EXE) ndisasm$(SUFFIX)$(EXE)
-
-
-# NASM
-nasm$(SUFFIX)$(EXE): $(NASMOBJS)
- $(LINK) $(LINKFLAGS) @&&| #open temp response file
- $(STARTUP) $**
- nasm$(SUFFIX)$(EXE)
- # default MAP file name for EXE
- $(LIBRARIES)
-| # close temp file, first column!
-
-
-# NDISASM
-ndisasm$(SUFFIX)$(EXE): $(NDISASMOBJS)
- $(LINK) $(LINKFLAGS) @&&| #open temp response file
- $(STARTUP) $**
- ndisasm$(SUFFIX)$(EXE)
- # default MAP file name for EXE
- $(LIBRARIES)
-| # close temp file, first column!
-
-
-# OBJs with dependencies
-assemble.$(OBJ): assemble.c nasm.h insnsi.h assemble.h insns.h
-disasm.$(OBJ): disasm.c nasm.h insnsi.h disasm.h sync.h insns.h names.c insnsn.c
-eval.$(OBJ): eval.c nasm.h insnsi.h nasmlib.h eval.h
-float.$(OBJ): float.c nasm.h insnsi.h
-insnsa.$(OBJ): insnsa.c nasm.h insnsi.h insns.h
-insnsd.$(OBJ): insnsd.c nasm.h insnsi.h insns.h
-labels.$(OBJ): labels.c nasm.h insnsi.h nasmlib.h
-listing.$(OBJ): listing.c nasm.h insnsi.h nasmlib.h listing.h
-nasm.$(OBJ): nasm.c nasm.h insnsi.h nasmlib.h parser.h assemble.h labels.h \
- listing.h outform.h
-nasmlib.$(OBJ): nasmlib.c nasm.h insnsi.h nasmlib.h
-ndisasm.$(OBJ): ndisasm.c nasm.h insnsi.h sync.h disasm.h
-outas86.$(OBJ): outas86.c nasm.h insnsi.h nasmlib.h
-outaout.$(OBJ): outaout.c nasm.h insnsi.h nasmlib.h
-outbin.$(OBJ): outbin.c nasm.h insnsi.h nasmlib.h
-outcoff.$(OBJ): outcoff.c nasm.h insnsi.h nasmlib.h
-outdbg.$(OBJ): outdbg.c nasm.h insnsi.h nasmlib.h
-outelf.$(OBJ): outelf.c nasm.h insnsi.h nasmlib.h
-outobj.$(OBJ): outobj.c nasm.h insnsi.h nasmlib.h
-outrdf.$(OBJ): outrdf.c nasm.h insnsi.h nasmlib.h
-outrdf2.$(OBJ): outrdf2.c nasm.h insnsi.h nasmlib.h
-zoutieee.$(OBJ): zoutieee.c nasm.h insnsi.h nasmlib.h
-outform.$(OBJ): outform.c outform.h nasm.h insnsi.h
-parser.$(OBJ): parser.c nasm.h insnsi.h nasmlib.h parser.h float.h names.c insnsn.c
-preproc.$(OBJ): preproc.c macros.c preproc.h nasm.h insnsi.h nasmlib.h
-sync.$(OBJ): sync.c sync.h
-
-clean:
- del *.obj
- del nasm$(SUFFIX)$(EXE)
- del ndisasm$(SUFFIX)$(EXE)
-
+# Makefile for the Netwide Assembler under 32 bit NT console
+#
+# The Netwide Assembler is copyright (C) 1996 Simon Tatham and
+# Julian Hall. All rights reserved. The software is
+# redistributable under the licence given in the file "Licence"
+# distributed in the NASM archive.
+#
+# This Makefile is designed to build NASM with the latest
+# version of Borland C++Builder and has been tested with
+# Borland C++ 5.3 (Borland C++Builder 3.0) and Borland C++ 5.4
+# (Borland C++Builder 4.0) in combination with
+# Borland MAKE versions 5.1 and 5.2
+#
+# MAKEFILE is maintained by Stefan.Hoffmeister@Econos.de
+#
+
+
+# If "BINDIR=C:\...." has not been defined on the command line
+# assume that the binary files are in the same directory as the
+# MAKE utility
+!message ****************************************************
+!message Note:
+!message -----
+!if $d(BINDIR)
+ !message Path to tools set to $(BINDIR)
+!else
+ BINDIR=$(MAKEDIR)
+ !message Assuming path to tools to be $(BINDIR)
+ !message
+ !message You can change this assumption by specifying
+ !message -DBINDIR=C:\my_path
+ !message as a command line paramter for MAKE
+!endif
+!message ****************************************************
+
+
+CC=$(BINDIR)\bcc32
+CCFLAGS=-tWC -c -O2 -A
+ # /-tWC: Windows console mode application
+ # /c: Compile, do not link
+ # /O2: Optimize for speed
+ # /A: ANSI compatible code only
+
+LINK=$(BINDIR)\ilink32
+LINKFLAGS=/V4.0 /x /c /ap /L$(BINDIR)\..\LIB # /L -> default LIB directory
+ # /V4.0: marked as Win95 / NT application in PE header
+ # /x: no map file
+ # /c: case sensitive link
+ # /ap: link for 32-bit console application
+ # /L...: path to .lib directory
+
+
+# default libraries for Win32 console applications
+LIBRARIES=cw32.lib import32.lib
+# default startup code for Win32 console applications
+STARTUP=c0x32.obj
+
+# default extension for our EXE
+EXE=.exe
+# default extension for OBJ files
+OBJ=obj
+
+
+SUFFIX= w# # by default, this makefile produces nasmw.exe and ndisasmw.exe
+
+
+# Builds C files to OBJ
+.c.$(OBJ):
+ $(CC) $(CCFLAGS) $*.c
+
+
+NASMOBJS = nasm.$(OBJ) nasmlib.$(OBJ) float.$(OBJ) insnsa.$(OBJ) \
+ assemble.$(OBJ) labels.$(OBJ) parser.$(OBJ) outform.$(OBJ) \
+ outbin.$(OBJ) outaout.$(OBJ) outcoff.$(OBJ) outelf.$(OBJ) \
+ outobj.$(OBJ) outas86.$(OBJ) outrdf.$(OBJ) outdbg.$(OBJ) \
+ outrdf2.$(OBJ) zoutieee.$(OBJ) \
+ preproc.$(OBJ) listing.$(OBJ) eval.$(OBJ)
+
+NDISASMOBJS = ndisasm.$(OBJ) disasm.$(OBJ) sync.$(OBJ) nasmlib.$(OBJ) \
+ insnsd.$(OBJ)
+
+
+BuildAll: nasm$(SUFFIX)$(EXE) ndisasm$(SUFFIX)$(EXE)
+
+
+# NASM
+nasm$(SUFFIX)$(EXE): $(NASMOBJS)
+ $(LINK) $(LINKFLAGS) @&&| #open temp response file
+ $(STARTUP) $**
+ nasm$(SUFFIX)$(EXE)
+ # default MAP file name for EXE
+ $(LIBRARIES)
+| # close temp file, first column!
+
+
+# NDISASM
+ndisasm$(SUFFIX)$(EXE): $(NDISASMOBJS)
+ $(LINK) $(LINKFLAGS) @&&| #open temp response file
+ $(STARTUP) $**
+ ndisasm$(SUFFIX)$(EXE)
+ # default MAP file name for EXE
+ $(LIBRARIES)
+| # close temp file, first column!
+
+
+# OBJs with dependencies
+assemble.$(OBJ): assemble.c nasm.h insnsi.h assemble.h insns.h
+disasm.$(OBJ): disasm.c nasm.h insnsi.h disasm.h sync.h insns.h names.c insnsn.c
+eval.$(OBJ): eval.c nasm.h insnsi.h nasmlib.h eval.h
+float.$(OBJ): float.c nasm.h insnsi.h
+insnsa.$(OBJ): insnsa.c nasm.h insnsi.h insns.h
+insnsd.$(OBJ): insnsd.c nasm.h insnsi.h insns.h
+labels.$(OBJ): labels.c nasm.h insnsi.h nasmlib.h
+listing.$(OBJ): listing.c nasm.h insnsi.h nasmlib.h listing.h
+nasm.$(OBJ): nasm.c nasm.h insnsi.h nasmlib.h parser.h assemble.h labels.h \
+ listing.h outform.h
+nasmlib.$(OBJ): nasmlib.c nasm.h insnsi.h nasmlib.h names.c insnsn.c
+ndisasm.$(OBJ): ndisasm.c nasm.h insnsi.h sync.h disasm.h
+outas86.$(OBJ): outas86.c nasm.h insnsi.h nasmlib.h
+outaout.$(OBJ): outaout.c nasm.h insnsi.h nasmlib.h
+outbin.$(OBJ): outbin.c nasm.h insnsi.h nasmlib.h
+outcoff.$(OBJ): outcoff.c nasm.h insnsi.h nasmlib.h
+outdbg.$(OBJ): outdbg.c nasm.h insnsi.h nasmlib.h
+outelf.$(OBJ): outelf.c nasm.h insnsi.h nasmlib.h
+outobj.$(OBJ): outobj.c nasm.h insnsi.h nasmlib.h
+outrdf.$(OBJ): outrdf.c nasm.h insnsi.h nasmlib.h
+outrdf2.$(OBJ): outrdf2.c nasm.h insnsi.h nasmlib.h
+zoutieee.$(OBJ): zoutieee.c nasm.h insnsi.h nasmlib.h
+outform.$(OBJ): outform.c outform.h nasm.h insnsi.h
+parser.$(OBJ): parser.c nasm.h insnsi.h nasmlib.h parser.h float.h names.c insnsn.c
+preproc.$(OBJ): preproc.c macros.c preproc.h nasm.h insnsi.h nasmlib.h
+sync.$(OBJ): sync.c sync.h
+
+clean:
+ del *.obj
+ del nasm$(SUFFIX)$(EXE)
+ del ndisasm$(SUFFIX)$(EXE)
diff --git a/Mkfiles/Makefile.bc2 b/Mkfiles/Makefile.bc2
index 996cddca..69a376df 100644
--- a/Mkfiles/Makefile.bc2
+++ b/Mkfiles/Makefile.bc2
@@ -158,7 +158,7 @@ $(OBJD)nasm.$(OBJ): nasm.c nasm.h insnsi.h nasmlib.h parser.h assemble.h labels.
listing.h outform.h
$(NASM_ASM)
-$(OBJD)nasmlib.$(OBJ): nasmlib.c nasm.h insnsi.h nasmlib.h
+$(OBJD)nasmlib.$(OBJ): nasmlib.c nasm.h insnsi.h nasmlib.h names.c insnsn.c
$(NASM_ASM)
$(OBJD)parser.$(OBJ): parser.c nasm.h insnsi.h nasmlib.h parser.h float.h names.c insnsn.c
diff --git a/Mkfiles/Makefile.bor b/Mkfiles/Makefile.bor
index d5883a14..d0303951 100644
--- a/Mkfiles/Makefile.bor
+++ b/Mkfiles/Makefile.bor
@@ -63,7 +63,7 @@ labels.$(OBJ): labels.c nasm.h insnsi.h nasmlib.h
listing.$(OBJ): listing.c nasm.h insnsi.h nasmlib.h listing.h
nasm.$(OBJ): nasm.c nasm.h insnsi.h nasmlib.h parser.h assemble.h labels.h \
listing.h outform.h
-nasmlib.$(OBJ): nasmlib.c nasm.h insnsi.h nasmlib.h
+nasmlib.$(OBJ): nasmlib.c nasm.h insnsi.h nasmlib.h names.c insnsn.c
ndisasm.$(OBJ): ndisasm.c nasm.h insnsi.h sync.h disasm.h
outas86.$(OBJ): outas86.c nasm.h insnsi.h nasmlib.h
outaout.$(OBJ): outaout.c nasm.h insnsi.h nasmlib.h
diff --git a/Mkfiles/Makefile.dj b/Mkfiles/Makefile.dj
index 3e24036c..7cb2399d 100644
--- a/Mkfiles/Makefile.dj
+++ b/Mkfiles/Makefile.dj
@@ -46,7 +46,7 @@ labels.o: labels.c nasm.h insnsi.h nasmlib.h
listing.o: listing.c nasm.h insnsi.h nasmlib.h listing.h
nasm.o: nasm.c nasm.h insnsi.h nasmlib.h preproc.h parser.h assemble.h labels.h \
outform.h listing.h
-nasmlib.o: nasmlib.c nasm.h insnsi.h nasmlib.h
+nasmlib.o: nasmlib.c nasm.h insnsi.h nasmlib.h names.c insnsn.c
ndisasm.o: ndisasm.c nasm.h insnsi.h nasmlib.h sync.h disasm.h
outaout.o: outaout.c nasm.h insnsi.h nasmlib.h outform.h
outas86.o: outas86.c nasm.h insnsi.h nasmlib.h outform.h
diff --git a/Mkfiles/Makefile.djo b/Mkfiles/Makefile.djo
index 575abdcc..d69a4dfe 100644
--- a/Mkfiles/Makefile.djo
+++ b/Mkfiles/Makefile.djo
@@ -97,7 +97,7 @@ labels.o: labels.c nasm.h insnsi.h nasmlib.h
listing.o: listing.c nasm.h insnsi.h nasmlib.h listing.h
nasm.o: nasm.c nasm.h insnsi.h nasmlib.h preproc.h parser.h assemble.h labels.h \
outform.h listing.h
-nasmlib.o: nasmlib.c nasm.h insnsi.h nasmlib.h
+nasmlib.o: nasmlib.c nasm.h insnsi.h nasmlib.h names.c insnsn.c
ndisasm.o: ndisasm.c nasm.h insnsi.h nasmlib.h sync.h disasm.h
outaout.o: outaout.c nasm.h insnsi.h nasmlib.h outform.h
outas86.o: outas86.c nasm.h insnsi.h nasmlib.h outform.h
diff --git a/Mkfiles/Makefile.dos b/Mkfiles/Makefile.dos
index 804fa629..6835e7df 100644
--- a/Mkfiles/Makefile.dos
+++ b/Mkfiles/Makefile.dos
@@ -50,7 +50,7 @@ labels.$(OBJ): labels.c nasm.h insnsi.h nasmlib.h
listing.$(OBJ): listing.c nasm.h insnsi.h nasmlib.h listing.h
nasm.$(OBJ): nasm.c nasm.h insnsi.h nasmlib.h parser.h assemble.h labels.h \
listing.h outform.h
-nasmlib.$(OBJ): nasmlib.c nasm.h insnsi.h nasmlib.h
+nasmlib.$(OBJ): nasmlib.c nasm.h insnsi.h nasmlib.h names.c insnsn.c
ndisasm.$(OBJ): ndisasm.c nasm.h insnsi.h sync.h disasm.h
outas86.$(OBJ): outas86.c nasm.h insnsi.h nasmlib.h
outaout.$(OBJ): outaout.c nasm.h insnsi.h nasmlib.h
diff --git a/Mkfiles/Makefile.lcc b/Mkfiles/Makefile.lcc
index f1911dd1..3c2c205d 100644
--- a/Mkfiles/Makefile.lcc
+++ b/Mkfiles/Makefile.lcc
@@ -78,7 +78,7 @@ labels.${OBJ}: labels.c nasm.h insnsi.h nasmlib.h
listing.${OBJ}: listing.c nasm.h insnsi.h nasmlib.h listing.h
nasm.${OBJ}: nasm.c nasm.h insnsi.h nasmlib.h preproc.h parser.h assemble.h labels.h \
outform.h listing.h
-nasmlib.${OBJ}: nasmlib.c nasm.h insnsi.h nasmlib.h
+nasmlib.${OBJ}: nasmlib.c nasm.h insnsi.h nasmlib.h names.c insnsn.c
ndisasm.${OBJ}: ndisasm.c nasm.h insnsi.h nasmlib.h sync.h disasm.h
outaout.${OBJ}: outaout.c nasm.h insnsi.h nasmlib.h outform.h
outas86.${OBJ}: outas86.c nasm.h insnsi.h nasmlib.h outform.h
diff --git a/Mkfiles/Makefile.os2 b/Mkfiles/Makefile.os2
index 3ebbac12..0d99283d 100644
--- a/Mkfiles/Makefile.os2
+++ b/Mkfiles/Makefile.os2
@@ -125,7 +125,7 @@ $(OBJD)nasm.$(OBJ): nasm.c nasm.h nasmlib.h parser.h assemble.h labels.h \
listing.h outform.h
$(NASM_ASM)
-$(OBJD)nasmlib.$(OBJ): nasmlib.c nasm.h nasmlib.h
+$(OBJD)nasmlib.$(OBJ): nasmlib.c nasm.h nasmlib.h names.c insnsn.c
$(NASM_ASM)
$(OBJD)parser.$(OBJ): parser.c nasm.h nasmlib.h parser.h float.h names.c
diff --git a/Mkfiles/Makefile.sc b/Mkfiles/Makefile.sc
index a892575b..325a7525 100644
--- a/Mkfiles/Makefile.sc
+++ b/Mkfiles/Makefile.sc
@@ -90,7 +90,7 @@ labels.$(OBJ): labels.c nasm.h insnsi.h nasmlib.h
listing.$(OBJ): listing.c nasm.h insnsi.h nasmlib.h listing.h
nasm.$(OBJ): nasm.c nasm.h insnsi.h nasmlib.h parser.h assemble.h labels.h \
listing.h outform.h
-nasmlib.$(OBJ): nasmlib.c nasm.h insnsi.h nasmlib.h
+nasmlib.$(OBJ): nasmlib.c nasm.h insnsi.h nasmlib.h names.c insnsn.c
ndisasm.$(OBJ): ndisasm.c nasm.h insnsi.h sync.h disasm.h
outas86.$(OBJ): outas86.c nasm.h insnsi.h nasmlib.h
outaout.$(OBJ): outaout.c nasm.h insnsi.h nasmlib.h
diff --git a/Mkfiles/Makefile.scw b/Mkfiles/Makefile.scw
index 5b7287a6..510b72a6 100644
--- a/Mkfiles/Makefile.scw
+++ b/Mkfiles/Makefile.scw
@@ -90,7 +90,7 @@ labels.$(OBJ): labels.c nasm.h insnsi.h nasmlib.h
listing.$(OBJ): listing.c nasm.h insnsi.h nasmlib.h listing.h
nasm.$(OBJ): nasm.c nasm.h insnsi.h nasmlib.h parser.h assemble.h labels.h \
listing.h outform.h
-nasmlib.$(OBJ): nasmlib.c nasm.h insnsi.h nasmlib.h
+nasmlib.$(OBJ): nasmlib.c nasm.h insnsi.h nasmlib.h names.c insnsn.c
ndisasm.$(OBJ): ndisasm.c nasm.h insnsi.h sync.h disasm.h
outas86.$(OBJ): outas86.c nasm.h insnsi.h nasmlib.h
outaout.$(OBJ): outaout.c nasm.h insnsi.h nasmlib.h
diff --git a/Mkfiles/Makefile.unx b/Mkfiles/Makefile.unx
index 37fd7a06..ef47696a 100644
--- a/Mkfiles/Makefile.unx
+++ b/Mkfiles/Makefile.unx
@@ -42,7 +42,7 @@ nasm: $(NASM)
ndisasm: $(NDISASM)
$(CC) -o ndisasm $(NDISASM)
-assemble.o: assemble.c nasm.h insnsi.h nasmlib.h assemble.h insns.h
+assemble.o: assemble.c nasm.h insnsi.h nasmlib.h assemble.h insnsn.c
disasm.o: disasm.c nasm.h insnsi.h disasm.h sync.h insns.h names.c insnsn.c
eval.o: eval.c eval.h nasm.h insnsi.h nasmlib.h
float.o: float.c nasm.h insnsi.h
@@ -52,7 +52,7 @@ labels.o: labels.c nasm.h insnsi.h nasmlib.h
listing.o: listing.c nasm.h insnsi.h nasmlib.h listing.h
nasm.o: nasm.c nasm.h insnsi.h nasmlib.h preproc.h parser.h assemble.h labels.h \
outform.h listing.h
-nasmlib.o: nasmlib.c nasm.h insnsi.h nasmlib.h
+nasmlib.o: nasmlib.c nasm.h insnsi.h nasmlib.h names.c insnsn.c
ndisasm.o: ndisasm.c nasm.h insnsi.h nasmlib.h sync.h disasm.h
outaout.o: outaout.c nasm.h insnsi.h nasmlib.h outform.h
outas86.o: outas86.c nasm.h insnsi.h nasmlib.h outform.h
diff --git a/Mkfiles/Makefile.vc b/Mkfiles/Makefile.vc
index e4ddc498..1e0ef1c4 100644
--- a/Mkfiles/Makefile.vc
+++ b/Mkfiles/Makefile.vc
@@ -49,7 +49,7 @@ labels.$(OBJ): labels.c nasm.h insnsi.h nasmlib.h
listing.$(OBJ): listing.c nasm.h insnsi.h nasmlib.h listing.h
nasm.$(OBJ): nasm.c nasm.h insnsi.h nasmlib.h parser.h assemble.h labels.h \
listing.h outform.h
-nasmlib.$(OBJ): nasmlib.c nasm.h insnsi.h nasmlib.h
+nasmlib.$(OBJ): nasmlib.c nasm.h insnsi.h nasmlib.h names.c insnsn.c
ndisasm.$(OBJ): ndisasm.c nasm.h insnsi.h sync.h disasm.h
outas86.$(OBJ): outas86.c nasm.h insnsi.h nasmlib.h
outaout.$(OBJ): outaout.c nasm.h insnsi.h nasmlib.h
diff --git a/Mkfiles/Makefile.wcw b/Mkfiles/Makefile.wcw
index 1a213272..289c45de 100644
--- a/Mkfiles/Makefile.wcw
+++ b/Mkfiles/Makefile.wcw
@@ -101,7 +101,7 @@ labels.$(OBJ): labels.c nasm.h insnsi.h nasmlib.h
listing.$(OBJ): listing.c nasm.h insnsi.h nasmlib.h listing.h
nasm.$(OBJ): nasm.c nasm.h insnsi.h nasmlib.h parser.h assemble.h labels.h \
listing.h outform.h
-nasmlib.$(OBJ): nasmlib.c nasm.h insnsi.h nasmlib.h
+nasmlib.$(OBJ): nasmlib.c nasm.h insnsi.h nasmlib.h names.c insnsn.c
ndisasm.$(OBJ): ndisasm.c nasm.h insnsi.h sync.h disasm.h
outas86.$(OBJ): outas86.c nasm.h insnsi.h nasmlib.h
outaout.$(OBJ): outaout.c nasm.h insnsi.h nasmlib.h
diff --git a/assemble.c b/assemble.c
index 426bae23..fef2ab77 100644
--- a/assemble.c
+++ b/assemble.c
@@ -177,7 +177,8 @@ long assemble (long segment, long offset, int bits,
errfunc (ERR_NONFATAL,
"one-byte relocation attempted");
else {
- out (offset, segment, &e->offset, OUT_RAWDATA+1,
+ unsigned char out_byte = e->offset;
+ out (offset, segment, &out_byte, OUT_RAWDATA+1,
NO_SEG, NO_SEG);
}
}
diff --git a/changed.asm b/changed.asm
index b0fd4241..29818d1b 100644
--- a/changed.asm
+++ b/changed.asm
@@ -322,6 +322,34 @@ arg_example2 arg2
%error "TEST_ME defined after %undef"
%endif
+;-----------------------------------------------------------------------------
+; Bug fix by hpa in insns.dat
+;
+; PSHUFW and PINSRW weren't handling the implicit sizes correctly; all of
+; the entries below are (or should be) legal
+;
+ pshufw mm2, mm1, 3
+ pshufw mm3,[ebx],2
+ pshufw mm7,[0+edi*8],1
+
+ pshufw mm2, mm1, byte 3
+ pshufw mm3,[ebx],byte 2
+ pshufw mm7,[0+edi*8],byte 1
+
+ pshufw mm2, mm1, 3
+ pshufw mm3, qword [ebx], 2
+ pshufw mm7, qword [0+edi*8], 1
+
+ pshufw mm2, mm1, byte 3
+ pshufw mm3, qword [ebx], byte 2
+ pshufw mm7, qword [0+edi*8], byte 1
+
+ pinsrw mm1, [esi], 1
+ pinsrw mm1, word [esi], 1
+ pinsrw mm1, [esi], byte 1
+ pinsrw mm1, word [esi], byte 1
+
+
%endif ; oldmsg
%ifdef oldcrash ;*************************************************************
diff --git a/configure.in b/configure.in
index 6555596f..bb551f28 100644
--- a/configure.in
+++ b/configure.in
@@ -111,4 +111,4 @@ if test $ac_cv_prog_make_vpathok = no; then
if test ! -f macros.c; then cp -p ${srcdir}/macros.c .; fi
fi
-AC_OUTPUT(Makefile rdoff/Makefile)
+AC_OUTPUT(Makefile rdoff/Makefile doc/Makefile)
diff --git a/doc/Makefile b/doc/Makefile
deleted file mode 100644
index c5104052..00000000
--- a/doc/Makefile
+++ /dev/null
@@ -1,29 +0,0 @@
-#
-# UNIX Makefile for NASM documentation
-#
-
-SRCS = nasmdoc.src
-OUT = nasm.info
-
-all: $(OUT)
-
-.SUFFIXES: .src .texi .info .ps .rtf .hpj .ps .txt .pl
-
-# Consider html, txt and src output a side effect
-.src.texi:
- mkdir -p html
- perl ./rdsrc.pl < $<
- mv -f *.html html
-
-nasm.info: nasmdoc.texi
- mkdir -p info
- makeinfo $<
- mv -f *.info *.info-* info
-
-clean:
- -rm -f *.rtf *.hpj *.texi
-
-spotless: clean
- -rm -rf html info *.hlp *.txt *.ps
-
-
diff --git a/doc/Makefile.in b/doc/Makefile.in
new file mode 100644
index 00000000..78fafa3b
--- /dev/null
+++ b/doc/Makefile.in
@@ -0,0 +1,50 @@
+# $Id$
+#
+# UNIX Makefile for NASM documentation
+#
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+bindir = @bindir@
+mandir = @mandir@
+docdir = $(prefix)/doc/nasm
+infodir = @infodir@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+
+PERL = perl
+MAKEINFO = makeinfo
+
+SRCS = nasmdoc.src
+OUT = nasm.info
+
+all: $(OUT)
+
+.SUFFIXES: .src .texi .info .ps .rtf .hpj .dvi .ps .txt .pl
+
+# Consider html, txt and src output a side effect
+.src.texi:
+ mkdir -p html
+ $(PERL) ./rdsrc.pl < $<
+ mv -f *.html html
+
+nasm.info: nasmdoc.texi
+ mkdir -p info
+ $(MAKEINFO) $<
+ mv -f *.info *.info-* info
+
+clean:
+ -rm -f *.rtf *.hpj *.texi *.ph *.gid
+
+spotless: clean
+ -rm -rf html info *.hlp *.txt *.ps
+
+install: all
+ $(INSTALL_DATA) info/* $(INSTALLROOT)$(infodir)
+ mkdir -p $(INSTALLROOT)$(docdir)/html
+ $(INSTALL_DATA) html/* $(INSTALLROOT)$(docdir)/html
+ $(INSTALL_DATA) nasmdoc.ps nasmdoc.txt $(INSTALLROOT)$(docdir)
diff --git a/doc/nasmdoc.src b/doc/nasmdoc.src
index 2828c7f3..29657073 100644
--- a/doc/nasmdoc.src
+++ b/doc/nasmdoc.src
@@ -1,12 +1,22 @@
-\IR{-o} \c{-o} option
+\# $Id$
+\#
+\# Source code to NASM documentation
+\#
+\IR{-D} \c{-D} option
+\IR{-E} \c{-E} option
+\IR{-I} \c{-I} option
+\IR{-P} \c{-P} option
+\IR{-U} \c{-U} option
+\IR{-a} \c{-a} option
+\IR{-d} \c{-d} option
+\IR{-e} \c{-e} option
\IR{-f} \c{-f} option
-\IR{-l} \c{-l} option
-\IR{-s} \c{-s} option
\IR{-i} \c{-i} option
+\IR{-l} \c{-l} option
+\IR{-o} \c{-o} option
\IR{-p} \c{-p} option
-\IR{-d} \c{-d} option
-\IR{-e} \c{-e} option
-\IR{-a} \c{-a} option
+\IR{-s} \c{-s} option
+\IR{-u} \c{-u} option
\IR{-w} \c{-w} option
\IR{!=} \c{!=} operator
\IR{$ here} \c{$} Here token
@@ -226,14 +236,19 @@ may use NASM.
\H{contact} Contact Information
+The current version of NASM (since 0.98) are maintained by H. Peter
+Anvin, \W{mailto:hpa@zytor.com}\c{hpa@zytor.com}. If you want to report
+a bug, please read \k{bugs} first.
+
NASM has a \i{WWW page} at
-\W{http://www.cryogen.com/Nasm}\c{http://www.cryogen.com/Nasm}. The
-authors are \i{e\-mail}able as
+\W{http://www.cryogen.com/Nasm}\c{http://www.cryogen.com/Nasm}.
+
+The original authors are \i{e\-mail}able as
\W{mailto:jules@earthcorp.com}\c{jules@earthcorp.com} and
-\W{mailto:anakin@pobox.com}\c{anakin@pobox.com}. If you want to
-report a bug to us, please read \k{bugs} first.
+\W{mailto:anakin@pobox.com}\c{anakin@pobox.com}.
\i{New releases} of NASM are uploaded to
+\W{ftp://ftp.kernel.org/pub/software/devel/nasm/}\i\c{ftp.kernel.org},
\W{ftp://sunsite.unc.edu/pub/Linux/devel/lang/assemblers/}\i\c{sunsite.unc.edu},
\W{ftp://ftp.simtel.net/pub/simtelnet/msdos/asmutl/}\i\c{ftp.simtel.net}
and
@@ -247,9 +262,15 @@ Announcements are posted to
\W{ftp://ftp.simtel.net/pub/simtelnet/msdos/asmutl/}\c{ftp.simtel.net}).
If you don't have Usenet access, or would rather be informed by
-\i{e\-mail} when new releases come out, e\-mail
-\W{mailto:anakin@pobox.com}\c{anakin@pobox.com}
-and ask.
+\i{e\-mail} when new releases come out, you can subscribe to the
+\c{nasm-announce} email list by sending an email containing the line
+\c{subscribe nasm-announce} to
+\W{mailto:majordomo@linux.kernel.org}\c{majordomo@linux.kernel.org}.
+
+If you want information about NASM beta releases, please subscribe to
+the \c{nasm-beta} email list by sending an email containing the line
+\c{subscribe nasm-beta} to
+\W{mailto:majordomo@linux.kernel.org}\c{majordomo@linux.kernel.org}.
\H{install} Installation
@@ -281,14 +302,20 @@ want to keep the documentation or test programs.
If you've downloaded the \i{DOS source archive}, \i\c{nasmXXXs.zip},
the \c{nasm} directory will also contain the full NASM \i{source
code}, and a selection of \i{Makefiles} you can (hopefully) use to
-rebuild your copy of NASM from scratch. The file \c{Readme} lists
-the various Makefiles and which compilers they work with. Note that
-the source files \c{insnsa.c} and \c{insnsd.c} are automatically
-generated from the master instruction table \c{insns.dat} by a Perl
-script; a \i{QBasic} version of the program is provided, but it is
-recommended that you use the Perl version. A DOS port of \i{Perl} is
-available from
-\W{http://www.perl.org/CPAN/ports/msdos/}\i{www.perl.org}.
+rebuild your copy of NASM from scratch. The file \c{Readme} lists the
+various Makefiles and which compilers they work with.
+
+Note that the source files \c{insnsa.c}, \c{insnsd.c}, \c{insnsi.h}
+and \c{insnsn.c} are automatically generated from the master
+instruction table \c{insns.dat} by a Perl script; the file
+\c{macros.c} is generated from \c{standard.mac} by another Perl
+script. Although the NASM 0.98 distribution includes these generated
+files, you will need to rebuild them (and hence, will need a Perl
+interpreter) if you change \c{insns.dat}, \c{standard.mac} or the
+documentation. It is possible future source distributions may not
+include these files at all. Ports of \i{Perl} for a variety of
+platforms, including DOS and Windows, are available from
+\W{http://www.cpan.org/ports/}\i{www.cpan.org}.
\S{instdos} Installing NASM under \i{Unix}
@@ -369,7 +396,8 @@ when you want NASM to produce Linux object files. If it says
\c nasm: Linux/i386 demand-paged executable (QMAGIC)
or something similar, your system is \c{a.out}, and you should use
-\c{-f aout} instead.
+\c{-f aout} instead (Linux \c{a.out} systems are considered obsolete,
+and are rare these days.)
Like Unix compilers and assemblers, NASM is silent unless it
goes wrong: you won't see any output at all, unless it gives error
@@ -427,7 +455,7 @@ right. For example:
\c nasm -f elf myfile.asm -l myfile.lst
-\S{opt-s} The \i\c{-s} Option: Send Errors to \i\c{stdout}
+\S{opt-E} The \i\c{-E} Option: Send Errors to a File
Under MS-\i{DOS} it can be difficult (though there are ways) to
redirect the standard-error output of a program to a file. Since
@@ -435,14 +463,25 @@ NASM usually produces its warning and \i{error messages} on
\i\c{stderr}, this can make it hard to capture the errors if (for
example) you want to load them into an editor.
-NASM therefore provides the \c{-s} option, requiring no argument,
-which causes errors to be sent to standard output rather than
+NASM therefore provides the \c{-E} option, taking a filename argument
+which causes errors to be sent to the specified files rather than
standard error. Therefore you can \I{redirecting errors}redirect
the errors into a file by typing
-\c nasm -s -f obj myfile.asm > myfile.err
+\c nasm -E myfile.err -f obj myfile.asm
+
+\S{opt-s} The \i\c{-s} Option: Send Errors to \i\c{stdout}
+
+The \c{-s} option redirects \i{error messages} to \c{stdout} rather
+than \c{stderr}, so it can be redirected under MS-\i{DOS}. To
+assemble the file \c{myfile.asm} and pipe its output to the \c{more}
+program, you can type:
+
+\c nasm -s -f obj myfile.asm | more
+
+See also the \c{-E} option, \k{opt-E}.
-\S{opt-i} The \i\c{-i} Option: Include File Search Directories
+\S{opt-i} The \i\c{-i}\I\c{-I} Option: Include File Search Directories
When NASM sees the \i\c{%include} directive in a source file (see
\k{include}), it will search for the given file not only in the
@@ -471,7 +510,10 @@ similar to \c{/usr/include} on Unix systems, you should place one or
more \c{-i} directives in the \c{NASM} environment variable (see
\k{nasmenv}).
-\S{opt-p} The \i\c{-p} Option: \I{pre-including files}Pre-Include a File
+For Makefile compatibility with many C compilers, this option can also
+be specified as \c{-I}.
+
+\S{opt-p} The \i\c{-p}\I\c{-P} Option: \I{pre-including files}Pre-Include a File
\I\c{%include}NASM allows you to specify files to be
\e{pre-included} into your source file, by the use of the \c{-p}
@@ -482,7 +524,10 @@ option. So running
is equivalent to running \c{nasm myfile.asm} and placing the
directive \c{%include "myinc.inc"} at the start of the file.
-\S{opt-d} The \i\c{-d} Option: \I{pre-defining macros} Pre-Define a Macro
+For consistency with the \c{-I}, \c{-D} and \c{-U} options, this
+option can also be specified as \c{-P}.
+
+\S{opt-d} The \i\c{-d}\I\c{-D} Option: \I{pre-defining macros} Pre-Define a Macro
\I\c{%define}Just as the \c{-p} option gives an alternative to placing
\c{%include} directives at the start of a source file, the \c{-d}
@@ -501,6 +546,26 @@ form of the directive may be useful for selecting \i{assembly-time
options} which are then tested using \c{%ifdef}, for example
\c{-dDEBUG}.
+For Makefile compatibility with many C compilers, this option can also
+be specified as \c{-D}.
+
+\S{opt-u} The \i\c{-u}\I\c{-U} Option: \I{Undefining macros} Undefine a Macro
+
+\I\c{%undef}The \c{-u} option undefines a macro that would otherwise
+have been pre-defined, either automatically or by a \c{-p} or \c{-d}
+option specified earlier on the command lines.
+
+For example, the following command line:
+
+\c nasm myfile.asm -dFOO=100 -uFOO
+
+would result in \c{FOO} \e{not} being a predefined macro in the
+program. This is useful to override options specified at a different
+point in a Makefile.
+
+For Makefile compatibility with many C compilers, this option can also
+be specified as \c{-U}.
+
\S{opt-e} The \i\c{-e} Option: Preprocess Only
NASM allows the \i{preprocessor} to be run on its own, up to a
@@ -1427,6 +1492,22 @@ when defining single-line macros with \c{%assign} (see \k{assign}).
You can \i{pre-define} single-line macros using the `-d' option on
the NASM command line: see \k{opt-d}.
+\S{undef} Undefining macros: \i\c{%undef}
+
+Single-line macros can be removed with the \c{%undef} command. For
+example, the following sequence:
+
+\c %define foo bar
+\c %undef foo
+\c mov eax, foo
+
+will expand to the instruction \c{mov eax, foo}, since after
+\c{%undef} the macro \c{foo} is no longer defined.
+
+Macros that would otherwise be pre-defined can be undefined on the
+command-line using the `-u' option on the NASM command line: see
+\k{opt-u}.
+
\S{assign} \i{Preprocessor Variables}: \i\c{%assign}
An alternative way to define single-line macros is by means of the
@@ -5007,7 +5088,7 @@ problem and generate sensible code.
We have never yet released a version of NASM with any \e{known}
bugs. That doesn't usually stop there being plenty we didn't know
about, though. Any that you find should be reported to
-\W{mailto:anakin@pobox.com}\c{anakin@pobox.com}.
+\W{mailto:hpa@zytor.com}\c{hpa@zytor.com}.
Please read \k{qstart} first, and don't report the bug if it's
listed in there as a deliberate feature. (If you think the feature
@@ -5093,7 +5174,7 @@ each one.
It is not intended to be exhaustive documentation on the fine
details of the instructions' function, such as which exceptions they
can trigger: for such documentation, you should go to Intel's Web
-site, \W{http://www.intel.com}\c{http://www.intel.com}.
+site, \W{http://www.intel.com/}\c{http://www.intel.com/}.
Instead, this appendix is intended primarily to provide
documentation on the way the instructions may be used within NASM.
diff --git a/doc/rdsrc.pl b/doc/rdsrc.pl
index 1a981287..38044b16 100644
--- a/doc/rdsrc.pl
+++ b/doc/rdsrc.pl
@@ -1519,6 +1519,10 @@ sub write_texi {
print "\input texinfo \@c -*-texinfo-*-\n";
print "\@c \%**start of header\n";
print "\@setfilename nasm.info\n";
+ print "\@dircategory Programming\n";
+ print "\@direntry\n";
+ print "* NASM: (nasm). The Netwide Assembler for x86.\n";
+ print "\@end direntry\n";
print "\@settitle NASM: The Netwide Assembler\n";
print "\@setchapternewpage odd\n";
print "\@c \%**end of header\n";
diff --git a/insns.dat b/insns.dat
index fb2cf454..2df98934 100644
--- a/insns.dat
+++ b/insns.dat
@@ -1272,7 +1272,8 @@ PEXTRW reg32,mmxreg,imm \2\x0F\xC5\110\22 KATMAI,MMX,SB,AR2
; -- accept either, but be truthful in disassembly
PINSRW mmxreg,reg16,imm \2\x0F\xC4\110\22 KATMAI,MMX,SB,AR2
PINSRW mmxreg,reg32,imm \2\x0F\xC4\110\22 KATMAI,MMX,SB,AR2,ND
-PINSRW mmxreg,mem16,imm \301\2\x0F\xC4\110\22 KATMAI,MMX,SB,AR2
+PINSRW mmxreg,mem,imm \301\2\x0F\xC4\110\22 KATMAI,MMX,SB,AR2
+PINSRW mmxreg,mem16,imm \301\2\x0F\xC4\110\22 KATMAI,MMX,SB,AR2,ND
PMAXSW mmxreg,mmxreg \2\x0F\xEE\110 KATMAI,MMX
PMAXSW mmxreg,mem \301\2\x0F\xEE\110 KATMAI,MMX,SM
PMAXUB mmxreg,mmxreg \2\x0F\xDE\110 KATMAI,MMX
@@ -1286,5 +1287,5 @@ PMULHUW mmxreg,mmxreg \2\x0F\xE4\110 KATMAI,MMX
PMULHUW mmxreg,mem \301\2\x0F\xE4\110 KATMAI,MMX,SM
PSADBW mmxreg,mmxreg \2\x0F\xF6\110 KATMAI,MMX
PSADBW mmxreg,mem \301\2\x0F\xF6\110 KATMAI,MMX,SM
-PSHUFW mmxreg,mmxreg,imm8 \2\x0F\x70\110\22 KATMAI,MMX
-PSHUFW mmxreg,mem,imm8 \301\2\x0F\x70\110\22 KATMAI,MMX,SM
+PSHUFW mmxreg,mmxreg,imm \2\x0F\x70\110\22 KATMAI,MMX,SB,AR2
+PSHUFW mmxreg,mem,imm \301\2\x0F\x70\110\22 KATMAI,MMX,SM2,SB,AR2
diff --git a/insns.pl b/insns.pl
index d0407ec1..c1eacb17 100644
--- a/insns.pl
+++ b/insns.pl
@@ -9,7 +9,21 @@
print STDERR "Reading insns.dat...\n";
-$fname = "insns.dat" unless $fname = $ARGV[0];
+@args = ();
+undef $output;
+foreach $arg ( @ARGV ) {
+ if ( $arg =~ /^\-/ ) {
+ if ( $arg =~ /^\-([adin])$/ ) {
+ $output = $1;
+ } else {
+ die "$0: Unknown option: ${arg}\n";
+ }
+ } else {
+ push (@args, $arg);
+ }
+}
+
+$fname = "insns.dat" unless $fname = $args[0];
open (F, $fname) || die "unable to open $fname";
$line = 0;
@@ -48,137 +62,145 @@ close F;
@opcodes = sort keys(%k_opcodes);
@opcodes_cc = sort keys(%k_opcodes_cc);
-print STDERR "Writing insnsa.c...\n";
-
-open A, ">insnsa.c";
-
-print A "/* This file auto-generated from insns.dat by insns.pl" .
+if ( !defined($output) || $output eq 'a' ) {
+ print STDERR "Writing insnsa.c...\n";
+
+ open A, ">insnsa.c";
+
+ print A "/* This file auto-generated from insns.dat by insns.pl" .
" - don't edit it */\n\n";
-print A "#include <stdio.h>\n";
-print A "#include \"nasm.h\"\n";
-print A "#include \"insns.h\"\n";
-print A "\n";
-
-foreach $i (@opcodes, @opcodes_cc) {
- print A "static struct itemplate instrux_${i}[] = {\n";
- $aname = "aa_$i";
- foreach $j (@$aname) {
- print A " $j\n";
- }
- print A " {-1}\n};\n\n";
-}
-print A "struct itemplate *nasm_instructions[] = {\n";
-foreach $i (@opcodes, @opcodes_cc) {
- print A " instrux_${i},\n";
+ print A "#include <stdio.h>\n";
+ print A "#include \"nasm.h\"\n";
+ print A "#include \"insns.h\"\n";
+ print A "\n";
+
+ foreach $i (@opcodes, @opcodes_cc) {
+ print A "static struct itemplate instrux_${i}[] = {\n";
+ $aname = "aa_$i";
+ foreach $j (@$aname) {
+ print A " $j\n";
+ }
+ print A " {-1}\n};\n\n";
+ }
+ print A "struct itemplate *nasm_instructions[] = {\n";
+ foreach $i (@opcodes, @opcodes_cc) {
+ print A " instrux_${i},\n";
+ }
+ print A "};\n";
+
+ close A;
}
-print A "};\n";
-close A;
-
-print STDERR "Writing insnsd.c...\n";
-
-open D, ">insnsd.c";
-
-print D "/* This file auto-generated from insns.dat by insns.pl" .
+if ( !defined($output) || $output eq 'd' ) {
+ print STDERR "Writing insnsd.c...\n";
+
+ open D, ">insnsd.c";
+
+ print D "/* This file auto-generated from insns.dat by insns.pl" .
" - don't edit it */\n\n";
-print D "#include <stdio.h>\n";
-print D "#include \"nasm.h\"\n";
-print D "#include \"insns.h\"\n";
-print D "\n";
-
-print D "static struct itemplate instrux[] = {\n";
-foreach $j (@big) {
- print D " $j\n";
-}
-print D " {-1}\n};\n\n";
-
-for ($c=0; $c<256; $c++) {
- $h = sprintf "%02X", $c;
- print D "static struct itemplate *itable_${h}[] = {\n";
- $aname = "dd_$h";
- foreach $j (@$aname) {
- print D " instrux + $j,\n";
- }
- print D " NULL\n};\n\n";
-}
-
-print D "struct itemplate **itable[] = {\n";
-for ($c=0; $c<256; $c++) {
- printf D " itable_%02X,\n", $c;
+ print D "#include <stdio.h>\n";
+ print D "#include \"nasm.h\"\n";
+ print D "#include \"insns.h\"\n";
+ print D "\n";
+
+ print D "static struct itemplate instrux[] = {\n";
+ foreach $j (@big) {
+ print D " $j\n";
+ }
+ print D " {-1}\n};\n\n";
+
+ for ($c=0; $c<256; $c++) {
+ $h = sprintf "%02X", $c;
+ print D "static struct itemplate *itable_${h}[] = {\n";
+ $aname = "dd_$h";
+ foreach $j (@$aname) {
+ print D " instrux + $j,\n";
+ }
+ print D " NULL\n};\n\n";
+ }
+
+ print D "struct itemplate **itable[] = {\n";
+ for ($c=0; $c<256; $c++) {
+ printf D " itable_%02X,\n", $c;
+ }
+ print D "};\n";
+
+ close D;
}
-print D "};\n";
-
-close D;
-
-print STDERR "Writing insnsi.h...\n";
-
-open I, ">insnsi.h";
-print I "/* This file is auto-generated from insns.dat by insns.pl" .
+if ( !defined($output) || $output eq 'i' ) {
+ print STDERR "Writing insnsi.h...\n";
+
+ open I, ">insnsi.h";
+
+ print I "/* This file is auto-generated from insns.dat by insns.pl" .
" - don't edit it */\n\n";
-print I "/* This file in included by nasm.h */\n\n";
-
-print I "/* Instruction names */\n";
-print I "enum {";
-$first = 1;
-$maxlen = 0;
-foreach $i (@opcodes, @opcodes_cc) {
- print I "," if ( !$first );
- $first = 0;
- print I "\n\tI_${i}";
- $len = length($i);
- $len++ if ( $i =~ /cc$/ ); # Condition codes can be 3 characters long
- $maxlen = $len if ( $len > $maxlen );
+ print I "/* This file in included by nasm.h */\n\n";
+
+ print I "/* Instruction names */\n";
+ print I "enum {";
+ $first = 1;
+ $maxlen = 0;
+ foreach $i (@opcodes, @opcodes_cc) {
+ print I "," if ( !$first );
+ $first = 0;
+ print I "\n\tI_${i}";
+ $len = length($i);
+ $len++ if ( $i =~ /cc$/ ); # Condition codes can be 3 characters long
+ $maxlen = $len if ( $len > $maxlen );
+ }
+ print I "\n};\n\n";
+ print I "#define MAX_INSLEN ", $maxlen, "\n";
+
+ close I;
}
-print I "\n};\n\n";
-print I "#define MAX_INSLEN ", $maxlen, "\n";
-
-close I;
-
-print STDERR "Writing insnsn.c...\n";
-
-open N, ">insnsn.c";
-print N "/* This file is auto-generated from insns.dat by insns.pl" .
+if ( !defined($output) || $output eq 'n' ) {
+ print STDERR "Writing insnsn.c...\n";
+
+ open N, ">insnsn.c";
+
+ print N "/* This file is auto-generated from insns.dat by insns.pl" .
" - don't edit it */\n\n";
-print N "/* This file in included by names.c */\n\n";
-
-print N "static char *insn_names[] = {";
-$first = 1;
-foreach $i (@opcodes) {
- print N "," if ( !$first );
- $first = 0;
- $ilower = $i;
- $ilower =~ tr/A-Z/a-z/; # Change to lower case (Perl 4 compatible)
- print N "\n\t\"${ilower}\"";
-}
-print N "\n};\n\n";
-print N "/* Conditional instructions */\n";
-print N "static char *icn[] = {";
-$first = 1;
-foreach $i (@opcodes_cc) {
- print N "," if ( !$first );
- $first = 0;
- $ilower = $i;
- $ilower =~ s/cc$//; # Skip cc suffix
- $ilower =~ tr/A-Z/a-z/; # Change to lower case (Perl 4 compatible)
- print N "\n\t\"${ilower}\"";
-}
-
-print N "\n};\n\n";
-print N "/* and the corresponding opcodes */\n";
-print N "static int ico[] = {";
-$first = 1;
-foreach $i (@opcodes_cc) {
- print N "," if ( !$first );
- $first = 0;
- print N "\n\tI_$i";
+ print N "/* This file in included by names.c */\n\n";
+
+ print N "static char *insn_names[] = {";
+ $first = 1;
+ foreach $i (@opcodes) {
+ print N "," if ( !$first );
+ $first = 0;
+ $ilower = $i;
+ $ilower =~ tr/A-Z/a-z/; # Change to lower case (Perl 4 compatible)
+ print N "\n\t\"${ilower}\"";
+ }
+ print N "\n};\n\n";
+ print N "/* Conditional instructions */\n";
+ print N "static char *icn[] = {";
+ $first = 1;
+ foreach $i (@opcodes_cc) {
+ print N "," if ( !$first );
+ $first = 0;
+ $ilower = $i;
+ $ilower =~ s/cc$//; # Skip cc suffix
+ $ilower =~ tr/A-Z/a-z/; # Change to lower case (Perl 4 compatible)
+ print N "\n\t\"${ilower}\"";
+ }
+
+ print N "\n};\n\n";
+ print N "/* and the corresponding opcodes */\n";
+ print N "static int ico[] = {";
+ $first = 1;
+ foreach $i (@opcodes_cc) {
+ print N "," if ( !$first );
+ $first = 0;
+ print N "\n\tI_$i";
+ }
+
+ print N "\n};\n";
+
+ close N;
}
-print N "\n};\n";
-
-close N;
-
printf STDERR "Done: %d instructions\n", $insns;
sub format {
diff --git a/labels.c b/labels.c
index dc7e0759..6259986a 100644
--- a/labels.c
+++ b/labels.c
@@ -215,12 +215,14 @@ void define_label (char *label, long segment, long offset, char *special,
lptr->defn.offset = offset;
lptr->defn.is_norm = (label[0] != '.' && is_norm);
- ofmt->symdef (lptr->defn.label, segment, offset,
- !!(lptr->defn.is_global & GLOBAL_BIT),
- special ? special : lptr->defn.special);
- ofmt->current_dfmt->debug_deflabel (label, segment, offset,
- !!(lptr->defn.is_global & GLOBAL_BIT),
- special ? special : lptr->defn.special);
+ if ( (lptr->defn.is_global & (GLOBAL_BIT|EXTERN_BIT)) != EXTERN_BIT ) {
+ ofmt->symdef (lptr->defn.label, segment, offset,
+ !!(lptr->defn.is_global & GLOBAL_BIT),
+ special ? special : lptr->defn.special);
+ ofmt->current_dfmt->debug_deflabel (label, segment, offset,
+ !!(lptr->defn.is_global & GLOBAL_BIT),
+ special ? special : lptr->defn.special);
+ }
}
void define_common (char *label, long segment, long size, char *special,
diff --git a/nasm.c b/nasm.c
index 74fcc08a..3c5327a4 100644
--- a/nasm.c
+++ b/nasm.c
@@ -326,7 +326,8 @@ static int process_arg (char *p, char *q)
case '-': /* -- => stop processing options */
stopoptions = 1;
break;
- case 's': /* silently ignored for compatibility */
+ case 's':
+ error_file = stdout;
break;
case 'o': /* these parameters take values */
case 'f':
@@ -390,7 +391,8 @@ static int process_arg (char *p, char *q)
" -e preprocess only (writes output to stdout by default)\n"
" -a don't preprocess (assemble only)\n"
" -M generate Makefile dependencies on stdout\n\n"
- " -E<file> redirect error messages to file\n\n"
+ " -E<file> redirect error messages to file\n"
+ " -s redirect error messages to stdout\n\n"
" -g enable debug info\n"
" -F format select a debugging format\n\n"
" -I<path> adds a pathname to the include file path\n"
@@ -812,18 +814,6 @@ static void assemble_file (char *fname)
report_error (ERR_NONFATAL,
"EQU not preceded by label");
- /*
- * EQU cannot be used to declare a label relative to
- * an external symbol.
- */
- else if ((output_ins.oprs[0].opflags & OPFLAG_EXTERN)
- || (output_ins.operands > 1
- && (output_ins.oprs[1].opflags & OPFLAG_EXTERN)))
- {
- report_error (ERR_NONFATAL,
- "EQU used relative to external symbol");
- }
-
else if (output_ins.label[0] != '.' ||
output_ins.label[1] != '.' ||
output_ins.label[2] == '@')
@@ -832,10 +822,11 @@ static void assemble_file (char *fname)
(output_ins.oprs[0].type & IMMEDIATE) &&
output_ins.oprs[0].wrt == NO_SEG)
{
- define_label (output_ins.label,
- output_ins.oprs[0].segment,
- output_ins.oprs[0].offset,
- NULL, FALSE, FALSE, ofmt, report_error);
+ int isext = output_ins.oprs[0].opflags & OPFLAG_EXTERN;
+ define_label (output_ins.label,
+ output_ins.oprs[0].segment,
+ output_ins.oprs[0].offset,
+ NULL, FALSE, isext, ofmt, report_error);
}
else if (output_ins.operands == 2 &&
(output_ins.oprs[0].type & IMMEDIATE) &&
diff --git a/nasm.h b/nasm.h
index 6a37e781..240d2d49 100644
--- a/nasm.h
+++ b/nasm.h
@@ -13,7 +13,7 @@
#define NASM_MAJOR_VER 0
#define NASM_MINOR_VER 98
-#define NASM_VER "0.98 pre-release 7"
+#define NASM_VER "0.98"
#ifndef NULL
#define NULL 0
diff --git a/nasm.spec b/nasm.spec
new file mode 100644
index 00000000..c5475134
--- /dev/null
+++ b/nasm.spec
@@ -0,0 +1,87 @@
+Summary: The Netwide Assembler, a portable x86 assembler with Intel-like syntax
+Name: nasm
+Version: 0.98
+Release: 1
+Copyright: Freely Distributable
+Group: Development/Languages
+Source: ftp://ftp.us.kernel.org/pub/software/devel/nasm/source/nasm-%{version}.tar.gz
+URL: http://www.cryogen.com/Nasm/
+BuildRoot: /tmp/rpm-build-nasm
+Prefix: /usr
+
+%package doc
+Summary: Extensive documentation for NASM
+Group: Development/Languages
+Prereq: /sbin/install-info
+
+%package rdoff
+Summary: Tools for the RDOFF binary format, sometimes used with NASM.
+Group: Development/Tools
+
+%description
+NASM is the Netwide Assembler, a free portable assembler for the Intel
+80x86 microprocessor series, using primarily the traditional Intel
+instruction mnemonics and syntax.
+
+%description doc
+Extensive documentation for the Netwide Assembler, NASM, in HTML,
+info, PostScript and text formats.
+
+%description rdoff
+Tools for the operating-system independent RDOFF binary format, which
+is sometimes used with the Netwide Assembler (NASM). These tools
+include linker, library manager, loader, and information dump.
+
+%prep
+%setup
+
+%build
+CFLAGS="$RPM_OPT_FLAGS" LDFLAGS=-s ./configure --prefix=/usr
+make everything
+
+%install
+mkdir -p "$RPM_BUILD_ROOT"
+mkdir -p "$RPM_BUILD_ROOT"/usr/bin
+mkdir -p "$RPM_BUILD_ROOT"/usr/man/man1
+mkdir -p "$RPM_BUILD_ROOT"/usr/info
+DOC="$RPM_BUILD_ROOT"/usr/doc/nasm-%{version}
+rm -rf "$DOC"
+mkdir -p "$DOC"
+mkdir -p "$DOC"/rdoff
+rm -f "$RPM_BUILD_ROOT"/usr/info/nasm.*
+make INSTALLROOT="$RPM_BUILD_ROOT" docdir=/usr/doc/nasm-%{version} install_everything
+gzip -9 "$RPM_BUILD_ROOT"/usr/info/nasm.*
+gzip -9 "$DOC"/*.txt "$DOC"/*.ps
+cp Changes Licence MODIFIED Readme Wishlist *.doc changed.asm "$DOC"
+cp rdoff/README rdoff/Changes "$DOC"/rdoff
+
+%clean
+rm -rf "$RPM_BUILD_ROOT"
+
+%post doc
+/sbin/install-info "$RPM_INSTALL_PREFIX"/info/nasm.info.gz "$RPM_INSTALL_PREFIX"/info/dir
+
+%preun doc
+if [ $1 = 0 ]; then
+ /sbin/install-info --delete "$RPM_INSTALL_PREFIX"/info/nasm.info.gz "$RPM_INSTALL_PREFIX"/info/dir
+fi
+
+%files
+%attr(-,root,root) /usr/bin/nasm
+%attr(-,root,root) /usr/bin/ndisasm
+%attr(-,root,root) %doc /usr/man/man1/nasm.1
+%attr(-,root,root) %doc /usr/man/man1/ndisasm.1
+%attr(-,root,root) %doc /usr/doc/nasm-%{version}/Licence
+
+%files doc
+%attr(-,root,root) %doc /usr/info/nasm.info*.gz
+%attr(-,root,root) %doc /usr/doc/nasm-%{version}/*
+
+%files rdoff
+%attr(-,root,root) /usr/bin/ldrdf
+%attr(-,root,root) /usr/bin/rdf2bin
+%attr(-,root,root) /usr/bin/rdf2com
+%attr(-,root,root) /usr/bin/rdfdump
+%attr(-,root,root) /usr/bin/rdflib
+%attr(-,root,root) /usr/bin/rdx
+%attr(-,root,root) %doc /usr/doc/nasm-%{version}/rdoff/*
diff --git a/outform.h b/outform.h
index 87313d41..564bbbae 100644
--- a/outform.h
+++ b/outform.h
@@ -92,6 +92,9 @@
#ifndef OF_AS86
#define OF_AS86
#endif
+#ifndef OF_RDF
+#define OF_RDF
+#endif
#ifndef OF_RDF2
#define OF_RDF2
#endif
@@ -177,6 +180,9 @@
#ifdef OF_NO_RDF2
#undef OF_RDF
#endif
+#ifdef OF_NO_IEEE
+#undef OF_IEEE
+#endif
#ifndef OF_DEFAULT
#define OF_DEFAULT of_bin
diff --git a/rdoff/Changes b/rdoff/Changes
new file mode 100644
index 00000000..34163a91
--- /dev/null
+++ b/rdoff/Changes
@@ -0,0 +1,63 @@
+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/Makefile.in b/rdoff/Makefile.in
index d9a93111..c55851db 100644
--- a/rdoff/Makefile.in
+++ b/rdoff/Makefile.in
@@ -1,3 +1,4 @@
+# $Id$
#
# Auto-configuring Makefile for RDOFF object file utils; part of the
# Netwide Assembler
@@ -7,24 +8,25 @@
# redistributable under the licence given in the file "Licence"
# distributed in the NASM archive.
-top_srcdir = @top_srcdir@
-srcdir = @srcdir@
-VPATH = @srcdir@
-prefix = @prefix@
-exec_prefix = @exec_prefix@
-bindir = @bindir@
-mandir = @mandir@
+top_srcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+bindir = @bindir@
+mandir = @mandir@
-CC = @CC@
-CFLAGS = @CFLAGS@ @GCCFLAGS@ -I$(top_srcdir)
+CC = @CC@
+CFLAGS = @CFLAGS@ @GCCFLAGS@ -I$(srcdir) -I$(top_srcdir)
+LDFLAGS = @LDFLAGS@
-INSTALL = @INSTALL@
-INSTALL_PROGRAM = @INSTALL_PROGRAM@
-INSTALL_DATA = @INSTALL_DATA@
-LN_S = @LN_S@
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+LN_S = @LN_S@
-LDRDFLIBS = rdoff.o nasmlib.o symtab.o collectn.o rdlib.o
-RDXLIBS = rdoff.o rdfload.o symtab.o collectn.o
+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) $<
@@ -32,18 +34,17 @@ RDXLIBS = rdoff.o rdfload.o symtab.o collectn.o
all: rdfdump ldrdf rdx rdflib rdf2bin rdf2com
rdfdump: rdfdump.o
- $(CC) -o rdfdump rdfdump.o
-
+ $(CC) $(LDFLAGS) -o rdfdump rdfdump.o
ldrdf: ldrdf.o $(LDRDFLIBS)
- $(CC) -o ldrdf ldrdf.o $(LDRDFLIBS)
+ $(CC) $(LDFLAGS) -o ldrdf ldrdf.o $(LDRDFLIBS)
rdx: rdx.o $(RDXLIBS)
- $(CC) -o rdx rdx.o $(RDXLIBS)
+ $(CC) $(LDFLAGS) -o rdx rdx.o $(RDXLIBS)
rdflib: rdflib.o
- $(CC) -o rdflib rdflib.o
+ $(CC) $(LDFLAGS) -o rdflib rdflib.o
rdf2bin: rdf2bin.o $(RDXLIBS) nasmlib.o
- $(CC) -o rdf2bin rdf2bin.o $(RDXLIBS) nasmlib.o
+ $(CC) $(LDFLAGS) -o rdf2bin rdf2bin.o $(RDXLIBS) nasmlib.o
rdf2com:
- $(LN_S) rdf2bin rdf2com
+ rm -f rdf2com && $(LN_S) rdf2bin rdf2com
rdf2bin.o: rdf2bin.c
rdfdump.o: rdfdump.c
@@ -55,6 +56,7 @@ 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) $(top_srcdir)/nasmlib.c
@@ -62,17 +64,15 @@ nasmlib.o: $(top_srcdir)/nasmlib.c
clean:
rm -f *.o rdfdump ldrdf rdx rdflib rdf2bin rdf2com
-distclean: clean
- rm -f Makefile *~ *.bak
-
-cleaner: clean
+spotless: clean
+ rm -f Makefile
-spotless: distclean
+distclean: spotless
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
+ $(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/Makefile.sc b/rdoff/Makefile.sc
index 816cc98e..fca911ad 100644
--- a/rdoff/Makefile.sc
+++ b/rdoff/Makefile.sc
@@ -1,112 +1,57 @@
-# Makefile for RDOFF object file utils; part of the Netwide Assembler
-
-#
-
-# The Netwide Assembler is copyright (C) 1996 Simon Tatham and
-
-# Julian Hall. All rights reserved. The software is
-
-# redistributable under the licence given in the file "Licence"
-
-# distributed in the NASM archive.
-
-#
-
-# This Makefile is designed for use under Unix (probably fairly
-
-# portably).
-
-
-
-CC = 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)
-
-
-
-
-
+# Makefile for RDOFF object file utils; part of the Netwide Assembler
+#
+# The Netwide Assembler is copyright (C) 1996 Simon Tatham and
+# Julian Hall. All rights reserved. The software is
+# redistributable under the licence given in the file "Licence"
+# distributed in the NASM archive.
+#
+# This Makefile is designed for use under Unix (probably fairly
+# portably).
+
+CC = 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)
+
+
+ \ No newline at end of file
diff --git a/rdoff/Makefile.unx b/rdoff/Makefile.unx
index f1558396..89d439f8 100644
--- a/rdoff/Makefile.unx
+++ b/rdoff/Makefile.unx
@@ -25,8 +25,8 @@ INSTALL_PROGRAM = ${INSTALL}
INSTALL_DATA = ${INSTALL} -m 644
LN_S = ln -s
-LDRDFLIBS = rdoff.o nasmlib.o symtab.o collectn.o rdlib.o
-RDXLIBS = rdoff.o rdfload.o symtab.o collectn.o
+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
@@ -51,12 +51,14 @@ 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
+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
diff --git a/rdoff/README b/rdoff/README
index bea5ecbe..29f9aa03 100644
--- a/rdoff/README
+++ b/rdoff/README
@@ -1,22 +1,45 @@
-RDOFF Utils v0.2
+RDOFF Utils v0.3
================
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 1 object files. Here is a brief summary of their usage:
+RDOFF version 2 object files. Note that these programs (with the
+exception of 'rdfdump') will NOT work with version 1 object files. See
+the subdirectory v1 for programs that perform that task.
+
+Note: If you do not have a v1 subdirectory, you may have unpacked the
+ZIP file without specifying the 'restore directory structure' option -
+delete these files, and run your ZIP extracter again with this option
+turned on ('-d' for PKUNZIP).
+
+RDOFF version 1 is no longer really supported, you should be using
+v2 instead now.
+
+There is also a 'Changes' file, which documents the differences between
+RDOFF 1 and 2, and an 'rdoff2.txt' file, 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 code and data segments.
+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
=====
@@ -66,19 +89,84 @@ Usage:
Valid commands are:
- c Create the library
+ 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
-Remove and List commands will be added soon (they're already documented
-as existing, but I haven't had time to implement them... if anyone
+A remove command will be added soon (it is already documented
+as existing, but I haven't had time to implement it... if anyone
else wants to do this, they're welcome to. The file format should be
amply documented in the source code... look at 'rdflib.c' and 'rdlib.c',
and the relevant sections of 'ldrdf.c' to see how libraries can be
handled).
+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 me at the address 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 I 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
+- Make everything work with both formats (?)
+- Add extra functions to ldrdf (strip symbols/keep symbol list)
+- Check for more bugs
+
+One last thing I have to say: good luck! Whatever it is that you want to use
+RDOFF for, I hope its a success. People out there are using it for many
+diverse applications, from operating system boot-loaders to loadable modules
+in games. Whatever your application is, I hope that it works, and that you
+have a good time writing it.
+
+
+
Julian Hall <jules@earthcorp.com>
diff --git a/rdoff/hash.c b/rdoff/hash.c
new file mode 100644
index 00000000..c22d182a
--- /dev/null
+++ b/rdoff/hash.c
@@ -0,0 +1,95 @@
+/* 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 licence given in the file "Licence"
+ * distributed in the NASM archive.
+ */
+
+#include "hash.h"
+
+typedef unsigned int crc32;
+
+const crc32 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 };
+
+unsigned
+hash (const char *name)
+{
+ register const char *n;
+ register crc32 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 00000000..2ccf9b96
--- /dev/null
+++ b/rdoff/hash.h
@@ -0,0 +1,12 @@
+/* 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 licence given in the file "Licence"
+ * distributed in the NASM archive.
+ */
+
+unsigned hash (const char* name);
+
diff --git a/rdoff/ldrdf.c b/rdoff/ldrdf.c
index 9e4a215d..72f87255 100644
--- a/rdoff/ldrdf.c
+++ b/rdoff/ldrdf.c
@@ -1,4 +1,4 @@
-/* ldrdf.c RDOFF Object File linker/loader main program
+/* ldrdf.c RDOFF Object File linker/loader main program
*
* The Netwide Assembler is copyright (C) 1996 Simon Tatham and
* Julian Hall. All rights reserved. The software is
@@ -6,18 +6,23 @@
* distributed in the NASM archive.
*/
-/* TODO: Make the system skip a module (other than the first) if none
- * of the other specified modules contain a reference to it.
- * May require the system to make an extra pass of the modules to be
- * loaded eliminating those that aren't required.
+/*
+ * TODO: actually get this new version working!
+ * - finish off write_output() - appears to be done
+ * - implement library searching - appears to be done
+ * - maybe we only want to do one pass, for performance reasons?
+ * this makes things a little harder, but unix 'ld' copes...
+ * - implement command line options - appears to be done
+ * - improve symbol table implementation - done, thanks to Graeme Defty
+ * - keep a cache of symbol names in each library module so
+ * we don't have to constantly recheck the file
+ * - general performance improvements
*
- * Support all the existing documented options...
- *
- * Support libaries (.a files - requires a 'ranlib' type utility)
- * (I think I've got this working, so I've upped the version)
- *
- * -s option to strip resolved symbols from exports. (Could make this an
- * external utility)
+ * BUGS & LIMITATIONS: this program doesn't support multiple code, data
+ * or bss segments, therefore for 16 bit programs whose code, data or BSS
+ * segment exceeds 64K in size, it will not work. This program probably
+ * wont work if compiled by a 16 bit compiler. Try DJGPP if you're running
+ * under DOS. '#define STINGY_MEMORY' may help a little.
*/
#include <stdio.h>
@@ -25,704 +30,1088 @@
#include <string.h>
#include "rdoff.h"
-#include "nasmlib.h"
#include "symtab.h"
#include "collectn.h"
#include "rdlib.h"
+#include "segtab.h"
-#define LDRDF_VERSION "0.30"
+#define LDRDF_VERSION "1.00 alpha 1"
-/* global variables - those to set options: */
+#define RDF_MAXSEGS 64
+/* #define STINGY_MEMORY */
-int verbose = 0; /* reflects setting of command line switch */
-int align = 16;
-int errors = 0; /* set by functions to cause halt after current
- stage of processing */
+/* =======================================================================
+ * Types & macros that are private to this program
+ */
+
+struct segment_infonode {
+ int dest_seg; /* output segment to be placed into, -1 to
+ skip linking this segment */
+ long reloc; /* segment's relocation factor */
+};
-/* the linked list of modules that must be loaded & linked */
struct modulenode {
- rdffile f; /* the file */
- long coderel; /* module's code relocation factor */
- long datarel; /* module's data relocation factor */
- long bssrel; /* module's bss data reloc. factor */
- void * header; /* header location, if loaded */
- char * name; /* filename */
- struct modulenode *next;
+ rdffile f; /* the RDOFF file structure */
+ struct segment_infonode seginfo[RDF_MAXSEGS]; /* what are we doing
+ with each segment? */
+ void * header;
+ char * name;
+ struct modulenode * next;
+ long bss_reloc;
};
+#include "ldsegs.h"
+
#define newstr(str) strcpy(malloc(strlen(str) + 1),str)
#define newstrcat(s1,s2) strcat(strcpy(malloc(strlen(s1)+strlen(s2)+1),s1),s2)
+/* ==========================================================================
+ * Function prototypes of private utility functions
+ */
-struct modulenode *modules = NULL,*lastmodule = NULL;
+void processmodule(const char * filename, struct modulenode * mod);
+int allocnewseg(int16 type,int16 reserved);
+int findsegment(int16 type,int16 reserved);
+void symtab_add(const char * symbol, int segment, long offset);
+int symtab_get(const char * symbol, int * segment, long * offset);
-/* the linked list of libraries to be searched for missing imported
- symbols */
+/* =========================================================================
+ * Global data structures.
+ */
-struct librarynode * libraries = NULL, * lastlib = NULL;
+/* a linked list of modules that will be included in the output */
+struct modulenode * modules = NULL;
+struct modulenode * lastmodule = NULL;
-void *symtab; /* The symbol table */
+/* a linked list of libraries to be searched for unresolved imported symbols */
+struct librarynode * libraries = NULL;
+struct librarynode * lastlib = NULL;
-rdf_headerbuf * newheader ; /* New header to be written to output */
+/* the symbol table */
+void * symtab = NULL;
-/* loadmodule - find the characteristics of a module and add it to the
- * list of those being linked together */
+/* the header of the output file, built up stage by stage */
+rdf_headerbuf * newheader = NULL;
-void loadmodule(char *filename)
+/* The current state of segment allocation, including information about
+ * which output segment numbers have been allocated, and their types and
+ * amount of data which has already been allocated inside them.
+ */
+struct SegmentHeaderRec outputseg[RDF_MAXSEGS];
+int nsegs = 0;
+long bss_length;
+
+/* global options which affect how the program behaves */
+struct ldrdfoptions {
+ int verbose;
+ int align;
+ int warnUnresolved;
+ int strip;
+} 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()
{
- struct modulenode *prev;
- if (! modules) {
- modules = malloc(sizeof(struct modulenode));
- lastmodule = modules;
- prev = NULL;
- }
- else {
- lastmodule->next = malloc(sizeof(struct modulenode));
- prev = lastmodule;
- lastmodule = lastmodule->next;
- }
-
- if (! lastmodule) {
- fputs("ldrdf: not enough memory\n",stderr);
- exit(1);
- }
-
- if (rdfopen(&lastmodule->f,filename)) {
- rdfperror("ldrdf",filename);
- exit(1);
- }
-
- lastmodule->header = NULL; /* header hasn't been loaded */
- lastmodule->name = filename;
- lastmodule->next = NULL;
-
- if (prev) {
- lastmodule->coderel = prev->coderel + prev->f.code_len;
- if (lastmodule->coderel % align != 0)
- lastmodule->coderel += align - (lastmodule->coderel % align);
- lastmodule->datarel = prev->datarel + prev->f.data_len;
- if (lastmodule->datarel % align != 0)
- lastmodule->datarel += align - (lastmodule->datarel % align);
- }
- else {
- lastmodule->coderel = 0;
- lastmodule->datarel = 0;
- }
-
- if (verbose)
- printf("%s code = %08lx (+%04lx), data = %08lx (+%04lx)\n",filename,
- lastmodule->coderel,lastmodule->f.code_len,
- lastmodule->datarel,lastmodule->f.data_len);
-
- lastmodule->header = malloc(lastmodule->f.header_len);
- if (!lastmodule->header) {
- fprintf(stderr,"ldrdf: out of memory\n");
- exit(1);
- }
-
- if (rdfloadseg(&lastmodule->f,RDOFF_HEADER,lastmodule->header))
- {
- rdfperror("ldrdf",filename);
- exit(1);
- }
+ 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;
}
-/* load_library add a library to list of libraries to search
- * for undefined symbols
+/*
+ * 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 load_library(char * name)
+void loadmodule(const char * filename)
{
- if (verbose)
- printf("adding library %s to search path\n",name);
-
- if (! lastlib) {
- lastlib = libraries = malloc(sizeof(struct librarynode));
+ 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
{
- lastlib->next = malloc(sizeof(struct librarynode));
- lastlib = lastlib->next;
+ lastmodule->next = malloc (sizeof(*modules));
+ lastmodule = lastmodule->next;
}
- if (! lastlib) {
+ if ( ! lastmodule)
+ {
fprintf(stderr, "ldrdf: out of memory\n");
exit(1);
}
- strcpy (lastlib->name = malloc (1+strlen(name)), name);
- lastlib->fp = NULL;
- lastlib->referenced = 0;
- lastlib->next = NULL;
-}
+ /* open the file using 'rdfopen', which returns nonzero on error */
-/* build_symbols() step through each module's header, and locate
- * exported symbols, placing them in a global table
- */
+ if (rdfopen(&lastmodule->f, filename) != 0)
+ {
+ rdfperror("ldrdf", filename);
+ exit(1);
+ }
-long bsslength;
+ /*
+ * 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)
+ */
-void mod_addsymbols(struct modulenode * mod)
+ lastmodule->header = NULL;
+ lastmodule->name = strdup(filename);
+ lastmodule->next = NULL;
+
+ processmodule(filename, lastmodule);
+}
+
+/*
+ * processmodule()
+ *
+ * step through each segment, determine what exactly we're doing with
+ * it, and if we intend to keep it, determine (a) which segment to
+ * put it in and (b) whereabouts in that segment it will end up.
+ * (b) is fairly easy, cos we're now keeping track of how big each segment
+ * in our output file is...
+ */
+
+void processmodule(const char * filename, struct modulenode * mod)
{
- rdfheaderrec *r;
- symtabEnt e;
- long cbBss;
-
- mod->bssrel = bsslength;
- cbBss = 0;
- rdfheaderrewind(&mod->f);
- while ((r = rdfgetheaderrec(&mod->f)))
+ struct segconfig sconf;
+ int seg, outseg;
+ void * header;
+ rdfheaderrec * hr;
+ long bssamount = 0;
+
+ for (seg = 0; seg < mod->f.nsegs; seg++)
{
+ /*
+ * get the segment configuration for this type from the segment
+ * table. getsegconfig() is a macro, defined in ldsegs.h.
+ */
+ getsegconfig(sconf, mod->f.seg[seg].type);
+
+ if (options.verbose > 1) {
+ printf ("%s %04x [%04x:%10s] ", filename, mod->f.seg[seg].number,
+ mod->f.seg[seg].type, sconf.typedesc);
+ }
+ /*
+ * sconf->dowhat tells us what to do with a segment of this type.
+ */
+ switch (sconf.dowhat) {
+ case SEG_IGNORE:
+ /*
+ * Set destination segment to -1, to indicate that this segment
+ * should be ignored for the purpose of output, ie it is left
+ * out of the linked executable.
+ */
+ mod->seginfo[seg].dest_seg = -1;
+ if (options.verbose > 1) printf("IGNORED\n");
+ break;
- if (r->type == 5) /* Allocate BSS */
- cbBss += r->b.amount;
+ case SEG_NEWSEG:
+ /*
+ * The configuration tells us to create a new segment for
+ * each occurrence of this segment type.
+ */
+ outseg = allocnewseg(sconf.mergetype,
+ mod->f.seg[seg].reserved);
+ mod->seginfo[seg].dest_seg = outseg;
+ mod->seginfo[seg].reloc = 0;
+ outputseg[outseg].length = mod->f.seg[seg].length;
+ if (options.verbose > 1)
+ printf ("=> %04x:%08lx (+%04lx)\n", outseg,
+ mod->seginfo[seg].reloc,
+ mod->f.seg[seg].length);
+ break;
- if (r->type != 3) continue; /* ignore all but export recs */
+ 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;
- e.segment = r->e.segment;
- e.offset = r->e.offset +
- (e.segment == 0 ? mod->coderel : /* 0 -> code */
- e.segment == 1 ? mod->datarel : /* 1 -> data */
- mod->bssrel) ; /* 2 -> bss */
-
- e.flags = 0;
- e.name = malloc(strlen(r->e.label) + 1);
- if (! e.name)
- {
- fprintf(stderr,"ldrdf: out of memory\n");
- exit(1);
+ if (options.verbose > 1)
+ printf ("=> %04x:%08lx (+%04lx)\n", outseg,
+ mod->seginfo[seg].reloc,
+ mod->f.seg[seg].length);
}
- strcpy(e.name,r->e.label);
- symtabInsert(symtab,&e);
+
}
- bsslength += cbBss;
-}
-void build_symbols()
-{
- struct modulenode *mod;
-
- if (verbose) printf("building global symbol table:\n");
- newheader = rdfnewheader();
-
- symtab = symtabNew();
- bsslength = 0; /* keep track of location of BSS symbols */
-
- for (mod = modules; mod; mod = mod->next)
- {
- mod_addsymbols( mod );
- }
- if (verbose)
- {
- symtabDump(symtab,stdout);
- printf("BSS length = %ld bytes\n\n",bsslength);
- }
-}
+ /*
+ * extract symbols from the header, and dump them into the
+ * symbol table
+ */
+ header = malloc(mod->f.header_len);
+ if (!header) {
+ fprintf(stderr, "ldrdf: not enough memory\n");
+ exit(1);
+ }
+ if (rdfloadseg(&mod->f, RDOFF_HEADER, header)) {
+ rdfperror("ldrdf", filename);
+ exit(1);
+ }
+ while ((hr = rdfgetheaderrec (&mod->f)))
+ {
+ switch(hr->type) {
+ case 2: /* imported symbol - define with seg = -1 */
+ case 7:
+ symtab_add(hr->i.label, -1, 0);
+ break;
-/* scan_libraries() search through headers of modules for undefined
- * symbols, and scan libraries for those symbols,
- * adding library modules found to list of modules
- * to load. */
+ case 3: /* exported symbol */
+ if (mod->seginfo[(int)hr->e.segment].dest_seg == -1)
+ continue;
+ symtab_add(hr->e.label, mod->seginfo[(int)hr->e.segment].dest_seg,
+ mod->seginfo[(int)hr->e.segment].reloc + hr->e.offset);
+ break;
-void scan_libraries(void)
-{
- struct modulenode * mod, * nm;
- struct librarynode * lib;
- rdfheaderrec * r;
- int found;
- char * tmp;
+ case 5: /* BSS reservation */
+ /*
+ * first, amalgamate all BSS reservations in this module
+ * into one, because we allow this in the output format.
+ */
+ bssamount += hr->b.amount;
+ break;
+ }
+ }
- if (verbose) printf("Scanning libraries for unresolved symbols...\n");
+ if (bssamount != 0)
+ {
+ /*
+ * handle the BSS segment - first pad the existing bss length
+ * to the correct alignment, then store the length in bss_reloc
+ * for this module. Then add this module's BSS length onto
+ * bss_length.
+ */
+ if (bss_length % options.align != 0)
+ bss_length += options.align - (bss_length % options.align);
+
+ mod->bss_reloc = bss_length;
+ if (options.verbose > 1) {
+ printf ("%s 0002 [ BSS] => 0002:%08lx (+%04lx)\n",
+ filename, bss_length, bssamount);
+ }
+ bss_length += bssamount;
+ }
- mod = modules;
+#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);
- while (mod)
- {
- rdfheaderrewind(&mod->f);
+#endif
- while ((r = rdfgetheaderrec(&mod->f)))
- {
- if (r->type != 2) continue; /* not an import record */
- if ( symtabFind (symtab,r->i.label) )
- continue; /* symbol already defined */
-
- /* okay, we have an undefined symbol... step through
- the libraries now */
- if (verbose >= 2) {
- printf("undefined symbol '%s'...",r->i.label);
- fflush(stdout);
- }
+}
- lib = libraries;
- found = 0;
+/*
+ * allocnewseg()
+ * findsegment()
+ *
+ * These functions manipulate the array of output segments, and are used
+ * by processmodule(). allocnewseg() allocates a segment in the array,
+ * initialising it to be empty. findsegment() first scans the array for
+ * a segment of the type requested, and if one isn't found allocates a
+ * new one.
+ */
+int allocnewseg(int16 type,int16 reserved)
+{
+ outputseg[nsegs].type = type;
+ outputseg[nsegs].number = nsegs;
+ outputseg[nsegs].reserved = reserved;
+ outputseg[nsegs].length = 0;
+ outputseg[nsegs].offset = 0;
+ outputseg[nsegs].data = NULL;
+
+ return nsegs++;
+}
- tmp = newstr(r->i.label);
- while (! found && lib)
- {
- /* move this to an outer loop...! */
- nm = malloc(sizeof(struct modulenode));
+int findsegment(int16 type,int16 reserved)
+{
+ int i;
- if (rdl_searchlib(lib,tmp,&nm->f))
- { /* found a module in the library */
+ for (i = 0; i < nsegs; i++)
+ if (outputseg[i].type == type) return i;
- /* create a modulenode for it */
+ return allocnewseg(type,reserved);
+}
- if (! nm) {
- fprintf(stderr,"ldrdf: out of memory\n");
- exit(1);
- }
+/*
+ * 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.
+ */
- nm->name = newstrcat(lib->name,nm->f.name);
- if (verbose >= 2) printf("found in '%s'\n",nm->name);
+void symtab_add(const char * symbol, int segment, long offset)
+{
+ symtabEnt * ste;
- nm->coderel = lastmodule->coderel + lastmodule->f.code_len;
- if (nm->coderel % align != 0)
- nm->coderel += align - (nm->coderel % align);
+ ste = symtabFind(symtab, symbol);
+ if (ste)
+ {
+ if (ste->segment >= 0) {
+ /*
+ * symbol previously defined
+ */
+ if (segment < 0) return;
+ fprintf (stderr, "warning: `%s' redefined\n", symbol);
+ return;
+ }
- nm->datarel = lastmodule->datarel + lastmodule->f.data_len;
- if (nm->datarel % align != 0)
- nm->datarel += align - (nm->datarel % align);
+ /*
+ * 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);
+}
- nm->header = malloc(nm->f.header_len);
- if (! nm->header)
- {
- fprintf(stderr,"ldrdf: out of memory\n");
- exit(1);
- }
+/*
+ * 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.
+ */
- if (rdfloadseg(&nm->f,RDOFF_HEADER,nm->header))
- {
- rdfperror("ldrdf",nm->name);
- exit(1);
- }
+int symtab_get(const char * symbol, int * segment, long * offset)
+{
+ symtabEnt * ste = symtabFind(symtab, symbol);
+ if (!ste) {
+ *segment = -1;
+ *offset = 0;
+ return 0;
+ }
+ else
+ {
+ *segment = ste->segment;
+ *offset = ste->offset;
+ return 1;
+ }
+}
- nm->next = NULL;
- found = 1;
- lastmodule->next = nm;
- lastmodule = nm;
+/*
+ * add_library()
+ *
+ * checks that a library can be opened and is in the correct format,
+ * then adds it to the linked list of libraries.
+ */
- if (verbose)
- printf("%s code = %08lx (+%04lx), data = %08lx "
- "(+%04lx)\n",lastmodule->name,
- lastmodule->coderel,lastmodule->f.code_len,
- lastmodule->datarel,lastmodule->f.data_len);
+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;
+ }
+ if (rdl_open(lastlib, name)) {
+ rdl_perror("ldrdf", name);
+ errorcount++;
+ return;
+ }
+}
- /* add the module's info to the symbol table */
- mod_addsymbols(nm);
- }
- else
+/*
+ * search_libraries()
+ *
+ * scans through the list of libraries, attempting to match symbols
+ * defined in library modules against symbols that are referenced but
+ * not defined (segment = -1 in the symbol table)
+ *
+ * returns 1 if any extra library modules are included, indicating that
+ * another pass through the library list should be made (possibly).
+ */
+
+int search_libraries()
+{
+ struct librarynode * cur;
+ rdffile f;
+ int i;
+ void * header;
+ int segment;
+ long offset;
+ int doneanything = 0, keepfile;
+ rdfheaderrec * hr;
+
+ cur = libraries;
+
+ while (cur)
+ {
+ if (options.verbose > 2)
+ printf("scanning library `%s'...\n", cur->name);
+
+ for (i = 0; rdl_openmodule(cur, i, &f) == 0; i++)
+ {
+ if (options.verbose > 3)
+ printf(" looking in module `%s'\n", f.name);
+
+ header = malloc(f.header_len);
+ if (!header) {
+ fprintf(stderr, "ldrdf: not enough memory\n");
+ exit(1);
+ }
+ if (rdfloadseg(&f, RDOFF_HEADER, header)) {
+ rdfperror("ldrdf", f.name);
+ errorcount++;
+ return 0;
+ }
+
+ keepfile = 0;
+
+ while ((hr = rdfgetheaderrec (&f)))
+ {
+ /* we're only interested in exports, so skip others: */
+ if (hr->type != 3) continue;
+
+ /*
+ * Find the symbol in the symbol table. If the symbol isn't
+ * defined, we aren't interested, so go on to the next.
+ * If it is defined as anything but -1, we're also not
+ * interested. But if it is defined as -1, insert this
+ * module into the list of modules to use, and go
+ * immediately on to the next module...
+ */
+ if (! symtab_get(hr->e.label, &segment, &offset)
+ || segment != -1)
{
- if (rdl_error) {
- rdl_perror("ldrdf",lib->name);
- exit(1);
- }
- free(nm);
+ continue;
}
- lib = lib->next;
+
+ 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);
+ processmodule(f.name, lastmodule);
+ break;
}
- free(tmp);
- if (!found && verbose >= 2) printf("not found\n");
+ if (!keepfile)
+ rdfclose(&f);
}
- mod = mod->next;
+ if (rdl_error != 0 && rdl_error != RDL_ENOTFOUND)
+ rdl_perror("ldrdf", cur->name);
+ cur = cur->next;
}
+
+ return doneanything;
}
-/* load_segments() allocates memory for & loads the code & data segs
- * from the RDF modules
+/*
+ * 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.
*/
-
-char *text,*data;
-long textlength,datalength;
-
-void load_segments(void)
+void write_output(const char * filename)
{
- struct modulenode *mod;
-
- if (!modules) {
- fprintf(stderr,"ldrdf: nothing to do\n");
- exit(0);
- }
- if (!lastmodule) {
- fprintf(stderr,"ldrdf: panic: module list exists, but lastmodule=NULL\n");
- exit(3);
- }
-
- if (verbose)
- printf("loading modules into memory\n");
-
- /* The following stops 16 bit DOS from crashing whilst attempting to
- work using segments > 64K */
- if (sizeof(int) == 2) { /* expect a 'code has no effect' warning on 32 bit
- platforms... */
- if (lastmodule->coderel + lastmodule->f.code_len > 65535 ||
- lastmodule->datarel + lastmodule->f.data_len > 65535) {
- fprintf(stderr,"ldrdf: segment length has exceeded 64K; use a 32 bit "
- "version.\nldrdf: code size = %05lx, data size = %05lx\n",
- lastmodule->coderel + lastmodule->f.code_len,
- lastmodule->datarel + lastmodule->f.data_len);
- exit(1);
+ FILE * f = fopen(filename, "wb");
+ rdf_headerbuf * rdfheader = rdfnewheader();
+ struct modulenode * cur;
+ int i, availableseg, seg, localseg, isrelative;
+ void * header;
+ rdfheaderrec * hr, newrec;
+ symtabEnt * se;
+ segtab segs;
+ long offset;
+ byte * data;
+
+ if (!f) {
+ fprintf(stderr, "ldrdf: couldn't open %s for output\n", filename);
+ exit(1);
}
- }
-
- text = malloc(textlength = lastmodule->coderel + lastmodule->f.code_len);
- data = malloc(datalength = lastmodule->datarel + lastmodule->f.data_len);
-
- if (!text || !data) {
- fprintf(stderr,"ldrdf: out of memory\n");
- exit(1);
- }
-
- mod = modules;
- while (mod) { /* load the segments for each module */
- if (verbose >= 2) printf(" loading %s\n",mod->name);
- if (rdfloadseg(&mod->f,RDOFF_CODE,&text[mod->coderel]) ||
- rdfloadseg(&mod->f,RDOFF_DATA,&data[mod->datarel])) {
- rdfperror("ldrdf",mod->name);
- exit(1);
- }
- rdfclose(&mod->f); /* close file; segments remain */
- mod = mod->next;
- }
-}
+ if (!rdfheader) {
+ fprintf(stderr, "ldrdf: out of memory\n");
+ exit(1);
+ }
+
+ if (options.verbose)
+ printf ("\nbuilding output module (%d segments)\n", nsegs);
-/* link_segments() step through relocation records in each module's
- * header, fixing up references.
- */
+ /*
+ * 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 = malloc(outputseg[i].length);
+ if (!outputseg[i].data) {
+ fprintf(stderr, "ldrdf: out of memory\n");
+ exit(1);
+ }
+ }
-void link_segments(void)
-{
- struct modulenode *mod;
- Collection imports;
- symtabEnt *s;
- long rel,relto;
- char *seg;
- rdfheaderrec *r;
- int bRelative;
-
- if (verbose) printf("linking segments\n");
-
- collection_init(&imports);
-
- for (mod = modules; mod; mod = mod->next) {
- if (verbose >= 2) printf("* processing %s\n",mod->name);
- rdfheaderrewind(&mod->f);
- while((r = rdfgetheaderrec(&mod->f))) {
- if (verbose >= 3) printf("record type: %d\n",r->type);
- switch(r->type) {
- case 1: /* relocation record */
- if (r->r.segment >= 64) { /* Relative relocation; */
- bRelative = 1; /* need to find location relative */
- r->r.segment -= 64; /* to start of this segment */
- relto = r->r.segment == 0 ? mod->coderel : mod->datarel;
+ /*
+ * 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);
}
- else
+ }
+
+ /*
+ * 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))
{
- bRelative = 0; /* non-relative - need to relocate
- * at load time */
- relto = 0; /* placate optimiser warnings */
+ 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);
- /* calculate absolute offset of reference, not rel to beginning of
- segment */
- r->r.offset += r->r.segment == 0 ? mod->coderel : mod->datarel;
-
- /* calculate the relocation factor to apply to the operand -
- the base address of one of this modules segments if referred
- segment is 0 - 2, or the address of an imported symbol
- otherwise. */
-
- if (r->r.refseg == 0) rel = mod->coderel;
- else if (r->r.refseg == 1) rel = mod->datarel;
- else if (r->r.refseg == 2) rel = mod->bssrel;
- else { /* cross module link - find reference */
- s = *colln(&imports,r->r.refseg - 2);
- if (!s) {
- fprintf(stderr,"ldrdf: link to undefined segment %04x in"
- " %s:%d\n", r->r.refseg,mod->name,r->r.segment);
- errors = 1;
+ while ((hr = rdfgetheaderrec(&cur->f)))
+ {
+ switch(hr->type) {
+ case 1: /* relocation record - need to do a fixup */
+ /*
+ * First correct the offset stored in the segment from
+ * the start of the segment (which may well have changed).
+ *
+ * To do this we add to the number stored the relocation
+ * factor associated with the segment that contains the
+ * target segment.
+ *
+ * The relocation could be a relative relocation, in which
+ * case we have to first subtract the amount we've relocated
+ * the containing segment by.
+ */
+
+ if (!get_seglocation(&segs, hr->r.refseg, &seg, &offset))
+ {
+ fprintf(stderr, "%s: reloc to undefined segment %04x\n",
+ cur->name, (int) hr->r.refseg);
+ errorcount++;
break;
}
- rel = s->offset;
-
- r->r.refseg = s->segment; /* change referred segment,
- so that new header is
- correct */
- }
- if (bRelative) /* Relative - subtract current segment start */
- rel -= relto;
- else
- { /* Add new relocation header */
- rdfaddheader(newheader,r);
- }
-
- /* Work out which segment we're making changes to ... */
- if (r->r.segment == 0) seg = text;
- else if (r->r.segment == 1) seg = data;
- else {
- fprintf(stderr,"ldrdf: relocation in unknown segment %d in "
- "%s\n", r->r.segment,mod->name);
- errors = 1;
- break;
- }
+ isrelative = (hr->r.segment & 64) == 64;
+ hr->r.segment &= 63;
+
+ if (hr->r.segment == 2 ||
+ (localseg = rdffindsegment(&cur->f, hr->r.segment)) == -1)
+ {
+ fprintf(stderr, "%s: reloc from %s segment (%d)\n",
+ cur->name,
+ hr->r.segment == 2 ? "BSS" : "unknown",
+ hr->r.segment);
+ errorcount++;
+ break;
+ }
- /* Add the relocation factor to the datum specified: */
+ 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;
+ }
- if (verbose >= 3)
- printf(" - relocating %d:%08lx by %08lx\n",r->r.segment,
- r->r.offset,rel);
+ /*
+ * 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(stderr, "warning: relocation out of range "
+ "at %s(%02x:%08lx)\n", cur->name,
+ (int)hr->r.segment, hr->r.offset);
+ *data = (char) offset;
+ break;
+ case 2:
+ offset += * (short *)data;
+ if (offset < -32767 || offset > 32768)
+ fprintf(stderr, "warning: relocation out of range "
+ "at %s(%02x:%08lx)\n", cur->name,
+ (int)hr->r.segment, hr->r.offset);
+ * (short *)data = (short) offset;
+ break;
+ case 4:
+ * (long *)data += offset;
+ /* we can't easily detect overflow on this one */
+ break;
+ }
- /**** The following code is non-portable. Rewrite it... ****/
- switch(r->r.length) {
- case 1:
- seg[r->r.offset] += (char) rel;
+ /*
+ * If the relocation was relative between two symbols in
+ * the same segment, then we're done.
+ *
+ * Otherwise, we need to output a new relocation record
+ * with the references updated segment and offset...
+ */
+ if (! isrelative
+ || cur->seginfo[localseg].dest_seg != seg)
+ {
+ hr->r.segment = cur->seginfo[localseg].dest_seg;
+ hr->r.offset += cur->seginfo[localseg].reloc;
+ hr->r.refseg = seg;
+ rdfaddheader(rdfheader, hr);
+ }
break;
- case 2:
- *(int16 *)(seg + r->r.offset) += (int16) rel;
+
+ case 2: /* import symbol */
+ case 7:
+ /*
+ * scan the global symbol table for the symbol
+ * and associate its location with the segment number
+ * for this module
+ */
+ se = symtabFind(symtab, hr->i.label);
+ if (!se || se->segment == -1) {
+ if (options.warnUnresolved) {
+ fprintf(stderr, "warning: unresolved reference to `%s'"
+ " in module `%s'\n", hr->i.label, cur->name);
+ }
+ /*
+ * 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 4:
- *(long *)(seg + r->r.offset) += rel;
+
+ case 3: /* export symbol */
+ /*
+ * need to insert an export for this symbol into the new
+ * header, unless we're stripping symbols [unless this
+ * symbol is in an explicit keep list]. *** FIXME ***
+ */
+ if (options.strip)
+ break;
+
+ if (hr->e.segment == 2) {
+ seg = 2;
+ offset = cur->bss_reloc;
+ }
+ else {
+ localseg = rdffindsegment(&cur->f, hr->e.segment);
+ if (localseg == -1) {
+ fprintf(stderr, "%s: exported symbol `%s' from "
+ "unrecognised segment\n", cur->name,
+ hr->e.label);
+ errorcount++;
+ break;
+ }
+ offset = cur->seginfo[localseg].reloc;
+ seg = cur->seginfo[localseg].dest_seg;
+ }
+
+ hr->e.segment = seg;
+ hr->e.offset += offset;
+ rdfaddheader(rdfheader, hr);
break;
- }
- break;
- case 2: /* import record */
- s = symtabFind(symtab, r->i.label);
- if (s == NULL) {
- /* Need to add support for dynamic linkage */
- fprintf(stderr,"ldrdf: undefined symbol %s in module %s\n",
- r->i.label,mod->name);
- errors = 1;
- }
- else
- {
- *colln(&imports,r->i.segment - 2) = s;
- if (verbose >= 2)
- printf("imported %s as %04x\n", r->i.label, r->i.segment);
- }
- break;
+ case 6: /* segment fixup */
+ /*
+ * modify the segment numbers if necessary, and
+ * pass straight through to the output module header
+ *
+ * *** FIXME ***
+ */
+ if (hr->r.segment == 2) {
+ fprintf(stderr, "%s: segment fixup in BSS section\n",
+ cur->name);
+ errorcount++;
+ break;
+ }
+ localseg = rdffindsegment(&cur->f, hr->r.segment);
+ if (localseg == -1) {
+ fprintf(stderr, "%s: segment fixup in unrecognised"
+ " segment (%d)\n", cur->name, hr->r.segment);
+ errorcount++;
+ break;
+ }
+ hr->r.segment = cur->seginfo[localseg].dest_seg;
+ hr->r.offset += cur->seginfo[localseg].reloc;
- case 3: /* export; dump to output new version */
- s = symtabFind(symtab, r->e.label);
- if (! s) {
- fprintf(stderr,"ldrdf: internal error - undefined symbol %s "
- "exported in header of '%s'\n",r->e.label,mod->name);
- continue;
+ 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;
}
- r->e.offset = s->offset;
- rdfaddheader(newheader,r);
- break;
-
- case 4: /* DLL record */
- rdfaddheader(newheader,r); /* copy straight to output */
- break;
}
- }
- if (rdf_errno != 0) {
- rdfperror("ldrdf",mod->name);
- exit(1);
- }
- collection_reset(&imports);
- }
-}
-
-/* write_output() write linked program out to a file */
-void write_output(char *filename)
-{
- FILE * fp;
- rdfheaderrec r;
+ free(header);
+ done_seglocations(&segs);
+
+ }
- if (verbose) printf("writing output to '%s'\n",filename);
+ /*
+ * combined BSS reservation for the entire results
+ */
+ newrec.type = 5;
+ newrec.b.reclen = 4;
+ newrec.b.amount = bss_length;
+ rdfaddheader(rdfheader, &newrec);
- fp = fopen(filename,"wb");
- if (! fp)
+ /*
+ * Write the header
+ */
+ for (i = 0; i < nsegs; i++)
{
- fprintf(stderr,"ldrdf: could not open '%s' for writing\n",filename);
- exit(1);
+ 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
+ */
- /* add BSS length count to header... */
- if (bsslength)
- {
- r.type = 5;
- r.b.amount = bsslength;
- rdfaddheader(newheader,&r);
- }
-
- /* Write header */
- rdfwriteheader(fp,newheader);
- rdfdoneheader(newheader);
- newheader = NULL;
-
- /* Write text */
- if (fwrite(&textlength,1,4,fp) != 4
- || fwrite(text,1,textlength,fp) !=textlength)
+ for (i = 0; i < nsegs; i++)
{
- fprintf(stderr,"ldrdf: error writing %s\n",filename);
- exit(1);
+ int16 s;
+ long l;
+
+ if (i == 2) continue;
+
+ s = translateshort(outputseg[i].type);
+ fwrite(&s, 2, 1, f);
+ s = translateshort(outputseg[i].number);
+ fwrite(&s, 2, 1, f);
+ s = translateshort(outputseg[i].reserved);
+ fwrite(&s, 2, 1, f);
+ l = translatelong(outputseg[i].length);
+ fwrite(&l, 4, 1, f);
+
+ fwrite(outputseg[i].data, outputseg[i].length, 1, f);
}
- /* Write data */
- if (fwrite(&datalength,1,4,fp) != 4 ||
- fwrite(data,1,datalength,fp) != datalength)
- {
- fprintf (stderr,"ldrdf: error writing %s\n", filename);
- exit(1);
- }
- fclose(fp);
+ fwrite("\0\0\0\0\0\0\0\0\0\0", 10, 1, f);
}
-
-/* main program: interpret command line, and pass parameters on to
- * individual module loaders & the linker
- *
- * Command line format:
- * ldrdf [-o outfile | -x] [-r xxxx] [-v] [--] infile [infile ...]
- *
- * Default action is to output a file named 'aout.rdx'. -x specifies
- * that the linked object program should be executed, rather than
- * written to a file. -r specifies that the object program should
- * be prelocated at address 'xxxx'. This option cannot be used
- * in conjunction with -x.
+/* =========================================================================
+ * Main program
*/
-const char *usagemsg = "usage:\n"
-" ldrdf [-o outfile | -x] [-a x] [-v] [-p x] [--] infile [infile ...]\n"
-" [-l<libname> ...]\n\n"
-" ldrdf -h displays this message\n"
-" ldrdf -r displays version information\n\n"
-" -o selects output filename (default is aout.rdx)\n"
-" -x causes ldrdx to link & execute rather than write to file\n"
-" -a x causes object program to be statically relocated to address 'x'\n"
-" -v turns on verbose mode\n"
-" -p x causes segments to be aligned (padded) to x byte boundaries\n"
-" (default is 16 bytes)\n"
-" -l<name> causes 'name' to be linked in as a library. Note no search is\n"
-" performed - the entire pathname MUST be specified.\n";
-
-void usage(void)
+void usage()
{
- fputs(usagemsg,stderr);
+ printf("usage:\n");
+ printf(" ldrdf [options] object modules ... [-llibrary ...]\n");
+ printf(" ldrdf -r\n");
+ printf("options:\n");
+ printf(" -v[=n] increases verbosity by 1, or sets it to n\n");
+ printf(" -a nn sets segment alignment value (default 16)\n");
+ printf(" -s strips exported symbols\n");
+ printf(" -x warn about unresolved symbols\n");
+ printf(" -o name write output in file 'name'\n");
+ printf("\n");
+ printf("Note: no library searching is performed. Please specify full\n");
+ printf("paths to all files referenced.\n");
+ exit(0);
}
-int main(int argc,char **argv)
+int main(int argc, char ** argv)
{
- char *ofilename = "aout.rdx";
- long relocateaddr = -1; /* -1 if no relocation is to occur */
- int execute = 0; /* 1 to execute after linking, 0 otherwise */
- int procsw = 1; /* set to 0 by '--' */
- int tmp;
-
- if (argc == 1) {
- usage();
- exit(1);
- }
-
- /* process command line switches, and add modules specified to linked list
- of modules, keeping track of total memory required to load them */
-
- while(argv++,--argc) {
- if (procsw && !strcmp(*argv,"-h")) { /* Help command */
- usage(); exit(1);
+ char * outname = "aout.rdf";
+ int moduleloaded = 0;
+
+ options.verbose = 0;
+ options.align = 16;
+ options.warnUnresolved = 0;
+ options.strip = 0;
+
+ argc --, argv ++;
+ if (argc == 0) usage();
+ while (argc && **argv == '-' && argv[0][1] != 'l')
+ {
+ switch(argv[0][1]) {
+ case 'r':
+ printf("ldrdf (linker for RDF files) version " LDRDF_VERSION "\n");
+ printf( _RDOFF_H "\n");
+ exit(0);
+ case 'v':
+ if (argv[0][2] == '=') {
+ options.verbose = argv[0][3] - '0';
+ if (options.verbose < 0 || options.verbose > 9) {
+ fprintf(stderr, "ldrdf: verbosity level must be a number"
+ " between 0 and 9\n");
+ exit(1);
+ }
+ }
+ else
+ options.verbose++;
+ break;
+ case 'a':
+ options.align = atoi(argv[1]);
+ if (options.align <= 0) {
+ fprintf(stderr,
+ "ldrdf: -a expects a positive number argument\n");
+ exit(1);
+ }
+ argv++, argc--;
+ break;
+ case 's':
+ options.strip = 1;
+ break;
+ case 'x':
+ options.warnUnresolved = 1;
+ break;
+ case 'o':
+ outname = argv[1];
+ argv++, argc--;
+ break;
+ default:
+ usage();
+ }
+ argv++, argc--;
}
- else if (procsw && !strcmp(*argv,"-r")) {
- printf("ldrdf version %s (%s) (%s)\n",LDRDF_VERSION,_RDOFF_H,
- sizeof(int) == 2 ? "16 bit" : "32 bit");
- exit(1);
+
+ if (options.verbose > 4) {
+ printf("ldrdf invoked with options:\n");
+ printf(" section alignment: %d bytes\n", options.align);
+ printf(" output name: `%s'\n", outname);
+ if (options.strip)
+ printf(" strip symbols\n");
+ if (options.warnUnresolved)
+ printf(" warn about unresolved symbols\n");
+ printf("\n");
}
- else if (procsw && !strcmp(*argv,"-o")) {
- ofilename = *++argv;
- --argc;
- if (execute) {
- fprintf(stderr,"ldrdf: -o and -x switches incompatible\n");
+
+ symtab = symtabNew();
+ initsegments();
+
+ if (!symtab) {
+ fprintf(stderr, "ldrdf: out of memory\n");
exit(1);
- }
- if (verbose > 1) printf("output filename set to '%s'\n",ofilename);
}
- else if (procsw && !strcmp(*argv,"-x")) {
- execute++;
- if (verbose > 1) printf("will execute linked object\n");
+
+ while (argc)
+ {
+ if (!strncmp(*argv, "-l", 2)) /* library */
+ add_library(*argv + 2);
+ else {
+ loadmodule(*argv);
+ moduleloaded = 1;
+ }
+ argv++, argc--;
}
- else if (procsw && !strcmp(*argv,"-a")) {
- relocateaddr = readnum(*++argv,&tmp);
- --argc;
- if (tmp) {
- fprintf(stderr,"ldrdf: error in parameter to '-a' switch: '%s'\n",
- *argv);
- exit(1);
- }
- if (execute) {
- fprintf(stderr,"ldrdf: -a and -x switches incompatible\n");
- exit(1);
- }
- if (verbose) printf("will relocate to %08lx\n",relocateaddr);
+
+ if (! moduleloaded) {
+ printf("ldrdf: nothing to do. ldrdf -h for usage\n");
+ return 0;
}
- else if (procsw && !strcmp(*argv,"-v")) {
- verbose++;
- if (verbose == 1) printf("verbose mode selected\n");
+
+
+ search_libraries();
+
+ if (options.verbose > 2)
+ {
+ printf ("symbol table:\n");
+ symtabDump(symtab, stdout);
}
- else if (procsw && !strcmp(*argv,"-p")) {
- align = readnum(*++argv,&tmp);
- --argc;
- if (tmp) {
- fprintf(stderr,"ldrdf: error in parameter to '-p' switch: '%s'\n",
- *argv);
- exit(1);
- }
- if (align != 1 && align != 2 && align != 4 && align != 8 && align != 16
- && align != 32 && align != 256) {
- fprintf(stderr,"ldrdf: %d is an invalid alignment factor - must be"
- "1,2,4,8,16 or 256\n",align);
+
+ write_output(outname);
+
+ if (errorcount > 0)
exit(1);
- }
- if (verbose > 1) printf("alignment %d selected\n",align);
- }
- else if (procsw && !strncmp(*argv,"-l",2)) {
- load_library(*argv + 2);
- }
- else if (procsw && !strcmp(*argv,"--")) {
- procsw = 0;
- }
- else { /* is a filename */
- if (verbose > 1) printf("processing module %s\n",*argv);
- loadmodule(*argv);
- }
- }
-
- /* we should be scanning for unresolved references, and removing
- unreferenced modules from the list of modules here, so that
- we know about the final size once libraries have been linked in */
-
- build_symbols(); /* build a global symbol table... */
-
- scan_libraries(); /* check for imported symbols not in table,
- and ensure the relevant library modules
- are loaded */
-
- load_segments(); /* having calculated size of reqd segments, load
- each rdoff module's segments into memory */
-
- link_segments(); /* step through each module's header, and resolve
- references to the global symbol table.
- This also does local address fixups. */
-
- if (errors) {
- fprintf(stderr,"ldrdf: there were errors - aborted\n");
- exit(errors);
- }
- if (execute) {
- fprintf(stderr,"ldrdf: module execution not yet supported\n");
- exit(1);
- }
- if (relocateaddr != -1) {
- fprintf(stderr,"ldrdf: static relocation not yet supported\n");
- exit(1);
- }
-
- write_output(ofilename);
- return 0;
+
+ return 0;
}
+
diff --git a/rdoff/ldrdf1.c b/rdoff/ldrdf1.c
new file mode 100644
index 00000000..9e4a215d
--- /dev/null
+++ b/rdoff/ldrdf1.c
@@ -0,0 +1,728 @@
+/* ldrdf.c RDOFF Object File linker/loader main program
+ *
+ * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
+ * Julian Hall. All rights reserved. The software is
+ * redistributable under the licence given in the file "Licence"
+ * distributed in the NASM archive.
+ */
+
+/* TODO: Make the system skip a module (other than the first) if none
+ * of the other specified modules contain a reference to it.
+ * May require the system to make an extra pass of the modules to be
+ * loaded eliminating those that aren't required.
+ *
+ * Support all the existing documented options...
+ *
+ * Support libaries (.a files - requires a 'ranlib' type utility)
+ * (I think I've got this working, so I've upped the version)
+ *
+ * -s option to strip resolved symbols from exports. (Could make this an
+ * external utility)
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "rdoff.h"
+#include "nasmlib.h"
+#include "symtab.h"
+#include "collectn.h"
+#include "rdlib.h"
+
+#define LDRDF_VERSION "0.30"
+
+/* global variables - those to set options: */
+
+int verbose = 0; /* reflects setting of command line switch */
+int align = 16;
+int errors = 0; /* set by functions to cause halt after current
+ stage of processing */
+
+/* the linked list of modules that must be loaded & linked */
+
+struct modulenode {
+ rdffile f; /* the file */
+ long coderel; /* module's code relocation factor */
+ long datarel; /* module's data relocation factor */
+ long bssrel; /* module's bss data reloc. factor */
+ void * header; /* header location, if loaded */
+ char * name; /* filename */
+ struct modulenode *next;
+};
+
+#define newstr(str) strcpy(malloc(strlen(str) + 1),str)
+#define newstrcat(s1,s2) strcat(strcpy(malloc(strlen(s1)+strlen(s2)+1),s1),s2)
+
+
+struct modulenode *modules = NULL,*lastmodule = NULL;
+
+/* the linked list of libraries to be searched for missing imported
+ symbols */
+
+struct librarynode * libraries = NULL, * lastlib = NULL;
+
+void *symtab; /* The symbol table */
+
+rdf_headerbuf * newheader ; /* New header to be written to output */
+
+/* loadmodule - find the characteristics of a module and add it to the
+ * list of those being linked together */
+
+void loadmodule(char *filename)
+{
+ struct modulenode *prev;
+ if (! modules) {
+ modules = malloc(sizeof(struct modulenode));
+ lastmodule = modules;
+ prev = NULL;
+ }
+ else {
+ lastmodule->next = malloc(sizeof(struct modulenode));
+ prev = lastmodule;
+ lastmodule = lastmodule->next;
+ }
+
+ if (! lastmodule) {
+ fputs("ldrdf: not enough memory\n",stderr);
+ exit(1);
+ }
+
+ if (rdfopen(&lastmodule->f,filename)) {
+ rdfperror("ldrdf",filename);
+ exit(1);
+ }
+
+ lastmodule->header = NULL; /* header hasn't been loaded */
+ lastmodule->name = filename;
+ lastmodule->next = NULL;
+
+ if (prev) {
+ lastmodule->coderel = prev->coderel + prev->f.code_len;
+ if (lastmodule->coderel % align != 0)
+ lastmodule->coderel += align - (lastmodule->coderel % align);
+ lastmodule->datarel = prev->datarel + prev->f.data_len;
+ if (lastmodule->datarel % align != 0)
+ lastmodule->datarel += align - (lastmodule->datarel % align);
+ }
+ else {
+ lastmodule->coderel = 0;
+ lastmodule->datarel = 0;
+ }
+
+ if (verbose)
+ printf("%s code = %08lx (+%04lx), data = %08lx (+%04lx)\n",filename,
+ lastmodule->coderel,lastmodule->f.code_len,
+ lastmodule->datarel,lastmodule->f.data_len);
+
+ lastmodule->header = malloc(lastmodule->f.header_len);
+ if (!lastmodule->header) {
+ fprintf(stderr,"ldrdf: out of memory\n");
+ exit(1);
+ }
+
+ if (rdfloadseg(&lastmodule->f,RDOFF_HEADER,lastmodule->header))
+ {
+ rdfperror("ldrdf",filename);
+ exit(1);
+ }
+}
+
+/* load_library add a library to list of libraries to search
+ * for undefined symbols
+ */
+
+void load_library(char * name)
+{
+ if (verbose)
+ printf("adding library %s to search path\n",name);
+
+ if (! lastlib) {
+ lastlib = libraries = malloc(sizeof(struct librarynode));
+ }
+ else
+ {
+ lastlib->next = malloc(sizeof(struct librarynode));
+ lastlib = lastlib->next;
+ }
+
+ if (! lastlib) {
+ fprintf(stderr, "ldrdf: out of memory\n");
+ exit(1);
+ }
+ strcpy (lastlib->name = malloc (1+strlen(name)), name);
+ lastlib->fp = NULL;
+ lastlib->referenced = 0;
+ lastlib->next = NULL;
+}
+
+
+/* build_symbols() step through each module's header, and locate
+ * exported symbols, placing them in a global table
+ */
+
+long bsslength;
+
+void mod_addsymbols(struct modulenode * mod)
+{
+ rdfheaderrec *r;
+ symtabEnt e;
+ long cbBss;
+
+ mod->bssrel = bsslength;
+ cbBss = 0;
+ rdfheaderrewind(&mod->f);
+ while ((r = rdfgetheaderrec(&mod->f)))
+ {
+
+ if (r->type == 5) /* Allocate BSS */
+ cbBss += r->b.amount;
+
+ if (r->type != 3) continue; /* ignore all but export recs */
+
+ e.segment = r->e.segment;
+ e.offset = r->e.offset +
+ (e.segment == 0 ? mod->coderel : /* 0 -> code */
+ e.segment == 1 ? mod->datarel : /* 1 -> data */
+ mod->bssrel) ; /* 2 -> bss */
+
+ e.flags = 0;
+ e.name = malloc(strlen(r->e.label) + 1);
+ if (! e.name)
+ {
+ fprintf(stderr,"ldrdf: out of memory\n");
+ exit(1);
+ }
+ strcpy(e.name,r->e.label);
+ symtabInsert(symtab,&e);
+ }
+ bsslength += cbBss;
+}
+
+void build_symbols()
+{
+ struct modulenode *mod;
+
+ if (verbose) printf("building global symbol table:\n");
+ newheader = rdfnewheader();
+
+ symtab = symtabNew();
+ bsslength = 0; /* keep track of location of BSS symbols */
+
+ for (mod = modules; mod; mod = mod->next)
+ {
+ mod_addsymbols( mod );
+ }
+ if (verbose)
+ {
+ symtabDump(symtab,stdout);
+ printf("BSS length = %ld bytes\n\n",bsslength);
+ }
+}
+
+
+/* scan_libraries() search through headers of modules for undefined
+ * symbols, and scan libraries for those symbols,
+ * adding library modules found to list of modules
+ * to load. */
+
+void scan_libraries(void)
+{
+ struct modulenode * mod, * nm;
+ struct librarynode * lib;
+ rdfheaderrec * r;
+ int found;
+ char * tmp;
+
+ if (verbose) printf("Scanning libraries for unresolved symbols...\n");
+
+ mod = modules;
+
+ while (mod)
+ {
+ rdfheaderrewind(&mod->f);
+
+ while ((r = rdfgetheaderrec(&mod->f)))
+ {
+ if (r->type != 2) continue; /* not an import record */
+ if ( symtabFind (symtab,r->i.label) )
+ continue; /* symbol already defined */
+
+ /* okay, we have an undefined symbol... step through
+ the libraries now */
+ if (verbose >= 2) {
+ printf("undefined symbol '%s'...",r->i.label);
+ fflush(stdout);
+ }
+
+ lib = libraries;
+ found = 0;
+
+ tmp = newstr(r->i.label);
+ while (! found && lib)
+ {
+ /* move this to an outer loop...! */
+ nm = malloc(sizeof(struct modulenode));
+
+ if (rdl_searchlib(lib,tmp,&nm->f))
+ { /* found a module in the library */
+
+ /* create a modulenode for it */
+
+ if (! nm) {
+ fprintf(stderr,"ldrdf: out of memory\n");
+ exit(1);
+ }
+
+ nm->name = newstrcat(lib->name,nm->f.name);
+ if (verbose >= 2) printf("found in '%s'\n",nm->name);
+
+ nm->coderel = lastmodule->coderel + lastmodule->f.code_len;
+ if (nm->coderel % align != 0)
+ nm->coderel += align - (nm->coderel % align);
+
+ nm->datarel = lastmodule->datarel + lastmodule->f.data_len;
+ if (nm->datarel % align != 0)
+ nm->datarel += align - (nm->datarel % align);
+
+ nm->header = malloc(nm->f.header_len);
+ if (! nm->header)
+ {
+ fprintf(stderr,"ldrdf: out of memory\n");
+ exit(1);
+ }
+
+ if (rdfloadseg(&nm->f,RDOFF_HEADER,nm->header))
+ {
+ rdfperror("ldrdf",nm->name);
+ exit(1);
+ }
+
+ nm->next = NULL;
+ found = 1;
+ lastmodule->next = nm;
+ lastmodule = nm;
+
+ if (verbose)
+ printf("%s code = %08lx (+%04lx), data = %08lx "
+ "(+%04lx)\n",lastmodule->name,
+ lastmodule->coderel,lastmodule->f.code_len,
+ lastmodule->datarel,lastmodule->f.data_len);
+
+ /* add the module's info to the symbol table */
+ mod_addsymbols(nm);
+ }
+ else
+ {
+ if (rdl_error) {
+ rdl_perror("ldrdf",lib->name);
+ exit(1);
+ }
+ free(nm);
+ }
+ lib = lib->next;
+ }
+ free(tmp);
+ if (!found && verbose >= 2) printf("not found\n");
+ }
+ mod = mod->next;
+ }
+}
+
+/* load_segments() allocates memory for & loads the code & data segs
+ * from the RDF modules
+ */
+
+char *text,*data;
+long textlength,datalength;
+
+void load_segments(void)
+{
+ struct modulenode *mod;
+
+ if (!modules) {
+ fprintf(stderr,"ldrdf: nothing to do\n");
+ exit(0);
+ }
+ if (!lastmodule) {
+ fprintf(stderr,"ldrdf: panic: module list exists, but lastmodule=NULL\n");
+ exit(3);
+ }
+
+ if (verbose)
+ printf("loading modules into memory\n");
+
+ /* The following stops 16 bit DOS from crashing whilst attempting to
+ work using segments > 64K */
+ if (sizeof(int) == 2) { /* expect a 'code has no effect' warning on 32 bit
+ platforms... */
+ if (lastmodule->coderel + lastmodule->f.code_len > 65535 ||
+ lastmodule->datarel + lastmodule->f.data_len > 65535) {
+ fprintf(stderr,"ldrdf: segment length has exceeded 64K; use a 32 bit "
+ "version.\nldrdf: code size = %05lx, data size = %05lx\n",
+ lastmodule->coderel + lastmodule->f.code_len,
+ lastmodule->datarel + lastmodule->f.data_len);
+ exit(1);
+ }
+ }
+
+ text = malloc(textlength = lastmodule->coderel + lastmodule->f.code_len);
+ data = malloc(datalength = lastmodule->datarel + lastmodule->f.data_len);
+
+ if (!text || !data) {
+ fprintf(stderr,"ldrdf: out of memory\n");
+ exit(1);
+ }
+
+ mod = modules;
+ while (mod) { /* load the segments for each module */
+ if (verbose >= 2) printf(" loading %s\n",mod->name);
+ if (rdfloadseg(&mod->f,RDOFF_CODE,&text[mod->coderel]) ||
+ rdfloadseg(&mod->f,RDOFF_DATA,&data[mod->datarel])) {
+ rdfperror("ldrdf",mod->name);
+ exit(1);
+ }
+ rdfclose(&mod->f); /* close file; segments remain */
+ mod = mod->next;
+ }
+}
+
+/* link_segments() step through relocation records in each module's
+ * header, fixing up references.
+ */
+
+void link_segments(void)
+{
+ struct modulenode *mod;
+ Collection imports;
+ symtabEnt *s;
+ long rel,relto;
+ char *seg;
+ rdfheaderrec *r;
+ int bRelative;
+
+ if (verbose) printf("linking segments\n");
+
+ collection_init(&imports);
+
+ for (mod = modules; mod; mod = mod->next) {
+ if (verbose >= 2) printf("* processing %s\n",mod->name);
+ rdfheaderrewind(&mod->f);
+ while((r = rdfgetheaderrec(&mod->f))) {
+ if (verbose >= 3) printf("record type: %d\n",r->type);
+ switch(r->type) {
+ case 1: /* relocation record */
+ if (r->r.segment >= 64) { /* Relative relocation; */
+ bRelative = 1; /* need to find location relative */
+ r->r.segment -= 64; /* to start of this segment */
+ relto = r->r.segment == 0 ? mod->coderel : mod->datarel;
+ }
+ else
+ {
+ bRelative = 0; /* non-relative - need to relocate
+ * at load time */
+ relto = 0; /* placate optimiser warnings */
+ }
+
+ /* calculate absolute offset of reference, not rel to beginning of
+ segment */
+ r->r.offset += r->r.segment == 0 ? mod->coderel : mod->datarel;
+
+ /* calculate the relocation factor to apply to the operand -
+ the base address of one of this modules segments if referred
+ segment is 0 - 2, or the address of an imported symbol
+ otherwise. */
+
+ if (r->r.refseg == 0) rel = mod->coderel;
+ else if (r->r.refseg == 1) rel = mod->datarel;
+ else if (r->r.refseg == 2) rel = mod->bssrel;
+ else { /* cross module link - find reference */
+ s = *colln(&imports,r->r.refseg - 2);
+ if (!s) {
+ fprintf(stderr,"ldrdf: link to undefined segment %04x in"
+ " %s:%d\n", r->r.refseg,mod->name,r->r.segment);
+ errors = 1;
+ break;
+ }
+ rel = s->offset;
+
+ r->r.refseg = s->segment; /* change referred segment,
+ so that new header is
+ correct */
+ }
+
+ if (bRelative) /* Relative - subtract current segment start */
+ rel -= relto;
+ else
+ { /* Add new relocation header */
+ rdfaddheader(newheader,r);
+ }
+
+ /* Work out which segment we're making changes to ... */
+ if (r->r.segment == 0) seg = text;
+ else if (r->r.segment == 1) seg = data;
+ else {
+ fprintf(stderr,"ldrdf: relocation in unknown segment %d in "
+ "%s\n", r->r.segment,mod->name);
+ errors = 1;
+ break;
+ }
+
+ /* Add the relocation factor to the datum specified: */
+
+ if (verbose >= 3)
+ printf(" - relocating %d:%08lx by %08lx\n",r->r.segment,
+ r->r.offset,rel);
+
+ /**** The following code is non-portable. Rewrite it... ****/
+ switch(r->r.length) {
+ case 1:
+ seg[r->r.offset] += (char) rel;
+ break;
+ case 2:
+ *(int16 *)(seg + r->r.offset) += (int16) rel;
+ break;
+ case 4:
+ *(long *)(seg + r->r.offset) += rel;
+ break;
+ }
+ break;
+
+ case 2: /* import record */
+ s = symtabFind(symtab, r->i.label);
+ if (s == NULL) {
+ /* Need to add support for dynamic linkage */
+ fprintf(stderr,"ldrdf: undefined symbol %s in module %s\n",
+ r->i.label,mod->name);
+ errors = 1;
+ }
+ else
+ {
+ *colln(&imports,r->i.segment - 2) = s;
+ if (verbose >= 2)
+ printf("imported %s as %04x\n", r->i.label, r->i.segment);
+ }
+ break;
+
+ case 3: /* export; dump to output new version */
+ s = symtabFind(symtab, r->e.label);
+ if (! s) {
+ fprintf(stderr,"ldrdf: internal error - undefined symbol %s "
+ "exported in header of '%s'\n",r->e.label,mod->name);
+ continue;
+ }
+ r->e.offset = s->offset;
+ rdfaddheader(newheader,r);
+ break;
+
+ case 4: /* DLL record */
+ rdfaddheader(newheader,r); /* copy straight to output */
+ break;
+ }
+ }
+ if (rdf_errno != 0) {
+ rdfperror("ldrdf",mod->name);
+ exit(1);
+ }
+ collection_reset(&imports);
+ }
+}
+
+/* write_output() write linked program out to a file */
+
+void write_output(char *filename)
+{
+ FILE * fp;
+ rdfheaderrec r;
+
+ if (verbose) printf("writing output to '%s'\n",filename);
+
+ fp = fopen(filename,"wb");
+ if (! fp)
+ {
+ fprintf(stderr,"ldrdf: could not open '%s' for writing\n",filename);
+ exit(1);
+ }
+
+
+ /* add BSS length count to header... */
+ if (bsslength)
+ {
+ r.type = 5;
+ r.b.amount = bsslength;
+ rdfaddheader(newheader,&r);
+ }
+
+ /* Write header */
+ rdfwriteheader(fp,newheader);
+ rdfdoneheader(newheader);
+ newheader = NULL;
+
+ /* Write text */
+ if (fwrite(&textlength,1,4,fp) != 4
+ || fwrite(text,1,textlength,fp) !=textlength)
+ {
+ fprintf(stderr,"ldrdf: error writing %s\n",filename);
+ exit(1);
+ }
+
+ /* Write data */
+ if (fwrite(&datalength,1,4,fp) != 4 ||
+ fwrite(data,1,datalength,fp) != datalength)
+ {
+ fprintf (stderr,"ldrdf: error writing %s\n", filename);
+ exit(1);
+ }
+ fclose(fp);
+}
+
+
+/* main program: interpret command line, and pass parameters on to
+ * individual module loaders & the linker
+ *
+ * Command line format:
+ * ldrdf [-o outfile | -x] [-r xxxx] [-v] [--] infile [infile ...]
+ *
+ * Default action is to output a file named 'aout.rdx'. -x specifies
+ * that the linked object program should be executed, rather than
+ * written to a file. -r specifies that the object program should
+ * be prelocated at address 'xxxx'. This option cannot be used
+ * in conjunction with -x.
+ */
+
+const char *usagemsg = "usage:\n"
+" ldrdf [-o outfile | -x] [-a x] [-v] [-p x] [--] infile [infile ...]\n"
+" [-l<libname> ...]\n\n"
+" ldrdf -h displays this message\n"
+" ldrdf -r displays version information\n\n"
+" -o selects output filename (default is aout.rdx)\n"
+" -x causes ldrdx to link & execute rather than write to file\n"
+" -a x causes object program to be statically relocated to address 'x'\n"
+" -v turns on verbose mode\n"
+" -p x causes segments to be aligned (padded) to x byte boundaries\n"
+" (default is 16 bytes)\n"
+" -l<name> causes 'name' to be linked in as a library. Note no search is\n"
+" performed - the entire pathname MUST be specified.\n";
+
+void usage(void)
+{
+ fputs(usagemsg,stderr);
+}
+
+int main(int argc,char **argv)
+{
+ char *ofilename = "aout.rdx";
+ long relocateaddr = -1; /* -1 if no relocation is to occur */
+ int execute = 0; /* 1 to execute after linking, 0 otherwise */
+ int procsw = 1; /* set to 0 by '--' */
+ int tmp;
+
+ if (argc == 1) {
+ usage();
+ exit(1);
+ }
+
+ /* process command line switches, and add modules specified to linked list
+ of modules, keeping track of total memory required to load them */
+
+ while(argv++,--argc) {
+ if (procsw && !strcmp(*argv,"-h")) { /* Help command */
+ usage(); exit(1);
+ }
+ else if (procsw && !strcmp(*argv,"-r")) {
+ printf("ldrdf version %s (%s) (%s)\n",LDRDF_VERSION,_RDOFF_H,
+ sizeof(int) == 2 ? "16 bit" : "32 bit");
+ exit(1);
+ }
+ else if (procsw && !strcmp(*argv,"-o")) {
+ ofilename = *++argv;
+ --argc;
+ if (execute) {
+ fprintf(stderr,"ldrdf: -o and -x switches incompatible\n");
+ exit(1);
+ }
+ if (verbose > 1) printf("output filename set to '%s'\n",ofilename);
+ }
+ else if (procsw && !strcmp(*argv,"-x")) {
+ execute++;
+ if (verbose > 1) printf("will execute linked object\n");
+ }
+ else if (procsw && !strcmp(*argv,"-a")) {
+ relocateaddr = readnum(*++argv,&tmp);
+ --argc;
+ if (tmp) {
+ fprintf(stderr,"ldrdf: error in parameter to '-a' switch: '%s'\n",
+ *argv);
+ exit(1);
+ }
+ if (execute) {
+ fprintf(stderr,"ldrdf: -a and -x switches incompatible\n");
+ exit(1);
+ }
+ if (verbose) printf("will relocate to %08lx\n",relocateaddr);
+ }
+ else if (procsw && !strcmp(*argv,"-v")) {
+ verbose++;
+ if (verbose == 1) printf("verbose mode selected\n");
+ }
+ else if (procsw && !strcmp(*argv,"-p")) {
+ align = readnum(*++argv,&tmp);
+ --argc;
+ if (tmp) {
+ fprintf(stderr,"ldrdf: error in parameter to '-p' switch: '%s'\n",
+ *argv);
+ exit(1);
+ }
+ if (align != 1 && align != 2 && align != 4 && align != 8 && align != 16
+ && align != 32 && align != 256) {
+ fprintf(stderr,"ldrdf: %d is an invalid alignment factor - must be"
+ "1,2,4,8,16 or 256\n",align);
+ exit(1);
+ }
+ if (verbose > 1) printf("alignment %d selected\n",align);
+ }
+ else if (procsw && !strncmp(*argv,"-l",2)) {
+ load_library(*argv + 2);
+ }
+ else if (procsw && !strcmp(*argv,"--")) {
+ procsw = 0;
+ }
+ else { /* is a filename */
+ if (verbose > 1) printf("processing module %s\n",*argv);
+ loadmodule(*argv);
+ }
+ }
+
+ /* we should be scanning for unresolved references, and removing
+ unreferenced modules from the list of modules here, so that
+ we know about the final size once libraries have been linked in */
+
+ build_symbols(); /* build a global symbol table... */
+
+ scan_libraries(); /* check for imported symbols not in table,
+ and ensure the relevant library modules
+ are loaded */
+
+ load_segments(); /* having calculated size of reqd segments, load
+ each rdoff module's segments into memory */
+
+ link_segments(); /* step through each module's header, and resolve
+ references to the global symbol table.
+ This also does local address fixups. */
+
+ if (errors) {
+ fprintf(stderr,"ldrdf: there were errors - aborted\n");
+ exit(errors);
+ }
+ if (execute) {
+ fprintf(stderr,"ldrdf: module execution not yet supported\n");
+ exit(1);
+ }
+ if (relocateaddr != -1) {
+ fprintf(stderr,"ldrdf: static relocation not yet supported\n");
+ exit(1);
+ }
+
+ write_output(ofilename);
+ return 0;
+}
diff --git a/rdoff/ldsegs.h b/rdoff/ldsegs.h
new file mode 100644
index 00000000..8b516faa
--- /dev/null
+++ b/rdoff/ldsegs.h
@@ -0,0 +1,55 @@
+/*
+ * ldsegs.h Data for 'ldrdf' to determine what to do with different
+ * types of segment. This may be useful in other contexts also.
+ */
+
+#ifndef UI16
+#define UI16 unsigned short
+#endif
+
+struct segconfig {
+ UI16 typelow, typehi;/* range of seg nos for which this is valid */
+ char * typedesc; /* a description of the segment type */
+ UI16 dowhat; /* one of the SEG_xxxx values below */
+ UI16 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); \
+ } \
+ }
diff --git a/rdoff/rdf2bin.c b/rdoff/rdf2bin.c
index 97b45b4c..21ea97d3 100644
--- a/rdoff/rdf2bin.c
+++ b/rdoff/rdf2bin.c
@@ -77,7 +77,7 @@ int main(int argc, char **argv)
printf("relocating %s: origin=%lx, align=%d\n",*argv,origin,align);
m->textrel = origin;
- m->datarel = origin + m->f.code_len;
+ m->datarel = origin + m->f.seg[0].length;
if (m->datarel % align != 0) {
codepad = align - (m->datarel % align);
m->datarel += codepad;
@@ -85,7 +85,7 @@ int main(int argc, char **argv)
else
codepad = 0;
- m->bssrel = m->datarel + m->f.data_len;
+ m->bssrel = m->datarel + m->f.seg[1].length;
if (m->bssrel % align != 0) {
datapad = align - (m->bssrel % align);
m->bssrel += datapad;
@@ -112,9 +112,9 @@ int main(int argc, char **argv)
return 1;
}
- if (fwrite(m->t,1,m->f.code_len,of) != m->f.code_len ||
+ if (fwrite(m->t,1,m->f.seg[0].length,of) != m->f.seg[0].length ||
fwrite(padding,1,codepad,of) != codepad ||
- fwrite(m->d,1,m->f.data_len,of) != m->f.data_len)
+ fwrite(m->d,1,m->f.seg[1].length,of) != m->f.seg[1].length)
{
fprintf(stderr,"rdf2bin: error writing to %s\n", *argv);
return 1;
diff --git a/rdoff/rdfdump.c b/rdoff/rdfdump.c
index 080c2e73..cb79a64d 100644
--- a/rdoff/rdfdump.c
+++ b/rdoff/rdfdump.c
@@ -4,6 +4,8 @@
FILE *infile;
+typedef unsigned short int16;
+
long translatelong(long in) { /* translate from little endian to
local representation */
long r;
@@ -18,7 +20,7 @@ long translatelong(long in) { /* translate from little endian to
return r;
}
-int translateshort(short in) {
+int translateshort(int16 in) {
int r;
unsigned char *i;
@@ -27,70 +29,136 @@ int translateshort(short in) {
return r;
}
-void print_header(long length) {
+
+void print_header(long length, int rdf_version) {
char buf[129],t,s,l;
+ unsigned char reclen;
long o,ll;
- short rs;
+ int16 rs;
while (length > 0) {
fread(&t,1,1,infile);
+ if (rdf_version >= 2) {
+ fread(&reclen,1,1,infile);
+ }
switch(t) {
case 1: /* relocation record */
+ case 6: /* segment relocation */
fread(&s,1,1,infile);
fread(&o,4,1,infile);
fread(&l,1,1,infile);
fread(&rs,2,1,infile);
- printf(" relocation: location (%04x:%08lx), length %d, "
- "referred seg %04x\n",(int)s,translatelong(o),(int)l,
+ printf(" %s: location (%04x:%08lx), length %d, "
+ "referred seg %04x\n", t == 1 ? "relocation" : "seg relocation",
+ (int)s,translatelong(o),(int)l,
translateshort(rs));
- length -= 9;
+ 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 2: /* import record */
+ case 7: /* import far symbol */
fread(&rs,2,1,infile);
ll = 0;
- do {
- fread(&buf[ll],1,1,infile);
- } while (buf[ll++]);
- printf(" import: segment %04x = %s\n",translateshort(rs),buf);
- length -= ll + 3;
+
+ if (rdf_version == 1) {
+ do {
+ fread(&buf[ll],1,1,infile);
+ } while (buf[ll++]);
+ }
+ else
+ {
+ for (;ll < reclen - 2; ll++)
+ fread(&buf[ll],1,1,infile);
+ }
+
+ printf(" %simport: segment %04x = %s\n",t == 7 ? "far " : "",
+ translateshort(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 3: /* export record */
fread(&s,1,1,infile);
fread(&o,4,1,infile);
ll = 0;
- do {
- fread(&buf[ll],1,1,infile);
- } while (buf[ll++]);
+
+ if (rdf_version == 1) {
+ do {
+ fread(&buf[ll],1,1,infile);
+ } while (buf[ll++]);
+ }
+ else
+ {
+ for (; ll < reclen - 5; ll ++)
+ fread(&buf[ll],1,1,infile);
+ }
printf(" export: (%04x:%08lx) = %s\n",(int)s,translatelong(o),buf);
- length -= ll + 6;
+ if (rdf_version == 1) length -= ll + 6;
break;
case 4: /* DLL record */
ll = 0;
- do {
- fread(&buf[ll],1,1,infile);
- } while (buf[ll++]);
+
+ if (rdf_version == 1) {
+ do {
+ fread(&buf[ll],1,1,infile);
+ } while (buf[ll++]);
+ }
+ else
+ {
+ for (; ll < reclen - 1; ll++)
+ fread(&buf[ll],1,1,infile);
+ }
printf(" dll: %s\n",buf);
- length -= ll + 1;
+ if (rdf_version == 1) length -= ll + 1;
break;
case 5: /* BSS reservation */
fread(&ll,4,1,infile);
printf(" bss reservation: %08lx bytes\n",translatelong(ll));
- length -= 5;
+ if (rdf_version == 1) length -= 5;
+ if (rdf_version > 1 && reclen != 4)
+ printf(" warning: reclen != 4\n");
break;
default:
- printf(" unrecognised record (type %d)\n",(int)t);
- length --;
+ printf(" unrecognised record (type %d",(int)t);
+ if (rdf_version > 1) printf(", length %d",(int)reclen);
+ printf(")\n");
+ if (rdf_version == 1) length --;
}
+ if (rdf_version != 1) length -= 2 + reclen;
}
}
+char * knowntypes[8] = {"NULL", "text", "data", "object comment",
+ "linked comment", "loader comment",
+ "symbolic debug", "line number debug"};
+
+char * translatesegmenttype(int16 type) {
+ if (type < 8) return knowntypes[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";
+}
+
int main(int argc,char **argv) {
char id[7];
long l;
+ int16 s;
int verbose = 0;
long offset;
+ int foundnullsegment = 0;
+ int version;
+ long segmentcontentlength = 0;
+ int nsegments = 0;
+ long headerlength = 0;
+ long objectlength = 0;
- puts("RDOFF Dump utility v1.1 (C) Copyright 1996 Julian R Hall");
+ puts("RDOFF Dump utility v2.0 (C) Copyright 1996 Julian R Hall");
if (argc < 2) {
fputs("Usage: rdfdump [-v] <filename>\n",stderr);
@@ -121,46 +189,103 @@ int main(int argc,char **argv) {
}
printf("File %s: RDOFF version %c\n\n",argv[1],id[5]);
- if (id[5] < '1' || id[5] > '1') {
+ if (id[5] < '1' || id[5] > '2') {
fprintf(stderr,"rdfdump: unknown RDOFF version '%c'\n",id[5]);
exit(1);
}
+ version = id[5] - '0';
- fread(&l,4,1,infile);
- l = translatelong(l);
- printf("Header (%ld bytes):\n",l);
- print_header(l);
-
- fread(&l,4,1,infile);
- l = translatelong(l);
- printf("\nText segment length = %ld bytes\n",l);
- offset = 0;
- while(l--) {
- fread(id,1,1,infile);
- if (verbose) {
- if (offset % 16 == 0)
- printf("\n%08lx ", offset);
- printf(" %02x",(int) (unsigned char)id[0]);
- offset++;
- }
+ if (version > 1) {
+ fread(&l, 4, 1, infile);
+ objectlength = translatelong(l);
+ printf("Object content size: %ld bytes\n", objectlength);
}
- if (verbose) printf("\n\n");
fread(&l,4,1,infile);
- l = translatelong(l);
- printf("Data segment length = %ld bytes\n",l);
+ headerlength = translatelong(l);
+ printf("Header (%ld bytes):\n",headerlength);
+ print_header(headerlength, version);
+
+ if (version == 1) {
+ fread(&l,4,1,infile);
+ l = translatelong(l);
+ printf("\nText segment length = %ld bytes\n",l);
+ offset = 0;
+ while(l--) {
+ fread(id,1,1,infile);
+ if (verbose) {
+ if (offset % 16 == 0)
+ printf("\n%08lx ", offset);
+ printf(" %02x",(int) (unsigned char)id[0]);
+ offset++;
+ }
+ }
+ if (verbose) printf("\n\n");
+
+ fread(&l,4,1,infile);
+ l = translatelong(l);
+ printf("Data segment length = %ld bytes\n",l);
- if (verbose)
+ if (verbose)
+ {
+ offset = 0;
+ while (l--) {
+ fread(id,1,1,infile);
+ if (offset % 16 == 0)
+ printf("\n%08lx ", offset);
+ printf(" %02x",(int) (unsigned char) id[0]);
+ offset++;
+ }
+ printf("\n");
+ }
+ }
+ else
{
- offset = 0;
- while (l--) {
- fread(id,1,1,infile);
- if (offset % 16 == 0)
- printf("\n%08lx ", offset);
- printf(" %02x",(int) (unsigned char) id[0]);
- offset++;
- }
- printf("\n");
+ do {
+ fread(&s,2,1,infile);
+ s = translateshort(s);
+ if (!s) {
+ printf("\nNULL segment\n");
+ foundnullsegment = 1;
+ break;
+ }
+ printf("\nSegment:\n Type = %04X (%s)\n",(int)s,
+ translatesegmenttype(s));
+ nsegments++;
+
+ fread(&s,2,1,infile);
+ printf(" Number = %04X\n",(int)translateshort(s));
+ fread(&s,2,1,infile);
+ printf(" Resrvd = %04X\n",(int)translateshort(s));
+ fread(&l,4,1,infile);
+ l = translatelong(l);
+ printf(" Length = %ld bytes\n",l);
+ segmentcontentlength += l;
+
+ offset = 0;
+ while(l--) {
+ fread(id,1,1,infile);
+ if (verbose) {
+ if (offset % 16 == 0)
+ printf("\n%08lx ", offset);
+ printf(" %02x",(int) (unsigned char)id[0]);
+ offset++;
+ }
+ }
+ if (verbose) printf("\n");
+ } while (!feof(infile));
+ if (! foundnullsegment)
+ printf("\nWarning: unexpected end of file - "
+ "NULL segment not found\n");
+
+ printf("\nTotal number of segments: %d\n", nsegments);
+ printf("Total segment content length: %ld bytes\n",segmentcontentlength);
+
+ /* calculate what the total object content length should have been */
+ l = segmentcontentlength + 10 * (nsegments+1) + headerlength + 4;
+ if (l != objectlength)
+ printf("Warning: actual object length (%ld) != "
+ "stored object length (%ld)\n", l, objectlength);
}
fclose(infile);
return 0;
diff --git a/rdoff/rdflib.c b/rdoff/rdflib.c
index 58465626..7a00fc6d 100644
--- a/rdoff/rdflib.c
+++ b/rdoff/rdflib.c
@@ -1,12 +1,22 @@
/* 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. There may be an optional
- directory placed on the end of the file. The format of the
- directory will be 'RDL' 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. */
+/*
+ * 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.
+ *
+ * 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 byte type & version identifier
+ * followed by long content size, followed by data.
+ */
#include <stdio.h>
#include <errno.h>
@@ -15,7 +25,7 @@
/* functions supported:
create a library (no extra operands required)
add a module from a library (requires filename and name to give mod.)
- remove a module from a library (requires given name)
+ remove a module from a library (requires given name) (not implemented)
extract a module from the library (requires given name and filename)
list modules */
@@ -25,7 +35,7 @@ const char *usage =
" where x is one of:\n"
" c - create library\n"
" a - add module (operands = filename module-name)\n"
- " r - remove (module-name)\n"
+ " r - remove (module-name) [not implemented]\n"
" x - extract (module-name filename)\n"
" t - list\n";
@@ -48,26 +58,27 @@ static void longtolocal(long * l)
#endif
}
-void copybytes(FILE *fp, FILE *fp2, int n)
+char copybytes(FILE *fp, FILE *fp2, int n)
{
- int i,t;
+ int i, t = 0;
for (i = 0 ; i < n; i++ )
{
t = fgetc(fp);
if (t == EOF)
{
- fprintf(stderr,"ldrdf: premature end of file in '%s'\n",
+ fprintf(stderr,"rdflib: premature end of file in '%s'\n",
_argv[2]);
exit(1);
}
if (fp2)
if (fputc(t, fp2) == EOF)
{
- fprintf(stderr,"ldrdf: write error\n");
+ fprintf(stderr,"rdflib: write error\n");
exit(1);
}
}
+ return (char) t; /* return last char read */
}
long copylong(FILE *fp, FILE *fp2)
@@ -82,14 +93,14 @@ long copylong(FILE *fp, FILE *fp2)
t = fgetc(fp);
if (t == EOF)
{
- fprintf(stderr,"ldrdf: premature end of file in '%s'\n",
+ fprintf(stderr,"rdflib: premature end of file in '%s'\n",
_argv[2]);
exit(1);
}
if (fp2)
if (fputc(t, fp2) == EOF)
{
- fprintf(stderr,"ldrdf: write error\n");
+ fprintf(stderr,"rdflib: write error\n");
exit(1);
}
*p++ = t;
@@ -101,8 +112,9 @@ long copylong(FILE *fp, FILE *fp2)
int main(int argc, char **argv)
{
FILE *fp, *fp2;
- char *p, buf[256];
+ char *p, buf[256], c;
int i;
+ long l;
_argv = argv;
@@ -117,8 +129,8 @@ int main(int argc, char **argv)
case 'c': /* create library */
fp = fopen(argv[2],"wb");
if (! fp) {
- fprintf(stderr,"ldrdf: could not open '%s'\n",argv[2]);
- perror("ldrdf");
+ fprintf(stderr,"rdflib: could not open '%s'\n",argv[2]);
+ perror("rdflib");
exit(1);
}
fclose(fp);
@@ -126,29 +138,29 @@ int main(int argc, char **argv)
case 'a': /* add module */
if (argc < 5) {
- fprintf(stderr,"ldrdf: required parameter missing\n");
+ fprintf(stderr,"rdflib: required parameter missing\n");
exit(1);
}
fp = fopen(argv[2],"ab");
if (! fp)
{
- fprintf(stderr,"ldrdf: could not open '%s'\n",argv[2]);
- perror("ldrdf");
+ fprintf(stderr,"rdflib: could not open '%s'\n",argv[2]);
+ perror("rdflib");
exit(1);
}
fp2 = fopen(argv[3],"rb");
if (! fp)
{
- fprintf(stderr,"ldrdf: could not open '%s'\n",argv[3]);
- perror("ldrdf");
+ 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,"ldrdf: write error\n");
+ fprintf(stderr,"rdflib: write error\n");
exit(1);
}
} while (*p++);
@@ -160,7 +172,7 @@ int main(int argc, char **argv)
}
if ( fputc(i, fp) == EOF ) {
- fprintf(stderr,"ldrdf: write error\n");
+ fprintf(stderr,"rdflib: write error\n");
exit(1);
}
}
@@ -170,15 +182,19 @@ int main(int argc, char **argv)
case 'x':
if (argc < 5) {
- fprintf(stderr,"ldrdf: required parameter missing\n");
+ fprintf(stderr,"rdflib: required parameter missing\n");
+ exit(1);
+ }
+ case 't':
+ if (argc < 3) {
+ fprintf(stderr, "rdflib: required paramenter missing\n");
exit(1);
}
-
fp = fopen(argv[2],"rb");
if (! fp)
{
- fprintf(stderr,"ldrdf: could not open '%s'\n",argv[2]);
- perror("ldrdf");
+ fprintf(stderr,"rdflib: could not open '%s'\n",argv[2]);
+ perror("rdflib");
exit(1);
}
@@ -191,25 +207,60 @@ int main(int argc, char **argv)
if (feof(fp)) break;
- /* check against desired name */
- if (! strcmp(buf,argv[3]) )
- {
- fp2 = fopen(argv[4],"wb");
- if (! fp2)
+ fp2 = NULL;
+ if (argv[1][0] == 'x') {
+ /* check against desired name */
+ if (! strcmp(buf,argv[3]) )
{
- fprintf(stderr,"ldrdf: could not open '%s'\n", argv[4]);
- perror("ldrdf");
- exit(1);
+ fp2 = fopen(argv[4],"wb");
+ if (! fp2)
+ {
+ fprintf(stderr,"rdflib: could not open '%s'\n",argv[4]);
+ perror("rdflib");
+ exit(1);
+ }
}
}
else
- fp2 = NULL;
+ 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);
- /* step over the RDOFF file, copying it if fp2 != NULL */
- copybytes(fp,fp2,6); /* magic number */
- copybytes(fp,fp2, copylong(fp,fp2)); /* header */
- copybytes(fp,fp2, copylong(fp,fp2)); /* text */
- copybytes(fp,fp2, copylong(fp,fp2)); /* data */
+ l = copylong(fp,fp2);
+
+ if (argv[1][0] == 't') printf(" %ld bytes content\n", l);
+
+ copybytes(fp,fp2,l);
+ }
+ else if ((c=copybytes(fp,fp2,6)) >= '2') /* version 2 or above */
+ {
+ l = copylong(fp,fp2);
+
+ if (argv[1][0] == 't')
+ printf("RDOFF%c %ld 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, copylong(fp,fp2)); /* header */
+ copybytes(fp,fp2, copylong(fp,fp2)); /* text */
+ copybytes(fp,fp2, copylong(fp,fp2)); /* data */
+ }
if (fp2)
break;
@@ -217,16 +268,16 @@ int main(int argc, char **argv)
fclose(fp);
if (fp2)
fclose(fp2);
- else
+ else if (argv[1][0] == 'x')
{
- fprintf(stderr,"ldrdf: module '%s' not found in '%s'\n",
+ fprintf(stderr,"rdflib: module '%s' not found in '%s'\n",
argv[3],argv[2]);
exit(1);
}
break;
default:
- fprintf(stderr,"ldrdf: command '%c' not recognised\n",
+ fprintf(stderr,"rdflib: command '%c' not recognised\n",
argv[1][0]);
exit(1);
}
diff --git a/rdoff/rdfload.c b/rdoff/rdfload.c
index b8483444..5b981034 100644
--- a/rdoff/rdfload.c
+++ b/rdoff/rdfload.c
@@ -10,6 +10,13 @@
* with instructions of how to obtain a copy via ftp.
*/
+/*
+ * 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 <stdlib.h>
#include <stdio.h>
@@ -49,8 +56,8 @@ rdfmodule * rdfload(const char *filename)
/* read in text and data segments, and header */
- f->t = malloc (f->f.code_len);
- f->d = malloc (f->f.data_len); /* BSS seg allocated later */
+ 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) {
@@ -135,7 +142,7 @@ int rdf_relocate(rdfmodule * m)
if ((r->r.segment & 63) == 0) seg = m->t;
else if ((r->r.segment & 63) == 1) seg = m->d;
else
- return 1;
+ 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
@@ -167,6 +174,11 @@ int rdf_relocate(rdfmodule * m)
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/rdlib.c b/rdoff/rdlib.c
index bc8d1e35..ed78a005 100644
--- a/rdoff/rdlib.c
+++ b/rdoff/rdlib.c
@@ -1,22 +1,113 @@
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include "rdoff.h"
#include "rdlib.h"
+/*
+ * format of rdoff library files:
+ * repeat
+ * null terminated module name (max 255 chars)
+ * RDOFF module
+ * until eof
+ */
+
+/*
+ * TODO
+ *
+ * No support exists yet for special modules. But we aren't using
+ * any special modules yet. They are only defined now so that their
+ * existance doesn't break older versions of the linker... presently
+ * anything whose name begins with '.' is ignored.
+ */
+
int rdl_error = 0;
-char *rdl_errors[3] = {
+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;
+ long 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;
+
+ fread(buf, 6, 1, fp);
+ buf[6] = 0;
+ if (buf[0] == '.') {
+ /*
+ * a special module, eg a directory.
+ * Format of such a module is defined to be:
+ * six char type identifier (which we've already read)
+ * long count bytes content
+ * content
+ * so we can handle it uniformaly with RDOFF2 modules...
+ * do nothing here. :-)
+ */
+ }
+ else if (strncmp(buf, "RDOFF", 5)) {
+ return rdl_error = lastresult = 2;
+ }
+ else if (buf[5] != '2') {
+ return rdl_error = lastresult = 3;
+ }
+
+ fread(&length, 4, 1, fp);
+ fseek(fp, length, SEEK_CUR); /* skip over the module */
+ }
+ 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[257];
- int i;
+ char buf[512];
+ int i, t;
void * hdr;
rdfheaderrec * r;
+ long l;
rdl_error = 0;
lib->referenced ++;
@@ -35,18 +126,36 @@ int rdl_searchlib (struct librarynode * lib,
while (! feof(lib->fp) )
{
- i = 1;
- while (fread(buf + i,1,1,lib->fp) == 1 && buf[i] && i < 257)
+ /*
+ * 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[0] = ':';
+ 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 = 2;
+ 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);
@@ -65,11 +174,14 @@ int rdl_searchlib (struct librarynode * lib,
}
/* find start of next module... */
- i = f->data_ofs + f->data_len;
+ 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)
{
@@ -79,9 +191,86 @@ int rdl_searchlib (struct librarynode * lib,
return 0;
}
+int rdl_openmodule (struct librarynode * lib, int moduleno, rdffile * f)
+{
+ char buf[512];
+ int i, cmod, t;
+ long 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)
{
- fprintf(stderr,"%s:%s:%s\n",apname,filename,rdl_errors[rdl_error]);
+ 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
index 94592ce2..28c6ee73 100644
--- a/rdoff/rdlib.h
+++ b/rdoff/rdlib.h
@@ -11,8 +11,17 @@ struct librarynode {
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);
diff --git a/rdoff/rdoff.c b/rdoff/rdoff.c
index 96620ecc..7f4937ac 100644
--- a/rdoff/rdoff.c
+++ b/rdoff/rdoff.c
@@ -4,11 +4,19 @@
* Julian Hall. All rights reserved. The software is
* redistributable under the licence given in the file "Licence"
* distributed in the NASM archive.
+ *
+ * Permission to use this file in your own projects is granted, as long
+ * as acknowledgement is given in an appropriate manner to its authors,
+ * with instructions of how to obtain a copy via ftp.
*/
/* TODO: The functions in this module assume they are running
* on a little-endian machine. This should be fixed to
* make it portable.
+ *
+ * This module no longer supports RDOFF1. If anybody *really*
+ * needs the functionality of supporting both types at the
+ * same time, I'll add it back in.
*/
#include <stdio.h>
@@ -22,115 +30,146 @@
#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 long it is).
* ======================================================================== */
-memorybuffer * newmembuf(){
- memorybuffer * t;
+memorybuffer * newmembuf()
+{
+ memorybuffer * t;
- t = malloc(sizeof(memorybuffer));
+ t = malloc(sizeof(memorybuffer));
- t->length = 0;
- t->next = NULL;
- return t;
+ t->length = 0;
+ t->next = NULL;
+ return t;
}
-void membufwrite(memorybuffer *b, void *data, int bytes) {
- int16 w;
- long l;
-
- if (b->next) { /* memory buffer full - use next buffer */
- membufwrite(b->next,data,bytes);
- return;
- }
- if ((bytes < 0 && b->length - bytes > BUF_BLOCK_LEN)
- || (bytes > 0 && b->length + bytes > BUF_BLOCK_LEN)) {
-
- /* buffer full and no next allocated... allocate and initialise next
- * buffer */
+void membufwrite(memorybuffer *b, void *data, int bytes)
+{
+ int16 w;
+ long l;
- b->next = newmembuf();
- membufwrite(b->next,data,bytes);
- }
+ if (b->next) { /* memory buffer full - use next buffer */
+ membufwrite(b->next,data,bytes);
+ return;
+ }
- switch(bytes) {
- case -4: /* convert to little-endian */
- l = * (long *) data ;
- b->buffer[b->length++] = l & 0xFF;
- l >>= 8 ;
- b->buffer[b->length++] = l & 0xFF;
- l >>= 8 ;
- b->buffer[b->length++] = l & 0xFF;
- l >>= 8 ;
- b->buffer[b->length++] = l & 0xFF;
- break;
+ 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;
+ }
- case -2:
- w = * (int16 *) data ;
- b->buffer[b->length++] = w & 0xFF;
- w >>= 8 ;
- b->buffer[b->length++] = w & 0xFF;
- break;
+ switch(bytes) {
+ case -4: /* convert to little-endian */
+ l = * (long *) data ;
+ b->buffer[b->length++] = l & 0xFF;
+ l >>= 8 ;
+ b->buffer[b->length++] = l & 0xFF;
+ l >>= 8 ;
+ b->buffer[b->length++] = l & 0xFF;
+ l >>= 8 ;
+ b->buffer[b->length++] = l & 0xFF;
+ break;
- default:
- while(bytes--) {
- b->buffer[b->length++] = *(* (unsigned char **) &data);
+ case -2:
+ w = * (int16 *) data ;
+ b->buffer[b->length++] = w & 0xFF;
+ w >>= 8 ;
+ b->buffer[b->length++] = w & 0xFF;
+ break;
- (* (unsigned char **) &data)++ ;
+ default:
+ while(bytes--) {
+ b->buffer[b->length++] = *(* (unsigned char **) &data);
+
+ (* (unsigned char **) &data)++ ;
+ }
+ break;
}
- break;
- }
}
void membufdump(memorybuffer *b,FILE *fp)
{
- if (!b) return;
+ if (!b) return;
- fwrite (b->buffer, 1, b->length, fp);
+ fwrite (b->buffer, 1, b->length, fp);
- membufdump(b->next,fp);
+ membufdump(b->next,fp);
}
int membuflength(memorybuffer *b)
{
- if (!b) return 0;
- return b->length + membuflength(b->next);
+ if (!b) return 0;
+ return b->length + membuflength(b->next);
}
void freemembuf(memorybuffer *b)
{
- if (!b) return;
- freemembuf(b->next);
- free(b);
+ if (!b) return;
+ freemembuf(b->next);
+ free(b);
}
/* =========================================================================
General purpose routines and variables used by the library functions
========================================================================= */
-long translatelong(long in) { /* translate from little endian to
- local representation */
- long r;
- unsigned char *i;
+/*
+ * translatelong() and translateshort()
+ *
+ * translate from little endian to local representation
+ */
+long translatelong(long in)
+{
+ long r;
+ unsigned char *i;
- i = (unsigned char *)&in;
- r = i[3];
- r = (r << 8) + i[2];
- r = (r << 8) + i[1];
- r = (r << 8) + *i;
+ i = (unsigned char *)&in;
+ r = i[3];
+ r = (r << 8) + i[2];
+ r = (r << 8) + i[1];
+ r = (r << 8) + *i;
- return r;
+ return r;
}
-const char *RDOFFId = "RDOFF1"; /* written to the start of RDOFF files */
+int16 translateshort(int16 in)
+{
+ int16 r;
+ unsigned char * i;
+
+ i = (unsigned char *)&in;
+ r = (i[1] << 8) + i[0];
+
+ return r;
+}
+
+const char *RDOFFId = "RDOFF2"; /* written to the start of RDOFF files */
-const char *rdf_errors[7] = {
+const char *rdf_errors[11] = {
"no error occurred","could not open file","invalid file format",
"error reading file","unknown error","header not read",
- "out of memory"};
+ "out of memory", "RDOFF v1 not supported",
+ "unknown extended header record",
+ "header record of known type but unknown length",
+ "no such segment"};
int rdf_errno = 0;
@@ -145,13 +184,15 @@ int rdfopen(rdffile *f, const char *name)
fp = fopen(name,"rb");
if (!fp) return rdf_errno = 1; /* error 1: file open error */
- return rdfopenhere(f,fp,NULL,"");
+ return rdfopenhere(f,fp,NULL,name);
}
-int rdfopenhere(rdffile *f, FILE *fp, int *refcount, char *name)
+int rdfopenhere(rdffile *f, FILE *fp, int *refcount, const char *name)
{
char buf[8];
long initpos;
+ long l;
+ int16 s;
if (translatelong(0x01020304) != 0x01020304)
{ /* fix this to be portable! */
@@ -168,38 +209,61 @@ int rdfopenhere(rdffile *f, FILE *fp, int *refcount, char *name)
if (strcmp(buf,RDOFFId)) {
fclose(f->fp);
+ if (!strcmp(buf,"RDOFF1"))
+ return rdf_errno = 7; /* error 7: RDOFF 1 not supported */
return rdf_errno = 2; /* error 2: invalid file format */
}
- if (fread(&f->header_len,1,4,f->fp) != 4) {
+ if (fread(&l,1,4,f->fp) != 4 ||
+ fread(&f->header_len,1,4,f->fp) != 4) {
fclose(f->fp);
return rdf_errno = 3; /* error 3: file read error */
}
f->header_ofs = ftell(f->fp);
+ f->eof_offset = f->header_ofs + translatelong(l) - 4;
if (fseek(f->fp,f->header_len,SEEK_CUR)) {
fclose(f->fp);
return rdf_errno = 2; /* seek past end of file...? */
}
- if (fread(&f->code_len,1,4,f->fp) != 4) {
- fclose(f->fp);
- return rdf_errno = 3;
+ if (fread(&s,1,2,f->fp) != 2) {
+ fclose(f->fp);
+ return rdf_errno = 3;
}
- f->code_ofs = ftell(f->fp);
- if (fseek(f->fp,f->code_len,SEEK_CUR)) {
- fclose(f->fp);
- return rdf_errno = 2;
- }
+ f->nsegs = 0;
- if (fread(&f->data_len,1,4,f->fp) != 4) {
- fclose(f->fp);
- return rdf_errno = 3;
+ 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 = 3;
+ }
+
+ 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 = 2;
+ }
+ f->nsegs++;
+
+ if (fread(&s,1,2,f->fp) != 2) {
+ fclose(f->fp);
+ return rdf_errno = 3;
+ }
}
- f->data_ofs = ftell(f->fp);
+ if (f->eof_offset != ftell(f->fp) + 8) /* +8 = skip null segment header */
+ {
+ fprintf(stderr, "warning: eof_offset [%ld] 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;
@@ -211,7 +275,7 @@ int rdfopenhere(rdffile *f, FILE *fp, int *refcount, char *name)
int rdfclose(rdffile *f)
{
- if (! f->refcount || ! *--f->refcount)
+ if (! f->refcount || ! --(*f->refcount))
fclose(f->fp);
free(f->name);
@@ -228,6 +292,14 @@ void rdfperror(const char *app,const char *name)
}
+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;
+}
+
int rdfloadseg(rdffile *f,int segment,void *buffer)
{
long fpos;
@@ -235,22 +307,20 @@ int rdfloadseg(rdffile *f,int segment,void *buffer)
switch(segment) {
case RDOFF_HEADER:
- fpos = f->header_ofs;
- slen = f->header_len;
- f->header_loc = (char *)buffer;
- f->header_fp = 0;
- break;
- case RDOFF_CODE:
- fpos = f->code_ofs;
- slen = f->code_len;
- break;
- case RDOFF_DATA:
- fpos = f->data_ofs;
- slen = f->data_len;
- break;
+ fpos = f->header_ofs;
+ slen = f->header_len;
+ f->header_loc = (byte *)buffer;
+ f->header_fp = 0;
+ break;
default:
- fpos = 0;
- slen = 0;
+ if (segment < f->nsegs) {
+ fpos = f->seg[segment].offset;
+ slen = f->seg[segment].length;
+ f->seg[segment].data = (byte *)buffer;
+ }
+ else {
+ return rdf_errno = 10; /* no such segment */
+ }
}
if (fseek(f->fp,fpos,SEEK_SET))
@@ -291,8 +361,15 @@ rdfheaderrec *rdfgetheaderrec(rdffile *f)
if (f->header_fp >= f->header_len) return 0;
RI8(r.type);
+ RI8(r.g.reclen);
+
switch(r.type) {
case 1: /* Relocation record */
+ case 6:
+ if (r.r.reclen != 8) {
+ rdf_errno = 9;
+ return NULL;
+ }
RI8(r.r.segment);
RI32(r.r.offset);
RI8(r.r.length);
@@ -300,6 +377,7 @@ rdfheaderrec *rdfgetheaderrec(rdffile *f)
break;
case 2: /* Imported symbol record */
+ case 7:
RI16(r.i.segment);
RS(r.i.label,32);
break;
@@ -315,12 +393,21 @@ rdfheaderrec *rdfgetheaderrec(rdffile *f)
break;
case 5: /* BSS reservation record */
+ if (r.r.reclen != 4) {
+ rdf_errno = 9;
+ return NULL;
+ }
RI32(r.b.amount);
break;
default:
- rdf_errno = 2; /* invalid file */
+#ifdef STRICT_ERRORS
+ rdf_errno = 8; /* unknown header record */
return NULL;
+#else
+ for (i = 0; i < r.g.reclen; i++)
+ RI8(r.g.data[i]);
+#endif
}
return &r;
}
@@ -333,65 +420,92 @@ void rdfheaderrewind(rdffile *f)
rdf_headerbuf * rdfnewheader(void)
{
- return newmembuf();
+ rdf_headerbuf * hb = malloc(sizeof(hb));
+ 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 1:
- membufwrite(h,&r->type,1);
- membufwrite(h,&r->r.segment,1);
- membufwrite(h,&r->r.offset,-4);
- membufwrite(h,&r->r.length,1);
- membufwrite(h,&r->r.refseg,-2); /* 9 bytes written */
+ case 6:
+ 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 2: /* import */
- membufwrite(h,&r->type,1);
- membufwrite(h,&r->i.segment,-2);
- membufwrite(h,&r->i.label,strlen(r->i.label) + 1);
+ case 7:
+ membufwrite(h->buf,&r->i.segment,-2);
+ membufwrite(h->buf,&r->i.label,strlen(r->i.label) + 1);
break ;
case 3: /* export */
- membufwrite(h,&r->type,1);
- membufwrite(h,&r->e.segment,1);
- membufwrite(h,&r->e.offset,-4);
- membufwrite(h,&r->e.label,strlen(r->e.label) + 1);
+ 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 4: /* DLL */
- membufwrite(h,&r->type,1);
- membufwrite(h,&r->d.libname,strlen(r->d.libname) + 1);
+ membufwrite(h->buf,&r->d.libname,strlen(r->d.libname) + 1);
break ;
case 5: /* BSS */
- membufwrite(h,&r->type,1);
- membufwrite(h,&r->b.amount,-4);
+ membufwrite(h->buf,&r->b.amount,-4);
break ;
default:
- return (rdf_errno = 2);
+#ifdef STRICT_ERRORS
+ return (rdf_errno = 8);
+#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, long seglength)
+{
+ h->nsegments ++;
+ h->seglength += seglength;
+ return 0;
+}
+
int rdfwriteheader(FILE * fp, rdf_headerbuf * h)
{
- long l;
+ long l, l2;
fwrite (RDOFFId, 1, strlen(RDOFFId), fp) ;
- l = translatelong ( membuflength (h) );
- fwrite (&l, 4, 1, fp);
+ l = membuflength (h->buf);
+ l2 = l + 14 + 10*h->nsegments + h->seglength;
+ l = translatelong(l);
+ l2 = translatelong(l2);
+ fwrite (&l2, 4, 1, fp); /* object length */
+ fwrite (&l, 4, 1, fp); /* header length */
- membufdump(h, fp);
+ membufdump(h->buf, fp);
return 0; /* no error handling in here... CHANGE THIS! */
}
void rdfdoneheader(rdf_headerbuf * h)
{
- freemembuf(h);
+ freemembuf(h->buf);
+ free(h);
}
diff --git a/rdoff/rdoff.h b/rdoff/rdoff.h
index 0f74b80a..e23ffa40 100644
--- a/rdoff/rdoff.h
+++ b/rdoff/rdoff.h
@@ -4,28 +4,39 @@
* Julian Hall. All rights reserved. The software is
* redistributable under the licence given in the file "Licence"
* distributed in the NASM archive.
+ *
+ * Permission to use this file in your own projects is granted, as long
+ * as acknowledgement is given in an appropriate manner to its authors,
+ * with instructions of how to obtain a copy via ftp.
*/
#ifndef _RDOFF_H
-#define _RDOFF_H "RDOFF1 support routines v0.1"
+#define _RDOFF_H "RDOFF2 support routines v0.3"
+
+/* Some systems don't define this automatically */
+extern char *strdup(const char *);
-typedef short int16; /* not sure if this will be required to be altered
- at all... best to typedef it just in case */
+typedef unsigned short int16;
+typedef unsigned char byte;
+
+#define RDF_MAXSEGS 64
/* the records that can be found in the RDOFF header */
struct RelocRec {
- char type; /* must be 1 */
- char segment; /* only 0 for code, or 1 for data supported,
+ byte type; /* must be 1 */
+ byte reclen; /* content length */
+ byte segment; /* only 0 for code, or 1 for data supported,
but add 64 for relative refs (ie do not require
reloc @ loadtime, only linkage) */
long offset; /* from start of segment in which reference is loc'd */
- char length; /* 1 2 or 4 bytes */
+ byte length; /* 1 2 or 4 bytes */
int16 refseg; /* segment to which reference refers to */
};
struct ImportRec {
- char type; /* must be 2 */
+ byte type; /* must be 2 */
+ byte reclen; /* content length */
int16 segment; /* segment number allocated to the label for reloc
records - label is assumed to be at offset zero
in this segment, so linker must fix up with offset
@@ -35,42 +46,71 @@ struct ImportRec {
};
struct ExportRec {
- char type; /* must be 3 */
- char segment; /* segment referred to (0/1) */
+ byte type; /* must be 3 */
+ byte reclen; /* content length */
+ byte segment; /* segment referred to (0/1) */
long offset; /* offset within segment */
char label[33]; /* zero terminated as above. max len = 32 chars */
};
struct DLLRec {
- char type; /* must be 4 */
+ byte type; /* must be 4 */
+ byte reclen; /* content length */
char libname[128]; /* name of library to link with at load time */
};
struct BSSRec {
- char type; /* must be 5 */
+ byte type; /* must be 5 */
+ byte reclen; /* content length */
long amount; /* number of bytes BSS to reserve */
};
-
+
+/* GenericRec - contains the type and length field, plus a 128 byte
+ char array 'data', which will probably never be used! */
+
+struct GenericRec {
+ byte type;
+ byte reclen;
+ char data[128];
+};
+
typedef union RDFHeaderRec {
char type; /* invariant throughout all below */
- struct RelocRec r; /* type == 1 */
- struct ImportRec i; /* type == 2 */
+ struct GenericRec g;
+ struct RelocRec r; /* type == 1 / 6 */
+ struct ImportRec i; /* type == 2 / 7 */
struct ExportRec e; /* type == 3 */
struct DLLRec d; /* type == 4 */
struct BSSRec b; /* type == 5 */
} rdfheaderrec;
+struct SegmentHeaderRec {
+ /* information from file */
+ int16 type;
+ int16 number;
+ int16 reserved;
+ long length;
+
+ /* information built up here */
+ long offset;
+ byte *data; /* pointer to segment data if it exists in memory */
+};
+
typedef struct RDFFileInfo {
FILE *fp; /* file descriptor; must be open to use this struct */
int rdoff_ver; /* should be 1; any higher => not guaranteed to work */
long header_len;
- long code_len;
- long data_len;
long header_ofs;
- long code_ofs;
- long data_ofs;
- char *header_loc; /* keep location of header */
+
+ byte *header_loc; /* keep location of header */
long header_fp; /* current location within header for reading */
+
+ struct SegmentHeaderRec seg[RDF_MAXSEGS];
+ int nsegs;
+
+ long eof_offset; /* offset of the first byte beyond the end of this
+ module */
+
char *name; /* name of module in libraries */
int *refcount; /* pointer to reference count on file, or NULL */
} rdffile;
@@ -79,11 +119,15 @@ typedef struct RDFFileInfo {
* on 80x86 machines for efficiency */
typedef struct memorybuffer {
int length;
- char buffer[BUF_BLOCK_LEN];
+ byte buffer[BUF_BLOCK_LEN];
struct memorybuffer *next;
} memorybuffer;
-typedef memorybuffer rdf_headerbuf;
+typedef struct {
+ memorybuffer * buf; /* buffer containing header records */
+ int nsegments; /* number of segments to be written */
+ long seglength; /* total length of all the segments */
+} rdf_headerbuf;
/* segments used by RDOFF, understood by rdoffloadseg */
#define RDOFF_CODE 0
@@ -96,10 +140,15 @@ typedef memorybuffer rdf_headerbuf;
extern int rdf_errno;
+/* utility functions */
+int16 translateshort(int16 in);
+long translatelong(long in);
+
/* RDOFF file manipulation functions */
int rdfopen(rdffile *f,const char *name);
-int rdfopenhere(rdffile *f, FILE *fp, int *refcount, 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 */
@@ -107,11 +156,14 @@ void rdfperror(const char *app,const char *name);
/* functions to write a new RDOFF header to a file -
use rdfnewheader to allocate a header, rdfaddheader to add records to it,
- rdfwriteheader to write 'RDOFF1', length of header, and the header itself
+ rdfaddsegment to notify the header routines that a segment exists, and
+ to tell it how long the segment will be.
+ rdfwriteheader to write the file id, object length, and header
to a file, and then rdfdoneheader to dispose of the header */
rdf_headerbuf *rdfnewheader(void);
int rdfaddheader(rdf_headerbuf *h,rdfheaderrec *r);
+int rdfaddsegment(rdf_headerbuf *h, long seglength);
int rdfwriteheader(FILE *fp,rdf_headerbuf *h);
void rdfdoneheader(rdf_headerbuf *h);
diff --git a/rdoff/rdx.c b/rdoff/rdx.c
index 28ffc427..5a3058db 100644
--- a/rdoff/rdx.c
+++ b/rdoff/rdx.c
@@ -29,7 +29,7 @@ int main(int argc, char **argv)
if (argc < 2)
{
- puts("usage: rdf <rdoff-executable> [params]\n");
+ puts("usage: rdx <rdoff-executable> [params]\n");
exit(255);
}
@@ -37,7 +37,7 @@ int main(int argc, char **argv)
if (! m)
{
- rdfperror("rdf",argv[1]);
+ rdfperror("rdx",argv[1]);
exit(255);
}
diff --git a/rdoff/segtab.c b/rdoff/segtab.c
new file mode 100644
index 00000000..f3168fc0
--- /dev/null
+++ b/rdoff/segtab.c
@@ -0,0 +1,142 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include "segtab.h"
+
+struct segtabnode {
+ int localseg;
+ int destseg;
+ long 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, long 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, long offset)
+{
+ descend_tree_add((struct segtabnode **) root, localseg, destseg, offset);
+}
+
+int get_seglocation(segtab * root, int localseg, int * destseg, long * 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 00000000..b5d96fa1
--- /dev/null
+++ b/rdoff/segtab.h
@@ -0,0 +1,7 @@
+typedef void * segtab;
+
+void init_seglocations(segtab * r);
+void add_seglocation(segtab * r, int localseg, int destseg, long offset);
+int get_seglocation(segtab * r, int localseg, int * destseg, long * offset);
+void done_seglocations(segtab * r);
+
diff --git a/rdoff/symtab.c b/rdoff/symtab.c
index 3fc363e3..4959a5d4 100644
--- a/rdoff/symtab.c
+++ b/rdoff/symtab.c
@@ -1,4 +1,6 @@
-/* symtab.c Routines to maintain and manipulate a symbol table
+/* symtab.c Routines to maintain and manipulate a symbol table
+ *
+ * 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
@@ -7,74 +9,117 @@
*/
#include <stdio.h>
#include <stdlib.h>
+#include <malloc.h>
#include "symtab.h"
+#include "hash.h"
-/* TODO: Implement a hash table, not this stupid implementation which
- is too slow to be of practical use */
+#define SYMTABSIZE 64
+#define slotnum(x) (hash((x)) % SYMTABSIZE)
+/* ------------------------------------- */
/* Private data types */
-typedef struct tagSymtab {
- symtabEnt ent;
- struct tagSymtab * next;
-} symtabList;
+typedef struct tagSymtabNode {
+ struct tagSymtabNode * next;
+ symtabEnt ent;
+} symtabNode;
+
+typedef symtabNode *(symtabTab[SYMTABSIZE]);
-typedef symtabList * _symtab;
+typedef symtabTab *symtab;
-void *symtabNew(void)
+/* ------------------------------------- */
+void *
+symtabNew(void)
{
- void *p = malloc(sizeof(_symtab));
- if (p == NULL) {
+ symtab mytab;
+
+ mytab = (symtabTab *) calloc(SYMTABSIZE ,sizeof(symtabNode *));
+ if (mytab == NULL) {
fprintf(stderr,"symtab: out of memory\n");
exit(3);
}
- *(_symtab *)p = NULL;
- return p;
+ return mytab;
}
-void symtabDone(void *symtab)
+/* ------------------------------------- */
+void
+symtabDone(void *stab)
{
- /* DO SOMETHING HERE! */
+ 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 *symtab,symtabEnt *ent)
+/* ------------------------------------- */
+void
+symtabInsert(void *stab, symtabEnt *ent)
{
- symtabList *l = malloc(sizeof(symtabList));
+ symtab mytab = (symtab) stab;
+ symtabNode *node;
+ int slot;
- if (l == NULL) {
+ node = malloc(sizeof(symtabNode));
+ if (node == NULL) {
fprintf(stderr,"symtab: out of memory\n");
exit(3);
}
- l->ent = *ent;
- l->next = *(_symtab *)symtab;
- *(_symtab *)symtab = l;
+ slot = slotnum(ent->name);
+
+ node->ent = *ent;
+ node->next = (*mytab)[slot];
+ (*mytab)[slot] = node;
}
-symtabEnt *symtabFind(void *symtab,char *name)
+/* ------------------------------------- */
+symtabEnt *
+symtabFind(void *stab, const char *name)
{
- symtabList *l = *(_symtab *)symtab;
-
- while (l) {
- if (!strcmp(l->ent.name,name)) {
- return &(l->ent);
- }
- l = l->next;
- }
- return NULL;
+ 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 *symtab,FILE *of)
+/* ------------------------------------- */
+void
+symtabDump(void *stab, FILE* of)
{
- symtabList *l = *(_symtab *)symtab;
-
- while(l) {
- fprintf(of,"%32s %s:%08lx (%ld)\n",l->ent.name,
- l->ent.segment ? "data" : "code" ,
- l->ent.offset, l->ent.flags);
- l = l->next;
- }
+ symtab mytab = (symtab)stab;
+ int i;
+
+ 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) {
+ fprintf(of, "%-32s %s:%08lx (%ld)\n",l->ent.name,
+ l->ent.segment ? "data" : "code" ,
+ 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
index 5780d447..c1fe0315 100644
--- a/rdoff/symtab.h
+++ b/rdoff/symtab.h
@@ -8,7 +8,7 @@
typedef struct {
char *name;
- long segment;
+ int segment;
long offset;
long flags;
} symtabEnt;
@@ -16,7 +16,7 @@ typedef struct {
void *symtabNew(void);
void symtabDone(void *symtab);
void symtabInsert(void *symtab,symtabEnt *ent);
-symtabEnt *symtabFind(void *symtab,char *name);
+symtabEnt *symtabFind(void *symtab,const char *name);
void symtabDump(void *symtab,FILE *of);
diff --git a/rdoff/test/rdfseg.asm b/rdoff/test/rdfseg.asm
new file mode 100644
index 00000000..4c6f587b
--- /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 00000000..2b9e4fd0
--- /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/v1/README b/rdoff/v1/README
new file mode 100644
index 00000000..56ad81b5
--- /dev/null
+++ b/rdoff/v1/README
@@ -0,0 +1,5 @@
+This directory contains programs for working with RDOFF version 1 object
+files. RDOFF version 1 is no longer supported - you should now be using
+RDOFF2. If you are working with your own code, the changes you will need
+to make are very simple, and are outlined in the document Changes in the
+nasm/rdoff directory.
diff --git a/rdoff/v1/collectn.c b/rdoff/v1/collectn.c
new file mode 100644
index 00000000..c265c95f
--- /dev/null
+++ b/rdoff/v1/collectn.c
@@ -0,0 +1,40 @@
+/* collectn.c Implements variable length pointer arrays [collections]
+ *
+ * This file is public domain.
+ */
+
+#include "collectn.h"
+#include <stdlib.h>
+
+void collection_init(Collection * c)
+{
+ int i;
+
+ for (i = 0; i < 32; i++) c->p[i] = NULL;
+ c->next = NULL;
+}
+
+void ** colln(Collection * c, int index)
+{
+ while (index >= 32) {
+ index -= 32;
+ if (c->next == NULL) {
+ c->next = malloc(sizeof(Collection));
+ collection_init(c->next);
+ }
+ c = c->next;
+ }
+ return &(c->p[index]);
+}
+
+void collection_reset(Collection *c)
+{
+ int i;
+ if (c->next) {
+ collection_reset(c->next);
+ free(c->next);
+ }
+
+ c->next = NULL;
+ for (i = 0; i < 32; i++) c->p[i] = NULL;
+}
diff --git a/rdoff/v1/collectn.h b/rdoff/v1/collectn.h
new file mode 100644
index 00000000..2dc786eb
--- /dev/null
+++ b/rdoff/v1/collectn.h
@@ -0,0 +1,22 @@
+/* collectn.h Header file for 'collection' abstract data type
+ *
+ * This file is public domain, and does not come under the NASM license.
+ * It, along with 'collectn.c' implements what is basically a variable
+ * length array (of pointers)
+ */
+
+#ifndef _COLLECTN_H
+#define _COLLECTN_H
+
+typedef struct tagCollection {
+ void *p[32]; /* array of pointers to objects */
+
+ struct tagCollection *next;
+} Collection;
+
+void collection_init(Collection * c);
+void ** colln(Collection * c, int index);
+void collection_reset(Collection * c);
+
+#endif
+
diff --git a/rdoff/v1/ldrdf.c b/rdoff/v1/ldrdf.c
new file mode 100644
index 00000000..9e4a215d
--- /dev/null
+++ b/rdoff/v1/ldrdf.c
@@ -0,0 +1,728 @@
+/* ldrdf.c RDOFF Object File linker/loader main program
+ *
+ * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
+ * Julian Hall. All rights reserved. The software is
+ * redistributable under the licence given in the file "Licence"
+ * distributed in the NASM archive.
+ */
+
+/* TODO: Make the system skip a module (other than the first) if none
+ * of the other specified modules contain a reference to it.
+ * May require the system to make an extra pass of the modules to be
+ * loaded eliminating those that aren't required.
+ *
+ * Support all the existing documented options...
+ *
+ * Support libaries (.a files - requires a 'ranlib' type utility)
+ * (I think I've got this working, so I've upped the version)
+ *
+ * -s option to strip resolved symbols from exports. (Could make this an
+ * external utility)
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "rdoff.h"
+#include "nasmlib.h"
+#include "symtab.h"
+#include "collectn.h"
+#include "rdlib.h"
+
+#define LDRDF_VERSION "0.30"
+
+/* global variables - those to set options: */
+
+int verbose = 0; /* reflects setting of command line switch */
+int align = 16;
+int errors = 0; /* set by functions to cause halt after current
+ stage of processing */
+
+/* the linked list of modules that must be loaded & linked */
+
+struct modulenode {
+ rdffile f; /* the file */
+ long coderel; /* module's code relocation factor */
+ long datarel; /* module's data relocation factor */
+ long bssrel; /* module's bss data reloc. factor */
+ void * header; /* header location, if loaded */
+ char * name; /* filename */
+ struct modulenode *next;
+};
+
+#define newstr(str) strcpy(malloc(strlen(str) + 1),str)
+#define newstrcat(s1,s2) strcat(strcpy(malloc(strlen(s1)+strlen(s2)+1),s1),s2)
+
+
+struct modulenode *modules = NULL,*lastmodule = NULL;
+
+/* the linked list of libraries to be searched for missing imported
+ symbols */
+
+struct librarynode * libraries = NULL, * lastlib = NULL;
+
+void *symtab; /* The symbol table */
+
+rdf_headerbuf * newheader ; /* New header to be written to output */
+
+/* loadmodule - find the characteristics of a module and add it to the
+ * list of those being linked together */
+
+void loadmodule(char *filename)
+{
+ struct modulenode *prev;
+ if (! modules) {
+ modules = malloc(sizeof(struct modulenode));
+ lastmodule = modules;
+ prev = NULL;
+ }
+ else {
+ lastmodule->next = malloc(sizeof(struct modulenode));
+ prev = lastmodule;
+ lastmodule = lastmodule->next;
+ }
+
+ if (! lastmodule) {
+ fputs("ldrdf: not enough memory\n",stderr);
+ exit(1);
+ }
+
+ if (rdfopen(&lastmodule->f,filename)) {
+ rdfperror("ldrdf",filename);
+ exit(1);
+ }
+
+ lastmodule->header = NULL; /* header hasn't been loaded */
+ lastmodule->name = filename;
+ lastmodule->next = NULL;
+
+ if (prev) {
+ lastmodule->coderel = prev->coderel + prev->f.code_len;
+ if (lastmodule->coderel % align != 0)
+ lastmodule->coderel += align - (lastmodule->coderel % align);
+ lastmodule->datarel = prev->datarel + prev->f.data_len;
+ if (lastmodule->datarel % align != 0)
+ lastmodule->datarel += align - (lastmodule->datarel % align);
+ }
+ else {
+ lastmodule->coderel = 0;
+ lastmodule->datarel = 0;
+ }
+
+ if (verbose)
+ printf("%s code = %08lx (+%04lx), data = %08lx (+%04lx)\n",filename,
+ lastmodule->coderel,lastmodule->f.code_len,
+ lastmodule->datarel,lastmodule->f.data_len);
+
+ lastmodule->header = malloc(lastmodule->f.header_len);
+ if (!lastmodule->header) {
+ fprintf(stderr,"ldrdf: out of memory\n");
+ exit(1);
+ }
+
+ if (rdfloadseg(&lastmodule->f,RDOFF_HEADER,lastmodule->header))
+ {
+ rdfperror("ldrdf",filename);
+ exit(1);
+ }
+}
+
+/* load_library add a library to list of libraries to search
+ * for undefined symbols
+ */
+
+void load_library(char * name)
+{
+ if (verbose)
+ printf("adding library %s to search path\n",name);
+
+ if (! lastlib) {
+ lastlib = libraries = malloc(sizeof(struct librarynode));
+ }
+ else
+ {
+ lastlib->next = malloc(sizeof(struct librarynode));
+ lastlib = lastlib->next;
+ }
+
+ if (! lastlib) {
+ fprintf(stderr, "ldrdf: out of memory\n");
+ exit(1);
+ }
+ strcpy (lastlib->name = malloc (1+strlen(name)), name);
+ lastlib->fp = NULL;
+ lastlib->referenced = 0;
+ lastlib->next = NULL;
+}
+
+
+/* build_symbols() step through each module's header, and locate
+ * exported symbols, placing them in a global table
+ */
+
+long bsslength;
+
+void mod_addsymbols(struct modulenode * mod)
+{
+ rdfheaderrec *r;
+ symtabEnt e;
+ long cbBss;
+
+ mod->bssrel = bsslength;
+ cbBss = 0;
+ rdfheaderrewind(&mod->f);
+ while ((r = rdfgetheaderrec(&mod->f)))
+ {
+
+ if (r->type == 5) /* Allocate BSS */
+ cbBss += r->b.amount;
+
+ if (r->type != 3) continue; /* ignore all but export recs */
+
+ e.segment = r->e.segment;
+ e.offset = r->e.offset +
+ (e.segment == 0 ? mod->coderel : /* 0 -> code */
+ e.segment == 1 ? mod->datarel : /* 1 -> data */
+ mod->bssrel) ; /* 2 -> bss */
+
+ e.flags = 0;
+ e.name = malloc(strlen(r->e.label) + 1);
+ if (! e.name)
+ {
+ fprintf(stderr,"ldrdf: out of memory\n");
+ exit(1);
+ }
+ strcpy(e.name,r->e.label);
+ symtabInsert(symtab,&e);
+ }
+ bsslength += cbBss;
+}
+
+void build_symbols()
+{
+ struct modulenode *mod;
+
+ if (verbose) printf("building global symbol table:\n");
+ newheader = rdfnewheader();
+
+ symtab = symtabNew();
+ bsslength = 0; /* keep track of location of BSS symbols */
+
+ for (mod = modules; mod; mod = mod->next)
+ {
+ mod_addsymbols( mod );
+ }
+ if (verbose)
+ {
+ symtabDump(symtab,stdout);
+ printf("BSS length = %ld bytes\n\n",bsslength);
+ }
+}
+
+
+/* scan_libraries() search through headers of modules for undefined
+ * symbols, and scan libraries for those symbols,
+ * adding library modules found to list of modules
+ * to load. */
+
+void scan_libraries(void)
+{
+ struct modulenode * mod, * nm;
+ struct librarynode * lib;
+ rdfheaderrec * r;
+ int found;
+ char * tmp;
+
+ if (verbose) printf("Scanning libraries for unresolved symbols...\n");
+
+ mod = modules;
+
+ while (mod)
+ {
+ rdfheaderrewind(&mod->f);
+
+ while ((r = rdfgetheaderrec(&mod->f)))
+ {
+ if (r->type != 2) continue; /* not an import record */
+ if ( symtabFind (symtab,r->i.label) )
+ continue; /* symbol already defined */
+
+ /* okay, we have an undefined symbol... step through
+ the libraries now */
+ if (verbose >= 2) {
+ printf("undefined symbol '%s'...",r->i.label);
+ fflush(stdout);
+ }
+
+ lib = libraries;
+ found = 0;
+
+ tmp = newstr(r->i.label);
+ while (! found && lib)
+ {
+ /* move this to an outer loop...! */
+ nm = malloc(sizeof(struct modulenode));
+
+ if (rdl_searchlib(lib,tmp,&nm->f))
+ { /* found a module in the library */
+
+ /* create a modulenode for it */
+
+ if (! nm) {
+ fprintf(stderr,"ldrdf: out of memory\n");
+ exit(1);
+ }
+
+ nm->name = newstrcat(lib->name,nm->f.name);
+ if (verbose >= 2) printf("found in '%s'\n",nm->name);
+
+ nm->coderel = lastmodule->coderel + lastmodule->f.code_len;
+ if (nm->coderel % align != 0)
+ nm->coderel += align - (nm->coderel % align);
+
+ nm->datarel = lastmodule->datarel + lastmodule->f.data_len;
+ if (nm->datarel % align != 0)
+ nm->datarel += align - (nm->datarel % align);
+
+ nm->header = malloc(nm->f.header_len);
+ if (! nm->header)
+ {
+ fprintf(stderr,"ldrdf: out of memory\n");
+ exit(1);
+ }
+
+ if (rdfloadseg(&nm->f,RDOFF_HEADER,nm->header))
+ {
+ rdfperror("ldrdf",nm->name);
+ exit(1);
+ }
+
+ nm->next = NULL;
+ found = 1;
+ lastmodule->next = nm;
+ lastmodule = nm;
+
+ if (verbose)
+ printf("%s code = %08lx (+%04lx), data = %08lx "
+ "(+%04lx)\n",lastmodule->name,
+ lastmodule->coderel,lastmodule->f.code_len,
+ lastmodule->datarel,lastmodule->f.data_len);
+
+ /* add the module's info to the symbol table */
+ mod_addsymbols(nm);
+ }
+ else
+ {
+ if (rdl_error) {
+ rdl_perror("ldrdf",lib->name);
+ exit(1);
+ }
+ free(nm);
+ }
+ lib = lib->next;
+ }
+ free(tmp);
+ if (!found && verbose >= 2) printf("not found\n");
+ }
+ mod = mod->next;
+ }
+}
+
+/* load_segments() allocates memory for & loads the code & data segs
+ * from the RDF modules
+ */
+
+char *text,*data;
+long textlength,datalength;
+
+void load_segments(void)
+{
+ struct modulenode *mod;
+
+ if (!modules) {
+ fprintf(stderr,"ldrdf: nothing to do\n");
+ exit(0);
+ }
+ if (!lastmodule) {
+ fprintf(stderr,"ldrdf: panic: module list exists, but lastmodule=NULL\n");
+ exit(3);
+ }
+
+ if (verbose)
+ printf("loading modules into memory\n");
+
+ /* The following stops 16 bit DOS from crashing whilst attempting to
+ work using segments > 64K */
+ if (sizeof(int) == 2) { /* expect a 'code has no effect' warning on 32 bit
+ platforms... */
+ if (lastmodule->coderel + lastmodule->f.code_len > 65535 ||
+ lastmodule->datarel + lastmodule->f.data_len > 65535) {
+ fprintf(stderr,"ldrdf: segment length has exceeded 64K; use a 32 bit "
+ "version.\nldrdf: code size = %05lx, data size = %05lx\n",
+ lastmodule->coderel + lastmodule->f.code_len,
+ lastmodule->datarel + lastmodule->f.data_len);
+ exit(1);
+ }
+ }
+
+ text = malloc(textlength = lastmodule->coderel + lastmodule->f.code_len);
+ data = malloc(datalength = lastmodule->datarel + lastmodule->f.data_len);
+
+ if (!text || !data) {
+ fprintf(stderr,"ldrdf: out of memory\n");
+ exit(1);
+ }
+
+ mod = modules;
+ while (mod) { /* load the segments for each module */
+ if (verbose >= 2) printf(" loading %s\n",mod->name);
+ if (rdfloadseg(&mod->f,RDOFF_CODE,&text[mod->coderel]) ||
+ rdfloadseg(&mod->f,RDOFF_DATA,&data[mod->datarel])) {
+ rdfperror("ldrdf",mod->name);
+ exit(1);
+ }
+ rdfclose(&mod->f); /* close file; segments remain */
+ mod = mod->next;
+ }
+}
+
+/* link_segments() step through relocation records in each module's
+ * header, fixing up references.
+ */
+
+void link_segments(void)
+{
+ struct modulenode *mod;
+ Collection imports;
+ symtabEnt *s;
+ long rel,relto;
+ char *seg;
+ rdfheaderrec *r;
+ int bRelative;
+
+ if (verbose) printf("linking segments\n");
+
+ collection_init(&imports);
+
+ for (mod = modules; mod; mod = mod->next) {
+ if (verbose >= 2) printf("* processing %s\n",mod->name);
+ rdfheaderrewind(&mod->f);
+ while((r = rdfgetheaderrec(&mod->f))) {
+ if (verbose >= 3) printf("record type: %d\n",r->type);
+ switch(r->type) {
+ case 1: /* relocation record */
+ if (r->r.segment >= 64) { /* Relative relocation; */
+ bRelative = 1; /* need to find location relative */
+ r->r.segment -= 64; /* to start of this segment */
+ relto = r->r.segment == 0 ? mod->coderel : mod->datarel;
+ }
+ else
+ {
+ bRelative = 0; /* non-relative - need to relocate
+ * at load time */
+ relto = 0; /* placate optimiser warnings */
+ }
+
+ /* calculate absolute offset of reference, not rel to beginning of
+ segment */
+ r->r.offset += r->r.segment == 0 ? mod->coderel : mod->datarel;
+
+ /* calculate the relocation factor to apply to the operand -
+ the base address of one of this modules segments if referred
+ segment is 0 - 2, or the address of an imported symbol
+ otherwise. */
+
+ if (r->r.refseg == 0) rel = mod->coderel;
+ else if (r->r.refseg == 1) rel = mod->datarel;
+ else if (r->r.refseg == 2) rel = mod->bssrel;
+ else { /* cross module link - find reference */
+ s = *colln(&imports,r->r.refseg - 2);
+ if (!s) {
+ fprintf(stderr,"ldrdf: link to undefined segment %04x in"
+ " %s:%d\n", r->r.refseg,mod->name,r->r.segment);
+ errors = 1;
+ break;
+ }
+ rel = s->offset;
+
+ r->r.refseg = s->segment; /* change referred segment,
+ so that new header is
+ correct */
+ }
+
+ if (bRelative) /* Relative - subtract current segment start */
+ rel -= relto;
+ else
+ { /* Add new relocation header */
+ rdfaddheader(newheader,r);
+ }
+
+ /* Work out which segment we're making changes to ... */
+ if (r->r.segment == 0) seg = text;
+ else if (r->r.segment == 1) seg = data;
+ else {
+ fprintf(stderr,"ldrdf: relocation in unknown segment %d in "
+ "%s\n", r->r.segment,mod->name);
+ errors = 1;
+ break;
+ }
+
+ /* Add the relocation factor to the datum specified: */
+
+ if (verbose >= 3)
+ printf(" - relocating %d:%08lx by %08lx\n",r->r.segment,
+ r->r.offset,rel);
+
+ /**** The following code is non-portable. Rewrite it... ****/
+ switch(r->r.length) {
+ case 1:
+ seg[r->r.offset] += (char) rel;
+ break;
+ case 2:
+ *(int16 *)(seg + r->r.offset) += (int16) rel;
+ break;
+ case 4:
+ *(long *)(seg + r->r.offset) += rel;
+ break;
+ }
+ break;
+
+ case 2: /* import record */
+ s = symtabFind(symtab, r->i.label);
+ if (s == NULL) {
+ /* Need to add support for dynamic linkage */
+ fprintf(stderr,"ldrdf: undefined symbol %s in module %s\n",
+ r->i.label,mod->name);
+ errors = 1;
+ }
+ else
+ {
+ *colln(&imports,r->i.segment - 2) = s;
+ if (verbose >= 2)
+ printf("imported %s as %04x\n", r->i.label, r->i.segment);
+ }
+ break;
+
+ case 3: /* export; dump to output new version */
+ s = symtabFind(symtab, r->e.label);
+ if (! s) {
+ fprintf(stderr,"ldrdf: internal error - undefined symbol %s "
+ "exported in header of '%s'\n",r->e.label,mod->name);
+ continue;
+ }
+ r->e.offset = s->offset;
+ rdfaddheader(newheader,r);
+ break;
+
+ case 4: /* DLL record */
+ rdfaddheader(newheader,r); /* copy straight to output */
+ break;
+ }
+ }
+ if (rdf_errno != 0) {
+ rdfperror("ldrdf",mod->name);
+ exit(1);
+ }
+ collection_reset(&imports);
+ }
+}
+
+/* write_output() write linked program out to a file */
+
+void write_output(char *filename)
+{
+ FILE * fp;
+ rdfheaderrec r;
+
+ if (verbose) printf("writing output to '%s'\n",filename);
+
+ fp = fopen(filename,"wb");
+ if (! fp)
+ {
+ fprintf(stderr,"ldrdf: could not open '%s' for writing\n",filename);
+ exit(1);
+ }
+
+
+ /* add BSS length count to header... */
+ if (bsslength)
+ {
+ r.type = 5;
+ r.b.amount = bsslength;
+ rdfaddheader(newheader,&r);
+ }
+
+ /* Write header */
+ rdfwriteheader(fp,newheader);
+ rdfdoneheader(newheader);
+ newheader = NULL;
+
+ /* Write text */
+ if (fwrite(&textlength,1,4,fp) != 4
+ || fwrite(text,1,textlength,fp) !=textlength)
+ {
+ fprintf(stderr,"ldrdf: error writing %s\n",filename);
+ exit(1);
+ }
+
+ /* Write data */
+ if (fwrite(&datalength,1,4,fp) != 4 ||
+ fwrite(data,1,datalength,fp) != datalength)
+ {
+ fprintf (stderr,"ldrdf: error writing %s\n", filename);
+ exit(1);
+ }
+ fclose(fp);
+}
+
+
+/* main program: interpret command line, and pass parameters on to
+ * individual module loaders & the linker
+ *
+ * Command line format:
+ * ldrdf [-o outfile | -x] [-r xxxx] [-v] [--] infile [infile ...]
+ *
+ * Default action is to output a file named 'aout.rdx'. -x specifies
+ * that the linked object program should be executed, rather than
+ * written to a file. -r specifies that the object program should
+ * be prelocated at address 'xxxx'. This option cannot be used
+ * in conjunction with -x.
+ */
+
+const char *usagemsg = "usage:\n"
+" ldrdf [-o outfile | -x] [-a x] [-v] [-p x] [--] infile [infile ...]\n"
+" [-l<libname> ...]\n\n"
+" ldrdf -h displays this message\n"
+" ldrdf -r displays version information\n\n"
+" -o selects output filename (default is aout.rdx)\n"
+" -x causes ldrdx to link & execute rather than write to file\n"
+" -a x causes object program to be statically relocated to address 'x'\n"
+" -v turns on verbose mode\n"
+" -p x causes segments to be aligned (padded) to x byte boundaries\n"
+" (default is 16 bytes)\n"
+" -l<name> causes 'name' to be linked in as a library. Note no search is\n"
+" performed - the entire pathname MUST be specified.\n";
+
+void usage(void)
+{
+ fputs(usagemsg,stderr);
+}
+
+int main(int argc,char **argv)
+{
+ char *ofilename = "aout.rdx";
+ long relocateaddr = -1; /* -1 if no relocation is to occur */
+ int execute = 0; /* 1 to execute after linking, 0 otherwise */
+ int procsw = 1; /* set to 0 by '--' */
+ int tmp;
+
+ if (argc == 1) {
+ usage();
+ exit(1);
+ }
+
+ /* process command line switches, and add modules specified to linked list
+ of modules, keeping track of total memory required to load them */
+
+ while(argv++,--argc) {
+ if (procsw && !strcmp(*argv,"-h")) { /* Help command */
+ usage(); exit(1);
+ }
+ else if (procsw && !strcmp(*argv,"-r")) {
+ printf("ldrdf version %s (%s) (%s)\n",LDRDF_VERSION,_RDOFF_H,
+ sizeof(int) == 2 ? "16 bit" : "32 bit");
+ exit(1);
+ }
+ else if (procsw && !strcmp(*argv,"-o")) {
+ ofilename = *++argv;
+ --argc;
+ if (execute) {
+ fprintf(stderr,"ldrdf: -o and -x switches incompatible\n");
+ exit(1);
+ }
+ if (verbose > 1) printf("output filename set to '%s'\n",ofilename);
+ }
+ else if (procsw && !strcmp(*argv,"-x")) {
+ execute++;
+ if (verbose > 1) printf("will execute linked object\n");
+ }
+ else if (procsw && !strcmp(*argv,"-a")) {
+ relocateaddr = readnum(*++argv,&tmp);
+ --argc;
+ if (tmp) {
+ fprintf(stderr,"ldrdf: error in parameter to '-a' switch: '%s'\n",
+ *argv);
+ exit(1);
+ }
+ if (execute) {
+ fprintf(stderr,"ldrdf: -a and -x switches incompatible\n");
+ exit(1);
+ }
+ if (verbose) printf("will relocate to %08lx\n",relocateaddr);
+ }
+ else if (procsw && !strcmp(*argv,"-v")) {
+ verbose++;
+ if (verbose == 1) printf("verbose mode selected\n");
+ }
+ else if (procsw && !strcmp(*argv,"-p")) {
+ align = readnum(*++argv,&tmp);
+ --argc;
+ if (tmp) {
+ fprintf(stderr,"ldrdf: error in parameter to '-p' switch: '%s'\n",
+ *argv);
+ exit(1);
+ }
+ if (align != 1 && align != 2 && align != 4 && align != 8 && align != 16
+ && align != 32 && align != 256) {
+ fprintf(stderr,"ldrdf: %d is an invalid alignment factor - must be"
+ "1,2,4,8,16 or 256\n",align);
+ exit(1);
+ }
+ if (verbose > 1) printf("alignment %d selected\n",align);
+ }
+ else if (procsw && !strncmp(*argv,"-l",2)) {
+ load_library(*argv + 2);
+ }
+ else if (procsw && !strcmp(*argv,"--")) {
+ procsw = 0;
+ }
+ else { /* is a filename */
+ if (verbose > 1) printf("processing module %s\n",*argv);
+ loadmodule(*argv);
+ }
+ }
+
+ /* we should be scanning for unresolved references, and removing
+ unreferenced modules from the list of modules here, so that
+ we know about the final size once libraries have been linked in */
+
+ build_symbols(); /* build a global symbol table... */
+
+ scan_libraries(); /* check for imported symbols not in table,
+ and ensure the relevant library modules
+ are loaded */
+
+ load_segments(); /* having calculated size of reqd segments, load
+ each rdoff module's segments into memory */
+
+ link_segments(); /* step through each module's header, and resolve
+ references to the global symbol table.
+ This also does local address fixups. */
+
+ if (errors) {
+ fprintf(stderr,"ldrdf: there were errors - aborted\n");
+ exit(errors);
+ }
+ if (execute) {
+ fprintf(stderr,"ldrdf: module execution not yet supported\n");
+ exit(1);
+ }
+ if (relocateaddr != -1) {
+ fprintf(stderr,"ldrdf: static relocation not yet supported\n");
+ exit(1);
+ }
+
+ write_output(ofilename);
+ return 0;
+}
diff --git a/rdoff/rdf.doc b/rdoff/v1/rdf.doc
index 300c2bc5..300c2bc5 100644
--- a/rdoff/rdf.doc
+++ b/rdoff/v1/rdf.doc
diff --git a/rdoff/v1/rdf2bin.c b/rdoff/v1/rdf2bin.c
new file mode 100644
index 00000000..97b45b4c
--- /dev/null
+++ b/rdoff/v1/rdf2bin.c
@@ -0,0 +1,125 @@
+/* rdf2bin: convert an RDOFF object file to flat binary */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "rdfload.h"
+#include "rdoff.h"
+#include "nasmlib.h"
+
+long origin = 0;
+int align = 16;
+
+char *getfilename(char * pathname)
+{
+ char * lastslash = pathname - 1;
+ char * i = pathname;
+
+ while ( *i ) {
+ if (*i == '/') lastslash = i;
+ i++;
+ }
+ return lastslash + 1;
+}
+
+int main(int argc, char **argv)
+{
+ rdfmodule * m;
+ int tmp;
+ FILE *of;
+ char * padding;
+ int codepad, datapad;
+
+ if (argc < 2) {
+ puts("Usage: rdf2bin [-o relocation-origin] [-p segment-alignment] "
+ "input-file output-file");
+ puts(" rdf2com [-p segment-alignment] input-file output-file");
+ return 1;
+ }
+
+ if (! nasm_stricmp(getfilename(*argv),"rdf2com")) {
+ origin = 0x100;
+ }
+ argv++, argc--;
+
+ while (argc > 2) {
+ if (! strcmp(*argv,"-o")) {
+ argv++, argc--;
+ origin = readnum(*argv, &tmp);
+ if (tmp) {
+ fprintf(stderr,"rdf2bin: invalid parameter: %s\n",*argv);
+ return 1;
+ }
+ } else if (! strcmp(*argv,"-p")) {
+ argv++, argc--;
+ align = readnum(*argv, &tmp);
+ if (tmp) {
+ fprintf(stderr,"rdf2bin: invalid parameter: %s\n",*argv);
+ return 1;
+ }
+ } else
+ break;
+
+ argv++, argc--;
+ }
+ if (argc < 2) {
+ puts("rdf2bin: required parameter missing");
+ return -1;
+ }
+ m = rdfload(*argv);
+
+ if (! m)
+ {
+ rdfperror("rdf2bin",*argv);
+ return 1;
+ }
+ printf("relocating %s: origin=%lx, align=%d\n",*argv,origin,align);
+
+ m->textrel = origin;
+ m->datarel = origin + m->f.code_len;
+ if (m->datarel % align != 0) {
+ codepad = align - (m->datarel % align);
+ m->datarel += codepad;
+ }
+ else
+ codepad = 0;
+
+ m->bssrel = m->datarel + m->f.data_len;
+ if (m->bssrel % align != 0) {
+ datapad = align - (m->bssrel % align);
+ m->bssrel += datapad;
+ }
+ else
+ datapad = 0;
+
+ printf("code: %08lx\ndata: %08lx\nbss: %08lx\n",
+ m->textrel, m->datarel, m->bssrel);
+
+ rdf_relocate(m);
+
+ argv++;
+
+ of = fopen(*argv,"wb");
+ if (!of) {
+ fprintf(stderr,"rdf2bin: could not open output file %s\n",*argv);
+ return 1;
+ }
+
+ padding = malloc(align);
+ if (!padding) {
+ fprintf(stderr,"rdf2bin: out of memory\n");
+ return 1;
+ }
+
+ if (fwrite(m->t,1,m->f.code_len,of) != m->f.code_len ||
+ fwrite(padding,1,codepad,of) != codepad ||
+ fwrite(m->d,1,m->f.data_len,of) != m->f.data_len)
+ {
+ fprintf(stderr,"rdf2bin: error writing to %s\n", *argv);
+ return 1;
+ }
+
+ fclose(of);
+ return 0;
+}
diff --git a/rdoff/v1/rdfdump.c b/rdoff/v1/rdfdump.c
new file mode 100644
index 00000000..080c2e73
--- /dev/null
+++ b/rdoff/v1/rdfdump.c
@@ -0,0 +1,167 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+FILE *infile;
+
+long translatelong(long in) { /* translate from little endian to
+ local representation */
+ long r;
+ unsigned char *i;
+
+ i = (unsigned char *)&in;
+ r = i[3];
+ r = (r << 8) + i[2];
+ r = (r << 8) + i[1];
+ r = (r << 8) + *i;
+
+ return r;
+}
+
+int translateshort(short in) {
+ int r;
+ unsigned char *i;
+
+ i = (unsigned char *)&in;
+ r = (i[1] << 8) + *i;
+
+ return r;
+}
+void print_header(long length) {
+ char buf[129],t,s,l;
+ long o,ll;
+ short rs;
+
+ while (length > 0) {
+ fread(&t,1,1,infile);
+ switch(t) {
+ case 1: /* relocation record */
+ fread(&s,1,1,infile);
+ fread(&o,4,1,infile);
+ fread(&l,1,1,infile);
+ fread(&rs,2,1,infile);
+ printf(" relocation: location (%04x:%08lx), length %d, "
+ "referred seg %04x\n",(int)s,translatelong(o),(int)l,
+ translateshort(rs));
+ length -= 9;
+ break;
+ case 2: /* import record */
+ fread(&rs,2,1,infile);
+ ll = 0;
+ do {
+ fread(&buf[ll],1,1,infile);
+ } while (buf[ll++]);
+ printf(" import: segment %04x = %s\n",translateshort(rs),buf);
+ length -= ll + 3;
+ break;
+ case 3: /* export record */
+ fread(&s,1,1,infile);
+ fread(&o,4,1,infile);
+ ll = 0;
+ do {
+ fread(&buf[ll],1,1,infile);
+ } while (buf[ll++]);
+ printf(" export: (%04x:%08lx) = %s\n",(int)s,translatelong(o),buf);
+ length -= ll + 6;
+ break;
+ case 4: /* DLL record */
+ ll = 0;
+ do {
+ fread(&buf[ll],1,1,infile);
+ } while (buf[ll++]);
+ printf(" dll: %s\n",buf);
+ length -= ll + 1;
+ break;
+ case 5: /* BSS reservation */
+ fread(&ll,4,1,infile);
+ printf(" bss reservation: %08lx bytes\n",translatelong(ll));
+ length -= 5;
+ break;
+ default:
+ printf(" unrecognised record (type %d)\n",(int)t);
+ length --;
+ }
+ }
+}
+
+int main(int argc,char **argv) {
+ char id[7];
+ long l;
+ int verbose = 0;
+ long offset;
+
+ puts("RDOFF Dump utility v1.1 (C) Copyright 1996 Julian R Hall");
+
+ if (argc < 2) {
+ fputs("Usage: rdfdump [-v] <filename>\n",stderr);
+ exit(1);
+ }
+
+ if (! strcmp (argv[1], "-v") )
+ {
+ verbose = 1;
+ if (argc < 3)
+ {
+ fputs("required parameter missing\n",stderr);
+ exit(1);
+ }
+ argv++;
+ }
+
+ infile = fopen(argv[1],"rb");
+ if (! infile) {
+ fprintf(stderr,"rdfdump: Could not open %s",argv[1]);
+ exit(1);
+ }
+
+ fread(id,6,1,infile);
+ if (strncmp(id,"RDOFF",5)) {
+ fputs("rdfdump: File does not contain valid RDOFF header\n",stderr);
+ exit(1);
+ }
+
+ printf("File %s: RDOFF version %c\n\n",argv[1],id[5]);
+ if (id[5] < '1' || id[5] > '1') {
+ fprintf(stderr,"rdfdump: unknown RDOFF version '%c'\n",id[5]);
+ exit(1);
+ }
+
+ fread(&l,4,1,infile);
+ l = translatelong(l);
+ printf("Header (%ld bytes):\n",l);
+ print_header(l);
+
+ fread(&l,4,1,infile);
+ l = translatelong(l);
+ printf("\nText segment length = %ld bytes\n",l);
+ offset = 0;
+ while(l--) {
+ fread(id,1,1,infile);
+ if (verbose) {
+ if (offset % 16 == 0)
+ printf("\n%08lx ", offset);
+ printf(" %02x",(int) (unsigned char)id[0]);
+ offset++;
+ }
+ }
+ if (verbose) printf("\n\n");
+
+ fread(&l,4,1,infile);
+ l = translatelong(l);
+ printf("Data segment length = %ld bytes\n",l);
+
+ if (verbose)
+ {
+ offset = 0;
+ while (l--) {
+ fread(id,1,1,infile);
+ if (offset % 16 == 0)
+ printf("\n%08lx ", offset);
+ printf(" %02x",(int) (unsigned char) id[0]);
+ offset++;
+ }
+ printf("\n");
+ }
+ fclose(infile);
+ return 0;
+}
diff --git a/rdoff/v1/rdflib.c b/rdoff/v1/rdflib.c
new file mode 100644
index 00000000..58465626
--- /dev/null
+++ b/rdoff/v1/rdflib.c
@@ -0,0 +1,235 @@
+/* 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. There may be an optional
+ directory placed on the end of the file. The format of the
+ directory will be 'RDL' 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. */
+
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+
+/* functions supported:
+ create a library (no extra operands required)
+ add a module from a library (requires filename and name to give mod.)
+ remove 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"
+ " r - remove (module-name)\n"
+ " x - extract (module-name filename)\n"
+ " t - list\n";
+
+char **_argv;
+
+#define _ENDIANNESS 0 /* 0 for little, 1 for big */
+
+static void longtolocal(long * l)
+{
+#if _ENDIANNESS
+ unsigned char t;
+ unsigned char * p = (unsigned char *) l;
+
+ t = p[0];
+ p[0] = p[3];
+ p[3] = t;
+ t = p[1];
+ p[1] = p[2];
+ p[2] = p[1];
+#endif
+}
+
+void copybytes(FILE *fp, FILE *fp2, int n)
+{
+ int i,t;
+
+ for (i = 0 ; i < n; i++ )
+ {
+ t = fgetc(fp);
+ if (t == EOF)
+ {
+ fprintf(stderr,"ldrdf: premature end of file in '%s'\n",
+ _argv[2]);
+ exit(1);
+ }
+ if (fp2)
+ if (fputc(t, fp2) == EOF)
+ {
+ fprintf(stderr,"ldrdf: write error\n");
+ exit(1);
+ }
+ }
+}
+
+long copylong(FILE *fp, FILE *fp2)
+{
+ long l;
+ int i,t;
+ unsigned char * p = (unsigned char *) &l;
+
+
+ for (i = 0 ; i < 4; i++ ) /* skip magic no */
+ {
+ t = fgetc(fp);
+ if (t == EOF)
+ {
+ fprintf(stderr,"ldrdf: premature end of file in '%s'\n",
+ _argv[2]);
+ exit(1);
+ }
+ if (fp2)
+ if (fputc(t, fp2) == EOF)
+ {
+ fprintf(stderr,"ldrdf: write error\n");
+ exit(1);
+ }
+ *p++ = t;
+ }
+ longtolocal (&l);
+ return l;
+}
+
+int main(int argc, char **argv)
+{
+ FILE *fp, *fp2;
+ char *p, buf[256];
+ int i;
+
+ _argv = argv;
+
+ if (argc < 3 || !strncmp(argv[1],"-h",2) || !strncmp(argv[1],"--h",3))
+ {
+ printf(usage);
+ exit(1);
+ }
+
+ switch(argv[1][0])
+ {
+ case 'c': /* create library */
+ fp = fopen(argv[2],"wb");
+ if (! fp) {
+ fprintf(stderr,"ldrdf: could not open '%s'\n",argv[2]);
+ perror("ldrdf");
+ exit(1);
+ }
+ fclose(fp);
+ break;
+
+ case 'a': /* add module */
+ if (argc < 5) {
+ fprintf(stderr,"ldrdf: required parameter missing\n");
+ exit(1);
+ }
+ fp = fopen(argv[2],"ab");
+ if (! fp)
+ {
+ fprintf(stderr,"ldrdf: could not open '%s'\n",argv[2]);
+ perror("ldrdf");
+ exit(1);
+ }
+
+ fp2 = fopen(argv[3],"rb");
+ if (! fp)
+ {
+ fprintf(stderr,"ldrdf: could not open '%s'\n",argv[3]);
+ perror("ldrdf");
+ exit(1);
+ }
+
+ p = argv[4];
+ do {
+ if ( fputc(*p,fp) == EOF ) {
+ fprintf(stderr,"ldrdf: write error\n");
+ exit(1);
+ }
+ } while (*p++);
+
+ while (! feof (fp2) ) {
+ i = fgetc (fp2);
+ if (i == EOF) {
+ break;
+ }
+
+ if ( fputc(i, fp) == EOF ) {
+ fprintf(stderr,"ldrdf: write error\n");
+ exit(1);
+ }
+ }
+ fclose(fp2);
+ fclose(fp);
+ break;
+
+ case 'x':
+ if (argc < 5) {
+ fprintf(stderr,"ldrdf: required parameter missing\n");
+ exit(1);
+ }
+
+ fp = fopen(argv[2],"rb");
+ if (! fp)
+ {
+ fprintf(stderr,"ldrdf: could not open '%s'\n",argv[2]);
+ perror("ldrdf");
+ exit(1);
+ }
+
+ fp2 = NULL;
+ while (! feof(fp) ) {
+ /* read name */
+ p = buf;
+ while( ( *(p++) = (char) fgetc(fp) ) )
+ if (feof(fp)) break;
+
+ if (feof(fp)) break;
+
+ /* check against desired name */
+ if (! strcmp(buf,argv[3]) )
+ {
+ fp2 = fopen(argv[4],"wb");
+ if (! fp2)
+ {
+ fprintf(stderr,"ldrdf: could not open '%s'\n", argv[4]);
+ perror("ldrdf");
+ exit(1);
+ }
+ }
+ else
+ fp2 = NULL;
+
+ /* step over the RDOFF file, copying it if fp2 != NULL */
+ copybytes(fp,fp2,6); /* magic number */
+ copybytes(fp,fp2, copylong(fp,fp2)); /* header */
+ copybytes(fp,fp2, copylong(fp,fp2)); /* text */
+ copybytes(fp,fp2, copylong(fp,fp2)); /* data */
+
+ if (fp2)
+ break;
+ }
+ fclose(fp);
+ if (fp2)
+ fclose(fp2);
+ else
+ {
+ fprintf(stderr,"ldrdf: module '%s' not found in '%s'\n",
+ argv[3],argv[2]);
+ exit(1);
+ }
+ break;
+
+ default:
+ fprintf(stderr,"ldrdf: command '%c' not recognised\n",
+ argv[1][0]);
+ exit(1);
+ }
+ return 0;
+}
+
diff --git a/rdoff/v1/rdfload.c b/rdoff/v1/rdfload.c
new file mode 100644
index 00000000..b8483444
--- /dev/null
+++ b/rdoff/v1/rdfload.c
@@ -0,0 +1,173 @@
+/* rdfload.c RDOFF Object File loader library
+ *
+ * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
+ * Julian Hall. All rights reserved. The software is
+ * redistributable under the licence given in the file "Licence"
+ * distributed in the NASM archive.
+ *
+ * Permission to use this file in your own projects is granted, as long
+ * as acknowledgement is given in an appropriate manner to its authors,
+ * with instructions of how to obtain a copy via ftp.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "rdfload.h"
+#include "symtab.h"
+#include "rdoff.h"
+#include "collectn.h"
+
+extern int rdf_errno;
+
+rdfmodule * rdfload(const char *filename)
+{
+ rdfmodule * f = malloc(sizeof(rdfmodule));
+ long bsslength = 0;
+ char * hdr;
+ rdfheaderrec *r;
+
+ if (f == NULL)
+ {
+ rdf_errno = 6; /* out of memory */
+ return NULL;
+ }
+
+ f->symtab = symtabNew();
+ if (!f->symtab)
+ {
+ free(f);
+ rdf_errno = 6;
+ return NULL;
+ }
+
+ /* open the file */
+ if ( rdfopen( &(f->f), filename ) ) {
+ free(f);
+ return NULL;
+ }
+
+ /* read in text and data segments, and header */
+
+ f->t = malloc (f->f.code_len);
+ f->d = malloc (f->f.data_len); /* BSS seg allocated later */
+ hdr = malloc (f->f.header_len);
+
+ if (! f->t || ! f->d || !hdr) {
+ rdf_errno = 6;
+ rdfclose(&f->f);
+ if (f->t) free(f->t);
+ if (f->d) free(f->d);
+ free(f);
+ return NULL;
+ }
+
+ if ( rdfloadseg (&f->f,RDOFF_HEADER,hdr) ||
+ rdfloadseg (&f->f,RDOFF_CODE,f->t) ||
+ rdfloadseg (&f->f,RDOFF_DATA,f->d) )
+ {
+ rdfclose(&f->f);
+ free(f->t);
+ free(f->d);
+ free(f);
+ free(hdr);
+ return NULL;
+ }
+
+ rdfclose(&f->f);
+
+ /* Allocate BSS segment; step through header and count BSS records */
+
+ while ( ( r = rdfgetheaderrec (&f->f) ) )
+ {
+ if (r->type == 5)
+ bsslength += r->b.amount;
+ }
+
+ f->b = malloc ( bsslength );
+ if (! f->b )
+ {
+ free(f->t);
+ free(f->d);
+ free(f);
+ free(hdr);
+ rdf_errno = 6;
+ return NULL;
+ }
+
+ rdfheaderrewind (&f->f);
+
+ f->textrel = (long)f->t;
+ f->datarel = (long)f->d;
+ f->bssrel = (long)f->b;
+
+ return f;
+}
+
+int rdf_relocate(rdfmodule * m)
+{
+ rdfheaderrec * r;
+ Collection imports;
+ symtabEnt e;
+ long rel;
+ unsigned char * seg;
+
+ rdfheaderrewind ( & m->f );
+ collection_init(&imports);
+
+ while ( (r = rdfgetheaderrec ( & m->f ) ) )
+ {
+ switch (r->type)
+ {
+ case 1: /* Relocation record */
+
+ /* calculate relocation factor */
+
+ if (r->r.refseg == 0) rel = m->textrel;
+ else if (r->r.refseg == 1) rel = m->datarel;
+ else if (r->r.refseg == 2) rel = m->bssrel;
+ else
+ /* We currently do not support load-time linkage.
+ This should be added some time soon... */
+
+ return 1; /* return error code */
+
+ if ((r->r.segment & 63) == 0) seg = m->t;
+ else if ((r->r.segment & 63) == 1) seg = m->d;
+ else
+ return 1;
+
+ /* it doesn't matter in this case that the code is non-portable,
+ as the entire concept of executing a module like this is
+ non-portable */
+ switch(r->r.length) {
+ case 1:
+ seg[r->r.offset] += (char) rel;
+ break;
+ case 2:
+ *(int16 *)(seg + r->r.offset) += (int16) rel;
+ break;
+ case 4:
+ *(long *)(seg + r->r.offset) += rel;
+ break;
+ }
+ break;
+
+ case 3: /* export record - add to symtab */
+ e.segment = r->e.segment;
+ e.offset = r->e.offset +
+ (e.segment == 0 ? m->textrel : /* 0 -> code */
+ e.segment == 1 ? m->datarel : /* 1 -> data */
+ m->bssrel) ; /* 2 -> bss */
+ e.flags = 0;
+ e.name = malloc(strlen(r->e.label) + 1);
+ if (! e.name)
+ return 1;
+
+ strcpy(e.name,r->e.label);
+ symtabInsert(m->symtab,&e);
+ break;
+ }
+ }
+ return 0;
+}
diff --git a/rdoff/v1/rdfload.h b/rdoff/v1/rdfload.h
new file mode 100644
index 00000000..5e264b93
--- /dev/null
+++ b/rdoff/v1/rdfload.h
@@ -0,0 +1,29 @@
+/* rdfload.h RDOFF Object File loader library header file
+ *
+ * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
+ * Julian Hall. All rights reserved. The software is
+ * redistributable under the licence given in the file "Licence"
+ * distributed in the NASM archive.
+ *
+ * See the file 'rdfload.c' for special license information for this
+ * file.
+ */
+
+#ifndef _RDFLOAD_H
+#define _RDFLOAD_H
+
+#include "rdoff.h"
+
+typedef struct RDFModuleStruct {
+ rdffile f; /* file structure */
+ unsigned char * t, * d, * b; /* text, data, and bss segments */
+ long textrel;
+ long datarel;
+ long bssrel;
+ void * symtab;
+} rdfmodule;
+
+rdfmodule * rdfload(const char * filename);
+int rdf_relocate(rdfmodule * m);
+
+#endif
diff --git a/rdoff/v1/rdlib.c b/rdoff/v1/rdlib.c
new file mode 100644
index 00000000..bc8d1e35
--- /dev/null
+++ b/rdoff/v1/rdlib.c
@@ -0,0 +1,88 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "rdoff.h"
+#include "rdlib.h"
+
+int rdl_error = 0;
+
+char *rdl_errors[3] = {
+ "no error","could not open file", "invalid file structure",
+};
+
+int rdl_searchlib (struct librarynode * lib,
+ const char * label, rdffile * f)
+{
+ char buf[257];
+ int i;
+ void * hdr;
+ rdfheaderrec * r;
+
+ 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) )
+ {
+ i = 1;
+ while (fread(buf + i,1,1,lib->fp) == 1 && buf[i] && i < 257)
+ i++;
+ buf[0] = ':';
+
+ if (feof(lib->fp)) break;
+
+ if ( rdfopenhere(f,lib->fp,&lib->referenced,buf) ) {
+ rdl_error = 2;
+ return 0;
+ }
+
+ 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->data_ofs + f->data_len;
+ rdfclose(f);
+ fseek(lib->fp,i,SEEK_SET);
+ }
+
+ lib->referenced --;
+ if (! lib->referenced)
+ {
+ fclose(lib->fp);
+ lib->fp = NULL;
+ }
+ return 0;
+}
+
+void rdl_perror(const char *apname, const char *filename)
+{
+ fprintf(stderr,"%s:%s:%s\n",apname,filename,rdl_errors[rdl_error]);
+}
+
+
+
diff --git a/rdoff/v1/rdlib.h b/rdoff/v1/rdlib.h
new file mode 100644
index 00000000..94592ce2
--- /dev/null
+++ b/rdoff/v1/rdlib.h
@@ -0,0 +1,18 @@
+/* rdlib.h Functions for manipulating librarys of RDOFF object files */
+
+
+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;
+
+int rdl_searchlib (struct librarynode * lib,
+ const char * label, rdffile * f);
+void rdl_perror(const char *apname, const char *filename);
+
+
diff --git a/rdoff/v1/rdoff.c b/rdoff/v1/rdoff.c
new file mode 100644
index 00000000..96620ecc
--- /dev/null
+++ b/rdoff/v1/rdoff.c
@@ -0,0 +1,397 @@
+/* rdoff.c library of routines for manipulating rdoff files
+ *
+ * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
+ * Julian Hall. All rights reserved. The software is
+ * redistributable under the licence given in the file "Licence"
+ * distributed in the NASM archive.
+ */
+
+/* TODO: The functions in this module assume they are running
+ * on a little-endian machine. This should be fixed to
+ * make it portable.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#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)
+
+/* ========================================================================
+ * Code for memory buffers (for delayed writing of header until we know
+ * how long it is).
+ * ======================================================================== */
+
+
+memorybuffer * newmembuf(){
+ memorybuffer * t;
+
+ t = malloc(sizeof(memorybuffer));
+
+ t->length = 0;
+ t->next = NULL;
+ return t;
+}
+
+void membufwrite(memorybuffer *b, void *data, int bytes) {
+ int16 w;
+ long l;
+
+ if (b->next) { /* memory buffer full - use next buffer */
+ membufwrite(b->next,data,bytes);
+ return;
+ }
+ if ((bytes < 0 && b->length - bytes > BUF_BLOCK_LEN)
+ || (bytes > 0 && b->length + bytes > BUF_BLOCK_LEN)) {
+
+ /* buffer full and no next allocated... allocate and initialise next
+ * buffer */
+
+ b->next = newmembuf();
+ membufwrite(b->next,data,bytes);
+ }
+
+ switch(bytes) {
+ case -4: /* convert to little-endian */
+ l = * (long *) data ;
+ b->buffer[b->length++] = l & 0xFF;
+ l >>= 8 ;
+ b->buffer[b->length++] = l & 0xFF;
+ l >>= 8 ;
+ b->buffer[b->length++] = l & 0xFF;
+ l >>= 8 ;
+ b->buffer[b->length++] = l & 0xFF;
+ break;
+
+ case -2:
+ w = * (int16 *) data ;
+ b->buffer[b->length++] = w & 0xFF;
+ w >>= 8 ;
+ b->buffer[b->length++] = w & 0xFF;
+ break;
+
+ default:
+ while(bytes--) {
+ b->buffer[b->length++] = *(* (unsigned char **) &data);
+
+ (* (unsigned char **) &data)++ ;
+ }
+ break;
+ }
+}
+
+void membufdump(memorybuffer *b,FILE *fp)
+{
+ if (!b) return;
+
+ fwrite (b->buffer, 1, b->length, fp);
+
+ membufdump(b->next,fp);
+}
+
+int membuflength(memorybuffer *b)
+{
+ if (!b) return 0;
+ return b->length + membuflength(b->next);
+}
+
+void freemembuf(memorybuffer *b)
+{
+ if (!b) return;
+ freemembuf(b->next);
+ free(b);
+}
+
+/* =========================================================================
+ General purpose routines and variables used by the library functions
+ ========================================================================= */
+
+long translatelong(long in) { /* translate from little endian to
+ local representation */
+ long r;
+ unsigned char *i;
+
+ i = (unsigned char *)&in;
+ r = i[3];
+ r = (r << 8) + i[2];
+ r = (r << 8) + i[1];
+ r = (r << 8) + *i;
+
+ return r;
+}
+
+const char *RDOFFId = "RDOFF1"; /* written to the start of RDOFF files */
+
+const char *rdf_errors[7] = {
+ "no error occurred","could not open file","invalid file format",
+ "error reading file","unknown error","header not read",
+ "out of memory"};
+
+int rdf_errno = 0;
+
+/* ========================================================================
+ The library functions
+ ======================================================================== */
+
+int rdfopen(rdffile *f, const char *name)
+{
+ FILE * fp;
+
+ fp = fopen(name,"rb");
+ if (!fp) return rdf_errno = 1; /* error 1: file open error */
+
+ return rdfopenhere(f,fp,NULL,"");
+}
+
+int rdfopenhere(rdffile *f, FILE *fp, int *refcount, char *name)
+{
+ char buf[8];
+ long initpos;
+
+ if (translatelong(0x01020304) != 0x01020304)
+ { /* fix this to be portable! */
+ fputs("*** this program requires a little endian machine\n",stderr);
+ fprintf(stderr,"01020304h = %08lxh\n",translatelong(0x01020304));
+ exit(3);
+ }
+
+ f->fp = fp;
+ initpos = ftell(fp);
+
+ fread(buf,6,1,f->fp); /* read header */
+ buf[6] = 0;
+
+ if (strcmp(buf,RDOFFId)) {
+ fclose(f->fp);
+ return rdf_errno = 2; /* error 2: invalid file format */
+ }
+
+ if (fread(&f->header_len,1,4,f->fp) != 4) {
+ fclose(f->fp);
+ return rdf_errno = 3; /* error 3: file read error */
+ }
+
+ f->header_ofs = ftell(f->fp);
+
+ if (fseek(f->fp,f->header_len,SEEK_CUR)) {
+ fclose(f->fp);
+ return rdf_errno = 2; /* seek past end of file...? */
+ }
+
+ if (fread(&f->code_len,1,4,f->fp) != 4) {
+ fclose(f->fp);
+ return rdf_errno = 3;
+ }
+
+ f->code_ofs = ftell(f->fp);
+ if (fseek(f->fp,f->code_len,SEEK_CUR)) {
+ fclose(f->fp);
+ return rdf_errno = 2;
+ }
+
+ if (fread(&f->data_len,1,4,f->fp) != 4) {
+ fclose(f->fp);
+ return rdf_errno = 3;
+ }
+
+ f->data_ofs = ftell(f->fp);
+ fseek(f->fp,initpos,SEEK_SET);
+ f->header_loc = NULL;
+
+ f->name = newstr(name);
+ f->refcount = refcount;
+ if (refcount) (*refcount)++;
+ return 0;
+}
+
+int rdfclose(rdffile *f)
+{
+ if (! f->refcount || ! *--f->refcount)
+ fclose(f->fp);
+ free(f->name);
+
+ return 0;
+}
+
+void rdfperror(const char *app,const char *name)
+{
+ fprintf(stderr,"%s:%s: %s\n",app,name,rdf_errors[rdf_errno]);
+ if (rdf_errno == 1 || rdf_errno == 3)
+ {
+ perror(app);
+ }
+
+}
+
+int rdfloadseg(rdffile *f,int segment,void *buffer)
+{
+ long fpos;
+ long slen;
+
+ switch(segment) {
+ case RDOFF_HEADER:
+ fpos = f->header_ofs;
+ slen = f->header_len;
+ f->header_loc = (char *)buffer;
+ f->header_fp = 0;
+ break;
+ case RDOFF_CODE:
+ fpos = f->code_ofs;
+ slen = f->code_len;
+ break;
+ case RDOFF_DATA:
+ fpos = f->data_ofs;
+ slen = f->data_len;
+ break;
+ default:
+ fpos = 0;
+ slen = 0;
+ }
+
+ if (fseek(f->fp,fpos,SEEK_SET))
+ return rdf_errno = 4;
+
+ if (fread(buffer,1,slen,f->fp) != slen)
+ return rdf_errno = 3;
+
+ return 0;
+}
+
+/* Macros for reading integers from header in memory */
+
+#define RI8(v) v = f->header_loc[f->header_fp++]
+#define RI16(v) { v = (f->header_loc[f->header_fp] + \
+ (f->header_loc[f->header_fp+1] << 8)); \
+ f->header_fp += 2; }
+
+#define RI32(v) { v = (f->header_loc[f->header_fp] + \
+ (f->header_loc[f->header_fp+1] << 8) + \
+ (f->header_loc[f->header_fp+2] << 16) + \
+ (f->header_loc[f->header_fp+3] << 24)); \
+ f->header_fp += 4; }
+
+#define RS(str,max) { for(i=0;i<max;i++){\
+ RI8(str[i]); if (!str[i]) break;} str[i]=0; }
+
+rdfheaderrec *rdfgetheaderrec(rdffile *f)
+{
+ static rdfheaderrec r;
+ int i;
+
+ if (!f->header_loc) {
+ rdf_errno = 5;
+ return NULL;
+ }
+
+ if (f->header_fp >= f->header_len) return 0;
+
+ RI8(r.type);
+ switch(r.type) {
+ case 1: /* Relocation record */
+ RI8(r.r.segment);
+ RI32(r.r.offset);
+ RI8(r.r.length);
+ RI16(r.r.refseg);
+ break;
+
+ case 2: /* Imported symbol record */
+ RI16(r.i.segment);
+ RS(r.i.label,32);
+ break;
+
+ case 3: /* Exported symbol record */
+ RI8(r.e.segment);
+ RI32(r.e.offset);
+ RS(r.e.label,32);
+ break;
+
+ case 4: /* DLL record */
+ RS(r.d.libname,127);
+ break;
+
+ case 5: /* BSS reservation record */
+ RI32(r.b.amount);
+ break;
+
+ default:
+ rdf_errno = 2; /* invalid file */
+ return NULL;
+ }
+ return &r;
+}
+
+void rdfheaderrewind(rdffile *f)
+{
+ f->header_fp = 0;
+}
+
+
+rdf_headerbuf * rdfnewheader(void)
+{
+ return newmembuf();
+}
+
+int rdfaddheader(rdf_headerbuf * h, rdfheaderrec * r)
+{
+ switch (r->type)
+ {
+ case 1:
+ membufwrite(h,&r->type,1);
+ membufwrite(h,&r->r.segment,1);
+ membufwrite(h,&r->r.offset,-4);
+ membufwrite(h,&r->r.length,1);
+ membufwrite(h,&r->r.refseg,-2); /* 9 bytes written */
+ break;
+
+ case 2: /* import */
+ membufwrite(h,&r->type,1);
+ membufwrite(h,&r->i.segment,-2);
+ membufwrite(h,&r->i.label,strlen(r->i.label) + 1);
+ break ;
+
+ case 3: /* export */
+ membufwrite(h,&r->type,1);
+ membufwrite(h,&r->e.segment,1);
+ membufwrite(h,&r->e.offset,-4);
+ membufwrite(h,&r->e.label,strlen(r->e.label) + 1);
+ break ;
+
+ case 4: /* DLL */
+ membufwrite(h,&r->type,1);
+ membufwrite(h,&r->d.libname,strlen(r->d.libname) + 1);
+ break ;
+
+ case 5: /* BSS */
+ membufwrite(h,&r->type,1);
+ membufwrite(h,&r->b.amount,-4);
+ break ;
+
+ default:
+ return (rdf_errno = 2);
+ }
+ return 0;
+}
+
+int rdfwriteheader(FILE * fp, rdf_headerbuf * h)
+{
+ long l;
+
+ fwrite (RDOFFId, 1, strlen(RDOFFId), fp) ;
+
+ l = translatelong ( membuflength (h) );
+ fwrite (&l, 4, 1, fp);
+
+ membufdump(h, fp);
+
+ return 0; /* no error handling in here... CHANGE THIS! */
+}
+
+void rdfdoneheader(rdf_headerbuf * h)
+{
+ freemembuf(h);
+}
diff --git a/rdoff/v1/rdoff.h b/rdoff/v1/rdoff.h
new file mode 100644
index 00000000..0f74b80a
--- /dev/null
+++ b/rdoff/v1/rdoff.h
@@ -0,0 +1,118 @@
+/* rdoff.h RDOFF Object File manipulation routines header file
+ *
+ * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
+ * Julian Hall. All rights reserved. The software is
+ * redistributable under the licence given in the file "Licence"
+ * distributed in the NASM archive.
+ */
+
+#ifndef _RDOFF_H
+#define _RDOFF_H "RDOFF1 support routines v0.1"
+
+typedef short int16; /* not sure if this will be required to be altered
+ at all... best to typedef it just in case */
+
+/* the records that can be found in the RDOFF header */
+
+struct RelocRec {
+ char type; /* must be 1 */
+ char segment; /* only 0 for code, or 1 for data supported,
+ but add 64 for relative refs (ie do not require
+ reloc @ loadtime, only linkage) */
+ long offset; /* from start of segment in which reference is loc'd */
+ char length; /* 1 2 or 4 bytes */
+ int16 refseg; /* segment to which reference refers to */
+};
+
+struct ImportRec {
+ char type; /* must be 2 */
+ int16 segment; /* segment number allocated to the label for reloc
+ records - label is assumed to be at offset zero
+ in this segment, so linker must fix up with offset
+ of segment and of offset within segment */
+ char label[33]; /* zero terminated... should be written to file until
+ the zero, but not after it - max len = 32 chars */
+};
+
+struct ExportRec {
+ char type; /* must be 3 */
+ char segment; /* segment referred to (0/1) */
+ long offset; /* offset within segment */
+ char label[33]; /* zero terminated as above. max len = 32 chars */
+};
+
+struct DLLRec {
+ char type; /* must be 4 */
+ char libname[128]; /* name of library to link with at load time */
+};
+
+struct BSSRec {
+ char type; /* must be 5 */
+ long amount; /* number of bytes BSS to reserve */
+};
+
+typedef union RDFHeaderRec {
+ char type; /* invariant throughout all below */
+ struct RelocRec r; /* type == 1 */
+ struct ImportRec i; /* type == 2 */
+ struct ExportRec e; /* type == 3 */
+ struct DLLRec d; /* type == 4 */
+ struct BSSRec b; /* type == 5 */
+} rdfheaderrec;
+
+typedef struct RDFFileInfo {
+ FILE *fp; /* file descriptor; must be open to use this struct */
+ int rdoff_ver; /* should be 1; any higher => not guaranteed to work */
+ long header_len;
+ long code_len;
+ long data_len;
+ long header_ofs;
+ long code_ofs;
+ long data_ofs;
+ char *header_loc; /* keep location of header */
+ long header_fp; /* current location within header for reading */
+ 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;
+ char buffer[BUF_BLOCK_LEN];
+ struct memorybuffer *next;
+} memorybuffer;
+
+typedef memorybuffer rdf_headerbuf;
+
+/* segments used by RDOFF, understood by rdoffloadseg */
+#define RDOFF_CODE 0
+#define RDOFF_DATA 1
+#define RDOFF_HEADER -1
+/* mask for 'segment' in relocation records to find if relative relocation */
+#define RDOFF_RELATIVEMASK 64
+/* mask to find actual segment value in relocation records */
+#define RDOFF_SEGMENTMASK 63
+
+extern int rdf_errno;
+
+/* RDOFF file manipulation functions */
+int rdfopen(rdffile *f,const char *name);
+int rdfopenhere(rdffile *f, FILE *fp, int *refcount, char *name);
+int rdfclose(rdffile *f);
+int rdfloadseg(rdffile *f,int segment,void *buffer);
+rdfheaderrec *rdfgetheaderrec(rdffile *f); /* returns static storage */
+void rdfheaderrewind(rdffile *f); /* back to start of header */
+void rdfperror(const char *app,const char *name);
+
+/* functions to write a new RDOFF header to a file -
+ use rdfnewheader to allocate a header, rdfaddheader to add records to it,
+ rdfwriteheader to write 'RDOFF1', length of header, and the header itself
+ to a file, and then rdfdoneheader to dispose of the header */
+
+rdf_headerbuf *rdfnewheader(void);
+int rdfaddheader(rdf_headerbuf *h,rdfheaderrec *r);
+int rdfwriteheader(FILE *fp,rdf_headerbuf *h);
+void rdfdoneheader(rdf_headerbuf *h);
+
+#endif /* _RDOFF_H */
diff --git a/rdoff/rdoff.txt b/rdoff/v1/rdoff.txt
index 7ee86d66..7ee86d66 100644
--- a/rdoff/rdoff.txt
+++ b/rdoff/v1/rdoff.txt
diff --git a/rdoff/v1/rdx.c b/rdoff/v1/rdx.c
new file mode 100644
index 00000000..28ffc427
--- /dev/null
+++ b/rdoff/v1/rdx.c
@@ -0,0 +1,61 @@
+/* rdx.c RDOFF Object File loader program
+ *
+ * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
+ * Julian Hall. All rights reserved. The software is
+ * redistributable under the licence given in the file "Licence"
+ * distributed in the NASM archive.
+ */
+
+/* note: most of the actual work of this program is done by the modules
+ "rdfload.c", which loads and relocates the object file, and by "rdoff.c",
+ which contains general purpose routines to manipulate RDOFF object
+ files. You can use these files in your own program to load RDOFF objects
+ and execute the code in them in a similar way to what is shown here. */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "rdfload.h"
+#include "rdoff.h"
+#include "symtab.h"
+
+typedef int (*main_fn) (int,char**); /* Main function prototype */
+
+int main(int argc, char **argv)
+{
+ rdfmodule * m;
+ main_fn code;
+ symtabEnt * s;
+
+ if (argc < 2)
+ {
+ puts("usage: rdf <rdoff-executable> [params]\n");
+ exit(255);
+ }
+
+ m = rdfload(argv[1]);
+
+ if (! m)
+ {
+ rdfperror("rdf",argv[1]);
+ exit(255);
+ }
+
+ rdf_relocate(m); /* in this instance, the default relocation
+ values will work fine, but they may need changing
+ in other cases... */
+
+ s = symtabFind(m->symtab, "_main");
+ if (! s)
+ {
+ fprintf(stderr,"rdx: could not find symbol '_main' in '%s'\n",argv[1]);
+ exit(255);
+ }
+
+ code = (main_fn) s->offset;
+
+ argv++, argc--; /* remove 'rdx' from command line */
+
+ return code(argc,argv); /* execute */
+}
+
diff --git a/rdoff/v1/symtab.c b/rdoff/v1/symtab.c
new file mode 100644
index 00000000..3fc363e3
--- /dev/null
+++ b/rdoff/v1/symtab.c
@@ -0,0 +1,80 @@
+/* symtab.c Routines to maintain and manipulate a symbol table
+ *
+ * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
+ * Julian Hall. All rights reserved. The software is
+ * redistributable under the licence given in the file "Licence"
+ * distributed in the NASM archive.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "symtab.h"
+
+/* TODO: Implement a hash table, not this stupid implementation which
+ is too slow to be of practical use */
+
+/* Private data types */
+
+typedef struct tagSymtab {
+ symtabEnt ent;
+ struct tagSymtab * next;
+} symtabList;
+
+typedef symtabList * _symtab;
+
+void *symtabNew(void)
+{
+ void *p = malloc(sizeof(_symtab));
+ if (p == NULL) {
+ fprintf(stderr,"symtab: out of memory\n");
+ exit(3);
+ }
+ *(_symtab *)p = NULL;
+
+ return p;
+}
+
+void symtabDone(void *symtab)
+{
+ /* DO SOMETHING HERE! */
+}
+
+void symtabInsert(void *symtab,symtabEnt *ent)
+{
+ symtabList *l = malloc(sizeof(symtabList));
+
+ if (l == NULL) {
+ fprintf(stderr,"symtab: out of memory\n");
+ exit(3);
+ }
+
+ l->ent = *ent;
+ l->next = *(_symtab *)symtab;
+ *(_symtab *)symtab = l;
+}
+
+symtabEnt *symtabFind(void *symtab,char *name)
+{
+ symtabList *l = *(_symtab *)symtab;
+
+ while (l) {
+ if (!strcmp(l->ent.name,name)) {
+ return &(l->ent);
+ }
+ l = l->next;
+ }
+ return NULL;
+}
+
+void symtabDump(void *symtab,FILE *of)
+{
+ symtabList *l = *(_symtab *)symtab;
+
+ while(l) {
+ fprintf(of,"%32s %s:%08lx (%ld)\n",l->ent.name,
+ l->ent.segment ? "data" : "code" ,
+ l->ent.offset, l->ent.flags);
+ l = l->next;
+ }
+}
+
diff --git a/rdoff/v1/symtab.h b/rdoff/v1/symtab.h
new file mode 100644
index 00000000..5780d447
--- /dev/null
+++ b/rdoff/v1/symtab.h
@@ -0,0 +1,22 @@
+/* symtab.h Header file for symbol table manipulation routines
+ *
+ * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
+ * Julian Hall. All rights reserved. The software is
+ * redistributable under the licence given in the file "Licence"
+ * distributed in the NASM archive.
+ */
+
+typedef struct {
+ char *name;
+ long segment;
+ long offset;
+ long flags;
+} symtabEnt;
+
+void *symtabNew(void);
+void symtabDone(void *symtab);
+void symtabInsert(void *symtab,symtabEnt *ent);
+symtabEnt *symtabFind(void *symtab,char *name);
+void symtabDump(void *symtab,FILE *of);
+
+