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:
5
Changes
5
Changes
@@ -446,8 +446,8 @@ corruption at ends of long PUBDEF records.
|
||||
Separated DOS archives into main-program and documentation to reduce
|
||||
download size.
|
||||
|
||||
0.98 not released yet
|
||||
---------------------
|
||||
0.98 released May 1999
|
||||
----------------------
|
||||
|
||||
Fixed a bug whereby STRUC didn't work at all in RDF.
|
||||
|
||||
@@ -539,3 +539,4 @@ help screen
|
||||
fixed limit checking bug, 'OUT byte nn, reg' bug, and a couple of rdoff
|
||||
related bugs, updated Wishlist; 0.98 Prerelease 3.
|
||||
|
||||
See the file "MODIFIED" for changes after 0.98p3.
|
||||
|
||||
13
Licence
13
Licence
@@ -1,3 +1,4 @@
|
||||
|
||||
Terms and Conditions for the use of the Netwide Assembler
|
||||
=========================================================
|
||||
|
||||
@@ -52,7 +53,8 @@ which a fee is charged), as long as permission is granted from the
|
||||
authors of the Software. The authors reserve the right to grant this
|
||||
permission only for a fee, which may at our option take the form of
|
||||
royalty payments. The authors also reserve the right to refuse to
|
||||
grant permission if they deem it necessary.
|
||||
grant permission if they deem it necessary. For further information
|
||||
about who exactly the authors are, see clause XI below.
|
||||
|
||||
V. The Software may be incorporated, in its original archive form,
|
||||
into software collections or archives which are not freely
|
||||
@@ -105,4 +107,13 @@ authors for the purpose of inclusion in the official release version
|
||||
are considered cleared for release under the full terms of this
|
||||
Licence.
|
||||
|
||||
XI. The authors of NASM are the original authors (Simon Tatham and
|
||||
Julian Hall) and all those who the original authors feel have
|
||||
contributed significantly to the overall project. If you wish to
|
||||
contact the authors, Julian Hall (jules@earthcorp.com) should be your
|
||||
first port of call.
|
||||
|
||||
XII. Should any part of this agreement be deemed unenforcable, it is
|
||||
intended that the remainder of the agreement be held in force.
|
||||
|
||||
END OF LICENCE AGREEMENT
|
||||
|
||||
42
MODIFIED
42
MODIFIED
@@ -1,7 +1,41 @@
|
||||
This is a modified version of NASM, modified and released by H. Peter
|
||||
Anvin <hpa@zytor.com>; it is not the original form released by the
|
||||
NASM authors. However, as of 0.98p6 I have agreed to release the
|
||||
official 0.98 version, so this is now an "official pre-release".
|
||||
This file details changes since NASM 0.98p3. All the releases in this
|
||||
file have been produced by H. Peter Anvin <hpa@zytor.com>.
|
||||
|
||||
For release 0.98:
|
||||
* The documentation comment delimiter is \# not #.
|
||||
* Allow EQU definitions to refer to external labels; reported by
|
||||
Pedro Gimeno.
|
||||
* Re-enable support for RDOFF v1; reported by Pedro Gimeno.
|
||||
* Updated License file per OK from Simon and Julian.
|
||||
|
||||
For release 0.98p9:
|
||||
* Update documentation (although the instruction set reference will
|
||||
have to wait; I don't want to hold up the 0.98 release for it.)
|
||||
* Verified that the NASM implementation of the PEXTRW and PMOVMSKB
|
||||
instructions is correct. The encoding differs from what the Intel
|
||||
manuals document, but the Pentium III behaviour matches NASM, not
|
||||
the Intel manuals.
|
||||
* Fix handling of implicit sizes in PSHUFW and PINSRW, reported by
|
||||
Stefan Hoffmeister.
|
||||
* Resurrect the -s option, which was removed when changing the
|
||||
diagnostic output to stdout.
|
||||
|
||||
For release 0.98p8:
|
||||
* Fix for "DB" when NASM is running on a bigendian machine.
|
||||
* Invoke insns.pl once for each output script, making Makefile.in
|
||||
legal for "make -j".
|
||||
* Improve the Unix configure-based makefiles to make package
|
||||
creation easier.
|
||||
* Included an RPM .spec file for building RPM (RedHat Package Manager)
|
||||
packages on Linux or Unix systems.
|
||||
* Fix Makefile dependency problems.
|
||||
* Change src/rdsrc.pl to include sectioning information in info
|
||||
output; required for install-info to work.
|
||||
* Updated the RDOFF distribution to version 2 from Jules; minor
|
||||
massaging to make it compile in my environment.
|
||||
* Split doc files that can be built by anyone with a Perl interpreter off
|
||||
into a separate archive.
|
||||
* "Dress rehearsal" release!
|
||||
|
||||
For release 0.98p7:
|
||||
|
||||
|
||||
88
Makefile.in
88
Makefile.in
@@ -1,3 +1,4 @@
|
||||
# $Id$
|
||||
#
|
||||
# Auto-configuring Makefile for the Netwide Assembler.
|
||||
#
|
||||
@@ -6,26 +7,36 @@
|
||||
# redistributable under the licence given in the file "Licence"
|
||||
# distributed in the NASM archive.
|
||||
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
bindir = @bindir@
|
||||
mandir = @mandir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
bindir = @bindir@
|
||||
mandir = @mandir@
|
||||
|
||||
CC = @CC@
|
||||
CFLAGS = @CFLAGS@ @GCCFLAGS@ -I$(srcdir) -I.
|
||||
CC = @CC@
|
||||
CFLAGS = @CFLAGS@ @GCCFLAGS@ -I$(srcdir) -I.
|
||||
LDFLAGS = @LDFLAGS@
|
||||
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
|
||||
NROFF = @NROFF@
|
||||
NROFF = @NROFF@
|
||||
|
||||
.SUFFIXES: .c .o .1 .man
|
||||
.SUFFIXES: .c .i .s .o .1 .man
|
||||
|
||||
.PHONY: all doc rdf install clean distclean cleaner spotless install_rdf
|
||||
.PHONY: install_doc everything install_everything
|
||||
|
||||
.c.o:
|
||||
$(CC) -c $(CFLAGS) $<
|
||||
$(CC) -c $(CFLAGS) -o $@ $<
|
||||
|
||||
.c.s:
|
||||
$(CC) -S $(CFLAGS) -o $@ $<
|
||||
|
||||
.c.i:
|
||||
$(CC) -E $(CFLAGS) -o $@ $<
|
||||
|
||||
.1.man:
|
||||
$(NROFF) -man $< > $@
|
||||
@@ -38,12 +49,13 @@ NASM = nasm.o nasmlib.o float.o insnsa.o assemble.o labels.o \
|
||||
NDISASM = ndisasm.o disasm.o sync.o nasmlib.o insnsd.o
|
||||
|
||||
all: nasm ndisasm nasm.man ndisasm.man
|
||||
cd rdoff; $(MAKE) all
|
||||
|
||||
nasm: $(NASM)
|
||||
$(CC) -o nasm $(NASM)
|
||||
$(CC) $(LDFLAGS) -o nasm $(NASM)
|
||||
|
||||
ndisasm: $(NDISASM)
|
||||
$(CC) -o ndisasm $(NDISASM)
|
||||
$(CC) $(LDFLAGS) -o ndisasm $(NDISASM)
|
||||
|
||||
assemble.o: assemble.c nasm.h insnsi.h nasmlib.h assemble.h insns.h
|
||||
disasm.o: disasm.c nasm.h insnsi.h disasm.h sync.h insns.h names.c insnsn.c
|
||||
@@ -55,7 +67,7 @@ labels.o: labels.c nasm.h insnsi.h nasmlib.h
|
||||
listing.o: listing.c nasm.h insnsi.h nasmlib.h listing.h
|
||||
nasm.o: nasm.c nasm.h insnsi.h nasmlib.h preproc.h parser.h assemble.h labels.h \
|
||||
outform.h listing.h
|
||||
nasmlib.o: nasmlib.c nasm.h insnsi.h nasmlib.h
|
||||
nasmlib.o: nasmlib.c nasm.h insnsi.h nasmlib.h names.c insnsn.c
|
||||
ndisasm.o: ndisasm.c nasm.h insnsi.h nasmlib.h sync.h disasm.h
|
||||
outaout.o: outaout.c nasm.h insnsi.h nasmlib.h outform.h
|
||||
outas86.o: outas86.c nasm.h insnsi.h nasmlib.h outform.h
|
||||
@@ -77,8 +89,14 @@ zoutieee.o: zoutieee.c nasm.h insnsi.h nasmlib.h outform.h
|
||||
# though, so it isn't necessary to have Perl just to recompile NASM
|
||||
# from the distribution.
|
||||
|
||||
insnsa.c insnsd.c insnsi.h insnsn.c: insns.dat insns.pl
|
||||
perl $(srcdir)/insns.pl $(srcdir)/insns.dat
|
||||
insnsa.c: insns.dat insns.pl
|
||||
perl $(srcdir)/insns.pl -a $(srcdir)/insns.dat
|
||||
insnsd.c: insns.dat insns.pl
|
||||
perl $(srcdir)/insns.pl -d $(srcdir)/insns.dat
|
||||
insnsi.h: insns.dat insns.pl
|
||||
perl $(srcdir)/insns.pl -i $(srcdir)/insns.dat
|
||||
insnsn.c: insns.dat insns.pl
|
||||
perl $(srcdir)/insns.pl -n $(srcdir)/insns.dat
|
||||
|
||||
# This source file is generated from the standard macros file
|
||||
# `standard.mac' by another Perl script. Again, it's part of the
|
||||
@@ -88,26 +106,38 @@ macros.c: standard.mac macros.pl
|
||||
perl $(srcdir)/macros.pl $(srcdir)/standard.mac
|
||||
|
||||
install: nasm ndisasm
|
||||
$(INSTALL_PROGRAM) nasm $(bindir)/nasm
|
||||
$(INSTALL_PROGRAM) ndisasm $(bindir)/ndisasm
|
||||
$(INSTALL_DATA) $(srcdir)/nasm.1 $(mandir)/man1/nasm.1
|
||||
$(INSTALL_DATA) $(srcdir)/ndisasm.1 $(mandir)/man1/ndisasm.1
|
||||
$(INSTALL_PROGRAM) nasm $(INSTALLROOT)$(bindir)/nasm
|
||||
$(INSTALL_PROGRAM) ndisasm $(INSTALLROOT)$(bindir)/ndisasm
|
||||
$(INSTALL_DATA) $(srcdir)/nasm.1 $(INSTALLROOT)$(mandir)/man1/nasm.1
|
||||
$(INSTALL_DATA) $(srcdir)/ndisasm.1 $(INSTALLROOT)$(mandir)/man1/ndisasm.1
|
||||
|
||||
clean:
|
||||
rm -f *.o nasm ndisasm
|
||||
cd rdoff; $(MAKE) clean
|
||||
rm -f *.o *.s *.i nasm ndisasm
|
||||
cd rdoff && $(MAKE) clean
|
||||
|
||||
distclean: clean
|
||||
rm -f config.* Makefile *~ *.bak changed.lst changed.bin
|
||||
cd rdoff; $(MAKE) distclean
|
||||
rm -f config.* Makefile *~ *.bak *.lst *.bin
|
||||
cd rdoff && $(MAKE) distclean
|
||||
|
||||
cleaner: clean
|
||||
rm -f insnsa.c insnsd.c insnsi.h insnsn.c macros.c *.man
|
||||
cd doc && $(MAKE) clean
|
||||
|
||||
spotless: distclean cleaner
|
||||
|
||||
rdf:
|
||||
cd rdoff; $(MAKE)
|
||||
cd rdoff && $(MAKE)
|
||||
|
||||
rdf_install install_rdf:
|
||||
cd rdoff; $(MAKE) install
|
||||
cd rdoff && $(MAKE) install
|
||||
|
||||
doc:
|
||||
cd doc && $(MAKE) all
|
||||
|
||||
doc_install install_doc:
|
||||
cd doc && $(MAKE) install
|
||||
|
||||
everything: all doc rdf
|
||||
|
||||
install_everything: everything install install_doc install_rdf
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
28
changed.asm
28
changed.asm
@@ -322,6 +322,34 @@ arg_example2 arg2
|
||||
%error "TEST_ME defined after %undef"
|
||||
%endif
|
||||
|
||||
;-----------------------------------------------------------------------------
|
||||
; Bug fix by hpa in insns.dat
|
||||
;
|
||||
; PSHUFW and PINSRW weren't handling the implicit sizes correctly; all of
|
||||
; the entries below are (or should be) legal
|
||||
;
|
||||
pshufw mm2, mm1, 3
|
||||
pshufw mm3,[ebx],2
|
||||
pshufw mm7,[0+edi*8],1
|
||||
|
||||
pshufw mm2, mm1, byte 3
|
||||
pshufw mm3,[ebx],byte 2
|
||||
pshufw mm7,[0+edi*8],byte 1
|
||||
|
||||
pshufw mm2, mm1, 3
|
||||
pshufw mm3, qword [ebx], 2
|
||||
pshufw mm7, qword [0+edi*8], 1
|
||||
|
||||
pshufw mm2, mm1, byte 3
|
||||
pshufw mm3, qword [ebx], byte 2
|
||||
pshufw mm7, qword [0+edi*8], byte 1
|
||||
|
||||
pinsrw mm1, [esi], 1
|
||||
pinsrw mm1, word [esi], 1
|
||||
pinsrw mm1, [esi], byte 1
|
||||
pinsrw mm1, word [esi], byte 1
|
||||
|
||||
|
||||
%endif ; oldmsg
|
||||
|
||||
%ifdef oldcrash ;*************************************************************
|
||||
|
||||
@@ -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)
|
||||
|
||||
29
doc/Makefile
29
doc/Makefile
@@ -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
50
doc/Makefile.in
Normal 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)
|
||||
145
doc/nasmdoc.src
145
doc/nasmdoc.src
@@ -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.
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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
236
insns.pl
@@ -9,7 +9,21 @@
|
||||
|
||||
print STDERR "Reading insns.dat...\n";
|
||||
|
||||
$fname = "insns.dat" unless $fname = $ARGV[0];
|
||||
@args = ();
|
||||
undef $output;
|
||||
foreach $arg ( @ARGV ) {
|
||||
if ( $arg =~ /^\-/ ) {
|
||||
if ( $arg =~ /^\-([adin])$/ ) {
|
||||
$output = $1;
|
||||
} else {
|
||||
die "$0: Unknown option: ${arg}\n";
|
||||
}
|
||||
} else {
|
||||
push (@args, $arg);
|
||||
}
|
||||
}
|
||||
|
||||
$fname = "insns.dat" unless $fname = $args[0];
|
||||
open (F, $fname) || die "unable to open $fname";
|
||||
|
||||
$line = 0;
|
||||
@@ -48,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;
|
||||
|
||||
|
||||
14
labels.c
14
labels.c
@@ -215,12 +215,14 @@ void define_label (char *label, long segment, long offset, char *special,
|
||||
lptr->defn.offset = offset;
|
||||
lptr->defn.is_norm = (label[0] != '.' && is_norm);
|
||||
|
||||
ofmt->symdef (lptr->defn.label, segment, offset,
|
||||
!!(lptr->defn.is_global & GLOBAL_BIT),
|
||||
special ? special : lptr->defn.special);
|
||||
ofmt->current_dfmt->debug_deflabel (label, segment, offset,
|
||||
!!(lptr->defn.is_global & GLOBAL_BIT),
|
||||
special ? special : lptr->defn.special);
|
||||
if ( (lptr->defn.is_global & (GLOBAL_BIT|EXTERN_BIT)) != EXTERN_BIT ) {
|
||||
ofmt->symdef (lptr->defn.label, segment, offset,
|
||||
!!(lptr->defn.is_global & GLOBAL_BIT),
|
||||
special ? special : lptr->defn.special);
|
||||
ofmt->current_dfmt->debug_deflabel (label, segment, offset,
|
||||
!!(lptr->defn.is_global & GLOBAL_BIT),
|
||||
special ? special : lptr->defn.special);
|
||||
}
|
||||
}
|
||||
|
||||
void define_common (char *label, long segment, long size, char *special,
|
||||
|
||||
27
nasm.c
27
nasm.c
@@ -326,7 +326,8 @@ static int process_arg (char *p, char *q)
|
||||
case '-': /* -- => stop processing options */
|
||||
stopoptions = 1;
|
||||
break;
|
||||
case 's': /* silently ignored for compatibility */
|
||||
case 's':
|
||||
error_file = stdout;
|
||||
break;
|
||||
case 'o': /* these parameters take values */
|
||||
case 'f':
|
||||
@@ -390,7 +391,8 @@ static int process_arg (char *p, char *q)
|
||||
" -e preprocess only (writes output to stdout by default)\n"
|
||||
" -a don't preprocess (assemble only)\n"
|
||||
" -M generate Makefile dependencies on stdout\n\n"
|
||||
" -E<file> redirect error messages to file\n\n"
|
||||
" -E<file> redirect error messages to file\n"
|
||||
" -s redirect error messages to stdout\n\n"
|
||||
" -g enable debug info\n"
|
||||
" -F format select a debugging format\n\n"
|
||||
" -I<path> adds a pathname to the include file path\n"
|
||||
@@ -812,18 +814,6 @@ static void assemble_file (char *fname)
|
||||
report_error (ERR_NONFATAL,
|
||||
"EQU not preceded by label");
|
||||
|
||||
/*
|
||||
* EQU cannot be used to declare a label relative to
|
||||
* an external symbol.
|
||||
*/
|
||||
else if ((output_ins.oprs[0].opflags & OPFLAG_EXTERN)
|
||||
|| (output_ins.operands > 1
|
||||
&& (output_ins.oprs[1].opflags & OPFLAG_EXTERN)))
|
||||
{
|
||||
report_error (ERR_NONFATAL,
|
||||
"EQU used relative to external symbol");
|
||||
}
|
||||
|
||||
else if (output_ins.label[0] != '.' ||
|
||||
output_ins.label[1] != '.' ||
|
||||
output_ins.label[2] == '@')
|
||||
@@ -832,10 +822,11 @@ static void assemble_file (char *fname)
|
||||
(output_ins.oprs[0].type & IMMEDIATE) &&
|
||||
output_ins.oprs[0].wrt == NO_SEG)
|
||||
{
|
||||
define_label (output_ins.label,
|
||||
output_ins.oprs[0].segment,
|
||||
output_ins.oprs[0].offset,
|
||||
NULL, FALSE, FALSE, ofmt, report_error);
|
||||
int isext = output_ins.oprs[0].opflags & OPFLAG_EXTERN;
|
||||
define_label (output_ins.label,
|
||||
output_ins.oprs[0].segment,
|
||||
output_ins.oprs[0].offset,
|
||||
NULL, FALSE, isext, ofmt, report_error);
|
||||
}
|
||||
else if (output_ins.operands == 2 &&
|
||||
(output_ins.oprs[0].type & IMMEDIATE) &&
|
||||
|
||||
2
nasm.h
2
nasm.h
@@ -13,7 +13,7 @@
|
||||
|
||||
#define NASM_MAJOR_VER 0
|
||||
#define NASM_MINOR_VER 98
|
||||
#define NASM_VER "0.98 pre-release 7"
|
||||
#define NASM_VER "0.98"
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL 0
|
||||
|
||||
87
nasm.spec
Normal file
87
nasm.spec
Normal 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/*
|
||||
@@ -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
63
rdoff/Changes
Normal 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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
100
rdoff/README
100
rdoff/README
@@ -1,22 +1,45 @@
|
||||
RDOFF Utils v0.2
|
||||
RDOFF Utils v0.3
|
||||
================
|
||||
|
||||
The files contained in this directory are the C source code of a set
|
||||
of tools (and general purpose library files) for the manipulation of
|
||||
RDOFF version 1 object files. Here is a brief summary of their usage:
|
||||
RDOFF version 2 object files. Note that these programs (with the
|
||||
exception of 'rdfdump') will NOT work with version 1 object files. See
|
||||
the subdirectory v1 for programs that perform that task.
|
||||
|
||||
Note: If you do not have a v1 subdirectory, you may have unpacked the
|
||||
ZIP file without specifying the 'restore directory structure' option -
|
||||
delete these files, and run your ZIP extracter again with this option
|
||||
turned on ('-d' for PKUNZIP).
|
||||
|
||||
RDOFF version 1 is no longer really supported, you should be using
|
||||
v2 instead now.
|
||||
|
||||
There is also a 'Changes' file, which documents the differences between
|
||||
RDOFF 1 and 2, and an 'rdoff2.txt' file, with complete documentation for the
|
||||
new format.
|
||||
|
||||
Here is a brief summary of the programs' usage:
|
||||
|
||||
rdfdump
|
||||
=======
|
||||
|
||||
This tool prints a list of the header records in an RDOFF object in
|
||||
human-readable form, and optionally prints a hex dump of the contents
|
||||
of the code and data segments.
|
||||
of the segments.
|
||||
|
||||
Usage:
|
||||
rdfdump [-v] filename
|
||||
|
||||
The -v flag specifies that the hex dump (see above) should be printed.
|
||||
|
||||
Changes from previous versions:
|
||||
|
||||
* rdfdump supports both version 1 and 2 of RDOFF.
|
||||
* rdfdump now gives warnings if the RDOFF2 format is violated (it
|
||||
looks for incorrect lengths for header records, and checks the
|
||||
overall length count at the start of the file)
|
||||
|
||||
ldrdf
|
||||
=====
|
||||
|
||||
@@ -66,19 +89,84 @@ Usage:
|
||||
|
||||
Valid commands are:
|
||||
|
||||
c Create the library
|
||||
c Create (or truncate) the library
|
||||
a Add a module (requires a filename and a name to give the
|
||||
module, ie 'rdflib a libc.rdl strcpy.rdf strcpy' puts the
|
||||
file 'strcpy.rdf' into 'libc.rdl', and calls it 'strcpy'.
|
||||
x Extract (arguments are the opposite to the 'a' command,
|
||||
ie you'd do 'rdflib x libc.rdl strcpy strcpy.rdf to get
|
||||
a copy of strcpy.rdf back out again...)
|
||||
t List modules in the library
|
||||
|
||||
Remove and List commands will be added soon (they're already documented
|
||||
as existing, but I haven't had time to implement them... if anyone
|
||||
A remove command will be added soon (it is already documented
|
||||
as existing, but I haven't had time to implement it... if anyone
|
||||
else wants to do this, they're welcome to. The file format should be
|
||||
amply documented in the source code... look at 'rdflib.c' and 'rdlib.c',
|
||||
and the relevant sections of 'ldrdf.c' to see how libraries can be
|
||||
handled).
|
||||
|
||||
Library functions
|
||||
=================
|
||||
|
||||
The files 'rdoff.c', 'rdoff.h', 'rdfload.c' and 'rdfload.h' contain
|
||||
code which you may find useful. They retain the same interface as
|
||||
the previous version, so any code that used them previously should
|
||||
still work OK (maybe). 'rdoff.c' contains at the top a line:
|
||||
|
||||
#define STRICT_ERRORS
|
||||
|
||||
Comment this line out if you wish to use record types other than the
|
||||
7 predefined types; it will then not report such records as an error,
|
||||
but accept them gracefully, and read them byte for byte into
|
||||
a 'generic record' (see the definition of GenericRec in 'rdoff.h').
|
||||
|
||||
If you are using these functions to write RDF modules (rather than
|
||||
just reading them), then please note the existance of a new function
|
||||
'rdfaddsegment(rdf_headerbuf,long)'. This must be called once for
|
||||
each segment in your object, to tell the header writing functions
|
||||
how long the segment is.
|
||||
|
||||
BUGS
|
||||
====
|
||||
|
||||
This product has recently undergone a major revision, and as such there
|
||||
are probably several bugs left over from the testing phase (although the
|
||||
previous version had quite a few that have now been fixed!). Could you
|
||||
please report any bugs to me at the address below, including the following
|
||||
information:
|
||||
|
||||
- A description of the bug
|
||||
- What you think the program should be doing
|
||||
- Which programs you are using
|
||||
- Which operating system you are using, and which C compiler was used to
|
||||
compile the programs (or state that the pre-compiled versions were used).
|
||||
- If appropriate, any of the following:
|
||||
* source code (preferably cut down to a minimum that will still assemble
|
||||
and show the bug)
|
||||
* the output of rdfdump on produced modules (or send the module if the
|
||||
problem is in code generated)
|
||||
* exact descriptions of error messages/symptoms/etc
|
||||
|
||||
TODO
|
||||
====
|
||||
|
||||
There are still various things unimplemented that I would like to add.
|
||||
If you want to find out what these are, search near the top of each *.c
|
||||
file for a comment containing the word 'TODO'. A brief list is given here:
|
||||
|
||||
- Improve the performace of ldrdf (there are several enhancements I can think
|
||||
of that wouldn't be too hard to add)
|
||||
- Stop assuming that we're on a little endian machine
|
||||
- Make everything work with both formats (?)
|
||||
- Add extra functions to ldrdf (strip symbols/keep symbol list)
|
||||
- Check for more bugs
|
||||
|
||||
One last thing I have to say: good luck! Whatever it is that you want to use
|
||||
RDOFF for, I hope its a success. People out there are using it for many
|
||||
diverse applications, from operating system boot-loaders to loadable modules
|
||||
in games. Whatever your application is, I hope that it works, and that you
|
||||
have a good time writing it.
|
||||
|
||||
|
||||
|
||||
Julian Hall <jules@earthcorp.com>
|
||||
|
||||
95
rdoff/hash.c
Normal file
95
rdoff/hash.c
Normal 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
12
rdoff/hash.h
Normal 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);
|
||||
|
||||
1645
rdoff/ldrdf.c
1645
rdoff/ldrdf.c
File diff suppressed because it is too large
Load Diff
728
rdoff/ldrdf1.c
Normal file
728
rdoff/ldrdf1.c
Normal 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
55
rdoff/ldsegs.h
Normal 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); \
|
||||
} \
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
233
rdoff/rdfdump.c
233
rdoff/rdfdump.c
@@ -4,6 +4,8 @@
|
||||
|
||||
FILE *infile;
|
||||
|
||||
typedef unsigned short int16;
|
||||
|
||||
long translatelong(long in) { /* translate from little endian to
|
||||
local representation */
|
||||
long r;
|
||||
@@ -18,7 +20,7 @@ long translatelong(long in) { /* translate from little endian to
|
||||
return r;
|
||||
}
|
||||
|
||||
int translateshort(short in) {
|
||||
int translateshort(int16 in) {
|
||||
int r;
|
||||
unsigned char *i;
|
||||
|
||||
@@ -27,70 +29,136 @@ int translateshort(short in) {
|
||||
|
||||
return r;
|
||||
}
|
||||
void print_header(long length) {
|
||||
|
||||
void print_header(long length, int rdf_version) {
|
||||
char buf[129],t,s,l;
|
||||
unsigned char reclen;
|
||||
long o,ll;
|
||||
short rs;
|
||||
int16 rs;
|
||||
|
||||
while (length > 0) {
|
||||
fread(&t,1,1,infile);
|
||||
if (rdf_version >= 2) {
|
||||
fread(&reclen,1,1,infile);
|
||||
}
|
||||
switch(t) {
|
||||
case 1: /* relocation record */
|
||||
case 6: /* segment relocation */
|
||||
fread(&s,1,1,infile);
|
||||
fread(&o,4,1,infile);
|
||||
fread(&l,1,1,infile);
|
||||
fread(&rs,2,1,infile);
|
||||
printf(" relocation: location (%04x:%08lx), length %d, "
|
||||
"referred seg %04x\n",(int)s,translatelong(o),(int)l,
|
||||
printf(" %s: location (%04x:%08lx), length %d, "
|
||||
"referred seg %04x\n", t == 1 ? "relocation" : "seg relocation",
|
||||
(int)s,translatelong(o),(int)l,
|
||||
translateshort(rs));
|
||||
length -= 9;
|
||||
if (rdf_version >= 2 && reclen != 8)
|
||||
printf(" warning: reclen != 8\n");
|
||||
if (rdf_version == 1) length -= 9;
|
||||
if (rdf_version == 1 && t == 6)
|
||||
printf(" warning: seg relocation not supported in RDOFF1\n");
|
||||
break;
|
||||
case 2: /* import record */
|
||||
case 7: /* import far symbol */
|
||||
fread(&rs,2,1,infile);
|
||||
ll = 0;
|
||||
do {
|
||||
fread(&buf[ll],1,1,infile);
|
||||
} while (buf[ll++]);
|
||||
printf(" import: segment %04x = %s\n",translateshort(rs),buf);
|
||||
length -= ll + 3;
|
||||
|
||||
if (rdf_version == 1) {
|
||||
do {
|
||||
fread(&buf[ll],1,1,infile);
|
||||
} while (buf[ll++]);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (;ll < reclen - 2; ll++)
|
||||
fread(&buf[ll],1,1,infile);
|
||||
}
|
||||
|
||||
printf(" %simport: segment %04x = %s\n",t == 7 ? "far " : "",
|
||||
translateshort(rs),buf);
|
||||
if (rdf_version == 1) length -= ll + 3;
|
||||
if (rdf_version == 1 && t == 7)
|
||||
printf (" warning: far import not supported in RDOFF1\n");
|
||||
break;
|
||||
case 3: /* export record */
|
||||
fread(&s,1,1,infile);
|
||||
fread(&o,4,1,infile);
|
||||
ll = 0;
|
||||
do {
|
||||
fread(&buf[ll],1,1,infile);
|
||||
} while (buf[ll++]);
|
||||
|
||||
if (rdf_version == 1) {
|
||||
do {
|
||||
fread(&buf[ll],1,1,infile);
|
||||
} while (buf[ll++]);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (; ll < reclen - 5; ll ++)
|
||||
fread(&buf[ll],1,1,infile);
|
||||
}
|
||||
printf(" export: (%04x:%08lx) = %s\n",(int)s,translatelong(o),buf);
|
||||
length -= ll + 6;
|
||||
if (rdf_version == 1) length -= ll + 6;
|
||||
break;
|
||||
case 4: /* DLL record */
|
||||
ll = 0;
|
||||
do {
|
||||
fread(&buf[ll],1,1,infile);
|
||||
} while (buf[ll++]);
|
||||
|
||||
if (rdf_version == 1) {
|
||||
do {
|
||||
fread(&buf[ll],1,1,infile);
|
||||
} while (buf[ll++]);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (; ll < reclen - 1; ll++)
|
||||
fread(&buf[ll],1,1,infile);
|
||||
}
|
||||
printf(" dll: %s\n",buf);
|
||||
length -= ll + 1;
|
||||
if (rdf_version == 1) length -= ll + 1;
|
||||
break;
|
||||
case 5: /* BSS reservation */
|
||||
fread(&ll,4,1,infile);
|
||||
printf(" bss reservation: %08lx bytes\n",translatelong(ll));
|
||||
length -= 5;
|
||||
if (rdf_version == 1) length -= 5;
|
||||
if (rdf_version > 1 && reclen != 4)
|
||||
printf(" warning: reclen != 4\n");
|
||||
break;
|
||||
default:
|
||||
printf(" unrecognised record (type %d)\n",(int)t);
|
||||
length --;
|
||||
printf(" unrecognised record (type %d",(int)t);
|
||||
if (rdf_version > 1) printf(", length %d",(int)reclen);
|
||||
printf(")\n");
|
||||
if (rdf_version == 1) length --;
|
||||
}
|
||||
if (rdf_version != 1) length -= 2 + reclen;
|
||||
}
|
||||
}
|
||||
|
||||
char * knowntypes[8] = {"NULL", "text", "data", "object comment",
|
||||
"linked comment", "loader comment",
|
||||
"symbolic debug", "line number debug"};
|
||||
|
||||
char * translatesegmenttype(int16 type) {
|
||||
if (type < 8) return knowntypes[type];
|
||||
if (type < 0x0020) return "reserved";
|
||||
if (type < 0x1000) return "reserved - moscow";
|
||||
if (type < 0x8000) return "reserved - system dependant";
|
||||
if (type < 0xFFFF) return "reserved - other";
|
||||
if (type == 0xFFFF) return "invalid type code";
|
||||
return "type code out of range";
|
||||
}
|
||||
|
||||
int main(int argc,char **argv) {
|
||||
char id[7];
|
||||
long l;
|
||||
int16 s;
|
||||
int verbose = 0;
|
||||
long offset;
|
||||
int foundnullsegment = 0;
|
||||
int version;
|
||||
long segmentcontentlength = 0;
|
||||
int nsegments = 0;
|
||||
long headerlength = 0;
|
||||
long objectlength = 0;
|
||||
|
||||
puts("RDOFF Dump utility v1.1 (C) Copyright 1996 Julian R Hall");
|
||||
puts("RDOFF Dump utility v2.0 (C) Copyright 1996 Julian R Hall");
|
||||
|
||||
if (argc < 2) {
|
||||
fputs("Usage: rdfdump [-v] <filename>\n",stderr);
|
||||
@@ -121,46 +189,103 @@ int main(int argc,char **argv) {
|
||||
}
|
||||
|
||||
printf("File %s: RDOFF version %c\n\n",argv[1],id[5]);
|
||||
if (id[5] < '1' || id[5] > '1') {
|
||||
if (id[5] < '1' || id[5] > '2') {
|
||||
fprintf(stderr,"rdfdump: unknown RDOFF version '%c'\n",id[5]);
|
||||
exit(1);
|
||||
}
|
||||
version = id[5] - '0';
|
||||
|
||||
fread(&l,4,1,infile);
|
||||
l = translatelong(l);
|
||||
printf("Header (%ld bytes):\n",l);
|
||||
print_header(l);
|
||||
|
||||
fread(&l,4,1,infile);
|
||||
l = translatelong(l);
|
||||
printf("\nText segment length = %ld bytes\n",l);
|
||||
offset = 0;
|
||||
while(l--) {
|
||||
fread(id,1,1,infile);
|
||||
if (verbose) {
|
||||
if (offset % 16 == 0)
|
||||
printf("\n%08lx ", offset);
|
||||
printf(" %02x",(int) (unsigned char)id[0]);
|
||||
offset++;
|
||||
}
|
||||
if (version > 1) {
|
||||
fread(&l, 4, 1, infile);
|
||||
objectlength = translatelong(l);
|
||||
printf("Object content size: %ld bytes\n", objectlength);
|
||||
}
|
||||
if (verbose) printf("\n\n");
|
||||
|
||||
fread(&l,4,1,infile);
|
||||
l = translatelong(l);
|
||||
printf("Data segment length = %ld bytes\n",l);
|
||||
headerlength = translatelong(l);
|
||||
printf("Header (%ld bytes):\n",headerlength);
|
||||
print_header(headerlength, version);
|
||||
|
||||
if (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;
|
||||
|
||||
143
rdoff/rdflib.c
143
rdoff/rdflib.c
@@ -1,12 +1,22 @@
|
||||
/* rdflib - manipulate RDOFF library files (.rdl) */
|
||||
|
||||
/* an rdoff library is simply a sequence of RDOFF object files, each
|
||||
preceded by the name of the module, an ASCII string of up to 255
|
||||
characters, terminated by a zero. There may be an optional
|
||||
directory placed on the end of the file. The format of the
|
||||
directory will be 'RDL' followed by a version number, followed by
|
||||
the length of the directory, and then the directory, the format of
|
||||
which has not yet been designed. */
|
||||
/*
|
||||
* an rdoff library is simply a sequence of RDOFF object files, each
|
||||
* preceded by the name of the module, an ASCII string of up to 255
|
||||
* characters, terminated by a zero.
|
||||
*
|
||||
* There may be an optional
|
||||
* directory placed on the end of the file. The format of the
|
||||
* directory will be 'RDLDD' followed by a version number, followed by
|
||||
* the length of the directory, and then the directory, the format of
|
||||
* which has not yet been designed. The module name of the directory
|
||||
* must be '.dir'.
|
||||
*
|
||||
* All module names beginning with '.' are reserved
|
||||
* for possible future extensions. The linker ignores all such modules,
|
||||
* assuming they have the format of a six byte type & version identifier
|
||||
* followed by long content size, followed by data.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
@@ -15,7 +25,7 @@
|
||||
/* functions supported:
|
||||
create a library (no extra operands required)
|
||||
add a module from a library (requires filename and name to give mod.)
|
||||
remove a module from a library (requires given name)
|
||||
remove a module from a library (requires given name) (not implemented)
|
||||
extract a module from the library (requires given name and filename)
|
||||
list modules */
|
||||
|
||||
@@ -25,7 +35,7 @@ const char *usage =
|
||||
" where x is one of:\n"
|
||||
" c - create library\n"
|
||||
" a - add module (operands = filename module-name)\n"
|
||||
" r - remove (module-name)\n"
|
||||
" r - remove (module-name) [not implemented]\n"
|
||||
" x - extract (module-name filename)\n"
|
||||
" t - list\n";
|
||||
|
||||
@@ -48,26 +58,27 @@ static void longtolocal(long * l)
|
||||
#endif
|
||||
}
|
||||
|
||||
void copybytes(FILE *fp, FILE *fp2, int n)
|
||||
char copybytes(FILE *fp, FILE *fp2, int n)
|
||||
{
|
||||
int i,t;
|
||||
int i, t = 0;
|
||||
|
||||
for (i = 0 ; i < n; i++ )
|
||||
{
|
||||
t = fgetc(fp);
|
||||
if (t == EOF)
|
||||
{
|
||||
fprintf(stderr,"ldrdf: premature end of file in '%s'\n",
|
||||
fprintf(stderr,"rdflib: premature end of file in '%s'\n",
|
||||
_argv[2]);
|
||||
exit(1);
|
||||
}
|
||||
if (fp2)
|
||||
if (fputc(t, fp2) == EOF)
|
||||
{
|
||||
fprintf(stderr,"ldrdf: write error\n");
|
||||
fprintf(stderr,"rdflib: write error\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
return (char) t; /* return last char read */
|
||||
}
|
||||
|
||||
long copylong(FILE *fp, FILE *fp2)
|
||||
@@ -82,14 +93,14 @@ long copylong(FILE *fp, FILE *fp2)
|
||||
t = fgetc(fp);
|
||||
if (t == EOF)
|
||||
{
|
||||
fprintf(stderr,"ldrdf: premature end of file in '%s'\n",
|
||||
fprintf(stderr,"rdflib: premature end of file in '%s'\n",
|
||||
_argv[2]);
|
||||
exit(1);
|
||||
}
|
||||
if (fp2)
|
||||
if (fputc(t, fp2) == EOF)
|
||||
{
|
||||
fprintf(stderr,"ldrdf: write error\n");
|
||||
fprintf(stderr,"rdflib: write error\n");
|
||||
exit(1);
|
||||
}
|
||||
*p++ = t;
|
||||
@@ -101,8 +112,9 @@ long copylong(FILE *fp, FILE *fp2)
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
FILE *fp, *fp2;
|
||||
char *p, buf[256];
|
||||
char *p, buf[256], c;
|
||||
int i;
|
||||
long l;
|
||||
|
||||
_argv = argv;
|
||||
|
||||
@@ -117,8 +129,8 @@ int main(int argc, char **argv)
|
||||
case 'c': /* create library */
|
||||
fp = fopen(argv[2],"wb");
|
||||
if (! fp) {
|
||||
fprintf(stderr,"ldrdf: could not open '%s'\n",argv[2]);
|
||||
perror("ldrdf");
|
||||
fprintf(stderr,"rdflib: could not open '%s'\n",argv[2]);
|
||||
perror("rdflib");
|
||||
exit(1);
|
||||
}
|
||||
fclose(fp);
|
||||
@@ -126,29 +138,29 @@ int main(int argc, char **argv)
|
||||
|
||||
case 'a': /* add module */
|
||||
if (argc < 5) {
|
||||
fprintf(stderr,"ldrdf: required parameter missing\n");
|
||||
fprintf(stderr,"rdflib: required parameter missing\n");
|
||||
exit(1);
|
||||
}
|
||||
fp = fopen(argv[2],"ab");
|
||||
if (! fp)
|
||||
{
|
||||
fprintf(stderr,"ldrdf: could not open '%s'\n",argv[2]);
|
||||
perror("ldrdf");
|
||||
fprintf(stderr,"rdflib: could not open '%s'\n",argv[2]);
|
||||
perror("rdflib");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
fp2 = fopen(argv[3],"rb");
|
||||
if (! fp)
|
||||
{
|
||||
fprintf(stderr,"ldrdf: could not open '%s'\n",argv[3]);
|
||||
perror("ldrdf");
|
||||
fprintf(stderr,"rdflib: could not open '%s'\n",argv[3]);
|
||||
perror("rdflib");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
p = argv[4];
|
||||
do {
|
||||
if ( fputc(*p,fp) == EOF ) {
|
||||
fprintf(stderr,"ldrdf: write error\n");
|
||||
fprintf(stderr,"rdflib: write error\n");
|
||||
exit(1);
|
||||
}
|
||||
} while (*p++);
|
||||
@@ -160,7 +172,7 @@ int main(int argc, char **argv)
|
||||
}
|
||||
|
||||
if ( fputc(i, fp) == EOF ) {
|
||||
fprintf(stderr,"ldrdf: write error\n");
|
||||
fprintf(stderr,"rdflib: write error\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
@@ -170,15 +182,19 @@ int main(int argc, char **argv)
|
||||
|
||||
case 'x':
|
||||
if (argc < 5) {
|
||||
fprintf(stderr,"ldrdf: required parameter missing\n");
|
||||
fprintf(stderr,"rdflib: required parameter missing\n");
|
||||
exit(1);
|
||||
}
|
||||
case 't':
|
||||
if (argc < 3) {
|
||||
fprintf(stderr, "rdflib: required paramenter missing\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
fp = fopen(argv[2],"rb");
|
||||
if (! fp)
|
||||
{
|
||||
fprintf(stderr,"ldrdf: could not open '%s'\n",argv[2]);
|
||||
perror("ldrdf");
|
||||
fprintf(stderr,"rdflib: could not open '%s'\n",argv[2]);
|
||||
perror("rdflib");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@@ -191,25 +207,60 @@ int main(int argc, char **argv)
|
||||
|
||||
if (feof(fp)) break;
|
||||
|
||||
/* check against desired name */
|
||||
if (! strcmp(buf,argv[3]) )
|
||||
{
|
||||
fp2 = fopen(argv[4],"wb");
|
||||
if (! fp2)
|
||||
fp2 = NULL;
|
||||
if (argv[1][0] == 'x') {
|
||||
/* check against desired name */
|
||||
if (! strcmp(buf,argv[3]) )
|
||||
{
|
||||
fprintf(stderr,"ldrdf: could not open '%s'\n", argv[4]);
|
||||
perror("ldrdf");
|
||||
exit(1);
|
||||
fp2 = fopen(argv[4],"wb");
|
||||
if (! fp2)
|
||||
{
|
||||
fprintf(stderr,"rdflib: could not open '%s'\n",argv[4]);
|
||||
perror("rdflib");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
fp2 = NULL;
|
||||
printf("%-40s ", buf);
|
||||
|
||||
/* step over the RDOFF file, 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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
211
rdoff/rdlib.c
211
rdoff/rdlib.c
@@ -1,22 +1,113 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "rdoff.h"
|
||||
#include "rdlib.h"
|
||||
|
||||
/*
|
||||
* format of rdoff library files:
|
||||
* repeat
|
||||
* null terminated module name (max 255 chars)
|
||||
* RDOFF module
|
||||
* until eof
|
||||
*/
|
||||
|
||||
/*
|
||||
* TODO
|
||||
*
|
||||
* No support exists yet for special modules. But we aren't using
|
||||
* any special modules yet. They are only defined now so that their
|
||||
* existance doesn't break older versions of the linker... presently
|
||||
* anything whose name begins with '.' is ignored.
|
||||
*/
|
||||
|
||||
int rdl_error = 0;
|
||||
|
||||
char *rdl_errors[3] = {
|
||||
char *rdl_errors[5] = {
|
||||
"no error","could not open file", "invalid file structure",
|
||||
"file contains modules of an unsupported RDOFF version",
|
||||
"module not found"
|
||||
};
|
||||
int rdl_verify(const char * filename)
|
||||
{
|
||||
FILE * fp = fopen(filename, "rb");
|
||||
char buf[257];
|
||||
int i;
|
||||
long length;
|
||||
static char lastverified[256];
|
||||
static int lastresult = -1;
|
||||
|
||||
if (lastresult != -1 && !strcmp(filename, lastverified))
|
||||
return lastresult;
|
||||
|
||||
strcpy(lastverified, filename);
|
||||
|
||||
if (!fp)
|
||||
return (rdl_error = lastresult = 1);
|
||||
|
||||
while (!feof(fp))
|
||||
{
|
||||
i = 0;
|
||||
|
||||
while (fread(buf + i,1,1,fp) == 1 && buf[i] && i < 257)
|
||||
i++;
|
||||
if (feof(fp)) break;
|
||||
|
||||
fread(buf, 6, 1, fp);
|
||||
buf[6] = 0;
|
||||
if (buf[0] == '.') {
|
||||
/*
|
||||
* a special module, eg a directory.
|
||||
* Format of such a module is defined to be:
|
||||
* six char type identifier (which we've already read)
|
||||
* long count bytes content
|
||||
* content
|
||||
* so we can handle it uniformaly with RDOFF2 modules...
|
||||
* do nothing here. :-)
|
||||
*/
|
||||
}
|
||||
else if (strncmp(buf, "RDOFF", 5)) {
|
||||
return rdl_error = lastresult = 2;
|
||||
}
|
||||
else if (buf[5] != '2') {
|
||||
return rdl_error = lastresult = 3;
|
||||
}
|
||||
|
||||
fread(&length, 4, 1, fp);
|
||||
fseek(fp, length, SEEK_CUR); /* skip over the module */
|
||||
}
|
||||
fclose(fp);
|
||||
return lastresult = 0; /* library in correct format */
|
||||
}
|
||||
|
||||
int rdl_open (struct librarynode * lib, const char * name)
|
||||
{
|
||||
int i = rdl_verify(name);
|
||||
if (i) return i;
|
||||
|
||||
lib->fp = NULL;
|
||||
lib->name = strdup(name);
|
||||
lib->referenced = 0;
|
||||
lib->next = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void rdl_close (struct librarynode * lib)
|
||||
{
|
||||
if (lib->fp)
|
||||
fclose(lib->fp);
|
||||
free(lib->name);
|
||||
}
|
||||
|
||||
int rdl_searchlib (struct librarynode * lib,
|
||||
const char * label, rdffile * f)
|
||||
{
|
||||
char buf[257];
|
||||
int i;
|
||||
char buf[512];
|
||||
int i, t;
|
||||
void * hdr;
|
||||
rdfheaderrec * r;
|
||||
long l;
|
||||
|
||||
rdl_error = 0;
|
||||
lib->referenced ++;
|
||||
@@ -35,18 +126,36 @@ int rdl_searchlib (struct librarynode * lib,
|
||||
|
||||
while (! feof(lib->fp) )
|
||||
{
|
||||
i = 1;
|
||||
while (fread(buf + i,1,1,lib->fp) == 1 && buf[i] && i < 257)
|
||||
/*
|
||||
* read the module name from the file, and prepend
|
||||
* the library name and '.' to it.
|
||||
*/
|
||||
strcpy(buf, lib->name);
|
||||
|
||||
i = strlen(lib->name);
|
||||
buf[i++] = '.'; t = i;
|
||||
while (fread(buf + i,1,1,lib->fp) == 1 && buf[i] && i < 512)
|
||||
i++;
|
||||
buf[0] = ':';
|
||||
|
||||
buf[i] = 0;
|
||||
|
||||
if (feof(lib->fp)) break;
|
||||
|
||||
if (!strcmp(buf + t, ".dir")) /* skip over directory */
|
||||
{
|
||||
fread (&l, 4, 1, lib->fp);
|
||||
fseek (lib->fp, l, SEEK_CUR);
|
||||
continue;
|
||||
}
|
||||
/*
|
||||
* open the RDOFF module
|
||||
*/
|
||||
if ( rdfopenhere(f,lib->fp,&lib->referenced,buf) ) {
|
||||
rdl_error = 2;
|
||||
rdl_error = 16 * rdf_errno;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* read in the header, and scan for exported symbols
|
||||
*/
|
||||
hdr = malloc(f->header_len);
|
||||
rdfloadseg(f,RDOFF_HEADER,hdr);
|
||||
|
||||
@@ -65,11 +174,14 @@ int rdl_searchlib (struct librarynode * lib,
|
||||
}
|
||||
|
||||
/* find start of next module... */
|
||||
i = f->data_ofs + f->data_len;
|
||||
i = f->eof_offset;
|
||||
rdfclose(f);
|
||||
fseek(lib->fp,i,SEEK_SET);
|
||||
}
|
||||
|
||||
/*
|
||||
* close the file if nobody else is using it
|
||||
*/
|
||||
lib->referenced --;
|
||||
if (! lib->referenced)
|
||||
{
|
||||
@@ -79,9 +191,86 @@ int rdl_searchlib (struct librarynode * lib,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rdl_openmodule (struct librarynode * lib, int moduleno, rdffile * f)
|
||||
{
|
||||
char buf[512];
|
||||
int i, cmod, t;
|
||||
long length;
|
||||
|
||||
lib->referenced++;
|
||||
|
||||
if (!lib->fp)
|
||||
{
|
||||
lib->fp = fopen(lib->name, "rb");
|
||||
if (!lib->fp) {
|
||||
lib->referenced--;
|
||||
return (rdl_error = 1);
|
||||
}
|
||||
}
|
||||
else
|
||||
rewind(lib->fp);
|
||||
|
||||
cmod = -1;
|
||||
while (!feof(lib->fp))
|
||||
{
|
||||
strcpy(buf, lib->name);
|
||||
i = strlen(buf);
|
||||
buf[i++] = '.'; t = i;
|
||||
while (fread(buf + i,1,1,lib->fp) == 1 && buf[i] && i < 512)
|
||||
i++;
|
||||
buf[i] = 0;
|
||||
if (feof(lib->fp)) break;
|
||||
|
||||
if (buf[t] != '.') /* special module - not counted in the numbering */
|
||||
cmod++; /* of RDOFF modules - must be referred to by name */
|
||||
|
||||
if (cmod == moduleno) {
|
||||
rdl_error = 16 *
|
||||
rdfopenhere(f, lib->fp, &lib->referenced, buf);
|
||||
lib->referenced--;
|
||||
if (!lib->referenced) {
|
||||
fclose(lib->fp);
|
||||
lib->fp = NULL;
|
||||
}
|
||||
return rdl_error;
|
||||
}
|
||||
|
||||
fread(buf, 6, 1, lib->fp);
|
||||
buf[6] = 0;
|
||||
if (buf[t] == '.') {
|
||||
/* do nothing */
|
||||
}
|
||||
else if (strncmp(buf, "RDOFF", 5)) {
|
||||
if (! --lib->referenced) {
|
||||
fclose(lib->fp);
|
||||
lib->fp = NULL;
|
||||
}
|
||||
return rdl_error = 2;
|
||||
}
|
||||
else if (buf[5] != '2') {
|
||||
if (! --lib->referenced) {
|
||||
fclose(lib->fp);
|
||||
lib->fp = NULL;
|
||||
}
|
||||
return rdl_error = 3;
|
||||
}
|
||||
|
||||
fread(&length, 4, 1, lib->fp);
|
||||
fseek(lib->fp, length, SEEK_CUR); /* skip over the module */
|
||||
}
|
||||
if (! --lib->referenced) {
|
||||
fclose(lib->fp);
|
||||
lib->fp = NULL;
|
||||
}
|
||||
return rdl_error = 4; /* module not found */
|
||||
}
|
||||
|
||||
void rdl_perror(const char *apname, const char *filename)
|
||||
{
|
||||
fprintf(stderr,"%s:%s:%s\n",apname,filename,rdl_errors[rdl_error]);
|
||||
if (rdl_error >= 16)
|
||||
rdfperror(apname, filename);
|
||||
else
|
||||
fprintf(stderr,"%s:%s:%s\n",apname,filename,rdl_errors[rdl_error]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
|
||||
364
rdoff/rdoff.c
364
rdoff/rdoff.c
@@ -4,11 +4,19 @@
|
||||
* Julian Hall. All rights reserved. The software is
|
||||
* redistributable under the licence given in the file "Licence"
|
||||
* distributed in the NASM archive.
|
||||
*
|
||||
* Permission to use this file in your own projects is granted, as long
|
||||
* as acknowledgement is given in an appropriate manner to its authors,
|
||||
* with instructions of how to obtain a copy via ftp.
|
||||
*/
|
||||
|
||||
/* TODO: The functions in this module assume they are running
|
||||
* on a little-endian machine. This should be fixed to
|
||||
* make it portable.
|
||||
*
|
||||
* This module no longer supports RDOFF1. If anybody *really*
|
||||
* needs the functionality of supporting both types at the
|
||||
* same time, I'll add it back in.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
@@ -22,115 +30,146 @@
|
||||
#define newstrcat(s1,s2) strcat(strcpy(malloc(strlen(s1) + strlen(s2) + 1), \
|
||||
s1),s2)
|
||||
|
||||
/*
|
||||
* Comment this out to allow the module to read & write header record types
|
||||
* that it isn't aware of. With this defined, unrecognised header records
|
||||
* will generate error number 8, reported as 'unknown extended header record'.
|
||||
*/
|
||||
|
||||
#define STRICT_ERRORS
|
||||
|
||||
/* ========================================================================
|
||||
* Code for memory buffers (for delayed writing of header until we know
|
||||
* how long it is).
|
||||
* ======================================================================== */
|
||||
|
||||
|
||||
memorybuffer * newmembuf(){
|
||||
memorybuffer * t;
|
||||
memorybuffer * newmembuf()
|
||||
{
|
||||
memorybuffer * t;
|
||||
|
||||
t = malloc(sizeof(memorybuffer));
|
||||
t = malloc(sizeof(memorybuffer));
|
||||
|
||||
t->length = 0;
|
||||
t->next = NULL;
|
||||
return t;
|
||||
t->length = 0;
|
||||
t->next = NULL;
|
||||
return t;
|
||||
}
|
||||
|
||||
void membufwrite(memorybuffer *b, void *data, int bytes) {
|
||||
int16 w;
|
||||
long l;
|
||||
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 *)∈
|
||||
r = i[3];
|
||||
r = (r << 8) + i[2];
|
||||
r = (r << 8) + i[1];
|
||||
r = (r << 8) + *i;
|
||||
i = (unsigned char *)∈
|
||||
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 *)∈
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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
142
rdoff/segtab.c
Normal 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
7
rdoff/segtab.h
Normal 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);
|
||||
|
||||
139
rdoff/symtab.c
139
rdoff/symtab.c
@@ -1,4 +1,6 @@
|
||||
/* symtab.c Routines to maintain and manipulate a symbol table
|
||||
/* symtab.c Routines to maintain and manipulate a symbol table
|
||||
*
|
||||
* These routines donated to the NASM effort by Graeme Defty.
|
||||
*
|
||||
* The Netwide Assembler is copyright (C) 1996 Simon Tatham and
|
||||
* Julian Hall. All rights reserved. The software is
|
||||
@@ -7,74 +9,117 @@
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <malloc.h>
|
||||
|
||||
#include "symtab.h"
|
||||
#include "hash.h"
|
||||
|
||||
/* TODO: Implement a hash table, not this stupid implementation which
|
||||
is too slow to be of practical use */
|
||||
#define SYMTABSIZE 64
|
||||
#define slotnum(x) (hash((x)) % SYMTABSIZE)
|
||||
|
||||
/* ------------------------------------- */
|
||||
/* Private data types */
|
||||
|
||||
typedef struct tagSymtab {
|
||||
symtabEnt ent;
|
||||
struct tagSymtab * next;
|
||||
} symtabList;
|
||||
typedef struct tagSymtabNode {
|
||||
struct tagSymtabNode * next;
|
||||
symtabEnt ent;
|
||||
} symtabNode;
|
||||
|
||||
typedef 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");
|
||||
}
|
||||
|
||||
@@ -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
20
rdoff/test/rdfseg.asm
Normal 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
12
rdoff/test/rdfseg2.asm
Normal 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
5
rdoff/v1/README
Normal 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
40
rdoff/v1/collectn.c
Normal 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
22
rdoff/v1/collectn.h
Normal 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
728
rdoff/v1/ldrdf.c
Normal 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
125
rdoff/v1/rdf2bin.c
Normal 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
167
rdoff/v1/rdfdump.c
Normal 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 *)∈
|
||||
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 *)∈
|
||||
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
235
rdoff/v1/rdflib.c
Normal 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
173
rdoff/v1/rdfload.c
Normal 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
29
rdoff/v1/rdfload.h
Normal 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
88
rdoff/v1/rdlib.c
Normal 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
18
rdoff/v1/rdlib.h
Normal 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
397
rdoff/v1/rdoff.c
Normal 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 *)∈
|
||||
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
118
rdoff/v1/rdoff.h
Normal 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
61
rdoff/v1/rdx.c
Normal 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
80
rdoff/v1/symtab.c
Normal 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
22
rdoff/v1/symtab.h
Normal 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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user