summaryrefslogtreecommitdiff
path: root/ld
diff options
context:
space:
mode:
authorRobert de Bath <rdebath@poboxes.com>1996-11-03 22:33:35 +0100
committerLubomir Rintel <lkundrak@v3.sk>2013-10-23 23:33:35 +0200
commitc218c617b5be443b7968308506969ad2b726d73c (patch)
tree0051f396af56133d24fcf2ab757fabc78c1a09bf /ld
parent0936b9aeab611665645a4e6bafaded7ca76dd189 (diff)
parent0d2fbe9b1bd284ce2cad55be17e8f2c896031a25 (diff)
downloaddev86-c218c617b5be443b7968308506969ad2b726d73c.tar.gz
Import Dev86src-0.0.8.tar.gzv0.0.8
Diffstat (limited to 'ld')
-rw-r--r--ld/Makefile21
-rw-r--r--ld/bindef.h68
-rw-r--r--ld/config.h7
-rw-r--r--ld/globvar.h12
-rw-r--r--ld/io.c39
-rw-r--r--ld/ld.c75
-rw-r--r--ld/linksyms.c84
-rw-r--r--ld/readobj.c2
-rw-r--r--ld/syshead.h45
-rw-r--r--ld/type.h18
-rw-r--r--ld/writebin.c179
-rw-r--r--ld/writex86.c547
-rw-r--r--ld/x86_aout.h (renamed from ld/a.out.h)0
13 files changed, 882 insertions, 215 deletions
diff --git a/ld/Makefile b/ld/Makefile
index 784763a..a4d2bb7 100644
--- a/ld/Makefile
+++ b/ld/Makefile
@@ -2,13 +2,17 @@
ifneq ($(TOPDIR),)
include $(TOPDIR)/Make.defs
-# CFLAGS=$(CCFLAGS) -DBSD_A_OUT
+CFLAGS=$(CCFLAGS) -DREL_OUTPUT
else
-CC=bcc
-LDFLAGS=-s
+CC=bcc -3 -N
+LDFLAGS=
endif
-OBJS =dumps.o io.o ld.o readobj.o table.o typeconv.o writebin.o
+# May need some of these if the auto-sense fails.
+# -DV7_A_OUT -DBSD_A_OUT -DSTANDARD_GNU_A_OUT
+
+OBJS= dumps.o io.o ld.o readobj.o table.o typeconv.o linksyms.o \
+ writex86.o writebin.o
all: ld86
@@ -22,10 +26,5 @@ install: ld86
clean:
rm -f $(OBJS) ld86
-dumps.o: dumps.c const.h config.h obj.h type.h globvar.h
-io.o: io.c const.h config.h obj.h type.h globvar.h
-ld.o: ld.c const.h config.h byteord.h type.h globvar.h
-readobj.o: readobj.c const.h config.h byteord.h obj.h type.h globvar.h
-table.o: table.c const.h config.h align.h obj.h type.h globvar.h
-typeconv.o: typeconv.c const.h config.h type.h globvar.h
-writebin.o: writebin.c const.h config.h obj.h type.h globvar.h
+$(OBJS): align.h ar.h bindef.h byteord.h config.h const.h globvar.h obj.h \
+ syshead.h type.h x86_aout.h
diff --git a/ld/bindef.h b/ld/bindef.h
new file mode 100644
index 0000000..4ccaf53
--- /dev/null
+++ b/ld/bindef.h
@@ -0,0 +1,68 @@
+
+/* Ok, I'm just gonna make it simple ... override this if you like. */
+#ifndef A_OUT_INCL
+#define A_OUT_INCL "a.out.h"
+#endif
+
+/* This is how it used to be ... */
+#ifndef A_OUT_INCL
+# ifdef BSD_A_OUT
+# ifdef STANDARD_GNU_A_OUT
+# define A_OUT_INCL <a.out.h>
+# else
+# define A_OUT_INCL "bsd-a.out.h"
+# endif
+
+# ifdef MSDOS
+# define A_OUT_INCL "a_out.h"
+# else
+# define A_OUT_INCL "a.out.h" /* maybe local copy of <a.out.h> for X-link */
+# endif
+# endif /* BSD_A_OUT */
+#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
+# define C_EXT N_EXT
+# 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 */
+
diff --git a/ld/config.h b/ld/config.h
index 1629ba3..a36e010 100644
--- a/ld/config.h
+++ b/ld/config.h
@@ -17,13 +17,18 @@
#undef HOST_8BIT /* enable some 8-bit optimizations */
-#ifndef __BCC__
+#ifndef __AS386_16__
#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 */
#endif
+/* Any machine can use long offsets but i386 needs them */
+#ifdef I80386
+#define LONG_OFFSETS
+#endif
+
/* these must be defined to suit the source libraries */
#define CREAT_PERMS 0666 /* permissions for creat() */
diff --git a/ld/globvar.h b/ld/globvar.h
index 0351a6b..d257d5c 100644
--- a/ld/globvar.h
+++ b/ld/globvar.h
@@ -2,13 +2,17 @@
/* Copyright (C) 1994 Bruce Evans */
-#ifdef EXTERN
-EXTERN char hexdigit[];
-#else
+#ifndef EXTERN
#define EXTERN
-PUBLIC char hexdigit[] = "0123456789abcdef";
#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 */
+
+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 */
diff --git a/ld/io.c b/ld/io.c
index fa4862a..7b88222 100644
--- a/ld/io.c
+++ b/ld/io.c
@@ -4,7 +4,6 @@
#include "syshead.h"
#include "const.h"
-#include "obj.h" /* needed for LONG_OFFSETS and bin_off_t */
#include "type.h"
#include "globvar.h"
@@ -15,7 +14,7 @@
#define OUTBUFSIZE 2048
#define TRELBUFSIZE 1024
-#ifdef BSD_A_OUT
+#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 */
@@ -35,7 +34,7 @@ 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 BSD_A_OUT
+#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 */
@@ -45,7 +44,7 @@ PRIVATE unsigned warncount; /* count of warnings */
FORWARD void errexit P((char *message));
FORWARD void flushout P((void));
-#ifdef BSD_A_OUT
+#ifdef REL_OUTPUT
FORWARD void flushtrel P((void));
#endif
FORWARD void outhexdigs P((bin_off_t num));
@@ -62,7 +61,7 @@ char *progname;
refname = progname; /* name must be static (is argv[0]) */
else
refname = "link";
-#ifdef BSD_A_OUT
+#ifdef REL_OUTPUT
drelbuf = malloc(DRELBUFSIZE);
drelbuftop = drelbuf + DRELBUFSIZE;
#endif
@@ -73,7 +72,7 @@ char *progname;
outbuf = malloc(OUTBUFSIZE);/* outbuf invalid if this fails but then */
/* will not be used - tableinit() aborts */
outbuftop = outbuf + OUTBUFSIZE;
-#ifdef BSD_A_OUT
+#ifdef REL_OUTPUT
trelbuf = malloc(TRELBUFSIZE);
trelbuftop = trelbuf + TRELBUFSIZE;
#endif
@@ -88,12 +87,12 @@ PUBLIC void closein()
PUBLIC void closeout()
{
-#ifdef BSD_A_OUT
+#ifdef REL_OUTPUT
unsigned nbytes;
#endif
flushout();
-#ifdef BSD_A_OUT
+#ifdef REL_OUTPUT
flushtrel();
nbytes = drelbufptr - drelbuf;
if (write(trelfd, drelbuf, nbytes) != nbytes)
@@ -101,7 +100,7 @@ PUBLIC void closeout()
#endif
if (close(outfd) == ERR)
outputerror("cannot close");
-#ifdef BSD_A_OUT
+#ifdef REL_OUTPUT
if (close(trelfd) == ERR)
outputerror("cannot close");
#endif
@@ -144,7 +143,7 @@ PRIVATE void flushout()
outbufptr = outbuf;
}
-#ifdef BSD_A_OUT
+#ifdef REL_OUTPUT
PRIVATE void flushtrel()
{
unsigned nbytes;
@@ -183,11 +182,11 @@ char *filename;
outputerror("cannot stat");
outputperms = statbuf.st_mode;
chmod(filename, outputperms & ~EXEC_PERMS);
-#ifdef BSD_A_OUT
+#ifdef REL_OUTPUT
drelbufptr = drelbuf;
#endif
outbufptr = outbuf;
-#ifdef BSD_A_OUT
+#ifdef REL_OUTPUT
if ((trelfd = open(filename, O_BINARY|O_WRONLY|O_CREAT|O_TRUNC, CREAT_PERMS)) == ERR)
outputerror("cannot reopen");
trelbufptr = trelbuf;
@@ -344,7 +343,7 @@ unsigned long offset;
outputerror("cannot seek in");
}
-#ifdef BSD_A_OUT
+#ifdef REL_OUTPUT
PUBLIC void seektrel(offset)
unsigned long offset;
{
@@ -369,7 +368,7 @@ int ch;
outbufptr = obuf;
}
-#ifdef BSD_A_OUT
+#ifdef REL_OUTPUT
PUBLIC void writedrel(buf, count)
register char *buf;
unsigned count;
@@ -407,7 +406,7 @@ unsigned count;
outbufptr = obuf;
}
-#ifdef BSD_A_OUT
+#ifdef REL_OUTPUT
PUBLIC void writetrel(buf, count)
register char *buf;
unsigned count;
@@ -554,14 +553,14 @@ PUBLIC void usage()
{
putstr("usage: ");
putstr(refname);
-#ifdef BSD_A_OUT
+#ifdef REL_OUTPUT
errexit("\
- [-03Mimrstz[-]] [-llib_extension] [-o outfile] [-Ccrtfile]\n\
- [-Llibdir] [-Olibfile] [-T textaddr] infile...");
+ [-03NMdimrstz[-]] [-llib_extension] [-o outfile] [-Ccrtfile]\n\
+ [-Llibdir] [-Olibfile] [-T textaddr] [-D dataaddr] infile...");
#else
errexit("\
- [-03Mimstz[-]] [-llib_extension] [-o outfile] [-Ccrtfile]\n\
- [-Llibdir] [-Olibfile] [-T textaddr] infile...");
+ [-03NMdimstz[-]] [-llib_extension] [-o outfile] [-Ccrtfile]\n\
+ [-Llibdir] [-Olibfile] [-T textaddr] [-D dataaddr] infile...");
#endif
}
diff --git a/ld/ld.c b/ld/ld.c
index 214538e..eacbaa2 100644
--- a/ld/ld.c
+++ b/ld/ld.c
@@ -15,8 +15,10 @@
#define NR_STDLIBS 0
#endif
-PUBLIC long text_base_address; /* XXX */
-PUBLIC int doscomfile = 0;
+PUBLIC bin_off_t text_base_value = 0; /* XXX */
+PUBLIC bin_off_t data_base_value = 0; /* XXX */
+PUBLIC int headerless = 0;
+PUBLIC char hexdigit[] = "0123456789abcdef";
PRIVATE bool_t flag[128];
PRIVATE char *libs[MAX_LIBS] = {
@@ -81,7 +83,7 @@ char **argv;
syminit();
typeconv_init(BIG_ENDIAN, LONG_BIG_ENDIAN);
#ifndef MC6809
- flag['z'] = flag['3'] = sizeof(char *) >= 4;
+ flag['3'] = sizeof(char *) >= 4;
#endif
outfilename = NUL_PTR;
for (argn = 1; argn < argc; ++argn)
@@ -92,17 +94,29 @@ char **argv;
else
switch (arg[1])
{
+ case 'r': /* relocatable output */
+#ifndef REL_OUTPUT
+#ifndef MSDOS
+ /* Ok, try for an alternate linker */
+ if( strcmp(argv[0], "ld86r") != 0 )
+ {
+ argv[0] = "ld86r";
+ execv("/usr/bin/ld86r", argv);
+ execv("/usr/bin/ld86", argv);
+ }
+#endif
+ usage();
+#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 */
-#ifdef BSD_A_OUT
- case 'r': /* relocatable output */
-#endif
case 's': /* strip symbols */
case 't': /* trace modules linked */
case 'z': /* unmapped zero page */
+ case 'N': /* Native format a.out */
+ case 'd': /* Make a headerless outfile */
if (arg[2] == 0)
flag[(int) arg[1]] = TRUE;
else if (arg[2] == '-' && arg[3] == 0)
@@ -112,18 +126,11 @@ char **argv;
if (arg[1] == '0') /* flag 0 is negative logic flag 3 */
flag['3'] = !flag['0'];
break;
- case 'd': /* Make DOS com file */
- flag['3'] = FALSE;
- flag['z'] = FALSE;
- flag['0'] = TRUE;
- flag['s'] = TRUE;
- flag['d'] = TRUE;
- text_base_address = 0x100;
- break;
case 'C': /* startfile name */
tfn = buildname(crtprefix, arg + 2, crtsuffix);
if ((infilename = expandlib(tfn)) == NUL_PTR)
- fatalerror(tfn); /* XXX - need to describe failure */
+ infilename = tfn;
+ /*fatalerror(tfn); * XXX - need to describe failure */
readsyms(infilename, flag['t']);
break;
case 'L': /* library path */
@@ -134,21 +141,37 @@ char **argv;
break;
case 'O': /* library file name */
if ((infilename = expandlib(arg + 2)) == NUL_PTR)
- fatalerror(arg); /* XXX */
+ infilename = arg+2;
+ /* fatalerror(arg); * XXX */
readsyms(infilename, flag['t']);
break;
case 'T': /* text base address */
- if (arg[2] != 0 || ++argn >= argc)
+ if (arg[2] == 0 && ++argn >= argc)
usage();
errno = 0;
- text_base_address = strtoul(argv[argn], (char **) NUL_PTR, 16);
+ 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 'l': /* library name */
tfn = buildname(libprefix, arg + 2, libsuffix);
if ((infilename = expandlib(tfn)) == NUL_PTR)
- fatalerror(tfn); /* XXX */
+ infilename = tfn;
+ /* fatalerror(tfn); * XXX */
readsyms(infilename, flag['t']);
break;
case 'o': /* output file name */
@@ -160,11 +183,21 @@ char **argv;
usage();
}
}
- doscomfile = flag['d'];
+
+ /* Headerless executables can't use symbols. */
+ headerless = flag['d'];
+ if( headerless ) flag['s'] = 1;
+
linksyms(flag['r']);
if (outfilename == NUL_PTR)
outfilename = "a.out";
- writebin(outfilename, flag['i'], flag['3'], flag['s'],
+#ifndef MSDOS
+ if( flag['N'] )
+ writebin(outfilename, flag['i'], flag['3'], flag['s'],
+ flag['z'] & flag['3']);
+ else
+#endif
+ write_elks(outfilename, flag['i'], flag['3'], flag['s'],
flag['z'] & flag['3']);
if (flag['m'])
dumpmods();
diff --git a/ld/linksyms.c b/ld/linksyms.c
new file mode 100644
index 0000000..b5304a3
--- /dev/null
+++ b/ld/linksyms.c
@@ -0,0 +1,84 @@
+
+/* linksyms.c - write binary file for linker */
+
+/* Copyright (C) 1994 Bruce Evans */
+
+#include "syshead.h"
+#include "const.h"
+#include "obj.h"
+#include "type.h"
+#undef EXTERN
+#include "globvar.h"
+
+FORWARD void linkrefs P((struct modstruct *modptr));
+PUBLIC bool_t reloc_output = 0;
+
+/* link all symbols connected to entry symbols */
+
+PUBLIC void linksyms(argreloc_output)
+bool_pt argreloc_output;
+{
+ char needlink;
+ struct entrylist *elptr;
+ struct modstruct *modptr;
+ struct symstruct *symptr;
+
+#ifdef REL_OUTPUT
+ reloc_output = argreloc_output;
+ if (argreloc_output)
+ {
+ if (modfirst->modnext != NUL_PTR)
+ fatalerror("relocatable output only works for one input file");
+ for (modptr = modfirst; modptr != NUL_PTR; modptr = modptr->modnext)
+ modptr->loadflag = TRUE;
+ return;
+ }
+#endif
+ if ((symptr = findsym("_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/ld/readobj.c b/ld/readobj.c
index eb5e0e3..da83b0a 100644
--- a/ld/readobj.c
+++ b/ld/readobj.c
@@ -127,7 +127,7 @@ PRIVATE unsigned readfileheader()
readin((char *) &fileheader, sizeof fileheader);
readin(&filechecksum, sizeof filechecksum);
if (filechecksum != checksum((char *) &fileheader, sizeof fileheader))
- input1error(" is not an object file");
+ input1error(" is not an object file (checksum failed)");
return c2u2(fileheader.count);
}
diff --git a/ld/syshead.h b/ld/syshead.h
index 33f1123..f5f32ea 100644
--- a/ld/syshead.h
+++ b/ld/syshead.h
@@ -18,8 +18,8 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
+#include <io.h>
-#define A_OUT_INCL "a_out.h"
#undef min
#define R_OK 0
#define mode_t unsigned short
@@ -27,10 +27,6 @@
#define STDOUT_FILENO 0
#endif
-#ifndef A_OUT_INCL
-#define A_OUT_INCL "a.out.h"
-#endif
-
#ifndef O_BINARY
#define O_BINARY 0
#endif
@@ -80,42 +76,3 @@ mode_t umask P((int oldmask));
int write P((int fd, const void *buf, unsigned nbytes));
#endif
-#ifndef A_OUT_INCL
-# ifdef BSD_A_OUT
-# ifdef STANDARD_GNU_A_OUT
-# define A_OUT_INCL <a.out.h>
-# else
-# define A_OUT_INCL "bsd-a.out.h"
-# endif
-
-# ifdef MSDOS
-# define A_OUT_INCL "a_out.h"
-# else
-# define A_OUT_INCL "a.out.h" /* maybe local copy of <a.out.h> for X-link */
-# endif
-# endif /* BSD_A_OUT */
-#endif
-
-# 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
-# define C_EXT N_EXT
-# 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 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 */
-
diff --git a/ld/type.h b/ld/type.h
index a419871..12758e3 100644
--- a/ld/type.h
+++ b/ld/type.h
@@ -17,8 +17,6 @@ typedef int fastin_t;
#endif
typedef int fastin_pt;
-#ifdef OBJ_H /* obj.h is included */
-
typedef unsigned flags_t; /* unsigned makes shifts logical */
#ifdef LONG_OFFSETS
@@ -27,6 +25,8 @@ typedef unsigned long bin_off_t;
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 */
@@ -93,10 +93,8 @@ void flusherr P((void));
void openin P((char *filename));
void openout P((char *filename));
void putstr P((char *message));
-#ifdef OBJ_H
void put08x P((bin_off_t num));
void put08lx P((bin_off_t num));
-#endif
void putbstr P((unsigned width, char *str));
void putbyte P((int ch));
int readchar P((void));
@@ -117,9 +115,7 @@ void prematureeof P((void));
void redefined P((char *name, char *message, char *archentry,
char *deffilename, char *defarchentry));
void reserved P((char *name));
-#ifdef OBJ_H
void size_error P((int seg, bin_off_t count, bin_off_t size));
-#endif
void undefined P((char *name));
void usage P((void));
void use_error P((char *message));
@@ -132,10 +128,10 @@ void objinit P((void));
void readsyms P((char *filename, bool_pt trace));
#ifdef OBJ_H
void entrysym P((struct symstruct *symptr));
-bin_off_t readconvsize P((unsigned countindex));
-bin_off_t readsize P((unsigned count));
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));
@@ -162,4 +158,10 @@ 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));
+
+/* write_elks.c */
+void write_elks P((char *outfilename, bool_pt argsepid, bool_pt argbits32,
+ bool_pt argstripflag, bool_pt arguzp));
+
+/* linksym.c */
void linksyms P((bool_pt argreloc_output));
diff --git a/ld/writebin.c b/ld/writebin.c
index fd3a3b9..de4b01c 100644
--- a/ld/writebin.c
+++ b/ld/writebin.c
@@ -1,34 +1,45 @@
-extern long text_base_address;
-#define btextoffset text_base_address
-static long bdataoffset;
-#define page_size() 4096
/* writebin.c - write binary file for linker */
/* Copyright (C) 1994 Bruce Evans */
#include "syshead.h"
-#include A_OUT_INCL
+#define A_OUT_INCL <a.out.h>
+#include "bindef.h"
#include "const.h"
#include "obj.h"
#include "type.h"
-#undef EXTERN
#include "globvar.h"
+#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 FILEHEADERLENGTH 32
+# define HEADERLEN (sizeof(struct exec))
# else
-# define FILEHEADERLENGTH (doscomfile?0:48)
+# define HEADERLEN (48)
# endif
# else
-# define FILEHEADERLENGTH (doscomfile?0:A_MINHDR)
+# 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
+# define FILEHEADERLENGTH (headerless?0:HEADERLEN)
#endif
#define DPSEG 2
@@ -64,13 +75,13 @@ 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 BSD_A_OUT
+#ifdef REL_OUTPUT
PRIVATE unsigned ndreloc; /* number of data relocations */
#endif
PRIVATE unsigned nsym; /* number of symbols written */
-#ifdef BSD_A_OUT
+#ifdef REL_OUTPUT
PRIVATE unsigned ntreloc; /* number of text relocations */
-PRIVATE bool_t reloc_output; /* nonzero to leave reloc info in output */
+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) */
@@ -91,7 +102,6 @@ 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 linkrefs 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));
@@ -104,64 +114,6 @@ FORWARD void writeheader P((void));
#endif
FORWARD void writenulls P((bin_off_t count));
-extern int doscomfile;
-
-/* link all symbols connected to entry symbols */
-
-PUBLIC void linksyms(argreloc_output)
-bool_pt argreloc_output;
-{
- char needlink;
- struct entrylist *elptr;
- struct modstruct *modptr;
- struct symstruct *symptr;
-
-#ifdef BSD_A_OUT
- reloc_output = argreloc_output;
- if (argreloc_output)
- {
- if (modfirst->modnext != NUL_PTR)
- fatalerror("relocatable output only works for one input file");
- for (modptr = modfirst; modptr != NUL_PTR; modptr = modptr->modnext)
- modptr->loadflag = TRUE;
- return;
- }
-#endif
- if ((symptr = findsym("_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);
-}
-
/* write binary file */
PUBLIC void writebin(outfilename, argsepid, argbits32, argstripflag, arguzp)
@@ -186,7 +138,7 @@ bool_pt arguzp;
sepid = argsepid;
bits32 = argbits32;
stripflag = argstripflag;
-#ifdef BSD_A_OUT
+#ifdef REL_OUTPUT
uzp = arguzp && !reloc_output;
#else
uzp = arguzp;
@@ -228,7 +180,7 @@ bool_pt arguzp;
symres("__end");
curseg = 0; /* text seg, s.b. variable */
symres("__etext");
- symres("__segoff");
+ if( headerless ) symres("__segoff");
/* calculate segment and common sizes (sum over loaded modules) */
/* use zero init of segsz[] */
@@ -252,14 +204,14 @@ bool_pt arguzp;
}
else if (symptr->value == 0)
{
-#ifdef BSD_A_OUT
+#ifdef REL_OUTPUT
if (!reloc_output)
#endif
undefined(symptr->name);
}
else
{
-#ifdef BSD_A_OUT
+#ifdef REL_OUTPUT
#if 0
if (!reloc_output)
#else
@@ -343,7 +295,7 @@ bool_pt arguzp;
{
if (symptr->flags & (C_MASK | SA_MASK))
{
-#ifdef BSD_A_OUT
+#ifdef REL_OUTPUT
#if 0
if (!reloc_output)
#else
@@ -353,7 +305,7 @@ bool_pt arguzp;
symptr->value += combase[symptr->flags & SEGM_MASK];
}
else
-#ifdef BSD_A_OUT
+#ifdef REL_OUTPUT
if (!reloc_output || !(symptr->flags & I_MASK))
#endif
symptr->value += segbase[symptr->flags & SEGM_MASK];
@@ -382,7 +334,7 @@ bool_pt arguzp;
setsym("__etext", etextoffset);
setsym("__edata", edataoffset);
setsym("__end", endoffset = combase[NSEG - 1] + comsz[NSEG - 1]);
- setsym("__segoff", (bin_off_t)(segadj[1]-segadj[0])/0x10);
+ if( headerless ) setsym("__segoff", (bin_off_t)(segadj[1]-segadj[0])/0x10);
if( !bits32 )
{
if( etextoffset > 65535L )
@@ -392,7 +344,7 @@ bool_pt arguzp;
}
openout(outfilename);
-#ifdef BSD_A_OUT
+#ifdef REL_OUTPUT
if (reloc_output)
seektrel(FILEHEADERLENGTH
+ (unsigned long) (etextpadoff - btextoffset)
@@ -421,7 +373,7 @@ bool_pt arguzp;
seekout(FILEHEADERLENGTH
+ (unsigned long) (etextpadoff - btextoffset)
+ (unsigned long) (edataoffset - bdataoffset)
-#ifdef BSD_A_OUT
+#ifdef REL_OUTPUT
+ ((unsigned long) ndreloc + ntreloc) * RELOC_INFO_SIZE
#endif
);
@@ -443,9 +395,21 @@ bool_pt arguzp;
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)
@@ -455,7 +419,7 @@ bool_pt arguzp;
else
extsym.n_was_sclass = C_STAT;
if (!(flags & I_MASK) ||
-#ifdef BSD_A_OUT
+#ifdef REL_OUTPUT
!reloc_output &&
#endif
flags & C_MASK)
@@ -475,8 +439,14 @@ bool_pt arguzp;
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
@@ -491,14 +461,26 @@ bool_pt arguzp;
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 BSD_A_OUT
+#ifdef REL_OUTPUT
seekout((unsigned long) offsetof(struct exec, a_trsize));
u4cn(buf4, (u4_t) ntreloc * RELOC_INFO_SIZE,
memsizeof(struct exec, a_trsize));
@@ -511,7 +493,7 @@ bool_pt arguzp;
}
#endif /* MINIX */
closeout();
-#ifdef BSD_A_OUT
+#ifdef REL_OUTPUT
if (!reloc_output)
#endif
executable();
@@ -649,7 +631,7 @@ struct modstruct *modptr;
offset -= (spos + relocsize);
offtocn(buf, segbase[modify & SEGM_MASK] + offset, relocsize);
writeout(buf, relocsize);
-#ifdef BSD_A_OUT
+#ifdef REL_OUTPUT
if (reloc_output)
{
u4_t bitfield;
@@ -682,7 +664,7 @@ struct modstruct *modptr;
else
writedrel(buf, 4);
}
-#endif /* BSD_A_OUT */
+#endif /* REL_OUTPUT */
spos += relocsize;
break;
case CM_SYMBOL_RELOC:
@@ -691,13 +673,13 @@ struct modstruct *modptr;
offset = readconvsize((unsigned) modify & OF_MASK);
if (modify & R_MASK)
offset -= (spos + relocsize);
-#ifdef BSD_A_OUT
+#ifdef REL_OUTPUT
if (!reloc_output || !(symptr->flags & I_MASK))
#endif
offset += symptr->value;
offtocn(buf, offset, relocsize);
writeout(buf, relocsize);
-#ifdef BSD_A_OUT
+#ifdef REL_OUTPUT
if (reloc_output)
{
u4_t bitfield;
@@ -734,25 +716,12 @@ struct modstruct *modptr;
else
writedrel(buf, 4);
}
-#endif /* BSD_A_OUT */
+#endif /* REL_OUTPUT */
spos += relocsize;
}
}
}
-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);
-}
-
PRIVATE void padmod(modptr)
struct modstruct *modptr;
{
@@ -788,7 +757,7 @@ bin_off_t value;
{
struct symstruct *symptr;
-#ifdef BSD_A_OUT
+#ifdef REL_OUTPUT
if (!reloc_output)
#endif
if ((symptr = findsym(name)) != NUL_PTR)
@@ -806,7 +775,7 @@ register char *name;
symptr->flags &= ~SEGM_MASK | curseg;
if (symptr->flags != (I_MASK | curseg) || symptr->value != 0)
reserved(name);
-#ifdef BSD_A_OUT
+#ifdef REL_OUTPUT
if (!reloc_output)
#endif
symptr->flags = E_MASK | curseg; /* show defined, not common */
@@ -900,7 +869,7 @@ PRIVATE void writeheader()
header.a_magic[0] = A_MAGIC0;
header.a_magic[1] = A_MAGIC1;
#endif
-#ifdef BSD_A_OUT
+#ifdef REL_OUTPUT
if (!reloc_output)
#endif
{
@@ -938,7 +907,7 @@ PRIVATE void writeheader()
sizeof header.a_data);
offtocn((char *) &header.a_bss, endoffset - edataoffset,
sizeof header.a_bss);
-#ifdef BSD_A_OUT
+#ifdef REL_OUTPUT
if (!reloc_output)
#endif
{
diff --git a/ld/writex86.c b/ld/writex86.c
new file mode 100644
index 0000000..25cc0d6
--- /dev/null
+++ b/ld/writex86.c
@@ -0,0 +1,547 @@
+/* writex86.c - write binary file for linker */
+
+/* Copyright (C) 1994 Bruce Evans */
+
+#include "syshead.h"
+#include "x86_aout.h"
+#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)
+
+# define FILEHEADERLENGTH (headerless?0:A_MINHDR)
+ /* 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 */
+
+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));
+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)
+char *outfilename;
+bool_pt argsepid;
+bool_pt argbits32;
+bool_pt argstripflag;
+bool_pt arguzp;
+{
+ 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 )
+ fatalerror("Output binformat not configured relocatable, use -N");
+
+ sepid = argsepid;
+ bits32 = argbits32;
+ stripflag = argstripflag;
+ uzp = arguzp;
+ 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 */
+ }
+ curseg = 3;
+ symres("__edata");
+ symres("__end");
+ curseg = 0; /* text seg, s.b. variable */
+ symres("__etext");
+ if( headerless ) 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 */
+ /* temp use fixed order 0D 0C 1D 1C 2D 2C ... */
+ /* assume seg 0 is text and rest are data */
+ 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];
+ for (seg = 2; seg < NSEG; ++seg)
+ {
+ segpos[seg] = segbase[seg] = combase[seg - 1] + comsz[seg - 1];
+ 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;
+ }
+ 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)
+ {
+ if (segsz[seg] != 0)
+ /* only count data of nonzero length */
+ 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 */
+ }
+ setsym("__etext", etextoffset);
+ setsym("__edata", edataoffset);
+ setsym("__end", endoffset = combase[NSEG - 1] + comsz[NSEG - 1]);
+ if( headerless ) setsym("__segoff", (bin_off_t)(segadj[1]-segadj[0])/0x10);
+ if( !bits32 )
+ {
+ if( etextoffset > 65535L )
+ fatalerror("text segment too large for 16bit");
+ if( endoffset > 65535L )
+ fatalerror("data segment too large for 16bit");
+ }
+
+ openout(outfilename);
+ 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)
+ {
+#ifdef __ELF__
+ 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, "__", 2);
+ strncpy((char *) extsym.n_name+2, symptr->name,
+ sizeof(extsym.n_name)-2);
+ }
+#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))
+ {
+ case 0:
+ extsym.n_sclass |= N_TEXT;
+ case A_MASK:
+ break;
+ default:
+ if (flags & (C_MASK | SA_MASK))
+ extsym.n_sclass |= N_BSS;
+ else
+ extsym.n_sclass |= N_DATA;
+ break;
+ }
+ writeout((char *) &extsym, sizeof extsym);
+ ++nsym;
+ }
+ }
+ 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)
+ 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)
+ 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));
+}
+
+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)
+ (endoffset < 0x00010000L ? 0x00010000L : endoffset + 0x0008000L),
+ sizeof header.a_total);
+ if( FILEHEADERLENGTH )
+ writeout((char *) &header, FILEHEADERLENGTH);
+}
+
+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/ld/a.out.h b/ld/x86_aout.h
index f6a7b94..f6a7b94 100644
--- a/ld/a.out.h
+++ b/ld/x86_aout.h