chmod chown chroot ci cksum cleantmp clear cmp co \
comm compress cp crc cron crontab cut date \
dd de decomp16 DESCRIBE dev2name devsize df dhcpd \
- dhrystone diff dirname dis88 diskctl du dumpcore \
+ dhrystone diff dirname dis386 dis88 diskctl du dumpcore \
ed eject elle elvis env expand factor file \
find finger fingerd fix fold format fortune fsck.mfs \
fsck1 ftp101 ftpd200 gcov-pull getty grep gomoku head hexdump host \
--- /dev/null
+# Makefile for dis386
+
+PROGS= dis386e dis386o
+SRCS.dis386e=dise.c misc.c unasm.c
+SRCS.dis386o=diso.c misc.c unasm.c
+MAN.dis386e=
+MAN.dis386o=
+
+.include <bsd.prog.mk>
--- /dev/null
+/* const.h - constants for db.
+ *
+ * $Id: const.h,v 1.0 1990/10/06 12:00:00 cwr Exp cwr $
+ */
+
+/* general constants */
+#define FALSE 0
+#undef NULL
+#define NULL 0
+#define TRUE 1
+
+/* C tricks */
+#define EXTERN extern
+#define FORWARD static
+#define PRIVATE static
+#define PUBLIC
+
+/* ASCII codes */
+#define CAN 24
+#define CR 13
+#define EOF (-1)
+#define LF 10
+#define XOFF 19
+
+/* hardware processor-specific for 8088 through 80386 */
+#ifndef HCLICK_SIZE
+#define HCLICK_SIZE 0x10
+#endif
+#define IF 0x0200 /* interrupt disable bit in flags */
+#define INT_BREAKPOINT 0xCC /* byte for breakpoint interrupt */
+#define LINEARADR(seg, off) \
+ (HCLICK_SIZE * (physoff_t) (segment_t) (seg) + (off))
+#define TF 0x0100 /* trap bit in flags */
+
+/* hardware processor-specific for 80386 and emulated for others */
+#define BS 0x4000 /* single-step bit in dr6 */
+
+/* use hardware codes for segments for simplest decoding */
+#define CSEG 0x2E /* 8088 through 80386 */
+#define DSEG 0x3E
+#define ESEG 0x26
+#define FSEG 0x64
+#define GSEG 0x65 /* 80386 only */
+#define SSEG 0x36
+
+/* software machine-specific for PC family */
+#define BIOS_DATA_SEG 0x40
+# define KB_FLAG 0x17 /* offset to 16-bits of keyboard shift flags */
+
+/* switches to handle non-conforming compilers */
+#define UCHAR_BUG /* compiler converts unsigned chars wrong */
+
+#ifdef UCHAR_BUG
+# define UCHAR(x) ((x) & 0xFF)
+#endif
+
--- /dev/null
+Dis36: a static disassembler for Minix 2.0. C W Rose, 20 Oct 97.
+
+SUMMARY
+
+This is the second release of dis386, a disassembler for Minix 2.0 At present
+it is comprised of two programs, dise which understands executable files, and
+diso which understands object files. The programs have been written using as
+much common code as possible, and in time they will be merged. Meantime, they
+are easier to debug separately.
+
+The two programs are both front ends for Bruce Evan's x86 disassembler. The
+disassembler can handle both 16-bit and 32-bit code, but since the programs
+use large data tables (kept in memory for speedy access) they have been tested
+only on 32-bit Minix.
+
+The changes between versions 1.0 and 1.1 are small, but add to the ease of
+use: addresses can now be entered in decimal or hexadecimal (leading 0x),
+and starting offset and program counter now have more intelligble values.
+
+OPTIONS
+
+Object, executable and core files have the following structures, where
+Name is the section name, and Option the option needed to display the section.
+
+Object file Executable file Core file
+Name Option Name Option Name Option
+Header } h Header h Memory map m
+Section headers } Process table p
+Sections - Sections - Sections -
+ text t text t text t
+ rom m
+ data d data d data d
+ bss - stack k
+Relocation structures r
+Symbol table s Symbol table s
+Symbol names n
+
+Other options are:
+ -A str set executable file name
+ -C str set core file name
+ -O str set object file name
+ -a display all sections
+ -b dump in straight binary
+ -f # set the first address to be displayed
+ -l # set the last address to be displayed
+ -x # set debugging level
+
+Not all these options are functional at present; in particular, the file type
+override of -A/C/O isn't implemented (since the programs are single-purpose).
+
+The default option is -h. The default input file is a.out for dise, and test.o
+for diso. Otherwise, input is taken from the first file option on the command
+line. Output is always written to standard output, and error messages to
+standard error.
+
+BUGS AND FEATURES
+
+The programs search the data area for possible local symbols; generally, these
+are the start of strings. At the moment this search is limited, and accepts
+even single printing characters as strings; it should probably accept only
+runs of three or more characters.
+
+There is no search for local text symbols, as opposed to data symbols; this
+would need two full passes over the text with the disassembler, and doesn't
+seem worthwhile. Once the data symbols are out of the way, the disassembled
+text is fairly easy to read.
+
+The programs do a fair amount of error checking to ensure that they are
+using eg. addresses that are within scope, but if they do fail they tend
+to abandon the task completely and bale out with a (supposedly informative)
+error message.
+
+There are many apparent dead-ends in the code, left as hooks for later
+additions.
+
+/* eof */
+
--- /dev/null
+/*
+ * dis386.h: header file for dis386.c.
+ *
+ * $Id: dis386.h,v 1.1 1997/10/20 12:00:00 cwr Exp cwr $
+ *
+ * Written by C W Rose.
+ */
+
+#ifndef EXTERN
+#define EXTERN extern
+#endif
+
+/* Generally used variables */
+struct locname { /* local symbol table entry */
+ char l_name[8]; /* symbol name */
+ unsigned char l_sclass; /* storage class */
+ long l_value; /* symbol value */
+ struct locname *l_next; /* pointer to next entry */
+};
+EXTERN struct locname *locsym[MAXSECT]; /* local symbol tables */
+
+EXTERN FILE *aoutfp; /* executable file pointer */
+EXTERN FILE *corefp; /* core file pointer */
+EXTERN FILE *disfp; /* disassembly file pointer */
+EXTERN FILE *objfp; /* object file pointer */
+EXTERN FILE *symfp; /* symbol file pointer */
+
+/* executable file variables */
+EXTERN struct exec a_hdrbuf; /* executable header structure */
+EXTERN struct nlist *a_symtab; /* executable symbol table */
+
+/* .o file variables */
+EXTERN struct outhead o_hdrbuf; /* object file header data */
+EXTERN struct outsect o_sectab[MAXSECT];/* object file section data */
+EXTERN char *o_secnam[MAXSECT]; /* object file section names */
+EXTERN struct outrelo *o_reltab; /* object file relocation table */
+EXTERN struct outname *o_symtab; /* object file symbol table */
+EXTERN char *o_strtab; /* object file symbol names */
+
+/* Generally used functions */
+PUBLIC int dasm(unsigned long addr, unsigned long count); /* disassemble opcodes */
+
+/*
+ * EOF
+ */
+
--- /dev/null
+/*
+ * dis_e386: disassemble 386 executable files.
+ *
+ * $Id: dise.c,v 1.1 1997/10/20 12:00:00 cwr Exp cwr $
+ *
+ * Written by C W Rose.
+ */
+
+/* Version settings */
+#define MINIX
+#undef OS2
+#undef TEST
+
+#ifdef MINIX
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <minix/config.h>
+#include <minix/const.h>
+#include <a.out.h>
+#include <ansi.h>
+#include <assert.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#undef S_ABS /* used in a.out.h */
+#include "out.h" /* ACK compiler output header */
+#undef EXTERN
+#define EXTERN
+#include "dis386.h" /* dis386 header */
+#endif
+
+#ifdef OS2
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include </local/minix/minix/config.h>
+#include </local/minix/minix/const.h>
+#include </local/minix/a.out.h>
+#include </local/minix/ansi.h>
+
+#include <assert.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <io.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#undef S_ABS /* used in a.out.h */
+#include "out.h" /* ACK compiler output header */
+#undef EXTERN
+#define EXTERN
+#include "dis386.h" /* dis386 header */
+#endif
+
+/* Standard defines */
+#define FALSE 0
+#undef TRUE
+#define TRUE !FALSE
+#define FAILED -1
+#define MAYBE 0
+#define OK 1
+#define SAME 0
+
+/* Local defines */
+#define L_BUFF_LEN 1024
+#define BUFF_LEN 256
+#define S_BUFF_LEN 20
+#define L_BUFF_MAX (L_BUFF_LEN-1)
+#define BUFF_MAX (BUFF_LEN-1)
+#define S_BUFF_MAX (S_BUFF_LEN-1)
+#define PSEP '\\'
+
+#define AOUT "a.out"
+#define CORE "core"
+#define STAB "symbol.tab"
+#define LINE_LEN 16
+#define SYMLEN 8
+
+#define TEXT 0 /* section indices for locsym[] */
+#define ROM 1
+#define DATA 2
+#define BSS 3
+
+#ifndef lint
+static char *Version = "@(#) dis_e386.c $Revision: 1.1 $ $Date: 1997/10/20 12:00:00 $";
+#endif
+
+/* Global variables */
+int opt_C = FALSE; /* core file name */
+int opt_E = FALSE; /* executable file name */
+int opt_O = FALSE; /* object file name */
+int opt_S = FALSE; /* symbol table name */
+int opt_a = FALSE; /* dump tables and disassemble segments */
+int opt_b = FALSE; /* dump straight binary */
+int opt_d = FALSE; /* dump the data segment */
+int opt_f = FALSE; /* first address of dump */
+int opt_h = FALSE; /* dump the header structure */
+int opt_l = FALSE; /* last address of dump */
+int opt_m = FALSE; /* dump the rom segment */
+int opt_n = FALSE; /* dump the symbol names */
+int opt_r = FALSE; /* dump the relocation structures */
+int opt_s = FALSE; /* dump the symbol table */
+int opt_t = FALSE; /* dump the text segment */
+int opt_u = FALSE; /* dump the bss segment */
+int opt_x = FALSE; /* debugging flag */
+
+char progname[BUFF_LEN]; /* program name */
+int dbglvl = 0; /* debugging level */
+
+struct a_sec { /* a.out section data */
+ char *name; /* section name */
+ int first; /* first index */
+ int last; /* last index */
+ int total;
+} a_sectab[] = { /* all known a.out sections */
+ "undefined", 0, 0, 0,
+ "absolute", 0, 0, 0,
+ "text", 0, 0, 0,
+ "data", 0, 0, 0,
+ "bss", 0, 0, 0,
+ "common", 0, 0, 0,
+ "rom", 0, 0, 0, /* this one is unknown */
+ (char *)NULL, 0, 0, 0
+};
+
+/* Forward declarations */
+unsigned long atoaddr(char *); /* Convert ascii hex/dec to unsigned long */
+int binary(unsigned char, char*); /* Binary output of 8-bit number */
+int dump_ahdr(struct exec *ep); /* Dump an a.out file header */
+int dump_adata(FILE *fp, int start, int count); /* Dump an a.out file data section */
+int dump_asym(struct nlist *np, int start, int count); /* Dump an a.out file symbol table */
+int dump_hex(FILE *fp, int start, int count); /* Dump bytes in hex and ascii */
+int find_asym(long value, int section); /* Find an a.out symbol */
+int gen_locsym(FILE *fp, int sec); /* Generate local symbols */
+int init_aout(FILE *fp); /* Initialise the a.out file tables */
+void usage(void); /* Usage message */
+
+
+/*
+ * a t o a d d r
+ *
+ * Convert ascii hex/dec to unsigned long.
+ *
+ * Returns: Conversion result Always
+ */
+unsigned long atoaddr(char *sp)
+{
+ char c, *cp, buff[S_BUFF_LEN];
+ int j;
+ unsigned long int result = 0;
+
+ /* flip to upper */
+ for (j = 0 ; j < S_BUFF_MAX && *(sp + j) != '\0' ; j++)
+ buff[j] = toupper(*(sp + j));
+ buff[j] = '\0';
+
+ /* lose leading whitespace */
+ cp = buff;
+ while isspace(*cp)
+ cp++;
+
+ /* check for hexadecimal entry */
+ if (*cp == '0' && *(cp + 1) == 'X') {
+ cp += 2;
+ while (isxdigit(*cp)) {
+ c = *cp++;
+ j = (c < 'A') ? c - '0' : c - 'A' + 10;
+ result = (result << 4) + (c < 'A' ? c - '0' : c - 'A' + 10);
+ }
+ }
+ else
+ result = atol(buff);
+
+ return result;
+}
+
+
+/*
+ * b i n a r y
+ *
+ * Produce a binary representation of an 8-bit number.
+ *
+ * Returns: 0 Always
+ */
+int binary(unsigned char uc, char *sp)
+{
+ int j;
+ unsigned char k;
+
+ for (k = 0x80, j = 0 ; j < 8 ; j++) {
+ if ((uc & k) == 0) *sp++ = '0';
+ else *sp++ = '1';
+ if (j == 3) *sp++ = '$';
+ k >>= 1;
+ }
+ *sp = '\0';
+
+ return(0);
+}
+
+
+/*
+ * d u m p _ a h d r
+ *
+ * Dump an a.out file header.
+ *
+ * Returns: OK Always
+ */
+int dump_ahdr(struct exec *ep)
+{
+ char buff[BUFF_LEN];
+
+ fprintf(stdout, "Magic number is: 0x%02x%02x\n",
+ ep->a_magic[0], ep->a_magic[1]);
+ sprintf(buff, "Flags are: 0x%02x", ep->a_flags);
+ if (ep->a_flags & A_UZP) strcat(buff, " A_UZP");
+ if (ep->a_flags & A_PAL) strcat(buff, " A_PAL");
+ if (ep->a_flags & A_NSYM) strcat(buff, " A_NSYM");
+ if (ep->a_flags & A_EXEC) strcat(buff, " A_EXEC");
+ if (ep->a_flags & A_SEP) strcat(buff, " A_SEP");
+ if (ep->a_flags & A_PURE) strcat(buff, " A_PURE");
+ if (ep->a_flags & A_TOVLY) strcat(buff, " A_TOVLY");
+ if (ep->a_flags & ~(A_UZP | A_PAL | A_NSYM | A_EXEC | A_SEP | A_PURE | A_TOVLY))
+ strcat(buff, " UNKNOWN");
+ fprintf(stdout, "%s\n", buff);
+
+ sprintf(buff, "CPU type is: 0x%02x", ep->a_cpu);
+ if (ep->a_cpu == A_NONE) strcat(buff, " A_NONE");
+ else if (ep->a_cpu == A_I8086) strcat(buff, " A_I8086");
+ else if (ep->a_cpu == A_M68K) strcat(buff, " A_M68K");
+ else if (ep->a_cpu == A_NS16K) strcat(buff, " A_NS16K");
+ else if (ep->a_cpu == A_I80386) strcat(buff, " A_I80386");
+ else if (ep->a_cpu == A_SPARC) strcat(buff, " A_SPARC");
+ else strcat(buff, " UNKNOWN");
+ fprintf(stdout, "%s\n", buff);
+
+ fprintf(stdout, "Byte order is: %s\n",
+ A_BLR(ep->a_cpu) ? "left to right" : "right to left");
+ fprintf(stdout, "Word order is: %s\n",
+ A_WLR(ep->a_cpu) ? "left to right" : "right to left");
+
+ fprintf(stdout, "Header length is: 0x%02x\n", ep->a_hdrlen);
+ fprintf(stdout, "Reserved byte is: 0x%02x\n", ep->a_unused);
+ fprintf(stdout, "Version stamp is: 0x%04x\n", ep->a_version);
+ fprintf(stdout, "Size of text segment is: 0x%08.8x\n", ep->a_text);
+ fprintf(stdout, "Size of data segment is: 0x%08.8x\n", ep->a_data);
+ fprintf(stdout, "Size of bss segment is: 0x%08.8x\n", ep->a_bss);
+ fprintf(stdout, "Entry point is: 0x%08.8x\n", ep->a_entry);
+ fprintf(stdout, "Total memory allocated is: 0x%08.8x\n", ep->a_total);
+ fprintf(stdout, "Size of symbol table is: 0x%08.8x bytes, %d entries\n",
+ ep->a_syms, ep->a_syms / sizeof(struct nlist));
+
+ /* SHORT FORM ENDS HERE */
+#if 0
+ fprintf(stdout, "Size of text relocation is 0x%08.8x\n", ep->a_trsize);
+ fprintf(stdout, "Size of data relocation is 0x%08.8x\n", ep->a_drsize);
+ fprintf(stdout, "Base of text relocation is 0x%08.8x\n", ep->a_tbase);
+ fprintf(stdout, "Base of data relocation is 0x%08.8x\n", ep->a_dbase);
+#endif
+
+ return(OK);
+}
+
+
+/*
+ * d u m p _ a d a t a
+ *
+ * Dump an a.out data section.
+ *
+ * Returns: OK Success
+ * FAILED File read failure, invalid arguments
+ *
+ * The a_hdrbuf structure is read to determine section addresses.
+ * The a_symtab structure is read to determine symbol names (if available).
+ */
+int dump_adata(FILE *fp, int start, int count)
+{
+ char label[S_BUFF_LEN], data[S_BUFF_LEN], buff[BUFF_LEN];
+ char *hex = "0123456789ABCDEF";
+ int j, k, newflg, index, last, status, found, quit;
+ long int addr;
+ unsigned long int ulj;
+ struct locname *np;
+
+ if (start < 0 || (start + count) > (A_SYMPOS(a_hdrbuf) - a_hdrbuf.a_hdrlen))
+ return(FAILED);
+
+ ulj = start;
+ quit = FALSE;
+ status = OK;
+ for (addr = start ; addr < (start + count) ; addr += 16) {
+ /* get a line's worth of data */
+ for (j = 0 ; j < 16 ; j++) {
+ if (j == (start + count - addr)) {
+ quit = TRUE;
+ break;
+ }
+ if ((k = fgetc(fp)) == EOF) {
+ status = FAILED;
+ quit = TRUE;
+ break;
+ }
+ data[j] = (char)k;
+ }
+
+ /* adjust for an unexpected EOF */
+ if (quit && status == FAILED) {
+ if (j == 0)
+ break;
+ else
+ j--;
+ }
+ last = j;
+
+ /* write out the address and clear the rest of the buffer */
+ sprintf(buff, "%06lx", ulj);
+ for (k = strlen(buff) ; k < BUFF_MAX ; k++)
+ buff[k] = ' ';
+
+ /* build the hex and ascii data representations */
+ newflg = TRUE;
+ found = FALSE;
+ for (j = 0 ; j < last ; j++ ) {
+
+ /* find a local symbol, one per address */
+ for (np = locsym[DATA] ; !found && np != (struct locname *)NULL ;
+ np = np->l_next) {
+ if (ulj == np->l_value) {
+ /* write out any outstanding data */
+ if (j != 0) {
+ buff[75] = '\0';
+ fprintf(stdout, "%s\n", buff);
+ for (k = 8 ; k < 75 ; k++)
+ buff[k] = ' ';
+ }
+ /* write out the symbol name */
+ for (k = 0 ; k < 8 ; k++)
+ label[k] = np->l_name[k];
+ label[k] = '\0';
+ fprintf(stdout, "%s\n", label);
+ found = TRUE;
+ }
+ }
+
+ /* find any global symbols, several per address */
+ while (!found && (index = find_asym(ulj, N_DATA)) != -1) {
+ /* for the first symbol, write out any outstanding data */
+ if (newflg && j != 0) {
+ buff[75] = '\0';
+ fprintf(stdout, "%s\n", buff);
+ for (k = 8 ; k < 75 ; k++)
+ buff[k] = ' ';
+ newflg = FALSE;
+ }
+ /* write out the symbol name */
+ for (k = 0 ; k < 8 ; k++)
+ label[k] = a_symtab[index].n_name[k];
+ label[k] = '\0';
+ /* for some reason, some table entries are empty */
+ if (label[0] != '\0') fprintf(stdout, "%s\n", label);
+ }
+
+ /* set up for the next pass */
+ newflg = TRUE;
+ found = FALSE;
+ ulj++;
+ /* hex digits */
+ buff[8 + (3 * j) + (j < 8 ? 0 : 2)] = hex[(data[j] >> 4) & 0x0f];
+ buff[9 + (3 * j) + (j < 8 ? 0 : 2)] = hex[data[j] & 0x0f];
+ /* ascii conversion */
+ if (data[j] < 32 || data[j] > 127)
+ buff[59 + j] = '.';
+ else
+ buff[59 + j] = data[j];
+ if (j == 8)
+ buff[32] = '-';
+ }
+ buff[75] = '\0';
+
+ /* write out the result */
+ fprintf(stdout, "%s\n", buff);
+
+ if (quit) break;
+ }
+
+ return(status);
+}
+
+
+/*
+ * d u m p _ a s y m
+ *
+ * Dump an a.out file symbol table.
+ *
+ * Returns: OK Success
+ * FAILED Invalid arguments
+ *
+ * The a_hdrbuf structure is read to determine section addresses.
+ */
+int dump_asym(struct nlist *np, int start, int count)
+{
+ char buff[BUFF_LEN], data[S_BUFF_LEN];
+ unsigned char uc;
+ int j, k;
+
+ if (start < 0 || (start + count) > (a_hdrbuf.a_syms / sizeof(struct nlist)))
+ return(FAILED);
+
+ for (j = start ; j < (start + count) ; j++) {
+ sprintf(buff, "%-4d ", j);
+ for (k = 0 ; k < SYMLEN ; k++)
+ data[k] = (np[j].n_name[k] == '\0') ? ' ' : np[j].n_name[k];
+ data[k] = '\0';
+ strcat(buff, data);
+ sprintf(data, " Val: 0x%08x", np[j].n_value);
+ strcat(buff, data);
+ sprintf(data, " Sto: 0x%02x", np[j].n_sclass);
+ strcat(buff, data);
+ uc = np[j].n_sclass;
+ if ((uc & N_SECT) == N_UNDF) strcat(buff, " N_UNDF");
+ else if ((uc & N_SECT) == N_ABS) strcat(buff, " N_ABS ");
+ else if ((uc & N_SECT) == N_TEXT) strcat(buff, " N_TEXT");
+ else if ((uc & N_SECT) == N_DATA) strcat(buff, " N_DATA");
+ else if ((uc & N_SECT) == N_BSS) strcat(buff, " N_BSS ");
+ else if ((uc & N_SECT) == N_COMM) strcat(buff, " N_COMM");
+ else strcat(buff, " UNKNOWN");
+ if ((uc & N_CLASS) == 0) strcat(buff, " C_NULL");
+ else if ((uc & N_CLASS) == C_EXT) strcat(buff, " C_EXT ");
+ else if ((uc & N_CLASS) == C_STAT) strcat(buff, " C_STAT");
+ else strcat(buff, " UNKNOWN");
+ sprintf(data, " Aux: 0x%02x", np[j].n_numaux);
+ strcat(buff, data);
+ sprintf(data, " Typ: 0x%04x", np[j].n_type);
+ strcat(buff, data);
+ fprintf(stdout, "%s\n", buff);
+ }
+
+ return(OK);
+}
+
+
+/*
+ * d u m p _ h e x
+ *
+ * Dump bytes in hex and ascii.
+ *
+ * Returns: OK Success
+ * FAILED File read failure, invalid arguments
+ */
+int dump_hex(FILE *fp, int start, int count)
+{
+ char c, buff[S_BUFF_LEN];
+ int j, k, status, quit, last;
+ unsigned long int ulj;
+
+ if (start < 0)
+ return(FAILED);
+
+ ulj = 0;
+ quit = FALSE;
+ status = OK;
+ while (TRUE) {
+ /* get 16 bytes of data */
+ for (j = 0 ; j < 16 ; j++) {
+ if ((k = fgetc(fp)) == EOF) {
+ quit = TRUE;
+ break;
+ }
+ else
+ buff[j] = (char)k;
+ }
+
+ /* set up to dump any remaining data */
+ if (quit) {
+ status = FAILED;
+ if (j == 0)
+ break;
+ else
+ j--;
+ }
+ last = j;
+
+ /* print the address */
+ fprintf(stdout, "%06lx ", start + ulj);
+ ulj += 16;
+ if (ulj >= count) {
+ quit = TRUE;
+ if (last == 16)
+ last = (count - 1) % 16;
+ }
+
+ /* print a line of hex data */
+ for (j = 0 ; j < 16 ; j++ ) {
+ if (j <= last)
+ fprintf(stdout, " %02x", buff[j] & 0xff);
+ else
+ fprintf(stdout, " ");
+ if (j == 7)
+ fprintf(stdout, " -");
+ }
+
+ /* print a trailer of ascii data */
+ fprintf(stdout, " ");
+ for (j = 0 ; j < 16 ; j++ ) {
+ if (j <= last)
+ c = buff[j];
+ else
+ c = ' ';
+ if (c < 32 || c > 127)
+ c = '.';
+ (void) fputc(c, stdout);
+ }
+
+ fprintf(stdout, "\n");
+ if (quit)
+ break;
+ }
+
+ return(status);
+}
+
+
+/*
+ * f i n d _ a s y m
+ *
+ * Find an a.out symbol index in a sorted list.
+ * There may be several symbols with the same value:
+ * return the first in the sequence.
+ *
+ * Returns: index Success
+ * -1 Failure
+ *
+ * The a_sectab structure is read to determine section indices.
+ * The a_symtab structure is read to determine symbol names.
+ */
+int find_asym(long value, int sec)
+{
+ static int index = 0;
+ static long oldval = 0;
+ static int oldsec = 0;
+ int j;
+
+ /* check for a repeated search */
+ if (value != oldval || sec != oldsec) {
+ oldval = value;
+ oldsec = sec;
+ index = a_sectab[sec].first;
+ }
+ /* never happen */
+ else if (index == -1)
+ return(FAILED);
+
+ /* do a linear search for a symbol, since repeated searches may be needed */
+ for (j = index ; j < a_sectab[sec].last ; j++) {
+ if (value == a_symtab[j].n_value)
+ break;
+ }
+
+ /* set up the index for the next pass */
+ if (j == a_sectab[sec].last) {
+ index = a_sectab[sec].first;
+ return(-1);
+ }
+ else {
+ index = j + 1;
+ return(j);
+ }
+ /* NOTREACHED */
+}
+
+
+/*
+ * g e n _ l o c s y m
+ *
+ * Generate local symbols.
+ *
+ * Returns: OK Success
+ * FAILED Invalid arguments, malloc failure
+ *
+ * This works only for data and bss segments. Text symbols need
+ * a disassembly of the text section, and intelligent guesses as
+ * to whether a local address refers to text or data. In fact,
+ * this routine is hardwired to the data area, and the bss area
+ * is ignored.
+ */
+int gen_locsym(FILE *fp, int sec)
+{
+ char data[20];
+ int j, txtflg, hdrflg;
+ long int addrcount;
+ struct locname *np, *current;
+
+ /* check that all offsets are valid - this routine won't work for text */
+ if (sec < ROM || sec > BSS) {
+ fprintf(stderr, "Invalid section %s\n", a_sectab[sec & 7].name);
+ return(FAILED);
+ }
+
+ /* initialise the label string */
+ strncpy(data, ".DAT", 4);
+ data[4] = '\0';
+
+ /* initialise the in-memory local name table pointers */
+ current = (struct locname *)(NULL);
+
+ /* read the data area and load the symbols */
+ (void) fseek(aoutfp, A_DATAPOS(a_hdrbuf), SEEK_SET);
+ addrcount = 0;
+ txtflg = hdrflg = FALSE;
+ while (addrcount < a_hdrbuf.a_data) {
+ j = fgetc(fp);
+ if (j < 040 || j > 0177) {
+ txtflg = FALSE;
+ hdrflg = FALSE;
+ }
+ else
+ txtflg = TRUE;
+
+ /* ensure that the start of each apparent string has a related symbol */
+ if (txtflg && !hdrflg) {
+ if (find_asym(addrcount, sec) == -1) {
+ /* if malloc fails, just collapse */
+ if ((np = (struct locname *)malloc(sizeof(struct locname)))
+ == (struct locname *)NULL) {
+ fprintf(stderr, "%s: malloc failed\n", progname);
+ return(FAILED);
+ }
+ /* update the current record */
+ sprintf(np->l_name, "%s%04x", data,
+ (a_hdrbuf.a_text + addrcount) & 0xffff);
+ /* nb. must follow l_name update */
+ if (sec == TEXT) np->l_sclass = S_TEXT & 0xff;
+ else if (sec == ROM) np->l_sclass = S_DATA & 0xff;
+ else if (sec == DATA) np->l_sclass = S_DATA & 0xff;
+ else if (sec == BSS) np->l_sclass = S_BSS & 0xff;
+ else sec = 0;
+ np->l_value = a_hdrbuf.a_text + addrcount;
+ np->l_next = (struct locname *)NULL;
+ /* and add it to the list */
+ if (current == (struct locname *)NULL)
+ locsym[sec] = np;
+ else
+ current->l_next = np;
+ current = np;
+ }
+ hdrflg = TRUE;
+ }
+ addrcount++;
+ }
+
+ return(OK);
+}
+
+
+/*
+ * i n i t _ a o u t
+ *
+ * Initialise the a.out file tables.
+ *
+ * Returns: OK Success
+ * FAILED File read failure
+ *
+ * The a_hdrbuf and a_symtab and a_sectab structures are
+ * all initialised here. Also, the ability to read the
+ * entire file is checked; no read checking is done
+ * later in the program.
+ */
+int init_aout(FILE *fp)
+{
+ char *cp;
+ int j, k, maxsym;
+ struct nlist *np;
+ struct nlist ntmp;
+
+ /* load the header into memory for fast access.
+ * the header length is the fifth byte of the header.
+ */
+ cp = (char *)&a_hdrbuf;
+ if (fread(cp, sizeof(char), 5, aoutfp) != 5) {
+ fprintf(stderr, "Cannot read executable header.\n");
+ return(FAILED);
+ }
+ j = cp[4] - 5;
+ cp += 5;
+ if (fread(cp, sizeof(char), j, aoutfp) != j) {
+ fprintf(stderr, "Cannot read executable header.\n");
+ return(FAILED);
+ }
+ if(BADMAG(a_hdrbuf)) {
+ fprintf(stderr, "%s: bad magic number.\n", progname);
+ return(FAILED);
+ }
+
+ /* check that the whole file can be read */
+ if (fseek(aoutfp, A_SYMPOS(a_hdrbuf) + a_hdrbuf.a_syms, SEEK_SET) != 0) {
+ fprintf(stderr, "%s: cannot seek to end of file.\n", progname);
+ return(FAILED);
+ }
+
+ /* load the symbol table into memory for fast access */
+ a_symtab = (struct nlist *)NULL;
+ if (a_hdrbuf.a_syms != 0) {
+ /* get space for the nlist data */
+ if ((cp = (char *)malloc(a_hdrbuf.a_syms)) == (char *)NULL) {
+ fprintf(stderr, "%s: malloc failed\n", progname);
+ return(FAILED);
+ }
+ if (fseek(aoutfp, -a_hdrbuf.a_syms, SEEK_CUR) != 0) {
+ fprintf(stderr, "%s: cannot seek to symbol area.\n", progname);
+ return(FAILED);
+ }
+ /* load the symbols into a sorted list */
+ np = (struct nlist *)cp;
+ maxsym = 0;
+ for (j = 0 ; j < a_hdrbuf.a_syms / sizeof(struct nlist) ; j++) {
+ if (fread(&ntmp, sizeof(struct nlist), 1, aoutfp) != 1) {
+ fprintf(stderr, "%s: cannot read symbol area.\n", progname);
+ return(FAILED);
+ }
+ /* insertion sort, by class and value */
+ for (k = maxsym ; k > 0 ; k--) {
+ if ((ntmp.n_sclass & N_SECT) < (np[k-1].n_sclass & N_SECT))
+ np[k] = np[k - 1];
+ else if ((ntmp.n_sclass & N_SECT) == (np[k-1].n_sclass & N_SECT) &&
+ ntmp.n_value < np[k-1].n_value)
+ np[k] = np[k - 1];
+ else
+ break;
+ }
+ np[k] = ntmp;
+ maxsym++;
+ }
+ /* finally, we have a valid symbol table */
+ a_symtab = (struct nlist *)cp;
+
+ /* update the symbol section index list */
+ a_sectab[a_symtab[0].n_sclass & N_SECT].first = 0;
+ for (j = 1 ; j < (a_hdrbuf.a_syms / sizeof(struct nlist)) ; j++) {
+ if ((a_symtab[j].n_sclass & N_SECT) != (a_symtab[j-1].n_sclass & N_SECT)) {
+ a_sectab[a_symtab[j-1].n_sclass & N_SECT].last = j - 1;
+ a_sectab[a_symtab[j-1].n_sclass & N_SECT].total =
+ j - a_sectab[a_symtab[j-1].n_sclass & N_SECT].first;
+ a_sectab[a_symtab[j].n_sclass & N_SECT].first = j;
+ }
+ }
+ a_sectab[a_symtab[j-1].n_sclass & N_SECT].last = j - 1;
+
+ /* build the local symbol tables */
+ for (j = 0 ; j < MAXSECT ; j++)
+ locsym[j] = (struct locname *)NULL;
+
+ /* build the local .text symbol table */
+ /* ### full disassembly ? */
+
+ /* build the local data symbol table */
+ if (gen_locsym(fp, DATA) == FAILED)
+ return(FAILED);
+ }
+
+ return(OK);
+}
+
+
+/*
+ * m a i n
+ *
+ * Main routine of dis_a386.
+ */
+int main(int argc, char *argv[])
+{
+ char *cp, binfile[BUFF_LEN], symbfile[BUFF_LEN];
+ int j, errors;
+ unsigned long int addrfirst, addrlast, addrcount;
+ struct stat statbuff;
+
+ /* initial set up */
+ if ((cp = strrchr(argv[0], PSEP)) == (char *)NULL)
+ cp = argv[0];
+ else
+ cp++;
+ strncpy(progname, cp, BUFF_MAX);
+ strncpy(binfile, AOUT, BUFF_MAX);
+ addrfirst = addrlast = addrcount = 0;
+
+ /* check for an MSDOS-style option */
+ if (argc == 2 && argv[1][0] == '/') {
+ usage();
+ exit(0);
+ }
+
+ /* parse arguments */
+ errors = opterr = 0;
+ while ((j = getopt(argc, argv, "E:abdf:hl:stx:")) != EOF) {
+ switch (j & 0177) {
+#if 0
+ case 'C': /* core file name */
+ opt_C = TRUE;
+ if (optarg != (char *)NULL)
+ strncpy(binfile, optarg, BUFF_MAX);
+ else
+ errors++;
+ break;
+#endif
+ case 'E': /* executable file name */
+ opt_E = TRUE;
+ if (optarg != (char *)NULL)
+ strncpy(binfile, optarg, BUFF_MAX);
+ else
+ errors++;
+ break;
+#if 0
+ case 'O': /* object file name */
+ opt_O = TRUE;
+ if (optarg != (char *)NULL)
+ strncpy(binfile, optarg, BUFF_MAX);
+ else
+ errors++;
+ break;
+ case 'S': /* symbol table name */
+ opt_S = TRUE;
+ if (optarg != (char *)NULL)
+ strncpy(symbfile, optarg, BUFF_MAX);
+ else
+ errors++;
+ break;
+#endif
+ case 'a': /* dump tables and disassemble segments */
+ opt_a = TRUE;
+ break;
+ case 'b': /* dump straight binary */
+ opt_b = TRUE;
+ break;
+ case 'd': /* dump the data segment */
+ opt_d = TRUE;
+ break;
+ case 'f': /* first address of dump */
+ opt_f = TRUE;
+ if (optarg != (char *)NULL)
+ addrfirst = atoaddr(optarg);
+ else
+ errors++;
+ break;
+ case 'h': /* dump the header */
+ opt_h = TRUE;
+ break;
+ case 'l': /* last address of dump */
+ opt_l = TRUE;
+ if (optarg != (char *)NULL)
+ addrlast = atoaddr(optarg);
+ else
+ errors++;
+ break;
+#if 0
+ case 'm': /* dump the rom segment */
+ opt_m = TRUE;
+ break;
+ case 'n': /* dump the symbol names */
+ opt_n = TRUE;
+ break;
+ case 'r': /* dump the relocation structures */
+ opt_r = TRUE;
+ break;
+#endif
+ case 's': /* dump the symbol table */
+ opt_s = TRUE;
+ break;
+ case 't': /* dump the text segment */
+ opt_t = TRUE;
+ break;
+#if 0
+ case 'u': /* dump the bss segment */
+ opt_u = TRUE;
+ break;
+#endif
+ case 'x': /* debugging flag */
+ opt_x = TRUE;
+ if (optarg != (char *)NULL)
+ dbglvl = atoi(optarg);
+ break;
+ case '?':
+ default:
+ usage();
+ exit(1);
+ break;
+ }
+ }
+
+ /* check the flags */
+ if (errors > 0) {
+ usage();
+ exit(1);
+ }
+ if (opt_a && (opt_d || opt_h || opt_s || opt_t)) {
+ usage();
+ exit(1);
+ }
+ if ((opt_f || opt_l) && (addrlast != 0 && addrfirst > addrlast)) {
+ usage();
+ exit(1);
+ }
+
+ /* check for a specific input file */
+ if (optind < argc)
+ strncpy(binfile, argv[optind], BUFF_MAX);
+
+ /* we must have a binary file of some sort */
+ if ((aoutfp = fopen(binfile, "rb")) == (FILE *)NULL ||
+ stat(binfile, &statbuff) == -1) {
+ perror(binfile);
+ exit(1);
+ }
+
+ /* initialise the a.out data structures */
+ if (init_aout(aoutfp) == FAILED) {
+ perror(binfile);
+ exit(1);
+ }
+
+ /* show the output file name and date */
+ fprintf(stdout, "File name: %s\nFile date: %s",
+ binfile, ctime(&statbuff.st_ctime));
+
+ /* show the header section - default behaviour */
+ if (opt_a || opt_h || (!opt_d && !opt_s && !opt_t)) {
+ fprintf(stdout, "\nHeader data:\n");
+ (void) dump_ahdr(&a_hdrbuf);
+ }
+
+ /* dump the data section */
+ if (opt_d && opt_b) {
+ /* check that all offsets are valid */
+ if (addrfirst > a_hdrbuf.a_data || addrlast > a_hdrbuf.a_data) {
+ fprintf(stderr, "Invalid data address range 0x%08.8lu to 0x%08.8lu\n",
+ addrfirst, addrlast);
+ }
+ else {
+ addrcount = (addrlast == 0) ? a_hdrbuf.a_data : addrlast;
+ addrcount -= addrfirst;
+ (void) fseek(aoutfp, A_DATAPOS(a_hdrbuf) + addrfirst, SEEK_SET);
+ fprintf(stdout, "\nData:\n");
+ (void) dump_hex(aoutfp, A_DATAPOS(a_hdrbuf) - a_hdrbuf.a_hdrlen + addrfirst,
+ addrcount);
+ }
+ }
+
+ /* disassemble the data section */
+ if (opt_a || (opt_d && !opt_b)) {
+ /* check that all offsets are valid */
+ if (addrfirst > a_hdrbuf.a_data || addrlast > a_hdrbuf.a_data) {
+ fprintf(stderr, "Invalid data address range 0x%08.8lu to 0x%08.8lu\n",
+ addrfirst, addrlast);
+ }
+ else {
+ addrcount = (addrlast == 0) ? a_hdrbuf.a_data : addrlast;
+ addrcount -= addrfirst;
+ (void) fseek(aoutfp, A_DATAPOS(a_hdrbuf) + addrfirst, SEEK_SET);
+ fprintf(stdout, "\nDisassembled data:\n");
+ (void) dump_adata(aoutfp, A_DATAPOS(a_hdrbuf) - a_hdrbuf.a_hdrlen
+ + addrfirst, addrcount);
+ }
+ }
+
+ /* dump the text section */
+ if (opt_t && opt_b) {
+ /* check that all offsets are valid */
+ if (addrfirst > a_hdrbuf.a_text || addrlast > a_hdrbuf.a_text) {
+ fprintf(stderr, "Invalid text address range 0x%08.8lu to 0x%08.8lu\n",
+ addrfirst, addrlast);
+ }
+ else {
+ addrcount = (addrlast == 0) ? a_hdrbuf.a_text : addrlast;
+ addrcount -= addrfirst;
+ (void) fseek(aoutfp, A_TEXTPOS(a_hdrbuf) + addrfirst, SEEK_SET);
+ fprintf(stdout, "\nText:\n");
+ (void) dump_hex(aoutfp, A_TEXTPOS(a_hdrbuf) - a_hdrbuf.a_hdrlen
+ + addrfirst, addrcount);
+ }
+ }
+
+ /* disassemble the text section */
+ if (opt_a || (opt_t && !opt_b)) {
+ /* check that all offsets are valid */
+ if (addrfirst > a_hdrbuf.a_text || addrlast > a_hdrbuf.a_text) {
+ fprintf(stderr, "Invalid text address range 0x%08.8lu to 0x%08.8lu\n",
+ addrfirst, addrlast);
+ }
+ else {
+ addrcount = (addrlast == 0) ? a_hdrbuf.a_text : addrlast;
+ addrcount -= addrfirst;
+ disfp = aoutfp; /* file to be disassembled */
+ objfp = (FILE *)NULL; /* without relocation information */
+ (void) fseek(disfp, A_TEXTPOS(a_hdrbuf) + addrfirst, SEEK_SET);
+ fprintf(stdout, "\nDisassembled text:\n");
+ (void) dasm(addrfirst, addrcount);
+ }
+ }
+
+ /* show the symbol data */
+ if (opt_a || opt_s) {
+ fprintf(stdout, "\nSymbol data:\n");
+ if (a_hdrbuf.a_syms == 0)
+ fprintf(stdout, "No symbol table available.\n");
+ else
+ (void) dump_asym(a_symtab, 0, a_hdrbuf.a_syms / sizeof(struct nlist));
+ }
+
+ /* wrap up */
+ (void) fclose(aoutfp);
+
+ exit(0);
+ /* NOTREACHED */
+}
+
+
+/*
+ * u s a g e
+ *
+ * Usage message.
+ *
+ * Returns: Nothing Always
+ */
+void usage()
+{
+ fprintf(stderr, "Usage: %s [-a|-dhst] [-b] [-f #] [-l #] [-E executable]\n",
+ progname);
+}
+
+/*
+ * EOF
+ */
+
--- /dev/null
+/*
+ * dis_o386: disassemble 386 object files.
+ *
+ * $Id: diso.c,v 1.1 1997/10/20 12:00:00 cwr Exp cwr $
+ *
+ * Written by C W Rose.
+ */
+
+/* Version settings */
+#define MINIX
+#undef OS2
+#undef TEST
+
+#ifdef MINIX
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <minix/config.h>
+#include <minix/const.h>
+#include <a.out.h>
+#include <ansi.h>
+#include <assert.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#undef S_ABS /* used in a.out.h */
+#include "out.h" /* ACK compiler output header */
+#undef EXTERN
+#define EXTERN
+#include "dis386.h" /* dis386 header */
+#endif
+
+#ifdef OS2
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include </local/minix/minix/config.h>
+#include </local/minix/minix/const.h>
+#include </local/minix/a.out.h>
+#include </local/minix/ansi.h>
+
+#include <assert.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <io.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#undef S_ABS /* used in a.out.h */
+#include "out.h" /* ACK compiler output header */
+#undef EXTERN
+#define EXTERN
+#include "dis386.h" /* dis386 header */
+#endif
+
+/* Standard defines */
+#define FALSE 0
+#undef TRUE
+#define TRUE !FALSE
+#define FAILED -1
+#define MAYBE 0
+#define OK 1
+#define SAME 0
+
+/* Local defines */
+#define L_BUFF_LEN 1024
+#define BUFF_LEN 256
+#define S_BUFF_LEN 20
+#define L_BUFF_MAX (L_BUFF_LEN-1)
+#define BUFF_MAX (BUFF_LEN-1)
+#define S_BUFF_MAX (S_BUFF_LEN-1)
+#define PSEP '\\'
+
+#define AOUT "a.out" /* useful default file names */
+#define CORE "core"
+#define OBJF "test.o"
+#define STAB "symbol.tab"
+#define LINE_LEN 16
+#define SYMLEN 8
+
+#define TEXT 0 /* section indices for locsym[] */
+#define ROM 1
+#define DATA 2
+#define BSS 3
+
+#ifndef lint
+static char *Version = "@(#) dis_o386.c $Revision: 1.1 $ $Date: 1997/10/20 12:00:00 $";
+#endif
+
+/* Global variables */
+int opt_C = FALSE; /* core file name */
+int opt_E = FALSE; /* executable file name */
+int opt_O = FALSE; /* object file name */
+int opt_S = FALSE; /* symbol table name */
+int opt_a = FALSE; /* dump tables and disassemble segments */
+int opt_b = FALSE; /* dump straight binary */
+int opt_d = FALSE; /* dump the data segment */
+int opt_f = FALSE; /* first address of dump */
+int opt_h = FALSE; /* dump the header structure */
+int opt_l = FALSE; /* last address of dump */
+int opt_m = FALSE; /* dump the rom segment */
+int opt_n = FALSE; /* dump the symbol names */
+int opt_r = FALSE; /* dump the relocation structures */
+int opt_s = FALSE; /* dump the symbol table */
+int opt_t = FALSE; /* dump the text segment */
+int opt_u = FALSE; /* dump the bss segment */
+int opt_x = FALSE; /* debugging flag */
+
+char progname[BUFF_LEN]; /* program name */
+int dbglvl = 0; /* debugging level */
+
+/* Forward declarations */
+/* _PROTOTYPE(void usage, (void)); */
+unsigned long int atoaddr(char *sp); /* Convert ascii hex/dec to ulong */
+int dump_hex(FILE *fp, long s, long n); /* Dump bytes in hex and ascii */
+int dump_odata(FILE *fp, long s, long n, int sec); /* Dump object file data section */
+int dump_ohdr(struct outhead *ph); /* Dump object file header */
+int dump_orel(FILE *fp, long s, long n); /* Dump object file relocation section */
+int dump_osec(long b, long e, int sec, int flg); /* Dump object file section */
+int dump_oshdr(FILE *fp, long s, long n); /* Dump object file section headers */
+int dump_ostr(FILE *fp, long s, long n); /* Dump object file string data */
+int dump_osym(FILE *fp, long s, long n); /* Dump object file symbol table data */
+int find_osym(long val, int sec); /* Find object file symbol index */
+int gen_locsym(FILE *fp, int sec); /* Generate local symbols */
+int getstruct(FILE *fp, char *bp, char *s); /* Get values from the input file */
+int init_objf(FILE *fp); /* Initialise object file tables */
+void usage(void); /* Usage message */
+
+
+/*
+ * a t o a d d r
+ *
+ * Convert ascii hex/dec to unsigned long.
+ *
+ * Returns: Conversion result Always
+ */
+unsigned long int atoaddr(char *sp)
+{
+ char c, *cp, buff[S_BUFF_LEN];
+ int j;
+ unsigned long int result = 0;
+
+ /* flip to upper */
+ for (j = 0 ; j < S_BUFF_MAX && *(sp + j) != '\0' ; j++)
+ buff[j] = toupper(*(sp + j));
+ buff[j] = '\0';
+
+ /* lose leading whitespace */
+ cp = buff;
+ while isspace(*cp)
+ cp++;
+
+ /* check for hexadecimal entry */
+ if (*cp == '0' && *(cp + 1) == 'X') {
+ cp += 2;
+ while (isxdigit(*cp)) {
+ c = *cp++;
+ j = (c < 'A') ? c - '0' : c - 'A' + 10;
+ result = (result << 4) + (c < 'A' ? c - '0' : c - 'A' + 10);
+ }
+ }
+ else
+ result = atol(buff);
+
+ return result;
+}
+
+
+/*
+ * d u m p _ h e x
+ *
+ * Dump bytes in hex and ascii.
+ *
+ * Returns: OK Success
+ * FAILED File read failure, invalid arguments
+ */
+int dump_hex(FILE *fp, long start, long count)
+{
+ char c, buff[S_BUFF_LEN];
+ int j, k, status, quit, last;
+ unsigned long int ulj;
+
+ if (start < 0)
+ return(FAILED);
+
+ ulj = 0;
+ quit = FALSE;
+ status = OK;
+ while (TRUE) {
+ /* get 16 bytes of data */
+ for (j = 0 ; j < 16 ; j++) {
+ if ((k = fgetc(fp)) == EOF) {
+ quit = TRUE;
+ break;
+ }
+ else
+ buff[j] = (char)k;
+ }
+
+ /* set up to dump any remaining data */
+ if (quit) {
+ status = FAILED;
+ if (j == 0)
+ break;
+ else
+ j--;
+ }
+ last = j;
+
+ /* print the address */
+ fprintf(stdout, "%06lx ", start + ulj);
+ ulj += 16;
+ if (ulj >= count) {
+ quit = TRUE;
+ if (last == 16)
+ last = (count - 1) % 16;
+ }
+
+ /* print a line of hex data */
+ for (j = 0 ; j < 16 ; j++ ) {
+ if (j <= last)
+ fprintf(stdout, " %02x", buff[j] & 0xff);
+ else
+ fprintf(stdout, " ");
+ if (j == 7)
+ fprintf(stdout, " -");
+ }
+
+ /* print a trailer of ascii data */
+ fprintf(stdout, " ");
+ for (j = 0 ; j < 16 ; j++ ) {
+ if (j <= last)
+ c = buff[j];
+ else
+ c = ' ';
+ if (c < 32 || c > 127)
+ c = '.';
+ fputc(c, stdout);
+ }
+
+ fprintf(stdout, "\n");
+ if (quit)
+ break;
+ }
+
+ return(status);
+}
+
+
+/*
+ * d u m p _ o d a t a
+ *
+ * Dump object file data section.
+ *
+ * Returns: OK Success
+ * FAILED File read failure, invalid arguments
+ *
+ * The o_hdrbuf and o_sectab structures are read to determine section addresses.
+ * The o_symtab and o_strtab structures are read to determine symbol names.
+ */
+int dump_odata(FILE *fp, long start, long count, int sec)
+{
+ char label[S_BUFF_LEN], data[S_BUFF_LEN], buff[BUFF_LEN];
+ char *hex = "0123456789ABCDEF";
+ int j, k, newflg, index, last, status, found, quit;
+ long int lj, addr;
+ unsigned long int ulj;
+ struct locname *np;
+
+ if (start < 0 || (start + count) > o_sectab[sec].os_flen)
+ return(FAILED);
+
+ ulj = start;
+ quit = FALSE;
+ status = OK;
+ for (addr = start ; addr < (start + count) ; addr += 16) {
+ /* get a line's worth of data */
+ for (j = 0 ; j < 16 ; j++) {
+ if (j == (start + count - addr)) {
+ quit = TRUE;
+ break;
+ }
+ if ((k = fgetc(fp)) == EOF) {
+ status = FAILED;
+ quit = TRUE;
+ break;
+ }
+ data[j] = (char)k;
+ }
+
+ /* adjust for an unexpected EOF */
+ if (quit && status == FAILED) {
+ if (j == 0)
+ break;
+ else
+ j--;
+ }
+ last = j;
+
+ /* write out the address and clear the rest of the buffer */
+ sprintf(buff, "%06lx", ulj);
+ for (k = strlen(buff) ; k < BUFF_MAX ; k++)
+ buff[k] = ' ';
+
+ /* build the hex and ascii data representations */
+ newflg = TRUE;
+ found = FALSE;
+ for (j = 0 ; j < last ; j++ ) {
+
+ /* find a local symbol, one per address */
+ for (np = locsym[sec] ; !found && np != (struct locname *)NULL ;
+ np = np->l_next) {
+ if (ulj == np->l_value) {
+ /* write out any outstanding data */
+ if (j != 0) {
+ buff[75] = '\0';
+ fprintf(stdout, "%s\n", buff);
+ for (k = 8 ; k < 75 ; k++)
+ buff[k] = ' ';
+ }
+ /* write out the symbol name */
+ for (k = 0 ; k < 8 ; k++)
+ label[k] = np->l_name[k];
+ label[k] = '\0';
+ fprintf(stdout, "%s\n", label);
+ found = TRUE;
+ }
+ }
+
+ /* find any global symbols, several per address */
+ while (!found && (index = find_osym(ulj, sec)) != -1) {
+ /* for the first symbol, write out any outstanding data */
+ if (newflg && j != 0) {
+ buff[75] = '\0';
+ fprintf(stdout, "%s\n", buff);
+ for (k = 8 ; k < 75 ; k++)
+ buff[k] = ' ';
+ newflg = FALSE;
+ }
+ /* write out the symbol name */
+ lj = o_symtab[index].on_foff - (long)OFF_CHAR(o_hdrbuf);
+ for (k = 0 ; k < 8 ; k++)
+ label[k] = *(o_strtab + lj + k);
+ label[k] = '\0';
+ fprintf(stdout, "%s\n", label);
+ }
+
+ /* set up for the next pass */
+ newflg = TRUE;
+ found = FALSE;
+ ulj++;
+ /* hex digits */
+ buff[8 + (3 * j) + (j < 8 ? 0 : 2)] = hex[(data[j] >> 4) & 0x0f];
+ buff[9 + (3 * j) + (j < 8 ? 0 : 2)] = hex[data[j] & 0x0f];
+ /* ascii conversion */
+ if (data[j] < 32 || data[j] > 127)
+ buff[59 + j] = '.';
+ else
+ buff[59 + j] = data[j];
+ if (j == 8)
+ buff[32] = '-';
+ }
+ buff[75] = '\0';
+
+ /* write out the result */
+ fprintf(stdout, "%s\n", buff);
+
+ if (quit) break;
+ }
+
+ return(status);
+}
+
+
+/*
+ * d u m p _ o h d r
+ *
+ * Dump object file header data.
+ *
+ * Returns: OK Always
+ */
+int dump_ohdr(struct outhead *ph)
+{
+ char buff[BUFF_LEN];
+
+ sprintf(buff, "Magic number: 0x%04.4x", ph->oh_magic);
+ if (ph->oh_magic == O_MAGIC) strcat(buff, " O_MAGIC");
+ else strcat(buff, " UNKNOWN");
+ fprintf(stdout, "%s\n", buff);
+
+ fprintf(stdout, "Version stamp: 0x%04.4x\n", ph->oh_stamp);
+
+ sprintf(buff, "Format flags: 0x%04.4x", ph->oh_flags);
+ if (ph->oh_flags & HF_LINK) strcat(buff, " HF_LINK");
+ if (ph->oh_flags & HF_8086) strcat(buff, " HF_8086");
+ if (ph->oh_flags & ~(HF_LINK | HF_8086)) strcat(buff, " UNKNOWN");
+ fprintf(stdout, "%s\n", buff);
+
+ fprintf(stdout, "Number of sections: 0x%04.4x\n", ph->oh_nsect);
+ fprintf(stdout, "Number of relocations: 0x%04.4x\n", ph->oh_nrelo);
+ fprintf(stdout, "Number of symbols: 0x%04.4x\n", ph->oh_nname);
+ fprintf(stdout, "Sum of section sizes: 0x%08.8x\n", ph->oh_nemit);
+ fprintf(stdout, "Size of string area: 0x%08.8x\n", ph->oh_nchar);
+
+ return(OK);
+}
+
+
+/*
+ * d u m p _ o r e l
+ *
+ * Dump object file relocation data.
+ *
+ * Returns: OK Success
+ * FAILED Invalid arguments
+ *
+ * The o_hdrbuf and o_sectab structures are read to determine section addresses.
+ * The o_symtab and o_strtab structures are read to determine symbol values.
+ */
+int dump_orel(FILE *fp, long start, long count)
+{
+ char buff[BUFF_LEN], data[S_BUFF_LEN];
+ int j;
+ unsigned int uj;
+ long int lj;
+ struct outrelo relbuf;
+
+ if (start < 0 || (start + count) > o_hdrbuf.oh_nrelo)
+ return(FAILED);
+
+ for (j = 0 ; j < count ; j++) {
+ (void) getstruct(fp, (char *)&relbuf, SF_RELO);
+ sprintf(buff, "%04d Type:", j + start);
+ if (relbuf.or_type & RELO1) strcat(buff, " RELO1");
+ if (relbuf.or_type & RELO2) strcat(buff, " RELO2");
+ if (relbuf.or_type & RELO4) strcat(buff, " RELO4");
+ if (relbuf.or_type & RELPC) strcat(buff, " RELPC");
+ else strcat(buff, " ");
+ if (relbuf.or_type & RELBR) strcat(buff, " RELBR");
+ if (relbuf.or_type & RELWR) strcat(buff, " RELWR");
+ if (relbuf.or_type & ~(RELO1 | RELO2 | RELO4 | RELPC | RELBR | RELWR))
+ strcat(buff, "UNKNOWN");
+
+ strcat(buff, " Sect:");
+ uj = relbuf.or_sect & S_TYP;
+ if (uj >= S_MIN && uj <= S_MAX) {
+#if 1
+ /* use arbitrary names for Minix 386 */
+ sprintf(data, " %-5s", o_secnam[uj - S_MIN]);
+#else
+ sprintf(data, " 0x%02.2x", uj - S_MIN);
+#endif
+ strcat(buff, data);
+ }
+ /* S_UND is the empty S_TYP field */
+ if ((relbuf.or_sect & S_TYP) == S_UND) strcat(buff, " S_UND");
+ if ((relbuf.or_sect & S_TYP) == S_ABS) strcat(buff, " S_ABS");
+ if ((relbuf.or_sect & S_TYP) == S_CRS) strcat(buff, " S_CRS");
+
+ if ((relbuf.or_sect & S_EXT) == S_EXT) strcat(buff, " S_EXT");
+ else strcat(buff, " ");
+
+ if (relbuf.or_sect & ~(S_TYP | S_EXT))
+ strcat(buff, " UNKNOWN");
+
+ strcat(buff, " Symb:");
+ if (relbuf.or_nami < o_hdrbuf.oh_nname) {
+ lj = o_symtab[relbuf.or_nami].on_foff - (long)OFF_CHAR(o_hdrbuf);
+ /* check that addressing isn't messed up */
+ assert(lj >= 0 && lj < o_hdrbuf.oh_nchar);
+ /* name size is defined by SZ_NAME */
+ sprintf(data, "%-13s", o_strtab + lj);
+ }
+ else
+ sprintf(data, " 0x%04.4x", relbuf.or_nami);
+ strcat(buff, data);
+ strcat(buff, " Addr:");
+ sprintf(data, " 0x%08.8x", relbuf.or_addr);
+ strcat(buff, data);
+ fprintf(stdout, "%s\n", buff);
+
+#if 0
+ printf("Type Section Symbol Address\n");
+ printf("0x%02.2x 0x%02.2x 0x%04.4x 0x%08.8x\n",
+ relbuf.or_type, relbuf.or_sect,
+ relbuf.or_nami, relbuf.or_addr);
+#endif
+ }
+
+ return(OK);
+}
+
+
+/*
+ * d u m p _ o s e c
+ *
+ * Dump object file section.
+ *
+ * Returns: OK Success
+ * FAILED Invalid arguments
+ */
+int dump_osec(long addrfirst, long addrlast, int sec, int full)
+{
+ long int addrcount;
+
+ /* check that all offsets are valid */
+ addrcount = o_sectab[sec].os_flen;
+ if (addrfirst > o_sectab[sec].os_flen || addrlast > o_sectab[sec].os_flen) {
+ fprintf(stderr, "Invalid %s address range 0x%08.8lu to 0x%08.8lu\n",
+ o_secnam[sec], addrfirst, addrlast);
+ return(FAILED);
+ }
+ else {
+ if (opt_l)
+ addrcount = addrlast + 1;
+ addrcount = addrcount - addrfirst;
+ (void) fseek(objfp, o_sectab[sec].os_foff, SEEK_SET);
+ fprintf(stdout, "\n%s%s:\n", full ? "Disassembled " : "", o_secnam[sec]);
+ if (full)
+ (void) dump_odata(objfp, addrfirst, addrcount, sec);
+ else
+ (void) dump_hex(objfp, addrfirst, addrcount);
+ return(OK);
+ }
+ /* NOTREACHED */
+}
+
+
+/*
+ * d u m p _ o s h d r
+ *
+ * Dump object file section headers.
+ *
+ * Returns: OK Always
+ *
+ * The o_secnam structure is read to determine section names.
+ */
+int dump_oshdr(FILE *fp, long start, long count)
+{
+ int j;
+ struct outsect secbuf;
+
+ fprintf(stdout,
+ "Name Index Core start Core size File start File size Alignment\n");
+ for (j = 0 ; j < count ; j++) {
+ (void) getstruct(fp, (char *)&secbuf, SF_SECT);
+ if (j >= start)
+ fprintf(stdout, "%-13s %4.4d 0x%08.8x 0x%08.8x 0x%08.8x 0x%08.8x 0x%08.8x\n",
+ o_secnam[j], j, secbuf.os_base, secbuf.os_size, secbuf.os_foff,
+ secbuf.os_flen, secbuf.os_lign);
+ }
+
+ return(OK);
+}
+
+
+/*
+ * d u m p _ o s t r
+ *
+ * Dump object file string data.
+ *
+ * Returns: OK Success
+ * FAILED File read failure, invalid arguments
+ *
+ * The o_hdrbuf structure is read to determine section addresses.
+ */
+int dump_ostr(FILE *fp, long start, long count)
+{
+ int j, k;
+
+ if (start < 0 || count > o_hdrbuf.oh_nname)
+ return(FAILED);
+
+ /* we cannot precalculate the offset of a name record */
+ for (j = 0 ; j < count ; j++) {
+ fprintf(stdout, "%04d ", j + start);
+ do {
+ switch (k = fgetc(fp)) {
+ case EOF:
+ return(FAILED);
+ break;
+ case 0:
+ fprintf(stdout, "\n");
+ break;
+ default:
+ fprintf(stdout, "%c", k);
+ break;
+ }
+ } while (k);
+ }
+
+ return(OK);
+}
+
+
+/*
+ * d u m p _ o s y m
+ *
+ * Dump object file symbol table data.
+ *
+ * Returns: OK Success
+ * FAILED Invalid arguments
+ *
+ * The o_hdrbuf structure is read to determine section addresses.
+ * The o_strtab and o_secnam structures are read to determine symbol values.
+ */
+int dump_osym(FILE *fp, long start, long count)
+{
+ char buff[BUFF_LEN], data[S_BUFF_LEN];
+ int j;
+ unsigned int uj;
+ long lj;
+ struct outname nambuf;
+
+ if (start < 0 || (start + count) > o_hdrbuf.oh_nname)
+ return(FAILED);
+
+ for (j = 0 ; j < count ; j++) {
+ (void) getstruct(fp, (char *)&nambuf, SF_NAME);
+ sprintf(buff, "%4.4d", j + start);
+#if 1
+ lj = nambuf.on_foff - (long)OFF_CHAR(o_hdrbuf);
+ /* check that addressing isn't messed up */
+ assert(lj >= 0 && lj < o_hdrbuf.oh_nchar);
+ /* name size is defined by SZ_NAME */
+ sprintf(data, " %-13s", o_strtab + lj);
+ strcat(buff, data);
+#else
+ sprintf(data, " 0x%08.8x", nambuf.on_foff);
+ strcat(buff, data);
+#endif
+ strcat(buff, " Type:");
+ uj = nambuf.on_type & S_TYP;
+ if (uj >= S_MIN && uj <= S_MAX) {
+#if 1
+ /* use arbitrary names for Minix 386 */
+ sprintf(data, " %-5s", o_secnam[uj - S_MIN]);
+#else
+ sprintf(data, " 0x%02.2x", uj - S_MIN);
+#endif
+ strcat(buff, data);
+ }
+ /* S_UND is the empty S_TYP field */
+ if ((nambuf.on_type & S_TYP) == S_UND) strcat(buff, " S_UND");
+ if ((nambuf.on_type & S_TYP) == S_ABS) strcat(buff, " S_ABS");
+ if ((nambuf.on_type & S_TYP) == S_CRS) strcat(buff, " S_CRS");
+
+ if ((nambuf.on_type & S_EXT) == S_EXT) strcat(buff, " S_EXT");
+ else strcat(buff, " ");
+
+ if ((nambuf.on_type & S_ETC) == S_SCT) strcat(buff, " S_SCT");
+ if ((nambuf.on_type & S_ETC) == S_LIN) strcat(buff, " S_LIN");
+ if ((nambuf.on_type & S_ETC) == S_FIL) strcat(buff, " S_FIL");
+ if ((nambuf.on_type & S_ETC) == S_MOD) strcat(buff, " S_MOD");
+ if ((nambuf.on_type & S_ETC) == S_COM) strcat(buff, " S_COM");
+ if ((nambuf.on_type & S_ETC) == 0) strcat(buff, " ");
+
+ if (nambuf.on_type &
+ ~(S_TYP | S_EXT | S_SCT | S_LIN | S_FIL | S_MOD | S_COM))
+ strcat(buff, " UNKNOWN");
+
+#if 1
+ /* Desc is not used, so save space */
+ strcat(buff, " Desc: 0x00");
+#else
+ strcat(buff, " Desc:");
+ sprintf(data, " 0x%04.4x", nambuf.on_desc);
+ strcat(buff, data);
+#endif
+ strcat(buff, " Valu:");
+ sprintf(data, " 0x%08.8x", nambuf.on_valu);
+ strcat(buff, data);
+ fprintf(stdout, "%s\n", buff);
+ }
+#if 0
+ fprintf(stdout, "Name Type Debug Value\n");
+ fprintf(stdout, "0x%08.8x 0x%04.4x 0x%04.4x 0x%08.8x\n",
+ nambuf.on_u.on_off, nambuf.on_type,
+ nambuf.on_desc, nambuf.on_valu);
+#endif
+
+ return(OK);
+}
+
+
+/*
+ * f i n d _ o s y m
+ *
+ * Find an object file symbol name in a unsorted list.
+ *
+ * Returns: index Found
+ * -1 Not found
+ *
+ * There may be several symbols with the same value:
+ * return each of them on successive calls.
+ *
+ */
+int find_osym(long value, int sec)
+{
+ static int index = 0;
+ static long oldval = 0;
+ static int oldsec = 0;
+ int j;
+
+ /* check for a repeated search */
+ if (value != oldval || sec != oldsec) {
+ oldval = value;
+ oldsec = sec;
+ index = 0;
+ }
+ /* never happen */
+ else if (index == -1)
+ return(FAILED);
+
+ /* do a linear search for a symbol, as the symbol table is unsorted */
+ for (j = index ; j < o_hdrbuf.oh_nname ; j++) {
+ if (value == o_symtab[j].on_valu &&
+ sec == ((o_symtab[j].on_type & S_TYP) - S_MIN))
+ break;
+ }
+
+ /* set up the index for the next pass */
+ if (j == o_hdrbuf.oh_nname)
+ index = 0;
+ else
+ index = j + 1;
+
+ return(index - 1);
+}
+
+
+/*
+ * g e n _ l o c s y m
+ *
+ * Generate local symbols.
+ *
+ * Returns: OK Success
+ * FAILED Invalid arguments, malloc failure
+ *
+ * This works only for .data, .rom and .bss. Text symbols need
+ * a disassembly of the text section, and intelligent guesses as
+ * to whether a local address refers to text or data. In fact,
+ * this routine can be usefully applied only to the .rom area.
+ */
+int gen_locsym(FILE *fp, int sec)
+{
+ char data[20];
+ int j, txtflg, hdrflg;
+ long int addrcount;
+ struct locname *np, *current;
+
+ /* check that all offsets are valid - this routine won't work for text */
+ if (sec < ROM || sec > BSS) {
+ fprintf(stderr, "Invalid section %s\n", o_secnam[sec]);
+ return(FAILED);
+ }
+
+ /* initialise the label string */
+ strncpy(data, o_secnam[sec], 4);
+ data[4] = '\0';
+
+ /* initialise the in-memory local name table pointers */
+ current = (struct locname *)(NULL);
+
+ /* read the data area and load the symbols */
+ (void) fseek(fp, o_sectab[sec].os_foff, SEEK_SET);
+ addrcount = 0;
+ txtflg = hdrflg = FALSE;
+ while (addrcount < o_sectab[sec].os_flen) {
+ j = fgetc(fp);
+ if (j < 040 || j > 0177) {
+ txtflg = FALSE;
+ hdrflg = FALSE;
+ }
+ else
+ txtflg = TRUE;
+
+ /* ensure that the start of each apparent string has a related symbol */
+ if (txtflg && !hdrflg) {
+ if (find_osym(addrcount, sec) == -1) {
+ /* if malloc fails, just collapse */
+ if ((np = (struct locname *)malloc(sizeof(struct locname)))
+ == (struct locname *)NULL) {
+ fprintf(stderr, "%s: malloc failed\n", progname);
+ return(FAILED);
+ }
+ /* update the current record */
+ sprintf(np->l_name, "%s%04x", data, addrcount & 0xffff);
+ /* nb. must follow l_name update */
+ if (sec == TEXT) np->l_sclass = S_TEXT & 0xff;
+ else if (sec == ROM) np->l_sclass = S_DATA & 0xff;
+ else if (sec == DATA) np->l_sclass = S_DATA & 0xff;
+ else if (sec == BSS) np->l_sclass = S_BSS & 0xff;
+ else sec = 0;
+ np->l_value = addrcount;
+ np->l_next = (struct locname *)NULL;
+ /* and add it to the list */
+ if (current == (struct locname *)NULL)
+ locsym[sec] = np;
+ else
+ current->l_next = np;
+ current = np;
+ }
+ hdrflg = TRUE;
+ }
+ addrcount++;
+ }
+
+ return(OK);
+}
+
+
+
+/*
+ * g e t s t r u c t
+ *
+ * Returns: 0 Always
+ *
+ * Get 1, 2 and 4 byte values from the input file.
+ *
+ * Note that the bytes must be reordered and the
+ * read pointer incremented correctly for each value;
+ * hence the need for a structure format string.
+ *
+ * Called with:
+ * a file destcriptor
+ * a pointer to the output buffer
+ * a structure format string
+ */
+int getstruct(FILE *fp, char *bp, char *s)
+{
+ int j;
+ long lj;
+
+ while (TRUE) {
+ switch (*s++) {
+#if 0
+ /* not used */
+ case '0':
+ bp++;
+ continue;
+#endif
+ case '1':
+ *bp++ = (char) getc(fp);
+ continue;
+ case '2':
+ j = getc(fp);
+ j |= (getc(fp) << 8);
+ *((short *)bp) = (short) j;
+ bp += 2;
+ continue;
+ case '4':
+ lj = (long)getc(fp);
+ lj |= ((long)getc(fp) << 8);
+ lj |= ((long)getc(fp) << 16);
+ lj |= ((long)getc(fp) << 24);
+ *((long *)bp) = lj;
+ bp += 4;
+ continue;
+ default:
+ break;
+ }
+ break;
+ }
+
+ return(0);
+}
+
+
+/*
+ * i n i t _ o b j f
+ *
+ * Initialise object file tables.
+ *
+ * Returns: OK Success
+ * FAILED Otherwise
+ */
+int init_objf(FILE *fp)
+{
+ char *cp;
+ int j;
+ unsigned int uj;
+ long int lj;
+
+ /* load the header into memory for fast access */
+ (void) getstruct(fp, (char *)&o_hdrbuf, SF_HEAD);
+ if (BADMAGIC(o_hdrbuf)) {
+ fprintf(stderr, "%s: bad magic number.\n", progname);
+ return(FAILED);
+ }
+ if (o_hdrbuf.oh_nsect == 0) {
+ fprintf(stderr, "%s: no sections present.\n", progname);
+ return(FAILED);
+ }
+
+ /* check that the whole file can be read */
+ if (fseek(fp, OFF_CHAR(o_hdrbuf) + o_hdrbuf.oh_nchar, SEEK_SET) != 0) {
+ fprintf(stderr, "%s: cannot seek to end of file.\n", progname);
+ return(FAILED);
+ }
+
+ /* load the section data into memory for fast access */
+ uj = o_hdrbuf.oh_nsect * sizeof(struct outsect);
+ if (fseek(fp, OFF_SECT(o_hdrbuf), SEEK_SET) != 0) {
+ fprintf(stderr, "%s: cannot seek to section area.\n", progname);
+ return(FAILED);
+ }
+ if (fread(o_sectab, sizeof(char), uj, fp) != uj) {
+ fprintf(stderr, "%s: cannot read section area.\n", progname);
+ return(FAILED);
+ }
+
+ /* load the relocation data into memory for fast access */
+ /* ### Should this be left on disk and only the indices loaded ? */
+ uj = o_hdrbuf.oh_nrelo * sizeof(struct outrelo);
+ if (fseek(fp, OFF_RELO(o_hdrbuf), SEEK_SET) != 0) {
+ fprintf(stderr, "%s: cannot seek to relocation area.\n", progname);
+ return(FAILED);
+ }
+ if ((cp = (char *)malloc(uj)) == (char *)NULL) {
+ fprintf(stderr, "%s: malloc failed\n", progname);
+ return(FAILED);
+ }
+ if (fread(cp, sizeof(char), uj, fp) != uj) {
+ fprintf(stderr, "%s: cannot read relocation area.\n", progname);
+ return(FAILED);
+ }
+ /* initialise the in-memory relocation table array pointers */
+ o_reltab = (struct outrelo *)cp;
+
+ /* ### needs to be optional for files without symbol tables */
+ /* load the symbol table into memory for fast access */
+ uj = o_hdrbuf.oh_nname * sizeof(struct outname);
+ if ((cp = (char *)malloc(uj)) == (char *)NULL) {
+ fprintf(stderr, "%s: malloc failed\n", progname);
+ return(FAILED);
+ }
+ if (fseek(fp, OFF_NAME(o_hdrbuf), SEEK_SET) != 0) {
+ fprintf(stderr, "%s: cannot seek to symbol area.\n", progname);
+ return(FAILED);
+ }
+ if (fread(cp, sizeof(char), uj, fp) != uj) {
+ fprintf(stderr, "%s: cannot read symbol area.\n", progname);
+ return(FAILED);
+ }
+ /* initialise the in-memory symbol table array pointers */
+ o_symtab = (struct outname *)cp;
+
+ /* load the string area into memory for fast access */
+ uj = (unsigned int)o_hdrbuf.oh_nchar;
+ if ((o_strtab = (char *)malloc(uj)) == (char *)NULL) {
+ fprintf(stderr, "%s: malloc failed\n", progname);
+ return(FAILED);
+ }
+ if (fseek(fp, OFF_CHAR(o_hdrbuf), SEEK_SET) != 0) {
+ fprintf(stderr, "%s: cannot seek to string area.\n", progname);
+ return(FAILED);
+ }
+ if (fread(o_strtab, sizeof(char), uj, fp) != uj) {
+ fprintf(stderr, "%s: cannot read string area.\n", progname);
+ return(FAILED);
+ }
+
+ /* build the section name table */
+ for (j = 0 ; j < o_hdrbuf.oh_nname ; j++) {
+ if ((o_symtab[j].on_type & S_ETC) == S_SCT) {
+ lj = o_symtab[j].on_foff - (long)OFF_CHAR(o_hdrbuf);
+ /* check that addressing isn't messed up */
+ assert(lj >= 0 && lj < o_hdrbuf.oh_nchar);
+ strncpy(o_secnam[(o_symtab[j].on_type & S_TYP) - S_MIN],
+ o_strtab + lj, SZ_NAME + 1);
+ }
+ }
+
+ /* build the local symbol tables */
+ for (j = 0 ; j < MAXSECT ; j++)
+ locsym[j] = (struct locname *)NULL;
+
+ /* build the local .text symbol table */
+ /* ### full disassembly ? */
+
+ /* build the local .rom symbol table */
+ if (gen_locsym(fp, ROM) == FAILED)
+ return(FAILED);
+
+ /* there's no point in building the .data and .bss tables */
+
+ return(OK);
+}
+
+
+/*
+ * m a i n
+ *
+ * Main routine of dis_o386.
+ */
+int main(int argc, char *argv[])
+{
+ char *cp, objfile[BUFF_LEN], symbfile[BUFF_LEN];
+ char table[MAXSECT*(SZ_NAME+2)];
+ int j, errors;
+ unsigned long int addrfirst, addrlast, addrcount;
+ struct stat statbuff;
+
+ /* initial set up */
+ if ((cp = strrchr(argv[0], PSEP)) == (char *)NULL)
+ cp = argv[0];
+ else
+ cp++;
+ strncpy(progname, cp, BUFF_MAX);
+ strncpy(objfile, OBJF, BUFF_MAX);
+ addrfirst = addrlast = addrcount = 0;
+
+ /* clear the in-core name tables */
+ o_strtab = (char *)NULL;
+ for (j = 0 ; j < MAXSECT ; j++)
+ o_secnam[j] = table + j * (SZ_NAME + 2); /* nb. leading '_' */
+ for (j = 0 ; j < sizeof(table) ; j++) table[j] = '\0';
+
+ /* check for an MSDOS-style option */
+ if (argc == 2 && argv[1][0] == '/') {
+ usage();
+ exit(0);
+ }
+
+ /* parse arguments */
+ errors = opterr = 0;
+ while ((j = getopt(argc, argv, "O:S:abdf:hl:mnrstx:")) != EOF) {
+ switch (j & 0177) {
+#if 0
+ case 'C': /* core file name */
+ opt_C = TRUE;
+ if (optarg != (char *)NULL)
+ strncpy(binfile, optarg, BUFF_MAX);
+ else
+ errors++;
+ break;
+ case 'E': /* executable file name */
+ opt_E = TRUE;
+ if (optarg != (char *)NULL)
+ strncpy(binfile, optarg, BUFF_MAX);
+ else
+ errors++;
+ break;
+#endif
+ case 'O': /* object file name */
+ opt_O = TRUE;
+ if (optarg != (char *)NULL)
+ strncpy(objfile, optarg, BUFF_MAX);
+ else
+ errors++;
+ break;
+ case 'S': /* symbol table name */
+ opt_S = TRUE;
+ if (optarg != (char *)NULL)
+ strncpy(symbfile, optarg, BUFF_MAX);
+ else
+ errors++;
+ break;
+ case 'a': /* dump tables and disassemble segments */
+ opt_a = TRUE;
+ break;
+ case 'b': /* dump straight binary */
+ opt_b = TRUE;
+ break;
+ case 'd': /* dump the data segment */
+ opt_d = TRUE;
+ break;
+ case 'f': /* first address of dump */
+ opt_f = TRUE;
+ if (optarg != (char *)NULL) {
+ addrfirst = atoaddr(optarg);
+ }
+ else
+ errors++;
+ break;
+ case 'h': /* dump the header */
+ opt_h = TRUE;
+ break;
+ case 'l': /* last address of dump */
+ opt_l = TRUE;
+ if (optarg != (char *)NULL) {
+ addrlast = atoaddr(optarg);
+ }
+ else
+ errors++;
+ break;
+ case 'm': /* dump the rom segment */
+ opt_m = TRUE;
+ break;
+ case 'n': /* dump the symbol names */
+ opt_n = TRUE;
+ break;
+ case 'r': /* dump the relocation structures */
+ opt_r = TRUE;
+ break;
+ case 's': /* dump the symbol table */
+ opt_s = TRUE;
+ break;
+ case 't': /* dump the text segment */
+ opt_t = TRUE;
+ break;
+#if 0
+ case 'u': /* dump the bss segment */
+ opt_u = TRUE;
+ break;
+#endif
+ case 'x': /* debugging flag */
+ opt_x = TRUE;
+ if (optarg != (char *)NULL)
+ dbglvl = atoi(optarg);
+ break;
+ case '?':
+ default:
+ usage();
+ exit(1);
+ break;
+ }
+ }
+
+ /* check the flags */
+ if (errors > 0) {
+ usage();
+ exit(1);
+ }
+ if (opt_a && (opt_d || opt_h || opt_m || opt_n ||
+ opt_r || opt_s || opt_t)) {
+ usage();
+ exit(1);
+ }
+ if ((opt_f || opt_l) && (addrlast > 0 && addrfirst > addrlast)) {
+ usage();
+ exit(1);
+ }
+
+ /* check for a specific input file */
+ if (optind < argc)
+ strncpy(objfile, argv[optind], BUFF_MAX);
+
+ /* we must have a binary file of some sort */
+ if ((objfp = fopen(objfile, "rb")) == (FILE *)NULL ||
+ stat(objfile, &statbuff) == -1) {
+ perror(objfile);
+ exit(1);
+ }
+
+ /* initialise the object file data structures */
+ if (init_objf(objfp) == FAILED) {
+ perror(objfile);
+ exit(1);
+ }
+
+ /* show the output file name and date */
+ fprintf(stdout, "File name: %s\nFile date: %s",
+ objfile, ctime(&statbuff.st_ctime));
+
+ /* show the header and section data - default behaviour */
+ if (opt_a || opt_h || (!opt_d && !opt_m && !opt_n &&
+ !opt_r && !opt_s && !opt_t)) {
+ fprintf(stdout, "\nHeader data:\n");
+ (void) dump_ohdr(&o_hdrbuf);
+ fprintf(stdout, "\nSection data:\n");
+ (void) fseek(objfp, OFF_SECT(hdrbuf), SEEK_SET);
+ (void) dump_oshdr(objfp, 0, o_hdrbuf.oh_nsect);
+ }
+
+ /* The core start address is zero for every section. What allowances
+ * should be made for the differences between file and core images?
+ */
+
+ /* dump or disassemble the rom section */
+ if (opt_a || opt_m) {
+ if (opt_b)
+ (void) dump_osec(addrfirst, addrlast, ROM, FALSE);
+ else
+ (void) dump_osec(addrfirst, addrlast, ROM, TRUE);
+ }
+
+ /* dump or disassemble the data section */
+ if (opt_a || opt_d) {
+ if (opt_b)
+ (void) dump_osec(addrfirst, addrlast, DATA, FALSE);
+ else
+ (void) dump_osec(addrfirst, addrlast, DATA, TRUE);
+ }
+
+ /* dump or disassemble the text section */
+ if (opt_a || opt_t) {
+ /* check that all offsets are valid */
+ if (addrfirst > o_sectab[TEXT].os_flen || addrlast > o_sectab[TEXT].os_flen) {
+ fprintf(stderr, "Invalid %s address range 0x%08.8lu to 0x%08.8lu\n",
+ "text", addrfirst, addrlast);
+ }
+ else {
+ if (opt_b)
+ (void) dump_osec(addrfirst, addrlast, TEXT, FALSE);
+ else {
+ addrcount = (addrlast == 0) ? o_sectab[TEXT].os_flen : addrlast;
+ addrcount -= addrfirst;
+ disfp = objfp; /* file to be disassembled */
+ (void) fseek(disfp, o_sectab[TEXT].os_foff + addrfirst, SEEK_SET);
+ fprintf(stdout, "\nDisassembled text:\n");
+ (void) dasm(addrfirst, addrcount);
+ }
+ }
+ }
+
+ /* show the relocation data */
+ if (opt_a || opt_r) {
+ if (opt_b)
+ addrcount = o_hdrbuf.oh_nrelo * sizeof(struct outrelo);
+ else
+ addrcount = o_hdrbuf.oh_nrelo;
+ /* check that all offsets are valid */
+ if (addrfirst >= addrcount || addrlast >= addrcount) {
+ fprintf(stderr, "Invalid %s address range 0x%08.8lu to 0x%08.8lu\n",
+ "relocation", addrfirst, addrlast);
+ }
+ else {
+ if (opt_l)
+ addrcount = addrlast + 1;
+ addrcount = addrcount - addrfirst;
+ if (opt_b) {
+ fprintf(stdout, "\nRelocation data dump:\n");
+ (void) fseek(objfp, OFF_RELO(o_hdrbuf) + addrfirst, SEEK_SET);
+ (void) dump_hex(objfp, addrfirst, addrcount);
+ }
+ else {
+ fprintf(stdout, "\nRelocation data:\n");
+ (void) fseek(objfp, OFF_RELO(o_hdrbuf) + addrfirst *
+ sizeof(struct outrelo), SEEK_SET);
+ (void) dump_orel(objfp, addrfirst, addrcount);
+ }
+ }
+ }
+
+ /* show the symbol data */
+ if (opt_a || opt_s) {
+ if (opt_b)
+ addrcount = o_hdrbuf.oh_nname * sizeof(struct outname);
+ else
+ addrcount = o_hdrbuf.oh_nname;
+ /* check that all offsets are valid */
+ if (addrfirst >= addrcount || addrlast >= addrcount) {
+ fprintf(stderr, "Invalid %s address range 0x%08.8lu to 0x%08.8lu\n",
+ "symbol", addrfirst, addrlast);
+ }
+ else {
+ if (opt_l)
+ addrcount = addrlast + 1;
+ addrcount = addrcount - addrfirst;
+ if (opt_b) {
+ fprintf(stdout, "\nSymbol data dump:\n");
+ (void) fseek(objfp, OFF_NAME(o_hdrbuf) + addrfirst, SEEK_SET);
+ (void) dump_hex(objfp, addrfirst, addrcount);
+ }
+ else {
+ fprintf(stdout, "\nSymbol data:\n");
+ (void) fseek(objfp, OFF_NAME(o_hdrbuf) + addrfirst *
+ sizeof(struct outname), SEEK_SET);
+ (void) dump_osym(objfp, addrfirst, addrcount);
+ }
+ }
+ }
+
+ /* show the string data */
+ if (opt_a || opt_n) {
+ if (opt_b)
+ addrcount = o_hdrbuf.oh_nchar;
+ else
+ addrcount = o_hdrbuf.oh_nname; /* assumes one name per symbol */
+ /* check that all offsets are valid */
+ if (addrfirst >= addrcount || addrlast >= addrcount) {
+ fprintf(stderr, "Invalid %s address range 0x%08.8lu to 0x%08.8lu\n",
+ "symbol", addrfirst, addrlast);
+ }
+ else {
+ if (opt_l)
+ addrcount = addrlast + 1;
+ addrcount = addrcount - addrfirst;
+ if (opt_b) {
+ fprintf(stdout, "\nName data dump:\n");
+ (void) fseek(objfp, OFF_CHAR(o_hdrbuf) + addrfirst, SEEK_SET);
+ (void) dump_hex(objfp, addrfirst, addrcount);
+ }
+ else {
+ fprintf(stdout, "\nName data:\n");
+ (void) fseek(objfp, o_symtab[addrfirst].on_foff, SEEK_SET);
+ (void) dump_ostr(objfp, addrfirst, addrcount);
+ }
+ }
+ }
+
+ /* wrap up */
+ fclose(objfp);
+
+ exit(0);
+}
+
+
+/*
+ * u s a g e
+ *
+ * Usage message.
+ *
+ * Returns: Nothing Always
+ */
+void usage()
+{
+ fprintf(stderr, "Usage: %s [-a|-dhmnrst] [-b] [-f #] [-l #] [-O objfile]\n",
+ progname);
+}
+
+
+/*
+ * EOF
+ */
+
--- /dev/null
+/*
+ * misc.c: interface to Bruce Evan's dis86 package.
+ *
+ * $Id: misc.c,v 1.1 1997/10/20 12:00:00 cwr Exp cwr $
+ *
+ * Heavily modified by C W Rose.
+ */
+
+/* Version settings */
+#define MINIX
+#undef OS2
+#undef TEST
+
+#include <sys/types.h>
+#ifdef MINIX
+#include <minix/config.h>
+#include <minix/const.h>
+#include <a.out.h>
+#endif
+#ifdef OS2
+typedef unsigned char u8_t;
+typedef unsigned int u16_t;
+typedef unsigned long u32_t;
+#include </local/minix/minix/config.h>
+#include </local/minix/minix/const.h>
+#include </local/minix/a.out.h>
+#endif
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "const.h"
+#include "type.h"
+#undef S_ABS /* clash with a.out.h */
+#include "out.h" /* ACK compiler output header */
+#include "var.h" /* db header */
+#include "dis386.h" /* dis386 package header */
+
+/* Standard defines */
+#define FAILED -1
+#define MAYBE 0
+#define OK 1
+
+/* Local defines */
+
+#ifndef lint
+static char *Version = "@(#) misc.c $Revision: 1.1 $ $Date: 1997/10/20 12:00:00 $";
+#endif
+
+/* Global variables */
+PRIVATE bool_t forceupper;
+PRIVATE bool_t someupper = TRUE;
+PRIVATE count_t stringcount = 0;
+PRIVATE char *string_ptr = (char *)0; /* stringptr ambiguous at 8th char */
+PRIVATE char *stringstart = (char *)0;
+
+/* Externals */
+
+/* Forward declarations */
+#if 0
+PUBLIC void closestring(void); /* */
+PUBLIC u8_pt get8(void); /* */
+PUBLIC u16_t get16(void); /* */
+PUBLIC u32_t get32(void); /* */
+PUBLIC void openstring(char *string, int len); /* */
+PUBLIC void outbyte(char_pt byte); /* */
+PUBLIC void outcolon(void); /* */
+PUBLIC void outcomma(void); /* */
+PUBLIC void outh4(u4_pt num); /* */
+PUBLIC void outh8(u8_pt num); /* */
+PUBLIC void outh16(u16_t num); /* */
+PUBLIC void outh32(u32_t num); /* */
+PUBLIC bool_pt outnl(void); /* */
+PUBLIC count_t outsegaddr(struct address_s *ap, offset_t addr); /* */
+PUBLIC count_t outsegreg(offset_t num); /* */
+PUBLIC void outspace(void); /* */
+PUBLIC void outstr(char *s); /* */
+PUBLIC void outtab(void); /* */
+PUBLIC void outustr(char *s); /* */
+PUBLIC count_t stringpos(void); /* */
+PUBLIC count_t stringtab(void); /* */
+PUBLIC void outrel(struct nlist *sp, offset_t off); /* */
+PUBLIC void outsym(struct nlist *sp, offset_t off); /* */
+PUBLIC struct nlist *findrval(offset_t value, int where);/* */
+PUBLIC struct nlist *findsval(offset_t value, int where);/* */
+PUBLIC int dasm(offset_t addr, offset_t count); /* */
+#endif
+
+PRIVATE u8_pt peek8(struct address_s *ap); /* */
+PRIVATE u16_t peek16(struct address_s *ap); /* */
+PRIVATE u32_t peek32(struct address_s *ap); /* */
+PRIVATE struct nlist *find_arval(offset_t value, int where); /* */
+PRIVATE struct nlist *find_orval(offset_t value, int where); /* */
+PRIVATE struct nlist *find_asval(offset_t value, int where); /* */
+PRIVATE struct nlist *find_osval(offset_t value, int where); /* */
+PRIVATE int dis_one(void); /* */
+
+
+/*
+ * Close string device.
+ */
+PUBLIC void closestring()
+{
+ stringcount = 0;
+ stringstart = string_ptr = (char *)0;
+}
+
+
+/*
+ * Get 8 bits from current instruction pointer and advance pointer.
+ */
+PUBLIC u8_pt get8()
+{
+ u8_pt temp;
+
+ temp = peek8(&uptr);
+ ++uptr.off;
+ return temp;
+}
+
+
+/*
+ * Get 16 bits from current instruction pointer and advance pointer.
+ */
+PUBLIC u16_pt get16()
+{
+ u16_pt temp;
+
+ temp = peek16(&uptr);
+ uptr.off += 2;
+ return temp;
+}
+
+
+/*
+ * Get 32 bits from current instruction pointer and advance pointer.
+ */
+PUBLIC u32_t get32()
+{
+ u32_t temp;
+
+ temp = peek32(&uptr);
+ uptr.off += 4;
+ return temp;
+}
+
+
+/*
+ * Open string device.
+ */
+PUBLIC void openstring(string, len)
+char *string; int len;
+{
+ while (--len >= 0)
+ string[len] = '\0';
+ stringcount = 0;
+ stringstart = string_ptr = string;
+}
+
+
+/*
+ * Print char to currently open output devices.
+ */
+PUBLIC void outbyte(char_pt byte)
+{
+ /* convert to upper case if required */
+ if (forceupper && byte >= 'a' && byte <= 'z')
+ byte += 'A' - 'a';
+
+ /* increment the output line character count, allowing for tab stops */
+ if (string_ptr != NULL) {
+ if ((*string_ptr++ = byte) == '\t')
+ stringcount = 8 * (stringcount / 8 + 1);
+ else
+ ++stringcount;
+ }
+ else
+ (void) fputc(byte, stdout);
+}
+
+
+/*
+ * Print colon.
+ */
+PUBLIC void outcolon()
+{
+ outbyte(':');
+}
+
+
+/*
+ * Print comma.
+ */
+PUBLIC void outcomma()
+{
+ outbyte(',');
+}
+
+
+/*
+ * Print 4 bits hex.
+ */
+PUBLIC void outh4(u4_pt num)
+{
+ static char hexdigits[] = "0123456789abcdef";
+
+ forceupper = someupper;
+ outbyte(hexdigits[num % 16]);
+ forceupper = FALSE;
+}
+
+
+/*
+ * Print 8 bits hex.
+ */
+PUBLIC void outh8(u8_pt num)
+{
+ outh4(num / 16);
+ outh4(num);
+}
+
+
+/*
+ * Print 16 bits hex.
+ */
+PUBLIC void outh16(u16_pt num)
+{
+ outh8(num / 256);
+ outh8(num);
+}
+
+
+/*
+ * Print 32 bits hex.
+ */
+PUBLIC void outh32(u32_t num)
+{
+ outh16((u16_t) (num >> 16));
+ outh16((u16_t) num);
+}
+
+
+/*
+ * Print newline.
+ */
+PUBLIC bool_pt outnl()
+{
+ /* bool_pt avoids change in type.h */
+ outstr("\n");
+ return OK;
+}
+
+
+/*
+ * Print segmented address.
+ */
+PUBLIC count_t outsegaddr(struct address_s *ap, offset_t addr)
+{
+ count_t bytes_printed;
+
+ bytes_printed = 2;
+
+ if (ap->base == regs.csbase)
+ outustr("cs");
+ else if (ap->base == regs.dsbase)
+ outustr("ds");
+ else if (ap->base == regs.esbase)
+ outustr("es");
+ else if (processor >= 386 && ap->base == regs.fsbase)
+ outustr("fs");
+ else if (processor >= 386 && ap->base == regs.gsbase)
+ outustr("gs");
+ else if (ap->base == regs.ssbase)
+ outustr("ss");
+ else
+ bytes_printed = outsegreg(ap->base);
+
+ if (bytes_printed > 4)
+ outbyte('+');
+ else
+ outcolon();
+ bytes_printed++;
+
+ if (ap->off >= 0x10000) {
+ outh32(ap->off + addr);
+ return bytes_printed + 8;
+ }
+ else {
+ outh16((u16_pt) ap->off + addr);
+ return bytes_printed + 4;
+ }
+}
+
+
+/*
+ * Print segment register.
+ */
+PUBLIC count_t outsegreg(offset_t num)
+{
+ if ((num % HCLICK_SIZE) != 0 || num >= 0x100000) {
+ outh32(num);
+ return 8;
+ }
+ outh16((u16_pt) (num / HCLICK_SIZE));
+ return 4;
+}
+
+
+/*
+ * Print space.
+ */
+PUBLIC void outspace()
+{
+ outbyte(' ');
+}
+
+
+/*
+ * Print string.
+ */
+PUBLIC void outstr(char *s)
+{
+ while (*s)
+ outbyte(*s++);
+}
+
+/*
+ * Print tab.
+ */
+PUBLIC void outtab()
+{
+ outbyte('\t');
+}
+
+
+/*
+ * Print string, perhaps converting case to upper.
+ */
+PUBLIC void outustr(char *s)
+{
+ forceupper = someupper;
+ while (*s)
+ outbyte(*s++);
+ forceupper = FALSE;
+}
+
+
+/*
+ * p e e k 8
+ *
+ * Get a byte from the process.
+ *
+ * Returns: byte Success
+ *
+ * Note: aborts on read error.
+ */
+PRIVATE u8_pt peek8(struct address_s *ap)
+{
+ unsigned int uj;
+
+ /* with luck buffering should make this fairly quick */
+ if (fseek(disfp, (long)(ap->off), SEEK_CUR) != 0) {
+ fprintf(stderr, "Cannot seek forward in object file\n");
+ exit(1);
+ }
+ uj = fgetc(disfp) & 0377;
+ if (fseek(disfp, -(long)(ap->off + 1), SEEK_CUR) != 0) {
+ fprintf(stderr, "Cannot seek backward in object file\n");
+ exit(1);
+ }
+
+ return uj;
+}
+
+
+/*
+ * p e e k 1 6
+ *
+ * Get a 16-bit short from the process.
+ *
+ * Returns: 2 bytes Success
+ *
+ * Note: aborts on read error.
+ */
+PRIVATE u16_t peek16(struct address_s *ap)
+{
+ unsigned int uj;
+
+ /* with luck buffering should make this fairly quick */
+ if (fseek(disfp, (long)(ap->off), SEEK_CUR) != 0) {
+ fprintf(stderr, "Cannot seek forward in object file\n");
+ exit(1);
+ }
+ /* Intel has right to left byte ordering */
+#if 1
+ uj = fgetc(disfp) & 0377;
+ uj |= (fgetc(disfp) & 0377) << 8;
+#else
+ uj = fgetc(disfp) & 0377;
+ uj <<= 8;
+ uj |= fgetc(disfp) & 0377;
+#endif
+ if (fseek(disfp, -(long)(ap->off + 2), SEEK_CUR) != 0) {
+ fprintf(stderr, "Cannot seek backward in object file\n");
+ exit(1);
+ }
+
+ return uj;
+}
+
+
+/*
+ * p e e k 3 2
+ *
+ * Get a 32-bit int from the process.
+ *
+ * Returns: 4 bytes Success
+ *
+ * Note: aborts on read error.
+ */
+PRIVATE u32_t peek32(struct address_s *ap)
+{
+ unsigned int uj;
+
+ /* with luck buffering should make this fairly quick */
+ if (fseek(disfp, (long)(ap->off), SEEK_CUR) != 0) {
+ fprintf(stderr, "Cannot seek forward in object file\n");
+ exit(1);
+ }
+#if 1
+ /* Intel has right to left byte ordering */
+ uj = fgetc(disfp) & 0377;
+ uj |= (fgetc(disfp) & 0377) << 8;
+ uj |= (fgetc(disfp) & 0377) << 16;
+ uj |= (fgetc(disfp) & 0377) << 24;
+#else
+ uj = fgetc(disfp) & 0377;
+ uj <<= 8;
+ uj |= fgetc(disfp) & 0377;
+ uj <<= 8;
+ uj |= fgetc(disfp) & 0377;
+ uj <<= 8;
+ uj |= fgetc(disfp) & 0377;
+#endif
+ if (fseek(disfp, -(long)(ap->off + 4), SEEK_CUR) != 0) {
+ fprintf(stderr, "Cannot seek backward in object file\n");
+ exit(1);
+ }
+
+ return uj;
+}
+
+
+/*
+ * Return current offset of string device.
+ */
+PUBLIC count_t stringpos()
+{
+ return string_ptr - stringstart;
+}
+
+
+/*
+ * Return current "tab" spot of string device.
+ */
+PUBLIC count_t stringtab()
+{
+ return stringcount;
+}
+
+/******************** sym.c ***********************/
+
+/*
+ * f i n d r v a l
+ *
+ * Check if an address refers to a relocation structure,
+ * and if so return the table entry.
+ *
+ * Returns: Pointer to struct nlist Success
+ * Null pointer Failure
+ *
+ * Note that the nlist interface must be maintained for use by unasm().
+ */
+PUBLIC struct nlist *findrval(offset_t value, int where)
+{
+ if (aoutfp != (FILE *)NULL)
+ return (find_arval(value, where));
+ else if (objfp != (FILE *)NULL)
+ return (find_orval(value, where));
+ else
+ return (struct nlist *)NULL;
+}
+
+
+/*
+ * f i n d _ a r v a l
+ *
+ * Check if an address refers to an a.out file relocation structure,
+ * and if so return the table entry.
+ *
+ * Returns: Pointer to struct nlist Success
+ * Null pointer Failure
+ *
+ * Note that the nlist interface must be maintained for use by unasm().
+ * ### Do any available ACK compilers have this feature?
+ */
+PRIVATE struct nlist *find_arval(offset_t value, int where)
+{
+ return (struct nlist *)NULL;
+}
+
+
+/*
+ * f i n d _ o r v a l
+ *
+ * Check if an address refers to an object file relocation structure,
+ * and if so return the table entry.
+ *
+ * Returns: Pointer to struct nlist Success
+ * Null pointer Failure
+ *
+ * Note that the nlist interface must be maintained for use by unasm().
+ * The table entry is stored in a static buffer which is overwritten
+ * on successive calls.
+ */
+PRIVATE struct nlist *find_orval(offset_t value, int where)
+{
+ char data[20];
+ int j, k, status;
+ long int lj;
+ static struct nlist sym;
+
+ /* we need to have an object file */
+ if (objfp == (FILE *)NULL) return (struct nlist *)NULL;
+
+ /* Sections in an object file usually have the order text, rom, data, bss.
+ * The order is actually set out in the section data header. Assume that
+ * the first user section is text, and all else is data.
+ */
+ if (where != CSEG && where != DSEG)
+ return(struct nlist *)NULL;
+
+ /* check for a relocation entry */
+ status = FAILED;
+ for (j = 0 ; j < o_hdrbuf.oh_nrelo ; j++) {
+ if (value == o_reltab[j].or_addr) {
+ /* abandon non-matching section entries */
+ if (where == CSEG && (o_reltab[j].or_sect & S_TYP) != S_MIN)
+ continue;
+ if (where == DSEG && ((o_reltab[j].or_sect & S_TYP) <= S_MIN ||
+ (o_reltab[j].or_sect & S_TYP) > (S_MIN + 3)))
+ continue;
+ /* the address is an offset from the symbol or section base */
+ if (o_reltab[j].or_nami < o_hdrbuf.oh_nname) {
+ lj = o_symtab[o_reltab[j].or_nami].on_foff -
+ (long)OFF_CHAR(o_hdrbuf);
+ /* check that addressing isn't messed up */
+ assert(lj >= 0 && lj < o_hdrbuf.oh_nchar);
+ /* name size is defined by SZ_NAME */
+ sprintf(data, "%-13s", o_strtab + lj);
+ /* convert from rel table to executable symbol table format */
+ for (k = 0 ; k < sizeof(sym.n_name) ; k++) {
+ sym.n_name[k] = data[k];/* 8 characters */
+ }
+ sym.n_value = o_symtab[o_reltab[j].or_nami].on_valu;
+ /* long */
+#if 1
+ sym.n_sclass = (where == CSEG) ? N_TEXT : N_DATA;
+#else
+ sym.n_sclass = (o_symtab[o_reltab[j].or_nami].on_type &
+ S_TYP) - S_MIN; /* unsigned char */
+#endif
+ sym.n_numaux = 0; /* unsigned char */
+ sym.n_type = 0; /* unsigned short */
+ status = OK;
+ break;
+ }
+ /* the address is an absolute number relative to the pc */
+ else if (o_reltab[j].or_nami == o_hdrbuf.oh_nname) {
+ strcpy(data, "Absolute");
+ /* convert from relocation data to executable symbol table format */
+ for (k = 0 ; k < sizeof(sym.n_name) ; k++) {
+ sym.n_name[k] = data[k];
+ }
+ sym.n_value = 0;
+ sym.n_sclass = (where == CSEG) ? N_TEXT : N_DATA;
+ sym.n_numaux = 0;
+ sym.n_type = 0;
+ status = OK;
+ break;
+ }
+ }
+ }
+ return (status == OK ? &sym : (struct nlist *)NULL);
+}
+
+
+/*
+ * f i n d s v a l
+ *
+ * Check if an address refers to a symbol,
+ * and if so return the table entry.
+ *
+ * Returns: Pointer to struct nlist Success
+ * Null pointer Failure
+ *
+ * Note that the nlist interface must be maintained for use by unasm().
+ */
+PUBLIC struct nlist *findsval(offset_t value, int where)
+{
+ if (aoutfp != (FILE *)NULL)
+ return (find_asval(value, where));
+ else if (objfp != (FILE *)NULL)
+ return (find_osval(value, where));
+ else
+ return (struct nlist *)NULL;
+}
+
+
+/*
+ * f i n d _ a s v a l
+ *
+ * Check if an address refers to an a.out file symbol,
+ * and if so return the table entry.
+ *
+ * Returns: Pointer to struct nlist Success
+ * Null pointer Failure
+ *
+ * Note that the nlist interface must be maintained for use by unasm().
+ * The table entry is stored in a static buffer which is overwritten
+ * on successive calls.
+ */
+PRIVATE struct nlist *find_asval(offset_t value, int where)
+{
+ int j, status;
+ static struct nlist sym;
+
+ /* Sections in an a.out file have the order text, data, bss
+ * but this function is called only with CSEG and DSEG.
+ */
+ if (where != CSEG && where != DSEG)
+ return(struct nlist *)NULL;
+
+ /* do a linear search for a symbol, as the symbol tables are unsorted */
+ status = FAILED;
+ for (j = 0 ; j < (a_hdrbuf.a_syms / sizeof(struct nlist)) ; j++) {
+ if (value == a_symtab[j].n_value &&
+ ((where == CSEG && (a_symtab[j].n_sclass & N_SECT) == N_TEXT) ||
+ (where == DSEG && ((a_symtab[j].n_sclass & N_SECT) == N_DATA ||
+ (a_symtab[j].n_sclass & N_SECT) == N_BSS)))) {
+ (void) memcpy(&sym, &a_symtab[j], sizeof(struct nlist));
+ status = OK;
+ break;
+ }
+ }
+ return (status == OK) ? &sym : (struct nlist *)NULL;
+}
+
+
+/*
+ * f i n d _ o s v a l
+ *
+ * Check if an address refers to an object file symbol,
+ * and if so return the table entry.
+ *
+ * Returns: Pointer to struct nlist Success
+ * Null pointer Failure
+ *
+ * Note that the nlist interface must be maintained for use by unasm().
+ * The table entry is stored in a static buffer which is overwritten
+ * on successive calls.
+ */
+PRIVATE struct nlist *find_osval(offset_t value, int where)
+{
+ int j, k, sec, status;
+ long int lj;
+ struct locname *np;
+ static struct nlist sym;
+
+ /* Sections in an object file usually have the order text, rom, data, bss.
+ * The order is actually set out in the section data header. Assume that
+ * the first user section is text, and all else is data.
+ */
+ if (where != CSEG && where != DSEG)
+ return(struct nlist *)NULL;
+
+ /* do a linear search for a local symbol, as the tables are unsorted */
+ status = FAILED;
+ if (where == DSEG) {
+ /* nb. hardcoded assumption of section order */
+ for (sec = 1 ; status == FAILED && sec < 4 ; sec++) {
+ for (np = locsym[sec] ; status == FAILED && np !=
+ (struct locname *)NULL ; np = np->l_next) {
+ if (np->l_value == value) {
+ for (k = 0 ; k < sizeof(sym.n_name) ; k++) {
+ sym.n_name[k] = np->l_name[k];/* 8 characters */
+ }
+ sym.n_value = value; /* long */
+ sym.n_sclass = N_DATA; /* unsigned char */
+ sym.n_numaux = 0; /* unsigned char */
+ sym.n_type = 0; /* unsigned short */
+ status = OK;
+ }
+ }
+ }
+ }
+
+ /* do a linear search for a symbol, as the symbol tables are unsorted */
+ for (j = 0 ; status == FAILED && j < o_hdrbuf.oh_nname ; j++) {
+ if (value == o_symtab[j].on_valu) {
+ /* abandon non-matching section entries */
+ if (where == CSEG && (o_symtab[j].on_type & S_TYP) != S_MIN)
+ continue;
+ if (where == DSEG && ((o_symtab[j].on_type & S_TYP) <= S_MIN ||
+ (o_symtab[j].on_type & S_TYP) > (S_MIN + 3)))
+ continue;
+#if 0
+ ((where == CSEG && sect == (o_symtab[j].on_type & S_TYP)) ||
+ (where == DSEG && sect <= (o_symtab[j].on_type & S_TYP)))) {
+#endif
+ /* find the name in the object file symbol table */
+ lj = o_symtab[j].on_foff - (long)OFF_CHAR(o_hdrbuf);
+ /* check that the offset addressing isn't messed up */
+ assert(lj >= 0 && lj < o_hdrbuf.oh_nchar);
+ /* convert from object to executable symbol table format */
+ for (k = 0 ; k < sizeof(sym.n_name) ; k++) {
+ sym.n_name[k] = *(o_strtab + lj + k);
+ /* 8 characters */
+ }
+ sym.n_value = o_symtab[j].on_valu; /* long */
+ sym.n_sclass = (where == CSEG) ? N_TEXT : N_DATA;
+ /* unsigned char */
+ sym.n_numaux = 0; /* unsigned char */
+ sym.n_type = 0; /* unsigned short */
+ status = OK;
+ }
+ }
+
+ return (status == OK ? &sym : (struct nlist *)NULL);
+}
+
+
+/*
+ * o u t r e l
+ *
+ * Output a symbol name from an nlist structure.
+ *
+ * Returns: Nothing Always
+ *
+ * Note that the nlist interface must be maintained for use by unasm().
+ * The label may be a segment name, in which case the address is relative
+ * to that segment and must be dereferenced further.
+ */
+PUBLIC void outrel(struct nlist *sp, offset_t off)
+{
+ char data[20];
+ int j, k;
+ struct nlist *spnew;
+
+ /* get a local copy of the label */
+ for (j = 0 ; j < 20 ; j++) {
+ data[j] = sp->n_name[j];
+ if (data[j] == ' ' || data[j] == '\0')
+ break;
+ }
+ data[j] = '\0';
+ data[8] = '\0';
+
+ /* see if we have a section name */
+ for (k = 0 ; k < 4 ; k++) {
+ if (strcmp(data, o_secnam[k]) == 0) {
+ /* look up the name in the appropriate section */
+ if ((spnew = findsval(off, (k ? DSEG : CSEG))) != (struct nlist *)NULL) {
+ /* get a local copy of the label */
+ for (j = 0 ; j < 20 ; j++) {
+ data[j] = spnew->n_name[j];
+ if (data[j] == '\0') break;
+ }
+ data[8] = '\0';
+ }
+ }
+ }
+
+ /* output the result */
+ for (j = 0 ; data[j] != 0 ; j++)
+ outbyte(data[j]);
+}
+
+
+/*
+ * o u t s y m
+ *
+ * Output a symbol name from an nlist structure.
+ *
+ * Returns: Nothing Always
+ *
+ * Note that the nlist interface must be maintained for use by unasm().
+ */
+PUBLIC void outsym(struct nlist *sp, offset_t off)
+{
+ char *s;
+ char *send;
+
+ /* output the symbol name */
+ for (s = sp->n_name, send = s + sizeof sp->n_name; *s != 0 && s < send; ++s)
+ outbyte(*s);
+
+ /* if the required address is offset from the name, output that too */
+ if ((off -= sp->n_value) != 0) {
+ outbyte('+');
+ if (off >= 0x10000)
+ outh32(off);
+ else if (off >= 0x100)
+ outh16((u16_pt) off);
+ else
+ outh8((u8_pt) off);
+ }
+}
+
+
+/*
+ * d a s m
+ *
+ * Disassemble a stream of instructions.
+ *
+ * Returns: OK Success
+ * FAILED Otherwise
+ */
+PUBLIC int dasm(offset_t addr, offset_t count)
+{
+#if (_WORD_SIZE == 4)
+ bits32 = TRUE; /* set mode */
+#else
+ bits32 = FALSE;
+#endif
+ processor = bits32 ? 386 : 0;
+ uptr.off = 0;
+ uptr.base = 0;
+
+ while (uptr.off < count) {
+ addrbase = addr;
+ /* assume that the object file text segment is first */
+ if (objfp != (FILE *)NULL && uptr.off >= o_sectab[0].os_flen)
+ return FAILED;
+ if (aoutfp != (FILE *)NULL && uptr.off >= (A_DATAPOS(a_hdrbuf) - 1))
+ return FAILED;
+ if (dis_one() == FAILED)
+ return FAILED;
+ }
+ return OK;
+}
+
+
+/*
+ * d i s _ o n e
+ *
+ * Disassemble a single instruction.
+ *
+ * Returns: OK Always
+ *
+ * File read failures are handled at a low level by simply
+ * baling out of the program; the startup checks on file
+ * readability should make this a rare occurrence. Hence
+ * there are no error returns from this routine.
+ * The output is written into a static line buffer, which
+ * is overwritten on successive calls.
+ */
+PRIVATE int dis_one()
+{
+ int idone, column, maxcol;
+ static char line[81];
+ struct address_s newuptr;
+ struct address_s olduptr;
+ struct nlist *sp;
+
+ do {
+ /* output a label */
+ if ((sp = findsval(uptr.off + addrbase, CSEG)) != NULL
+ && sp->n_value == uptr.off + addrbase) {
+ outsym(sp, uptr.off + addrbase);
+ outbyte(':');
+ (void) outnl();
+ }
+
+ /* park the current address */
+ olduptr = uptr;
+
+ /* initialise the string input */
+ openstring(line, sizeof(line));
+
+ /* output an instruction */
+ idone = puti();
+
+ /* terminate the line buffer */
+ line[stringpos()] = 0;
+
+ /* deinitialise the string input */
+ closestring();
+
+ /* park the new address, set by puti() */
+ newuptr = uptr;
+
+ /* get back the current address */
+ uptr = olduptr;
+
+ /* output the segment data */
+ column = outsegaddr(&uptr, addrbase);
+ outspace();
+ outspace();
+ column += 2;
+
+ /* output the raw bytes of the current instruction */
+ while (uptr.off != newuptr.off) {
+ outh8(get8());
+ column += 2;
+ }
+
+ /* format the disassembled output */
+ maxcol = bits32 ? 24 : 16;
+ while (column < maxcol) {
+ outtab();
+ column += 8;
+ }
+ outtab();
+
+ /* display the collected buffer */
+ outstr(line);
+ (void) outnl();
+ } while (!idone); /* eat all prefixes */
+
+ return OK;
+}
+
+/*
+ * EOF
+ */
+
--- /dev/null
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header: out.h,v 1.1 91/05/16 14:09:17 ceriel Exp $ */
+
+#ifndef __OUT_H_INCLUDED
+#define __OUT_H_INCLUDED
+/*
+ * output format for ACK assemblers
+ */
+#ifndef ushort
+#define ushort unsigned short
+#endif /* ushort */
+
+struct outhead {
+ ushort oh_magic; /* magic number */
+ ushort oh_stamp; /* version stamp */
+ ushort oh_flags; /* several format flags */
+ ushort oh_nsect; /* number of outsect structures */
+ ushort oh_nrelo; /* number of outrelo structures */
+ ushort oh_nname; /* number of outname structures */
+ long oh_nemit; /* sum of all os_flen */
+ long oh_nchar; /* size of string area */
+};
+
+#define O_MAGIC 0x0201 /* magic number of output file */
+#define O_STAMP 0 /* version stamp */
+#define MAXSECT 64 /* Maximum number of sections */
+
+#define HF_LINK 0x0004 /* unresolved references left */
+#define HF_8086 0x0008 /* os_base specially encoded */
+
+struct outsect {
+ long os_base; /* startaddress in machine */
+ long os_size; /* section size in machine */
+ long os_foff; /* startaddress in file */
+ long os_flen; /* section size in file */
+ long os_lign; /* section alignment */
+};
+
+struct outrelo {
+ char or_type; /* type of reference */
+ char or_sect; /* referencing section */
+ ushort or_nami; /* referenced symbol index */
+ long or_addr; /* referencing address */
+};
+
+struct outname {
+ union {
+ char *on_ptr; /* symbol name (in core) */
+ long on_off; /* symbol name (in file) */
+ } on_u;
+#define on_mptr on_u.on_ptr
+#define on_foff on_u.on_off
+ ushort on_type; /* symbol type */
+ ushort on_desc; /* debug info */
+ long on_valu; /* symbol value */
+};
+
+/*
+ * relocation type bits
+ */
+#define RELSZ 0x07 /* relocation length */
+#define RELO1 1 /* 1 byte */
+#define RELO2 2 /* 2 bytes */
+#define RELO4 4 /* 4 bytes */
+#define RELPC 0x08 /* pc relative */
+#define RELBR 0x10 /* High order byte lowest address. */
+#define RELWR 0x20 /* High order word lowest address. */
+
+/*
+ * section type bits and fields
+ */
+#define S_TYP 0x007F /* undefined, absolute or relative */
+#define S_EXT 0x0080 /* external flag */
+#define S_ETC 0x7F00 /* for symbolic debug, bypassing 'as' */
+
+/*
+ * S_TYP field values
+ */
+#define S_UND 0x0000 /* undefined item */
+#define S_ABS 0x0001 /* absolute item */
+#define S_MIN 0x0002 /* first user section */
+#define S_MAX (S_TYP-1) /* last user section */
+#define S_CRS S_TYP /* on_valu is symbol index which contains value */
+
+/*
+ * S_ETC field values
+ */
+#define S_SCT 0x0100 /* section names */
+#define S_LIN 0x0200 /* hll source line item */
+#define S_FIL 0x0300 /* hll source file item */
+#define S_MOD 0x0400 /* ass source file item */
+#define S_COM 0x1000 /* Common name. */
+#define S_STB 0xe000 /* entries with any of these bits set are
+ reserved for debuggers
+ */
+
+/*
+ * structure format strings
+ */
+#define SF_HEAD "22222244"
+#define SF_SECT "44444"
+#define SF_RELO "1124"
+#define SF_NAME "4224"
+
+/*
+ * structure sizes (bytes in file; add digits in SF_*)
+ */
+#define SZ_HEAD 20
+#define SZ_SECT 20
+#define SZ_RELO 8
+#define SZ_NAME 12
+
+/*
+ * file access macros
+ */
+#define BADMAGIC(x) ((x).oh_magic!=O_MAGIC)
+#define OFF_SECT(x) SZ_HEAD
+#define OFF_EMIT(x) (OFF_SECT(x) + ((long)(x).oh_nsect * SZ_SECT))
+#define OFF_RELO(x) (OFF_EMIT(x) + (x).oh_nemit)
+#define OFF_NAME(x) (OFF_RELO(x) + ((long)(x).oh_nrelo * SZ_RELO))
+#define OFF_CHAR(x) (OFF_NAME(x) + ((long)(x).oh_nname * SZ_NAME))
+
+#endif /* __OUT_H_INCLUDED */
+
--- /dev/null
+/* type.h - types for db.
+ *
+ * $Id: type.h,v 1.1 1997/10/20 12:00:00 cwr Exp cwr $
+ */
+
+typedef unsigned long bigcount_t;
+typedef unsigned long flags_t;
+typedef int bool_pt;
+typedef char bool_t;
+typedef int char_pt;
+typedef int char16_t; /* ASCII character possibly with scan code */
+typedef unsigned count_t;
+typedef unsigned long offset_t;
+typedef unsigned opcode_pt; /* promote to unsigned and not int */
+typedef int (*pfi_t)();
+typedef void (*pfv_t)();
+typedef unsigned long physoff_t;
+typedef unsigned peekboff_t;
+typedef unsigned peekoff_t;
+typedef int peekseg_t;
+typedef unsigned port_t;
+typedef int reg_pt;
+typedef unsigned char reg_t;
+typedef unsigned segment_t;
+typedef long soffset_t;
+typedef int su8_pt;
+typedef int su16_t;
+typedef unsigned u4_pt; /* promote to unsigned and not int */
+typedef unsigned u8_pt;
+typedef unsigned u16_pt;
+
+struct address_s
+{
+ offset_t off;
+ offset_t base;
+};
+
+struct desctableptr_s {
+ u16_t limit;
+ u32_t base; /* really u24_t + pad for 286 */
+};
+
+struct regs_s
+{
+ offset_t ax;
+ offset_t bx;
+ offset_t cx;
+ offset_t dx;
+ offset_t si;
+ offset_t di;
+ offset_t bp;
+ offset_t sp;
+ offset_t dsbase;
+ offset_t esbase;
+ offset_t fsbase;
+ offset_t gsbase;
+ offset_t ssbase;
+ offset_t csbase;
+ offset_t ip;
+ flags_t f;
+ offset_t ds;
+ offset_t es;
+ offset_t fs;
+ offset_t gs;
+ offset_t ss;
+ offset_t cs;
+};
+
+struct specregs_s
+{
+ u32_t cr0; /* control regs, cr0 is msw + pad for 286 */
+ u32_t cr2;
+ u32_t cr3;
+ u32_t dr0; /* debug regs */
+ u32_t dr1;
+ u32_t dr2;
+ u32_t dr3;
+ u32_t dr6;
+ u32_t dr7;
+ u32_t tr6; /* test regs */
+ u32_t tr7;
+ u16_t gdtlimit;
+ u32_t gdtbase; /* depend on 16-bit compiler so no long align */
+ u16_t gdtpad;
+ u16_t idtlimit;
+ u32_t idtbase;
+ u16_t idtpad;
+ u16_t ldtlimit;
+ u32_t ldtbase;
+ u16_t ldt;
+ u16_t tr; /* task register */
+ u16_t trpad;
+};
+
+/* prototypes */
+
+#if __STDC__
+#define P(x) x
+#else
+#define P(x) ()
+#endif
+
+/* library, very few! */
+void *memcpy P((void *dst, const void *src, unsigned size));
+void *memmove P((void *dst, const void *src, unsigned size));
+unsigned strlen P((const char *s));
+char *strncpy P((char *dst, const char *src, unsigned size));
+
+/* db.c */
+void db_main P((void));
+void get_kbd_state P(());
+void get_scr_state P(());
+void info P((void));
+void reboot P((void));
+void reset_kbd_state P(());
+
+/* getline.c */
+char *getline P((char *startline, unsigned maxlength, unsigned offset));
+
+/* ihexload.c */
+void ihexload P((void));
+
+/* io.c */
+void can_itty P((void));
+void can_keyboard P((void));
+void can_otty P((void));
+void can_screen P((void));
+void closeio P((void));
+void closestring P((void));
+void enab_itty P((void));
+void enab_keyboard P((void));
+void enab_otty P((void));
+void enab_screen P((void));
+void flipcase P((void));
+u8_pt get8 P((void));
+u16_pt get16 P((void));
+u32_t get32 P((void));
+char16_t inchar P((void));
+char_pt mytolower P((char_pt ch));
+void openio P((void));
+void openstring P((char *string, int length));
+void outbyte P((char_pt byte));
+void outcomma P((void));
+void outh4 P((u4_pt num));
+void outh8 P((u8_pt num));
+void outh16 P((u16_pt num));
+void outh32 P((u32_t num));
+bool_pt outnl P((void));
+count_t outsegaddr P((struct address_s *ap, offset_t addr));
+count_t outsegreg P((offset_t num));
+void outspace P((void));
+void outstr P((char *s));
+void outtab P((void));
+void outustr P((char *s));
+void set_tty P((void));
+void show_db_screen P((void));
+void show_user_screen P((void));
+count_t stringpos P((void));
+count_t stringtab P((void));
+char_pt testchar P((void));
+
+/* lib88.s */
+int get_privilege P((void));
+unsigned get_processor P((void));
+unsigned in16portb P((port_t port));
+physoff_t linear2addr P((segment_t segment, u16_pt offset));
+void oportb P((port_t port, u8_pt value));
+u8_pt peek_byte P((physoff_t offset));
+u16_pt peek_word P((physoff_t offset));
+u32_t peek_dword P((physoff_t offset));
+void poke_byte P((physoff_t offset, u8_pt value));
+void poke_word P((physoff_t offset, u16_pt value));
+#ifdef N_TEXT
+void symswap P((struct nlist *left, struct nlist *right,
+ segment_t tableseg, unsigned length));
+#endif
+
+/* pcio.c */
+void kbdclose P((void));
+char_pt kbdin P((void));
+void kbdioctl P((int command));
+void kbdopen P((void));
+void kbdout P((int c));
+
+/* screen.s */
+void scrclose P((void));
+void scrioctl P((int command));
+char_pt scrin P((void));
+void scropen P((void));
+void scrout P((char_pt c));
+
+/* sym.c */
+#ifdef N_TEXT
+struct nlist *findsname P((char *name, int where, bool_pt allflag));
+struct nlist *findsval P((offset_t value, int where));
+struct nlist *findrval P((offset_t value, int where));
+void outsym P((struct nlist *sp, offset_t off));
+void outrel P((struct nlist *sp, offset_t off));
+#endif
+void setproc P((char_pt c, struct address_s *pdptr, struct address_s *pmptr));
+void syminit P((void));
+
+/* tty.s */
+void ttyclose P((void));
+void ttyioctl P((int command));
+char_pt ttyin P((void));
+void ttyopen P((void));
+void ttyout P((char_pt c));
+
+/* unasm.c */
+bool_pt puti P((void));
+
--- /dev/null
+/*
+ * unasm.c: Bruce Evan's dis86 package.
+ *
+ * $Id: unasm.c,v 1.1 1997/10/20 12:00:00 cwr Exp cwr $
+ *
+ * Minimal changes by C W Rose.
+ */
+
+/* Version settings */
+#define MINIX
+#undef OS2
+#undef TEST
+
+#ifdef MINIX
+#include <sys/types.h>
+#include <a.out.h>
+#endif
+#ifdef OS2
+typedef unsigned char u8_t;
+typedef unsigned int u16_t;
+typedef unsigned long u32_t;
+#include </local/minix/a.out.h>
+#endif
+#include "const.h"
+#include "type.h"
+#undef EXTERN
+#define EXTERN
+#include "var.h"
+
+#define LINDIRECT '['
+#define RINDIRECT ']'
+
+#define BASE_MASK 0x07
+#define INDEX_MASK 0x38
+#define INDEX_SHIFT 3
+#define MOD_MASK 0xC0 /* mod reg r/m is mmrrrRRR */
+# define REG_MOD 0xC0
+# define MEM0_MOD 0x00
+# define MEM1_MOD 0x40
+# define MEM2_MOD 0x80
+#define REG_MASK 0x38
+#define REG_SHIFT 3
+#define RM_MASK 0x07
+#define RM_SHIFT 0
+#define SS_MASK 0xC0
+#define SS_SHIFT 6
+
+#define SIGNBIT 0x02 /* opcode bits xxxxxxsw for immediates */
+#define WORDBIT 0x01
+#define TOREGBIT 0x02 /* opcode bit for non-immediates */
+
+#define MAX_SIGNED_CHAR 0x7F /* will assume 2's complement */
+#define MAX_UNSIGNED_CHAR 0xFF
+
+FORWARD void CL P((void));
+FORWARD void Eb P((void));
+FORWARD void Ev P((void));
+FORWARD void EvGv P((void));
+FORWARD void EvIb P((void));
+FORWARD void Ew P((void));
+FORWARD void EwRw P((void));
+FORWARD void Gv P((void));
+FORWARD void Gv1 P((void));
+FORWARD void GvEv P((void));
+FORWARD void GvEw P((void));
+FORWARD void GvM P((void));
+FORWARD void GvMa P((void));
+FORWARD void GvMp P((void));
+FORWARD void Ib P((void));
+FORWARD void Iw P((void));
+FORWARD void Iv P((void));
+FORWARD void Jb P((void));
+FORWARD void Jv P((void));
+FORWARD void Ms P((void));
+FORWARD void checkmemory P((void));
+FORWARD su8_pt get8s P((void));
+FORWARD void getmodregrm P((void));
+FORWARD void i_00_to_3f P((opcode_pt opc));
+FORWARD void i_40_to_5f P((opcode_pt opc));
+FORWARD void i_60_to_6f P((opcode_pt opc));
+FORWARD void i_70_to_7f P((opcode_pt opc));
+FORWARD void i_80 P((opcode_pt opc));
+FORWARD void i_88 P((opcode_pt opc));
+FORWARD void i_90 P((opcode_pt opc));
+FORWARD void i_98 P((opcode_pt opc));
+FORWARD void i_a0 P((opcode_pt opc));
+FORWARD void i_a8 P((opcode_pt opc));
+FORWARD void i_b0 P((opcode_pt opc));
+FORWARD void i_b8 P((opcode_pt opc));
+FORWARD void i_c0 P((opcode_pt opc));
+FORWARD void i_c8 P((opcode_pt opc));
+FORWARD void i_d0 P((opcode_pt opc));
+FORWARD void i_d8 P((opcode_pt opc));
+FORWARD void i_e0 P((opcode_pt opc));
+FORWARD void i_e8 P((opcode_pt opc));
+FORWARD void i_f0 P((opcode_pt opc));
+FORWARD void i_f8 P((opcode_pt opc));
+FORWARD void outad P((opcode_pt opc));
+FORWARD void outad1 P((opcode_pt opc));
+FORWARD void outalorx P((opcode_pt opc));
+FORWARD void outax P((void));
+FORWARD void outbptr P((void));
+FORWARD void outbwptr P((opcode_pt opc));
+FORWARD void outea P((opcode_pt wordflags));
+FORWARD void outf1 P((void));
+FORWARD void outfishy P((void));
+FORWARD void outgetaddr P((void));
+FORWARD void outimmed P((opcode_pt signwordflag));
+FORWARD void outpc P((offset_t pc, int f));
+FORWARD void outsegpc P((void));
+FORWARD void oututstr P((char *s));
+FORWARD void outword P((void));
+FORWARD void outwptr P((void));
+FORWARD void outwsize P((void));
+FORWARD void pagef P((void));
+FORWARD void shift P((opcode_pt opc));
+
+PRIVATE pfv_t optable[] =
+{
+ i_00_to_3f,
+ i_00_to_3f,
+ i_00_to_3f,
+ i_00_to_3f,
+ i_00_to_3f,
+ i_00_to_3f,
+ i_00_to_3f,
+ i_00_to_3f,
+ i_40_to_5f,
+ i_40_to_5f,
+ i_40_to_5f,
+ i_40_to_5f,
+ i_60_to_6f,
+ i_60_to_6f,
+ i_70_to_7f,
+ i_70_to_7f,
+ i_80,
+ i_88,
+ i_90,
+ i_98,
+ i_a0,
+ i_a8,
+ i_b0,
+ i_b8,
+ i_c0,
+ i_c8,
+ i_d0,
+ i_d8,
+ i_e0,
+ i_e8,
+ i_f0,
+ i_f8,
+};
+
+PRIVATE char fishy[] = "???";
+PRIVATE char movtab[] = "mov\t";
+
+PRIVATE char *genreg[] =
+{
+ "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh",
+ "ax", "cx", "dx", "bx", "sp", "bp", "si", "di",
+ "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi",
+};
+PRIVATE char *segreg[] =
+{
+ "es", "cs", "ss", "ds", "fs", "gs", "?s", "?s",
+};
+PRIVATE char *indreg[] =
+{
+ "bx+si", "bx+di", "bp+si", "bp+di", "si", "di", "bp", "bx",
+};
+
+PRIVATE char *str_00_to_3f[] =
+{
+ /* index by (opcode >> 3) & 7 */
+ "add", "or", "adc", "sbb", "and", "sub", "xor", "cmp",
+};
+PRIVATE char *sstr_00_to_3f[] =
+{
+ /* index ((opc>>2) & 0x0E) + (opc & 7) - 6 */
+ "push\tes", "pop\tes", "push\tcs", "pop\tcs",
+ "push\tss", "pop\tss", "push\tds", "pop\tds",
+ "es:", "daa", "cs:", "das", "ss:", "aaa", "ds:", "aas",
+};
+PRIVATE char *sstr_0f[] =
+{
+ "push\tfs", "pop\tfs", fishy, "bt\t", "shld\t", "shld\t", fishy, fishy,
+ "push\tgs", "pop\tgs", fishy, "bts\t", "shrd\t", "shrd\t", fishy, "imul\t",
+ fishy, fishy, "lss\t", "btr\t", "lfs\t", "lgs\t", "movzx\t", "movzx\t",
+ fishy, fishy, "", "btc\t", "bsf\t", "bsr\t", "movsx\t", "movsx\t",
+};
+PRIVATE char *ssstr_0f[] =
+{
+ "sldt\t", "str\t", "lldt\t", "ltr\t", "verr\t", "verw\t", fishy, fishy,
+ "sgdt\t", "sidt\t", "lgdt\t", "lidt\t", "smsw\t", fishy, "lmsw\t", fishy,
+ fishy, fishy, fishy, fishy, "bt\t", "bts\t", "btr\t", "btc\t",
+};
+PRIVATE char *str_40_to_5f[] =
+{
+ /* index by (opcode >> 3) & 3 */
+ "inc\t", "dec\t", "push\t", "pop\t",
+};
+PRIVATE char *str_60_to_6f[] =
+{
+ "pusha", "popa", "bound\t", "arpl\t", "fs:", "gs:", "os:", "as:",
+ "push\t", "imul\t", "push\t", "imul\t", "insb", "ins", "outsb", "outs",
+};
+PRIVATE char *str_flags[] =
+{
+ /* opcodes 0x70 to 0x7F, and 0x0F80 to 0x0F9F */
+ "o", "no", "b", "nb", "z", "nz", "be", "a",
+ "s", "ns", "pe", "po", "l", "ge", "le", "g",
+};
+PRIVATE char *str_98[] =
+{
+ "cbw", "cwd", "call\t", "wait", "pushf", "popf", "sahf", "lahf",
+ "cwde", "cdq", "call\t", "wait", "pushfd", "popfd", "sahf", "lahf",
+};
+PRIVATE char *str_a0[] =
+{
+ movtab, movtab, movtab, movtab, "movsb", "movs", "cmpsb", "cmps",
+};
+PRIVATE char *str_a8[] =
+{
+ "test\t", "test\t", "stosb", "stos", "lodsb", "lods", "scasb", "scas",
+};
+PRIVATE char *str_c0[] =
+{
+ "", "", "ret\t", "ret", "les\t", "lds\t", movtab, movtab,
+};
+PRIVATE char *str_c8[] =
+{
+ "enter\t", "leave", "retf\t", "retf", "int\t3", "int\t", "into", "iret",
+};
+PRIVATE char *str_d0[] =
+{
+ "aam", "aad", "db\td6", "xlat",
+};
+PRIVATE char *sstr_d0[] =
+{
+ "rol", "ror", "rcl", "rcr", "shl", "shr", fishy, "sar",
+};
+PRIVATE char *str_d8[] =
+{
+ "fadd", "fmul", "fcom", "fcomp", "fsub", "fsubr", "fdiv", "fdivr",
+ "fld", NULL, "fst", "fstp", "fldenv", "fldcw", "fstenv", "fstcw",
+ "fiadd", "fimul", "ficom", "ficomp", "fisub", "fisubr", "fidiv", "fidivr",
+ "fild", NULL, "fist", "fistp", NULL, "fld", NULL, "fstp",
+ "fadd", "fmul", "fcom", "fcomp", "fsub", "fsubr", "fdiv", "fdivr",
+ "fld", NULL, "fst", "fstp", "frstor", NULL, "fsave", "fstsw",
+ "fiadd", "fimul", "ficom", "ficomp", "fisub", "fisubr", "fidiv", "fidivr",
+ "fild", NULL, "fist", "fistp", "fbld", "fild", "fbstp", "fistp",
+};
+PRIVATE char *str1_d8[] =
+{
+ "fadd", "fmul", "fcom", "fcomp", "fsub", "fsubr", "fdiv", "fdivr",
+ "fld", "fxch", "\0\0", NULL, "\0\10", "\0\20", "\0\30", "\0\40",
+ NULL, NULL, NULL, NULL, NULL, "\0\50", NULL, NULL,
+ NULL, NULL, NULL, NULL, "\0\60", NULL, NULL, NULL,
+ "fadd", "fmul", NULL, NULL, "fsubr", "fsub", "fdivr", "fdiv",
+ "ffree", NULL, "fst", "fstp", "fucom", "fucomp", NULL, NULL,
+ "faddp", "fmulp", NULL, "\0\70", "fsubrp", "fsubp", "fdivrp", "fdivp",
+ NULL, NULL, NULL, NULL, "\0\100", NULL, NULL, NULL,
+};
+PRIVATE unsigned char size_d8[] =
+{
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 4, 4, 14-28, 2, 14-28, 2,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 4, 4, 0, 10, 0, 10,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 0, 8, 8, 94-108, 0, 94-108, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 10, 8, 10, 8,
+};
+PRIVATE char *sstr_d8[] =
+{
+ "fnop", NULL, NULL, NULL, /* D9D0 */
+ NULL, NULL, NULL, NULL,
+ "fchs", "fabs", NULL, NULL, /* D9E0 */
+ "ftst", "fxam", NULL, NULL,
+ "fld1", "fldl2t", "fldl2e", "fldpi", /* D9E8 */
+ "fldlg2", "fldln2", "fldz", NULL,
+ "f2xm1", "fyl2x", "fptan", "fpatan", /* D9F0 */
+ "fxtract", "fprem1", "fdecstp", "fincstp",
+ "fprem", "fyl2xp1", "fsqrt", "fsincos", /* D9F8 */
+ "frndint", "fscale", "fsin", "fcos",
+ NULL, "fucompp", NULL, NULL, /* DAE8 */
+ NULL, NULL, NULL, NULL,
+ "feni", "fdisi", "fclex", "finit", /* DBE0 */
+ "fsetpm", NULL, NULL, NULL,
+ NULL, "fcompp", NULL, NULL, /* DED8 */
+ NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, /* DFE0 */
+ "fstsw\tax", NULL, NULL, NULL,
+};
+PRIVATE char *str_e0[] =
+{
+ "loopnz\t", "loopz\t", "loop\t", "jcxz\t",
+ "in\t", "in\t", "out\t", "out\t",
+};
+PRIVATE char *str_e8[] =
+{
+ "call\t", "jmp\t", "jmp\t", "jmp\t",
+ "in\t", "in\t", "out\t", "out\t",
+};
+PRIVATE char *str_f0[] =
+{
+ "lock\t", "db\tf1", "repnz\t", "repz\t",
+ "hlt", "cmc",
+ /* other 2 from sstr_f0 */
+};
+PRIVATE char *sstr_f0[] =
+{
+ "test\t", fishy, "not\t", "neg\t",
+ "mul\t", "imul\t", "div\t", "idiv\t",
+};
+PRIVATE char *str_f8[] =
+{
+ "clc", "stc", "cli", "sti",
+ "cld", "std",
+ /* other 2 from sstr_f8 */
+};
+PRIVATE char *sstr_f8[] =
+{
+ "inc\t", "dec\t", "call\t", "call\tfar ",
+ "jmp\t", "jmp\tfar ", "push\t", "???\t",
+};
+
+PRIVATE int nop_flg; /* check for leading NOPs in opcodes */
+PRIVATE int data_seg; /* data segment (munged name for asld) */
+PRIVATE count_t hasize; /* half address size in bits */
+PRIVATE count_t hdefsize;
+PRIVATE count_t hosize; /* half operand size in bits */
+ /* for easy index into reg tables */
+PRIVATE opcode_pt mod;
+PRIVATE offset_t offtable[2];
+PRIVATE offset_t *offptr;
+PRIVATE offset_t *off1ptr;
+PRIVATE opcode_pt reg;
+PRIVATE opcode_pt rm;
+
+PRIVATE su8_pt get8s()
+{
+ u8_pt got;
+
+ if ((got = get8()) > MAX_SIGNED_CHAR)
+ got -= (MAX_UNSIGNED_CHAR + 1);
+ return got;
+}
+
+PRIVATE void getmodregrm()
+{
+ opcode_pt modregrm;
+
+ modregrm = get8();
+ mod = modregrm & MOD_MASK;
+ reg = (modregrm & REG_MASK) >> REG_SHIFT;
+ rm = (modregrm & RM_MASK) >> RM_SHIFT;
+}
+
+PRIVATE void i_00_to_3f(opc)
+opcode_pt opc;
+{
+ opcode_pt sub;
+ struct nlist *sp;
+
+ /* attempt to step over linker padding */
+ if (nop_flg && opc == 0
+ && (sp = findsval(uptr.off + addrbase, CSEG)) != NULL
+ && sp->n_value == uptr.off + addrbase) {
+ outustr("nop");
+ return;
+ }
+ if (opc == 15)
+ pagef();
+ else if ((sub = opc & 7) >= 6)
+ {
+ outustr((sstr_00_to_3f - 6)[((opc >> 2) & 0x0E) + sub]);
+ if (!(opc & 1))
+ data_seg = opc;
+ }
+ else
+ {
+ oututstr(str_00_to_3f[(opc >> 3) & 7]);
+ if (sub == 4)
+ {
+ outustr(genreg[0]);
+ outcomma();
+ Ib();
+ }
+ else if (sub == 5)
+ {
+ outax();
+ outcomma();
+ Iv();
+ }
+ else
+ outad(sub);
+ }
+}
+
+PRIVATE void i_40_to_5f(opc)
+opcode_pt opc;
+{
+ outustr(str_40_to_5f[(opc >> 3) & 3]);
+ outustr(genreg[hosize + (opc & 7)]);
+}
+
+PRIVATE void i_60_to_6f(opc)
+opcode_pt opc;
+{
+ /* most for 386, some for 286 */
+
+ outustr((str_60_to_6f - 0x60)[opc]);
+ switch (opc)
+ {
+ case 0x60:
+ case 0x61:
+ if (hosize == 16)
+ outwsize();
+ break;
+ case 0x62:
+ GvMa();
+ break;
+ case 0x63:
+ EwRw();
+ break;
+ case 0x64:
+ case 0x65:
+ data_seg = opc;
+ break;
+ case 0x66:
+ hosize = (16 + 8) - hdefsize;
+ break;
+ case 0x67:
+ hasize = (16 + 8) - hdefsize;
+ break;
+ case 0x68:
+ outword();
+ Iv();
+ break;
+ case 0x6A:
+ outword();
+ outimmed(SIGNBIT | WORDBIT);
+ break;
+ case 0x69:
+ GvEv();
+ outcomma();
+ Iv();
+ break;
+ case 0x6B:
+ GvEv();
+ outcomma();
+ outimmed(SIGNBIT | WORDBIT);
+ break;
+ case 0x6D:
+ case 0x6F:
+ outwsize();
+ break;
+ default:
+ break;
+ }
+}
+
+PRIVATE void i_70_to_7f(opc)
+opcode_pt opc;
+{
+ outustr("j");
+ oututstr((str_flags - 0x70)[opc]);
+ Jb();
+}
+
+PRIVATE void i_80(opc)
+opcode_pt opc;
+{
+ if (opc >= 4)
+ {
+ outustr(opc >= 6 ? "xchg\t" : "test\t");
+ outad(opc);
+ }
+ else
+ {
+ getmodregrm();
+ oututstr(str_00_to_3f[reg]);
+ outbwptr(opc);
+ outea(opc);
+ outcomma();
+ outimmed(opc);
+#ifdef SIGNED_LOGICALS
+ if (opc & SIGNBIT && (reg == 1 || reg == 4 || reg == 6))
+ /* and, or and xor with signe extension are not documented in some
+ * 8086 and 80286 manuals, but make sense and work
+ */
+ outfishy();
+#endif
+ }
+}
+
+PRIVATE void i_88(opc)
+opcode_pt opc;
+{
+ if (opc < 4)
+ {
+ outustr(movtab);
+ outad(opc);
+ }
+ else if (opc == 5)
+ {
+ oututstr("lea");
+ GvM();
+ }
+ else if (opc == 7)
+ {
+ oututstr("pop");
+ getmodregrm();
+ outwptr();
+ Ev();
+ if (reg != 0)
+ outfishy();
+ }
+ else
+ {
+ getmodregrm();
+ outustr(movtab);
+ if (!(opc & TOREGBIT))
+ {
+ Ev();
+ outcomma();
+ }
+ outustr(segreg[reg]);
+ if (opc & TOREGBIT)
+ {
+ outcomma();
+ Ev();
+ }
+ }
+}
+
+PRIVATE void i_90(opc)
+opcode_pt opc;
+{
+ if (opc == 0)
+ outustr("nop");
+ else
+ {
+ outustr("xchg\t");
+ outax();
+ outcomma();
+ outustr(genreg[hosize + opc]);
+ }
+}
+
+PRIVATE void i_98(opc)
+opcode_pt opc;
+{
+ outustr((str_98 - 8)[opc + hosize]);
+ if (opc == 2)
+ outsegpc();
+}
+
+PRIVATE void i_a0(opc)
+opcode_pt opc;
+{
+ outustr(str_a0[opc]);
+ if (opc < 4)
+ {
+ mod = MEM0_MOD; /* fake */
+ reg = 0; /* fake ax */
+ if (hasize == 16)
+ rm = 5; /* fake [d16] */
+ else
+ rm = 6; /* fake [d32] */
+ outad1(opc ^ TOREGBIT);
+ }
+ else if (opc & 1)
+ outwsize();
+}
+
+PRIVATE void i_a8(opc)
+opcode_pt opc;
+{
+ outustr(str_a8[opc]);
+ if (opc < 2)
+ {
+ outalorx(opc);
+ outcomma();
+ outimmed(opc);
+ }
+ else if (opc & 1)
+ outwsize();
+}
+
+PRIVATE void i_b0(opc)
+opcode_pt opc;
+{
+ outustr(movtab);
+ outustr(genreg[opc]);
+ outcomma();
+ Ib();
+}
+
+PRIVATE void i_b8(opc)
+opcode_pt opc;
+{
+ outustr(movtab);
+ outustr(genreg[hosize + opc]);
+ outcomma();
+ Iv();
+}
+
+PRIVATE void i_c0(opc)
+opcode_pt opc;
+{
+ outustr(str_c0[opc]);
+ if (opc >= 6)
+ {
+ getmodregrm();
+ outbwptr(opc);
+ outea(opc);
+ outcomma();
+ outimmed(opc & WORDBIT);
+ if (reg != 0)
+ /* not completely decoded (like DEBUG) */
+ outfishy();
+ }
+ else if (opc >= 4)
+ GvMp();
+ else if (opc == 2)
+ Iv();
+ else if (opc < 2)
+ shift(opc);
+}
+
+PRIVATE void i_c8(opc)
+opcode_pt opc;
+{
+ outustr(str_c8[opc]);
+ if (opc == 0)
+ {
+ Iw();
+ outcomma();
+ Ib();
+ }
+ if (opc == 2)
+ Iv();
+ else if (opc == 5)
+ Ib();
+ else if (opc == 7 && hosize == 16)
+ outwsize();
+}
+
+PRIVATE void i_d0(opc)
+opcode_pt opc;
+{
+ opcode_pt aabyte;
+
+ if (opc < 4)
+ shift(opc | 0xD0);
+ else
+ {
+ outustr((str_d0 - 4)[opc]);
+ if (opc < 6 && (aabyte = get8()) != 0x0A)
+ {
+ outtab();
+ outh8(aabyte);
+ outfishy();
+ }
+ }
+}
+
+PRIVATE void i_d8(opc)
+opcode_pt opc;
+{
+ opcode_pt esc;
+ char *str;
+
+ getmodregrm();
+ esc = (opc << 3) | reg;
+ if ((str = (mod == REG_MOD ? str1_d8 : str_d8)[esc]) == NULL)
+ {
+escape:
+ oututstr("esc");
+ outh8(esc);
+ outcomma();
+ outea(0);
+ return;
+ }
+ if (*str == 0)
+ {
+ str = sstr_d8[str[1] + rm];
+ if (str == NULL)
+ goto escape;
+ outustr(str);
+ return;
+ }
+ outustr(str);
+ outtab();
+ if (mod == REG_MOD)
+ {
+ if (opc == 0 && reg != 2 && reg != 3)
+ outustr("st,");
+ outf1();
+ if (opc == 4 || opc == 6)
+ outustr(",st");
+ return;
+ }
+ switch(size_d8[esc])
+ {
+ case 4:
+ outustr("d");
+ /* FALL THROUGH */
+ case 2:
+ outwptr();
+ break;
+ case 8:
+ outustr("q");
+ outwptr();
+ break;
+ case 10:
+ outustr("t");
+ outbptr();
+ break;
+ default:
+ break;
+ }
+ outea(opc);
+}
+
+PRIVATE void i_e0(opc)
+opcode_pt opc;
+{
+ outustr(str_e0[opc]);
+ if (opc < 4)
+ Jb();
+ else if (opc < 6)
+ {
+ outalorx(opc);
+ outcomma();
+ Ib();
+ }
+ else
+ {
+ Ib();
+ outcomma();
+ outalorx(opc);
+ }
+}
+
+PRIVATE void i_e8(opc)
+opcode_pt opc;
+{
+ outustr(str_e8[opc]);
+ if (opc < 2)
+ Jv();
+ else if (opc == 2)
+ outsegpc();
+ else if (opc == 3)
+ Jb();
+ else
+ {
+ if (opc & TOREGBIT)
+ {
+ outustr(genreg[10]);
+ outcomma();
+ outalorx(opc);
+ }
+ else
+ {
+ outalorx(opc);
+ outcomma();
+ outustr(genreg[10]);
+ }
+ }
+}
+
+PRIVATE void i_f0(opc)
+opcode_pt opc;
+{
+ if (opc < 6)
+ outustr(str_f0[opc]);
+ else
+ {
+ getmodregrm();
+ outustr(sstr_f0[reg]);
+ outbwptr(opc);
+ outea(opc);
+ if (reg == 0)
+ {
+ outcomma();
+ outimmed(opc & WORDBIT);
+ }
+ }
+}
+
+PRIVATE void i_f8(opc)
+opcode_pt opc;
+{
+ if (opc < 6)
+ outustr(str_f8[opc]);
+ else
+ {
+ getmodregrm();
+ if (opc == 6 && reg >= 2)
+ outustr("fishy\t");
+ else
+ outustr(sstr_f8[reg]);
+ outbwptr(opc);
+ outea(opc);
+ }
+}
+
+PRIVATE void outad(opc)
+opcode_pt opc;
+{
+ getmodregrm();
+ outad1(opc);
+}
+
+PRIVATE void outad1(opc)
+opcode_pt opc;
+{
+ if (!(opc & TOREGBIT))
+ {
+ outea(opc);
+ outcomma();
+ }
+ if (opc & WORDBIT)
+ Gv1();
+ else
+ outustr(genreg[reg]);
+ if (opc & TOREGBIT)
+ {
+ outcomma();
+ outea(opc);
+ }
+}
+
+PRIVATE void outalorx(opc)
+opcode_pt opc;
+{
+ if (opc & WORDBIT)
+ outax();
+ else
+ outustr(genreg[0]);
+}
+
+PRIVATE void outax()
+{
+ outustr(genreg[hosize]);
+}
+
+PRIVATE void outbptr()
+{
+ outustr("byte ptr ");
+}
+
+PRIVATE void outbwptr(opc)
+opcode_pt opc;
+{
+ if (mod != REG_MOD)
+ {
+ if (opc & WORDBIT)
+ outwptr();
+ else
+ outbptr();
+ }
+}
+
+PRIVATE void outea(wordflags)
+opcode_pt wordflags;
+{
+ reg_pt base = 0;
+ reg_pt index = 0;
+ opcode_pt ss = 0;
+ opcode_pt ssindexbase = 0;
+
+ if (mod == REG_MOD)
+ outustr(genreg[hosize * (wordflags & WORDBIT) + rm]);
+ else
+ {
+ outbyte(LINDIRECT);
+ if (hasize == 16)
+ {
+ if (rm == 4)
+ {
+ base = (ssindexbase = get8()) & BASE_MASK;
+ if (mod == MEM0_MOD && base == 5)
+ outgetaddr();
+ else
+ outustr((genreg + 16)[base]);
+ ss = (ssindexbase & SS_MASK) >> SS_SHIFT;
+ if ((index = (ssindexbase & INDEX_MASK) >> INDEX_SHIFT) != 4)
+ {
+ outbyte('+');
+ outustr((genreg + 16)[index]);
+ outstr("\0\0\0*2\0*4\0*8\0" + (3 * ss));
+ }
+ }
+ else if (mod == MEM0_MOD && rm == 5)
+ outgetaddr();
+ else
+ outustr((genreg + 16)[rm]);
+ }
+ else if (mod == MEM0_MOD && rm == 6)
+ outgetaddr();
+ else
+ outustr(indreg[rm]);
+ if (mod == MEM1_MOD)
+ /* fake sign extension to get +- */
+ outimmed(SIGNBIT | WORDBIT);
+ else if (mod == MEM2_MOD)
+ {
+ outbyte('+');
+ outgetaddr();
+ }
+ outbyte(RINDIRECT);
+ if (hasize == 16 && rm == 4 && index == 4 && ss != 0)
+ outfishy();
+ }
+}
+
+PRIVATE void outf1()
+{
+ outustr("st(");
+ outbyte((int) (rm + '0'));
+ outbyte(')');
+}
+
+PRIVATE void outfishy()
+{
+ outustr("\t???");
+}
+
+PRIVATE void outgetaddr()
+{
+ offset_t off;
+ struct nlist *sp;
+
+ if (hasize == 16)
+ off = get32();
+ else
+ off = get16();
+
+ /* do we ever need to call finrval with DSEG ? */
+ if ((sp = findrval(uptr.off - (hasize / 4), CSEG)) != NULL)
+ {
+ outrel(sp, off);
+ *offptr++ = off;
+ }
+ else if ((sp = findsval(off, data_seg)) != NULL)
+ {
+ outsym(sp, off);
+ *offptr++ = off;
+ }
+ else if (hasize == 16)
+ outh32(off);
+ else
+ outh16((u16_pt) off);
+}
+
+PRIVATE void outimmed(signwordflag)
+opcode_pt signwordflag;
+{
+ su8_pt byte;
+
+ if (signwordflag & WORDBIT)
+ {
+ if (signwordflag & SIGNBIT)
+ {
+ if ((byte = get8s()) < 0)
+ {
+ outbyte('-');
+ byte = -byte;
+ }
+ else
+ outbyte('+');
+ outh8((u8_pt) byte);
+ }
+ else
+ Iv();
+ }
+ else
+ Ib();
+}
+
+PRIVATE void outpc(pc, f)
+offset_t pc;
+int f;
+{
+ struct nlist *sp;
+
+ if (hosize == 8)
+ pc = (u16_t) pc;
+ if ((sp = findrval(uptr.off - (hosize / 4), CSEG)) != NULL)
+ {
+ if (f == 1) pc -= uptr.off;
+ outrel(sp, pc);
+ *offptr++ = pc;
+ }
+ else if ((sp = findsval(pc, CSEG)) != NULL)
+ {
+ outsym(sp, pc);
+ *offptr++ = pc;
+ }
+ else if (hosize == 16)
+ outh32(pc);
+ else
+ outh16((u16_pt) pc);
+}
+
+PRIVATE void outsegpc()
+{
+ offset_t oldbase;
+ offset_t pc;
+
+ if (hosize == 16)
+ pc = get32();
+ else
+ pc = get16();
+ oldbase = uptr.base;
+ outh16((u16_t) (uptr.base = get16())); /* fake seg for lookup of pc */
+ /* TODO - convert to offset in protected mode */
+ /* ### can this ever be a reloc structure ? */
+ outbyte(':');
+ outpc(pc, 0);
+ uptr.base = oldbase;
+}
+
+PRIVATE void oututstr(s)
+char *s;
+{
+ outustr(s);
+ outtab();
+}
+
+PRIVATE void outword()
+{
+ outustr("dword " + ((16 - hosize) >> 3));
+}
+
+PRIVATE void outwptr()
+{
+ outword();
+ outustr("ptr ");
+}
+
+PRIVATE void outwsize()
+{
+ if (hosize == 16)
+ outustr("d");
+ else
+ outustr("w");
+}
+
+PRIVATE void pagef()
+{
+ opcode_pt opc;
+ bool_t regbad;
+
+ if ((opc = get8()) <= 1 || opc == 0xBA)
+ {
+ if (opc == 0xBA)
+ opc = 16;
+ else
+ opc *= 8;
+ getmodregrm();
+ outustr(ssstr_0f[opc += reg]);
+ if (opc < 6 || opc == 12 || opc == 14)
+ Ew();
+ else if (opc >= 8 && opc < 13)
+ Ms();
+ else if (opc >= 20)
+ {
+ outbwptr(WORDBIT);
+ EvIb();
+ }
+ }
+ else if (opc < 4)
+ {
+ oututstr("lar\0lsl" + 4 * (opc - 2));
+ GvEw();
+ }
+ else if (opc == 5)
+ {
+ outustr("loadall");
+ outfishy();
+ }
+ else if (opc == 6)
+ outustr("clts");
+ else if (opc < 0x20)
+ outstr(fishy);
+ else if (opc < 0x27 && opc != 0x25)
+ {
+ outustr(movtab);
+ getmodregrm();
+ hosize = 16;
+ if (!(opc & TOREGBIT))
+ {
+ Ev(); /* Rd() since hosize is 16 */
+ outcomma();
+ }
+ regbad = FALSE;
+ if (opc & 1)
+ {
+ outustr("dr");
+ if (reg == 4 || reg == 5)
+ regbad = TRUE;
+ }
+ else if (opc < 0x24)
+ {
+ outustr("cr");
+ if (reg >= 4 || reg == 1)
+ regbad = TRUE;
+ }
+ else
+ {
+ outustr("tr");
+ if (reg < 6)
+ regbad = TRUE;
+ }
+ outbyte((int) (reg + '0'));
+ if (opc & TOREGBIT)
+ {
+ outcomma();
+ Ev();
+ }
+ if (regbad || mod != REG_MOD)
+ outfishy();
+ }
+ else if (opc < 0x80)
+ outstr(fishy);
+ else if (opc < 0x90)
+ {
+ outustr("j");
+ oututstr((str_flags - 0x80)[opc]);
+ Jv();
+ }
+ else if (opc < 0xA0)
+ {
+ outustr("set");
+ oututstr((str_flags - 0x90)[opc]);
+ getmodregrm();
+ outbwptr(0);
+ Eb();
+ }
+ else if (opc < 0xC0)
+ {
+ outustr((sstr_0f - 0xA0)[opc]);
+ switch (opc)
+ {
+ case 0xA3:
+ case 0xAB:
+ case 0xB3:
+ case 0xBB:
+ EvGv();
+ break;
+ case 0xA4:
+ case 0xAC:
+ EvGv();
+ outcomma();
+ Ib();
+ break;
+ case 0xA5:
+ case 0xAD:
+ EvGv();
+ outcomma();
+ CL();
+ break;
+ case 0xAF:
+ case 0xBC:
+ case 0xBD:
+ GvEv();
+ break;
+ case 0xB2:
+ case 0xB4:
+ case 0xB5:
+ GvMp();
+ break;
+ case 0xB6:
+ case 0xBE:
+ Gv();
+ outcomma();
+ outbwptr(opc);
+ Eb();
+ break;
+ case 0xB7:
+ case 0xBF:
+ Gv();
+ outcomma();
+ hosize = 8; /* done in Ew(), but too late */
+ outbwptr(opc);
+ Ew();
+ break;
+ default:
+ break;
+ }
+ }
+ else
+ outstr(fishy);
+}
+
+PUBLIC bool_pt puti()
+{
+ static bool_t hadprefix = FALSE;
+ opcode_pt opcode;
+
+ nop_flg = TRUE;
+
+more:
+ offptr = offtable;
+ opcode = get8();
+ nop_flg = (nop_flg && (opcode == '\0'));
+ if (!hadprefix)
+ {
+ data_seg = DSEG;
+ hdefsize = 8;
+ if (bits32)
+ hdefsize = 16;
+ hosize = hasize = hdefsize;
+ }
+ (*optable[opcode >> 3])(opcode < 0x80 ? opcode : opcode & 7);
+ if (offptr > offtable)
+ {
+ if (stringtab() >= 31)
+ {
+ outspace();
+ outspace();
+ }
+ else
+ while (stringtab() < 32)
+ outtab();
+ outbyte(';');
+ for (off1ptr = offtable; off1ptr < offptr; ++off1ptr)
+ {
+ outspace();
+ if (*off1ptr < 0x10000)
+ outh16((u16_t) *off1ptr);
+ else
+ outh32(*off1ptr);
+ }
+ offptr = offtable;
+ }
+ if ((opcode & 0xE7) == 0x26 ||
+ opcode >= 0x64 && opcode < 0x68 ||
+ opcode == 0xF0 || opcode == 0xF2 || opcode == 0xF3)
+ /* not finished instruction for 0x26, 0x2E, 0x36, 0x3E seg overrides
+ * and 0x64, 0x65 386 seg overrides
+ * and 0x66, 0x67 386 size prefixes
+ * and 0xF0 lock, 0xF2 repne, 0xF3 rep
+ */
+ {
+ hadprefix = TRUE;
+ goto more; /* TODO - print prefixes better */
+ return FALSE;
+ }
+ hadprefix = FALSE;
+ return TRUE;
+}
+
+PRIVATE void shift(opc)
+opcode_pt opc;
+{
+ getmodregrm();
+ oututstr(sstr_d0[reg]);
+ outbwptr(opc);
+ outea(opc);
+ outcomma();
+ if (opc < 0xD0)
+ Ib();
+ else if (opc & 2)
+ CL();
+ else
+ outbyte('1');
+}
+
+PRIVATE void checkmemory()
+{
+ if (mod == REG_MOD)
+ outfishy();
+}
+
+PRIVATE void CL()
+{
+ outustr(genreg[1]);
+}
+
+PRIVATE void Eb()
+{
+ outea(0);
+}
+
+PRIVATE void Ev()
+{
+ outea(WORDBIT);
+}
+
+PRIVATE void EvGv()
+{
+ getmodregrm();
+ Ev();
+ outcomma();
+ Gv1();
+}
+
+PRIVATE void EvIb()
+{
+ Ev();
+ outcomma();
+ Ib();
+}
+
+PRIVATE void Ew()
+{
+ hosize = 8;
+ Ev();
+}
+
+PRIVATE void EwRw()
+{
+ hosize = 8;
+ EvGv();
+}
+
+PRIVATE void Gv()
+{
+ getmodregrm();
+ Gv1();
+}
+
+PRIVATE void Gv1()
+{
+ outustr(genreg[hosize + reg]);
+}
+
+PRIVATE void GvEv()
+{
+ Gv();
+ outcomma();
+ Ev();
+}
+
+PRIVATE void GvEw()
+{
+ Gv();
+ outcomma();
+ Ew();
+}
+
+PRIVATE void GvM()
+{
+ GvEv();
+ checkmemory();
+}
+
+PRIVATE void GvMa()
+{
+ GvM();
+}
+
+PRIVATE void GvMp()
+{
+ GvM();
+}
+
+PRIVATE void Ib()
+{
+ outh8(get8());
+}
+
+PRIVATE void Iw()
+{
+ outh16(get16());
+}
+
+PRIVATE void Iv()
+{
+#if 1
+ offset_t pcjump;
+
+ if (hosize == 16)
+ pcjump = get32();
+ else
+ pcjump = (su16_t) get16();
+ outpc(pcjump, 0);
+#else
+ if (hosize == 16)
+ outh32(get32());
+ else
+ Iw();
+#endif
+}
+
+PRIVATE void Jb()
+{
+ /* jump can be in either direction */
+ int pcjump;
+
+ pcjump = get8s();
+ outpc(pcjump + uptr.off, 1);
+}
+
+PRIVATE void Jv()
+{
+ offset_t pcjump;
+
+ if (hosize == 16)
+ pcjump = get32();
+ else
+ pcjump = (su16_t) get16();
+ outpc((long)pcjump + uptr.off, 1);
+}
+
+PRIVATE void Ms()
+{
+ Ev();
+ checkmemory();
+}
+
+/*
+ * EOF
+ */
+
--- /dev/null
+/* var.h - variables for db.
+ *
+ * $Id: var.h,v 1.1 1997/10/20 12:00:00 cwr Exp cwr $
+ */
+
+EXTERN bool_t bits32;
+EXTERN unsigned processor;
+EXTERN char_pt prompt;
+EXTERN bool_t protected;
+EXTERN offset_t addrbase;
+EXTERN struct regs_s regs;
+EXTERN struct specregs_s specregs;
+EXTERN struct address_s uptr;
+