--- /dev/null
+PLATFORM = 6809
+CC = m6809-unknown-gcc
+# These are wrappers for lwasm and lwar
+ASM = m6809-unknown-as
+AR = m6809-unknown-ar
+LINKER = lwlink
+CFLAGS = -I../../Library/include -I../../Library/include/6502 -Wall -pedantic -fno-strict-aliasing
+COPT = -Os
+LINKER_OPT = --format=raw -L../../Library/libs -lc6809
+LIBGCCDIR = $(dir $(shell $(CC) -print-libgcc-file-name))
+LINKER_OPT += -L$(LIBGCCDIR) -lgcc -m ld09.map
+LINKER_OPT += --script=../util/$(TARGET).link
+ASM_OPT = -o
+CRT0 = ../../Library/libs/crt0_6809.o
+
+LIBDIR =/usr/bin
+LDFLAGS =
+
+# Will need some of these if you want native executables on non-Linux/i386
+# -DDETECTAOUT # Turn on detection.
+# -DV7_A_OUT # a.out.h is like V7
+# -DBSD_A_OUT # a.out.h is like BSD
+# -DSTANDARD_GNU_A_OUT # a.out.h is like GNU normal.
+#
+# -DREL_OUTPUT -DBUGCOMPAT # -r Produces weird *.o files.
+#
+DEFS =-DREL_OUTPUT
+
+# An alternative file for a non-standard a.out.h (eg i386 linux on an Alpha)
+#
+# NATIVE=-DA_OUT_INCL='"a_out_local.h"'
+
+OBJS= dumps.o io.o ld.o readobj.o table.o typeconv.o linksyms.o mkar.o \
+ writebin.o writeemu.o
+
+all: ld09 objchop
+
+ld09: $(OBJS)
+ $(LINKER) -o $@ $(LINKER_OPT) $(CRT0) $(OBJS)
+
+objchop: objchop.o
+ $(LINKER) -o $@ $(LINKER_OPT) $(CRT0) $(OBJS)
+
+clean realclean clobber:
+ rm -f *.o ld09 ld09r objchop catimage objdump09 *~
+
+$(OBJS): align.h ar.h bindef.h byteord.h config.h const.h globvar.h obj.h \
+ syshead.h type.h x86_aout.h
+
+ar.h:
+ test -f ar.h || \
+ { rm -f ar.h ; ln -s ../libc/include/ar.h . ; } || \
+ ln ../libc/include/ar.h .
+
+writebin.o: writebin.c
+ $(CC) $(CFLAGS) $(DEFS) $(NATIVE) -c $<
+
+writerel.o: writebin.c
+
+.c.o:
+ $(CC) $(COPT) $(CFLAGS) $(DEFS) -c $< -o $@
--- /dev/null
+/* align.h - memory alignment requirements for linker */
+
+/* Copyright (C) 1994 Bruce Evans */
+
+#ifndef S_ALIGNMENT
+# define align(x)
+#else
+
+#if defined(__STDC__) && defined(_POSIX_SOURCE)
+# define align(x) ((x)=(void *) \
+ (((ssize_t)(x) + (S_ALIGNMENT-1)) & ~(S_ALIGNMENT-1)))
+#else
+# define align(x) ((x)=(void *) \
+ ((char *)(x) + ((S_ALIGNMENT-(char)(x)) & (S_ALIGNMENT-1))))
+#endif
+#endif
+
+
+
+
+
+
+
--- /dev/null
+#ifndef __AR_H
+#define __AR_H
+
+#define ARMAG "!<arch>\n"
+#define SARMAG 8
+#define ARFMAG "`\n"
+
+struct ar_hdr {
+ char ar_name[16],
+ ar_date[12],
+ ar_uid[6],
+ ar_gid[6],
+ ar_mode[8],
+ ar_size[10],
+ ar_fmag[2];
+};
+
+#endif /* __AR_H */
--- /dev/null
+
+/* Only do native on Linux/i386 by default -- it's safer. */
+#ifndef DETECTAOUT
+#if defined(__i386__) && defined(__linux__)
+#define DETECTAOUT
+#else
+# ifdef A_OUT_INCL
+# define DETECTAOUT
+# endif
+#endif
+#endif
+
+#ifdef DETECTAOUT
+/* Ok, I'm just gonna make it simple ... override this if you like. */
+#ifndef A_OUT_INCL
+#define A_OUT_INCL <a.out.h>
+#endif
+
+#include A_OUT_INCL
+
+/* Try and guess type ... */
+#ifndef V7_A_OUT
+#ifndef BSD_A_OUT
+#ifndef STANDARD_GNU_A_OUT
+
+# ifndef C_EXT
+# define BSD_A_OUT
+# endif
+
+/* Not sure about this one ... it works here ... */
+# if defined(BSD_A_OUT) && defined(N_MAGIC)
+# define STANDARD_GNU_A_OUT
+# endif
+
+#endif
+#endif
+#endif
+
+/* General specs as to how it works ... */
+# ifdef BSD_A_OUT
+# ifdef STANDARD_GNU_A_OUT
+# define RELOC_INFO_SIZE 8 /* unportable bitfields - bcc doesn't pack */
+# else
+# define RELOC_INFO_SIZE (sizeof (struct relocation_info))
+# endif
+# ifdef N_EXT
+# define C_EXT N_EXT
+# endif
+# define C_STAT 0
+# define n_was_name n_un.n_name
+# define n_was_numaux n_other
+# define n_was_other n_numaux
+# define n_was_sclass n_type
+# define n_was_strx n_un.n_strx
+# define n_was_type n_desc
+# else /* not BSD_A_OUT */
+# define RELOC_INFO_SIZE (sizeof (struct reloc))
+# define n_was_name n_name
+# define n_was_numaux n_numaux
+# define n_was_other n_other
+# define n_was_sclass n_sclass
+# define n_was_strx n_value
+# define n_was_type n_type
+# endif /* BSD_A_OUT */
+
+/* And finally make sure it worked */
+#if defined(A_MINHDR) || defined(BSD_A_OUT)
+#if defined(C_EXT) && defined(C_STAT) && !defined(SCNHSZ)
+
+#define AOUT_DETECTED 1
+
+#endif
+#endif
+
+#endif /* NO_AOUT */
--- /dev/null
+/* byteord.h - byte order dependencies for C compiler, assembler, linker */
+
+/* Copyright (C) 1994 Bruce Evans */
+
+/* These are for the targets of everything and for linker source too. */
+
+#ifdef I8086
+# define INT_BIG_ENDIAN 0
+# define LONG_BIG_ENDIAN 0 /* except longs are back to front for Xenix */
+#endif
+
+#ifdef I80386
+# define INT_BIG_ENDIAN 0
+# define LONG_BIG_ENDIAN 0
+#endif
+
+#ifdef MC6809
+# define INT_BIG_ENDIAN 1 /* byte order in words is high-low */
+# define LONG_BIG_ENDIAN 1 /* byte order in longs is high-low */
+#endif
--- /dev/null
+/*
+ * This program concatenates memory images the executables specified
+ * on it's command line.
+ *
+ * The 'boot' image must have a symbol table any symbols that match
+ * the below patterns have their values patched.
+ *
+ * int __seg0_text; - Always zero
+ * int __seg0_data; - Segment offset of data of boot executable
+ *
+ * int __seg1_text; - Segment offset of text of first executable
+ * int __seg1_data; - Segment offset of data of first executable
+ * int __seg2_text; - Segment offset of text of second executable
+ * int __seg2_data; - Segment offset of data of second executable
+ *
+ * int __seg9_text; - Segment offset of text of executable nine
+ * int __seg9_data; - Segment offset of data of executable nine
+ *
+ * Any segment that's not an exact multiple of 16 bytes long is rounded up.
+ *
+ */
+
+#include <stdio.h>
+#ifdef __STDC__
+#include <unistd.h>
+#include <stdlib.h>
+#endif
+#include "x86_aout.h"
+
+#ifndef __OUT_OK
+#error "Compile error: struct exec invalid (long not 32 bit ?)"
+#endif
+
+unsigned long text_offt[10]; /* Locations to patch (0=don't) */
+unsigned long data_offt[10];
+
+char * input_file = "";
+FILE * ofd;
+FILE * ifd = 0;
+struct exec header;
+
+main(argc, argv)
+int argc;
+char ** argv;
+{
+ long image_offset, text_off;
+ int image_id;
+
+ if( argc < 3 || argc > 11 )
+ fatal("Usage: catimage mem.bin boot.out [a1.out] ... [a9.out]");
+
+ open_obj(argv[2]);
+
+ ofd = fopen(argv[1], "w");
+ if( ofd == 0 ) fatal("Cannot open output file");
+
+ read_symtable();
+
+ image_offset = 0;
+
+ for(image_id=0; image_id < argc-2; image_id++)
+ {
+ open_obj(argv[image_id+2]);
+
+ printf("File %-14s seg=0x%04lx text=0x%04lx data=0x%04lx\n",
+ input_file, (image_offset>>4),
+ (header.a_text>>4), (header.a_total>>4));
+
+ text_off = image_offset;
+ if( header.a_flags & A_SEP )
+ {
+ copy_segment(image_offset, A_TEXTPOS(header), header.a_text);
+ image_offset += header.a_text;
+ image_offset = ((image_offset+15L)&-16L);
+
+ copy_segment(image_offset, A_DATAPOS(header), header.a_data);
+ }
+ else
+ {
+ copy_segment(image_offset, A_TEXTPOS(header),
+ header.a_text+header.a_data);
+ }
+
+ patch_bin(text_offt[image_id], (unsigned)(text_off>>4));
+ patch_bin(data_offt[image_id], (unsigned)(image_offset>>4));
+
+ image_offset += header.a_total;
+ image_offset = ((image_offset+15L)&-16L);
+ }
+
+ if( fseek(ofd, image_offset-1, 0) < 0 )
+ fatal("Cannot seek to end of output");
+
+ fputc('\0', ofd);
+ fclose(ofd);
+
+ printf("Output file size %ldKb\n", ((image_offset+0x3FF)>>10));
+
+ if( ifd ) fclose(ifd);
+ exit(0);
+}
+
+open_obj(fname)
+char * fname;
+{
+ input_file = fname;
+
+ if( ifd ) fclose(ifd);
+
+ ifd = fopen(fname, "r");
+ if( ifd == 0 ) fatal("Cannot open input file");
+
+ if( fread(&header, A_MINHDR, 1, ifd) != 1 )
+ fatal("Incomplete executable header");
+
+ if( BADMAG(header) )
+ fatal("Input file has bad magic number");
+}
+
+copy_segment(out_offset, in_offset, length)
+long out_offset, in_offset, length;
+{
+ char buffer[1024];
+ int ssize;
+ long bsize = length;
+
+ if( fseek(ifd, in_offset, 0) < 0 )
+ fatal("Cannot seek to start of input segment");
+
+ if( fseek(ofd, out_offset, 0) < 0 )
+ fatal("Cannot seek to start of output segment");
+
+ while(bsize>0)
+ {
+ if( bsize > sizeof(buffer) ) ssize = sizeof(buffer);
+ else ssize = bsize;
+
+ if( (ssize=fread(buffer, 1, ssize, ifd)) <= 0 )
+ fatal("Error reading segment from executable");
+ if( fwrite(buffer, 1, ssize, ofd) != ssize )
+ fatal("Error writing output file");
+ bsize -= ssize;
+ }
+}
+
+patch_bin(file_off, value)
+long file_off;
+int value;
+{
+ char wbuf[4];
+ if( file_off > 0 )
+ {
+ printf("Patch at offset 0x%05lx = %04x\n", file_off, value);
+
+ wbuf[0] = value;
+ wbuf[0] = (value>>8);
+
+ if( fseek(ofd, file_off, 0) < 0 )
+ fatal("Cannot seek to patch binary");
+
+ if( fwrite(wbuf, 1, 2, ofd) != 2 )
+ fatal("Error patching output file");
+ }
+}
+
+read_symtable()
+{
+ struct nlist item;
+ int nitems;
+ long base_off = 0;
+
+ if( header.a_syms == 0 )
+ fatal("Input file has been stripped!");
+
+ if( fseek(ifd, A_SYMPOS(header), 0) < 0 )
+ fatal("Cannot seek to start of symbols");
+
+ nitems = header.a_syms;
+
+ /* Foreach symbol */
+ while( fread(&item, sizeof(struct nlist), 1, ifd) == 1 )
+ {
+ if( nitems-- <= 0 ) break;
+
+ /* Match the name */
+ if( memcmp(item.n_name, "__seg", 5) != 0 || item.n_name[6] != '_' )
+ continue;
+
+ /* Externals only */
+ if( (item.n_sclass & N_CLASS) != C_EXT )
+ continue;
+
+ /* Data seg only */
+ if( (item.n_sclass & N_SECT) != N_DATA &&
+ (item.n_sclass & N_SECT) != N_BSS &&
+ (item.n_sclass & N_SECT) != N_TEXT )
+ continue;
+
+ if( item.n_name[5] < '0' || item.n_name[5] > '9' )
+ continue;
+
+ if( (header.a_flags & A_SEP) && (item.n_sclass & N_SECT) != N_TEXT )
+ base_off = header.a_text;
+ else
+ base_off = 0;
+
+ switch( item.n_name[7] )
+ {
+ case 'd': data_offt[item.n_name[5]-'0'] = base_off+item.n_value; break;
+ case 't': text_offt[item.n_name[5]-'0'] = base_off+item.n_value; break;
+ }
+
+#ifdef DEBUG
+ printf("%-8.8s ", item.n_name);
+ printf("%08lx ", item.n_value);
+ switch(item.n_sclass & N_CLASS)
+ {
+ case C_NULL: printf("C_NULL "); break;
+ case C_EXT: printf("C_EXT "); break;
+ case C_STAT: printf("C_STAT "); break;
+ default: printf("%-6d ", (item.n_sclass & N_CLASS)); break;
+ }
+ switch(item.n_sclass & N_SECT)
+ {
+ case N_UNDF: printf("N_UNDF "); break;
+ case N_ABS : printf("N_ABS "); break;
+ case N_TEXT: printf("N_TEXT "); break;
+ case N_DATA: printf("N_DATA "); break;
+ case N_BSS : printf("N_BSS "); break;
+ case N_COMM: printf("N_COMM "); break;
+ }
+ printf("\n");
+#endif
+ }
+}
+
+fatal(str)
+char * str;
+{
+ fprintf(stderr, "catimage:%s: %s\n", input_file, str);
+ exit(2);
+}
+
--- /dev/null
+/* config.h - configuration for linker */
+
+/* Copyright (C) 1994 Bruce Evans */
+
+/* one of these target processors must be defined */
+
+#undef I8086 /* Intel 8086 */
+#undef I80386 /* Intel 80386 */
+#define MC6809 /* Motorola 6809 */
+
+/* one of these target operating systems must be defined */
+
+#define EDOS /* generate EDOS executable */
+#undef MINIX /* generate Minix executable */
+
+/* these may need to be defined to suit the source processor */
+
+#define HOST_8BIT /* enable some 8-bit optimizations */
+
+/* #define S_ALIGNMENT 4 */ /* source memory alignment, power of 2 */
+ /* don't use for 8 bit processors */
+ /* don't use even for 80386 - overhead for */
+ /* alignment cancels improved access */
+
+/* these must be defined to suit the source libraries */
+
+#define CREAT_PERMS 0666 /* permissions for creat() */
+#define EXEC_PERMS 0111 /* extra permissions to set for executable */
--- /dev/null
+/* const.h - constants for linker */
+
+/* Copyright (C) 1994 Bruce Evans */
+
+#define FALSE 0
+#define NUL_PTR ((void*)0)
+#define TRUE 1
+
+#define EXTERN extern
+#define FORWARD static
+#define PRIVATE static
+#define PUBLIC
+
+#include "config.h"
--- /dev/null
+/* dumps.c - print data about symbols and modules for linker */
+
+/* Copyright (C) 1994 Bruce Evans */
+
+#include "syshead.h"
+#include "const.h"
+#include "obj.h"
+#include "type.h"
+#include "globvar.h"
+
+/* print list of modules and whether they are loaded */
+
+PUBLIC void dumpmods()
+{
+ struct modstruct *modptr;
+ char *s, *d;
+ int i;
+
+ for (modptr = modfirst; modptr != NUL_PTR; modptr = modptr->modnext)
+ {
+ for(s=d=modptr->filename; *s ; s++)
+ if( *s == '/' ) d=s+1;
+ if( memcmp(d, "libc", 4) == 0 && !modptr->loadflag ) continue;
+
+ putstr(modptr->modname);
+ i = strlen(modptr->modname);
+ while(i<16) putbyte(' '),i++;
+ putbyte( modptr->loadflag ? '+':'-' );
+ putstr(d);
+ if( modptr->archentry )
+ {
+ putbyte('(');
+ putstr(modptr->archentry);
+ putbyte(')');
+ }
+ putbyte('\n');
+ }
+}
+
+/* print data about symbols (in loaded modules only) */
+
+PUBLIC void dumpsyms()
+{
+ flags_t flags;
+ struct modstruct *modptr;
+ struct symstruct **symparray;
+ struct symstruct *symptr;
+ char uflag;
+
+ for (modptr = modfirst; modptr != NUL_PTR; modptr = modptr->modnext)
+ if (modptr->loadflag)
+ {
+ for (symparray = modptr->symparray;
+ (symptr = *symparray) != NUL_PTR; ++symparray)
+ if (symptr->modptr == modptr)
+ {
+ uflag = FALSE;
+ if (((flags = symptr->flags) & (C_MASK | I_MASK)) == I_MASK)
+ uflag = TRUE;
+ putbstr(20, uflag ? "" : modptr->modname);
+ putstr(" ");
+ putbstr(20, symptr->name);
+ putstr(" ");
+ putbyte(hexdigit[flags & SEGM_MASK]);
+ putstr(" ");
+ if (uflag)
+ putstr(" ");
+ else
+#ifdef LONG_OFFSETS
+ put08lx(symptr->value);
+#else
+ put08x(symptr->value);
+#endif
+ if( flags & (E_MASK|C_MASK) )
+ putstr(flags & A_MASK ? " A" : " R");
+ else
+ putstr(flags & A_MASK ? " a" : " r");
+ if (uflag)
+ putstr(" U");
+ if (flags & C_MASK)
+ putstr(" C");
+ if (flags & N_MASK)
+ putstr(" N");
+ putbyte('\n');
+ }
+ }
+
+ putstr("Total memory used: ");
+#ifdef LONG_OFFSETS
+ put08lx(memory_used());
+#else
+ put08x(memory_used());
+#endif
+ putbyte('\n');
+}
--- /dev/null
+/* globvar.h - global variables for linker */
+
+/* Copyright (C) 1994 Bruce Evans */
+
+#ifndef EXTERN
+#define EXTERN
+#endif
+EXTERN unsigned errcount; /* count of errors */
+EXTERN struct entrylist *entryfirst; /* first on list of entry symbols */
+EXTERN struct modstruct *modfirst; /* data for 1st module */
+EXTERN struct redlist *redfirst; /* first on list of redefined symbols */
+
+/* K&R _explicitly_ says extern followed by public is OK */
+extern char hexdigit[]; /* constant */
+extern int headerless; /* Don't output header on exe */
+#ifndef VERY_SMALL_MEMORY
+extern int v7; /* Generate an UNIX v7 a.out header */
+#endif
+#ifndef MSDOS
+extern int cpm86; /* Generate CP/M-86 CMD header */
+#endif
+
+extern bin_off_t text_base_value; /* Base address of text seg */
+extern bin_off_t data_base_value; /* Base or alignment of data seg */
+extern bin_off_t heap_top_value; /* Minimum 'total' value in x86 header */
--- /dev/null
+/* io.c - input/output and error modules for linker */
+
+/* Copyright (C) 1994 Bruce Evans */
+
+#include "syshead.h"
+#include "const.h"
+#include "type.h"
+#include "globvar.h"
+#include "version.h"
+
+#define DRELBUFSIZE 3072
+#define ERR (-1)
+#define ERRBUFSIZE 1024
+#define INBUFSIZE 1024
+#define OUTBUFSIZE 2048
+#define TRELBUFSIZE 1024
+
+#ifdef REL_OUTPUT
+PRIVATE char *drelbuf; /* extra output buffer for data relocations */
+PRIVATE char *drelbufptr; /* data relocation output buffer ptr */
+PRIVATE char *drelbuftop; /* data relocation output buffer top */
+#endif
+PRIVATE char *errbuf; /* error buffer (actually uses STDOUT) */
+PRIVATE char *errbufptr; /* error buffer ptr */
+PRIVATE char *errbuftop; /* error buffer top */
+PRIVATE int errfil = STDOUT_FILENO;
+PRIVATE char *inbuf; /* input buffer */
+PRIVATE char *inbufend; /* input buffer top */
+PRIVATE char *inbufptr; /* end of input in input buffer */
+PRIVATE int infd; /* input file descriptor */
+PRIVATE char *inputname; /* name of current input file */
+PRIVATE char *outbuf; /* output buffer */
+PRIVATE char *outbufptr; /* output buffer ptr */
+PRIVATE char *outbuftop; /* output buffer top */
+PRIVATE int outfd; /* output file descriptor */
+PRIVATE mode_t outputperms; /* permissions of output file */
+PRIVATE char *outputname; /* name of output file */
+PRIVATE char *refname; /* name of program for error reference */
+#ifdef REL_OUTPUT
+PRIVATE char *trelbuf; /* extra output buffer for text relocations */
+PRIVATE char *trelbufptr; /* text relocation output buffer ptr */
+PRIVATE char *trelbuftop; /* text relocation output buffer top */
+PRIVATE int trelfd; /* text relocation output file descriptor */
+#endif
+PRIVATE unsigned warncount; /* count of warnings */
+
+#ifdef MSDOS
+#define off_t long /* NOT a typedef */
+#endif
+
+FORWARD void errexit P((char *message));
+FORWARD void flushout P((void));
+#ifdef REL_OUTPUT
+FORWARD void flushtrel P((void));
+#endif
+FORWARD void outhexdigs P((bin_off_t num));
+FORWARD void outputerror P((char *message));
+FORWARD void put04x P((unsigned num));
+FORWARD void putstrn P((char *message));
+FORWARD void refer P((void));
+FORWARD void stderr_out P((void));
+
+PUBLIC void ioinit(progname)
+char *progname;
+{
+ infd = ERR;
+ if (*progname)
+ refname = progname; /* name must be static (is argv[0]) */
+ else
+ refname = "link";
+ for(progname=refname; *progname; progname++)
+ if(*progname=='/')
+ refname=progname+1;
+
+#ifdef REL_OUTPUT
+ drelbuf = malloc(DRELBUFSIZE);
+ drelbuftop = drelbuf + DRELBUFSIZE;
+#endif
+ errbuf = malloc(ERRBUFSIZE);
+ errbufptr = errbuf;
+ errbuftop = errbuf + ERRBUFSIZE;
+ inbuf = malloc(INBUFSIZE);
+ outbuf = malloc(OUTBUFSIZE);/* outbuf invalid if this fails but then */
+ /* will not be used - tableinit() aborts */
+ outbuftop = outbuf + OUTBUFSIZE;
+#ifdef REL_OUTPUT
+ trelbuf = malloc(TRELBUFSIZE);
+ trelbuftop = trelbuf + TRELBUFSIZE;
+#endif
+}
+
+PUBLIC void closein()
+{
+ if (infd != ERR && close(infd) < 0)
+ inputerror("cannot close");
+ infd = ERR;
+}
+
+PUBLIC void closeout()
+{
+#ifdef REL_OUTPUT
+ unsigned nbytes;
+#endif
+
+ flushout();
+#ifdef REL_OUTPUT
+ flushtrel();
+ nbytes = drelbufptr - drelbuf;
+ if (write(trelfd, drelbuf, nbytes) != nbytes)
+ outputerror("cannot write");
+#endif
+ if (close(outfd) == ERR)
+ outputerror("cannot close");
+#ifdef REL_OUTPUT
+ if (close(trelfd) == ERR)
+ outputerror("cannot close");
+#endif
+}
+
+PUBLIC void errtrace(name, level)
+char *name;
+int level;
+{
+ while (level-- > 0)
+ putbyte(' ');
+ putstrn(name);
+}
+
+PUBLIC void executable()
+{
+ if (errcount)
+ unlink(outputname);
+#ifndef MSDOS
+ else
+ chmod(outputname, outputperms);
+#endif
+}
+
+PUBLIC void flusherr()
+{
+ if( errbufptr != errbuf )
+ write(errfil, errbuf, (unsigned) (errbufptr - errbuf));
+ errbufptr = errbuf;
+}
+
+PRIVATE void stderr_out()
+{
+ if( errfil != STDERR_FILENO )
+ {
+ flusherr();
+ errfil = STDERR_FILENO;
+ }
+}
+
+PRIVATE void flushout()
+{
+ unsigned nbytes;
+
+ nbytes = outbufptr - outbuf;
+ if (write(outfd, outbuf, nbytes) != nbytes)
+ outputerror("cannot write");
+ outbufptr = outbuf;
+}
+
+#ifdef REL_OUTPUT
+PRIVATE void flushtrel()
+{
+ unsigned nbytes;
+
+ nbytes = trelbufptr - trelbuf;
+ if (write(trelfd, trelbuf, nbytes) != nbytes)
+ outputerror("cannot write");
+ trelbufptr = trelbuf;
+}
+#endif
+
+PUBLIC void openin(filename)
+char *filename;
+{
+#if 0 /* XXX - this probably won't work with constructed lib names? */
+ if (infd == ERR || strcmp(inputname, filename) != 0)
+#endif
+ {
+ closein();
+ inputname = filename; /* this relies on filename being static */
+#ifdef O_BINARY
+ if ((infd = open(filename, O_BINARY|O_RDONLY)) < 0)
+#else
+ if ((infd = open(filename, O_RDONLY)) < 0)
+#endif
+ inputerror("cannot open");
+ inbufptr = inbufend = inbuf;
+ }
+}
+
+PUBLIC void openout(filename)
+char *filename;
+{
+ mode_t oldmask;
+
+ outputname = filename;
+#ifdef O_BINARY
+ if ((outfd = open(filename, O_BINARY|O_WRONLY|O_CREAT|O_TRUNC, CREAT_PERMS)) == ERR)
+#else
+ if ((outfd = creat(filename, CREAT_PERMS)) == ERR)
+#endif
+ outputerror("cannot open");
+
+#ifndef MSDOS
+ /* Can't do this on MSDOS; it upsets share.exe */
+ oldmask = umask(0); umask(oldmask);
+ outputperms = ((CREAT_PERMS | EXEC_PERMS) & ~oldmask);
+ chmod(filename, outputperms & ~EXEC_PERMS);
+#endif
+
+#ifdef REL_OUTPUT
+ drelbufptr = drelbuf;
+#endif
+ outbufptr = outbuf;
+#ifdef REL_OUTPUT
+#ifdef O_BINARY
+ if ((trelfd = open(filename, O_BINARY|O_WRONLY, CREAT_PERMS)) == ERR)
+#else
+ if ((trelfd = open(filename, O_WRONLY, CREAT_PERMS)) == ERR)
+#endif
+ outputerror("cannot reopen");
+ trelbufptr = trelbuf;
+#endif
+}
+
+PRIVATE void outhexdigs(num)
+register bin_off_t num;
+{
+ if (num >= 0x10)
+ {
+ outhexdigs(num / 0x10);
+ num %= 0x10;
+ }
+ putbyte(hexdigit[num]);
+}
+
+PRIVATE void put04x(num)
+register unsigned num;
+{
+ putbyte(hexdigit[num / 0x1000]);
+ putbyte(hexdigit[(num / 0x100) & 0x0F]);
+ putbyte(hexdigit[(num / 0x10) & 0x0F]);
+ putbyte(hexdigit[num & 0x0F]);
+}
+
+#ifdef LONG_OFFSETS
+
+PUBLIC void put08lx(num)
+register bin_off_t num;
+{
+ put04x(num / 0x10000);
+ put04x(num % 0x10000);
+}
+
+#else /* not LONG_OFFSETS */
+
+PUBLIC void put08x(num)
+register bin_off_t num;
+{
+ putstr("0000");
+ put04x(num);
+}
+
+#endif /* not LONG_OFFSETS */
+
+PUBLIC void putbstr(width, str)
+unsigned width;
+char *str;
+{
+ unsigned length;
+
+ for (length = strlen(str); length < width; ++length)
+ putbyte(' ');
+ putstr(str);
+}
+
+PUBLIC void putbyte(ch)
+int ch;
+{
+ register char *ebuf;
+
+ ebuf = errbufptr;
+ if (ebuf >= errbuftop)
+ {
+ flusherr();
+ ebuf = errbufptr;
+ }
+ *ebuf++ = ch;
+ errbufptr = ebuf;
+}
+
+PUBLIC void putstr(message)
+char *message;
+{
+ while (*message != 0)
+ putbyte(*message++);
+}
+
+PRIVATE void putstrn(message)
+char *message;
+{
+ putstr(message);
+ putbyte('\n');
+ flusherr(); errfil = STDOUT_FILENO;
+}
+
+PUBLIC int readchar()
+{
+ int ch;
+
+ register char *ibuf;
+ int nread;
+
+ ibuf = inbufptr;
+ if (ibuf >= inbufend)
+ {
+ ibuf = inbufptr = inbuf;
+ nread = read(infd, ibuf, INBUFSIZE);
+ if (nread <= 0)
+ {
+ inbufend = ibuf;
+ return ERR;
+ }
+ inbufend = ibuf + nread;
+ }
+ ch = (unsigned char) *ibuf++;
+ inbufptr = ibuf;
+ return ch;
+}
+
+PUBLIC void readin(buf, count)
+char *buf;
+unsigned count;
+{
+ int ch;
+
+ while (count--)
+ {
+ if ((ch = readchar()) < 0)
+ prematureeof();
+ *buf++ = ch;
+ }
+}
+
+PUBLIC bool_pt readineofok(buf, count)
+char *buf;
+unsigned count;
+{
+ int ch;
+
+ while (count--)
+ {
+ if ((ch = readchar()) < 0)
+ return TRUE;
+ *buf++ = ch;
+ }
+ return FALSE;
+}
+
+PUBLIC void seekin(offset)
+unsigned long offset;
+{
+ inbufptr = inbufend = inbuf;
+ if (lseek(infd, (off_t) offset, SEEK_SET) != offset)
+ prematureeof();
+}
+
+PUBLIC void seekout(offset)
+unsigned long offset;
+{
+ flushout();
+ if (lseek(outfd, (off_t) offset, SEEK_SET) != offset)
+ outputerror("cannot seek in");
+}
+
+#ifdef REL_OUTPUT
+PUBLIC void seektrel(offset)
+unsigned long offset;
+{
+ flushtrel();
+ if (lseek(trelfd, (off_t) offset, SEEK_SET) != offset)
+ outputerror("cannot seek in");
+}
+#endif
+
+PUBLIC void writechar(ch)
+int ch;
+{
+ register char *obuf;
+
+ obuf = outbufptr;
+ if (obuf >= outbuftop)
+ {
+ flushout();
+ obuf = outbufptr;
+ }
+ *obuf++ = ch;
+ outbufptr = obuf;
+}
+
+#ifdef REL_OUTPUT
+PUBLIC void writedrel(buf, count)
+register char *buf;
+unsigned count;
+{
+ register char *rbuf;
+
+ rbuf = drelbufptr;
+ while (count--)
+ {
+ if (rbuf >= drelbuftop)
+ inputerror("data relocation buffer full while processing");
+ *rbuf++ = *buf++;
+ }
+ drelbufptr = rbuf;
+}
+#endif
+
+PUBLIC void writeout(buf, count)
+register char *buf;
+unsigned count;
+{
+ register char *obuf;
+
+ obuf = outbufptr;
+ while (count--)
+ {
+ if (obuf >= outbuftop)
+ {
+ outbufptr = obuf;
+ flushout();
+ obuf = outbufptr;
+ }
+ *obuf++ = *buf++;
+ }
+ outbufptr = obuf;
+}
+
+#ifdef REL_OUTPUT
+PUBLIC void writetrel(buf, count)
+register char *buf;
+unsigned count;
+{
+ register char *rbuf;
+
+ rbuf = trelbufptr;
+ while (count--)
+ {
+ if (rbuf >= trelbuftop)
+ {
+ trelbufptr = rbuf;
+ flushtrel();
+ rbuf = trelbufptr;
+ }
+ *rbuf++ = *buf++;
+ }
+ trelbufptr = rbuf;
+}
+#endif
+
+/* error module */
+
+PRIVATE void errexit(message)
+char *message;
+{
+ putstrn(message);
+ exit(2);
+}
+
+PUBLIC void fatalerror(message)
+char *message;
+{
+ refer();
+ errexit(message);
+}
+
+PUBLIC void inputerror(message)
+char *message;
+{
+ refer();
+ putstr(message);
+ putstr(" input file ");
+ errexit(inputname);
+}
+
+PUBLIC void input1error(message)
+char *message;
+{
+ refer();
+ putstr(inputname);
+ errexit(message);
+}
+
+PRIVATE void outputerror(message)
+char *message;
+{
+ refer();
+ putstr(message);
+ putstr(" output file ");
+ errexit(outputname);
+}
+
+PUBLIC void outofmemory()
+{
+ inputerror("out of memory while processing");
+}
+
+PUBLIC void prematureeof()
+{
+ inputerror("premature end of");
+}
+
+PUBLIC void redefined(name, message, archentry, deffilename, defarchentry)
+char *name;
+char *message;
+char *archentry;
+char *deffilename;
+char *defarchentry;
+{
+ ++warncount;
+ refer();
+ putstr("warning: ");
+ putstr(name);
+ putstr(" redefined");
+ putstr(message);
+ putstr(" in file ");
+ putstr(inputname);
+ if (archentry != NUL_PTR)
+ {
+ putbyte('(');
+ putstr(archentry);
+ putbyte(')');
+ }
+ putstr("; using definition in ");
+ putstr(deffilename);
+ if (defarchentry != NUL_PTR)
+ {
+ putbyte('(');
+ putstr(defarchentry);
+ putbyte(')');
+ }
+ putstrn("");
+}
+
+PUBLIC void interseg(fname, aname, name)
+char *fname, *aname, *name;
+{
+ ++errcount;
+ refer();
+ putstr("error in ");
+ putstr(fname);
+ if( aname )
+ {
+ putstr("(");
+ putstr(aname);
+ putstr(")");
+ }
+ putstr(" intersegment jump to ");
+ if( name ) putstr(name);
+ else putstr("same file");
+
+ putstrn("");
+}
+
+PRIVATE void refer()
+{
+ stderr_out();
+ putstr(refname);
+ putstr(": ");
+}
+
+PUBLIC void reserved(name)
+char *name;
+{
+ ++errcount;
+ stderr_out();
+ putstr("incorrect use of reserved symbol: ");
+ putstrn(name);
+}
+
+PUBLIC void size_error(seg, count, size)
+int seg;
+bin_off_t count;
+bin_off_t size;
+{
+ refer();
+ putstr("seg ");
+ outhexdigs((bin_off_t) seg);
+ putstr(" has wrong size ");
+ outhexdigs(count);
+ putstr(", supposed to be ");
+ outhexdigs(size);
+ errexit("");
+}
+
+PUBLIC void undefined(name)
+char *name;
+{
+ ++errcount;
+ stderr_out();
+ putstr("undefined symbol: ");
+ putstrn(name);
+}
+
+PUBLIC void usage()
+{
+ stderr_out();
+ putstr("usage: ");
+ putstr(refname);
+#ifdef REL_OUTPUT
+ errexit("\
+ [-03NMdimrstz[-]] [-llib_extension] [-o outfile] [-Ccrtfile]\n\
+ [-Llibdir] [-Olibfile] [-Ttextaddr] [-Ddataaddr] [-Hheapsize] infile...");
+#else
+ errexit("\
+ [-03NMdimstz[-]] [-llib_extension] [-o outfile] [-Ccrtfile]\n\
+ [-Llibdir] [-Olibfile] [-Ttextaddr] [-Ddataaddr] [-Hheapsize] infile...");
+#endif
+}
+
+PUBLIC void version_msg()
+{
+ stderr_out();
+#ifdef VERSION
+ putstr("ld86 version: ");
+ errexit(VERSION);
+#else
+ errexit("ld86 version unknown");
+#endif
+}
+
+PUBLIC void use_error(message)
+char *message;
+{
+ refer();
+ putstrn(message);
+ usage();
+}
--- /dev/null
+/* ld.c - linker for Introl format (6809 C) object files 6809/8086/80386 */
+
+/* Copyright (C) 1994 Bruce Evans */
+
+#include "syshead.h"
+#include "const.h"
+#include "byteord.h"
+#include "type.h"
+#include "globvar.h"
+
+#define MAX_LIBS (NR_STDLIBS + 5)
+#ifdef MC6809
+#define NR_STDLIBS 1
+#else
+#define NR_STDLIBS 0
+#endif
+
+PUBLIC bin_off_t text_base_value = 0; /* XXX */
+PUBLIC bin_off_t data_base_value = 0; /* XXX */
+PUBLIC bin_off_t heap_top_value = 0; /* XXX */
+PUBLIC int headerless = 0;
+#ifndef VERY_SMALL_MEMORY
+PUBLIC int v7 = 0;
+#endif
+#ifndef MSDOS
+PUBLIC int cpm86 = 0;
+#endif
+PUBLIC char hexdigit[] = "0123456789abcdef";
+
+PRIVATE bool_t flag[128];
+PRIVATE char *libs[MAX_LIBS] = {
+#ifdef MC6809
+ "/usr/local/lib/m09/",
+#endif
+ 0
+};
+PRIVATE int lastlib = NR_STDLIBS;
+
+FORWARD char *buildname P((char *pre, char *mid, char *suf));
+FORWARD char *expandlib P((char *fn));
+
+PRIVATE char *buildname(pre, mid, suf)
+char *pre;
+char *mid;
+char *suf;
+{
+ char *name;
+
+ name = ourmalloc(strlen(pre) + strlen(mid) + strlen(suf) + 1);
+ strcpy(name, pre);
+ strcat(name, mid);
+ strcat(name, suf);
+ return name;
+}
+
+PRIVATE char *expandlib(fn)
+char *fn;
+{
+ char *path, *s;
+ int i;
+
+ for (i = lastlib - 1; i >= 0; --i)
+ {
+ path = ourmalloc(strlen(libs[i]) + strlen(fn) + 2);
+ strcpy(path, libs[i]);
+ s = path + strlen(path);
+ if (s!=path && s[-1] != '/') strcat(path, "/");
+ strcat(path, fn);
+ if (access(path, R_OK) == 0)
+ return path;
+ ourfree(path);
+ }
+ return NUL_PTR;
+}
+
+PUBLIC int main(argc, argv)
+int argc;
+char **argv;
+{
+ register char *arg;
+ int argn;
+ static char crtprefix[] = "crt";
+ static char crtsuffix[] = ".o";
+ char *infilename;
+ static char libprefix[] = "lib";
+ static char libsuffix[] = ".a";
+ char *outfilename;
+ char *tfn;
+ int icount=0;
+
+ ioinit(argv[0]);
+ objinit();
+ syminit();
+ typeconv_init(INT_BIG_ENDIAN, LONG_BIG_ENDIAN);
+#ifndef MC6809
+ flag['3'] = sizeof(char *) >= 4;
+#endif
+ outfilename = NUL_PTR;
+ for (argn = 1; argn < argc; ++argn)
+ {
+ arg = argv[argn];
+ if (*arg != '-')
+ {
+ readsyms(arg, flag['t']);
+ icount++;
+ }
+ else
+ switch (arg[1])
+ {
+ case 'v':
+ version_msg();
+ case 'r': /* relocatable output */
+ case 't': /* trace modules linked */
+ if (icount > 0) usage();
+#ifdef REL_OUTPUT
+ case 'B': /* Broken -r for dosemu. */
+#endif
+ case '0': /* use 16-bit libraries */
+ case '3': /* use 32-bit libraries */
+ case 'M': /* print symbols linked */
+ case 'i': /* separate I & D output */
+ case 'm': /* print modules linked */
+ case 's': /* strip symbols */
+ case 'z': /* unmapped zero page */
+ case 'N': /* Native format a.out */
+ case 'd': /* Make a headerless outfile */
+#ifndef MSDOS
+ case 'c': /* Write header in CP/M-86 format */
+#endif
+ case 'y': /* Use a newer symbol table */
+#ifndef VERY_SMALL_MEMORY
+ case '7': /* Produce a UNIX v7 a.out header */
+#endif
+ if (arg[2] == 0)
+ flag[(int) arg[1]] = TRUE;
+ else if (arg[2] == '-' && arg[3] == 0)
+ flag[(int) arg[1]] = FALSE;
+ else
+ usage();
+ if (arg[1] == '0') /* flag 0 is negative logic flag 3 */
+ flag['3'] = !flag['0'];
+ break;
+ case 'C': /* startfile name */
+ tfn = buildname(crtprefix, arg + 2, crtsuffix);
+ if ((infilename = expandlib(tfn)) == NUL_PTR)
+ infilename = tfn;
+ /*fatalerror(tfn); * XXX - need to describe failure */
+ readsyms(infilename, flag['t']);
+ icount++;
+ break;
+ case 'L': /* library path */
+ if (lastlib < MAX_LIBS)
+ libs[lastlib++] = arg + 2;
+ else
+ fatalerror("too many library paths");
+ break;
+ case 'O': /* library file name */
+ if ((infilename = expandlib(arg + 2)) == NUL_PTR)
+ infilename = arg+2;
+ /* fatalerror(arg); * XXX */
+ readsyms(infilename, flag['t']);
+ break;
+ case 'T': /* text base address */
+ if (arg[2] == 0 && ++argn >= argc)
+ usage();
+ errno = 0;
+ if (arg[2] == 0 )
+ text_base_value = strtoul(argv[argn], (char **)0, 16);
+ else
+ text_base_value = strtoul(arg+2, (char **)0, 16);
+ if (errno != 0)
+ use_error("invalid text address");
+ break;
+ case 'D': /* data base address */
+ if (arg[2] == 0 && ++argn >= argc)
+ usage();
+ errno = 0;
+ if (arg[2] == 0 )
+ data_base_value = strtoul(argv[argn], (char **)0, 16);
+ else
+ data_base_value = strtoul(arg+2, (char **)0, 16);
+ if (errno != 0)
+ use_error("invalid data address");
+ break;
+ case 'H': /* heap top address */
+ if (arg[2] == 0 && ++argn >= argc)
+ usage();
+ errno = 0;
+ if (arg[2] == 0 )
+ heap_top_value = strtoul(argv[argn], (char **)0, 16);
+ else
+ heap_top_value = strtoul(arg+2, (char **)0, 16);
+ if (errno != 0)
+ use_error("invalid heap top");
+ break;
+ case 'l': /* library name */
+ tfn = buildname(libprefix, arg + 2, libsuffix);
+ if ((infilename = expandlib(tfn)) == NUL_PTR)
+ infilename = tfn;
+ /* fatalerror(tfn); * XXX */
+ readsyms(infilename, flag['t']);
+ icount+=2;
+ break;
+ case 'o': /* output file name */
+ if (arg[2] != 0 || ++argn >= argc || outfilename != NUL_PTR)
+ usage();
+ outfilename = argv[argn];
+ break;
+ default:
+ usage();
+ }
+ }
+ if(icount==0) usage();
+
+#ifdef BUGCOMPAT
+ if( icount==1 && ( flag['r'] && !flag['N'] ) ) {
+ flag['r'] = 0;
+ flag['B'] = 1;
+ }
+#endif
+
+#ifdef REL_OUTPUT
+#ifndef MSDOS
+ if( flag['r'] && !flag['N'] )
+ {
+ /* Do a relocatable link -- actually fake it with 'ar.c' */
+ ld86r(argc, argv);
+ }
+#endif
+#endif
+
+#ifdef MSDOS
+ /* MSDOS Native is special, we make a COM file */
+ if( flag['N'] )
+ {
+ flag['N'] = 0;
+ flag['d'] = 1;
+ text_base_value = 0x100;
+ }
+#endif
+
+ /* Headerless executables can't use symbols. */
+ headerless = flag['d'];
+ if( headerless ) flag['s'] = 1;
+
+#ifndef VERY_SMALL_MEMORY
+ /* UNIX seventh edition executables */
+ v7 = flag['7'];
+#endif
+
+#ifndef MSDOS
+ /* CP/M-86 executables can't use symbols. */
+ cpm86 = flag['c'];
+ if ( cpm86 ) flag['s'] = 1;
+#endif
+
+ linksyms(flag['r'] | flag['B']);
+ if (outfilename == NUL_PTR)
+ outfilename = "a.out";
+#ifndef MSDOS
+ if( flag['N'] )
+ writebin(outfilename, flag['i'], flag['3'], flag['s'],
+ flag['z'] & flag['3']);
+ else
+#endif
+ if( flag['B'] )
+ write_dosemu(outfilename, flag['i'], flag['3'], flag['s'],
+ flag['z'] & flag['3']);
+#if 0 /* FIXME */
+ else
+ write_elks(outfilename, flag['i'], flag['3'], flag['s'],
+ flag['z'], flag['y']);
+#endif
+ if (flag['m'])
+ dumpmods();
+ if (flag['M'])
+ dumpsyms();
+ flusherr();
+ return errcount ? 1 : 0;
+}
--- /dev/null
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#ifdef __STDC__
+#include <stdlib.h>
+#include <unistd.h>
+#else
+#include <malloc.h>
+#endif
+
+#define ARMAG "!<arch>\n"
+#define SARMAG 8
+#define ARFMAG "`\n"
+
+struct ar_hdr {
+ char ar_name[16],
+ ar_date[12],
+ ar_uid[6],
+ ar_gid[6],
+ ar_mode[8],
+ ar_size[10],
+ ar_fmag[2];
+} arbuf;
+
+void
+fatal(char * str) { fprintf(stderr, "%s\n", str); exit(2); }
+
+void
+main(int argc, char ** argv)
+{
+char buf[128];
+ FILE * fd, * ifd;
+ struct stat st;
+ int ar, libarg=0, need_o = 0, got_o = 0;
+
+ for(ar=1; ar<argc; ar++) if( argv[ar][0] == '-' )
+ {
+ if( argv[ar][1] == 'r' ) need_o = 1;
+ if( argv[ar][1] == 'o' ) { got_o++; libarg = 0; }
+ }
+ else
+ {
+ if( libarg == 0 ) libarg = ar;
+ }
+
+ if( libarg == 0 || got_o > 1 || need_o > got_o )
+ fatal("Err, what's the output gonna be called?");
+
+ if( (fd =fopen(argv[libarg], "wb")) == 0 ) fatal("Cannot open archive");
+ if( fwrite(ARMAG, 1, SARMAG, fd) != SARMAG) fatal("Cannot write magic");
+
+ for(ar=1; ar<argc; ar++) if( ar != libarg && argv[ar][0] != '-' )
+ {
+ char * ptr;
+ if( stat(argv[ar], &st) < 0 ) fatal("Cannot stat object");
+ if((ptr=strchr(argv[ar], '/'))) ptr++; else ptr=argv[ar];
+ memset(&arbuf, ' ', sizeof(arbuf));
+ strcpy(buf, ptr); strcat(buf, "/ ");
+ strncpy(arbuf.ar_name, buf, sizeof(arbuf.ar_name));
+
+ sprintf(arbuf.ar_date, "%-12ld", (long)st.st_mtime);
+ sprintf(arbuf.ar_uid, "%-6d", (int)(st.st_uid%1000000L));
+ sprintf(arbuf.ar_gid, "%-6d", (int)(st.st_gid%1000000L));
+ sprintf(arbuf.ar_mode, "%-8lo", (long)st.st_mode);
+ sprintf(arbuf.ar_size, "%-10ld", (long)st.st_size);
+ memcpy(arbuf.ar_fmag, ARFMAG, sizeof(arbuf.ar_fmag));
+
+ if( fwrite(&arbuf, 1, sizeof(arbuf), fd) != sizeof(arbuf) )
+ fatal("Cannot write header");
+
+ ptr = malloc(st.st_size+2);
+ if( ptr == 0 ) fatal("Out of memory");
+ ptr[st.st_size] = ' ';
+ if( (ifd = fopen(argv[ar], "rb")) == 0 ) fatal("Cannot open input");
+ if( fread(ptr, 1, st.st_size, ifd) != st.st_size )
+ fatal("Cannot read input file");
+ fclose(ifd);
+
+ if( st.st_size&1 ) st.st_size++;
+ if( fwrite(ptr, 1, st.st_size, fd) != st.st_size )
+ fatal("Cannot write output file");
+ }
+ fclose(fd);
+ exit(0);
+}
--- /dev/null
+
+/* linksyms.c - write binary file for linker */
+
+/* Copyright (C) 1994 Bruce Evans */
+
+#include "syshead.h"
+#include "const.h"
+#include "obj.h"
+#include "type.h"
+#undef EXTERN
+#include "globvar.h"
+
+FORWARD void linkrefs P((struct modstruct *modptr));
+PUBLIC bool_t reloc_output = 0;
+
+/* link all symbols connected to entry symbols */
+
+PUBLIC void linksyms(argreloc_output)
+bool_pt argreloc_output;
+{
+ char needlink;
+ struct entrylist *elptr;
+ struct modstruct *modptr;
+ struct symstruct *symptr;
+
+#ifdef REL_OUTPUT
+ reloc_output = argreloc_output;
+ if (argreloc_output)
+ {
+ if (modfirst->modnext != NUL_PTR)
+ fatalerror("relocatable output only works for one input file");
+ for (modptr = modfirst; modptr != NUL_PTR; modptr = modptr->modnext)
+ modptr->loadflag = TRUE;
+ return;
+ }
+#endif
+ if ((symptr = findsym("_start")) != NUL_PTR ||
+ (symptr = findsym("_main")) != NUL_PTR)
+ entrysym(symptr);
+ do
+ {
+ if ((elptr = entryfirst) == NUL_PTR)
+ fatalerror("no start symbol");
+ for (modptr = modfirst; modptr != NUL_PTR; modptr = modptr->modnext)
+ modptr->loadflag = FALSE;
+ for (; elptr != NUL_PTR; elptr = elptr->elnext)
+ linkrefs(elptr->elsymptr->modptr);
+ if ((symptr = findsym("start")) != NUL_PTR)
+ linkrefs(symptr->modptr);
+ needlink = FALSE;
+ {
+ struct redlist *prlptr = 0;
+ struct redlist *rlptr;
+
+ for (rlptr = redfirst; rlptr != NUL_PTR;
+ rlptr = (prlptr = rlptr)->rlnext)
+ if (rlptr->rlmodptr->loadflag &&
+ rlptr->rlmodptr->class > rlptr->rlsymptr->modptr->class)
+ {
+ rlptr->rlsymptr->modptr = rlptr->rlmodptr;
+ rlptr->rlsymptr->value = rlptr->rlvalue;
+ if (rlptr == redfirst)
+ redfirst = rlptr->rlnext;
+ else
+ prlptr->rlnext = rlptr->rlnext;
+ needlink = TRUE;
+ }
+ }
+ }
+ while (needlink);
+}
+
+PRIVATE void linkrefs(modptr)
+struct modstruct *modptr;
+{
+ register struct symstruct **symparray;
+ register struct symstruct *symptr;
+
+ modptr->loadflag = TRUE;
+ for (symparray = modptr->symparray;
+ (symptr = *symparray) != NUL_PTR; ++symparray)
+ if (symptr->modptr->loadflag == FALSE)
+ linkrefs(symptr->modptr);
+}
+
--- /dev/null
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#ifdef __STDC__
+#include <stdlib.h>
+#include <unistd.h>
+#else
+#include <malloc.h>
+#endif
+
+#include "type.h"
+#include "ar.h"
+
+static struct ar_hdr arbuf;
+
+#ifdef __STDC__
+void
+ld86r(int argc, char ** argv)
+#else
+ld86r(argc, argv)
+ int argc; char ** argv;
+#endif
+{
+char buf[128];
+ FILE * fd, * ifd;
+ struct stat st;
+ int ar, libarg=0, need_o = 0, got_o = 0;
+
+ for(ar=1; ar<argc; ar++) if( argv[ar][0] == '-' )
+ {
+ if( argv[ar][1] == 'r' ) need_o = 1;
+ if( argv[ar][1] == 'o' ) { got_o++; libarg = 0; }
+ }
+ else
+ {
+ if( libarg == 0 ) libarg = ar;
+ }
+
+ if( libarg == 0 || got_o > 1 || need_o > got_o )
+ fatalerror("-o option required for -r");
+
+ if( (fd =fopen(argv[libarg], "wb")) == 0 ) fatalerror("Cannot open archive");
+ if( fwrite(ARMAG, 1, SARMAG, fd) != SARMAG) fatalerror("Cannot write magic");
+
+ for(ar=1; ar<argc; ar++) if( ar != libarg && argv[ar][0] != '-' )
+ {
+ char * ptr;
+ if( stat(argv[ar], &st) < 0 ) fatalerror("Cannot stat object");
+ if((ptr=strchr(argv[ar], '/'))) ptr++; else ptr=argv[ar];
+ memset(&arbuf, ' ', sizeof(arbuf));
+ strcpy(buf, ptr); strcat(buf, "/ ");
+ strncpy(arbuf.ar_name, buf, sizeof(arbuf.ar_name));
+
+ snprintf(arbuf.ar_date, 12, "%-12ld", (long)st.st_mtime);
+ snprintf(arbuf.ar_uid, 6, "%-6d", (int)(st.st_uid%1000000L));
+ snprintf(arbuf.ar_gid, 6, "%-6d", (int)(st.st_gid%1000000L));
+ snprintf(arbuf.ar_mode, 8, "%-8lo", (long)st.st_mode);
+ snprintf(arbuf.ar_size, 10, "%-10ld", (long)st.st_size);
+ memcpy(arbuf.ar_fmag, ARFMAG, sizeof(arbuf.ar_fmag));
+
+ if( fwrite(&arbuf, 1, sizeof(arbuf), fd) != sizeof(arbuf) )
+ fatalerror("Cannot write header");
+
+ ptr = malloc(st.st_size+2);
+ if( ptr == 0 ) fatalerror("Out of memory");
+ ptr[st.st_size] = ' ';
+ if( (ifd = fopen(argv[ar], "rb")) == 0 ) fatalerror("Cannot open input");
+ if( fread(ptr, 1, st.st_size, ifd) != st.st_size )
+ fatalerror("Cannot read input file");
+ fclose(ifd);
+
+ if( st.st_size&1 ) st.st_size++;
+ if( fwrite(ptr, 1, st.st_size, fd) != st.st_size )
+ fatalerror("Cannot write output file");
+ }
+ fclose(fd);
+ exit(0);
+}
--- /dev/null
+/* obj.h - constants for Introl object modules */
+
+/* Copyright (C) 1994 Bruce Evans */
+
+#define OBJ_H
+
+#ifndef OMAGIC
+# ifdef I80386
+# define OMAGIC 0x86A3
+# endif
+
+# ifdef I8086
+# define OMAGIC 0x86A0
+# endif
+
+# ifdef MC6809
+# define OMAGIC 0x5331
+# endif
+#endif
+
+#ifdef LONG_OFFSETS
+# define cntooffset cnu4
+# define offtocn u4cn
+#else
+# define cntooffset cnu2
+# define offtocn u2cn
+#endif
+
+#ifdef MC6809 /* temp don't support alignment at all */
+# define ld_roundup( num, boundary, type ) (num)
+#else
+# define ld_roundup( num, boundary, type ) \
+ (((num) + ((boundary) - 1)) & (type) ~((boundary) - 1))
+#endif
+
+#define MAX_OFFSET_SIZE 4
+#define NSEG 16
+
+/* flag values |SZ|LXXXX|N|E|I|R|A|SEGM|, X not used */
+
+#define A_MASK 0x0010 /* absolute */
+#define C_MASK 0x0020 /* common (internal only) */
+#define E_MASK 0x0080 /* exported */
+#define I_MASK 0x0040 /* imported */
+#define N_MASK 0x0100 /* entry point */
+#define R_MASK 0x0020 /* relative (in text only) */
+#define SEGM_MASK 0x000F /* segment (if not absolute) */
+#define SA_MASK 0x2000 /* offset is storage allocation */
+#define SZ_MASK 0xC000 /* size descriptor for value */
+#define SZ_SHIFT 14
--- /dev/null
+
+#include <stdio.h>
+#ifdef __STDC__
+#include <unistd.h>
+#include <stdlib.h>
+#endif
+#include "x86_aout.h"
+
+#ifndef __OUT_OK
+
+main()
+{
+ fprintf(stderr, "Compile error: struct exec invalid\n");
+ exit(1);
+}
+
+#else
+
+FILE * ifd;
+struct exec header;
+
+main(argc, argv)
+int argc;
+char ** argv;
+{
+ FILE * ofd;
+ if( argc != 5 ) fatal("Usage: objchop a.out text.bin data.bin sizes.asm");
+
+ ifd = fopen(argv[1], "r");
+ if( ifd == 0 ) fatal("Cannot open input file");
+
+ if( fread(&header, A_MINHDR, 1, ifd) != 1 )
+ fatal("Incomplete executable header");
+
+ if( BADMAG(header) )
+ fatal("Input file has bad magic number");
+
+ if( fseek(ifd, A_TEXTPOS(header), 0) < 0 )
+ fatal("Cannot seek to start of text");
+
+ write_file(argv[2], header.a_text);
+
+ if( fseek(ifd, A_DATAPOS(header), 0) < 0 )
+ fatal("Cannot seek to start of data");
+
+ write_file(argv[3], header.a_data);
+
+ ofd = fopen(argv[4], "w");
+ if( ofd == 0 ) fatal("Cannot open output file");
+
+ fprintf(ofd, "TEXT_SIZE=%ld\nDATA_SIZE=%ld\nBSS_SIZE=%ld\nALLOC_SIZE=%ld\n",
+ header.a_text, header.a_data, header.a_bss, header.a_total);
+
+ fclose(ofd);
+
+ exit(0);
+}
+
+write_file(fname, bsize)
+char * fname;
+long bsize;
+{
+ char buffer[1024];
+ int ssize;
+ FILE * ofd;
+
+ ofd = fopen(fname, "w");
+ if( ofd == 0 ) fatal("Cannot open output file");
+
+ while(bsize>0)
+ {
+ if( bsize > sizeof(buffer) ) ssize = sizeof(buffer);
+ else ssize = bsize;
+
+ if( (ssize=fread(buffer, 1, ssize, ifd)) <= 0 )
+ fatal("Error reading segment from executable");
+ if( fwrite(buffer, 1, ssize, ofd) != ssize )
+ fatal("Error writing output file");
+ bsize -= ssize;
+ }
+ fclose(ofd);
+}
+
+fatal(str)
+char * str;
+{
+ fprintf(stderr, "objchop: %s\n", str);
+ exit(2);
+}
+
+#endif
--- /dev/null
+/*
+ * This is a combination of three tools for decoding information from
+ * Dev86/ELKS object files and executables.
+ *
+ * This executable can be given the names:
+ *
+ * objdump86: Dumps detailed information about a binary file.
+ * size86: Summary sizes of the data in a binary file.
+ * nm86: The symbol table of the binary file.
+ *
+ * None of these programs have any options.
+ * This may be a minor problem with nm86.
+ *
+ * Copyright (c) 1999 by Greg Haerr <greg@censoft.com>
+ * Added archive file reading capabilties
+ */
+
+#include <stdio.h>
+#ifdef __STDC__
+#include <stdlib.h>
+#else
+#include <malloc.h>
+#endif
+#include <string.h>
+#include "const.h"
+#include "ar.h"
+#include "obj.h"
+
+FILE * ifd;
+char * ifname;
+
+#ifdef __STDC__
+#define _(x) x
+#else
+#define _(x) ()
+#endif
+
+long get_long _((void));
+long get_sized _((int sz));
+unsigned int get_word _((void));
+int get_byte _((void));
+int main _((int argc, char**argv));
+void do_file _((char * fname));
+long read_arheader _((char *archentry));
+void do_module _((char * fname, char *archive));
+int error _((char * str));
+int read_objheader _((void));
+int read_sectheader _((void));
+int read_syms _((void));
+void disp_sectheader _((void));
+int disp_syms _((void));
+void read_databytes _((void));
+void hex_output _((int ch));
+void fetch_aout_hdr _((void));
+void dump_aout _((void));
+void size_aout _((void));
+void nm_aout _((void));
+#ifndef VERY_SMALL_MEMORY
+void fetch_v7_hdr _((void));
+void dump_v7 _((void));
+void size_v7 _((void));
+#endif
+
+int obj_ver;
+int sections;
+long segsizes[16];
+long textoff;
+long textlen;
+long str_off;
+long str_len;
+long filepos;
+int num_syms;
+long code_bytes;
+
+char ** symnames;
+char * strtab;
+
+struct {
+ unsigned int nameoff, symtype;
+ long offset;
+} *symtab;
+
+int display_mode = 0;
+int multiple_files = 0;
+int byte_order = 0;
+
+int opt_o;
+
+long size_text, size_data, size_bss;
+long tot_size_text=0, tot_size_data=0, tot_size_bss=0;
+
+int
+main(argc, argv)
+int argc;
+char ** argv;
+{
+ int ar;
+ char * p;
+
+ ifd = stdin; /* In Libc6 stdin is weird */
+
+ p = strrchr(argv[0], '/');
+ if(p) p++; else p=argv[0];
+
+ if( p[0] == 's' ) display_mode = 1;
+ if( p[0] == 'n' ) display_mode = 2;
+
+ multiple_files = 0;
+ for(ar=1; ar<argc; ar++)
+ {
+ if( argv[ar][0] == '-' ) switch(argv[ar][1])
+ {
+ case 's': display_mode = 1; break;
+ case 'n': display_mode = 2; break;
+ case 'o': opt_o++; break;
+ }
+ else
+ multiple_files++;
+ }
+
+ if( !multiple_files ) exit(1);
+
+ multiple_files = (multiple_files>1);
+
+ if( display_mode == 1 )
+ printf("text\tdata\tbss\tdec\thex\tfilename\n");
+
+ for(ar=1; ar<argc; ar++) if(argv[ar][0] != '-')
+ do_file(argv[ar]);
+
+ if( display_mode == 1 && multiple_files)
+ printf("%ld\t%ld\t%ld\t%ld\t%lx\tTotal\n",
+ tot_size_text, tot_size_data, tot_size_bss,
+ tot_size_text+ tot_size_data+ tot_size_bss,
+ tot_size_text+ tot_size_data+ tot_size_bss);
+
+ return 0;
+}
+
+void
+do_file(fname)
+char * fname;
+{
+ unsigned int magic;
+ long filelength;
+ char archentry[sizeof(struct ar_hdr)]; /* sizeof ar_hdr.ar_name*/
+ char filemagic[SARMAG];
+
+ ifname = fname;
+ if( (ifd=fopen(fname, "rb")) == 0 )
+ {
+ error("Cannot open file");
+ return;
+ }
+ filepos = 0L;
+
+ /* check if file is an archive*/
+ if(fread(filemagic, sizeof(filemagic), 1, ifd) == 1
+ && strncmp(filemagic, ARMAG, sizeof filemagic) == 0)
+ {
+ filepos = SARMAG;
+ while((filelength = read_arheader(archentry)) > 0)
+ {
+ filepos += sizeof(struct ar_hdr);
+ magic = get_word();
+ if(magic == 0x86A3)
+ { /* OMAGIC*/
+ fseek(ifd, filepos, 0);
+ do_module(archentry, fname);
+ }
+ else if(magic == 0x3C21 ) /* "!<" */
+ filelength = SARMAG;
+ filepos += ld_roundup(filelength, 2, long);
+ fseek(ifd, filepos, 0);
+ }
+ }
+ else
+ {
+ fseek(ifd, 0L, 0);
+ do_module(fname, NULL);
+ }
+ fclose(ifd);
+}
+
+/* read archive header and return length */
+long
+read_arheader(archentry)
+char *archentry;
+{
+ char * endptr;
+ struct ar_hdr arheader;
+
+ if(fread((char *)&arheader, sizeof(arheader), 1, ifd) != 1)
+ return 0;
+ strncpy(archentry, arheader.ar_name, sizeof(arheader.ar_name));
+ archentry[sizeof(arheader.ar_name)] = 0;
+ endptr = archentry + sizeof(arheader.ar_name);
+ do
+ {
+ *endptr-- = 0;
+ } while(endptr > archentry && (*endptr == ' ' || *endptr == '/'));
+ return strtoul(arheader.ar_size, (char **)NULL, 0);
+}
+
+void
+do_module(fname, archive)
+char * fname;
+char * archive;
+{
+ int modno, i;
+
+ size_text = size_data = size_bss = 0;
+ byte_order = 0;
+
+ if( !display_mode )
+ {
+ if(archive)
+ printf("ARCHIVEFILE '%s'\n", archive);
+ printf("OBJECTFILE '%s'\n", fname);
+ }
+
+ switch( read_objheader() )
+ {
+ case 0: /* as86 object file */
+
+ for(modno=1; modno<=sections; modno++)
+ {
+ if( modno != 1 && !display_mode )
+ printf("OBJECTSECTION %d\n", modno);
+ if( read_sectheader() < 0 ) break;
+
+ /* segments 0, 4-E are text, 1-3 are data*/
+ for(i=0; i<16; i++)
+ {
+ if(i < 1 || i > 4)
+ size_text += segsizes[i];
+ else size_data += segsizes[i];
+ }
+
+ if( read_syms() < 0 ) break;
+
+ strtab = malloc((unsigned int)str_len+1);
+ if( strtab == 0 ) { error("Out of memory"); break; }
+ str_off = ftell(ifd);
+ fread(strtab, 1, (unsigned int)str_len, ifd);
+
+ disp_sectheader();
+ disp_syms();
+
+ if( display_mode == 0 )
+ printf("text\tdata\tbss\tdec\thex\tfilename\n");
+ if( display_mode != 2 )
+ {
+ printf("%ld\t%ld\t%ld\t%ld\t%lx\t",
+ size_text, size_data, size_bss,
+ size_text+ size_data+ size_bss,
+ size_text+ size_data+ size_bss);
+
+ if(archive) printf("%s(%s)\n", archive, fname);
+ else printf("%s\n", fname);
+
+ tot_size_text += size_text;
+ tot_size_data += size_data;
+ tot_size_bss += size_bss;
+ }
+
+ if( sections == 1 && display_mode != 0 )
+ break;
+
+ read_databytes();
+ }
+ break;
+
+ case 1: /* ELKS executable */
+ fseek(ifd, 0L, 0);
+ fetch_aout_hdr();
+
+ switch(display_mode)
+ {
+ case 0: dump_aout(); break;
+ case 1: size_aout(); break;
+ case 2: nm_aout(); break;
+ }
+ break;
+#ifndef VERY_SMALL_MEMORY
+ case 2: /* V7 executable */
+ fseek(ifd, 0L, 0);
+ fetch_v7_hdr();
+
+ switch(display_mode)
+ {
+ case 0: dump_v7(); break;
+ case 1: size_v7(); break;
+ case 2: error("Symbol table not supported for v7"); exit(1); break;
+ }
+ break;
+#endif
+ }
+
+ if( strtab ) free(strtab);
+ if( symnames ) free(symnames);
+ strtab = 0;
+ symnames = 0;
+}
+
+int
+error(str)
+char * str;
+{
+ switch( display_mode )
+ {
+ case 1: fprintf(stderr, "size: %s: %s\n", ifname, str); break;
+ case 2: fprintf(stderr, "nm: %s: %s\n", ifname, str); break;
+ default:
+ printf("Error: %s\n", str);
+ break;
+ }
+ return -1;
+}
+
+int
+read_objheader()
+{
+ unsigned char buf[5];
+
+ if( fread(buf, 1, 5, ifd) != 5 )
+ return error("Cannot read object header");
+
+ if( buf[0] != 0xA3 || buf[1] != 0x86 )
+ {
+ if( buf[0] == 1 && buf[1] == 3 )
+ {
+ sections = 1;
+ return 1;
+ }
+#ifndef VERY_SMALL_MEMORY
+ if( buf[1] == 1 ) /* 04xx octal */
+ {
+ sections = 1;
+ return 2;
+ }
+#endif
+ return error("Bad magic number");
+ }
+
+ if( (unsigned char)(buf[0] + buf[1] + buf[2] + buf[3]) != buf[4] )
+ return error("Bad header checksum");
+
+ sections= buf[2]+256*buf[3];
+
+ return 0;
+}
+
+int
+read_sectheader()
+{
+ long ssenc;
+ int i;
+
+ textoff = get_long(); /* Offset of bytecode in file */
+ textlen = get_long(); /* Length of text+data (no bss) in memory */
+ str_len = get_word(); /* Length of string table in file */
+ obj_ver = get_word(); /* 0.0 */
+
+ (void)get_long(); /* Ignore fives */
+ ssenc = get_long(); /* Sixteen segment size sizes */
+
+ for(i=0; i<16; i++)
+ {
+ int ss;
+ ss = (i^3);
+ ss = ((ssenc>>(2*(15-ss)))&3);
+ segsizes[i] = get_sized(ss);
+ }
+
+ num_syms = get_word(); /* Number of symbol codes */
+
+ return 0;
+}
+
+void
+disp_sectheader()
+{
+ int i;
+ if( display_mode ) return;
+
+ printf("MODULE '%s'\n", strtab);
+ printf("BYTEPOS %08lx\n", textoff);
+ printf("BINLEN %08lx\n", textlen);
+ printf("STRINGS %04lx +%04lx\n", str_off, str_len);
+ printf("VERSION %d.%d\n", obj_ver/256, obj_ver%256);
+
+ for(i=0; i<16; i++)
+ if( segsizes[i] )
+ printf("SEG%x %08lx\n", i, segsizes[i]);
+
+ printf("\n");
+ printf("SYMS %u\n", num_syms);
+}
+
+int
+read_syms()
+{
+ int i;
+
+ if( num_syms < 0 ) return error("Bad symbol table");
+
+ symnames = malloc(num_syms*sizeof(char*)+1);
+ if( symnames == 0 ) return error("Out of memory");
+
+ symtab = calloc(num_syms, sizeof(*symtab));
+ if( symtab == 0 ) return error("Out of memory");
+
+ for(i=0; i<num_syms; i++)
+ {
+ unsigned int symtype;
+
+ symtab[i].nameoff = get_word();
+ symtab[i].symtype = get_word();
+ symtype = (symtab[i].symtype & 0x3FFF);
+
+ if (symtab[i].nameoff == -1 || symtab[i].symtype == -1) {
+ printf("!!! EOF in symbol table\n");
+ break;
+ }
+ symtab[i].offset = get_sized((symtab[i].symtype>>14)&3);
+
+ if( symtype == 0x43 || symtype == 0x2003 )
+ size_bss += symtab[i].offset;
+ }
+
+ return 0;
+}
+
+int
+disp_syms()
+{
+ int i;
+
+ if(display_mode == 2 && multiple_files && !opt_o)
+ printf("\n%s:\n", ifname);
+
+ for(i=0; i<num_syms; i++)
+ {
+ long offset=0;
+ unsigned int nameoff, symtype;
+
+ nameoff = symtab[i].nameoff;
+ symtype = symtab[i].symtype;
+ offset = symtab[i].offset;
+
+ symtype &= 0x3FFF;
+ if (nameoff > str_len || nameoff < 0)
+ symnames[i] = strtab + str_len;
+ else
+ symnames[i] = strtab+nameoff;
+
+ if( !display_mode )
+ {
+ printf("SYM %-4d %08lx ", i, offset);
+
+ printf("%s", (symtype&0x2000)?"C":".");
+ printf("%s", (symtype&0x0100)?"N":".");
+ printf("%s", (symtype&0x0080)?"E":".");
+ printf("%s", (symtype&0x0040)?"I":".");
+ printf("%c", "T12D456789abcdeUAhijklmnopqrstuv"[symtype&0x1F]);
+ if( symtype &0x1E20 )
+ printf(" %04x", symtype);
+ printf(" %s\n", symnames[i]);
+ }
+ if( display_mode == 2 )
+ {
+ if (opt_o)
+ printf("%s: ", ifname);
+ if( symtype == 0x004f || symtype == 0x0040 )
+ printf(" ");
+ else
+ printf("%08lx ", offset);
+ switch(symtype)
+ {
+ case 0x004F: putchar('U'); break;
+ case 0x0000: putchar('t'); break;
+ case 0x0003: putchar('d'); break;
+ case 0x2003: putchar('b'); break;
+ case 0x0043: putchar('C'); break;
+ case 0x0083: putchar('D'); break;
+ case 0x0080: putchar('T'); break;
+ case 0x0040: putchar('T'); break;
+ case 0x0180: putchar('N'); break;
+ case 0x0010: putchar('a'); break;
+ case 0x0090: putchar('A'); break;
+ default:
+ if((symtype & ~0xF) == 0x40 )
+ putchar('u');
+ else if((symtype & ~0xF) == 0x80 )
+ printf("%c", "T12D456789abcdeU"[symtype&0xF]);
+ else
+ putchar('?');
+ break;
+ }
+ printf(" %s\n", symnames[i]);
+ }
+ }
+ if( !display_mode )
+ printf("\n");
+
+ return 0;
+}
+
+void
+read_databytes()
+{
+static char * relstr[] = {"ERR", "DB", "DW", "DD"};
+ long l, cpos;
+ int ch, i;
+ int curseg = 0;
+ int relsize = 0;
+
+ cpos = ftell(ifd);
+ fseek(ifd, filepos+textoff, 0);
+
+ printf("\nBYTECODE\n");
+ for(;;)
+ {
+ if( (ch=get_byte()) == -1 ) break;
+
+ if( ch == 0 ) break;
+
+ switch( ch & 0xC0 )
+ {
+ case 0x00: switch(ch & 0xF0)
+ {
+ case 0x00: /* Relocator size */
+ printf("RELSZ %d\n", relsize= (ch&0xF));
+ if(relsize>3) relsize=3;
+ break;
+ case 0x10: /* Skip bytes */
+ printf("SKP %ld\n", get_sized(ch&0xF));
+ break;
+ case 0x20: /* Segment */
+ printf("SEG %x\n", curseg= (ch&0xF));
+ break;
+ default: printf("CODE %02x - unknown\n", ch);
+ goto break_break ;
+ }
+ break;
+ case 0x40: /* Raw bytes */
+ {
+ int abscnt = (ch&0x3F);
+ if( abscnt == 0 ) abscnt = 64;
+ for( i=0; i<abscnt; i++ )
+ {
+ if( (ch=get_byte()) == -1 ) break;
+ hex_output(ch);
+ }
+ hex_output(EOF);
+
+ if( ch == -1 ) goto break_break;
+ }
+ break;
+ case 0x80: /* Relocator - simple */
+ l = get_sized(relsize);
+ printf("%s SEG%x%s%s", relstr[relsize],
+ (ch&0xF),
+ (ch&0x20)?"-PC":"",
+ (ch&0x10)?"+?":"");
+ if(l)
+ printf("+0x%04lx", l);
+ putchar('\n');
+ break;
+ case 0xC0: /* Relocator - symbol relative */
+ if( ch & 0x18 )
+ {
+ printf("CODE %02x - unknown\n", ch);
+ goto break_break;
+ }
+ if( ch & 4 ) i = get_word();
+ else i = get_byte();
+ l = get_sized(ch&3);
+
+ printf("%s %s%s%s", relstr[relsize],
+ symnames[i],
+ (ch&0x20)?"-PC":"",
+ (ch&0x18)?"+?":"");
+ if(l)
+ printf("+0x%04lx", l);
+ putchar('\n');
+ break;
+ }
+ }
+break_break:;
+ printf("\n");
+ fseek(ifd, cpos, 0);
+}
+
+long
+get_sized(sz)
+int sz;
+{
+ switch(sz)
+ {
+ case 0: return 0;
+ case 1: return get_byte();
+ case 2: return get_word();
+ case 3: return get_long();
+ }
+ return -1;
+}
+
+long
+get_long()
+{
+ long retv = 0;
+ int i;
+ for(i=0; i<32; i+=16)
+ {
+ unsigned int v = get_word();
+ if( byte_order & 2 )
+ retv += ((long)v<<(16-i));
+ else
+ retv += ((long)v<<i);
+ }
+ return retv;
+}
+
+unsigned int
+get_word()
+{
+ long retv = 0;
+ int i;
+ for(i=0; i<16; i+=8)
+ {
+ int v = getc(ifd);
+ if( v == EOF ) return -1;
+ code_bytes++;
+ if( byte_order & 1 )
+ retv += (v<<(8-i));
+ else
+ retv += (v<<i);
+ }
+ return retv;
+}
+
+int
+get_byte()
+{
+ int v = getc(ifd);
+ if (v == EOF) return -1;
+ code_bytes++;
+ return v;
+}
+
+void
+hex_output(ch)
+int ch;
+{
+static char linebuf[80];
+static char buf[20];
+static int pos = 0;
+
+ if( ch == EOF )
+ {
+ if(pos)
+ printf(": %.66s\n", linebuf);
+ pos = 0;
+ }
+ else
+ {
+ if(!pos)
+ memset(linebuf, ' ', sizeof(linebuf));
+ sprintf(buf, "%02x", ch&0xFF);
+ memcpy(linebuf+pos*3+(pos>7), buf, 2);
+ if( ch > ' ' && ch <= '~' ) linebuf[50+pos] = ch;
+ else linebuf[50+pos] = '.';
+ pos = ((pos+1) & 0xF);
+ if( pos == 0 )
+ {
+ printf(": %.66s\n", linebuf);
+ memset(linebuf, ' ', sizeof(linebuf));
+ }
+ }
+}
+
+/************************************************************************/
+/* ELKS a.out versions
+ */
+
+long header[12];
+int h_len, h_flgs, h_cpu;
+
+void
+fetch_aout_hdr()
+{
+ int i;
+
+ header[0] = get_long();
+ header[1] = get_long();
+ byte_order = ((header[0]>>24) & 3);
+
+ h_len = (header[1] & 0xFF);
+ h_flgs = ((header[0]>>16) & 0xFF);
+ h_cpu = ((header[0]>>24) & 0xFF);
+
+ for(i=2; i<8; i++)
+ {
+ if( i*4 <= h_len )
+ header[i] = get_long();
+ else
+ header[i] = 0;
+ }
+}
+
+void
+dump_aout()
+{
+static char * cpu[] = { "unknown", "8086", "m68k", "ns16k", "i386", "sparc" };
+static char * byteord[] = { "LITTLE_ENDIAN", "(2143)","(3412)","BIG_ENDIAN" };
+ int i;
+ long l;
+
+ if( h_cpu > 0x17 ) h_cpu &= 3;
+
+ printf("HLEN %d\n", h_len);
+ printf("CPU %s %s\n", cpu[h_cpu>>2], byteord[h_cpu&3]);
+
+ printf("FLAGS:");
+ if( h_flgs & 0x01 ) printf(" A_UZP");
+ if( h_flgs & 0x02 ) printf(" A_PAL");
+ if( h_flgs & 0x04 ) printf(" A_NSYM");
+ if( h_flgs & 0x08 ) printf(" FLG-08");
+ if( h_flgs & 0x10 ) printf(" A_EXEC");
+ if( h_flgs & 0x20 ) printf(" A_SEP");
+ if( h_flgs & 0x40 ) printf(" A_PURE");
+ if( h_flgs & 0x80 ) printf(" A_TOVLY");
+ printf("\n");
+
+ if( header[5] )
+ printf("a_entry = 0x%08lx\n", header[5]);
+ printf("a_total = 0x%08lx\n", header[6]);
+ if( header[7] )
+ printf("a_syms = 0x%08lx\n", header[7]);
+
+ if( h_len >= 36 )
+ printf("a_trsize = 0x%08lx\n", header[8]);
+ if( h_len >= 40 )
+ printf("a_drsize = 0x%08lx\n", header[9]);
+ if( h_len >= 44 )
+ printf("a_tbase = 0x%08lx\n", header[10]);
+ if( h_len >= 48 )
+ printf("a_dbase = 0x%08lx\n", header[11]);
+ printf("\n");
+
+ size_aout();
+ printf("\n");
+
+ if( header[7] )
+ {
+ printf("SYMBOLS\n");
+ nm_aout();
+ }
+ else
+ printf("NO SYMBOLS\n");
+ printf("\n");
+
+ printf("TEXTSEG\n");
+ fseek(ifd, (long)h_len, 0);
+ for(l=0; l<header[2]; l++)
+ {
+ if( (i=getc(ifd)) == EOF ) break;
+ hex_output(i);
+ }
+ hex_output(EOF);
+
+ printf("DATASEG\n");
+ fseek(ifd, (long)h_len+header[2], 0);
+ for(l=0; l<header[3]; l++)
+ {
+ if( (i=getc(ifd)) == EOF ) break;
+ hex_output(i);
+ }
+ hex_output(EOF);
+}
+
+void
+size_aout()
+{
+ if( display_mode == 0 )
+ printf("text\tdata\tbss\tdec\thex\tfilename\n");
+
+ printf("%ld\t%ld\t%ld\t%ld\t%lx\t%s\n",
+ header[2], header[3], header[4],
+ header[2]+ header[3]+ header[4],
+ header[2]+ header[3]+ header[4],
+ ifname);
+
+ tot_size_text += header[2];
+ tot_size_data += header[3];
+ tot_size_bss += header[4];
+}
+
+void
+nm_aout()
+{
+ char n_name[10];
+ long n_value;
+ int n_sclass, n_numaux, n_type;
+ long bytes_left;
+ int pending_nl = 0;
+
+ fseek(ifd, h_len+header[2]+header[3]+header[8]+header[9], 0);
+
+ if( h_flgs & 4 )
+ { error("Executable has new format symbol table.\n"); return; }
+
+ bytes_left = header[7];
+
+ if( bytes_left == 0 )
+ printf("No symbols in '%s'\n", ifname);
+ else if(multiple_files && !opt_o)
+ printf("\n%s:\n", ifname);
+
+ while(bytes_left > 16)
+ {
+ if( fread(n_name, 1, 8, ifd) != 8 ) break;
+ n_name[8] = 0;
+ n_value = get_long();
+ if( (n_sclass = getc(ifd)) == EOF ) break;
+ if( (n_numaux = getc(ifd)) == EOF ) break;
+ n_type = get_word();
+
+ if( pending_nl && n_sclass == 0 )
+ {
+ printf("%s", n_name);
+ continue;
+ }
+
+ if( pending_nl ) putchar('\n');
+ if (opt_o)
+ printf("%s: ", ifname);
+ if( n_sclass == 0x10 )
+ printf(" ");
+ else
+ printf("%08lx ", n_value);
+ switch(n_sclass)
+ {
+ case 0x01: printf("a "); break;
+ case 0x12: printf("T "); break;
+ case 0x13: printf("D "); break;
+ case 0x14: printf("C "); break;
+ case 0x1a: printf("t "); break;
+ case 0x1b: printf("d "); break;
+ case 0x1c: printf("b "); break;
+ case 0x10: printf("U "); break;
+ default: if( display_mode )
+ {
+ printf("? "); break;
+ }
+
+ printf("n_sclass=");
+ switch(n_sclass>>3)
+ {
+ case 0: printf("C_NULL,"); break;
+ case 2: printf("C_EXT,"); break;
+ case 3: printf("C_STAT,"); break;
+ default: printf("%04o,", n_sclass&0xF8);
+ }
+ switch(n_sclass&7)
+ {
+ case 0: printf("N_UNDF "); break;
+ case 1: printf("N_ABS "); break;
+ case 2: printf("N_TEXT "); break;
+ case 3: printf("N_DATA "); break;
+ case 4: printf("N_BSS "); break;
+ case 5: printf("N_COMM "); break;
+ default: printf("%o ", n_sclass&7); break;
+ }
+ break;
+ }
+
+ if( display_mode == 0 )
+ {
+ if( n_numaux )
+ printf("n_numaux=%02x ", n_numaux);
+ if( n_type )
+ printf("n_type=%04x ", n_type);
+ }
+
+ printf("%s", n_name);
+
+ pending_nl=1;
+ }
+
+ if( pending_nl ) putchar('\n');
+}
+
+#ifndef VERY_SMALL_MEMORY
+/************************************************************************/
+/* V7 a.out versions
+ */
+
+void
+fetch_v7_hdr()
+{
+ int i;
+
+ h_len = 8;
+ for(i=0; i<h_len; i++)
+ {
+ header[i] = get_word();
+ }
+}
+
+void
+size_v7()
+{
+ if( display_mode == 0 )
+ printf("text\tdata\tbss\tdec\thex\tfilename\n");
+
+ printf("%ld\t%ld\t%ld\t%ld\t%lx\t%s\n",
+ header[1], header[2], header[3],
+ header[1]+ header[2]+ header[3],
+ header[1]+ header[2]+ header[3],
+ ifname);
+
+ tot_size_text += header[1];
+ tot_size_data += header[2];
+ tot_size_bss += header[3];
+}
+
+void
+dump_v7()
+{
+ int i;
+ long l;
+
+ printf("TYPE:");
+ switch (header[0]) {
+ case 0405: printf(" overlay"); break;
+ case 0407: printf(" impure"); break;
+ case 0410: printf(" read-only text"); break;
+ case 0411: printf(" pure"); break;
+ case 0413: printf(" demand load"); break;
+ default: printf(" (unknown)"); break;
+ }
+ printf("\n");
+
+ if( header[5] )
+ printf("a_entry = 0x%08lx\n", header[5]);
+ printf("\n");
+
+ size_aout();
+ printf("\n");
+
+ printf("TEXTSEG\n");
+ fseek(ifd, (long)h_len, 0);
+ for(l=0; l<header[1]; l++)
+ {
+ if( (i=getc(ifd)) == EOF ) break;
+ hex_output(i);
+ }
+ hex_output(EOF);
+
+ printf("DATASEG\n");
+ fseek(ifd, (long)h_len+header[1], 0);
+ for(l=0; l<header[2]; l++)
+ {
+ if( (i=getc(ifd)) == EOF ) break;
+ hex_output(i);
+ }
+ hex_output(EOF);
+}
+#endif
--- /dev/null
+/* readobj.c - read object file for linker */
+
+/* Copyright (C) 1994 Bruce Evans */
+
+#include "syshead.h"
+#include "ar.h" /* maybe local copy of <ar.h> for cross-link */
+#include "const.h"
+#include "byteord.h"
+#include "obj.h"
+#include "type.h"
+#include "globvar.h"
+
+/*
+ Linking takes 2 passes. The 1st pass reads through all files specified
+in the command line, and all libraries. All public symbols are extracted
+and stored in a chained hash table. For each module, its file and header
+data recorded, and the resulting structures are chained together
+(interleaved with the symbols).
+
+ The symbol descriptors are separated from the symbol names, so we must
+record all the descriptors of a module before putting the symbols in the
+symbol table (poor design). The descriptors are stored in the symbol
+table, then moved to the top of the table to make room for the symols.
+The symbols referred to in a given module are linked together by a chain
+beginning in the module descriptor.
+*/
+
+PRIVATE unsigned convertsize[NSEG / 4] = {0, 1, 2, 4};
+PRIVATE struct entrylist *entrylast; /* last on list of entry symbols */
+PRIVATE struct redlist *redlast; /* last on list of redefined symbols */
+PRIVATE struct modstruct *modlast; /* data for last module */
+
+FORWARD long readarheader P((char **parchentry));
+FORWARD unsigned readfileheader P((void));
+FORWARD void readmodule P((char *filename, char *archentry));
+FORWARD void reedmodheader P((void));
+FORWARD bool_pt redsym P((struct symstruct *symptr, bin_off_t value));
+FORWARD unsigned checksum P((char *string, unsigned length));
+FORWARD unsigned segbits P((unsigned seg, char *sizedesc));
+
+/* initialise object file handler */
+
+PUBLIC void objinit()
+{
+ modfirst = modlast = NUL_PTR;
+ entryfirst = entrylast = NUL_PTR;
+ redfirst = redlast = NUL_PTR;
+}
+
+/* read all symbol definitions in an object file */
+
+PUBLIC void readsyms(filename, trace)
+char *filename;
+bool_pt trace;
+{
+ char *archentry;
+ long filelength;
+ char filemagic[SARMAG];
+ unsigned long filepos;
+ unsigned modcount;
+
+ if (trace)
+ errtrace(filename, 0);
+ openin(filename); /* input is not open, so position is start */
+ switch ((unsigned) readsize(2))
+ {
+ case OMAGIC:
+ seekin((unsigned long) 0);
+ for (modcount = readfileheader(); modcount-- != 0;)
+ readmodule(filename, (char *) NUL_PTR);
+ break;
+ default:
+ seekin((unsigned long) 0);
+ readin(filemagic, sizeof filemagic);
+ if (strncmp(filemagic, ARMAG, sizeof filemagic) != 0)
+ input1error(" has bad magic number");
+ filepos = SARMAG;
+ while ((filelength = readarheader(&archentry)) > 0)
+ {
+ unsigned int magic;
+ if (trace)
+ errtrace(archentry, 2);
+ filepos += sizeof(struct ar_hdr);
+ magic = (unsigned) readsize(2);
+ if(magic == OMAGIC)
+ {
+ seekin(filepos);
+ for (modcount = readfileheader(); modcount-- != 0;)
+ {
+ readmodule(stralloc(filename), archentry);
+ modlast->textoffset += filepos;
+ }
+ }
+ else if( magic == 0x3C21 ) /* "!<" */
+ filelength = SARMAG;
+ seekin(filepos += ld_roundup(filelength, 2, long));
+ }
+ break;
+ }
+ closein();
+}
+
+/* read archive header and return length */
+
+PRIVATE long readarheader(parchentry)
+char **parchentry;
+{
+ struct ar_hdr arheader;
+ char *endptr;
+ char *nameptr;
+
+ if (readineofok((char *) &arheader, sizeof arheader))
+ return 0;
+ strncpy (*parchentry = nameptr = ourmalloc(sizeof arheader.ar_name + 1),
+ arheader.ar_name, sizeof arheader.ar_name);
+ endptr = nameptr + sizeof arheader.ar_name;
+ do
+ *endptr-- = 0;
+ while (endptr > nameptr && (*endptr == ' ' || *endptr == '/'));
+ return strtoul(arheader.ar_size, (char **) NUL_PTR, 0);
+}
+
+/* read and check file header of the object file just opened */
+
+PRIVATE unsigned readfileheader()
+{
+ struct
+ {
+ char magic[2];
+ char count[2]; /* really an int */
+ }
+ fileheader;
+ char filechecksum; /* part of fileheader but would unalign */
+
+ readin((char *) &fileheader, sizeof fileheader);
+ readin(&filechecksum, sizeof filechecksum);
+ if (filechecksum != checksum((char *) &fileheader, sizeof fileheader))
+ input1error(" is not an object file (checksum failed)");
+ return c2u2(fileheader.count);
+}
+
+/* read the next module */
+
+PRIVATE void readmodule(filename, archentry)
+char *filename;
+char *archentry;
+{
+ struct symdstruct /* to save parts of symbol before name known */
+ {
+ bin_off_t dvalue;
+ flags_t dflags;
+ };
+ struct symdstruct *endsymdptr;
+ flags_t flags;
+ unsigned nsymbol;
+ struct symdstruct *symdptr;
+ char *symname;
+ struct symstruct **symparray;
+ struct symstruct *symptr;
+
+ reedmodheader();
+ modlast->filename = filename;
+ modlast->archentry = archentry;
+ nsymbol = readsize(2);
+ symdptr = (struct symdstruct *)
+ ourmalloc(nsymbol * sizeof(struct symdstruct));
+ for (endsymdptr = symdptr + nsymbol; symdptr < endsymdptr; ++symdptr)
+ {
+ readsize(2); /* discard string offset, assume strings seq */
+ symdptr->dflags = flags = readsize(2);
+ symdptr->dvalue = readconvsize((flags & SZ_MASK) >> SZ_SHIFT);
+ /* NB unsigned flags to give logical shift */
+ /* bug in Xenix 2.5 cc causes (int) of the */
+ /* argument to turn flags into an int */
+ }
+ symdptr = (struct symdstruct *)
+ moveup(nsymbol * sizeof(struct symdstruct));
+ modlast->symparray = symparray = (struct symstruct **)
+ ourmalloc((nsymbol + 1) * sizeof(struct symstruct *));
+ symname = readstring(); /* module name */
+ modlast->modname = stralloc(symname); /* likely OK overlapped copy */
+ for (endsymdptr = symdptr + nsymbol; symdptr < endsymdptr;
+ *symparray++ = symptr, release((char *) ++symdptr))
+ {
+ symname = readstring();
+ if ((flags = symdptr->dflags) & (E_MASK | I_MASK) &&
+ (symptr = findsym(symname)) != NUL_PTR)
+ {
+ /*
+ weaken segment-checking by letting the maximum segment
+ (SEGM_MASK) mean any segment
+ */
+ if ((symptr->flags & SEGM_MASK) == SEGM_MASK)
+ symptr->flags &= ~(flags_t) SEGM_MASK | (flags & SEGM_MASK);
+ else if ((flags & SEGM_MASK) == SEGM_MASK)
+ flags &= ~(flags_t) SEGM_MASK | (symptr->flags & SEGM_MASK);
+ if ((flags ^ symptr->flags) & (A_MASK | SEGM_MASK))
+ {
+ redefined(symname, " with different segment or relocatability",
+ archentry, symptr->modptr->filename,
+ symptr->modptr->archentry);
+ continue;
+ }
+ if (symptr->flags & E_MASK)
+ {
+ if (flags & E_MASK && redsym(symptr, symdptr->dvalue))
+ redefined(symname, "", archentry, symptr->modptr->filename,
+ symptr->modptr->archentry);
+ continue;
+ }
+ if (flags & I_MASK && symdptr->dvalue <= symptr->value)
+ continue;
+ }
+ else
+ symptr = addsym(symname);
+ symptr->modptr = modlast;
+ symptr->value = symdptr->dvalue;
+ symptr->flags = flags;
+ if (flags & N_MASK)
+ entrysym(symptr);
+ }
+ *symparray = NUL_PTR;
+}
+
+/* put symbol on entry symbol list if it is not already */
+
+PUBLIC void entrysym(symptr)
+struct symstruct *symptr;
+{
+ register struct entrylist *elptr;
+
+ for (elptr = entryfirst; elptr != NUL_PTR; elptr = elptr->elnext)
+ if (symptr == elptr->elsymptr)
+ return;
+ elptr = (struct entrylist *) ourmalloc(sizeof(struct entrylist));
+ elptr->elnext = NUL_PTR;
+ elptr->elsymptr = symptr;
+ if (entryfirst == NUL_PTR)
+ entryfirst = elptr;
+ else
+ entrylast->elnext = elptr;
+ entrylast = elptr;
+}
+
+/* read the header of the next module */
+
+PRIVATE void reedmodheader()
+{
+ struct
+ {
+ char htextoffset[4]; /* offset to module text in file */
+ char htextsize[4]; /* size of text (may be 0 for last mod) */
+ char stringssize[2]; /* size of string area */
+ char hclass; /* module class */
+ char revision; /* module revision */
+ }
+ modheader;
+ unsigned seg;
+ unsigned count;
+ char *cptr;
+ struct modstruct *modptr;
+
+ readin((char *) &modheader, sizeof modheader);
+ modptr = (struct modstruct *) ourmalloc(sizeof(struct modstruct));
+ modptr->modnext = NUL_PTR;
+ modptr->textoffset = c4u4(modheader.htextoffset);
+ modptr->class = modheader.hclass;
+ readin(modptr->segmaxsize, sizeof modptr->segmaxsize);
+ readin(modptr->segsizedesc, sizeof modptr->segsizedesc);
+ cptr = modptr->segsize;
+ for (seg = 0; seg < NSEG; ++seg)
+ {
+ if ((count = segsizecount(seg, modptr)) != 0)
+ {
+ if (cptr == modptr->segsize)
+ ourmalloc(count - 1); /* 1st byte reserved in struct */
+ else
+ ourmalloc(count);
+ readin(cptr, count);
+ cptr += count;
+ }
+ }
+ if (modfirst == NUL_PTR)
+ modfirst = modptr;
+ else
+ modlast->modnext = modptr;
+ modlast = modptr;
+}
+
+PRIVATE bool_pt redsym(symptr, value)
+register struct symstruct *symptr;
+bin_off_t value;
+{
+ register struct redlist *rlptr;
+ char class;
+
+ if (symptr->modptr->class != (class = modlast->class))
+ for (rlptr = redfirst;; rlptr = rlptr->rlnext)
+ {
+ if (rlptr == NUL_PTR)
+ {
+ rlptr = (struct redlist *)
+ ourmalloc(sizeof(struct redlist));
+ rlptr->rlnext = NUL_PTR;
+ rlptr->rlsymptr = symptr;
+ if (symptr->modptr->class < class)
+ /* prefer lower class - put other on redlist */
+ {
+ rlptr->rlmodptr = modlast;
+ rlptr->rlvalue = value;
+ }
+ else
+ {
+ rlptr->rlmodptr = symptr->modptr;
+ symptr->modptr = modlast;
+ rlptr->rlvalue = symptr->value;
+ symptr->value = value;
+ }
+ if (redfirst == NUL_PTR)
+ redfirst = rlptr;
+ else
+ redlast->rlnext = rlptr;
+ redlast = rlptr;
+ return FALSE;
+ }
+ if (symptr == rlptr->rlsymptr && class == rlptr->rlmodptr->class)
+ break;
+ }
+ return TRUE;
+}
+
+PRIVATE unsigned checksum(string, length)
+char *string;
+unsigned length;
+{
+ unsigned char sum; /* this is a 1-byte checksum */
+
+ for (sum = 0; length-- != 0;)
+ sum += *string++ & 0xFF;
+ return sum;
+}
+
+PUBLIC bin_off_t readconvsize(countindex)
+unsigned countindex;
+{
+ return readsize(convertsize[countindex]);
+}
+
+PUBLIC bin_off_t readsize(count)
+unsigned count;
+{
+ char buf[MAX_OFFSET_SIZE];
+
+ if (count == 0)
+ return 0;
+ readin(buf, count);
+ return cntooffset(buf, count);
+}
+
+PRIVATE unsigned segbits(seg, sizedesc)
+unsigned seg;
+char *sizedesc;
+{
+ return 3 & ((unsigned) sizedesc[((NSEG - 1) - seg) / 4] >> (2 * (seg % 4)));
+ /* unsigned to give logical shift */
+}
+
+PUBLIC unsigned segsizecount(seg, modptr)
+unsigned seg;
+struct modstruct *modptr;
+{
+ return convertsize[segbits(seg, modptr->segsizedesc)];
+}
--- /dev/null
+#ifndef _BSD_A_OUT_H
+#define _BSD_A_OUT_H
+
+struct exec { /* a.out header */
+ unsigned char a_magic[2]; /* magic number */
+ unsigned char a_flags; /* flags, see below */
+ unsigned char a_cpu; /* cpu id */
+ unsigned char a_hdrlen; /* length of header */
+ unsigned char a_unused; /* reserved for future use */
+ unsigned short a_version; /* version stamp (not used at present) */
+ long a_text; /* size of text segement in bytes */
+ long a_data; /* size of data segment in bytes */
+ long a_bss; /* size of bss segment in bytes */
+ long a_entry; /* entry point */
+ long a_total; /* total memory allocated */
+ long a_syms; /* size of symbol table */
+ /* SHORT FORM ENDS HERE */
+
+ long a_trsize; /* text relocation size */
+ long a_drsize; /* data relocation size */
+ long a_tbase; /* text relocation base */
+ long a_dbase; /* data relocation base */
+};
+
+#define A_MAGIC0 ((unsigned char) 0x01)
+#define A_MAGIC1 ((unsigned char) 0x03)
+#define BADMAG(X) ((X).a_magic[0] != A_MAGIC0 || (X).a_magic[1] != A_MAGIC1)
+
+/* CPU Id of TARGET machine (byte order coded in low order two bits) */
+#define A_NONE 0x00 /* unknown */
+#define A_I8086 0x04 /* intel i8086/8088 */
+#define A_M68K 0x0B /* motorola m68000 */
+#define A_NS16K 0x0C /* national semiconductor 16032 */
+#define A_I80386 0x10 /* intel i80386 */
+#define A_SPARC 0x17 /* Sun SPARC */
+
+#define A_BLR(cputype) ((cputype&0x01)!=0) /* TRUE if bytes left-to-right */
+#define A_WLR(cputype) ((cputype&0x02)!=0) /* TRUE if words left-to-right */
+
+/* Flags. */
+#define A_UZP 0x01 /* unmapped zero page (pages) */
+#define A_EXEC 0x10 /* executable */
+#define A_SEP 0x20 /* separate I/D */
+#define A_PURE 0x40 /* pure text */ /* not used */
+#define A_TOVLY 0x80 /* text overlay */ /* not used */
+
+/* Tell a.out.gnu.h not to define `struct exec'. */
+#define __STRUCT_EXEC_OVERRIDE__
+
+/* Hide M_386 from enum declaration in a.out.h. */
+#define M_386 HIDE_M_386
+
+#ifndef __A_OUT_GNU_H__
+#define __A_OUT_GNU_H__
+
+#if defined(sequent) && defined(i386)
+#define a_magic a_info
+#include <a.out.h>
+#undef a_magic
+#define __STRUCT_EXEC_OVERRIDE__
+#define N_NLIST_DECLARED
+#define N_RELOCATION_INFO_DECLARED
+#endif
+
+#define __GNU_EXEC_MACROS__
+
+#ifndef __STRUCT_EXEC_OVERRIDE__
+
+struct exec
+{
+ unsigned long a_info; /* Use macros N_MAGIC, etc for access */
+ unsigned long a_text; /* length of text, in bytes */
+ unsigned long a_data; /* length of data, in bytes */
+ unsigned long a_bss; /* length of uninitialized data area for file, in bytes */
+ unsigned long a_syms; /* length of symbol table data in file, in bytes */
+ unsigned long a_entry; /* start address */
+ unsigned long a_trsize; /* length of relocation info for text, in bytes */
+ unsigned long a_drsize; /* length of relocation info for data, in bytes */
+};
+
+#endif /* __STRUCT_EXEC_OVERRIDE__ */
+
+/* these go in the N_MACHTYPE field */
+enum machine_type {
+#if defined (M_OLDSUN2)
+ M__OLDSUN2 = M_OLDSUN2,
+#else
+ M_OLDSUN2 = 0,
+#endif
+#if defined (M_68010)
+ M__68010 = M_68010,
+#else
+ M_68010 = 1,
+#endif
+#if defined (M_68020)
+ M__68020 = M_68020,
+#else
+ M_68020 = 2,
+#endif
+#if defined (M_SPARC)
+ M__SPARC = M_SPARC,
+#else
+ M_SPARC = 3,
+#endif
+ /* skip a bunch so we don't run into any of sun's numbers */
+ M_386 = 100,
+};
+
+#if !defined (N_MAGIC)
+#define N_MAGIC(exec) ((exec).a_info & 0xffff)
+#endif
+#define N_MACHTYPE(exec) ((enum machine_type)(((exec).a_info >> 16) & 0xff))
+#define N_FLAGS(exec) (((exec).a_info >> 24) & 0xff)
+#define N_SET_INFO(exec, magic, type, flags) \
+ ((exec).a_info = ((magic) & 0xffff) \
+ | (((int)(type) & 0xff) << 16) \
+ | (((flags) & 0xff) << 24))
+#define N_SET_MAGIC(exec, magic) \
+ ((exec).a_info = (((exec).a_info & 0xffff0000) | ((magic) & 0xffff)))
+
+#define N_SET_MACHTYPE(exec, machtype) \
+ ((exec).a_info = \
+ ((exec).a_info&0xff00ffff) | ((((int)(machtype))&0xff) << 16))
+
+#define N_SET_FLAGS(exec, flags) \
+ ((exec).a_info = \
+ ((exec).a_info&0x00ffffff) | (((flags) & 0xff) << 24))
+
+#ifndef OMAGIC
+/* Code indicating object file or impure executable. */
+#define OMAGIC 0407
+/* Code indicating pure executable. */
+#define NMAGIC 0410
+/* Code indicating demand-paged executable. */
+#define ZMAGIC 0413
+#endif /* not OMAGIC */
+
+#if !defined (N_BADMAG)
+#define N_BADMAG(x) \
+ (N_MAGIC(x) != OMAGIC && N_MAGIC(x) != NMAGIC \
+ && N_MAGIC(x) != ZMAGIC)
+#endif
+
+#define _N_BADMAG(x) \
+ (N_MAGIC(x) != OMAGIC && N_MAGIC(x) != NMAGIC \
+ && N_MAGIC(x) != ZMAGIC)
+
+#define _N_HDROFF(x) (SEGMENT_SIZE - sizeof (struct exec))
+
+#if !defined (N_TXTOFF)
+#define N_TXTOFF(x) \
+ (N_MAGIC(x) == ZMAGIC ? _N_HDROFF((x)) + sizeof (struct exec) : sizeof (struct exec))
+#endif
+
+#if !defined (N_DATOFF)
+#define N_DATOFF(x) (N_TXTOFF(x) + (x).a_text)
+#endif
+
+#if !defined (N_TRELOFF)
+#define N_TRELOFF(x) (N_DATOFF(x) + (x).a_data)
+#endif
+
+#if !defined (N_DRELOFF)
+#define N_DRELOFF(x) (N_TRELOFF(x) + (x).a_trsize)
+#endif
+
+#if !defined (N_SYMOFF)
+#define N_SYMOFF(x) (N_DRELOFF(x) + (x).a_drsize)
+#endif
+
+#if !defined (N_STROFF)
+#define N_STROFF(x) (N_SYMOFF(x) + (x).a_syms)
+#endif
+
+/* Address of text segment in memory after it is loaded. */
+#if !defined (N_TXTADDR)
+#define N_TXTADDR(x) 0
+#endif
+
+/* Address of data segment in memory after it is loaded.
+ Note that it is up to you to define SEGMENT_SIZE
+ on machines not listed here. */
+#if defined(vax) || defined(hp300) || defined(pyr)
+#define SEGMENT_SIZE PAGE_SIZE
+#endif
+#ifdef hp300
+#define PAGE_SIZE 4096
+#endif
+#ifdef sony
+#define SEGMENT_SIZE 0x2000
+#endif /* Sony. */
+#ifdef is68k
+#define SEGMENT_SIZE 0x20000
+#endif
+#if defined(m68k) && defined(PORTAR)
+#define PAGE_SIZE 0x400
+#define SEGMENT_SIZE PAGE_SIZE
+#endif
+
+#define _N_SEGMENT_ROUND(x) (((x) + SEGMENT_SIZE - 1) & ~(SEGMENT_SIZE - 1))
+
+#define _N_TXTENDADDR(x) (N_TXTADDR(x)+(x).a_text)
+
+#ifndef N_DATADDR
+#define N_DATADDR(x) \
+ (N_MAGIC(x)==OMAGIC? (_N_TXTENDADDR(x)) \
+ : (_N_SEGMENT_ROUND (_N_TXTENDADDR(x))))
+#endif
+
+/* Address of bss segment in memory after it is loaded. */
+#if !defined (N_BSSADDR)
+#define N_BSSADDR(x) (N_DATADDR(x) + (x).a_data)
+#endif
+\f
+#if !defined (N_NLIST_DECLARED)
+struct nlist {
+ union {
+ char *n_name;
+ struct nlist *n_next;
+ long n_strx;
+ } n_un;
+ unsigned char n_type;
+ char n_other;
+ short n_desc;
+ unsigned long n_value;
+};
+#endif /* no N_NLIST_DECLARED. */
+
+#if !defined (N_UNDF)
+#define N_UNDF 0
+#endif
+#if !defined (N_ABS)
+#define N_ABS 2
+#endif
+#if !defined (N_TEXT)
+#define N_TEXT 4
+#endif
+#if !defined (N_DATA)
+#define N_DATA 6
+#endif
+#if !defined (N_BSS)
+#define N_BSS 8
+#endif
+#if !defined (N_COMM)
+#define N_COMM 18
+#endif
+#if !defined (N_FN)
+#define N_FN 15
+#endif
+
+#if !defined (N_EXT)
+#define N_EXT 1
+#endif
+#if !defined (N_TYPE)
+#define N_TYPE 036
+#endif
+#if !defined (N_STAB)
+#define N_STAB 0340
+#endif
+
+/* The following type indicates the definition of a symbol as being
+ an indirect reference to another symbol. The other symbol
+ appears as an undefined reference, immediately following this symbol.
+
+ Indirection is asymmetrical. The other symbol's value will be used
+ to satisfy requests for the indirect symbol, but not vice versa.
+ If the other symbol does not have a definition, libraries will
+ be searched to find a definition. */
+#define N_INDR 0xa
+
+/* The following symbols refer to set elements.
+ All the N_SET[ATDB] symbols with the same name form one set.
+ Space is allocated for the set in the text section, and each set
+ element's value is stored into one word of the space.
+ The first word of the space is the length of the set (number of elements).
+
+ The address of the set is made into an N_SETV symbol
+ whose name is the same as the name of the set.
+ This symbol acts like a N_DATA global symbol
+ in that it can satisfy undefined external references. */
+
+/* These appear as input to LD, in a .o file. */
+#define N_SETA 0x14 /* Absolute set element symbol */
+#define N_SETT 0x16 /* Text set element symbol */
+#define N_SETD 0x18 /* Data set element symbol */
+#define N_SETB 0x1A /* Bss set element symbol */
+
+/* This is output from LD. */
+#define N_SETV 0x1C /* Pointer to set vector in data area. */
+\f
+#if !defined (N_RELOCATION_INFO_DECLARED)
+/* This structure describes a single relocation to be performed.
+ The text-relocation section of the file is a vector of these structures,
+ all of which apply to the text section.
+ Likewise, the data-relocation section applies to the data section. */
+
+struct relocation_info
+{
+ /* Address (within segment) to be relocated. */
+ unsigned long r_address;
+#if 0
+ /* The meaning of r_symbolnum depends on r_extern. */
+ unsigned int r_symbolnum:24;
+ /* Nonzero means value is a pc-relative offset
+ and it should be relocated for changes in its own address
+ as well as for changes in the symbol or section specified. */
+ unsigned int r_pcrel:1;
+ /* Length (as exponent of 2) of the field to be relocated.
+ Thus, a value of 2 indicates 1<<2 bytes. */
+ unsigned int r_length:2;
+ /* 1 => relocate with value of symbol.
+ r_symbolnum is the index of the symbol
+ in file's the symbol table.
+ 0 => relocate with the address of a segment.
+ r_symbolnum is N_TEXT, N_DATA, N_BSS or N_ABS
+ (the N_EXT bit may be set also, but signifies nothing). */
+ unsigned int r_extern:1;
+ /* Four bits that aren't used, but when writing an object file
+ it is desirable to clear them. */
+ unsigned int r_pad:4;
+#else
+ unsigned long foo;
+#endif
+};
+#endif /* no N_RELOCATION_INFO_DECLARED. */
+
+
+#endif /* __A_OUT_GNU_H__ */
+
+#undef M_386
+#define M_386 A_I80386
+
+#undef N_MAGIC
+#define N_MAGIC3(magic0, magic1, type) \
+ ((magic0) | ((magic1) << 8) | ((type) << 16))
+#define N_MAGIC(exec) \
+ N_MAGIC3((exec).a_magic[0], (exec).a_magic[1], (exec).a_flags)
+
+#undef N_MACHTYPE
+#define N_MACHTYPE(exec) ((enum machine_type)((exec).a_cpu))
+
+#undef N_FLAGS
+#define N_FLAGS(exec) 0
+
+#undef N_SET_INFO
+#define N_SET_INFO(exec, magic, type, flags) \
+ ((exec).a_magic[0] = (magic) & 0xff, \
+ (exec).a_magic[1] = ((magic) >> 8) & 0xff, \
+ (exec).a_flags = ((magic) >> 16) & 0xff, \
+ (exec).a_cpu = (type) & 0xff)
+
+#undef N_SET_MAGIC
+#define N_SET_MAGIC(exec, magic) \
+ ((exec).a_magic[0] = (magic) & 0xff, \
+ (exec).a_magic[1] = ((magic) >> 8) & 0xff, \
+ (exec).a_flags = ((magic) >> 16) & 0xff)
+
+#undef N_SET_MACHTYPE
+#define N_SET_MACHTYPE(exec, machtype) \
+ ((exec).a_cpu = (machtype) & 0xff, \
+ (exec).a_hdrlen = sizeof (exec))
+
+#undef N_SET_FLAGS
+#define N_SET_FLAGS(exec, flags) /* nothing */
+
+#undef OMAGIC
+#define OMAGIC N_MAGIC3(A_MAGIC0, A_MAGIC1, 0)
+
+#undef NMAGIC
+#define NMAGIC N_MAGIC3(A_MAGIC0, A_MAGIC1, A_EXEC)
+
+#undef ZMAGIC
+#define ZMAGIC N_MAGIC3(A_MAGIC0, A_MAGIC1, A_EXEC)
+
+#undef _N_HDROFF
+#define _N_HDROFF(x) 0
+
+#undef PAGE_SIZE
+#define PAGE_SIZE 16
+#define SEGMENT_SIZE PAGE_SIZE
+#define getpagesize() PAGE_SIZE
+
+#endif /* _BSD_A_OUT_H */
--- /dev/null
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+/******************************************************************************/
+
+/* EEEEyuk!! */
+
+#ifdef __STDC__
+#define P(x) x
+#else
+#define P(x) ()
+#endif
+
--- /dev/null
+/* table.c - table-handler module for linker */
+
+/* Copyright (C) 1994 Bruce Evans */
+
+#include "syshead.h"
+#include "const.h"
+#include "align.h"
+#include "obj.h"
+#include "type.h"
+#include "globvar.h"
+
+#define GOLDEN 157 /* GOLDEN/HASHTABSIZE approx golden ratio */
+#define HASHTABSIZE 256
+
+PRIVATE struct symstruct *hashtab[HASHTABSIZE]; /* hash table */
+PRIVATE char *tableptr; /* next free spot in catchall table */
+PRIVATE char *tableend; /* ptr to spot after last in table */
+
+PUBLIC int maxused = 0; /* Stats */
+PRIVATE int mainavail, usedtop; /* Stats */
+
+FORWARD struct symstruct **gethashptr P((char *name));
+FORWARD void check_used P((void));
+
+/* initialise symbol table */
+
+PUBLIC void syminit()
+{
+ unsigned i;
+
+ for (i = sizeof(int) <= 2 ? 0xE000 : (unsigned) 0x38000;
+ i != 0; i -= 512)
+ if ((tableptr = malloc(i)) != NUL_PTR)
+ break;
+ if (tableptr == NUL_PTR)
+ outofmemory();
+ tableend = tableptr + i;
+ for (i = 0; i < HASHTABSIZE; i++)
+ hashtab[i] = NUL_PTR;
+
+ mainavail = tableend - tableptr;
+ usedtop = 0;
+}
+
+/* add named symbol to end of table - initialise only name and next fields */
+/* caller must not duplicate names of externals for findsym() to work */
+
+PUBLIC struct symstruct *addsym(name)
+char *name;
+{
+ struct symstruct **hashptr;
+ struct symstruct *oldsymptr = 0;
+ struct symstruct *symptr;
+
+ hashptr = gethashptr(name);
+ symptr = *hashptr;
+ while (symptr != NUL_PTR)
+ {
+ oldsymptr = symptr;
+ symptr = symptr->next;
+ }
+ align(tableptr);
+ symptr = (struct symstruct *) tableptr;
+ if ((tableptr = symptr->name + (strlen(name) + 1)) > tableend)
+ outofmemory();
+ symptr->modptr = NUL_PTR;
+ symptr->next = NUL_PTR;
+ if (name != symptr->name)
+ strcpy(symptr->name, name); /* should't happen */
+ if (*hashptr == NUL_PTR)
+ *hashptr = symptr;
+ else
+ oldsymptr->next = symptr;
+ return symptr;
+}
+
+/* lookup named symbol */
+
+PUBLIC struct symstruct *findsym(name)
+char *name;
+{
+ struct symstruct *symptr;
+
+ symptr = *gethashptr(name);
+ while (symptr != NUL_PTR && (!(symptr->flags & (E_MASK | I_MASK)) ||
+ strcmp(symptr->name, name) != 0))
+ symptr = symptr->next;
+ return symptr;
+}
+
+/* convert name to a hash table ptr */
+
+PRIVATE struct symstruct **gethashptr(name)
+register char *name;
+{
+ register unsigned hashval;
+
+ hashval = 0;
+ while (*name)
+ hashval = hashval * 2 + *name++;
+ return hashtab + ((hashval * GOLDEN) & (HASHTABSIZE - 1));
+
+/*
+
+#asm
+
+GOLDEN EQU 157
+HASHTABSIZE EQU 256
+
+ CLRB can build value here since HASHTABSIZE <= 256
+ LDA ,X
+ BEQ HASHVAL.EXIT
+HASHVAL.LOOP
+ ADDB ,X+
+ LSLB
+ LDA ,X
+ BNE HASHVAL.LOOP
+ RORB
+ LDA #GOLDEN
+ MUL
+HASHVAL.EXIT
+HASHVAL.EXIT
+ LDX #_hashtab
+ ABX discard A - same as taking mod HASHTABSIZE
+ ABX
+#endasm
+
+*/
+
+}
+
+/* move symbol descriptor entries to top of table (no error checking) */
+
+PUBLIC char *moveup(nbytes)
+unsigned nbytes;
+{
+ register char *source;
+ register char *target;
+
+ usedtop += nbytes;
+ mainavail -= nbytes;
+
+ source = tableptr;
+ target = tableend;
+ while (nbytes--)
+ *--target = *--source;
+ tableptr = source;
+ return tableend = target;
+}
+
+/* our version of malloc */
+
+PUBLIC char *ourmalloc(nbytes)
+unsigned nbytes;
+{
+ char *allocptr;
+
+ align(tableptr);
+ allocptr = tableptr;
+ if ((tableptr += nbytes) > tableend)
+ outofmemory();
+ return allocptr;
+}
+
+/* our version of free (release from bottom of table) */
+
+PUBLIC void ourfree(cptr)
+char *cptr;
+{
+ check_used();
+ tableptr = cptr;
+ check_used();
+}
+
+/* read string from file into table at offset suitable for next symbol */
+
+PUBLIC char *readstring()
+{
+ int c;
+ char *s;
+ char *start;
+
+ align(tableptr);
+ start = s = ((struct symstruct *) tableptr)->name;
+ while (TRUE)
+ {
+ /* Stats: need a checkused against 's', maybe. */
+ if (s >= tableend)
+ outofmemory();
+ if ((c = readchar()) < 0)
+ prematureeof();
+ if ((*s++ = c) == 0)
+ return start;
+ }
+ /* NOTREACHED */
+}
+
+/* release from top of table */
+
+PUBLIC void release(cptr)
+char *cptr;
+{
+ check_used();
+ mainavail += cptr - tableend;
+ usedtop -= cptr - tableend;
+
+ tableend = cptr;
+}
+
+PRIVATE void check_used()
+{
+ int used;
+
+ used = usedtop + mainavail - (tableend - tableptr);
+ if (used > maxused) maxused = used;
+}
+
+PUBLIC int memory_used()
+{
+ check_used();
+ return maxused;
+}
+
+/* allocate space for string */
+
+PUBLIC char *stralloc(s)
+char *s;
+{
+ return strcpy(ourmalloc((unsigned) strlen(s) + 1), s);
+}
--- /dev/null
+/* type.h - types for linker */
+
+/* Copyright (C) 1994 Bruce Evans */
+
+typedef int bool_pt;
+typedef unsigned char bool_t;
+
+typedef unsigned short u2_t;
+typedef unsigned u2_pt;
+typedef unsigned long u4_t;
+typedef unsigned long u4_pt;
+
+#ifdef HOST_8BIT
+typedef char fastin_t;
+#else
+typedef int fastin_t;
+#endif
+typedef int fastin_pt;
+
+typedef unsigned flags_t; /* unsigned makes shifts logical */
+
+#ifdef LONG_OFFSETS
+typedef unsigned long bin_off_t;
+#else
+typedef unsigned bin_off_t;
+#endif
+
+#ifdef OBJ_H /* obj.h is included */
+
+struct entrylist /* list of entry symbols */
+{
+ struct entrylist *elnext; /* next on list */
+ struct symstruct *elsymptr; /* entry on list */
+};
+
+struct modstruct /* module table entry format */
+{
+ char *filename; /* file containing this module */
+ char *archentry; /* name of component file for archives */
+ char *modname; /* name of module */
+ unsigned long textoffset; /* offset to module text in file */
+ char class; /* class of module */
+ char loadflag; /* set if module to be loaded */
+ char segmaxsize[NSEG / 4]; /* |SF|SE|..|S0|, 2 bits for seg max size */
+ /* 00 = 1, 01 = 2, 10 = 3, 11 = 4 */
+ char segsizedesc[NSEG / 4]; /* |SF|SE|..|S0|, 2 bits for #bytes for size */
+ /* 00 = 0, 01 = 1, 10 = 2, 11 = 4 */
+ struct symstruct **symparray; /* ^array of ptrs to referenced syms */
+ struct modstruct *modnext; /* next module in order of initial reading */
+ char segsize[1]; /* up to 64 size bytes begin here */
+}; /* careful with sizeof( struct modstruct )!! */
+
+struct redlist /* list of redefined (exported) symbols */
+{
+ struct redlist *rlnext; /* next on list */
+ struct symstruct *rlsymptr; /* to symbol with same name, flags */
+ struct modstruct *rlmodptr; /* module for this redefinition */
+ bin_off_t rlvalue; /* value for this redefinition */
+};
+
+struct symstruct /* symbol table entry format */
+{
+ struct modstruct *modptr; /* module where symbol is defined */
+ bin_off_t value; /* value of symbol */
+ flags_t flags; /* see below (unsigned makes shifts logical) */
+ struct symstruct *next; /* next symbol with same hash value */
+ char name[1]; /* name is any string beginning here */
+}; /* don't use sizeof( struct symstruct )!! */
+
+#endif /* obj.h is included */
+
+/* prototypes */
+
+#ifndef P
+#ifdef __STDC__
+#define P(x) x
+#else
+#define P(x) ()
+#endif
+#endif
+
+/* dump.c */
+void dumpmods P((void));
+void dumpsyms P((void));
+
+/* io.c */
+void ioinit P((char *progname));
+void closein P((void));
+void closeout P((void));
+void errtrace P((char *name, int level));
+void executable P((void));
+void flusherr P((void));
+void openin P((char *filename));
+void openout P((char *filename));
+void putstr P((char *message));
+void put08x P((bin_off_t num));
+void put08lx P((bin_off_t num));
+void putbstr P((unsigned width, char *str));
+void putbyte P((int ch));
+int readchar P((void));
+void readin P((char *buf, unsigned count));
+bool_pt readineofok P((char *buf, unsigned count));
+void seekin P((unsigned long offset));
+void seekout P((unsigned long offset));
+void seektrel P((unsigned long offset));
+void writechar P((int c));
+void writedrel P((char *buf, unsigned count));
+void writeout P((char *buf, unsigned count));
+void writetrel P((char *buf, unsigned count));
+void fatalerror P((char *message));
+void inputerror P((char *message));
+void input1error P((char *message));
+void outofmemory P((void));
+void prematureeof P((void));
+void redefined P((char *name, char *message, char *archentry,
+ char *deffilename, char *defarchentry));
+void interseg P((char *fname, char *aname, char *name));
+void reserved P((char *name));
+void size_error P((int seg, bin_off_t count, bin_off_t size));
+void undefined P((char *name));
+void usage P((void));
+void version_msg P((void));
+void use_error P((char *message));
+
+/* ld.c */
+int main P((int argc, char **argv));
+
+/* readobj.c */
+void objinit P((void));
+void readsyms P((char *filename, bool_pt trace));
+#ifdef OBJ_H
+void entrysym P((struct symstruct *symptr));
+unsigned segsizecount P((unsigned seg, struct modstruct *modptr));
+#endif
+bin_off_t readconvsize P((unsigned countindex));
+bin_off_t readsize P((unsigned count));
+
+/* table.c */
+void syminit P((void));
+struct symstruct *addsym P((char *name));
+struct symstruct *findsym P((char *name));
+char *moveup P((unsigned nbytes));
+char *ourmalloc P((unsigned nbytes));
+void ourfree P((char *cptr));
+char *readstring P((void));
+void release P((char *cptr));
+int memory_used P((void));
+char *stralloc P((char *s));
+
+/* typeconvert.c */
+u2_pt c2u2 P((char *buf));
+u4_t c4u4 P((char *buf));
+u2_pt cnu2 P((char *buf, unsigned count));
+u4_t cnu4 P((char *buf, unsigned count));
+void u2c2 P((char *buf, u2_pt offset));
+void u4c4 P((char *buf, u4_t offset));
+void u2cn P((char *buf, u2_pt offset, unsigned count));
+void u4cn P((char *buf, u4_t offset, unsigned count));
+bool_pt typeconv_init P((bool_pt big_endian, bool_pt long_big_endian));
+
+/* writebin.c */
+void writebin P((char *outfilename, bool_pt argsepid, bool_pt argbits32,
+ bool_pt argstripflag, bool_pt arguzp));
+
+void write_dosemu P((char *outfilename, bool_pt argsepid, bool_pt argbits32,
+ bool_pt argstripflag, bool_pt arguzp));
+
+/* write_elks.c */
+void write_elks P((char *outfilename, bool_pt argsepid, bool_pt argbits32,
+ bool_pt argstripflag, bool_pt arguzp, bool_pt nsym));
+
+/* linksym.c */
+void linksyms P((bool_pt argreloc_output));
+
+/* mkar.c */
+void ld86r P((int argc, char ** argv));
--- /dev/null
+
+/*
+ * Type conversion routines, these have been rewritten for portability.
+ *
+ * The only requirement is now that the u2_t and u4_t must be big enough.
+ */
+
+#include "syshead.h"
+#include "const.h"
+#include "type.h"
+#include "globvar.h"
+
+void xxerr P((char *));
+void xxerr(x) char * x; { write(2, x, strlen(x)); }
+
+static int no_swap = 1;
+
+static int long_off[4] = {0,1,2,3};
+static int int_off[2] = {0,1};
+
+PUBLIC bool_pt typeconv_init(big_endian, long_big_endian)
+bool_pt big_endian;
+bool_pt long_big_endian;
+{
+ int i;
+ no_swap = (!big_endian && !long_big_endian);
+
+ for(i=0; i<4; i++) long_off[i] = i;
+ for(i=0; i<2; i++) int_off[i] = i;
+
+ if( long_big_endian )
+ {
+ i = long_off[0]; long_off[0] = long_off[2]; long_off[2] = i;
+ i = long_off[1]; long_off[1] = long_off[3]; long_off[3] = i;
+ }
+ if( big_endian )
+ {
+ i = long_off[2]; long_off[2] = long_off[3]; long_off[3] = i;
+ i = long_off[0]; long_off[0] = long_off[1]; long_off[1] = i;
+
+ i = int_off[0]; int_off[0] = int_off[1]; int_off[1] = i;
+ }
+ return 1;
+}
+
+PUBLIC void u2c2(buf, offset)
+char *buf;
+u2_pt offset;
+{
+#ifdef __AS386_16__
+ if( no_swap )
+ {
+ *((unsigned short*)buf) = offset; /* UNALIGNED ACCESS! */
+ return;
+ }
+#endif
+ buf[int_off[0]] = offset;
+ buf[int_off[1]] = (offset>>8);
+}
+
+PUBLIC void u4c4(buf, offset)
+char *buf;
+u4_t offset;
+{
+ int i;
+#ifdef __AS386_16__
+ if( no_swap )
+ {
+ *((unsigned long*)buf) = offset; /* UNALIGNED ACCESS! */
+ return;
+ }
+#endif
+ for(i=0; i<4; i++)
+ {
+ buf[long_off[i]] = offset;
+ offset >>= 8;
+ }
+}
+
+PUBLIC void u4cn(buf, offset, count)
+char *buf;
+u4_t offset;
+unsigned count;
+{
+ switch(count)
+ {
+ case 1:
+ buf[0] = (char) offset;
+ return;
+ case 2:
+ u2c2(buf, (u2_pt) offset);
+ return;
+ case 4:
+ u4c4(buf, (u4_t) offset);
+ return;
+ default:
+ xxerr("WARNING: typeconv.c(u4cn) illegal count\n");
+ return;
+ }
+}
+
+PUBLIC void u2cn(buf, offset, count)
+char *buf;
+u2_pt offset;
+unsigned count;
+{
+ switch(count)
+ {
+ case 1:
+ buf[0] = (char) offset;
+ return;
+ case 2:
+ u2c2(buf, (u2_pt) offset);
+ return;
+ case 4:
+ u4c4(buf, (u4_t) offset);
+ return;
+ default:
+ xxerr("WARNING: typeconv.c(u2cn) illegal count\n");
+ return;
+ }
+}
+
+PUBLIC u2_pt c2u2(buf)
+char *buf;
+{
+ u2_pt res;
+#ifdef __AS386_16__
+ if( no_swap ) return *((u2_pt *)buf); /* UNALIGNED ACCESS! */
+#endif
+
+ res = ((unsigned char *)buf) [int_off[0]]
+ + ((((unsigned char *)buf) [int_off[1]]) << 8);
+ return res;
+}
+
+PUBLIC u4_t c4u4(buf)
+char *buf;
+{
+ u4_t res;
+ int i;
+#ifdef __AS386_16__
+ if( no_swap ) return *((u4_t *)buf); /* UNALIGNED ACCESS! */
+#endif
+ res = 0;
+ for(i=3; i>=0; i--)
+ {
+ res = (res<<8) + ((unsigned char *)buf) [long_off[i]];
+ }
+ return res;
+}
+
+PUBLIC u4_t cnu4(buf, count)
+char *buf;
+unsigned count;
+{
+ switch (count)
+ {
+ case 0:
+ return 0;
+ case 1:
+ return buf[0] & 0xFF;
+ case 2:
+ return c2u2(buf);
+ case 4:
+ return c4u4(buf);
+ default:
+ xxerr("WARNING: typeconv.c(cnu4) illegal count\n");
+ return 0;
+ }
+}
+
+PUBLIC u2_pt cnu2(buf, count)
+char *buf;
+unsigned count;
+{
+ switch (count)
+ {
+ case 0:
+ return 0;
+ case 1:
+ return buf[0] & 0xFF;
+ case 2:
+ return c2u2(buf);
+ case 4:
+ return (u2_pt) c4u4(buf);
+ default:
+ xxerr("WARNING: typeconv.c(cnu2) illegal count\n");
+ return 0;
+ }
+}
--- /dev/null
+/* Header format of 16-bit
+ * Seventh edition UNIX executables */
+
+#ifndef _V7_A_OUT_H
+#define _V7_A_OUT_H
+
+#define V7_MAGIC4 0405 /* v7 overlay */
+#define V7_OMAGIC 0407 /* I&D in one segment (impure) */
+#define V7_NMAGIC 0410 /* read-only text */
+#define V7_MAGIC3 0411 /* v7 separate I&D (pure) */
+#define V7_ZMAGIC 0413 /* v8 demand load */
+
+#define V7_HEADERLEN 16
+
+struct v7_exec {
+ short magic;
+ unsigned short textsize;
+ unsigned short datasize;
+ unsigned short bsssize;
+ unsigned short symtabsize;
+ unsigned short entry;
+ unsigned short pad;
+ unsigned short noreloc;
+};
+
+#endif /* _V7_A_OUT_H */
--- /dev/null
+#define VERSION "0.16.21"
--- /dev/null
+
+/* writebin.c - write binary file for linker */
+
+/* Copyright (C) 1994 Bruce Evans */
+
+#include "syshead.h"
+#include "bindef.h"
+#include "const.h"
+#include "obj.h"
+#include "type.h"
+#include "globvar.h"
+
+#ifdef AOUT_DETECTED
+#define btextoffset (text_base_value)
+#define bdataoffset (data_base_value)
+#define page_size() 4096
+
+#ifdef __ELF__
+#ifndef ELF_SYMS
+#define ELF_SYMS 1
+#endif
+#endif
+
+#ifdef EDOS
+# define FILEHEADERLENGTH 0
+#endif
+#ifdef MINIX
+# ifdef BSD_A_OUT
+# ifdef STANDARD_GNU_A_OUT
+# define HEADERLEN (sizeof(struct exec))
+# else
+# define HEADERLEN (48)
+# endif
+# else
+# ifdef REL_OUTPUT
+# define HEADERLEN (reloc_output?sizeof(struct exec):A_MINHDR)
+ /* part of header not counted in offsets */
+# else
+# define HEADERLEN (A_MINHDR)
+# endif
+# endif
+# ifndef FILEHEADERLENGTH
+# define FILEHEADERLENGTH (headerless?0:HEADERLEN)
+# endif
+#endif
+#define DPSEG 2
+
+#define CM_MASK 0xC0
+#define MODIFY_MASK 0x3F
+#define S_MASK 0x04
+#define OF_MASK 0x03
+
+#define CM_SPECIAL 0
+#define CM_ABSOLUTE 0x40
+#define CM_OFFSET_RELOC 0x80
+#define CM_SYMBOL_RELOC 0xC0
+
+#define CM_EOT 0
+#define CM_BYTE_SIZE 1
+#define CM_WORD_SIZE 2
+#define CM_LONG_SIZE 3
+#define CM_1_SKIP 17
+#define CM_2_SKIP 18
+#define CM_4_SKIP 19
+#define CM_0_SEG 32
+
+#define ABS_TEXT_MAX 64
+
+#define offsetof(struc, mem) ((int) &((struc *) 0)->mem)
+#define memsizeof(struc, mem) sizeof(((struc *) 0)->mem)
+
+PRIVATE bool_t bits32; /* nonzero for 32-bit executable */
+PRIVATE bin_off_t combase[NSEG];/* bases of common parts of segments */
+PRIVATE bin_off_t comsz[NSEG]; /* sizes of common parts of segments */
+PRIVATE fastin_t curseg; /* current segment, 0 to $F */
+PRIVATE bin_off_t edataoffset; /* end of data */
+PRIVATE bin_off_t endoffset; /* end of bss */
+PRIVATE bin_off_t etextoffset; /* end of text */
+PRIVATE bin_off_t etextpadoff; /* end of padded text */
+#ifdef REL_OUTPUT
+PRIVATE unsigned ndreloc; /* number of data relocations */
+#endif
+PRIVATE unsigned nsym; /* number of symbols written */
+#ifdef REL_OUTPUT
+PRIVATE unsigned ntreloc; /* number of text relocations */
+extern bool_t reloc_output; /* nonzero to leave reloc info in output */
+#endif
+PRIVATE unsigned relocsize; /* current relocation size 1, 2 or 4 */
+PRIVATE bin_off_t segadj[NSEG]; /* adjusts (file offset - seg offset) */
+ /* depends on zero init */
+PRIVATE bin_off_t segbase[NSEG];/* bases of data parts of segments */
+PRIVATE char segboundary[9] = "__seg0DH";
+ /* name of seg boundary __seg0DL to __segfCH */
+PRIVATE bin_off_t segpos[NSEG]; /* segment positions for current module */
+PRIVATE bin_off_t segsz[NSEG]; /* sizes of data parts of segments */
+ /* depends on zero init */
+PRIVATE bool_t sepid; /* nonzero for separate I & D */
+PRIVATE bool_t stripflag; /* nonzero to strip symbols */
+PRIVATE bin_off_t spos; /* position in current seg */
+PRIVATE bool_t uzp; /* nonzero for unmapped zero page */
+
+#ifdef EDOS
+FORWARD unsigned binheaderlength P((char *commandname));
+FORWARD char *idconvert P((struct entrylist *elptr, char *commandname));
+#endif
+FORWARD void linkmod P((struct modstruct *modptr));
+FORWARD void padmod P((struct modstruct *modptr));
+FORWARD void setsym P((char *name, bin_off_t value));
+FORWARD void symres P((char *name));
+FORWARD void setseg P((fastin_pt newseg));
+FORWARD void skip P((unsigned countsize));
+#ifdef EDOS
+FORWARD void writeheader P((char *commandname));
+#else
+FORWARD void writeheader P((void));
+#endif
+FORWARD void writenulls P((bin_off_t count));
+
+/* write binary file */
+#ifndef FUNCNAME
+#define FUNCNAME writebin
+#endif
+
+PUBLIC void FUNCNAME(outfilename, argsepid, argbits32, argstripflag, arguzp)
+char *outfilename;
+bool_pt argsepid;
+bool_pt argbits32;
+bool_pt argstripflag;
+bool_pt arguzp;
+{
+ char buf4[4];
+#ifdef EDOS
+ char *commandname;
+#endif
+ char *cptr;
+ struct nlist extsym;
+ flags_t flags;
+ struct modstruct *modptr;
+ fastin_t seg;
+ unsigned sizecount;
+ bin_off_t tempoffset;
+
+ sepid = argsepid;
+ bits32 = argbits32;
+ stripflag = argstripflag;
+#ifdef REL_OUTPUT
+ uzp = arguzp && !reloc_output;
+#else
+ uzp = arguzp;
+#endif
+ if (uzp)
+ {
+ if (btextoffset == 0)
+#ifdef QMAGIC
+ btextoffset = page_size()+HEADERLEN;
+#else
+ btextoffset = page_size();
+#endif
+ if (bdataoffset == 0 && sepid)
+ bdataoffset = page_size();
+ }
+#ifdef EDOS
+ commandname = stralloc(outfilename);
+ if ((cptr = strchr(commandname, ':')) != NUL_PTR)
+ commandname = cptr + 1;
+ if ((cptr = strrchr(commandname, '.')) != NUL_PTR)
+ *cptr = 0;
+#endif
+
+ /* reserve special symbols use curseg to pass parameter to symres() */
+ for (curseg = 0; curseg < NSEG; ++curseg)
+ {
+ segboundary[5] = hexdigit[curseg]; /* to __segX?H */
+ segboundary[6] = 'D';
+ symres(segboundary); /* __segXDH */
+ segboundary[7] = 'L';
+ symres(segboundary); /* __segXDL */
+ segboundary[6] = 'C';
+ symres(segboundary); /* __segXCL */
+ segboundary[7] = 'H';
+ symres(segboundary); /* __segXCH */
+#ifndef DATASEGS
+ if( curseg > 3 )
+ {
+ segboundary[6] = 'S';
+ segboundary[7] = 'O';
+ symres(segboundary); /* __segXSO */
+ }
+#endif
+ }
+#ifdef EDOS
+ curseg = 0; /* data seg, s.b. variable */
+#else
+ curseg = 3;
+#endif
+ symres("__edata");
+ symres("__end");
+ curseg = 0; /* text seg, s.b. variable */
+ symres("__etext");
+ symres("__segoff");
+
+ /* calculate segment and common sizes (sum over loaded modules) */
+ /* use zero init of segsz[] */
+ /* also relocate symbols relative to starts of their segments */
+ for (modptr = modfirst; modptr != NUL_PTR; modptr = modptr->modnext)
+ if (modptr->loadflag)
+ {
+ register struct symstruct **symparray;
+ register struct symstruct *symptr;
+
+ for (symparray = modptr->symparray;
+ (symptr = *symparray) != NUL_PTR; ++symparray)
+ if (symptr->modptr == modptr && !(symptr->flags & A_MASK))
+ {
+ if (!(symptr->flags & (I_MASK | SA_MASK)))
+ {
+ /* relocate by offset of module in segment later */
+ /* relocate by offset of segment in memory special */
+ /* symbols get relocated improperly */
+ symptr->value += segsz[symptr->flags & SEGM_MASK];
+ }
+ else if (symptr->value == 0)
+ {
+#ifdef REL_OUTPUT
+ if (!reloc_output)
+#endif
+ undefined(symptr->name);
+ }
+ else
+ {
+#ifdef REL_OUTPUT
+#if 0
+ if (!reloc_output)
+#else
+ if (!reloc_output || !(symptr->flags & I_MASK))
+#endif
+#endif
+ {
+ tempoffset = ld_roundup(symptr->value, 4, bin_off_t);
+ /* temp kludge quad alignment for 386 */
+ symptr->value = comsz[seg = symptr->flags & SEGM_MASK];
+ comsz[seg] += tempoffset;
+ }
+ if (!(symptr->flags & SA_MASK))
+ symptr->flags |= C_MASK;
+ }
+ }
+ for (seg = 0, cptr = modptr->segsize; seg < NSEG; ++seg)
+ {
+ segsz[seg] += cntooffset(cptr,
+ sizecount = segsizecount((unsigned) seg, modptr));
+#ifndef EDOS
+
+ /* adjust sizes to even to get quad boundaries */
+ /* this should be specifiable dynamically */
+ segsz[seg] = ld_roundup(segsz[seg], 4, bin_off_t);
+ comsz[seg] = ld_roundup(comsz[seg], 4, bin_off_t);
+#endif
+ cptr += sizecount;
+ }
+ }
+
+ /* calculate seg positions now their sizes are known */
+ /* temp use fixed order 0D 0C 1D 1C 2D 2C ... */
+ /*
+#ifdef DATASEGS
+ * Assume seg 0 is text and rest are data
+#else
+ * Assume seg 1..3 are data, Seg 0 is real text, seg 4+ are far text
+#endif
+ */
+#ifdef EDOS
+ if (btextoffset == 0)
+ btextoffset = binheaderlength(commandname);
+#endif
+ segpos[0] = segbase[0] = spos = btextoffset;
+ combase[0] = segbase[0] + segsz[0];
+ segadj[1] = segadj[0] = -btextoffset;
+ etextpadoff = etextoffset = combase[0] + comsz[0];
+ if (sepid)
+ {
+ etextpadoff = ld_roundup(etextoffset, 0x10, bin_off_t);
+ segadj[1] += etextpadoff - bdataoffset;
+ }
+#ifdef QMAGIC
+ else if (uzp && bdataoffset == 0)
+ {
+ bdataoffset = ld_roundup(etextoffset, page_size(), bin_off_t);
+ etextpadoff = ld_roundup(etextoffset, page_size(), bin_off_t);
+ segadj[1] += etextpadoff - bdataoffset;
+ }
+#endif
+ else if (bdataoffset == 0)
+ bdataoffset = etextpadoff;
+ segpos[1] = segbase[1] = edataoffset = bdataoffset;
+ combase[1] = segbase[1] + segsz[1];
+#ifndef DATASEGS
+ for (seg = 4; seg < NSEG; ++seg)
+ {
+ segpos[seg] = segbase[seg] = 0;
+ combase[seg] = segbase[seg] + segsz[seg];
+ segadj[seg] = etextpadoff;
+
+ etextpadoff += ld_roundup(segsz[seg] + comsz[seg], 0x10, bin_off_t);
+ segadj[1] += ld_roundup(segsz[seg] + comsz[seg], 0x10, bin_off_t);
+ }
+ for (seg = 2; seg < 4; ++seg)
+#else
+ for (seg = 2; seg < NSEG; ++seg)
+#endif
+ {
+ segpos[seg] = segbase[seg] = combase[seg - 1] + comsz[seg - 1];
+#ifdef MC6809
+ if (seg == DPSEG)
+ {
+ /* temporarily have fixed DP seg */
+ /* adjust if nec so it only spans 1 page */
+ tempoffset = segsz[seg] + comsz[seg];
+ if (tempoffset > 0x100)
+ fatalerror("direct page segment too large");
+ if ((((segbase[seg] + tempoffset) ^ segbase[seg])
+ & ~(bin_off_t) 0xFF) != 0)
+ segpos[seg] = segbase[seg] = (segbase[seg] + 0xFF)
+ & ~(bin_off_t) 0xFF;
+ }
+#endif
+
+#ifdef QMAGIC
+ if(seg==3 && uzp && !stripflag) /* XXX Stripped last seek needed */
+ {
+ bin_off_t val;
+ val = ld_roundup(segbase[seg]+segsz[seg], page_size(), bin_off_t);
+ segsz[seg] = val - segbase[seg];
+ }
+#endif
+ combase[seg] = segbase[seg] + segsz[seg];
+ segadj[seg] = segadj[seg - 1];
+ }
+
+ /* relocate symbols by offsets of segments in memory */
+ for (modptr = modfirst; modptr != NUL_PTR; modptr = modptr->modnext)
+ if (modptr->loadflag)
+ {
+ register struct symstruct **symparray;
+ register struct symstruct *symptr;
+
+ for (symparray = modptr->symparray;
+ (symptr = *symparray) != NUL_PTR; ++symparray)
+ if (symptr->modptr == modptr && !(symptr->flags & A_MASK))
+ {
+ if (symptr->flags & (C_MASK | SA_MASK))
+ {
+#ifdef REL_OUTPUT
+#if 0
+ if (!reloc_output)
+#else
+ if (!reloc_output || !(symptr->flags & I_MASK))
+#endif
+#endif
+ symptr->value += combase[symptr->flags & SEGM_MASK];
+ }
+ else
+#ifdef REL_OUTPUT
+ if (!reloc_output || !(symptr->flags & I_MASK))
+#endif
+ symptr->value += segbase[symptr->flags & SEGM_MASK];
+ }
+ }
+
+ /* adjust special symbols */
+ for (seg = 0; seg < NSEG; ++seg)
+ {
+#ifdef DATASEGS
+ if (segsz[seg] != 0)
+ /* only count data of nonzero length */
+#else
+ if (segsz[seg] != 0 && seg < 4)
+#endif
+ edataoffset = segbase[seg] + segsz[seg];
+ segboundary[5] = hexdigit[seg]; /* to __segX?H */
+ segboundary[6] = 'D';
+ setsym(segboundary, (tempoffset = segbase[seg]) + segsz[seg]);
+ /* __segXDH */
+ segboundary[7] = 'L';
+ setsym(segboundary, tempoffset); /* __segXDL */
+ segboundary[6] = 'C';
+ setsym(segboundary, tempoffset = combase[seg]);
+ /* __segXCL */
+ segboundary[7] = 'H';
+ setsym(segboundary, tempoffset + comsz[seg]);
+ /* __segXCH */
+#ifndef DATASEGS
+ if( seg > 3 )
+ {
+ segboundary[6] = 'S';
+ segboundary[7] = 'O';
+ setsym(segboundary, (bin_off_t)(segadj[seg]-segadj[0])/0x10);
+ /* __segXSO */
+ }
+#endif
+ }
+ setsym("__etext", etextoffset);
+ setsym("__edata", edataoffset);
+#ifdef DATASEGS
+ setsym("__end", endoffset = combase[NSEG - 1] + comsz[NSEG - 1]);
+#else
+ setsym("__end", endoffset = combase[3] + comsz[3]);
+#endif
+ setsym("__segoff", (bin_off_t)(segadj[1]-segadj[0])/0x10);
+ if( !bits32 )
+ {
+ if( etextoffset > 65536L )
+ fatalerror("text segment too large for 16bit");
+ if( endoffset > 65536L )
+ fatalerror("data segment too large for 16bit");
+ }
+
+ openout(outfilename);
+#ifdef REL_OUTPUT
+ if (reloc_output)
+ seektrel(FILEHEADERLENGTH
+ + (unsigned long) (etextpadoff - btextoffset)
+ + (unsigned long) (edataoffset - bdataoffset));
+#endif
+#ifdef EDOS
+ writeheader(commandname);
+#else
+ writeheader();
+#endif
+ for (modptr = modfirst; modptr != NUL_PTR; modptr = modptr->modnext)
+ if (modptr->loadflag)
+ {
+ linkmod(modptr);
+ padmod(modptr);
+ }
+
+ /* dump symbol table */
+#ifdef MINIX
+ if (!stripflag)
+ {
+#ifdef BSD_A_OUT
+ unsigned stringoff;
+#endif
+
+ seekout(FILEHEADERLENGTH
+ + (unsigned long) (etextpadoff - btextoffset)
+ + (unsigned long) (edataoffset - bdataoffset)
+#ifdef REL_OUTPUT
+ + ((unsigned long) ndreloc + ntreloc) * RELOC_INFO_SIZE
+#endif
+ );
+ extsym.n_was_numaux = extsym.n_was_type = 0;
+#ifdef BSD_A_OUT
+ stringoff = 4;
+#endif
+ for (modptr = modfirst; modptr != NUL_PTR; modptr = modptr->modnext)
+ if (modptr->loadflag)
+ {
+ register struct symstruct **symparray;
+ register struct symstruct *symptr;
+
+ for (symparray = modptr->symparray;
+ (symptr = *symparray) != NUL_PTR; ++symparray)
+ if (symptr->modptr == modptr)
+ {
+#ifdef BSD_A_OUT
+ offtocn((char *) &extsym.n_was_strx,
+ (bin_off_t) stringoff, 4);
+#else
+#if ELF_SYMS
+ if( symptr->name[0] == '_' && symptr->name[1] )
+ strncpy((char *) extsym.n_was_name, symptr->name+1,
+ sizeof extsym.n_was_name);
+ else
+ {
+ memcpy((char *) extsym.n_was_name, "__", 2);
+ strncpy((char *) extsym.n_was_name+2, symptr->name,
+ sizeof(extsym.n_was_name)-2);
+ }
+#else
+ strncpy((char *) extsym.n_was_name, symptr->name,
+ sizeof extsym.n_was_name);
+#endif
+#endif
+ u4cn((char *) &extsym.n_value, (u4_t) symptr->value,
+ sizeof extsym.n_value);
+ if ((flags = symptr->flags) & A_MASK)
+ extsym.n_was_sclass = N_ABS;
+ else if (flags & (E_MASK | I_MASK))
+ extsym.n_was_sclass = C_EXT;
+ else
+ extsym.n_was_sclass = C_STAT;
+ if (!(flags & I_MASK) || (
+#ifdef REL_OUTPUT
+ !reloc_output &&
+#endif
+ (flags & C_MASK)))
+ switch (flags & (A_MASK | SEGM_MASK))
+ {
+#ifdef DATASEGS
+ case 0:
+#else
+ default:
+#endif
+ extsym.n_was_sclass |= N_TEXT;
+ case A_MASK:
+ break;
+#ifdef DATASEGS
+ default:
+#else
+ case 1: case 2: case 3:
+ case A_MASK|1: case A_MASK|2: case A_MASK|3:
+#endif
+ if (flags & (C_MASK | SA_MASK))
+ extsym.n_was_sclass |= N_BSS;
+ else
+ extsym.n_was_sclass |= N_DATA;
+ break;
+ }
+ writeout((char *) &extsym, sizeof extsym);
+ ++nsym;
+#ifdef BSD_A_OUT
+#if ELF_SYMS
+ stringoff += strlen(symptr->name);
+ if( symptr->name[0] != '_' || symptr->name[1] == '\0' )
+ stringoff += 3;
+#else
+ stringoff += strlen(symptr->name) + 1;
+#endif
+#endif
+ }
+ }
+#ifdef BSD_A_OUT
+ offtocn((char *) &extsym.n_was_strx, (bin_off_t) stringoff, 4);
+ writeout((char *) &extsym.n_was_strx, 4);
+ for (modptr = modfirst; modptr != NUL_PTR; modptr = modptr->modnext)
+ if (modptr->loadflag)
+ {
+ register struct symstruct **symparray;
+ register struct symstruct *symptr;
+
+ for (symparray = modptr->symparray;
+ (symptr = *symparray) != NUL_PTR; ++symparray)
+ if (symptr->modptr == modptr)
+#if ELF_SYMS
+ {
+ if( symptr->name[0] == '_' && symptr->name[1] )
+ writeout(symptr->name + 1, strlen(symptr->name));
+ else
+ {
+ writeout("__", 2);
+ writeout(symptr->name, strlen(symptr->name) + 1);
+ }
+ }
+#else
+ writeout(symptr->name, strlen(symptr->name) + 1);
+#endif
+ }
+#endif
+ seekout((unsigned long) offsetof(struct exec, a_syms));
+ u4cn(buf4, (u4_t) nsym * sizeof extsym,
+ memsizeof(struct exec, a_syms));
+ writeout(buf4, memsizeof(struct exec, a_syms));
+#ifdef REL_OUTPUT
+ if( FILEHEADERLENGTH >= offsetof(struct exec, a_trsize)+8)
+ {
+ seekout((unsigned long) offsetof(struct exec, a_trsize));
+ u4cn(buf4, (u4_t) ntreloc * RELOC_INFO_SIZE,
+ memsizeof(struct exec, a_trsize));
+ writeout(buf4, memsizeof(struct exec, a_trsize));
+ seekout((unsigned long) offsetof(struct exec, a_drsize));
+ u4cn(buf4, (u4_t) ndreloc * RELOC_INFO_SIZE,
+ memsizeof(struct exec, a_drsize));
+ writeout(buf4, memsizeof(struct exec, a_drsize));
+ }
+#endif
+ }
+#endif /* MINIX */
+ closeout();
+#ifdef REL_OUTPUT
+ if (!reloc_output)
+#endif
+ executable();
+}
+
+#ifdef EDOS
+
+PRIVATE unsigned binheaderlength(commandname)
+char *commandname;
+{
+ unsigned count;
+ char *name;
+ struct entrylist *elptr;
+ struct symstruct *startptr;
+
+ count = 2 + 2 + 1; /* len len nul */
+ startptr = findsym("start");
+ for (elptr = entryfirst; elptr != NUL_PTR; elptr = elptr->elnext)
+ {
+ name = idconvert(elptr, commandname);
+ count += strlen(name) + 1 + 2 + 1; /* nul off flg */
+ ourfree(name);
+ if (startptr != NUL_PTR)
+ count += 6; /* LBSR $xxxx and LBRA $xxxx */
+ }
+ return count;
+}
+
+/* convert name of symbol (entry) list element to a Basic identifier */
+/* new name is built in storage obtained from stralloc() */
+/* the special name _main is converted to the command name first */
+/* copy upper case and numerals, convert lower case to upper, ignore rest */
+
+PRIVATE char *idconvert(elptr, commandname)
+struct entrylist *elptr;
+char *commandname;
+{
+ char *name;
+ char *newname;
+
+ if (strcmp(name = elptr->elsymptr->name, "_main") == 0)
+ name = commandname;
+ newname = stralloc(name);
+ {
+ register char *t;
+ register char *s;
+
+ t = newname;
+ s = name;
+ do
+ {
+ if (*s >= '0' && *s <= '9' || *s >= 'A' && *s <= 'Z')
+ *t++ = *s;
+ if (*s >= 'a' && *s <= 'z')
+ *t++ = *s + ('A' - 'a');
+ }
+ while (*s++);
+ *t = 0;
+ }
+ if (*newname < 'A') /* numeral or null */
+ fatalerror("bad entry name");
+ return newname;
+}
+
+#endif /* EDOS */
+
+PRIVATE void linkmod(modptr)
+struct modstruct *modptr;
+{
+ char buf[ABS_TEXT_MAX];
+ int command;
+ unsigned char modify;
+ bin_off_t offset;
+ int symbolnum;
+ struct symstruct **symparray;
+ struct symstruct *symptr;
+
+ setseg(0);
+ relocsize = 2;
+ symparray = modptr->symparray;
+ openin(modptr->filename); /* does nothing if already open */
+ seekin(modptr->textoffset);
+ while (TRUE)
+ {
+ if ((command = readchar()) < 0)
+ prematureeof();
+ modify = command & MODIFY_MASK;
+ switch (command & CM_MASK)
+ {
+ case CM_SPECIAL:
+ switch (modify)
+ {
+ case CM_EOT:
+ segpos[curseg] = spos;
+ return;
+ case CM_BYTE_SIZE:
+ relocsize = 1;
+ break;
+ case CM_WORD_SIZE:
+ relocsize = 2;
+ break;
+ case CM_LONG_SIZE:
+#ifdef LONG_OFFSETS
+ relocsize = 4;
+ break;
+#else
+ fatalerror("relocation by long offsets not implemented");
+#endif
+ case CM_1_SKIP:
+ skip(1);
+ break;
+ case CM_2_SKIP:
+ skip(2);
+ break;
+ case CM_4_SKIP:
+ skip(4);
+ break;
+ default:
+ if ((modify -= CM_0_SEG) >= NSEG)
+ inputerror("bad data in");
+ setseg(modify);
+ break;
+ }
+ break;
+ case CM_ABSOLUTE:
+ if (modify == 0)
+ modify = ABS_TEXT_MAX;
+ readin(buf, (unsigned) modify);
+ writeout(buf, (unsigned) modify);
+ spos += (int) modify;
+ break;
+ case CM_OFFSET_RELOC:
+ offset = readsize(relocsize);
+ if (modify & R_MASK)
+ {
+#ifndef DATASEGS
+ int m = (modify & SEGM_MASK);
+ if( curseg != m && m != SEGM_MASK )
+ interseg(modptr->filename, modptr->archentry, (char*)0);
+#endif
+ offset -= (spos + relocsize);
+ }
+ offtocn(buf, segbase[modify & SEGM_MASK] + offset, relocsize);
+ writeout(buf, relocsize);
+#ifdef REL_OUTPUT
+ if (reloc_output)
+ {
+ u4_t bitfield;
+
+ if (curseg == 0)
+ {
+ ++ntreloc;
+ offtocn(buf, spos, 4);
+ writetrel(buf, 4);
+ }
+ else
+ {
+ ++ndreloc;
+ offtocn(buf, spos - segbase[1], 4);
+ writedrel(buf, 4);
+ }
+ if ((modify & SEGM_MASK) == 0)
+ bitfield = N_TEXT;
+ else
+ bitfield = N_DATA;
+ if (modify & R_MASK)
+ bitfield |= 1L << 24;
+ if (relocsize == 2)
+ bitfield |= 1L << 25;
+ else if (relocsize == 4)
+ bitfield |= 1L << 26;
+ u4cn(buf, bitfield, 4);
+ if (curseg == 0)
+ writetrel(buf, 4);
+ else
+ writedrel(buf, 4);
+ }
+#endif /* REL_OUTPUT */
+ spos += relocsize;
+ break;
+ case CM_SYMBOL_RELOC:
+ symptr = symparray[symbolnum = readconvsize((unsigned)
+ (modify & S_MASK ? 2 : 1))];
+ offset = readconvsize((unsigned) modify & OF_MASK);
+ if (modify & R_MASK)
+ {
+#ifndef DATASEGS
+ int m = (symptr->flags & SEGM_MASK);
+ if( curseg != m && m != SEGM_MASK )
+ interseg(modptr->filename, modptr->archentry, symptr->name);
+#endif
+ offset -= (spos + relocsize);
+ }
+#ifdef REL_OUTPUT
+ if (!reloc_output || !(symptr->flags & I_MASK))
+#endif
+ offset += symptr->value;
+ offtocn(buf, offset, relocsize);
+ writeout(buf, relocsize);
+#ifdef REL_OUTPUT
+ if (reloc_output)
+ {
+ u4_t bitfield;
+
+ if (curseg == 0)
+ {
+ ++ntreloc;
+ offtocn(buf, spos, 4);
+ writetrel(buf, 4);
+ }
+ else
+ {
+ ++ndreloc;
+ offtocn(buf, spos - segbase[1], 4);
+ writedrel(buf, 4);
+ }
+ if (symptr->flags & I_MASK)
+ bitfield = (1L << 27) | symbolnum;
+ else if ((symptr->flags & SEGM_MASK) == 0)
+ bitfield = N_TEXT;
+ else if (symptr->flags & (C_MASK | SA_MASK))
+ bitfield = N_BSS;
+ else
+ bitfield = N_DATA;
+ if (modify & R_MASK)
+ bitfield |= 1L << 24;
+ if (relocsize == 2)
+ bitfield |= 1L << 25;
+ else if (relocsize == 4)
+ bitfield |= 1L << 26;
+ u4cn(buf, bitfield, 4);
+ if (curseg == 0)
+ writetrel(buf, 4);
+ else
+ writedrel(buf, 4);
+ }
+#endif /* REL_OUTPUT */
+ spos += relocsize;
+ }
+ }
+}
+
+PRIVATE void padmod(modptr)
+struct modstruct *modptr;
+{
+ bin_off_t count;
+ fastin_t seg;
+ bin_off_t size;
+ unsigned sizecount;
+ char *sizeptr;
+
+ for (seg = 0, sizeptr = modptr->segsize; seg < NSEG; ++seg)
+ {
+ size = cntooffset(sizeptr,
+ sizecount = segsizecount((unsigned) seg, modptr));
+ sizeptr += sizecount;
+ if ((count = segpos[seg] - segbase[seg]) != size)
+ size_error(seg, count, size);
+
+ /* pad to quad boundary */
+ /* not padding in-between common areas which sometimes get into file */
+ if ((size = ld_roundup(segpos[seg], 4, bin_off_t) - segpos[seg]) != 0)
+ {
+ setseg(seg);
+ writenulls(size);
+ segpos[seg] = spos;
+ }
+ segbase[seg] = segpos[seg];
+ }
+}
+
+PRIVATE void setsym(name, value)
+char *name;
+bin_off_t value;
+{
+ struct symstruct *symptr;
+
+#ifdef REL_OUTPUT
+ if (!reloc_output)
+#endif
+ if ((symptr = findsym(name)) != NUL_PTR)
+ symptr->value = value;
+}
+
+PRIVATE void symres(name)
+register char *name;
+{
+ register struct symstruct *symptr;
+
+ if ((symptr = findsym(name)) != NUL_PTR)
+ {
+ if ((symptr->flags & SEGM_MASK) == SEGM_MASK)
+ symptr->flags &= ~SEGM_MASK | curseg;
+ if (symptr->flags != (I_MASK | curseg) || symptr->value != 0)
+ reserved(name);
+#ifdef REL_OUTPUT
+ if (!reloc_output)
+#endif
+ symptr->flags = E_MASK | curseg; /* show defined, not common */
+ }
+}
+
+/* set new segment */
+
+PRIVATE void setseg(newseg)
+fastin_pt newseg;
+{
+ if (newseg != curseg)
+ {
+ segpos[curseg] = spos;
+ spos = segpos[curseg = newseg];
+ seekout(FILEHEADERLENGTH + (unsigned long) spos
+ + (unsigned long) segadj[curseg]);
+ }
+}
+
+PRIVATE void skip(countsize)
+unsigned countsize;
+{
+ writenulls((bin_off_t) readsize(countsize));
+}
+
+#ifdef EDOS
+
+PRIVATE void writeheader(commandname)
+char *commandname;
+{
+ char buf[MAX_OFFSET_SIZE];
+ bin_off_t offset;
+ unsigned headlength;
+ char *name;
+ struct entrylist *elptr;
+ struct symstruct *startptr;
+
+ headlength = binheaderlength(commandname);
+ for (elptr = entryfirst; elptr != NUL_PTR; elptr = elptr->elnext)
+ headlength -= 6;
+ offset = headlength;
+ startptr = findsym("start");
+ offtocn(buf, edataoffset, 2);
+ writeout(buf, 2);
+ writechar(0xFF); /* dummy data length 0xFFFF takes everything */
+ writechar(0xFF);
+ for (elptr = entryfirst; elptr != NUL_PTR; elptr = elptr->elnext)
+ {
+ name = idconvert(elptr, commandname);
+ writeout(name, (unsigned) strlen(name) + 1);
+ ourfree(name);
+ offtocn(buf, startptr == NUL_PTR ? elptr->elsymptr->value : offset, 2);
+ writeout(buf, 2);
+ writechar(0x82); /* 8 = set flags from here, 2 = cmd line */
+ offset += 6; /* LBSR $xxxx and LBRA $xxxx */
+ }
+ writechar(0);
+ if (startptr != NUL_PTR)
+ {
+ offset = headlength + 3; /* over 1st LBSR */
+ for (elptr = entryfirst; elptr != NUL_PTR; elptr = elptr->elnext)
+ {
+ writechar(0x17); /* LBSR */
+ offtocn(buf, startptr->value - offset, 2);
+ writeout(buf, 2);
+ writechar(0x16); /* LBRA */
+ offtocn(buf, elptr->elsymptr->value - offset - 3, 2);
+ writeout(buf, 2);
+ offset += 6;
+ }
+ }
+}
+
+#endif /* EDOS */
+
+#ifdef MINIX
+
+PRIVATE void writeheader()
+{
+ struct exec header;
+
+ memset(&header, 0, sizeof header);
+#ifdef STANDARD_GNU_A_OUT
+#ifdef N_SET_MAGIC
+#ifdef QMAGIC
+ if(uzp)
+ N_SET_MAGIC(header, QMAGIC);
+ else
+#endif
+ N_SET_MAGIC(header, OMAGIC);
+#else
+ *(unsigned short *) &header.a_magic = OMAGIC; /* XXX - works for 386BSD */
+#endif
+#else
+ header.a_magic[0] = A_MAGIC0;
+ header.a_magic[1] = A_MAGIC1;
+#endif
+#ifdef REL_OUTPUT
+ if (!reloc_output)
+#endif
+ {
+#ifdef STANDARD_GNU_A_OUT
+#ifdef N_SET_FLAGS
+ N_SET_FLAGS(header, 0);
+#else
+ /* XXX - works for 386BSD */
+#endif
+#else
+ header.a_flags = sepid ? A_SEP : A_EXEC;
+ if (uzp)
+ header.a_flags |= A_UZP;
+#endif
+ }
+#ifdef BSD_A_OUT
+#ifdef STANDARD_GNU_A_OUT
+#ifdef N_SET_FLAGS
+ N_SET_MACHTYPE(header, M_386);
+#else
+ /* XXX - works for 386BSD which doesn't define its own machtype :-( */
+#endif
+#else
+ header.a_cpu = (bits32 || reloc_output) ? A_I80386 : A_I8086;
+#endif
+#else
+ header.a_cpu = bits32 ? A_I80386 : A_I8086;
+#endif
+#ifndef STANDARD_GNU_A_OUT
+ header.a_hdrlen = FILEHEADERLENGTH;
+#endif
+#ifdef QMAGIC
+ if (uzp)
+ offtocn((char *) &header.a_text, etextpadoff - btextoffset+HEADERLEN,
+ sizeof header.a_text);
+ else
+#endif
+ offtocn((char *) &header.a_text, etextpadoff - btextoffset,
+ sizeof header.a_text);
+ offtocn((char *) &header.a_data, edataoffset - bdataoffset,
+ sizeof header.a_data);
+ offtocn((char *) &header.a_bss, endoffset - edataoffset,
+ sizeof header.a_bss);
+
+#ifdef REL_OUTPUT
+ if (!reloc_output)
+#endif
+ {
+ offtocn((char *) &header.a_entry, btextoffset,
+ sizeof header.a_entry);
+#ifndef STANDARD_GNU_A_OUT
+ offtocn((char *) &header.a_total, (bin_off_t)
+ (endoffset < 0x00010000L ? 0x00010000L : endoffset + 0x0008000L),
+ sizeof header.a_total);
+#endif
+ }
+ if( FILEHEADERLENGTH )
+ writeout((char *) &header, FILEHEADERLENGTH);
+}
+
+#endif /* MINIX */
+
+PRIVATE void writenulls(count)
+bin_off_t count;
+{
+ long lcount = count;
+ if( lcount < 0 )
+ fatalerror("org command requires reverse seek");
+ spos += count;
+ while (count-- > 0)
+ writechar(0);
+}
+#else
+
+#ifndef FUNCNAME
+#define FUNCNAME writebin
+#endif
+
+PUBLIC void FUNCNAME(outfilename, argsepid, argbits32, argstripflag, arguzp)
+char *outfilename;
+bool_pt argsepid;
+bool_pt argbits32;
+bool_pt argstripflag;
+bool_pt arguzp;
+{
+ char * s = "WARNING: Native a.out generation not included, sorry\n";
+ write(2, s, strlen(s));
+/* write_elks(outfilename, argsepid, argbits32, argstripflag, arguzp, 0); */
+}
+#endif
--- /dev/null
+/*
+ * This uses a special version of writebin for bug compatibility with
+ * the old bin86 package.
+ *
+ * This _should_ be replaced by a function that writes out a as86 object
+ * but then it would completely **** up dosemu compiles.
+ *
+ * NOTE: A some time I intend to replace this with a routine that generates
+ * an as86 object file.
+ */
+
+#undef A_OUT_INCL
+#define A_OUT_INCL "rel_aout.h"
+#define BSD_A_OUT 1
+#define FILEHEADERLENGTH 32
+#define ELF_SYMS 0
+
+#define FUNCNAME write_dosemu
+
+#include "writebin.c"
--- /dev/null
+/* writex86.c - write binary file for linker */
+
+/* Copyright (C) 1994 Bruce Evans */
+
+#include "syshead.h"
+#include "x86_aout.h"
+#ifndef VERY_SMALL_MEMORY
+#include "v7_aout.h"
+#endif
+#ifndef MSDOS
+#include "x86_cpm86.h"
+#endif
+#include "const.h"
+#include "obj.h"
+#include "type.h"
+#include "globvar.h"
+
+#define btextoffset (text_base_value)
+#define bdataoffset (data_base_value)
+#define page_size() ((bin_off_t)4096)
+
+#ifndef ELF_SYMS
+#define ELF_SYMS 0
+#endif
+
+#ifdef MSDOS
+# define FILEHEADERLENGTH (headerless?0:A_MINHDR)
+#else
+# ifdef VERY_SMALL_MEMORY
+# define FILEHEADERLENGTH (headerless?0:(cpm86?CPM86_HEADERLEN:A_MINHDR))
+# else
+# define FILEHEADERLENGTH (headerless?0:(cpm86?CPM86_HEADERLEN:(v7?V7_HEADERLEN:A_MINHDR)))
+# endif
+#endif
+ /* part of header not counted in offsets */
+#define DPSEG 2
+
+#define CM_MASK 0xC0
+#define MODIFY_MASK 0x3F
+#define S_MASK 0x04
+#define OF_MASK 0x03
+
+#define CM_SPECIAL 0
+#define CM_ABSOLUTE 0x40
+#define CM_OFFSET_RELOC 0x80
+#define CM_SYMBOL_RELOC 0xC0
+
+#define CM_EOT 0
+#define CM_BYTE_SIZE 1
+#define CM_WORD_SIZE 2
+#define CM_LONG_SIZE 3
+#define CM_1_SKIP 17
+#define CM_2_SKIP 18
+#define CM_4_SKIP 19
+#define CM_0_SEG 32
+
+#define ABS_TEXT_MAX 64
+
+#define offsetof(struc, mem) ((int) &((struc *) 0)->mem)
+#define memsizeof(struc, mem) sizeof(((struc *) 0)->mem)
+
+PRIVATE bool_t bits32; /* nonzero for 32-bit executable */
+PRIVATE bin_off_t combase[NSEG];/* bases of common parts of segments */
+PRIVATE bin_off_t comsz[NSEG]; /* sizes of common parts of segments */
+PRIVATE fastin_t curseg; /* current segment, 0 to $F */
+PRIVATE bin_off_t edataoffset; /* end of data */
+PRIVATE bin_off_t endoffset; /* end of bss */
+PRIVATE bin_off_t etextoffset; /* end of text */
+PRIVATE bin_off_t etextpadoff; /* end of padded text */
+PRIVATE unsigned nsym; /* number of symbols written */
+PRIVATE unsigned relocsize; /* current relocation size 1, 2 or 4 */
+PRIVATE bin_off_t segadj[NSEG]; /* adjusts (file offset - seg offset) */
+ /* depends on zero init */
+PRIVATE bin_off_t segbase[NSEG];/* bases of data parts of segments */
+PRIVATE char segboundary[9] = "__seg0DH";
+ /* name of seg boundary __seg0DL to __segfCH */
+PRIVATE bin_off_t segpos[NSEG]; /* segment positions for current module */
+PRIVATE bin_off_t segsz[NSEG]; /* sizes of data parts of segments */
+ /* depends on zero init */
+PRIVATE bool_t sepid; /* nonzero for separate I & D */
+PRIVATE bool_t stripflag; /* nonzero to strip symbols */
+PRIVATE bin_off_t spos; /* position in current seg */
+PRIVATE bool_t uzp; /* nonzero for unmapped zero page */
+PRIVATE bool_t xsym; /* extended symbol table */
+
+FORWARD void linkmod P((struct modstruct *modptr));
+FORWARD void padmod P((struct modstruct *modptr));
+FORWARD void setsym P((char *name, bin_off_t value));
+FORWARD void symres P((char *name));
+FORWARD void setseg P((fastin_pt newseg));
+FORWARD void skip P((unsigned countsize));
+FORWARD void writeheader P((void));
+#ifndef VERY_SMALL_MEMORY
+FORWARD void v7header P((void));
+#endif
+#ifndef MSDOS
+FORWARD void cpm86header P((void));
+#endif
+FORWARD void writenulls P((bin_off_t count));
+
+EXTERN bool_t reloc_output;
+
+/* write binary file */
+
+PUBLIC void write_elks(outfilename, argsepid, argbits32, argstripflag, arguzp, argxsym)
+char *outfilename;
+bool_pt argsepid;
+bool_pt argbits32;
+bool_pt argstripflag;
+bool_pt arguzp;
+bool_pt argxsym;
+{
+ char buf4[4];
+ char *cptr;
+ struct nlist extsym;
+ flags_t flags;
+ struct modstruct *modptr;
+ fastin_t seg;
+ unsigned sizecount;
+ bin_off_t tempoffset;
+
+ if( reloc_output )
+#ifndef MSDOS
+ fatalerror("Output binformat not configured relocatable, use -N");
+#else
+ fatalerror("Cannot use -r under MSDOS, sorry");
+#endif
+
+ sepid = argsepid;
+ bits32 = argbits32;
+ stripflag = argstripflag;
+ uzp = arguzp;
+ xsym = argxsym;
+ if (uzp)
+ {
+ if (btextoffset == 0)
+ btextoffset = page_size();
+ if (bdataoffset == 0 && sepid)
+ bdataoffset = page_size();
+ }
+
+ /* reserve special symbols use curseg to pass parameter to symres() */
+ for (curseg = 0; curseg < NSEG; ++curseg)
+ {
+ segboundary[5] = hexdigit[curseg]; /* to __segX?H */
+ segboundary[6] = 'D';
+ symres(segboundary); /* __segXDH */
+ segboundary[7] = 'L';
+ symres(segboundary); /* __segXDL */
+ segboundary[6] = 'C';
+ symres(segboundary); /* __segXCL */
+ segboundary[7] = 'H';
+ symres(segboundary); /* __segXCH */
+#ifndef DATASEGS
+ if( curseg > 3 )
+ {
+ segboundary[6] = 'S';
+ segboundary[7] = 'O';
+ symres(segboundary); /* __segXSO */
+ }
+#endif
+ }
+ curseg = 3;
+ symres("__edata");
+ symres("__end");
+ symres("__heap_top");
+ curseg = 0; /* text seg, s.b. variable */
+ symres("__etext");
+ symres("__segoff");
+
+ /* calculate segment and common sizes (sum over loaded modules) */
+ /* use zero init of segsz[] */
+ /* also relocate symbols relative to starts of their segments */
+ for (modptr = modfirst; modptr != NUL_PTR; modptr = modptr->modnext)
+ if (modptr->loadflag)
+ {
+ register struct symstruct **symparray;
+ register struct symstruct *symptr;
+
+ for (symparray = modptr->symparray;
+ (symptr = *symparray) != NUL_PTR; ++symparray)
+ if (symptr->modptr == modptr && !(symptr->flags & A_MASK))
+ {
+ if (!(symptr->flags & (I_MASK | SA_MASK)))
+ {
+ /* relocate by offset of module in segment later */
+ /* relocate by offset of segment in memory special */
+ /* symbols get relocated improperly */
+ symptr->value += segsz[symptr->flags & SEGM_MASK];
+ }
+ else if (symptr->value == 0)
+ {
+ undefined(symptr->name);
+ }
+ else
+ {
+ tempoffset = ld_roundup(symptr->value, 4, bin_off_t);
+ /* temp kludge quad alignment for 386 */
+ symptr->value = comsz[seg = symptr->flags & SEGM_MASK];
+ comsz[seg] += tempoffset;
+ if (!(symptr->flags & SA_MASK))
+ symptr->flags |= C_MASK;
+ }
+ }
+ for (seg = 0, cptr = modptr->segsize; seg < NSEG; ++seg)
+ {
+ segsz[seg] += cntooffset(cptr,
+ sizecount = segsizecount((unsigned) seg, modptr));
+
+ /* adjust sizes to even to get quad boundaries */
+ /* this should be specifiable dynamically */
+ segsz[seg] = ld_roundup(segsz[seg], 4, bin_off_t);
+ comsz[seg] = ld_roundup(comsz[seg], 4, bin_off_t);
+ cptr += sizecount;
+ }
+ }
+
+ /* calculate seg positions now their sizes are known */
+ /*
+#ifdef DATASEGS
+ * Assume seg 0 is text and rest are data
+#else
+ * Assume seg 1..3 are data, Seg 0 is real text, seg 4+ are far text
+#endif
+ */
+ segpos[0] = segbase[0] = spos = btextoffset;
+ combase[0] = segbase[0] + segsz[0];
+ segadj[1] = segadj[0] = -btextoffset;
+ etextpadoff = etextoffset = combase[0] + comsz[0];
+ if (sepid)
+ {
+ etextpadoff = ld_roundup(etextoffset, 0x10, bin_off_t);
+ segadj[1] += etextpadoff - bdataoffset;
+ }
+ else if (bdataoffset == 0)
+ bdataoffset = etextpadoff;
+ segpos[1] = segbase[1] = edataoffset = bdataoffset;
+ combase[1] = segbase[1] + segsz[1];
+#ifndef DATASEGS
+ for (seg = 4; seg < NSEG; ++seg)
+ {
+ segpos[seg] = segbase[seg] = 0;
+ combase[seg] = segbase[seg] + segsz[seg];
+ segadj[seg] = etextpadoff;
+
+ etextpadoff += ld_roundup(segsz[seg] + comsz[seg], 0x10, bin_off_t);
+ segadj[1] += ld_roundup(segsz[seg] + comsz[seg], 0x10, bin_off_t);
+ }
+ for (seg = 2; seg < 4; ++seg)
+#else
+ for (seg = 2; seg < NSEG; ++seg)
+#endif
+ {
+ segpos[seg] = segbase[seg] = combase[seg - 1] + comsz[seg - 1];
+#ifdef MC6809
+ if (seg == DPSEG)
+ {
+ /* temporarily have fixed DP seg */
+ /* adjust if nec so it only spans 1 page */
+ tempoffset = segsz[seg] + comsz[seg];
+ if (tempoffset > 0x100)
+ fatalerror("direct page segment too large");
+ if ((((segbase[seg] + tempoffset) ^ segbase[seg])
+ & ~(bin_off_t) 0xFF) != 0)
+ segpos[seg] = segbase[seg] = (segbase[seg] + 0xFF)
+ & ~(bin_off_t) 0xFF;
+ }
+#endif
+ combase[seg] = segbase[seg] + segsz[seg];
+ segadj[seg] = segadj[seg - 1];
+ }
+
+ /* relocate symbols by offsets of segments in memory */
+ for (modptr = modfirst; modptr != NUL_PTR; modptr = modptr->modnext)
+ if (modptr->loadflag)
+ {
+ register struct symstruct **symparray;
+ register struct symstruct *symptr;
+
+ for (symparray = modptr->symparray;
+ (symptr = *symparray) != NUL_PTR; ++symparray)
+ if (symptr->modptr == modptr && !(symptr->flags & A_MASK))
+ {
+ if (symptr->flags & (C_MASK | SA_MASK))
+ symptr->value += combase[symptr->flags & SEGM_MASK];
+ else
+ symptr->value += segbase[symptr->flags & SEGM_MASK];
+ }
+ }
+
+ /* adjust special symbols */
+ for (seg = 0; seg < NSEG; ++seg)
+ {
+#ifdef DATASEGS
+ if (segsz[seg] != 0)
+ /* only count data of nonzero length */
+#else
+ if (segsz[seg] != 0 && seg < 4)
+#endif
+ edataoffset = segbase[seg] + segsz[seg];
+ segboundary[5] = hexdigit[seg]; /* to __segX?H */
+ segboundary[6] = 'D';
+ setsym(segboundary, (tempoffset = segbase[seg]) + segsz[seg]);
+ /* __segXDH */
+ segboundary[7] = 'L';
+ setsym(segboundary, tempoffset); /* __segXDL */
+ segboundary[6] = 'C';
+ setsym(segboundary, tempoffset = combase[seg]);
+ /* __segXCL */
+ segboundary[7] = 'H';
+ setsym(segboundary, tempoffset + comsz[seg]);
+ /* __segXCH */
+#ifndef DATASEGS
+ if( seg > 3 )
+ {
+ segboundary[6] = 'S';
+ segboundary[7] = 'O';
+ setsym(segboundary, (bin_off_t)(segadj[seg]-segadj[0])/0x10);
+ /* __segXSO */
+ }
+#endif
+ }
+ setsym("__etext", etextoffset);
+ setsym("__edata", edataoffset);
+#ifdef DATASEGS
+ setsym("__end", endoffset = combase[NSEG - 1] + comsz[NSEG - 1]);
+#else
+ setsym("__end", endoffset = combase[3] + comsz[3]);
+#endif
+ setsym("__segoff", (bin_off_t)(segadj[1]-segadj[0])/0x10);
+ if( !bits32 )
+ {
+ if( etextoffset > 65536L )
+ fatalerror("text segment too large for 16bit");
+ if( endoffset > 65536L )
+ fatalerror("data segment too large for 16bit");
+ }
+
+ if( heap_top_value < 0x100 || endoffset > heap_top_value-0x100)
+ heap_top_value = endoffset + 0x8000;
+ if( heap_top_value > 0x10000 && !bits32 ) heap_top_value = 0x10000;
+ setsym("__heap_top", (bin_off_t)heap_top_value);
+
+ openout(outfilename);
+#ifndef MSDOS
+ if (cpm86) cpm86header();
+ else
+#endif
+#ifndef VERY_SMALL_MEMORY
+ if (v7)
+ v7header();
+ else
+#endif
+ writeheader();
+ for (modptr = modfirst; modptr != NUL_PTR; modptr = modptr->modnext)
+ if (modptr->loadflag)
+ {
+ linkmod(modptr);
+ padmod(modptr);
+ }
+
+ /* dump symbol table */
+ if (!stripflag)
+ {
+ seekout(FILEHEADERLENGTH
+ + (unsigned long) (etextpadoff - btextoffset)
+ + (unsigned long) (edataoffset - bdataoffset)
+ );
+ extsym.n_numaux = extsym.n_type = 0;
+ for (modptr = modfirst; modptr != NUL_PTR; modptr = modptr->modnext)
+ if (modptr->loadflag)
+ {
+ register struct symstruct **symparray;
+ register struct symstruct *symptr;
+
+ for (symparray = modptr->symparray;
+ (symptr = *symparray) != NUL_PTR; ++symparray)
+ if (symptr->modptr == modptr)
+ {
+#if ELF_SYMS
+ if (symptr->name[0] == '_' && symptr->name[1] )
+ strncpy((char *) extsym.n_name, symptr->name+1,
+ sizeof extsym.n_name);
+ else
+ {
+ memcpy((char *) extsym.n_name, "$", 1);
+ strncpy((char *) extsym.n_name+1, symptr->name,
+ sizeof(extsym.n_name)-1);
+ }
+#else
+ strncpy((char *) extsym.n_name, symptr->name,
+ sizeof extsym.n_name);
+#endif
+ u4cn((char *) &extsym.n_value, (u4_t) symptr->value,
+ sizeof extsym.n_value);
+ if ((flags = symptr->flags) & A_MASK)
+ extsym.n_sclass = N_ABS;
+ else if (flags & (E_MASK | I_MASK))
+ extsym.n_sclass = C_EXT;
+ else
+ extsym.n_sclass = C_STAT;
+ if (!(flags & I_MASK) ||
+ flags & C_MASK)
+ switch (flags & (A_MASK | SEGM_MASK))
+ {
+#ifdef DATASEGS
+ case 0:
+#else
+ default:
+#endif
+ extsym.n_sclass |= N_TEXT;
+ case A_MASK:
+ break;
+#ifdef DATASEGS
+ default:
+#else
+ case 1: case 2: case 3:
+ case A_MASK|1: case A_MASK|2: case A_MASK|3:
+#endif
+ if (flags & (C_MASK | SA_MASK))
+ extsym.n_sclass |= N_BSS;
+ else
+ extsym.n_sclass |= N_DATA;
+ break;
+ }
+ writeout((char *) &extsym, sizeof extsym);
+ ++nsym;
+#if !ELF_SYMS
+ if( xsym )
+ {
+ int i;
+ extsym.n_sclass = 0;
+ memset((void*)&extsym.n_value,0,
+ sizeof(extsym.n_value));
+
+ for(i=sizeof extsym.n_name; i<strlen(symptr->name);
+ i+=sizeof extsym.n_name)
+ {
+ strncpy((char *) extsym.n_name, symptr->name+i,
+ sizeof extsym.n_name);
+ writeout((char *) &extsym, sizeof extsym);
+ ++nsym;
+ }
+ }
+#endif
+ }
+ }
+ seekout((unsigned long) offsetof(struct exec, a_syms));
+ u4cn(buf4, (u4_t) nsym * sizeof extsym,
+ memsizeof(struct exec, a_syms));
+ writeout(buf4, memsizeof(struct exec, a_syms));
+ }
+ closeout();
+ executable();
+}
+
+PRIVATE void linkmod(modptr)
+struct modstruct *modptr;
+{
+ char buf[ABS_TEXT_MAX];
+ int command;
+ unsigned char modify;
+ bin_off_t offset;
+ int symbolnum;
+ struct symstruct **symparray;
+ struct symstruct *symptr;
+
+ setseg(0);
+ relocsize = 2;
+ symparray = modptr->symparray;
+ openin(modptr->filename); /* does nothing if already open */
+ seekin(modptr->textoffset);
+ while (TRUE)
+ {
+ if ((command = readchar()) < 0)
+ prematureeof();
+ modify = command & MODIFY_MASK;
+ switch (command & CM_MASK)
+ {
+ case CM_SPECIAL:
+ switch (modify)
+ {
+ case CM_EOT:
+ segpos[curseg] = spos;
+ return;
+ case CM_BYTE_SIZE:
+ relocsize = 1;
+ break;
+ case CM_WORD_SIZE:
+ relocsize = 2;
+ break;
+ case CM_LONG_SIZE:
+#ifdef LONG_OFFSETS
+ relocsize = 4;
+ break;
+#else
+ fatalerror("relocation by long offsets not implemented");
+#endif
+ case CM_1_SKIP:
+ skip(1);
+ break;
+ case CM_2_SKIP:
+ skip(2);
+ break;
+ case CM_4_SKIP:
+ skip(4);
+ break;
+ default:
+ if ((modify -= CM_0_SEG) >= NSEG)
+ inputerror("bad data in");
+ setseg(modify);
+ break;
+ }
+ break;
+ case CM_ABSOLUTE:
+ if (modify == 0)
+ modify = ABS_TEXT_MAX;
+ readin(buf, (unsigned) modify);
+ writeout(buf, (unsigned) modify);
+ spos += (int) modify;
+ break;
+ case CM_OFFSET_RELOC:
+ offset = readsize(relocsize);
+ if (modify & R_MASK)
+ {
+#ifndef DATASEGS
+ int m = (modify & SEGM_MASK);
+ if( curseg != m && m != SEGM_MASK )
+ interseg(modptr->filename, modptr->archentry, (char*)0);
+#endif
+ offset -= (spos + relocsize);
+ }
+ offtocn(buf, segbase[modify & SEGM_MASK] + offset, relocsize);
+ writeout(buf, relocsize);
+ spos += relocsize;
+ break;
+ case CM_SYMBOL_RELOC:
+ symptr = symparray[symbolnum = readconvsize((unsigned)
+ (modify & S_MASK ? 2 : 1))];
+ offset = readconvsize((unsigned) modify & OF_MASK);
+ if (modify & R_MASK)
+ {
+#ifndef DATASEGS
+ int m = (symptr->flags & SEGM_MASK);
+ if( curseg != m && m != SEGM_MASK )
+ interseg(modptr->filename, modptr->archentry, symptr->name);
+#endif
+ offset -= (spos + relocsize);
+ }
+ offset += symptr->value;
+ offtocn(buf, offset, relocsize);
+ writeout(buf, relocsize);
+ spos += relocsize;
+ }
+ }
+}
+
+PRIVATE void padmod(modptr)
+struct modstruct *modptr;
+{
+ bin_off_t count;
+ fastin_t seg;
+ bin_off_t size;
+ unsigned sizecount;
+ char *sizeptr;
+
+ for (seg = 0, sizeptr = modptr->segsize; seg < NSEG; ++seg)
+ {
+ size = cntooffset(sizeptr,
+ sizecount = segsizecount((unsigned) seg, modptr));
+ sizeptr += sizecount;
+ if ((count = segpos[seg] - segbase[seg]) != size)
+ size_error(seg, count, size);
+
+ /* pad to quad boundary */
+ /* not padding in-between common areas which sometimes get into file */
+ if ((size = ld_roundup(segpos[seg], 4, bin_off_t) - segpos[seg]) != 0)
+ {
+ setseg(seg);
+ writenulls(size);
+ segpos[seg] = spos;
+ }
+ segbase[seg] = segpos[seg];
+ }
+}
+
+PRIVATE void setsym(name, value)
+char *name;
+bin_off_t value;
+{
+ struct symstruct *symptr;
+
+ if ((symptr = findsym(name)) != NUL_PTR)
+ symptr->value = value;
+}
+
+PRIVATE void symres(name)
+register char *name;
+{
+ register struct symstruct *symptr;
+
+ if ((symptr = findsym(name)) != NUL_PTR)
+ {
+ if ((symptr->flags & SEGM_MASK) == SEGM_MASK)
+ symptr->flags &= ~SEGM_MASK | curseg;
+ if (symptr->flags != (I_MASK | curseg) || symptr->value != 0)
+ reserved(name);
+ symptr->flags = E_MASK | curseg; /* show defined, not common */
+ }
+}
+
+/* set new segment */
+
+PRIVATE void setseg(newseg)
+fastin_pt newseg;
+{
+ if (newseg != curseg)
+ {
+ segpos[curseg] = spos;
+ spos = segpos[curseg = newseg];
+ seekout(FILEHEADERLENGTH + (unsigned long) spos
+ + (unsigned long) segadj[curseg]);
+ }
+}
+
+PRIVATE void skip(countsize)
+unsigned countsize;
+{
+ writenulls((bin_off_t) readsize(countsize));
+}
+
+#ifndef MSDOS
+PRIVATE void cpm86header()
+{
+ struct cpm86_exec header;
+ memset(&header, 0, sizeof header);
+
+ if (sepid)
+ {
+ header.ce_group[0].cg_type = CG_CODE;
+ u2c2(header.ce_group[0].cg_len, (15 + etextpadoff) / 16);
+ u2c2(header.ce_group[0].cg_min, (15 + etextpadoff) / 16);
+ header.ce_group[1].cg_type = CG_DATA;
+ u2c2(header.ce_group[1].cg_len, (15 + edataoffset) / 16);
+ u2c2(header.ce_group[1].cg_min, (15 + endoffset ) / 16);
+ u2c2(header.ce_group[1].cg_max, 0x1000);
+ }
+ else
+ {
+ header.ce_group[0].cg_type = CG_CODE;
+ u2c2(header.ce_group[0].cg_len, (15 + edataoffset) / 16);
+ u2c2(header.ce_group[0].cg_min, (15 + endoffset ) / 16);
+ }
+ if( FILEHEADERLENGTH )
+ writeout((char *) &header, FILEHEADERLENGTH);
+}
+#endif
+
+PRIVATE void writeheader()
+{
+ struct exec header;
+
+ memset(&header, 0, sizeof header);
+ header.a_magic[0] = A_MAGIC0;
+ header.a_magic[1] = A_MAGIC1;
+ header.a_flags = sepid ? A_SEP : A_EXEC;
+ if (uzp)
+ header.a_flags |= A_UZP;
+ header.a_cpu = bits32 ? A_I80386 : A_I8086;
+ header.a_hdrlen = FILEHEADERLENGTH;
+ offtocn((char *) &header.a_text, etextpadoff - btextoffset,
+ sizeof header.a_text);
+ offtocn((char *) &header.a_data, edataoffset - bdataoffset,
+ sizeof header.a_data);
+ offtocn((char *) &header.a_bss, endoffset - edataoffset,
+ sizeof header.a_bss);
+ if (uzp)
+ offtocn((char *) &header.a_entry, page_size(),
+ sizeof header.a_entry);
+
+ offtocn((char *) &header.a_total, (bin_off_t) heap_top_value,
+ sizeof header.a_total);
+ if( FILEHEADERLENGTH )
+ writeout((char *) &header, FILEHEADERLENGTH);
+}
+
+#ifndef VERY_SMALL_MEMORY
+PRIVATE void v7header()
+{
+ struct v7_exec header;
+
+ if( sizeof header != FILEHEADERLENGTH )
+ fatalerror("Executable miscompiled, computed wrong header size");
+
+ memset(&header, 0, sizeof header);
+
+ if( bits32 )
+ fatalerror("V7 a.out format is for 16-bit only");
+
+ offtocn((char *) &header.magic, sepid ? V7_MAGIC3 : V7_OMAGIC,
+ sizeof header.magic);
+
+ offtocn((char *) &header.textsize, etextpadoff - btextoffset,
+ sizeof header.textsize);
+ offtocn((char *) &header.datasize, edataoffset - bdataoffset,
+ sizeof header.datasize);
+ offtocn((char *) &header.bsssize, endoffset - edataoffset,
+ sizeof header.bsssize);
+
+ if( !stripflag )
+ fatalerror("Symbol table not implemented for V7 yet");
+
+ if( uzp )
+ fatalerror("No QMAGIC for V7");
+
+ offtocn((char *) &header.entry, entryfirst->elsymptr->value,
+ sizeof header.entry);
+
+ if( FILEHEADERLENGTH )
+ writeout((char *) &header, FILEHEADERLENGTH);
+}
+#endif
+
+PRIVATE void writenulls(count)
+bin_off_t count;
+{
+ long lcount = count;
+ spos += count;
+#if 0
+ /* This will only work if we record the highest spos found an seek there
+ * at the end of the generation
+ */
+
+ seekout(FILEHEADERLENGTH + (unsigned long) spos
+ + (unsigned long) segadj[curseg]);
+ return;
+
+#endif
+ if( lcount < 0 )
+ fatalerror("org command requires reverse seek");
+ while (count-- > 0)
+ writechar(0);
+}
--- /dev/null
+/* Copyright (C) 1990-1996
+ * This file is part of the ld86 command for Linux-86
+ * It is distributed under the GNU Library General Public License.
+ *
+ * - This may actually be BSD or Minix code, can someone clarify please. -RDB
+ */
+
+#ifndef __AOUT_H
+#define __AOUT_H
+
+/* If the host isn't an x86 all bets are off, use chars. */
+#if defined(i386) || defined(__BCC__) || defined(MSDOS)
+typedef long Long;
+#define __OUT_OK 1
+#else
+/* Beware: this will probably allow some BE hosts to generate broken files. */
+#ifdef INT32_MAX
+#include <stdint.h>
+typedef int32_t Long;
+#define __OUT_OK 1
+#else
+typedef char Long[4];
+#endif
+#endif
+
+struct exec { /* a.out header */
+ unsigned char a_magic[2]; /* magic number */
+ unsigned char a_flags; /* flags, see below */
+ unsigned char a_cpu; /* cpu id */
+ unsigned char a_hdrlen; /* length of header */
+ unsigned char a_unused; /* reserved for future use */
+ unsigned char a_version[2]; /* version stamp (not used at present) */
+ Long a_text; /* size of text segement in bytes */
+ Long a_data; /* size of data segment in bytes */
+ Long a_bss; /* size of bss segment in bytes */
+ Long a_entry; /* entry point */
+ Long a_total; /* total memory allocated */
+ Long a_syms; /* size of symbol table */
+
+ /* SHORT FORM ENDS HERE */
+ Long a_trsize; /* text relocation size */
+ Long a_drsize; /* data relocation size */
+ Long a_tbase; /* text relocation base */
+ Long a_dbase; /* data relocation base */
+};
+
+#define A_MAGIC0 (unsigned char) 0x01
+#define A_MAGIC1 (unsigned char) 0x03
+#define BADMAG(X) ((X).a_magic[0] != A_MAGIC0 ||(X).a_magic[1] != A_MAGIC1)
+
+/* CPU Id of TARGET machine (byte order coded in low order two bits) */
+#define A_NONE 0x00 /* unknown */
+#define A_I8086 0x04 /* intel i8086/8088 */
+#define A_M68K 0x0B /* motorola m68000 */
+#define A_NS16K 0x0C /* national semiconductor 16032 */
+#define A_I80386 0x10 /* intel i80386 */
+#define A_SPARC 0x17 /* Sun SPARC */
+
+#define A_BLR(cputype) ((cputype&0x01)!=0) /* TRUE if bytes left-to-right */
+#define A_WLR(cputype) ((cputype&0x02)!=0) /* TRUE if words left-to-right */
+
+/* Flags. */
+#define A_UZP 0x01 /* unmapped zero page (pages) */
+#define A_PAL 0x02 /* page aligned executable */
+#define A_NSYM 0x04 /* new style symbol table */
+#define A_EXEC 0x10 /* executable */
+#define A_SEP 0x20 /* separate I/D */
+#define A_PURE 0x40 /* pure text */
+#define A_TOVLY 0x80 /* text overlay */
+
+/* Offsets of various things. */
+#define A_MINHDR 32
+#define A_TEXTPOS(X) ((long)(X).a_hdrlen)
+#define A_HASRELS(X) ((X).a_hdrlen > (unsigned char) A_MINHDR)
+#define A_HASEXT(X) ((X).a_hdrlen > (unsigned char) (A_MINHDR + 8))
+#define A_HASLNS(X) ((X).a_hdrlen > (unsigned char) (A_MINHDR + 16))
+#define A_HASTOFF(X) ((X).a_hdrlen > (unsigned char) (A_MINHDR + 24))
+#ifdef __OUT_OK
+#define A_DATAPOS(X) (A_TEXTPOS(X) + (X).a_text)
+#define A_TRELPOS(X) (A_DATAPOS(X) + (X).a_data)
+#define A_DRELPOS(X) (A_TRELPOS(X) + (X).a_trsize)
+#define A_SYMPOS(X) (A_TRELPOS(X) + (A_HASRELS(X) ? \
+ ((X).a_trsize + (X).a_drsize) : 0))
+#endif
+
+struct reloc {
+ long r_vaddr; /* virtual address of reference */
+ unsigned short r_symndx; /* internal segnum or extern symbol num */
+ unsigned short r_type; /* relocation type */
+};
+
+/* r_tyep values: */
+#define R_ABBS 0
+#define R_RELLBYTE 2
+#define R_PCRBYTE 3
+#define R_RELWORD 4
+#define R_PCRWORD 5
+#define R_RELLONG 6
+#define R_PCRLONG 7
+#define R_REL3BYTE 8
+#define R_KBRANCHE 9
+
+/* r_symndx for internal segments */
+#define S_ABS ((unsigned short)-1)
+#define S_TEXT ((unsigned short)-2)
+#define S_DATA ((unsigned short)-3)
+#define S_BSS ((unsigned short)-4)
+
+struct nlist { /* symbol table entry */
+ char n_name[8]; /* symbol name */
+ Long n_value; /* value */
+ unsigned char n_sclass; /* storage class */
+ unsigned char n_numaux; /* number of auxiliary entries (not used) */
+ unsigned short n_type; /* language base and derived type (not used) */
+};
+
+/* Low bits of storage class (section). */
+#define N_SECT 07 /* section mask */
+#define N_UNDF 00 /* undefined */
+#define N_ABS 01 /* absolute */
+#define N_TEXT 02 /* text */
+#define N_DATA 03 /* data */
+#define N_BSS 04 /* bss */
+#define N_COMM 05 /* (common) */
+
+/* High bits of storage class. */
+#define N_CLASS 0370 /* storage class mask */
+#define C_NULL 0
+#define C_EXT 0020 /* external symbol */
+#define C_STAT 0030 /* static */
+
+#endif /* _AOUT_H */
--- /dev/null
+/* Copyright (C) 2002
+ * This file is part of the ld86 command for Linux-86
+ * It is distributed under the GNU Library General Public License.
+ *
+ * CP/M-86 CMD file header
+ */
+
+#ifndef __CPM86_H
+#define __CPM86_H
+
+typedef char Short16[2];
+
+struct cpm86_group {
+ unsigned char cg_type; /* 1=Code 2=Data */
+ Short16 cg_len; /* Group length, paragraphs */
+ Short16 cg_base; /* Group address, normally 0 for relocatable */
+ Short16 cg_min; /* Minimum size, normally = group length */
+ Short16 cg_max; /* Maximum size, normally 0x1000 (64k) */
+};
+
+
+struct cpm86_exec { /* CP/M-86 header */
+ struct cpm86_group ce_group[8];
+ unsigned char ce_spare[51];
+ Short16 ce_rsxs; /* Record with RSX list */
+ Short16 ce_fixups; /* Record with fixups */
+ unsigned char ce_flags; /* Concurrent CP/M flags */
+};
+
+/* Group types */
+#define CG_EMPTY 0
+#define CG_CODE 1
+#define CG_DATA 2
+#define CG_EXTRA 3
+#define CG_STACK 4
+#define CG_AUX1 5
+#define CG_AUX2 6
+#define CG_AUX3 7
+#define CG_AUX4 8
+#define CG_PURE 9 /* Code that is known to be pure */
+
+#define CPM86_HEADERLEN 0x80
+
+#endif /* _CPM86_H */