From e63c244cb22bf48ca1d2695784a072269d19ea96 Mon Sep 17 00:00:00 2001 From: Robert de Bath Date: Fri, 9 May 1997 19:36:29 +0200 Subject: Import Dev86src-0.12.0.tar.gz --- ld/Makefile | 19 +- ld/align.h | 13 +- ld/bindef.h | 6 +- ld/bugs | 14 -- ld/byteord.h | 6 +- ld/ld.c | 10 +- ld/rel_aout.h | 383 ++++++++++++++++++++++++++++++++++++ ld/type.h | 3 + ld/typeconv.c | 579 +++++++++++------------------------------------------- ld/typeconv.c.old | 536 ++++++++++++++++++++++++++++++++++++++++++++++++++ ld/writebin.c | 34 ++-- ld/writerel.c | 22 +++ ld/x86_aout.h | 44 +++-- 13 files changed, 1149 insertions(+), 520 deletions(-) delete mode 100644 ld/bugs create mode 100644 ld/rel_aout.h create mode 100644 ld/typeconv.c.old create mode 100644 ld/writerel.c (limited to 'ld') diff --git a/ld/Makefile b/ld/Makefile index da7b268..2e30d96 100644 --- a/ld/Makefile +++ b/ld/Makefile @@ -4,11 +4,19 @@ CFLAGS =-O LDFLAGS =-s # May need some of these if the auto-sense fails. -# -DV7_A_OUT -DBSD_A_OUT -DSTANDARD_GNU_A_OUT -DEFS =-DREL_OUTPUT +# -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. +# -DNO_AOUT # a.out.h is like nothing known! +# +DEFS =-DREL_OUTPUT -DBUGCOMPAT + +# 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 \ - writex86.o writebin.o + writex86.o writebin.o writerel.o all: ld86 @@ -29,5 +37,10 @@ ar.h: ln -s ../libc/include/ar.h . || \ ln ../libc/include/ar.h . +writebin.o: writebin.c + $(CC) $(CFLAGS) $(DEFS) $(NATIVE) -c writebin.c + +writerel.o: writebin.c + .c.o: $(CC) $(CFLAGS) $(DEFS) -c $< -o $@ diff --git a/ld/align.h b/ld/align.h index 02bbe43..52b1e89 100644 --- a/ld/align.h +++ b/ld/align.h @@ -5,8 +5,14 @@ #ifndef S_ALIGNMENT # define align(x) #else -# define align(x) ((x)=(void*) \ - ((char *)(x) + ((S_ALIGNMENT-(int)(x)) & (S_ALIGNMENT-1)))) + +#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 @@ -14,7 +20,4 @@ -/* * assumes sizeof(int) == sizeof(char *) * -# define align(x) ((x) = (void *)(((int) (x) + (S_ALIGNMENT-1)) & ~(S_ALIGNMENT-1))) -*/ diff --git a/ld/bindef.h b/ld/bindef.h index 2a2d8d8..dbacfcd 100644 --- a/ld/bindef.h +++ b/ld/bindef.h @@ -66,8 +66,12 @@ # endif /* BSD_A_OUT */ /* And finally make sure it worked */ -#ifdef C_EXT +#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/ld/bugs b/ld/bugs deleted file mode 100644 index 9444281..0000000 --- a/ld/bugs +++ /dev/null @@ -1,14 +0,0 @@ -1. Should cause error when an address which requires > 16 bits is referenced - using 16 bits. - -TODO: - integrate byteord.h with compiler as well as assembler - -TODO: - integrate align.h with compiler and assembler - use alignment for *86 like compiler - use more portable macro - ((x) + (-(int) (x) & MASK)) when it is either necessary or - faster - -TODO: - do malloc stuff better, as in compiler diff --git a/ld/byteord.h b/ld/byteord.h index 57d17b9..c854979 100644 --- a/ld/byteord.h +++ b/ld/byteord.h @@ -5,16 +5,16 @@ /* These are for the targets of everything and for linker source too. */ #ifdef I8086 -# define BIG_ENDIAN 0 +# define INT_BIG_ENDIAN 0 # define LONG_BIG_ENDIAN 0 /* except longs are back to front for Xenix */ #endif #ifdef I80386 -# define BIG_ENDIAN 0 +# define INT_BIG_ENDIAN 0 # define LONG_BIG_ENDIAN 0 #endif #ifdef MC6809 -# define BIG_ENDIAN 1 /* byte order in words is high-low */ +# 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/ld/ld.c b/ld/ld.c index 1de55ce..0a307e9 100644 --- a/ld/ld.c +++ b/ld/ld.c @@ -83,7 +83,7 @@ char **argv; ioinit(argv[0]); objinit(); syminit(); - typeconv_init(BIG_ENDIAN, LONG_BIG_ENDIAN); + typeconv_init(INT_BIG_ENDIAN, LONG_BIG_ENDIAN); #ifndef MC6809 flag['3'] = sizeof(char *) >= 4; #endif @@ -205,6 +205,7 @@ char **argv; #ifdef REL_OUTPUT #ifndef MSDOS +#ifndef BUGCOMPAT if( flag['r'] && !flag['N'] ) { /* Ok, try for an alternate linker */ @@ -217,6 +218,7 @@ char **argv; } #endif #endif +#endif #ifdef MSDOS /* MSDOS Native is special, we make a COM file */ @@ -240,6 +242,12 @@ char **argv; writebin(outfilename, flag['i'], flag['3'], flag['s'], flag['z'] & flag['3']); else +#endif +#ifdef BUGCOMPAT + if( flag['r'] ) + write_rel(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']); diff --git a/ld/rel_aout.h b/ld/rel_aout.h new file mode 100644 index 0000000..9316a72 --- /dev/null +++ b/ld/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/ld/type.h b/ld/type.h index 12758e3..217d6a9 100644 --- a/ld/type.h +++ b/ld/type.h @@ -159,6 +159,9 @@ bool_pt typeconv_init P((bool_pt big_endian, bool_pt long_big_endian)); void writebin P((char *outfilename, bool_pt argsepid, bool_pt argbits32, bool_pt argstripflag, bool_pt arguzp)); +void write_rel 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)); diff --git a/ld/typeconv.c b/ld/typeconv.c index 82dafdd..6cc4a20 100644 --- a/ld/typeconv.c +++ b/ld/typeconv.c @@ -1,536 +1,187 @@ -/* typeconv.c - convert between char arrays and unsigneds */ - -/* Copyright (C) 1994 Bruce Evans */ /* - c2u2(): 2 byte array to 2 byte unsigned - c4u4(): 4 byte array to 4 byte unsigned - cnu2(): n byte array to 2 byte unsigned - cnu4(): n byte array to 4 byte unsigned - u2c2(): 2 byte unsigned to 2 byte array - u2cn(): 2 byte unsigned to n byte array - u4c4(): 4 byte unsigned to 4 byte array - u4cn(): 4 byte unsigned to n byte array - typeconv_init: (re)initialise for given byte order. - Default is no swapping, but the initialisation should be done - anyway to provide some validity checks (returns FALSE if error). - - Not provided: - c2u4(), c4u2(), u2c4(), u4c2(). - Each of these is best done by truncating or extending a return value - or argument to the appropiate fixed-count function. - c4u2() has too many cases to do in-line conveniently, and the others - are hardly more efficient when done in-line. - - 4 byte orderings for both char arrays and unsigneds are supported: - 0123 - little-endian - 3210 - big-endian - 2301 - little-endian with long words big-endian (pdp11) - 1032 - big-endian with long words little_endian (who knows?) - - The unsigned's byte order is that of the machine on which these - routines are running. - It is determined at run time initialisation since the compiler/ - preprocessor is too dumb to tell us at compile time. -*/ + * 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" -FORWARD u2_pt c2u2_00 P((char *buf)); -FORWARD u4_pt c4u4_00 P((char *buf)); -FORWARD u2_pt c2u2_ss P((char *buf)); -FORWARD u4_pt c4u4_ss P((char *buf)); -FORWARD u4_pt c4u4_s0 P((char *buf)); -FORWARD u4_pt c4u4_0s P((char *buf)); -FORWARD void u2c2_00 P((char *buf, u2_pt offset)); -FORWARD void u4c4_00 P((char *buf, u4_t offset)); -FORWARD void u2c2_ss P((char *buf, u2_pt offset)); -FORWARD void u4c4_ss P((char *buf, u4_t offset)); -FORWARD void u4c4_s0 P((char *buf, u4_t offset)); -FORWARD void u4c4_0s P((char *buf, u4_t offset)); - -PRIVATE u2_pt (*pc2u2) P((char *buf)) = c2u2_00; -PRIVATE u4_pt (*pc4u4) P((char *buf)) = c4u4_00; -PRIVATE void (*pu2c2) P((char *buf, u2_pt offset)) = u2c2_00; -PRIVATE void (*pu4c4) P((char *buf, u4_t offset)) = u4c4_00; - -/* === char arrays to unsigneds === */ - -/* no bytes swapped, longwinded to avoid alignment problems */ - -PRIVATE u2_pt c2u2_00(buf) -register char *buf; -{ - u2_t offset; - - ((char *) &offset)[0] = buf[0]; - ((char *) &offset)[1] = buf[1]; - return offset; -} - -PRIVATE u4_pt c4u4_00(buf) -register char *buf; -{ - u4_t offset; +void xxerr P((char *)); +void xxerr(x) char * x; { write(2, x, strlen(x)); } - ((char *) &offset)[0] = buf[0]; - ((char *) &offset)[1] = buf[1]; - ((char *) &offset)[2] = buf[2]; - ((char *) &offset)[3] = buf[3]; - return offset; -} - -/* straight swapping for little-endian to big-endian and vice versa */ - -PRIVATE u2_pt c2u2_ss(buf) -register char *buf; -{ - u2_t offset; - - ((char *) &offset)[0] = buf[1]; - ((char *) &offset)[1] = buf[0]; - return offset; -} - -PRIVATE u4_pt c4u4_ss(buf) -register char *buf; -{ - u4_t offset; - - ((char *) &offset)[0] = buf[3]; - ((char *) &offset)[1] = buf[2]; - ((char *) &offset)[2] = buf[1]; - ((char *) &offset)[3] = buf[0]; - return offset; -} +static int no_swap = 1; -/* wierd swapping for different-endian u2's, same-endian u4's */ +static long_off[4] = {0,1,2,3}; +static int_off[2] = {0,1}; -PRIVATE u4_pt c4u4_s0(buf) -register char *buf; +PUBLIC bool_pt typeconv_init(big_endian, long_big_endian) +bool_pt big_endian; +bool_pt long_big_endian; { - u4_t offset; + int i; + no_swap = (!big_endian && !long_big_endian); - ((char *) &offset)[0] = buf[1]; - ((char *) &offset)[1] = buf[0]; - ((char *) &offset)[2] = buf[3]; - ((char *) &offset)[3] = buf[2]; - return offset; -} - -/* very wierd swapping for same-endian u2's, different-endian u4's */ + for(i=0; i<4; i++) long_off[i] = i; + for(i=0; i<2; i++) int_off[i] = i; -PRIVATE u4_pt c4u4_0s(buf) -register char *buf; -{ - u4_t offset; + 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; - ((char *) &offset)[0] = buf[2]; - ((char *) &offset)[1] = buf[3]; - ((char *) &offset)[2] = buf[0]; - ((char *) &offset)[3] = buf[1]; - return offset; + i = int_off[0]; int_off[0] = int_off[1]; int_off[1] = i; + } + return 1; } -/* === entry points === */ - -PUBLIC u2_pt c2u2(buf) +PUBLIC void u2c2(buf, offset) char *buf; +u2_pt offset; { - return (*pc2u2) (buf); +#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 u4_t c4u4(buf) +PUBLIC void u4c4(buf, offset) char *buf; +u4_t offset; { - return (*pc4u4) (buf); + 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 u2_pt cnu2(buf, count) +PUBLIC void u4cn(buf, offset, count) char *buf; +u4_t offset; unsigned count; { - switch (count) + switch(count) { case 1: - return buf[0] & 0xFF; + buf[0] = (char) offset; + return; case 2: - return (*pc2u2) (buf); + u2c2(buf, (u2_pt) offset); + return; case 4: - return (u2_pt) (*pc4u4) (buf); + u4c4(buf, (u4_t) offset); + return; default: - return 0; + xxerr("WARNING: typeconv.c(u4cn) illegal count\n"); + return; } } -PUBLIC u4_t cnu4(buf, count) +PUBLIC void u2cn(buf, offset, count) char *buf; +u2_pt offset; unsigned count; { - switch (count) + switch(count) { case 1: - return buf[0] & 0xFF; + buf[0] = (char) offset; + return; case 2: - return (*pc2u2) (buf); + u2c2(buf, (u2_pt) offset); + return; case 4: - return (*pc4u4) (buf); + u4c4(buf, (u4_t) offset); + return; default: - return 0; + xxerr("WARNING: typeconv.c(u2cn) illegal count\n"); + return; } } -/* === unsigneds to char arrays === */ - -/* no bytes swapped, longwinded to avoid alignment problems */ - -PRIVATE void u2c2_00(buf, offset) -register char *buf; -u2_pt offset; -{ - - buf[0] = ((char *) &offset)[0]; - buf[1] = ((char *) &offset)[1]; -} - -PRIVATE void u4c4_00(buf, offset) -register char *buf; -u4_t offset; -{ - buf[0] = ((char *) &offset)[0]; - buf[1] = ((char *) &offset)[1]; - buf[2] = ((char *) &offset)[2]; - buf[3] = ((char *) &offset)[3]; -} - -/* straight swapping for little-endian to big-endian and vice versa */ - -PRIVATE void u2c2_ss(buf, offset) -register char *buf; -u2_pt offset; -{ - u2_t offset2; - - offset2 = offset; - buf[0] = ((char *) &offset2)[1]; - buf[1] = ((char *) &offset2)[0]; -} - -PRIVATE void u4c4_ss(buf, offset) -register char *buf; -u4_t offset; -{ - buf[0] = ((char *) &offset)[3]; - buf[1] = ((char *) &offset)[2]; - buf[2] = ((char *) &offset)[1]; - buf[3] = ((char *) &offset)[0]; -} - -/* wierd swapping for different-endian u2's, same-endian u4's */ - -PRIVATE void u4c4_s0(buf, offset) -register char *buf; -u4_t offset; -{ - buf[0] = ((char *) &offset)[1]; - buf[1] = ((char *) &offset)[0]; - buf[2] = ((char *) &offset)[3]; - buf[3] = ((char *) &offset)[2]; -} - -/* very wierd swapping for same-endian u2's, different-endian u4's */ - -PRIVATE void u4c4_0s(buf, offset) -register char *buf; -u4_t offset; +PUBLIC u2_pt c2u2(buf) +char *buf; { - buf[0] = ((char *) &offset)[2]; - buf[1] = ((char *) &offset)[3]; - buf[2] = ((char *) &offset)[0]; - buf[3] = ((char *) &offset)[1]; -} - -/* === entry points === */ + u2_pt res; +#ifdef __AS386_16__ + if( no_swap ) return *((u2_pt *)buf); /* UNALIGNED ACCESS! */ +#endif -PUBLIC void u2c2(buf, offset) -register char *buf; -u2_pt offset; -{ - (*pu2c2) (buf, offset); + res = ((unsigned char *)buf) [int_off[0]] + + ((((unsigned char *)buf) [int_off[1]]) << 8); + return res; } -PUBLIC void u4c4(buf, offset) -register char *buf; -u4_t offset; +PUBLIC u4_t c4u4(buf) +char *buf; { - (*pu4c4) (buf, offset); + 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 void u2cn(buf, offset, count) -register char *buf; -u2_pt offset; +PUBLIC u4_t cnu4(buf, count) +char *buf; unsigned count; { switch (count) { case 1: - buf[0] = (char) offset; - return; + return buf[0] & 0xFF; case 2: - (*pu2c2) (buf, offset); - return; + return c2u2(buf); case 4: - (*pu4c4) (buf, (u4_t) offset); - return; + return c4u4(buf); + default: + xxerr("WARNING: typeconv.c(cnu4) illegal count\n"); + return 0; } } -PUBLIC void u4cn(buf, offset, count) -register char *buf; -u4_t offset; +PUBLIC u2_pt cnu2(buf, count) +char *buf; unsigned count; { switch (count) { case 1: - buf[0] = (char) offset; - return; + return buf[0] & 0xFF; case 2: - (*pu2c2) (buf, (u2_pt) (u2_t) offset); - return; + return c2u2(buf); case 4: - (*pu4c4) (buf, offset); - return; - } -} - -/* initialise type conversion, return FALSE if it cannot be handled */ - -PUBLIC bool_pt typeconv_init(big_endian, long_big_endian) -bool_pt big_endian; -bool_pt long_big_endian; -{ - u2_pt conv2; - u4_pt conv4; - char *conv2ptr; - char *conv4ptr; - - if (sizeof(u2_t) != 2 || sizeof(u4_t) != 4) - /* dumb preprocessor's don't accept sizeof in #if expressions */ - return FALSE; - - if (big_endian) - { - conv2ptr = (conv4ptr = "\1\2\3\4") + 2; - if (!long_big_endian) - conv4ptr = "\3\4\1\2"; - } - else - { - conv2ptr = conv4ptr = "\4\3\2\1"; - if (long_big_endian) - conv4ptr = "\2\1\4\3"; - } - conv2 = c2u2_00(conv2ptr); - conv4 = c4u4_00(conv4ptr); - if (conv2 == 0x0304) - { - pc2u2 = c2u2_00; - pc4u4 = c4u4_00; - pu2c2 = u2c2_00; - pu4c4 = u4c4_00; - if (conv4 == 0x03040102L) - { - pc4u4 = c4u4_0s; - pu4c4 = u4c4_0s; - } - else if (conv4 != 0x01020304L) - return FALSE; - } - else if (conv2 == 0x0403) - { - pc2u2 = c2u2_ss; - pc4u4 = c4u4_ss; - pu2c2 = u2c2_ss; - pu4c4 = u4c4_ss; - if (conv4 == 0x02010403L) - { - pc4u4 = c4u4_s0; - pu4c4 = u4c4_s0; - } - else if (conv4 != 0x04030201L) - return FALSE; + return (u2_pt) c4u4(buf); + default: + xxerr("WARNING: typeconv.c(cnu2) illegal count\n"); + return 0; } - else - return FALSE; - return TRUE; } - -#ifdef DEBUG_TYPECONV - -main() -{ - char *source; - char target[4]; - u2_t u2; - u2_t u2a; - u4_t u4; - u4_t u4a; - - printf("%u\n", typeconv_init(FALSE, FALSE)); - printf("%u\n", typeconv_init(FALSE, TRUE)); - printf("%u\n", typeconv_init(TRUE, FALSE)); - printf("%u\n", typeconv_init(TRUE, TRUE)); - - typeconv_init(FALSE, FALSE); - source = "\4\3\2\1"; - - target[0] = 0; - target[1] = 0; - u2 = cnu2(source, 2); - u2cn(target, u2, 2); - if (strncmp(source, target, 2)) - printf("oops9\n"); - - target[0] = 0; - target[1] = 0; - u4a = cnu4(source, 2); - u4cn(target, u4a, 2); - if (strncmp(source, target, 2)) - printf("oops10\n"); - - target[0] = 0; - target[1] = 0; - target[2] = 0; - target[3] = 0; - u2a = cnu2(source, 4); - u2cn(target, u2a, 4); - if (strncmp(target, "\4\3\0\0", 4)) - printf("oops11\n"); - - target[0] = 0; - target[1] = 0; - target[2] = 0; - target[3] = 0; - u4 = cnu4(source, 4); - u4cn(target, u4, 4); - if (strncmp(source, target, 4)) - printf("oops12\n"); - - printf("%04x %04x %08lx %08lx\n", u2, u2a, u4, u4a); - - typeconv_init(FALSE, TRUE); - source = "\2\1\4\3"; - - target[0] = 0; - target[1] = 0; - u2 = cnu2(source + 2, 2); - u2cn(target, u2, 2); - if (strncmp(source + 2, target, 2)) - printf("oops13\n"); - - target[0] = 0; - target[1] = 0; - u4a = cnu4(source + 2, 2); - u4cn(target, u4a, 2); - if (strncmp(source + 2, target, 2)) - printf("oops14\n"); - - target[0] = 0; - target[1] = 0; - target[2] = 0; - target[3] = 0; - u2a = cnu2(source, 4); - u2cn(target, u2a, 4); - if (strncmp(target, "\0\0\4\3", 4)) - printf("oops15\n"); - - target[0] = 0; - target[1] = 0; - target[2] = 0; - target[3] = 0; - u4 = cnu4(source, 4); - u4cn(target, u4, 4); - if (strncmp(source, target, 4)) - printf("oops16\n"); - - printf("%04x %04x %08lx %08lx\n", u2, u2a, u4, u4a); - - typeconv_init(TRUE, FALSE); - source = "\3\4\1\2"; - - target[0] = 0; - target[1] = 0; - u2 = cnu2(source, 2); - u2cn(target, u2, 2); - if (strncmp(source, target, 2)) - printf("oops5\n"); - - target[0] = 0; - target[1] = 0; - u4a = cnu4(source, 2); - u4cn(target, u4a, 2); - if (strncmp(source, target, 2)) - printf("oops6\n"); - - target[0] = 0; - target[1] = 0; - target[2] = 0; - target[3] = 0; - u2a = cnu2(source, 4); - u2cn(target, u2a, 4); - if (strncmp(target, "\3\4\0\0", 4)) - printf("oops7\n"); - - target[0] = 0; - target[1] = 0; - target[2] = 0; - target[3] = 0; - u4 = cnu4(source, 4); - u4cn(target, u4, 4); - if (strncmp(source, target, 4)) - printf("oops8\n"); - - printf("%04x %04x %08lx %08lx\n", u2, u2a, u4, u4a); - - typeconv_init(TRUE, TRUE); - source = "\1\2\3\4"; - - target[0] = 0; - target[1] = 0; - u2 = cnu2(source + 2, 2); - u2cn(target, u2, 2); - if (strncmp(source + 2, target, 2)) - printf("oops1\n"); - - target[0] = 0; - target[1] = 0; - u4a = cnu4(source + 2, 2); - u4cn(target, u4a, 2); - if (strncmp(source + 2, target, 2)) - printf("oops2\n"); - - target[0] = 0; - target[1] = 0; - target[2] = 0; - target[3] = 0; - u2a = cnu2(source, 4); - u2cn(target, u2a, 4); - if (strncmp(target, "\0\0\3\4", 4)) - printf("oops3\n"); - - target[0] = 0; - target[1] = 0; - target[2] = 0; - target[3] = 0; - u4 = cnu4(source, 4); - u4cn(target, u4, 4); - if (strncmp(source, target, 4)) - printf("oops4\n"); - - printf("%04x %04x %08lx %08lx\n", u2, u2a, u4, u4a); -} - -#endif /* DEBUG_TYPECONV */ diff --git a/ld/typeconv.c.old b/ld/typeconv.c.old new file mode 100644 index 0000000..82dafdd --- /dev/null +++ b/ld/typeconv.c.old @@ -0,0 +1,536 @@ +/* typeconv.c - convert between char arrays and unsigneds */ + +/* Copyright (C) 1994 Bruce Evans */ + +/* + c2u2(): 2 byte array to 2 byte unsigned + c4u4(): 4 byte array to 4 byte unsigned + cnu2(): n byte array to 2 byte unsigned + cnu4(): n byte array to 4 byte unsigned + u2c2(): 2 byte unsigned to 2 byte array + u2cn(): 2 byte unsigned to n byte array + u4c4(): 4 byte unsigned to 4 byte array + u4cn(): 4 byte unsigned to n byte array + typeconv_init: (re)initialise for given byte order. + Default is no swapping, but the initialisation should be done + anyway to provide some validity checks (returns FALSE if error). + + Not provided: + c2u4(), c4u2(), u2c4(), u4c2(). + Each of these is best done by truncating or extending a return value + or argument to the appropiate fixed-count function. + c4u2() has too many cases to do in-line conveniently, and the others + are hardly more efficient when done in-line. + + 4 byte orderings for both char arrays and unsigneds are supported: + 0123 - little-endian + 3210 - big-endian + 2301 - little-endian with long words big-endian (pdp11) + 1032 - big-endian with long words little_endian (who knows?) + + The unsigned's byte order is that of the machine on which these + routines are running. + It is determined at run time initialisation since the compiler/ + preprocessor is too dumb to tell us at compile time. +*/ + +#include "const.h" +#include "type.h" +#include "globvar.h" + +FORWARD u2_pt c2u2_00 P((char *buf)); +FORWARD u4_pt c4u4_00 P((char *buf)); +FORWARD u2_pt c2u2_ss P((char *buf)); +FORWARD u4_pt c4u4_ss P((char *buf)); +FORWARD u4_pt c4u4_s0 P((char *buf)); +FORWARD u4_pt c4u4_0s P((char *buf)); +FORWARD void u2c2_00 P((char *buf, u2_pt offset)); +FORWARD void u4c4_00 P((char *buf, u4_t offset)); +FORWARD void u2c2_ss P((char *buf, u2_pt offset)); +FORWARD void u4c4_ss P((char *buf, u4_t offset)); +FORWARD void u4c4_s0 P((char *buf, u4_t offset)); +FORWARD void u4c4_0s P((char *buf, u4_t offset)); + +PRIVATE u2_pt (*pc2u2) P((char *buf)) = c2u2_00; +PRIVATE u4_pt (*pc4u4) P((char *buf)) = c4u4_00; +PRIVATE void (*pu2c2) P((char *buf, u2_pt offset)) = u2c2_00; +PRIVATE void (*pu4c4) P((char *buf, u4_t offset)) = u4c4_00; + +/* === char arrays to unsigneds === */ + +/* no bytes swapped, longwinded to avoid alignment problems */ + +PRIVATE u2_pt c2u2_00(buf) +register char *buf; +{ + u2_t offset; + + ((char *) &offset)[0] = buf[0]; + ((char *) &offset)[1] = buf[1]; + return offset; +} + +PRIVATE u4_pt c4u4_00(buf) +register char *buf; +{ + u4_t offset; + + ((char *) &offset)[0] = buf[0]; + ((char *) &offset)[1] = buf[1]; + ((char *) &offset)[2] = buf[2]; + ((char *) &offset)[3] = buf[3]; + return offset; +} + +/* straight swapping for little-endian to big-endian and vice versa */ + +PRIVATE u2_pt c2u2_ss(buf) +register char *buf; +{ + u2_t offset; + + ((char *) &offset)[0] = buf[1]; + ((char *) &offset)[1] = buf[0]; + return offset; +} + +PRIVATE u4_pt c4u4_ss(buf) +register char *buf; +{ + u4_t offset; + + ((char *) &offset)[0] = buf[3]; + ((char *) &offset)[1] = buf[2]; + ((char *) &offset)[2] = buf[1]; + ((char *) &offset)[3] = buf[0]; + return offset; +} + +/* wierd swapping for different-endian u2's, same-endian u4's */ + +PRIVATE u4_pt c4u4_s0(buf) +register char *buf; +{ + u4_t offset; + + ((char *) &offset)[0] = buf[1]; + ((char *) &offset)[1] = buf[0]; + ((char *) &offset)[2] = buf[3]; + ((char *) &offset)[3] = buf[2]; + return offset; +} + +/* very wierd swapping for same-endian u2's, different-endian u4's */ + +PRIVATE u4_pt c4u4_0s(buf) +register char *buf; +{ + u4_t offset; + + ((char *) &offset)[0] = buf[2]; + ((char *) &offset)[1] = buf[3]; + ((char *) &offset)[2] = buf[0]; + ((char *) &offset)[3] = buf[1]; + return offset; +} + +/* === entry points === */ + +PUBLIC u2_pt c2u2(buf) +char *buf; +{ + return (*pc2u2) (buf); +} + +PUBLIC u4_t c4u4(buf) +char *buf; +{ + return (*pc4u4) (buf); +} + +PUBLIC u2_pt cnu2(buf, count) +char *buf; +unsigned count; +{ + switch (count) + { + case 1: + return buf[0] & 0xFF; + case 2: + return (*pc2u2) (buf); + case 4: + return (u2_pt) (*pc4u4) (buf); + default: + return 0; + } +} + +PUBLIC u4_t cnu4(buf, count) +char *buf; +unsigned count; +{ + switch (count) + { + case 1: + return buf[0] & 0xFF; + case 2: + return (*pc2u2) (buf); + case 4: + return (*pc4u4) (buf); + default: + return 0; + } +} + +/* === unsigneds to char arrays === */ + +/* no bytes swapped, longwinded to avoid alignment problems */ + +PRIVATE void u2c2_00(buf, offset) +register char *buf; +u2_pt offset; +{ + + buf[0] = ((char *) &offset)[0]; + buf[1] = ((char *) &offset)[1]; +} + +PRIVATE void u4c4_00(buf, offset) +register char *buf; +u4_t offset; +{ + buf[0] = ((char *) &offset)[0]; + buf[1] = ((char *) &offset)[1]; + buf[2] = ((char *) &offset)[2]; + buf[3] = ((char *) &offset)[3]; +} + +/* straight swapping for little-endian to big-endian and vice versa */ + +PRIVATE void u2c2_ss(buf, offset) +register char *buf; +u2_pt offset; +{ + u2_t offset2; + + offset2 = offset; + buf[0] = ((char *) &offset2)[1]; + buf[1] = ((char *) &offset2)[0]; +} + +PRIVATE void u4c4_ss(buf, offset) +register char *buf; +u4_t offset; +{ + buf[0] = ((char *) &offset)[3]; + buf[1] = ((char *) &offset)[2]; + buf[2] = ((char *) &offset)[1]; + buf[3] = ((char *) &offset)[0]; +} + +/* wierd swapping for different-endian u2's, same-endian u4's */ + +PRIVATE void u4c4_s0(buf, offset) +register char *buf; +u4_t offset; +{ + buf[0] = ((char *) &offset)[1]; + buf[1] = ((char *) &offset)[0]; + buf[2] = ((char *) &offset)[3]; + buf[3] = ((char *) &offset)[2]; +} + +/* very wierd swapping for same-endian u2's, different-endian u4's */ + +PRIVATE void u4c4_0s(buf, offset) +register char *buf; +u4_t offset; +{ + buf[0] = ((char *) &offset)[2]; + buf[1] = ((char *) &offset)[3]; + buf[2] = ((char *) &offset)[0]; + buf[3] = ((char *) &offset)[1]; +} + +/* === entry points === */ + +PUBLIC void u2c2(buf, offset) +register char *buf; +u2_pt offset; +{ + (*pu2c2) (buf, offset); +} + +PUBLIC void u4c4(buf, offset) +register char *buf; +u4_t offset; +{ + (*pu4c4) (buf, offset); +} + +PUBLIC void u2cn(buf, offset, count) +register char *buf; +u2_pt offset; +unsigned count; +{ + switch (count) + { + case 1: + buf[0] = (char) offset; + return; + case 2: + (*pu2c2) (buf, offset); + return; + case 4: + (*pu4c4) (buf, (u4_t) offset); + return; + } +} + +PUBLIC void u4cn(buf, offset, count) +register char *buf; +u4_t offset; +unsigned count; +{ + switch (count) + { + case 1: + buf[0] = (char) offset; + return; + case 2: + (*pu2c2) (buf, (u2_pt) (u2_t) offset); + return; + case 4: + (*pu4c4) (buf, offset); + return; + } +} + +/* initialise type conversion, return FALSE if it cannot be handled */ + +PUBLIC bool_pt typeconv_init(big_endian, long_big_endian) +bool_pt big_endian; +bool_pt long_big_endian; +{ + u2_pt conv2; + u4_pt conv4; + char *conv2ptr; + char *conv4ptr; + + if (sizeof(u2_t) != 2 || sizeof(u4_t) != 4) + /* dumb preprocessor's don't accept sizeof in #if expressions */ + return FALSE; + + if (big_endian) + { + conv2ptr = (conv4ptr = "\1\2\3\4") + 2; + if (!long_big_endian) + conv4ptr = "\3\4\1\2"; + } + else + { + conv2ptr = conv4ptr = "\4\3\2\1"; + if (long_big_endian) + conv4ptr = "\2\1\4\3"; + } + conv2 = c2u2_00(conv2ptr); + conv4 = c4u4_00(conv4ptr); + if (conv2 == 0x0304) + { + pc2u2 = c2u2_00; + pc4u4 = c4u4_00; + pu2c2 = u2c2_00; + pu4c4 = u4c4_00; + if (conv4 == 0x03040102L) + { + pc4u4 = c4u4_0s; + pu4c4 = u4c4_0s; + } + else if (conv4 != 0x01020304L) + return FALSE; + } + else if (conv2 == 0x0403) + { + pc2u2 = c2u2_ss; + pc4u4 = c4u4_ss; + pu2c2 = u2c2_ss; + pu4c4 = u4c4_ss; + if (conv4 == 0x02010403L) + { + pc4u4 = c4u4_s0; + pu4c4 = u4c4_s0; + } + else if (conv4 != 0x04030201L) + return FALSE; + } + else + return FALSE; + return TRUE; +} + +#ifdef DEBUG_TYPECONV + +main() +{ + char *source; + char target[4]; + u2_t u2; + u2_t u2a; + u4_t u4; + u4_t u4a; + + printf("%u\n", typeconv_init(FALSE, FALSE)); + printf("%u\n", typeconv_init(FALSE, TRUE)); + printf("%u\n", typeconv_init(TRUE, FALSE)); + printf("%u\n", typeconv_init(TRUE, TRUE)); + + typeconv_init(FALSE, FALSE); + source = "\4\3\2\1"; + + target[0] = 0; + target[1] = 0; + u2 = cnu2(source, 2); + u2cn(target, u2, 2); + if (strncmp(source, target, 2)) + printf("oops9\n"); + + target[0] = 0; + target[1] = 0; + u4a = cnu4(source, 2); + u4cn(target, u4a, 2); + if (strncmp(source, target, 2)) + printf("oops10\n"); + + target[0] = 0; + target[1] = 0; + target[2] = 0; + target[3] = 0; + u2a = cnu2(source, 4); + u2cn(target, u2a, 4); + if (strncmp(target, "\4\3\0\0", 4)) + printf("oops11\n"); + + target[0] = 0; + target[1] = 0; + target[2] = 0; + target[3] = 0; + u4 = cnu4(source, 4); + u4cn(target, u4, 4); + if (strncmp(source, target, 4)) + printf("oops12\n"); + + printf("%04x %04x %08lx %08lx\n", u2, u2a, u4, u4a); + + typeconv_init(FALSE, TRUE); + source = "\2\1\4\3"; + + target[0] = 0; + target[1] = 0; + u2 = cnu2(source + 2, 2); + u2cn(target, u2, 2); + if (strncmp(source + 2, target, 2)) + printf("oops13\n"); + + target[0] = 0; + target[1] = 0; + u4a = cnu4(source + 2, 2); + u4cn(target, u4a, 2); + if (strncmp(source + 2, target, 2)) + printf("oops14\n"); + + target[0] = 0; + target[1] = 0; + target[2] = 0; + target[3] = 0; + u2a = cnu2(source, 4); + u2cn(target, u2a, 4); + if (strncmp(target, "\0\0\4\3", 4)) + printf("oops15\n"); + + target[0] = 0; + target[1] = 0; + target[2] = 0; + target[3] = 0; + u4 = cnu4(source, 4); + u4cn(target, u4, 4); + if (strncmp(source, target, 4)) + printf("oops16\n"); + + printf("%04x %04x %08lx %08lx\n", u2, u2a, u4, u4a); + + typeconv_init(TRUE, FALSE); + source = "\3\4\1\2"; + + target[0] = 0; + target[1] = 0; + u2 = cnu2(source, 2); + u2cn(target, u2, 2); + if (strncmp(source, target, 2)) + printf("oops5\n"); + + target[0] = 0; + target[1] = 0; + u4a = cnu4(source, 2); + u4cn(target, u4a, 2); + if (strncmp(source, target, 2)) + printf("oops6\n"); + + target[0] = 0; + target[1] = 0; + target[2] = 0; + target[3] = 0; + u2a = cnu2(source, 4); + u2cn(target, u2a, 4); + if (strncmp(target, "\3\4\0\0", 4)) + printf("oops7\n"); + + target[0] = 0; + target[1] = 0; + target[2] = 0; + target[3] = 0; + u4 = cnu4(source, 4); + u4cn(target, u4, 4); + if (strncmp(source, target, 4)) + printf("oops8\n"); + + printf("%04x %04x %08lx %08lx\n", u2, u2a, u4, u4a); + + typeconv_init(TRUE, TRUE); + source = "\1\2\3\4"; + + target[0] = 0; + target[1] = 0; + u2 = cnu2(source + 2, 2); + u2cn(target, u2, 2); + if (strncmp(source + 2, target, 2)) + printf("oops1\n"); + + target[0] = 0; + target[1] = 0; + u4a = cnu4(source + 2, 2); + u4cn(target, u4a, 2); + if (strncmp(source + 2, target, 2)) + printf("oops2\n"); + + target[0] = 0; + target[1] = 0; + target[2] = 0; + target[3] = 0; + u2a = cnu2(source, 4); + u2cn(target, u2a, 4); + if (strncmp(target, "\0\0\3\4", 4)) + printf("oops3\n"); + + target[0] = 0; + target[1] = 0; + target[2] = 0; + target[3] = 0; + u4 = cnu4(source, 4); + u4cn(target, u4, 4); + if (strncmp(source, target, 4)) + printf("oops4\n"); + + printf("%04x %04x %08lx %08lx\n", u2, u2a, u4, u4a); +} + +#endif /* DEBUG_TYPECONV */ diff --git a/ld/writebin.c b/ld/writebin.c index a001b5d..3b31649 100644 --- a/ld/writebin.c +++ b/ld/writebin.c @@ -4,8 +4,10 @@ /* Copyright (C) 1994 Bruce Evans */ #ifndef NO_AOUT +#ifndef A_OUT_INCL #define A_OUT_INCL #endif +#endif #include "syshead.h" #include "bindef.h" @@ -43,7 +45,9 @@ # define HEADERLEN (A_MINHDR) # endif # endif -# define FILEHEADERLENGTH (headerless?0:HEADERLEN) +# ifndef FILEHEADERLENGTH +# define FILEHEADERLENGTH (headerless?0:HEADERLEN) +# endif #endif #define DPSEG 2 @@ -119,8 +123,11 @@ FORWARD void writeheader P((void)); FORWARD void writenulls P((bin_off_t count)); /* write binary file */ +#ifndef FUNCNAME +#define FUNCNAME writebin +#endif -PUBLIC void writebin(outfilename, argsepid, argbits32, argstripflag, arguzp) +PUBLIC void FUNCNAME(outfilename, argsepid, argbits32, argstripflag, arguzp) char *outfilename; bool_pt argsepid; bool_pt argbits32; @@ -422,11 +429,11 @@ bool_pt arguzp; extsym.n_was_sclass = C_EXT; else extsym.n_was_sclass = C_STAT; - if (!(flags & I_MASK) || + if (!(flags & I_MASK) || ( #ifdef REL_OUTPUT !reloc_output && #endif - flags & C_MASK) + (flags & C_MASK))) switch (flags & (A_MASK | SEGM_MASK)) { case 0: @@ -485,14 +492,17 @@ bool_pt arguzp; memsizeof(struct exec, a_syms)); writeout(buf4, memsizeof(struct exec, a_syms)); #ifdef REL_OUTPUT - 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)); + 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 */ diff --git a/ld/writerel.c b/ld/writerel.c new file mode 100644 index 0000000..a0294f5 --- /dev/null +++ b/ld/writerel.c @@ -0,0 +1,22 @@ +/* + * 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. + */ + +#ifdef BUGCOMPAT +#define A_OUT_INCL "rel_aout.h" +#define BSD_A_OUT 1 +#define FILEHEADERLENGTH 32 +#define ELF_SYMS 0 + +#define FUNCNAME write_rel +#undef NO_AOUT + +#include "writebin.c" +#endif diff --git a/ld/x86_aout.h b/ld/x86_aout.h index bd58346..af2c537 100644 --- a/ld/x86_aout.h +++ b/ld/x86_aout.h @@ -8,25 +8,33 @@ #ifndef __AOUT_H #define __AOUT_H +/* If the host isn't an x86 all bets are off, use chars. */ +#if defined(i386) || defined(__BCC__) +typedef long Long; +#define __OUT_OK 1 +#else +typedef char Long[4]; +#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 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 */ + 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 */ + 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 @@ -34,12 +42,12 @@ struct exec { /* a.out header */ #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_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_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 */ @@ -56,15 +64,17 @@ struct exec { /* a.out header */ /* Offsets of various things. */ #define A_MINHDR 32 #define A_TEXTPOS(X) ((long)(X).a_hdrlen) -#define A_DATAPOS(X) (A_TEXTPOS(X) + (X).a_text) #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 */ -- cgit v1.2.1