0
0
mirror of https://github.com/netwide-assembler/nasm.git synced 2025-11-08 23:27:15 -05:00

NASM 0.98

This commit is contained in:
H. Peter Anvin
2002-04-30 20:58:18 +00:00
parent ef7468f4ec
commit 41bf8002b2
74 changed files with 6282 additions and 1500 deletions

View File

@@ -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.

13
Licence
View File

@@ -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

View File

@@ -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:

View File

@@ -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

View File

@@ -114,7 +114,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
@@ -135,4 +135,3 @@ clean:
del *.obj
del nasm$(SUFFIX)$(EXE)
del ndisasm$(SUFFIX)$(EXE)

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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);
}
}

View File

@@ -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 ;*************************************************************

View File

@@ -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)

View File

@@ -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

50
doc/Makefile.in Normal file
View File

@@ -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)

View File

@@ -1,12 +1,22 @@
\IR{-o} \c{-o} option
\IR{-f} \c{-f} option
\IR{-l} \c{-l} option
\IR{-s} \c{-s} option
\IR{-i} \c{-i} option
\IR{-p} \c{-p} 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{-a} \c{-a} option
\IR{-f} \c{-f} option
\IR{-i} \c{-i} option
\IR{-l} \c{-l} option
\IR{-o} \c{-o} option
\IR{-p} \c{-p} 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-i} The \i\c{-i} Option: Include File Search Directories
\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}\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.

View File

@@ -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";

View File

@@ -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

236
insns.pl
View File

@@ -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,136 +62,144 @@ close F;
@opcodes = sort keys(%k_opcodes);
@opcodes_cc = sort keys(%k_opcodes_cc);
print STDERR "Writing insnsa.c...\n";
if ( !defined($output) || $output eq 'a' ) {
print STDERR "Writing insnsa.c...\n";
open A, ">insnsa.c";
open A, ">insnsa.c";
print A "/* This file auto-generated from insns.dat by insns.pl" .
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";
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";
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 "struct itemplate *nasm_instructions[] = {\n";
foreach $i (@opcodes, @opcodes_cc) {
print A " instrux_${i},\n";
}
print A "};\n";
close A;
if ( !defined($output) || $output eq 'd' ) {
print STDERR "Writing insnsd.c...\n";
print STDERR "Writing insnsd.c...\n";
open D, ">insnsd.c";
open D, ">insnsd.c";
print D "/* This file auto-generated from insns.dat by insns.pl" .
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 "#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";
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";
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 "struct itemplate **itable[] = {\n";
for ($c=0; $c<256; $c++) {
printf D " itable_%02X,\n", $c;
}
print D "};\n";
if ( !defined($output) || $output eq 'i' ) {
print STDERR "Writing insnsi.h...\n";
close D;
open I, ">insnsi.h";
print STDERR "Writing insnsi.h...\n";
open I, ">insnsi.h";
print I "/* This file is auto-generated from insns.dat by insns.pl" .
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 "/* 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 "/* 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;
if ( !defined($output) || $output eq 'n' ) {
print STDERR "Writing insnsn.c...\n";
print STDERR "Writing insnsn.c...\n";
open N, ">insnsn.c";
open N, ">insnsn.c";
print N "/* This file is auto-generated from insns.dat by insns.pl" .
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 "/* 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 "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\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;
printf STDERR "Done: %d instructions\n", $insns;

View File

@@ -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,

27
nasm.c
View File

@@ -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) &&

2
nasm.h
View File

@@ -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

87
nasm.spec Normal file
View File

@@ -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/*

View File

@@ -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

63
rdoff/Changes Normal file
View File

@@ -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.

View File

@@ -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
spotless: clean
rm -f Makefile
cleaner: clean
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

View File

@@ -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)


View File

@@ -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

View File

@@ -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>

95
rdoff/hash.c Normal file
View File

@@ -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);
}

12
rdoff/hash.h Normal file
View File

@@ -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);

File diff suppressed because it is too large Load Diff

728
rdoff/ldrdf1.c Normal file
View File

@@ -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;
}

55
rdoff/ldsegs.h Normal file
View File

@@ -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); \
} \
}

View File

@@ -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;

View File

@@ -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 (verbose)
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)
{
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;

View File

@@ -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, 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 */
/* step over the RDOFF file, extracting type information for
* the listing, and copying it if fp2 != NULL */
if (buf[0] == '.') {
if (argv[1][0] == 't')
for (i = 0; i < 6; i++)
printf("%c", copybytes(fp,fp2,1));
else
copybytes(fp,fp2,6);
l = 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);
}

View File

@@ -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;

View File

@@ -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]);
}

View File

@@ -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);

View File

@@ -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;
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)++ ;
if (b->next) { /* memory buffer full - use next buffer */
membufwrite(b->next,data,bytes);
return;
}
if ((bytes < 0 && b->length - bytes > BUF_BLOCK_LEN)
|| (bytes > 0 && b->length + bytes > BUF_BLOCK_LEN))
{
/* buffer full and no next allocated... allocate and initialise next
* buffer */
b->next = newmembuf();
membufwrite(b->next,data,bytes);
return;
}
switch(bytes) {
case -4: /* convert to little-endian */
l = * (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;
}
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;
const char *rdf_errors[7] = {
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[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;
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;
}
}
if (fread(&f->data_len,1,4,f->fp) != 4) {
fclose(f->fp);
return rdf_errno = 3;
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);
}
f->data_ofs = ftell(f->fp);
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);
}

