From 48f0b3eb836162d41622cedc1eb5f5168168fb8e Mon Sep 17 00:00:00 2001 From: Robert de Bath Date: Sun, 1 Feb 1998 11:26:21 +0100 Subject: Import Dev86src-0.13.5.tar.gz --- ld/Makefile | 6 +- ld/dumps.c | 24 +- ld/io.c | 48 +++- ld/objchop.c | 2 +- ld/objdump86.c | 681 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ld/syshead.h | 2 + ld/type.h | 1 + ld/writex86.c | 80 ++++++- ld/x | 1 + 9 files changed, 827 insertions(+), 18 deletions(-) create mode 100644 ld/objdump86.c create mode 100644 ld/x (limited to 'ld') diff --git a/ld/Makefile b/ld/Makefile index 985008c..6dad38a 100644 --- a/ld/Makefile +++ b/ld/Makefile @@ -13,12 +13,12 @@ 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"' +# 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 writerel.o -all: ld86 objchop catimage +all: ld86 objchop catimage objdump86 ld86: $(OBJS) $(CC) $(LDFLAGS) $(OBJS) -o $@ @@ -28,7 +28,7 @@ install: ld86 install -m 755 ld86 $(LIBDIR) clean realclean: - rm -f *.o ld86 ld86r objchop catimage + rm -f *.o ld86 ld86r objchop catimage objdump86 $(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/dumps.c b/ld/dumps.c index c9a40d4..a969123 100644 --- a/ld/dumps.c +++ b/ld/dumps.c @@ -12,11 +12,26 @@ PUBLIC void dumpmods() { struct modstruct *modptr; + char *s, *d; + int i; for (modptr = modfirst; modptr != NUL_PTR; modptr = modptr->modnext) { - putstr(modptr->loadflag ? "L " : " "); - putbstr(20, modptr->modname); + for(s=d=modptr->filename; *s ; s++) + if( *s == '/' ) d=s+1; + if( memcmp(d, "libc", 4) == 0 && !modptr->loadflag ) continue; + + putstr(modptr->modname); + i = strlen(modptr->modname); + while(i<16) putbyte(' '),i++; + putbyte( modptr->loadflag ? '+':'-' ); + putstr(d); + if( modptr->archentry ) + { + putbyte('('); + putstr(modptr->archentry); + putbyte(')'); + } putbyte('\n'); } } @@ -55,7 +70,10 @@ PUBLIC void dumpsyms() #else put08x(symptr->value); #endif - putstr(flags & A_MASK ? " A" : " R"); + if( flags & (E_MASK|C_MASK) ) + putstr(flags & A_MASK ? " A" : " R"); + else + putstr(flags & A_MASK ? " a" : " r"); if (uflag) putstr(" U"); if (flags & C_MASK) diff --git a/ld/io.c b/ld/io.c index a21ecd3..e56a474 100644 --- a/ld/io.c +++ b/ld/io.c @@ -22,6 +22,7 @@ PRIVATE char *drelbuftop; /* data relocation output buffer top */ PRIVATE char *errbuf; /* error buffer (actually uses STDOUT) */ PRIVATE char *errbufptr; /* error buffer ptr */ PRIVATE char *errbuftop; /* error buffer top */ +PRIVATE int errfil = STDOUT_FILENO; PRIVATE char *inbuf; /* input buffer */ PRIVATE char *inbufend; /* input buffer top */ PRIVATE char *inbufptr; /* end of input in input buffer */ @@ -56,6 +57,7 @@ FORWARD void outputerror P((char *message)); FORWARD void put04x P((unsigned num)); FORWARD void putstrn P((char *message)); FORWARD void refer P((void)); +FORWARD void stderr_out P((void)); PUBLIC void ioinit(progname) char *progname; @@ -65,6 +67,10 @@ char *progname; refname = progname; /* name must be static (is argv[0]) */ else refname = "link"; + for(progname=refname; *progname; progname++) + if(*progname=='/') + refname=progname+1; + #ifdef REL_OUTPUT drelbuf = malloc(DRELBUFSIZE); drelbuftop = drelbuf + DRELBUFSIZE; @@ -129,10 +135,20 @@ PUBLIC void executable() PUBLIC void flusherr() { - write(STDOUT_FILENO, errbuf, (unsigned) (errbufptr - errbuf)); + if( errbufptr != errbuf ) + write(errfil, errbuf, (unsigned) (errbufptr - errbuf)); errbufptr = errbuf; } +PRIVATE void stderr_out() +{ + if( errfil != STDERR_FILENO ) + { + flusherr(); + errfil = STDERR_FILENO; + } +} + PRIVATE void flushout() { unsigned nbytes; @@ -287,7 +303,7 @@ char *message; { putstr(message); putbyte('\n'); - flusherr(); + flusherr(); errfil = STDOUT_FILENO; } PUBLIC int readchar() @@ -525,11 +541,32 @@ char *defarchentry; putstr(defarchentry); putbyte(')'); } - putbyte('\n'); + putstrn(""); +} + +PUBLIC void interseg(fname, aname, name) +char *fname, *aname, *name; +{ + ++errcount; + refer(); + putstr("error in "); + putstr(fname); + if( aname ) + { + putstr("("); + putstr(aname); + putstr(")"); + } + putstr(" intersegment jump to "); + if( name ) putstr(name); + else putstr("same file"); + + putstrn(""); } PRIVATE void refer() { + stderr_out(); putstr(refname); putstr(": "); } @@ -538,6 +575,7 @@ PUBLIC void reserved(name) char *name; { ++errcount; + stderr_out(); putstr("incorrect use of reserved symbol: "); putstrn(name); } @@ -554,19 +592,21 @@ bin_off_t size; outhexdigs(count); putstr(", supposed to be "); outhexdigs(size); - errexit("\n"); + errexit(""); } PUBLIC void undefined(name) char *name; { ++errcount; + stderr_out(); putstr("undefined symbol: "); putstrn(name); } PUBLIC void usage() { + stderr_out(); putstr("usage: "); putstr(refname); #ifdef REL_OUTPUT diff --git a/ld/objchop.c b/ld/objchop.c index c5a81e4..8defc13 100644 --- a/ld/objchop.c +++ b/ld/objchop.c @@ -61,7 +61,7 @@ long bsize; FILE * ofd; ofd = fopen(fname, "w"); - if( ofd == 0 ) fatal("Cannout open output file"); + if( ofd == 0 ) fatal("Cannot open output file"); while(bsize>0) { diff --git a/ld/objdump86.c b/ld/objdump86.c new file mode 100644 index 0000000..a5dbf44 --- /dev/null +++ b/ld/objdump86.c @@ -0,0 +1,681 @@ +/* + * This is a combination of three tools for decoding information from + * Dev86/ELKS object files and executables. + * + * This executable can be given the names: + * + * objdump86: Dumps detailed information about a binary file. + * size86: Summary sizes of the data in a binary file. + * nm86: The symbol table of the binary file. + * + * None of these programs have any options, neither can they currently deal + * with archive files. This may be a minor problem with nm86. + */ + +#include +#include +#include + +FILE * ifd = stdin; +char * ifname; + +#ifdef __STDC__ +#define _(x) x +#else +#define _(x) () +#endif + +long get_long _((void)); +long get_sized _((int sz)); +unsigned int get_word _((void)); +int main _((int argc, char**argv)); +void do_file _((char * fname)); +int error _((char * str)); +int read_objheader _((void)); +int read_sectheader _((void)); +int read_syms _((void)); +void read_databytes _((void)); +void hex_output _((int ch)); +void fetch_aout_hdr _((void)); +void dump_aout _((void)); +void size_aout _((void)); +void nm_aout _((void)); + +int sections; +long segsizes[16]; +long textoff, textlen; +long str_off, str_len; + +char ** symnames; +char * symtab; + +int display_mode = 0; +int multiple_files = 0; +int byte_order = 0; + +long size_text, size_data, size_bss; + +int +main(argc, argv) +int argc; +char ** argv; +{ + int ar; + char * p; + + p = strrchr(argv[0], '/'); + if(p) p++; else p=argv[0]; + + if( p[0] == 's' ) display_mode = 1; + if( p[0] == 'n' ) display_mode = 2; + + if( display_mode == 1 ) + printf("text\tdata\tbss\tdec\thex\tfilename\n"); + + multiple_files = (argc>2); + + for(ar=1; ar>(2*(15-ss)))&3); + segsizes[i] = get_sized(ss); + if( segsizes[i] && !display_mode ) + printf("SEG%x %08lx\n", i, segsizes[i]); + } + if( !display_mode ) + printf("\n"); + + return 0; +} + +int +read_syms() +{ + int syms, i; + + syms=get_word(); + + if( !display_mode ) printf("SYMS %u\n", syms); + if( syms < 0 ) return error("Bad symbol table"); + + symnames = malloc(syms*sizeof(char*)+1); + if( symnames == 0 ) return error("Out of memory"); + + if(display_mode == 2 && multiple_files) + printf("\n%s:\n", ifname); + + for(i=0; i>14)&3); + symtype &= 0x3FFF; + symnames[i] = symtab+nameoff; + + if( !display_mode ) + { + printf("SYM %-4d %08lx ", i, offset); + + printf("%s", (symtype&0x2000)?"C":"."); + printf("%s", (symtype&0x0100)?"N":"."); + printf("%s", (symtype&0x0080)?"E":"."); + printf("%s", (symtype&0x0040)?"I":"."); + printf("%c", "T12D456789abcdeUAhijklmnopqrstuv"[symtype&0x1F]); + if( symtype &0x1E20 ) + printf(" %04x", symtype); + printf(" %s\n", symnames[i]); + } + if( display_mode == 2 ) + { + if( symtype == 0x004f || symtype == 0x0040 ) + printf(" "); + else + printf("%08lx ", offset); + switch(symtype) + { + case 0x004F: putchar('U'); break; + case 0x0000: putchar('t'); break; + case 0x0003: putchar('d'); break; + case 0x2003: putchar('b'); break; + case 0x0043: putchar('C'); break; + case 0x0083: putchar('D'); break; + case 0x0080: putchar('T'); break; + case 0x0040: putchar('T'); break; + case 0x0180: putchar('N'); break; + case 0x0010: putchar('a'); break; + case 0x0090: putchar('A'); break; + default: putchar('?'); break; + } + printf(" %s\n", symnames[i]); + } + + if( symtype == 0x43 || symtype == 0x2003 ) + size_bss += offset; + } + if( !display_mode ) + printf("\n"); + + return 0; +} + +void +read_databytes() +{ +static char * relstr[] = {"ERR", "DB", "DW", "DD"}; + long l; + int ch, i; + int curseg = 0; + int relsize = 0; + fseek(ifd, textoff, 0); + + printf("\nBYTECODE\n"); + for(;;) + { + if( (ch=getc(ifd)) == EOF ) break; + + if( ch == 0 ) break; + + switch( ch & 0xC0 ) + { + case 0x00: switch(ch & 0xF0) + { + case 0x00: /* Relocator size */ + printf("RELSZ %d\n", relsize= (ch&0xF)); + if(relsize>3) relsize=3; + break; + case 0x10: /* Skip bytes */ + printf("SKP %ld\n", get_sized(ch&0xF)); + break; + case 0x20: /* Segment */ + printf("SEG %x\n", curseg= (ch&0xF)); + break; + default: printf("CODE %02x - unknown\n", ch); + return ; + } + break; + case 0x40: /* Raw bytes */ + { + int abscnt = (ch&0x3F); + if( abscnt == 0 ) abscnt = 64; + for( i=0; i7), buf, 2); + if( ch > ' ' && ch <= '~' ) linebuf[50+pos] = ch; + else linebuf[50+pos] = '.'; + pos = ((pos+1) & 0xF); + if( pos == 0 ) + { + printf(": %.66s\n", linebuf); + memset(linebuf, ' ', sizeof(linebuf)); + } + } +} + +/************************************************************************/ +/* ELKS a.out versions + */ + +long header[12]; +int h_len, h_flgs, h_cpu; + +void +fetch_aout_hdr() +{ + int i; + + header[0] = get_long(); + header[1] = get_long(); + byte_order = ((header[0]>>24) & 3); + + h_len = (header[1] & 0xFF); + h_flgs = ((header[0]>>16) & 0xFF); + h_cpu = ((header[0]>>24) & 0xFF); + + for(i=2; i<8; i++) + { + if( i*4 <= h_len ) + header[i] = get_long(); + else + header[i] = 0; + } +} + +void +dump_aout() +{ +static char * cpu[] = { "unknown", "8086", "m68k", "ns16k", "i386", "sparc" }; +static char * byteord[] = { "LITTLE_ENDIAN", "(2143)","(3412)","BIG_ENDIAN" }; + int i; + long l; + + if( display_mode == 0 ) fetch_aout_hdr(); + + if( h_cpu > 0x17 ) h_cpu &= 3; + + printf("HLEN %d\n", h_len); + printf("CPU %s %s\n", cpu[h_cpu>>2], byteord[h_cpu&3]); + + printf("FLAGS:"); + if( h_flgs & 0x01 ) printf(" A_UZP"); + if( h_flgs & 0x02 ) printf(" A_PAL"); + if( h_flgs & 0x04 ) printf(" A_NSYM"); + if( h_flgs & 0x08 ) printf(" FLG-08"); + if( h_flgs & 0x10 ) printf(" A_EXEC"); + if( h_flgs & 0x20 ) printf(" A_SEP"); + if( h_flgs & 0x40 ) printf(" A_PURE"); + if( h_flgs & 0x80 ) printf(" A_TOVLY"); + printf("\n"); + + if( header[5] ) + printf("a_entry = 0x%08lx\n", header[5]); + printf("a_total = 0x%08lx\n", header[6]); + if( header[7] ) + printf("a_syms = 0x%08lx\n", header[7]); + + if( h_len >= 36 ) + printf("a_trsize = 0x%08lx\n", header[8]); + if( h_len >= 40 ) + printf("a_drsize = 0x%08lx\n", header[9]); + if( h_len >= 44 ) + printf("a_tbase = 0x%08lx\n", header[10]); + if( h_len >= 48 ) + printf("a_dbase = 0x%08lx\n", header[11]); + printf("\n"); + + size_aout(); + printf("\n"); + + if( header[7] ) + { + printf("SYMBOLS\n"); + nm_aout(); + } + else + printf("NO SYMBOLS\n"); + printf("\n"); + + printf("TEXTSEG\n"); + fseek(ifd, (long)h_len, 0); + for(l=0; l 16) + { + if( fread(n_name, 1, 8, ifd) != 8 ) return; + n_name[8] = 0; + n_value = get_long(); + if( (n_sclass = getc(ifd)) == EOF ) return; + if( (n_numaux = getc(ifd)) == EOF ) return; + n_type = get_word(); + + printf("%08lx ", n_value); + switch(n_sclass) + { + case 0x01: printf("a "); break; + case 0x12: printf("T "); break; + case 0x13: printf("D "); break; + case 0x14: printf("C "); break; + case 0x1a: printf("t "); break; + case 0x1b: printf("d "); break; + case 0x1c: printf("b "); break; + default: if( display_mode ) + { + printf("? "); break; + } + + printf("n_sclass="); + switch(n_sclass>>3) + { + case 0: printf("C_NULL,"); break; + case 2: printf("C_EXT,"); break; + case 3: printf("C_STAT,"); break; + default: printf("%04o,", n_sclass&0xF8); + } + switch(n_sclass&7) + { + case 0: printf("N_UNDF "); break; + case 1: printf("N_ABS "); break; + case 2: printf("N_TEXT "); break; + case 3: printf("N_DATA "); break; + case 4: printf("N_BSS "); break; + case 5: printf("N_COMM "); break; + default: printf("%o ", n_sclass&7); break; + } + break; + } + + if( display_mode == 0 ) + { + if( n_numaux ) + printf("n_numaux=%02x ", n_numaux); + if( n_type ) + printf("n_type=%04x ", n_type); + } + + printf("%s\n", n_name); + } +} diff --git a/ld/syshead.h b/ld/syshead.h index 5eeda82..fa5c23a 100644 --- a/ld/syshead.h +++ b/ld/syshead.h @@ -24,6 +24,7 @@ #define mode_t unsigned short #define SEEK_SET 0 #define STDOUT_FILENO 0 +#define STDERR_FILENO 0 #endif /******************************************************************************/ @@ -54,6 +55,7 @@ void *memset P((void *s, int c, unsigned n)); int access P((const char *path, int amode)); #define SEEK_SET 0 #define STDOUT_FILENO 0 +#define STDERR_FILENO 2 #define mode_t unsigned short #define off_t long diff --git a/ld/type.h b/ld/type.h index 217d6a9..a4c16aa 100644 --- a/ld/type.h +++ b/ld/type.h @@ -114,6 +114,7 @@ void outofmemory P((void)); void prematureeof P((void)); void redefined P((char *name, char *message, char *archentry, char *deffilename, char *defarchentry)); +void interseg P((char *fname, char *aname, char *name)); void reserved P((char *name)); void size_error P((int seg, bin_off_t count, bin_off_t size)); void undefined P((char *name)); diff --git a/ld/writex86.c b/ld/writex86.c index 5dd3e8d..b2bab23 100644 --- a/ld/writex86.c +++ b/ld/writex86.c @@ -13,10 +13,8 @@ #define bdataoffset (data_base_value) #define page_size() ((bin_off_t)4096) -#ifdef __ELF__ #ifndef ELF_SYMS -#define ELF_SYMS 1 -#endif +#define ELF_SYMS 0 #endif # define FILEHEADERLENGTH (headerless?0:A_MINHDR) @@ -130,13 +128,21 @@ bool_pt arguzp; symres(segboundary); /* __segXCL */ segboundary[7] = 'H'; symres(segboundary); /* __segXCH */ +#ifndef DATASEGS + if( curseg > 3 ) + { + segboundary[6] = 'S'; + segboundary[7] = 'O'; + symres(segboundary); /* __segXSO */ + } +#endif } curseg = 3; symres("__edata"); symres("__end"); curseg = 0; /* text seg, s.b. variable */ symres("__etext"); - if( headerless ) symres("__segoff"); + symres("__segoff"); /* calculate segment and common sizes (sum over loaded modules) */ /* use zero init of segsz[] */ @@ -186,8 +192,13 @@ bool_pt arguzp; } /* 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 */ + /* +#ifdef DATASEGS + * Assume seg 0 is text and rest are data +#else + * Assume seg 1..3 are data, Seg 0 is real text, seg 4+ are far text +#endif + */ segpos[0] = segbase[0] = spos = btextoffset; combase[0] = segbase[0] + segsz[0]; segadj[1] = segadj[0] = -btextoffset; @@ -201,9 +212,23 @@ bool_pt arguzp; bdataoffset = etextpadoff; segpos[1] = segbase[1] = edataoffset = bdataoffset; combase[1] = segbase[1] + segsz[1]; +#ifndef DATASEGS + for (seg = 4; seg < NSEG; ++seg) + { + segpos[seg] = segbase[seg] = 0; + combase[seg] = segbase[seg] + segsz[seg]; + segadj[seg] = etextpadoff; + + etextpadoff += ld_roundup(segsz[seg] + comsz[seg], 0x10, bin_off_t); + segadj[1] += ld_roundup(segsz[seg] + comsz[seg], 0x10, bin_off_t); + } + for (seg = 2; seg < 4; ++seg) +#else for (seg = 2; seg < NSEG; ++seg) +#endif { segpos[seg] = segbase[seg] = combase[seg - 1] + comsz[seg - 1]; +#ifdef MC6809 if (seg == DPSEG) { /* temporarily have fixed DP seg */ @@ -216,6 +241,7 @@ bool_pt arguzp; segpos[seg] = segbase[seg] = (segbase[seg] + 0xFF) & ~(bin_off_t) 0xFF; } +#endif combase[seg] = segbase[seg] + segsz[seg]; segadj[seg] = segadj[seg - 1]; } @@ -241,8 +267,12 @@ bool_pt arguzp; /* adjust special symbols */ for (seg = 0; seg < NSEG; ++seg) { +#ifdef DATASEGS if (segsz[seg] != 0) /* only count data of nonzero length */ +#else + if (segsz[seg] != 0 && seg < 4) +#endif edataoffset = segbase[seg] + segsz[seg]; segboundary[5] = hexdigit[seg]; /* to __segX?H */ segboundary[6] = 'D'; @@ -256,11 +286,24 @@ bool_pt arguzp; segboundary[7] = 'H'; setsym(segboundary, tempoffset + comsz[seg]); /* __segXCH */ +#ifndef DATASEGS + if( seg > 3 ) + { + segboundary[6] = 'S'; + segboundary[7] = 'O'; + setsym(segboundary, (bin_off_t)(segadj[seg]-segadj[0])/0x10); + /* __segXSO */ + } +#endif } setsym("__etext", etextoffset); setsym("__edata", edataoffset); +#ifdef DATASEGS setsym("__end", endoffset = combase[NSEG - 1] + comsz[NSEG - 1]); - if( headerless ) setsym("__segoff", (bin_off_t)(segadj[1]-segadj[0])/0x10); +#else + setsym("__end", endoffset = combase[3] + comsz[3]); +#endif + setsym("__segoff", (bin_off_t)(segadj[1]-segadj[0])/0x10); if( !bits32 ) { if( etextoffset > 65536L ) @@ -322,11 +365,20 @@ bool_pt arguzp; flags & C_MASK) switch (flags & (A_MASK | SEGM_MASK)) { +#ifdef DATASEGS case 0: +#else + default: +#endif extsym.n_sclass |= N_TEXT; case A_MASK: break; +#ifdef DATASEGS default: +#else + case 1: case 2: case 3: + case A_MASK|1: case A_MASK|2: case A_MASK|3: +#endif if (flags & (C_MASK | SA_MASK)) extsym.n_sclass |= N_BSS; else @@ -414,7 +466,14 @@ struct modstruct *modptr; case CM_OFFSET_RELOC: offset = readsize(relocsize); if (modify & R_MASK) + { +#ifndef DATASEGS + int m = (modify & SEGM_MASK); + if( curseg != m && m != SEGM_MASK ) + interseg(modptr->filename, modptr->archentry, (char*)0); +#endif offset -= (spos + relocsize); + } offtocn(buf, segbase[modify & SEGM_MASK] + offset, relocsize); writeout(buf, relocsize); spos += relocsize; @@ -424,7 +483,14 @@ struct modstruct *modptr; (modify & S_MASK ? 2 : 1))]; offset = readconvsize((unsigned) modify & OF_MASK); if (modify & R_MASK) + { +#ifndef DATASEGS + int m = (symptr->flags & SEGM_MASK); + if( curseg != m && m != SEGM_MASK ) + interseg(modptr->filename, modptr->archentry, symptr->name); +#endif offset -= (spos + relocsize); + } offset += symptr->value; offtocn(buf, offset, relocsize); writeout(buf, relocsize); diff --git a/ld/x b/ld/x new file mode 100644 index 0000000..90d943e --- /dev/null +++ b/ld/x @@ -0,0 +1 @@ +PUBLIC void interseg(fname, aname, name) -- cgit v1.2.1