dis386 - a disassembler for ack

- it can disassemble object files (dis386o) and executables
    (dis386a)
  - only useful for as long as we still have ack
This commit is contained in:
Ben Gras 2010-10-04 13:26:53 +00:00
parent e2570d9b1b
commit 98ddbffe6e
12 changed files with 5255 additions and 1 deletions

View file

@ -9,7 +9,7 @@ SUBDIR= aal add_route adduser advent arp ash at autil awk \
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 \

9
commands/dis386/Makefile Normal file
View file

@ -0,0 +1,9 @@
# 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>

56
commands/dis386/const.h Normal file
View file

@ -0,0 +1,56 @@
/* 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

View file

@ -0,0 +1,77 @@
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 */

46
commands/dis386/dis386.h Normal file
View file

@ -0,0 +1,46 @@
/*
* 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
*/

1036
commands/dis386/dise.c Normal file

File diff suppressed because it is too large Load diff

1322
commands/dis386/diso.c Normal file

File diff suppressed because it is too large Load diff

937
commands/dis386/misc.c Normal file
View file

@ -0,0 +1,937 @@
/*
* 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
*/

127
commands/dis386/out.h Normal file
View file

@ -0,0 +1,127 @@
/*
* (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 */

212
commands/dis386/type.h Normal file
View file

@ -0,0 +1,212 @@
/* 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));

1418
commands/dis386/unasm.c Normal file

File diff suppressed because it is too large Load diff

14
commands/dis386/var.h Normal file
View file

@ -0,0 +1,14 @@
/* 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;