View File

@@ -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"
typedef short int16; /* not sure if this will be required to be altered
at all... best to typedef it just in case */
/* Some systems don't define this automatically */
extern char *strdup(const char *);
typedef unsigned short int16;
typedef unsigned char byte;
#define RDF_MAXSEGS 64
/* the records that can be found in the RDOFF header */
struct RelocRec {
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);

View File

@@ -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);
}

142
rdoff/segtab.c Normal file
View File

@@ -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

7
rdoff/segtab.h Normal file
View File

@@ -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);

View File

@@ -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 symtabList * _symtab;
typedef symtabNode *(symtabTab[SYMTABSIZE]);
void *symtabNew(void)
typedef symtabTab *symtab;
/* ------------------------------------- */
void *
symtabNew(void)
{
void *p = malloc(sizeof(_symtab));
if (p == NULL) {
fprintf(stderr,"symtab: out of memory\n");
exit(3);
}
*(_symtab *)p = NULL;
symtab mytab;
return p;
}
void symtabDone(void *symtab)
{
/* DO SOMETHING HERE! */
}
void symtabInsert(void *symtab,symtabEnt *ent)
{
symtabList *l = malloc(sizeof(symtabList));
if (l == NULL) {
mytab = (symtabTab *) calloc(SYMTABSIZE ,sizeof(symtabNode *));
if (mytab == NULL) {
fprintf(stderr,"symtab: out of memory\n");
exit(3);
}
l->ent = *ent;
l->next = *(_symtab *)symtab;
*(_symtab *)symtab = l;
return mytab;
}
symtabEnt *symtabFind(void *symtab,char *name)
/* ------------------------------------- */
void
symtabDone(void *stab)
{
symtabList *l = *(_symtab *)symtab;
symtab mytab = (symtab)stab;
int i;
symtabNode *this, *next;
while (l) {
if (!strcmp(l->ent.name,name)) {
return &(l->ent);
}
l = l->next;
}
return NULL;
for (i=0; i < SYMTABSIZE; ++i) {
for (this = (*mytab)[i]; this; this=next)
{ next = this->next; free (this); }
}
free (*mytab);
}
void symtabDump(void *symtab,FILE *of)
/* ------------------------------------- */
void
symtabInsert(void *stab, symtabEnt *ent)
{
symtabList *l = *(_symtab *)symtab;
symtab mytab = (symtab) stab;
symtabNode *node;
int slot;
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;
node = malloc(sizeof(symtabNode));
if (node == NULL) {
fprintf(stderr,"symtab: out of memory\n");
exit(3);
}
slot = slotnum(ent->name);
node->ent = *ent;
node->next = (*mytab)[slot];
(*mytab)[slot] = node;
}
/* ------------------------------------- */
symtabEnt *
symtabFind(void *stab, const char *name)
{
symtab mytab = (symtab) stab;
int slot = slotnum(name);
symtabNode *node = (*mytab)[slot];
while (node) {
if (!strcmp(node->ent.name,name)) {
return &(node->ent);
}
node = node->next;
}
return NULL;
}
/* ------------------------------------- */
void
symtabDump(void *stab, FILE* of)
{
symtab mytab = (symtab)stab;
int i;
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");
}

View File

@@ -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);

20
rdoff/test/rdfseg.asm Normal file
View File

@@ -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

12
rdoff/test/rdfseg2.asm Normal file
View File

@@ -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

5
rdoff/v1/README Normal file
View File

@@ -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.

40
rdoff/v1/collectn.c Normal file
View File

@@ -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;
}

22
rdoff/v1/collectn.h Normal file
View File

@@ -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

728
rdoff/v1/ldrdf.c Normal file
View File

@@ -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;
}

125
rdoff/v1/rdf2bin.c Normal file
View File

@@ -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;
}

167
rdoff/v1/rdfdump.c Normal file
View File

@@ -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;
}

235
rdoff/v1/rdflib.c Normal file
View File

@@ -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;
}

173
rdoff/v1/rdfload.c Normal file
View File

@@ -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;
}

29
rdoff/v1/rdfload.h Normal file
View File

@@ -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

88
rdoff/v1/rdlib.c Normal file
View File

@@ -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]);
}

18
rdoff/v1/rdlib.h Normal file
View File

@@ -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);

397
rdoff/v1/rdoff.c Normal file
View File

@@ -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);
}

118
rdoff/v1/rdoff.h Normal file
View File

@@ -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 */

61
rdoff/v1/rdx.c Normal file
View File

@@ -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 */
}

80
rdoff/v1/symtab.c Normal file
View File

@@ -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;
}
}

22
rdoff/v1/symtab.h Normal file
View File

@@ -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);