From e5b06a7876499642ec445ed658aff43a35312aeb Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 8 Jun 2015 22:22:55 +0100 Subject: [PATCH] ld09: first cut Needs the output side replacing with a simple binary writer for FUZIX format headers. This one actually should fit nicely on a Dragon32 ! --- Applications/ld09/Makefile | 61 ++ Applications/ld09/align.h | 23 + Applications/ld09/ar.h | 18 + Applications/ld09/bindef.h | 75 +++ Applications/ld09/byteord.h | 20 + Applications/ld09/catimage.c | 243 ++++++++ Applications/ld09/config.h | 28 + Applications/ld09/const.h | 14 + Applications/ld09/dumps.c | 95 +++ Applications/ld09/globvar.h | 25 + Applications/ld09/io.c | 643 ++++++++++++++++++++ Applications/ld09/ld.c | 280 +++++++++ Applications/ld09/ld86r.c | 86 +++ Applications/ld09/linksyms.c | 85 +++ Applications/ld09/mkar.c | 80 +++ Applications/ld09/obj.h | 50 ++ Applications/ld09/objchop.c | 91 +++ Applications/ld09/objdump86.c | 972 ++++++++++++++++++++++++++++++ Applications/ld09/readobj.c | 373 ++++++++++++ Applications/ld09/rel_aout.h | 383 ++++++++++++ Applications/ld09/syshead.h | 18 + Applications/ld09/table.c | 230 +++++++ Applications/ld09/type.h | 176 ++++++ Applications/ld09/typeconv.c | 191 ++++++ Applications/ld09/v7_aout.h | 26 + Applications/ld09/version.h | 1 + Applications/ld09/writebin.c | 1065 +++++++++++++++++++++++++++++++++ Applications/ld09/writeemu.c | 20 + Applications/ld09/writex86.c | 743 +++++++++++++++++++++++ Applications/ld09/x86_aout.h | 132 ++++ Applications/ld09/x86_cpm86.h | 44 ++ 31 files changed, 6291 insertions(+) create mode 100644 Applications/ld09/Makefile create mode 100644 Applications/ld09/align.h create mode 100644 Applications/ld09/ar.h create mode 100644 Applications/ld09/bindef.h create mode 100644 Applications/ld09/byteord.h create mode 100644 Applications/ld09/catimage.c create mode 100644 Applications/ld09/config.h create mode 100644 Applications/ld09/const.h create mode 100644 Applications/ld09/dumps.c create mode 100644 Applications/ld09/globvar.h create mode 100644 Applications/ld09/io.c create mode 100644 Applications/ld09/ld.c create mode 100644 Applications/ld09/ld86r.c create mode 100644 Applications/ld09/linksyms.c create mode 100644 Applications/ld09/mkar.c create mode 100644 Applications/ld09/obj.h create mode 100644 Applications/ld09/objchop.c create mode 100644 Applications/ld09/objdump86.c create mode 100644 Applications/ld09/readobj.c create mode 100644 Applications/ld09/rel_aout.h create mode 100644 Applications/ld09/syshead.h create mode 100644 Applications/ld09/table.c create mode 100644 Applications/ld09/type.h create mode 100644 Applications/ld09/typeconv.c create mode 100644 Applications/ld09/v7_aout.h create mode 100644 Applications/ld09/version.h create mode 100644 Applications/ld09/writebin.c create mode 100644 Applications/ld09/writeemu.c create mode 100644 Applications/ld09/writex86.c create mode 100644 Applications/ld09/x86_aout.h create mode 100644 Applications/ld09/x86_cpm86.h diff --git a/Applications/ld09/Makefile b/Applications/ld09/Makefile new file mode 100644 index 00000000..b8a34b0f --- /dev/null +++ b/Applications/ld09/Makefile @@ -0,0 +1,61 @@ +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 $@ diff --git a/Applications/ld09/align.h b/Applications/ld09/align.h new file mode 100644 index 00000000..52b1e897 --- /dev/null +++ b/Applications/ld09/align.h @@ -0,0 +1,23 @@ +/* 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 + + + + + + + diff --git a/Applications/ld09/ar.h b/Applications/ld09/ar.h new file mode 100644 index 00000000..c6083717 --- /dev/null +++ b/Applications/ld09/ar.h @@ -0,0 +1,18 @@ +#ifndef __AR_H +#define __AR_H + +#define ARMAG "!\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 */ diff --git a/Applications/ld09/bindef.h b/Applications/ld09/bindef.h new file mode 100644 index 00000000..c359509b --- /dev/null +++ b/Applications/ld09/bindef.h @@ -0,0 +1,75 @@ + +/* 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 +#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 */ diff --git a/Applications/ld09/byteord.h b/Applications/ld09/byteord.h new file mode 100644 index 00000000..c854979e --- /dev/null +++ b/Applications/ld09/byteord.h @@ -0,0 +1,20 @@ +/* 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 diff --git a/Applications/ld09/catimage.c b/Applications/ld09/catimage.c new file mode 100644 index 00000000..1f5e1609 --- /dev/null +++ b/Applications/ld09/catimage.c @@ -0,0 +1,243 @@ +/* + * 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 +#ifdef __STDC__ +#include +#include +#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); +} + diff --git a/Applications/ld09/config.h b/Applications/ld09/config.h new file mode 100644 index 00000000..dc5fed43 --- /dev/null +++ b/Applications/ld09/config.h @@ -0,0 +1,28 @@ +/* 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 */ diff --git a/Applications/ld09/const.h b/Applications/ld09/const.h new file mode 100644 index 00000000..04d63306 --- /dev/null +++ b/Applications/ld09/const.h @@ -0,0 +1,14 @@ +/* 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" diff --git a/Applications/ld09/dumps.c b/Applications/ld09/dumps.c new file mode 100644 index 00000000..10879b7f --- /dev/null +++ b/Applications/ld09/dumps.c @@ -0,0 +1,95 @@ +/* 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'); +} diff --git a/Applications/ld09/globvar.h b/Applications/ld09/globvar.h new file mode 100644 index 00000000..5663cc04 --- /dev/null +++ b/Applications/ld09/globvar.h @@ -0,0 +1,25 @@ +/* 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 */ diff --git a/Applications/ld09/io.c b/Applications/ld09/io.c new file mode 100644 index 00000000..542ab63b --- /dev/null +++ b/Applications/ld09/io.c @@ -0,0 +1,643 @@ +/* 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(); +} diff --git a/Applications/ld09/ld.c b/Applications/ld09/ld.c new file mode 100644 index 00000000..3a472681 --- /dev/null +++ b/Applications/ld09/ld.c @@ -0,0 +1,280 @@ +/* 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; +} diff --git a/Applications/ld09/ld86r.c b/Applications/ld09/ld86r.c new file mode 100644 index 00000000..dfc876d9 --- /dev/null +++ b/Applications/ld09/ld86r.c @@ -0,0 +1,86 @@ +#include +#include +#include +#include +#ifdef __STDC__ +#include +#include +#else +#include +#endif + +#define ARMAG "!\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 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; armodnext != 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); +} + diff --git a/Applications/ld09/mkar.c b/Applications/ld09/mkar.c new file mode 100644 index 00000000..b271a590 --- /dev/null +++ b/Applications/ld09/mkar.c @@ -0,0 +1,80 @@ + +#include +#include +#include +#include +#ifdef __STDC__ +#include +#include +#else +#include +#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 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 +#ifdef __STDC__ +#include +#include +#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 diff --git a/Applications/ld09/objdump86.c b/Applications/ld09/objdump86.c new file mode 100644 index 00000000..85032a17 --- /dev/null +++ b/Applications/ld09/objdump86.c @@ -0,0 +1,972 @@ +/* + * 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 + * Added archive file reading capabilties + */ + +#include +#ifdef __STDC__ +#include +#else +#include +#endif +#include +#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; ar1); + + if( display_mode == 1 ) + printf("text\tdata\tbss\tdec\thex\tfilename\n"); + + for(ar=1; ar 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>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 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; i7), 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 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 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)]; +} diff --git a/Applications/ld09/rel_aout.h b/Applications/ld09/rel_aout.h new file mode 100644 index 00000000..9316a72b --- /dev/null +++ b/Applications/ld09/rel_aout.h @@ -0,0 +1,383 @@ +#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 +#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 + +#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. */ + +#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 */ diff --git a/Applications/ld09/syshead.h b/Applications/ld09/syshead.h new file mode 100644 index 00000000..f107ac39 --- /dev/null +++ b/Applications/ld09/syshead.h @@ -0,0 +1,18 @@ +#include +#include +#include +#include +#include +#include +#include + +/******************************************************************************/ + +/* EEEEyuk!! */ + +#ifdef __STDC__ +#define P(x) x +#else +#define P(x) () +#endif + diff --git a/Applications/ld09/table.c b/Applications/ld09/table.c new file mode 100644 index 00000000..f960da05 --- /dev/null +++ b/Applications/ld09/table.c @@ -0,0 +1,230 @@ +/* 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); +} diff --git a/Applications/ld09/type.h b/Applications/ld09/type.h new file mode 100644 index 00000000..5301b6f0 --- /dev/null +++ b/Applications/ld09/type.h @@ -0,0 +1,176 @@ +/* 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)); diff --git a/Applications/ld09/typeconv.c b/Applications/ld09/typeconv.c new file mode 100644 index 00000000..d8c0c89c --- /dev/null +++ b/Applications/ld09/typeconv.c @@ -0,0 +1,191 @@ + +/* + * 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; + } +} diff --git a/Applications/ld09/v7_aout.h b/Applications/ld09/v7_aout.h new file mode 100644 index 00000000..020079b6 --- /dev/null +++ b/Applications/ld09/v7_aout.h @@ -0,0 +1,26 @@ +/* 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 */ diff --git a/Applications/ld09/version.h b/Applications/ld09/version.h new file mode 100644 index 00000000..0af81ac2 --- /dev/null +++ b/Applications/ld09/version.h @@ -0,0 +1 @@ +#define VERSION "0.16.21" diff --git a/Applications/ld09/writebin.c b/Applications/ld09/writebin.c new file mode 100644 index 00000000..85350689 --- /dev/null +++ b/Applications/ld09/writebin.c @@ -0,0 +1,1065 @@ + +/* 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 diff --git a/Applications/ld09/writeemu.c b/Applications/ld09/writeemu.c new file mode 100644 index 00000000..b0438fc5 --- /dev/null +++ b/Applications/ld09/writeemu.c @@ -0,0 +1,20 @@ +/* + * 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" diff --git a/Applications/ld09/writex86.c b/Applications/ld09/writex86.c new file mode 100644 index 00000000..feb7b550 --- /dev/null +++ b/Applications/ld09/writex86.c @@ -0,0 +1,743 @@ +/* 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; iname); + 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); +} diff --git a/Applications/ld09/x86_aout.h b/Applications/ld09/x86_aout.h new file mode 100644 index 00000000..542a70df --- /dev/null +++ b/Applications/ld09/x86_aout.h @@ -0,0 +1,132 @@ +/* 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 +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 */ diff --git a/Applications/ld09/x86_cpm86.h b/Applications/ld09/x86_cpm86.h new file mode 100644 index 00000000..0a858f51 --- /dev/null +++ b/Applications/ld09/x86_cpm86.h @@ -0,0 +1,44 @@ +/* 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 */ -- 2.34.1