diff options
author | Robert de Bath <rdebath@poboxes.com> | 1996-11-03 22:33:35 +0100 |
---|---|---|
committer | Lubomir Rintel <lkundrak@v3.sk> | 2013-10-23 23:33:35 +0200 |
commit | c218c617b5be443b7968308506969ad2b726d73c (patch) | |
tree | 0051f396af56133d24fcf2ab757fabc78c1a09bf /ld | |
parent | 0936b9aeab611665645a4e6bafaded7ca76dd189 (diff) | |
parent | 0d2fbe9b1bd284ce2cad55be17e8f2c896031a25 (diff) | |
download | dev86-c218c617b5be443b7968308506969ad2b726d73c.tar.gz |
Import Dev86src-0.0.8.tar.gzv0.0.8
Diffstat (limited to 'ld')
-rw-r--r-- | ld/Makefile | 21 | ||||
-rw-r--r-- | ld/bindef.h | 68 | ||||
-rw-r--r-- | ld/config.h | 7 | ||||
-rw-r--r-- | ld/globvar.h | 12 | ||||
-rw-r--r-- | ld/io.c | 39 | ||||
-rw-r--r-- | ld/ld.c | 75 | ||||
-rw-r--r-- | ld/linksyms.c | 84 | ||||
-rw-r--r-- | ld/readobj.c | 2 | ||||
-rw-r--r-- | ld/syshead.h | 45 | ||||
-rw-r--r-- | ld/type.h | 18 | ||||
-rw-r--r-- | ld/writebin.c | 179 | ||||
-rw-r--r-- | ld/writex86.c | 547 | ||||
-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 */ @@ -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 } @@ -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 */ - @@ -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 |