seem to have made it work (runtime debugging and core reading).
cd kermit && $(MAKE) $@
cd m4 && $(MAKE) $@
cd make && $(MAKE) $@
+ cd mdb && $(MAKE) $@
cd mined && $(MAKE) $@
cd patch && $(MAKE) $@
cd ps && $(MAKE) $@
--- /dev/null
+Mdb (Minix debugger) Distribution
+=================================
+
+Version: 2.6.0
+Date: Sept 9/96
+Author: Philip Murton
+E-mail: philip.murton@utoronto.ca
+
+
+Files included:
+===============
+
+Dist This file
+Makefile Makefile
+MDB.TXT Cover file
+README README file
+a.out.h GNU a.out.h (copied to /usr/include/gnu)
+core.c core file functions
+decode.c Optional for syscalls support
+gnu_load.c Optional for GNU EXEC support
+io.c I/O done here
+ioctl.c Optional for syscalls support
+kernel.c kernel functions
+log Log from sample command file (See README)
+mdb.c main program
+mdb.h main header
+mdb.1 man page
+mdbdis86.c Disassembler
+mdbexp.c Expression parsing
+misc.c misc functions including help
+gnu_sym.c Optional for GNU EXEC support
+proto.h Prototypes
+ptrace.2 man page
+sample sample command file
+sym.c Symbolic names read from exec file
+syscalls.c Optional for syscalls support
+trace.c ptrace() called here
+
--- /dev/null
+INFORMATION on mdb version 2.6.0 (Sept 9/96).
+
+MDB is the MINIX debugger which allows you to place breakpoints and
+control the execution of a program. It has a lot of the features that
+you would expect in a program debugger; for example, stack traces and
+single step execution.
+
+The current version works with MINIX for PC and was developed and tested
+under MINIX 1.7.x (32 bit version). It should work with 16 bit MINIX.
+
+How to Install
+
+1) Unpack mdb.tar.Z and review additional information in the README file.
+ (If you got this from the Minix CD-ROM or an MS-DOS system rename
+ MDB.TAZ to mdb.tar.Z)
+2) Edit Makefile for Compiler and extra options as required.
+3) make
+4) make install
+5) make install_man
+
+Comments to:
+
+Philip Murton.
+philip.murton@utoronto.ca
+
--- /dev/null
+#
+# Makefile for mdb
+#
+#
+# Edit as indicated below.
+#
+USR =/usr
+#
+# (1) For Compiler and target system:
+#
+#
+# For ANSI C and Minix 1.7.x 32-bit
+#
+CC =exec cc -O2
+LD =exec cc
+LDFLAGS =-i
+TARGET =mdb
+STACK =100000
+#
+# (2) If kernel and mm are not in "/usr/src" change this
+#
+SYSTEM =$(USR)/src
+#
+# (3) Select Options
+#
+# i) For GNU_EXEC Support, uncomment:
+#
+#FOR_GNU =gnu_sym.o gnu_load.o
+#DEF_GNU =-DGNU_SUPPORT
+#
+# ii) For tracing of syscalls, uncomment:
+#
+#FOR_SYSCALLS =syscalls.o decode.o ioctl.o
+#DEF_SYSCALLS =-DSYSCALLS_SUPPORT
+#
+# iii) For no debugging of mdb, uncomment:
+#
+#DEF_DEBUG =-DNDEBUG
+
+EXTRA_OBJS =$(FOR_GNU) $(FOR_SYSCALLS)
+EXTRA_DEFS =$(DEF_GNU) $(DEF_SYSCALLS) $(DEF_DEBUG)
+
+all: $(TARGET)
+
+CFLAGS =-I$(SYSTEM) -I$(SYSTEM)/servers -I$(INCLUDE) -D_MINIX -D_POSIX_SOURCE $(EXTRA_DEFS)
+
+# For various included files or system files
+#
+INCLUDE =$(USR)/include
+KERNEL =$(SYSTEM)/kernel
+PTRACE =$(INCLUDE)/sys/ptrace.h
+
+
+# Header files from pm (used by core.c)
+#
+MMFILES= $(SYSTEM)/servers/pm/const.h \
+ $(SYSTEM)/servers/pm/type.h \
+ $(SYSTEM)/servers/pm/mproc.h
+
+# Header files from system and kernel in "mdb.h"
+#
+SYSFILES= $(INCLUDE)/minix/config.h \
+ $(INCLUDE)/minix/const.h \
+ $(INCLUDE)/ansi.h \
+ $(INCLUDE)/minix/type.h \
+ $(INCLUDE)/limits.h \
+ $(INCLUDE)/errno.h \
+ $(INCLUDE)/sys/types.h \
+ $(KERNEL)/const.h \
+ $(KERNEL)/type.h \
+ $(KERNEL)/proc.h
+
+# Common objects
+#
+OBJCOMMON =mdb.o mdbexp.o kernel.o sym.o trace.o core.o misc.o io.o
+
+# Common source
+#
+SRCCOMMON =mdb.c mdbexp.c kernel.o sym.c trace.c core.c misc.c io.c
+
+# Object files for PC
+#
+OBJPC =$(OBJCOMMON) mdbdis86.o
+
+# Source file
+#
+SRCPC =$(SRCCOMMON) mdbdis86.c
+
+
+mdb: $(OBJPC) $(EXTRA_OBJS)
+ $(LD) $(LDFLAGS) -o mdb $(OBJPC) $(EXTRA_OBJS)
+ install -S $(STACK) mdb
+
+#
+# Dependencies for objects
+#
+mdb.o: mdb.c mdb.h
+mdbdis86.o: mdbdis86.c mdb.h
+mdbexp.o: mdbexp.c mdb.h
+sym.o: sym.c mdb.h
+trace.o: trace.c mdb.h $(PTRACE)
+core.o: core.c mdb.h $(MMFILES)
+misc.o: misc.c mdb.h
+io.o: io.c mdb.h
+mdb.h: $(SYSFILES) proto.h
+
+syscalls.o: syscalls.c mdb.h
+decode.o: decode.c mdb.h $(INCLUDE)/minix/callnr.h
+ioctl.o: ioctl.c mdb.h
+
+gnu_sym.o: gnu_sym.c mdb.h $(INCLUDE)/gnu/a.out.h
+gnu_load.o: gnu_load.c $(INCLUDE)/gnu/a.out.h
+
+$(INCLUDE)/gnu/a.out.h: a.out.h
+ install -c -o bin a.out.h $(INCLUDE)/gnu
+
+
+#
+# install
+#
+
+install: mdb
+ install -cs -o bin mdb /usr/local/bin
+
+install_man: mdb.1 ptrace.2
+ install -c -o bin mdb.1 /usr/man/man1
+ install -c -o bin ptrace.2 /usr/man/man2
+clean:
+ rm -f *.o mdb
+
--- /dev/null
+README for mdb version 2.6.0
+
+Sept 9/96
+
+Please note the following:
+
+1) Has been tested with Minix 1.7.4 (32-bit version).
+ A previous version was tested with Minix 1.7.x (16 bit version).
+ Some optional parts of mdb have not been extensively tested.
+ This is especially true on the code to trace system calls.
+ See options in Makefile.
+
+2) I know that the commands are somewhat cryptic; thus
+ there are currently two types of 'help' for mdb
+ a) the "?" gives a help page.
+ b) typing "command ?" will give help on a specific command.
+
+3) The sample comand file and log output.
+ To test this, type something like the following
+ "mdb -llog.new /usr/bin/sleep @sample"
+ The output "log.new' should be similar to the distributed "log" file;
+ but not necessarily exactly the same.
+
+4) Man pages need some more work.
+
+5) See top part of mdb.c for version history.
+
+Send comments to Philip Murton. Thanks.
+
+philip.murton@utoronto.ca
+
+
--- /dev/null
+/*
+ * MINIX 1.7.x
+ * GNU version based on Linux 1.1.45 version
+ * if _MINIX_EXEC defined use old MINIX GNU format
+ */
+
+#ifndef __A_OUT_GNU_H__
+#define __A_OUT_GNU_H__
+
+#define __GNU_EXEC_MACROS__
+
+#ifndef __STRUCT_EXEC_OVERRIDE__
+
+struct exec
+{
+ unsigned long a_info; /* Use macros N_MAGIC, etc for access */
+ unsigned a_text; /* length of text, in bytes */
+ unsigned a_data; /* length of data, in bytes */
+ unsigned a_bss; /* length of uninitialized data area for file, in bytes */
+ unsigned a_syms; /* length of symbol table data in file, in bytes */
+ unsigned a_entry; /* start address */
+ unsigned a_trsize; /* length of relocation info for text, in bytes */
+ unsigned a_drsize; /* length of relocation info for data, in bytes */
+#ifdef _MINIX_EXEC
+ unsigned a_smagic; /* SMAGIC */
+ unsigned a_memsize; /* Dynamic Memory Size */
+#endif
+};
+
+#ifdef _MINIX_EXEC
+#define GNU_SMAGIC 0xdeadbabe
+#define GNU_DYNMEM (64 * 1024)
+#else
+#define GNU_STACK 64 /* Default Stack */
+#endif
+
+#endif /* __STRUCT_EXEC_OVERRIDE__ */
+
+/* these go in the N_MACHTYPE field */
+enum machine_type {
+#if defined (M_OLDSUN2)
+ M__OLDSUN2 = M_OLDSUN2,
+#else
+ M_OLDSUN2 = 0,
+#endif
+#if defined (M_68010)
+ M__68010 = M_68010,
+#else
+ M_68010 = 1,
+#endif
+#if defined (M_68020)
+ M__68020 = M_68020,
+#else
+ M_68020 = 2,
+#endif
+#if defined (M_SPARC)
+ M__SPARC = M_SPARC,
+#else
+ M_SPARC = 3,
+#endif
+ /* skip a bunch so we don't run into any of sun's numbers */
+ M_386 = 100
+};
+
+#if !defined (N_MAGIC)
+#define N_MAGIC(exec) ((exec).a_info & 0xffff)
+#endif
+#define N_MACHTYPE(exec) ((enum machine_type)(((exec).a_info >> 16) & 0xff))
+#define N_FLAGS(exec) (((exec).a_info >> 24) & 0xff)
+#define N_SET_INFO(exec, magic, type, flags) \
+ ((exec).a_info = ((magic) & 0xffff) \
+ | (((int)(type) & 0xff) << 16) \
+ | (((flags) & 0xff) << 24))
+#define N_SET_MAGIC(exec, magic) \
+ ((exec).a_info = (((exec).a_info & 0xffff0000) | ((magic) & 0xffff)))
+
+#define N_SET_MACHTYPE(exec, machtype) \
+ ((exec).a_info = \
+ ((exec).a_info&0xff00ffff) | ((((int)(machtype))&0xff) << 16))
+
+#define N_SET_FLAGS(exec, flags) \
+ ((exec).a_info = \
+ ((exec).a_info&0x00ffffff) | (((flags) & 0xff) << 24))
+
+#ifdef _MINIX
+#define N_SET_MEMORY(exec, mem) \
+ ((exec).a_info = \
+ ((exec).a_info & 0x0000FFFF) | (((mem) & 0xFFFF) << 16))
+#define N_MEMORY(exec) (((exec).a_info >> 16) & 0xFFFF)
+#endif
+
+/* Code indicating object file or impure executable. */
+#define OMAGIC 0407
+/* Code indicating pure executable. */
+#define NMAGIC 0410
+/* Code indicating demand-paged executable. */
+#define ZMAGIC 0413
+/* This indicates a demand-paged executable with the header in the text.
+ The first page is unmapped to help trap NULL pointer references */
+#define QMAGIC 0314
+
+/* Code indicating core file. */
+#define CMAGIC 0421
+
+#if !defined (N_BADMAG)
+#define N_BADMAG(x) (N_MAGIC(x) != OMAGIC \
+ && N_MAGIC(x) != NMAGIC \
+ && N_MAGIC(x) != ZMAGIC \
+ && N_MAGIC(x) != QMAGIC)
+#endif
+
+#define _N_HDROFF(x) (1024 - sizeof (struct exec))
+
+#if !defined (N_TXTOFF)
+#define N_TXTOFF(x) \
+ (N_MAGIC(x) == ZMAGIC ? _N_HDROFF((x)) + sizeof (struct exec) : \
+ (N_MAGIC(x) == QMAGIC ? 0 : sizeof (struct exec)))
+#endif
+
+#if !defined (N_DATOFF)
+#define N_DATOFF(x) (N_TXTOFF(x) + (x).a_text)
+#endif
+
+#if !defined (N_TRELOFF)
+#define N_TRELOFF(x) (N_DATOFF(x) + (x).a_data)
+#endif
+
+#if !defined (N_DRELOFF)
+#define N_DRELOFF(x) (N_TRELOFF(x) + (x).a_trsize)
+#endif
+
+#if !defined (N_SYMOFF)
+#define N_SYMOFF(x) (N_DRELOFF(x) + (x).a_drsize)
+#endif
+
+#if !defined (N_STROFF)
+#define N_STROFF(x) (N_SYMOFF(x) + (x).a_syms)
+#endif
+
+/* Address of text segment in memory after it is loaded. */
+#if !defined (N_TXTADDR)
+#define N_TXTADDR(x) (N_MAGIC(x) == QMAGIC ? PAGE_SIZE : 0)
+#endif
+
+/* Address of data segment in memory after it is loaded.
+ Note that it is up to you to define SEGMENT_SIZE
+ on machines not listed here. */
+#if defined(vax) || defined(hp300) || defined(pyr)
+#define SEGMENT_SIZE page_size
+#endif
+#ifdef sony
+#define SEGMENT_SIZE 0x2000
+#endif /* Sony. */
+#ifdef is68k
+#define SEGMENT_SIZE 0x20000
+#endif
+#if defined(m68k) && defined(PORTAR)
+#define PAGE_SIZE 0x400
+#define SEGMENT_SIZE PAGE_SIZE
+#endif
+
+#ifndef PAGE_SIZE
+#define PAGE_SIZE 1024
+#endif
+
+#ifndef SEGMENT_SIZE
+#define SEGMENT_SIZE PAGE_SIZE
+#endif
+
+#define _N_SEGMENT_ROUND(x) (((x) + SEGMENT_SIZE - 1) & ~(SEGMENT_SIZE - 1))
+
+#define _N_TXTENDADDR(x) (N_TXTADDR(x)+(x).a_text)
+
+#ifndef N_DATADDR
+#define N_DATADDR(x) \
+ (N_MAGIC(x)==OMAGIC? (_N_TXTENDADDR(x)) \
+ : (_N_SEGMENT_ROUND (_N_TXTENDADDR(x))))
+#endif
+
+/* Address of bss segment in memory after it is loaded. */
+#if !defined (N_BSSADDR)
+#define N_BSSADDR(x) (N_DATADDR(x) + (x).a_data)
+#endif
+\f
+#if !defined (N_NLIST_DECLARED)
+struct nlist {
+ union {
+ char *n_name;
+ struct nlist *n_next;
+ long n_strx;
+ } n_un;
+ unsigned char n_type;
+ char n_other;
+ short n_desc;
+ unsigned long n_value;
+};
+#endif /* no N_NLIST_DECLARED. */
+
+#if !defined (N_UNDF)
+#define N_UNDF 0
+#endif
+#if !defined (N_ABS)
+#define N_ABS 2
+#endif
+#if !defined (N_TEXT)
+#define N_TEXT 4
+#endif
+#if !defined (N_DATA)
+#define N_DATA 6
+#endif
+#if !defined (N_BSS)
+#define N_BSS 8
+#endif
+#if !defined (N_FN)
+#define N_FN 15
+#endif
+
+#if !defined (N_EXT)
+#define N_EXT 1
+#endif
+#if !defined (N_TYPE)
+#define N_TYPE 036
+#endif
+#if !defined (N_STAB)
+#define N_STAB 0340
+#endif
+
+/* The following type indicates the definition of a symbol as being
+ an indirect reference to another symbol. The other symbol
+ appears as an undefined reference, immediately following this symbol.
+
+ Indirection is asymmetrical. The other symbol's value will be used
+ to satisfy requests for the indirect symbol, but not vice versa.
+ If the other symbol does not have a definition, libraries will
+ be searched to find a definition. */
+#define N_INDR 0xa
+
+/* The following symbols refer to set elements.
+ All the N_SET[ATDB] symbols with the same name form one set.
+ Space is allocated for the set in the text section, and each set
+ element's value is stored into one word of the space.
+ The first word of the space is the length of the set (number of elements).
+
+ The address of the set is made into an N_SETV symbol
+ whose name is the same as the name of the set.
+ This symbol acts like a N_DATA global symbol
+ in that it can satisfy undefined external references. */
+
+/* These appear as input to LD, in a .o file. */
+#define N_SETA 0x14 /* Absolute set element symbol */
+#define N_SETT 0x16 /* Text set element symbol */
+#define N_SETD 0x18 /* Data set element symbol */
+#define N_SETB 0x1A /* Bss set element symbol */
+
+/* This is output from LD. */
+#define N_SETV 0x1C /* Pointer to set vector in data area. */
+\f
+#if !defined (N_RELOCATION_INFO_DECLARED)
+/* This structure describes a single relocation to be performed.
+ The text-relocation section of the file is a vector of these structures,
+ all of which apply to the text section.
+ Likewise, the data-relocation section applies to the data section. */
+
+struct relocation_info
+{
+ /* Address (within segment) to be relocated. */
+ int r_address;
+ /* The meaning of r_symbolnum depends on r_extern. */
+ unsigned int r_symbolnum:24;
+ /* Nonzero means value is a pc-relative offset
+ and it should be relocated for changes in its own address
+ as well as for changes in the symbol or section specified. */
+ unsigned int r_pcrel:1;
+ /* Length (as exponent of 2) of the field to be relocated.
+ Thus, a value of 2 indicates 1<<2 bytes. */
+ unsigned int r_length:2;
+ /* 1 => relocate with value of symbol.
+ r_symbolnum is the index of the symbol
+ in file's the symbol table.
+ 0 => relocate with the address of a segment.
+ r_symbolnum is N_TEXT, N_DATA, N_BSS or N_ABS
+ (the N_EXT bit may be set also, but signifies nothing). */
+ unsigned int r_extern:1;
+ /* Four bits that aren't used, but when writing an object file
+ it is desirable to clear them. */
+#ifdef NS32K
+ unsigned r_bsr:1;
+ unsigned r_disp:1;
+ unsigned r_pad:2;
+#else
+ unsigned int r_pad:4;
+#endif
+};
+#endif /* no N_RELOCATION_INFO_DECLARED. */
+
+
+#endif /* __A_OUT_GNU_H__ */
--- /dev/null
+/*
+ * core.c for mdb
+ *
+ * reads information from 'core' file
+ * Partly derived from 'adb' by D. Dugger.
+ */
+#include <pm/const.h>
+
+#include "mdb.h"
+
+#include <signal.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/ptrace.h>
+
+#include <pm/type.h>
+#include <pm/mproc.h>
+
+#include <kernel/const.h>
+#include <kernel/type.h>
+#include <kernel/proc.h>
+
+/* defined in kernel.c */
+extern struct proc *prc;
+
+#include "proto.h"
+
+#define BSIZE 512
+#define LOGBS 9
+
+PRIVATE struct file {
+ int fid;
+ char *name;
+ long cblock;
+ long tmap[3];
+ long dmap[3];
+ long smap[3];
+ char buf[BSIZE + BSIZE];
+} Core_File, *core_file;
+
+#define b1 tmap[0]
+#define e1 tmap[1]
+#define f1 tmap[2]
+#define b2 dmap[0]
+#define e2 dmap[1]
+#define f2 dmap[2]
+#define b3 smap[0]
+#define e3 smap[1]
+#define f3 smap[2]
+
+PRIVATE long cnt[3]; /* Sizes of segments */
+PRIVATE int h_size; /* Size of core header */
+PRIVATE char def_name[] = "core"; /* Default core name */
+
+#define SIZE_MP_SEG (sizeof(struct mem_map) * NR_LOCAL_SEGS)
+#define SIZE_KINFO sizeof(struct proc)
+#define SIZE_HEADER SIZE_MP_SEG
+
+FORWARD _PROTOTYPE( int kernel_info , (int fd ));
+FORWARD _PROTOTYPE( void setmap , (struct file *fp ));
+FORWARD _PROTOTYPE( void read_info , (struct file *fp ));
+FORWARD _PROTOTYPE( void ill_addr , (long d , int segment ));
+FORWARD _PROTOTYPE( long map_addr , (long d , int segment ));
+FORWARD _PROTOTYPE( unsigned long c_status, (void));
+FORWARD _PROTOTYPE( long getn, (long d, int s) );
+
+/*
+ * set and display mapping for core file
+ */
+PRIVATE void setmap(fp)
+struct file *fp;
+{
+long h = (long) h_size;
+
+ fp->b1 = st_addr;
+ fp->e1 = st_addr + cnt[T];
+ fp->f1 = h;
+
+ fp->b2 = sd_addr;
+ fp->e2 = sd_addr + cnt[D];
+ fp->f2 = cnt[T] + h;
+
+ fp->b3 = sk_addr;
+ fp->e3 = sk_addr + cnt[S];
+ fp->f3 = cnt[T] + cnt[D] + h;
+
+#ifdef MINIX_PC
+ if(is_separate) {
+ if ( end_addr < et_addr ) end_addr = et_addr;
+ }
+ else {
+ fp->b2 = st_addr;
+ fp->e2 = st_addr + cnt[T] + cnt[D];
+ fp->f2 = h;
+ end_addr = fp->e2;
+
+ fp->b1 = 0;
+ fp->e1 = -1;
+ fp->f1 = 0;
+ }
+#endif
+ Printf("From core file:\n");
+ Printf("T\t%8lx %8lx %8lx\n", core_file->b1, core_file->e1, core_file->f1);
+ Printf("D\t%8lx %8lx %8lx\n", core_file->b2, core_file->e2, core_file->f2);
+ Printf("S\t%8lx %8lx %8lx\n", core_file->b3, core_file->e3, core_file->f3);
+ Printf("\n");
+
+}
+
+/* Print mapping */
+PUBLIC void prtmap()
+{
+ Printf("%s I & D space\t", (is_separate) ? "Separate " : "Combined ");
+ if (corepid > 0) {
+ Printf("File: %s\n\n", core_file->name);
+ setmap(core_file);
+ disp_maps();
+ }
+ else {
+ Printf("Pid: %d\n\n", curpid);
+ update();
+ disp_maps();
+ }
+}
+
+/* Illegal address */
+PRIVATE void ill_addr(d, segment)
+long d;
+int segment;
+{
+ Printf("Bad addr=%lx seg=%d",d,segment);
+ mdb_error("\n");
+}
+
+/* Map virtual address -> core file addresses
+ * depends on current segment if Separate I & D
+ */
+PRIVATE long map_addr(d, segment)
+long d;
+int segment;
+{
+#ifdef MINIX_PC
+ if (is_separate)
+ switch (segment) {
+ case T:
+ if (d >= core_file->b1 && d < core_file->e1)
+ d += core_file->f1 - core_file->b1;
+ else
+ ill_addr(d,segment);
+ break;
+ case D:
+ case S:
+ if (d >= core_file->b2 && d < core_file->e2)
+ d += core_file->f2 - core_file->b2;
+ else if (d >= core_file->b3 && d < core_file->e3)
+ d += core_file->f3 - core_file->b3;
+ else
+ ill_addr(d,segment);
+ break;
+ }
+ else {
+#endif
+ if (d >= core_file->b1 && d < core_file->e1)
+ d += core_file->f1 - core_file->b1;
+ else if (d >= core_file->b2 && d < core_file->e2)
+ d += core_file->f2 - core_file->b2;
+ else if (d >= core_file->b3 && d < core_file->e3)
+ d += core_file->f3 - core_file->b3;
+ else
+ ill_addr(d,segment);
+#ifdef MINIX_PC
+ }
+#endif
+ return d;
+}
+
+
+/* Get value with address d and segment s */
+PRIVATE long getn(d, s)
+long d;
+int s;
+{
+ long b;
+ register int o,i;
+ union {
+ unsigned long l;
+ unsigned char c[4];
+ } data;
+
+ /* Map address */
+ d = map_addr(d, s);
+
+ b = d >> LOGBS;
+ o = d & (BSIZE - 1);
+
+ if (core_file->cblock != b) {
+ core_file->cblock = b;
+ lseek(core_file->fid, b << LOGBS, 0);
+ read(core_file->fid, core_file->buf, sizeof(core_file->buf));
+ }
+
+ for(i = 0; i<4; i++)
+ data.c[i] = core_file->buf[o+i];
+
+#ifdef DEBUG
+ if (debug)
+ Printf("getn at %8lx val %8lx\n", d, data.l);
+#endif
+ return data.l;
+}
+
+/* Read kernel info from core file into lbuf[] */
+PRIVATE int kernel_info(fd)
+int fd;
+{
+ int r;
+ int ks;
+
+ /* Round SIZE_KINFO to multiple of sizeof(long) */
+ /* See mm/signal.c to see how a 'core' file is written */
+ ks = ( SIZE_KINFO / sizeof(long) ) * sizeof(long);
+ r = read(fd, (char *)lbuf, ks);
+ return(r == ks) ? ks : -1;
+}
+
+/*
+ * Print status info from core - returns PC
+ */
+PRIVATE unsigned long c_status()
+{
+ fprintf(stderr, "WARNING: don't know pid from core; using proc nr for pid.\n");
+
+ Printf("Proc = %6d\n", prc->p_nr);
+
+ /* Set current pid to that of core */
+ curpid = corepid = prc->p_nr;
+ disp_maps();
+ Printf("\nPC = 0x%0*lx\t", 2 * ADDRSIZE, PC_MEMBER(prc) & MASK(ADDRSIZE));
+ symbolic((long) PC_MEMBER(prc), '\n');
+ dasm((long) PC_MEMBER(prc), 1, 1);
+ return PC_MEMBER(prc);
+}
+
+/* Read memory maps and kernel info from core file */
+PRIVATE void read_info(fp)
+struct file *fp;
+{
+ struct mproc mm_info;
+ struct mproc *rmp;
+ int r;
+ int i;
+
+ rmp = &mm_info;
+ lseek(fp->fid, 0L, 0L);
+
+ /* First read memory map of all segments. */
+ if (read(fp->fid, (char *) rmp->mp_seg, (int) SIZE_MP_SEG) < 0) {
+ close(fp->fid);
+ Printf("mdb: cannot read core header\n");
+ fp->fid = -1;
+ return;
+ }
+ h_size = SIZE_HEADER;
+
+ /* Read kernel dependent info */
+ r = kernel_info(fp->fid);
+ if (r < 0) {
+ close(fp->fid);
+ Printf("mdb: cannot read kernel info from 'core' file\n");
+ fp->fid = -1;
+ return;
+ } else
+ h_size += r;
+
+ /* copy info */
+ for (i = T; i <= S; i++)
+ cnt[i] = (long) rmp->mp_seg[i].mem_len << CLICK_SHIFT;
+
+ /* This needs to be set for map_addr() below */
+ if(coreonly && cnt[T] != 0) is_separate = TRUE;
+
+ st_addr = (long) rmp->mp_seg[T].mem_vir << CLICK_SHIFT;
+ et_addr = st_addr + ((long) rmp->mp_seg[T].mem_len << CLICK_SHIFT);
+
+ sd_addr = (long) rmp->mp_seg[D].mem_vir << CLICK_SHIFT;
+ end_addr = ed_addr =
+ sd_addr + ((long) rmp->mp_seg[D].mem_len << CLICK_SHIFT);
+
+ sk_addr = (long) rmp->mp_seg[S].mem_vir << CLICK_SHIFT;
+ sk_size = (long) rmp->mp_seg[S].mem_len << CLICK_SHIFT;
+
+ setmap(fp);
+}
+
+/* initialization for core files
+ * returns PC address from core file
+ */
+PUBLIC unsigned long core_init(filename)
+char *filename;
+{
+ core_file = &Core_File;
+ core_file->name = (filename != NULL) ? filename : def_name;
+
+ core_file->fid = open(core_file->name, 0);
+ if (filename != NULL && core_file->fid < 0) {
+ Printf("mdb - warning cannot open: %s\n", core_file->name);
+ return -1;
+ }
+
+ core_file->b1 = core_file->b2 = core_file->b3 = 0;
+ core_file->e1 = core_file->e2 = core_file->e3 = -1;
+ core_file->f1 = core_file->f2 = core_file->f3 = 0;
+ core_file->cblock = -1;
+
+ if (core_file->fid > 0) {
+ read_info(core_file);
+ return c_status();
+ }
+ return 0;
+}
+
+
+/* initialization for a file ( -f option )
+ * always returns 0
+ * Similar to core files.
+ */
+PUBLIC unsigned long file_init(filename)
+char *filename;
+{
+ core_file = &Core_File;
+ core_file->name = (filename != NULL) ? filename : def_name;
+
+ core_file->fid = open(core_file->name, 0);
+ if (filename != NULL && core_file->fid < 0) {
+ Printf("mdb - warning cannot open: %s\n", core_file->name);
+ return -1;
+ }
+
+ core_file->b1 = core_file->b2 = core_file->b3 = 0;
+ core_file->e1 = core_file->e2 = core_file->e3 = -1;
+ core_file->f1 = core_file->f2 = core_file->f3 = 0;
+ core_file->cblock = -1;
+
+ is_separate = FALSE;
+ core_file->e1 = file_size(core_file->fid);
+ curpid = corepid = 1;
+ return 0;
+
+}
+
+/*
+ * Read from core file
+ * Called by mdbtrace()
+ */
+PUBLIC long read_core(req, addr, data)
+int req;
+long addr, data;
+{
+int i;
+int segment;
+long val;
+
+ switch (req) {
+ case T_GETINS:
+ case T_GETDATA:
+ /* Check segment and address - call getn to read core file */
+ segment = (req == T_GETINS) ? T : D;
+ addr &= MASK(ADDRSIZE);
+ val = getn(addr, segment);
+#ifdef DEBUG
+ if (debug) Printf("val=>%lx\n", val);
+#endif
+ return val;
+ break;
+ case T_GETUSER:
+ /* Convert addr to index to long array */
+ i = (int) (addr >> 2);
+#ifdef DEBUG
+ if (debug) Printf("lbuf[%d] %lx\n", i, lbuf[i]);
+#endif
+ return lbuf[i];
+ break;
+ case T_OK:
+ case T_EXIT:
+ return 0L;
+ break;
+ default:
+ mdb_error("Not supported with 'core' files\n");
+ }
+}
+
--- /dev/null
+/*
+ * decode.c for mdb -- decodes a Minix system call
+ */
+#include "mdb.h"
+#ifdef SYSCALLS_SUPPORT
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#define ptrace mdbtrace
+#include <sys/ptrace.h>
+#include <minix/type.h>
+#include <minix/callnr.h>
+#include "proto.h"
+
+FORWARD _PROTOTYPE( void get_message, (message *m, unsigned bx) );
+FORWARD _PROTOTYPE( void get_data, (char *s, unsigned bx, int cnt) );
+
+PRIVATE message sent;
+PRIVATE message recv;
+PRIVATE unsigned saved_addr;
+PRIVATE int last_call;
+
+#define NOSYS 0
+#define NOP 1
+
+#define _M1 0x0100
+#define _M2 0x0200
+#define _M3 0x0400
+#define _M4 0x0800
+
+#define _M13 0x0500
+
+#define M1_I1 (_M1|1)
+#define M1_I2 (_M1|2)
+#define M1_I3 (_M1|4)
+#define M1_P1 (_M1|8)
+#define M1_P2 (_M1|16)
+#define M1_P3 (_M1|32)
+
+#define M2_I1 (_M2|1)
+#define M2_I2 (_M2|2)
+#define M2_I3 (_M2|4)
+#define M2_L1 (_M2|8)
+#define M2_L2 (_M2|16)
+#define M2_P1 (_M2|32)
+
+#define M3_I1 (_M3|1)
+#define M3_I2 (_M3|2)
+#define M3_P1 (_M3|4)
+#define M3_C1 (_M3|8)
+
+#define M4_L1 (_M4|1)
+#define M4_L2 (_M4|2)
+#define M4_L3 (_M4|4)
+#define M4_L4 (_M4|8)
+#define M4_L5 (_M4|16)
+
+#define M13_OPEN (_M13|1)
+
+#define M1_I12 (M1_I1|M1_I2)
+#define M1_NAME1 (M1_I1|M1_P1)
+#define M1_NAME2 (M1_I2|M1_P2)
+#define M1_2NAMES (M1_I1|M1_P1|M1_I2|M1_P2)
+#define M1_SIGACTION (M1_I2|M1_P1|M1_P2|M1_P3)
+
+#define M2_IOCTL (M2_I1|M2_I3|M2_L1|M2_L2)
+#define M2_4P (M2_I1|M2_I2|M2_L1|M2_L2)
+#define M2_SIGRETURN (M2_I2|M2_L1|M2_P1)
+#define M2_SIGPROC (M2_I1|M2_L1)
+#define M2_UTIME (M2_I1|M2_I2|M2_L1|M2_L2|M2_P1)
+
+#define M3_LOAD (M3_I1|M3_C1)
+
+struct decode_system {
+ int syscall;
+ unsigned int sflag;
+ unsigned int rflag;
+ char *name;
+} decode[NCALLS] = {
+ 0, NOSYS, NOP, NULL,
+ EXIT, M1_I1, NOP, "EXIT",
+ FORK, NOP, NOP, "FORK",
+ READ, M1_I12, NOP, "READ",
+ WRITE, M1_I12, NOP, "WRITE",
+ OPEN, M13_OPEN, NOP, "OPEN",
+ CLOSE, M1_I1, NOP, "CLOSE",
+ WAIT, NOP, M2_I1, "WAIT",
+ CREAT, M3_LOAD, NOP, "CREAT",
+ LINK, M1_2NAMES, NOP, "LINK",
+ UNLINK, M3_LOAD, NOP, "UNLINK",
+ WAITPID, M1_I1, M2_I1, "WAITPID",
+ CHDIR, M3_LOAD, NOP, "CHDIR",
+ TIME, NOP, M2_L1, "TIME",
+ MKNOD, M1_NAME1, NOP, "MKNOD",
+ CHMOD, M3_LOAD, NOP, "CHMOD",
+ CHOWN, M1_NAME1, NOP, "CHOWN",
+ BRK, M1_P1, M2_P1, "BRK",
+ STAT, M1_NAME1, NOP, "STAT",
+ LSEEK, M1_I1, NOP, "LSEEK",
+ GETPID, NOP, NOP, "GETPID",
+ MOUNT, M1_2NAMES, NOP, "MOUNT",
+ UMOUNT, M3_LOAD, NOP, "UMOUNT",
+ SETUID, M1_I1, NOP, "SETUID",
+ GETUID, NOP, NOP, "GETUID",
+ STIME, M2_L1, NOP, "STIME",
+ PTRACE, M2_4P, NOP, "PTRACE",
+ ALARM, M1_I1, NOP, "ALARM",
+ FSTAT, M1_I1, NOP, "FSTAT",
+ PAUSE, NOP, NOP, "PAUSE",
+ UTIME, M2_UTIME, NOP, "UTIME",
+ 31, NOSYS, NOP, NULL,
+ 32, NOSYS, NOP, NULL,
+ ACCESS, M3_LOAD, NOP, "ACCESS",
+ 34, NOSYS, NOP, NULL,
+ 35, NOSYS, NOP, NULL,
+ SYNC, NOP, NOP, "SYNC",
+ KILL, M1_I12, NOP, "KILL",
+ RENAME, M1_2NAMES, NOP, "RENAME",
+ MKDIR, M1_NAME1, NOP, "MKDIR",
+ RMDIR, M3_LOAD, NOP, "RMDIR",
+ DUP, NOP, NOP, "DUP",
+ PIPE, NOP, M1_I12, "PIPE",
+ TIMES, M4_L5, NOP, "TIMES",
+ 44, NOSYS, NOP, NULL,
+ 45, NOSYS, NOP, NULL,
+ SETGID, M1_I1, NOP, "SETGID",
+ GETGID, NOP, NOP, "GETGID",
+ SIGNAL, NOP, NOP, "SIGNAL",
+ 49, NOSYS, NOP, NULL,
+ 50, NOSYS, NOP, NULL,
+ 51, NOSYS, NOP, NULL,
+ 52, NOSYS, NOP, NULL,
+ 53, NOSYS, NOP, NULL,
+ IOCTL, M2_IOCTL, M2_IOCTL, "IOCTL",
+ FCNTL, M1_I12, NOP, "FCNTL",
+#if ENABLE_SYMLINK
+ RDLINK, M1_NAME1, NOP, "RDLINK",
+ SLINK, M1_NAME1, NOP, "SLINK",
+ LSTAT, M1_NAME1, NOP, "LSTAT",
+#else
+ 56, NOSYS, NOP, NULL,
+ 57, NOSYS, NOP, NULL,
+ 58, NOSYS, NOP, NULL,
+#endif
+ EXEC, M1_NAME1, NOP, "EXEC",
+ UMASK, M1_I1, NOP, "UMASK",
+ CHROOT, M3_LOAD, NOP, "CHROOT",
+ SETSID, NOP, NOP, "SETSID",
+ GETPGRP, NOP, NOP, "GETPGRP",
+ KSIG, NOSYS, NOP, "KSIG",
+ UNPAUSE, NOSYS, NOP, "UNPAUSE",
+ 66, NOSYS, NOP, NULL,
+ REVIVE, NOSYS, NOP, "REVIVE",
+ TASK_REPLY, NOSYS, NOP, "TASK_REPLY",
+ 69, NOSYS, NOP, NULL,
+ 70, NOSYS, NOP, NULL,
+ SIGACTION, M1_SIGACTION, NOP, "SIGACTION",
+ SIGSUSPEND, M2_L1, NOP, "SIGSUSPEND",
+ SIGPENDING, NOP, M2_L1, "SIGPENDING",
+ SIGPROCMASK, M2_SIGPROC, NOP, "SIGPROCMASK",
+ SIGRETURN, M2_SIGRETURN, NOP, "SIGRETURN",
+ REBOOT, M1_I1, NOP, "REBOOT"
+};
+
+PRIVATE void get_message(m,bx)
+message *m;
+unsigned bx;
+{
+ unsigned addr;
+ int i;
+ long buffer[ MESS_SIZE/4 + 1 ];
+
+ addr = bx;
+ for (i = 0; i< sizeof(buffer)/4; i++)
+ buffer[i] = ptrace(T_GETDATA,curpid,
+ (long) (addr+i*4) ,0L);
+
+ memcpy(m,buffer,MESS_SIZE);
+
+}
+
+PRIVATE void get_data(s, bx, cnt)
+char *s;
+unsigned bx;
+int cnt;
+{
+ unsigned addr;
+ int i,nl;
+ long buffer[PATH_MAX/4 + 1];
+
+ addr = bx;
+ nl = (cnt / 4) + 1;
+ for (i = 0; i< nl; i++)
+ buffer[i] = ptrace(T_GETDATA, curpid, (long) (addr+i*4) ,0L);
+
+ memcpy(s, buffer, cnt);
+}
+
+
+PUBLIC void decode_result()
+{
+
+ /* Update message */
+ get_message(&recv,saved_addr);
+ Printf("result=%d\n", recv.m_type);
+
+ if (last_call < 0 || last_call >NCALLS) {
+ Printf("Bad call in decode_result\n");
+ return;
+ }
+
+ switch (decode[last_call].rflag) {
+ case NOP:
+ return;
+ break;
+ case M1_I12:
+ Printf("m1_l1=%d m1_i2=%d ",recv.m1_i1,recv.m1_i2);
+ break;
+ case M2_IOCTL:
+ decode_ioctl('R',&recv);
+ break;
+ case M2_P1:
+ Printf("m2_p1=%lx ",(unsigned long)recv.m2_p1);
+ break;
+ case M2_L1:
+ Printf("m2_l1=%lx ",recv.m2_l1);
+ break;
+ case M2_I1:
+ Printf("m2_i1=%x ",recv.m2_i1);
+ break;
+ default:
+ Printf("rflag=%d ",decode[last_call].rflag);
+ break;
+ }
+ Printf("\n");
+}
+
+
+void decode_message(bx)
+unsigned bx;
+{
+int t;
+int slen;
+unsigned int flag;
+char path[PATH_MAX];
+
+ /* Save address of message */
+ saved_addr = bx;
+ get_message(&sent,bx);
+
+ t = sent.m_type;
+
+ if ( t <= 0 || t >= NCALLS ) {
+ Printf("Bad call - not in range\n");
+ last_call = 0;
+ return;
+ }
+
+ flag = decode[t].sflag;
+
+ if ( flag == NOSYS) {
+ Printf("Bad call - not in system\n");
+ last_call = 0;
+ return;
+ }
+ else
+ last_call = t;
+
+ Printf(" type %s (%d) ", decode[last_call].name, last_call);
+
+ switch (flag) {
+ case NOP:
+ break;
+ case M1_I1:
+ case M1_I12:
+ Printf("i1=%d ",sent.m1_i1);
+ if ( flag == M1_I1) break;
+ case M1_I2:
+ Printf("i2=%d ",sent.m1_i2);
+ break;
+ case M1_P1:
+ Printf("p1=%lx ",(unsigned long)sent.m1_p1);
+ break;
+ case M1_NAME1:
+ case M1_2NAMES:
+ slen = sent.m1_i1;
+ get_data(path, (unsigned long) sent.m1_p1, slen);
+ path[slen] = '\0';
+ Printf("s1=%s ",path);
+ if ( flag == M1_NAME1) break;
+ slen = sent.m1_i2;
+ get_data(path, (unsigned long) sent.m1_p2, slen);
+ path[slen] = '\0';
+ Printf("s2=%s ",path);
+ break;
+ case M2_UTIME:
+ if ( sent.m2_i1 == 0 )
+ slen = sent.m2_i2;
+ else
+ slen = sent.m2_i1;
+ get_data(path, (unsigned long) sent.m2_p1, slen);
+ path[slen] = '\0';
+ Printf("p1=%s ",path);
+ if ( sent.m2_i1 != 0 )
+ Printf("l1=%lx l2=%lx ",sent.m2_l1,sent.m2_l2);
+ break;
+ case M1_SIGACTION:
+ Printf("m1_i2=%d p1=%lx p2=%lx p3=%lx\n",
+ sent.m1_i2,
+ (unsigned long)sent.m1_p1,
+ (unsigned long)sent.m1_p2,
+ (unsigned long)sent.m1_p3);
+ break;
+ case M2_4P: Printf("m2_i1=%d m2_i2=%d m2_l1=%lx m2_l2=%lx ",
+ sent.m2_i1,sent.m2_i2,sent.m2_l1,sent.m2_l2);
+ break;
+ case M2_L1:
+ Printf("m2_l1=%ld ",sent.m2_l1);
+ break;
+ case M2_IOCTL:
+ decode_ioctl('S',&sent);
+ break;
+ case M2_SIGRETURN:
+ Printf("m2_i2=%d l1=%lx p1=%lx ",
+ sent.m2_i2,sent.m2_l1,
+ (unsigned long)sent.m1_p1);
+ break;
+ case M2_SIGPROC:
+ Printf("m2_i1=%d l1=%lx ", sent.m2_i1,sent.m2_l1);
+ break;
+ case M13_OPEN:
+ if (sent.m1_i2 & O_CREAT) {
+ slen = sent.m1_i1;
+ get_data(path, (unsigned long) sent.m1_p1, slen);
+ path[slen] = '\0';
+ Printf("s1=%s ",path);
+ break;
+ }
+ /* fall to M3_LOAD */
+ case M3_LOAD:
+ slen = sent.m3_i1;
+ if ( slen <= M3_STRING)
+ strncpy(path,sent.m3_ca1,M3_STRING);
+ else
+ get_data(path, (unsigned long) sent.m3_ca1, slen);
+ path[slen] = '\0';
+ Printf("m3_name=%s ",path);
+ break;
+ case M4_L5:
+ Printf("m4_l5=%ld ",sent.m4_l5);
+ break;
+ default: Printf("sflag=%d ",decode[last_call].sflag);
+ break;
+ }
+ Printf("\n");
+}
+
+#endif /* SYSCALLS_SUPPORT */
--- /dev/null
+/*
+ * gnu_load for mdb.c
+ */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <gnu/a.out.h>
+
+_PROTOTYPE( unsigned int gnu_load, (char *filename, struct nlist **start) );
+_PROTOTYPE( void do_error, (char *message) );
+
+unsigned int gnu_load( filename, start)
+char *filename;
+struct nlist **start;
+{
+ struct exec header;
+ unsigned int nsym, string_size;
+ char *names;
+ struct nlist *p;
+ int fd;
+
+ if ( (fd = open( filename, 0)) < 0 ||
+ read( fd, (char *) &header, sizeof header ) != sizeof header )
+ {
+ do_error( "gnu_load" );
+ if ( fd >= 0) close( fd );
+ return 0;
+ }
+
+ if ( lseek( fd, N_STROFF( header ), 0 ) != N_STROFF( header ) )
+ {
+ do_error( "gnu_load - reading header" );
+ close( fd );
+ return 0;
+ }
+
+ if ( read( fd, (char *) &string_size, sizeof string_size ) < 0 )
+ {
+ do_error( "gnu_load - reading header" );
+ close( fd );
+ return 0;
+ }
+
+ if ( (int) header.a_syms < 0 ||
+ (unsigned) header.a_syms != header.a_syms ||
+ (*start = (struct nlist *) malloc( (unsigned) header.a_syms +
+ string_size ))
+ == (struct nlist *) NULL &&
+ header.a_syms != 0 )
+ {
+ close( fd );
+ return 0;
+ }
+
+ lseek( fd, N_SYMOFF( header ), 0 );
+
+ if ( read( fd, (char *) *start, (int) header.a_syms + string_size ) < 0 )
+ {
+ do_error( "gnu_load - reading symbols" );
+ close( fd );
+ return 0;
+ }
+ close( fd );
+
+ nsym = (unsigned int) header.a_syms / sizeof (struct nlist);
+ names = (char *) *start + header.a_syms;
+
+ for ( p = *start; p < *start + nsym; p++)
+ if(p->n_un.n_strx)
+ p->n_un.n_name = names + p->n_un.n_strx;
+
+ return nsym;
+}
--- /dev/null
+/*
+ * gnu_sym.c for mdb
+ * copied and modified from sym.c
+ * Support GNU Exec symbol tables
+ */
+
+#include "mdb.h"
+
+#ifdef EXTRA_SYMBOLS
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#if GNU_SUPPORT
+#include <gnu/a.out.h>
+#endif
+#include "proto.h"
+
+#if GNU_SUPPORT
+_PROTOTYPE( PUBLIC unsigned int gnu_load, (char *filename, struct nlist **start) );
+#endif
+
+struct symtab_s
+{
+ struct nlist *start;
+ struct nlist *end;
+ unsigned int nsym;
+};
+
+PRIVATE struct symtab_s symtab;
+
+FORWARD _PROTOTYPE( void gnu_sort , (struct nlist *array , struct nlist *top ));
+FORWARD _PROTOTYPE( int gnu_symeq , (char *t , struct nlist *sp ));
+FORWARD _PROTOTYPE( int gnu_symprefix , (char *t , struct nlist *sp ));
+FORWARD _PROTOTYPE( struct nlist *gnu_sname, (char *name, int is_text, int allflag) );
+FORWARD _PROTOTYPE( struct nlist *gnu_sval, (off_t value, int where) );
+FORWARD _PROTOTYPE( void gnu_sym, (struct nlist *sp, off_t off) );
+
+PUBLIC void gnu_init( filename )
+char *filename;
+{
+ register struct symtab_s *tp;
+
+ tp = &symtab;
+
+ tp->nsym = gnu_load(filename, &tp->start);
+ tp->end = tp->start + tp->nsym;
+
+ /* sort on value only, name search not used much and storage a problem */
+ Printf("Sorting %d GNU symbols ....", tp->nsym );
+ gnu_sort( tp->start, tp->end );
+ Printf("\n");
+}
+
+
+
+PUBLIC long gnu_symbolvalue( name, is_text )
+char *name;
+int is_text;
+{
+ register struct nlist *sp;
+ sp = gnu_sname(name,is_text,0);
+ if (sp != NULL)
+ return sp->n_value;
+ else
+ return 0L;
+}
+
+
+PRIVATE struct nlist *gnu_sname( name, is_text, allflag )
+char *name;
+int is_text;
+int allflag;
+{
+ char *s;
+ unsigned char sclass;
+ int schar;
+ char *send;
+ register struct nlist *sp;
+ register struct symtab_s *tp;
+
+ tp = &symtab;
+
+ if ( allflag )
+ {
+ /* find and print all matching symbols */
+ for ( sp = tp->start; sp < tp->end; ++sp )
+ {
+ if ( gnu_symprefix( name, sp ) )
+ {
+ sp = sp;
+ for ( s = sp->n_un.n_name, send = s + strlen(s);
+ *s != 0 && s < send; ++s )
+ outbyte( *s );
+ for ( ; s <= send; ++s )
+ outspace();
+ switch( sp->n_type & N_TYPE )
+ {
+ case N_ABS: schar = 'a'; break;
+ case N_TEXT: schar = 't'; break;
+ case N_DATA: schar = 'd'; break;
+ case N_BSS: schar = 'b'; break;
+ default: schar = '?'; break;
+ }
+ if ( (sp->n_type & N_EXT) && schar != '?' )
+ schar += 'A' - 'a';
+ outbyte( schar );
+ outspace();
+ outh32( sp->n_value );
+ outbyte('\n');
+ }
+ }
+ }
+ else
+ {
+ /* find symbol by dumb linear search */
+ for ( sp = tp->start; sp < tp->end; ++sp )
+ {
+ sclass = sp->n_type & N_TYPE;
+ if ( (is_text && sclass == N_TEXT ||
+ !is_text && (sclass == N_DATA || sclass == N_BSS)) &&
+ gnu_symeq( name, sp ) )
+ return sp;
+ }
+ }
+ return NULL;
+}
+
+PRIVATE struct nlist *gnu_sval( value, where )
+off_t value;
+int where;
+{
+ int left;
+ int middle;
+ int right;
+ unsigned char sclass;
+ register struct nlist *sp;
+ register struct symtab_s *tp;
+
+ tp = &symtab;
+
+ /* find last symbol with value <= desired one by binary search */
+ for ( left = 0, right = tp->nsym - 1; left <= right; )
+ {
+ middle = (left + right) / 2;
+ sp = tp->start + middle;
+ if ( value < sp->n_value )
+ right = middle - 1;
+ else
+ left = middle + 1;
+ }
+ if ( right >= 0 )
+ /* otherwise tp->start + right may wrap around to > tp->start !! */
+ for ( sp = tp->start + right; sp >= tp->start; --sp )
+ {
+ if ( !(sp->n_type & N_EXT) ) continue;
+ sclass = sp->n_type & N_TYPE;
+ if ( (where == CSEG && sclass == N_TEXT ||
+ where != CSEG && (sclass == N_DATA || sclass == N_BSS)) )
+ return sp;
+ }
+ return NULL;
+}
+
+
+PRIVATE void gnu_sym( sp, off )
+struct nlist *sp;
+off_t off;
+{
+ register char *s;
+ char *send;
+
+ for ( s = sp->n_un.n_name, send = s + strlen(s); *s != 0 && s < send; ++s )
+ outbyte( *s );
+ if ( (off -= sp->n_value) != 0 )
+ {
+ outbyte( '+' );
+ printhex(off);
+ }
+}
+
+/* shell sort symbols on value */
+
+PRIVATE void gnu_sort( array, top )
+struct nlist *array;
+struct nlist *top;
+{
+ int gap;
+ int i;
+ int j;
+ register struct nlist *left;
+ register struct nlist *right;
+ struct nlist swaptemp;
+ int size;
+
+ size = top - array;
+ /* choose gaps according to Knuth V3 p95 */
+ for ( gap = 1, i = 4; (j = 3 * i + 1) < size; gap = i, i = j )
+ ;
+ do
+ {
+ for ( j = gap; j < size; ++j )
+ for ( i = j - gap; i >= 0; i -= gap )
+ {
+ left = array + i;
+ right = array + (i + gap);
+ if ( (off_t) left->n_value <=
+ right->n_value )
+ break;
+ swaptemp = *left;
+ *left = *right;
+ *right = swaptemp;
+ }
+ }
+ while ( (gap /= 3) != 0 );
+}
+
+PUBLIC void gnu_symbolic( value, separator )
+off_t value;
+int separator;
+{
+ register struct nlist *sp;
+ long off;
+
+ if (value < st_addr || value > end_addr) {
+ outstr("0x");
+ printhex(value);
+ outbyte(separator);
+ return;
+ }
+
+ if ( (sp = gnu_sval( value, CSEG )) != NULL )
+ {
+ gnu_sym( sp, value );
+ }
+ else if ( (sp = gnu_sval( value, DSEG )) != NULL )
+ {
+ gnu_sym( sp, value );
+ }
+ else
+ {
+ outstr("_start");
+ off = value - st_addr;
+ if ( off != 0 )
+ {
+ outbyte( '+' );
+ printhex(off);
+ }
+ }
+ outbyte( separator );
+}
+
+
+PRIVATE int gnu_symeq( t, sp )
+register char *t;
+struct nlist *sp;
+{
+ return strncmp( t, sp->n_un.n_name, strlen(t) ) == 0;
+}
+
+PRIVATE int gnu_symprefix( t, sp )
+register char *t;
+struct nlist *sp;
+{
+ register char *s;
+ char *send;
+
+ for ( ; *t == '_'; ++t )
+ ;
+ for ( s = sp->n_un.n_name, send = s + strlen(s);
+ s < send && *s == '_'; ++s )
+ ;
+ return strncmp( s, t, send - s ) == 0;
+}
+
+
+
+/* list all symbols - test for selection criteria */
+
+PUBLIC void gnu_listsym( tchar )
+char tchar;
+{
+ register struct symtab_s *tp;
+ register struct nlist *sp;
+ char *s;
+ char *send;
+ char schar;
+
+ outbyte('\n');
+ tp = &symtab;
+ for ( sp = tp->start; sp < tp->end; ++sp )
+ {
+ switch( sp->n_type & N_TYPE )
+ {
+ case N_ABS: schar = 'a'; break;
+ case N_TEXT: schar = 't'; break;
+ case N_DATA: schar = 'd'; break;
+ case N_BSS: schar = 'b'; break;
+ default: schar = '?'; break;
+ }
+
+ if ( (sp->n_type & N_EXT) && schar != '?' )
+ schar += 'A' - 'a';
+
+ /* check for selection */
+ if ( tchar != '*' && schar != tchar)
+ continue;
+
+ /* print symbol type and value */
+ outh32( sp->n_value );
+ outspace();
+ outbyte( schar );
+ outbyte( '\t' );
+ for ( s = sp->n_un.n_name, send = s + strlen(s);
+ *s != 0 && s < send; ++s ) outbyte( *s );
+ outbyte('\n');
+ }
+}
+
+PUBLIC int gnu_text_symbol(value)
+off_t value;
+{
+struct nlist *sp;
+
+ if ((sp = gnu_sval(value, CSEG)) != NULL && sp->n_value == value)
+ {
+ gnu_sym(sp, value);
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+PUBLIC int gnu_finds_data(off,data_seg)
+off_t off;
+int data_seg;
+{
+struct nlist *sp;
+
+ if ((sp = gnu_sval(off, data_seg)) != NULL)
+ {
+ gnu_sym(sp, off);
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+PUBLIC int gnu_finds_pc(pc)
+off_t pc;
+{
+struct nlist *sp;
+
+ if ((sp = gnu_sval(pc, CSEG)) != NULL)
+ {
+ gnu_sym(sp, pc);
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+
+#endif /* EXTRA_SYMBOLS */
--- /dev/null
+/*
+ * io.c for mdb
+ * all the i/o is here
+ * NB: Printf()
+ */
+#include "mdb.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <sys/types.h>
+#include "proto.h"
+
+#define OUTBUFSIZE 512
+#define PAGESIZE 24
+
+PRIVATE int forceupper = FALSE;
+PRIVATE int someupper = FALSE;
+PRIVATE int stringcount = 0;
+PRIVATE char *string_ptr = NULL; /* stringptr ambiguous at 8th char */
+PRIVATE char *stringstart = NULL;
+
+PRIVATE char outbuf[OUTBUFSIZE];
+PRIVATE FILE *cmdfile = stdin;
+PRIVATE FILE *outfile = stdout;
+PRIVATE FILE *logfile;
+PRIVATE int lineno;
+
+_PROTOTYPE( int _doprnt, (const char *format, va_list ap, FILE *stream ));
+
+PUBLIC char *get_cmd(cbuf, csize)
+char *cbuf;
+int csize;
+{
+char *r;
+
+ fflush(stdout);
+ if( cmdfile == stdin && outfile == stdout )
+ printf("* ");
+ r = fgets(cbuf, csize, cmdfile);
+ if ( r == NULL && cmdfile != stdin ) {
+ cmdfile = stdin;
+ return get_cmd(cbuf, csize);
+ }
+
+ if ( logfile != NULL ) {
+ fprintf( logfile, "%s", cbuf );
+ lineno++;
+ }
+
+ return r;
+}
+
+PUBLIC void openin(s)
+char *s;
+{
+char *t;
+
+ if ((t = strchr(s,'\n')) != NULL) *t = '\0';
+ if ((t = strchr(s,' ')) != NULL) *t = '\0';
+ cmdfile = fopen(s,"r");
+ if (cmdfile == NULL) {
+ Printf("Cannot open %s for input\n",s);
+ cmdfile = stdin;
+ }
+}
+
+
+/* Special version of printf
+ * really sprintf()
+ * from MINIX library
+ * followed by outstr()
+ */
+PUBLIC int Printf(const char *format, ...)
+{
+ va_list ap;
+ int retval;
+ FILE tmp_stream;
+
+ va_start(ap, format);
+
+ tmp_stream._fd = -1;
+ tmp_stream._flags = _IOWRITE + _IONBF + _IOWRITING;
+ tmp_stream._buf = (unsigned char *) outbuf;
+ tmp_stream._ptr = (unsigned char *) outbuf;
+ tmp_stream._count = 512;
+
+ retval = _doprnt(format, ap, &tmp_stream);
+ putc('\0',&tmp_stream);
+
+ va_end(ap);
+
+ outstr(outbuf);
+
+ return retval;
+}
+
+/*
+ * Set logging options
+ */
+PUBLIC void logging( c, name )
+int c;
+char *name;
+{
+char *t;
+
+ if ( c == 'q' && logfile != NULL ) {
+ fclose(logfile);
+ return;
+ }
+
+ if ((t = strchr(name,'\n')) != NULL) *t = '\0';
+ if ((t = strchr(name,' ' )) != NULL) *t = '\0';
+ if ( logfile != NULL ) fclose(logfile);
+
+ if ( strlen(name) > 0 ) {
+ logfile = fopen(name,"w");
+
+ if (logfile == NULL) {
+ Printf("Cannot open %s for output\n",name);
+ return;
+ }
+
+ /* Close standard output file for L */
+ if ( c == 'L' ) {
+ fclose(outfile);
+ outfile = NULL;
+ }
+ }
+ else
+ /* Reset */
+ {
+ if ( logfile != NULL ) fclose(logfile);
+ outfile = stdout;
+ outbyte('\n');
+ }
+
+}
+
+/* Output system error string */
+PUBLIC void do_error(m)
+char *m;
+{
+ outstr(m);
+ outstr(": ");
+ outstr(strerror(errno));
+}
+
+PUBLIC void closestring()
+{
+/* close string device */
+
+ stringcount = 0;
+ stringstart = string_ptr = NULL;
+}
+
+PUBLIC int mytolower(ch)
+int ch;
+{
+/* convert char to lower case */
+
+ if (ch >= 'A' && ch <= 'Z')
+ ch += 'a' - 'A';
+ return ch;
+}
+
+
+PUBLIC void openstring(string)
+char *string;
+{
+/* open string device */
+
+ stringcount = 0;
+ stringstart = string_ptr = string;
+}
+
+PUBLIC void outbyte(byte)
+int byte;
+{
+/* print char to currently open output devices */
+
+ if (forceupper && byte >= 'a' && byte <= 'z')
+ byte += 'A' - 'a';
+ if (string_ptr != NULL)
+ {
+ if ((*string_ptr++ = byte) == '\t')
+ stringcount = 8 * (stringcount / 8 + 1);
+ else
+ ++stringcount;
+ }
+ else
+ {
+ if ( paging && byte == '\n' ) {
+ lineno++;
+ if ( lineno >= PAGESIZE) {
+ if ( cmdfile == stdin ) {
+ printf("\nMore...any key to continue");
+ fgets( outbuf, OUTBUFSIZE-1, cmdfile );
+ }
+ }
+ lineno = 0;
+ }
+
+ if ( outfile != NULL )
+ putc(byte,outfile);
+ /* Do not log CR */
+ if ( logfile != NULL && byte != '\r' )
+ putc(byte,logfile);
+ }
+}
+
+
+PUBLIC void outcomma()
+{
+/* print comma */
+
+ outbyte(',');
+}
+
+PRIVATE char hexdigits[] = "0123456789ABCDEF";
+PUBLIC void outh4(num)
+unsigned num;
+{
+/* print 4 bits hex */
+
+ outbyte(hexdigits[num % 16]);
+}
+
+PUBLIC void outh8(num)
+unsigned num;
+{
+/* print 8 bits hex */
+
+ outh4(num / 16);
+ outh4(num);
+}
+
+PUBLIC void outh16(num)
+unsigned num;
+{
+/* print 16 bits hex */
+
+ outh8(num / 256);
+ outh8(num);
+}
+
+PUBLIC void outh32(num)
+unsigned num;
+{
+/* print 32 bits hex */
+
+ outh16((u16_t) (num >> 16));
+ outh16((u16_t) num);
+}
+
+PUBLIC void outspace()
+{
+/* print space */
+
+ outbyte(' ');
+}
+
+PUBLIC void outstr(s)
+register char *s;
+{
+/* print string */
+
+ while (*s)
+ outbyte(*s++);
+}
+
+PUBLIC void outtab()
+{
+/* print tab */
+
+ outbyte('\t');
+}
+
+PUBLIC void outustr(s)
+register char *s;
+{
+/* print string, perhaps converting case to upper */
+
+ forceupper = someupper;
+ while (*s)
+ outbyte(*s++);
+ forceupper = FALSE;
+}
+
+
+PUBLIC int stringpos()
+{
+/* return current offset of string device */
+
+ return string_ptr - stringstart;
+}
+
+PUBLIC int stringtab()
+{
+/* return current "tab" spot of string device */
+
+ return stringcount;
+}
+
--- /dev/null
+/*
+ * ioctl.c for mdb -- decode an IOCTL system call
+ */
+#include "mdb.h"
+#ifdef SYSCALLS_SUPPORT
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <minix/type.h>
+#include <minix/callnr.h>
+#include <minix/com.h>
+#include <sys/ioctl.h>
+#include <sgtty.h>
+#include "proto.h"
+
+PRIVATE int get_request;
+
+PRIVATE char *rnames[] = {
+ "TIOCGETP",
+ "TIOCSETP",
+ "TIOCGETC",
+ "TIOCSETC"
+};
+
+#define GETPNAME 0
+#define SETPNAME 1
+#define GETCNAME 2
+#define SETCNAME 3
+
+/*
+ * decode ioctl call
+ * send or receive = 'R' or 'S'
+ */
+void decode_ioctl(sr, m)
+int sr;
+message *m;
+{
+int rq;
+int request, device;
+int high;
+long spek, flags;
+int ispeed, ospeed, speed, erase, kill;
+int t_intrc, t_quitc, t_startc, t_stopc, t_brk, t_eof;
+
+ device = m->m2_i1;
+ request = m->m2_i3;
+ spek = m->m2_l1;
+ flags = m->m2_l2;
+
+#ifdef DEBUG
+ if( debug )
+ Printf("%c device=%d request=%c|%d m2_l1=%lx m2_l2=%lx\n",
+ sr,device,
+ (request >> 8) & BYTE,
+ request & BYTE,
+ spek,flags);
+#endif
+
+ if ( sr == 'R') request = get_request;
+
+ switch(request) {
+ case TIOCGETP:
+ case TIOCSETP:
+ rq = (request == TIOCGETP) ? GETPNAME : SETPNAME;
+ if (sr == 'S') {
+ get_request = request;
+ Printf( "Sending %s ",rnames[rq] );
+ if ( request == TIOCGETP ) break;
+ }
+
+ if ( (sr == 'R') && (request == TIOCSETP) ) break;
+
+ erase = (spek >> 8) & BYTE;
+ kill = spek & BYTE;
+ flags = flags & 0xFFFF;
+ speed = (spek >> 16) & 0xFFFFL;
+ ispeed = speed & BYTE;
+ ospeed = (speed >> 8) & BYTE;
+ Printf("%s erase=%d kill=%d speed=%d/%d flags=%lx ",
+ rnames[rq], erase, kill, ispeed, ospeed, flags);
+ break;
+
+ case TIOCGETC:
+ case TIOCSETC:
+ rq = (request == TIOCGETC) ? GETCNAME : SETCNAME;
+ if (sr == 'S') {
+ get_request = request;
+ Printf( "Sending %s ",rnames[rq] );
+ if ( request == TIOCGETC ) break;
+ }
+
+ if ( (sr == 'R') && (request == TIOCSETC) ) break;
+
+ t_intrc = (spek >> 24) & BYTE;
+ t_quitc = (spek >> 16) & BYTE;
+ t_startc = (spek >> 8) & BYTE;
+ t_stopc = (spek >> 0) & BYTE;
+ t_brk = flags & BYTE;
+ t_eof = (flags >> 8 ) & BYTE;
+ Printf("%s int %d quit %d start %d stop %d brk %d eof %d\n",
+ rnames[rq],
+ t_intrc, t_quitc, t_startc, t_stopc, t_brk, t_eof);
+ break;
+
+ default:
+
+#ifdef __i86 /* 16 bit */
+ if ( sr == 'S' ) {
+ Printf("Sending ");
+ get_request = request;
+ }
+ else
+ Printf("Receiving ");
+
+ Printf("Other IOCTL device=%d request=%c|%d\n",
+ device, (request >> 8) & BYTE, request & BYTE );
+
+ break;
+#endif
+
+#ifdef __i386 /* 32 bit encoding */
+ if ( sr == 'S' ) {
+ Printf("Sending (%lx) ", request);
+ get_request = request;
+ }
+ else
+ Printf("Receiving (%lx) ", request);
+
+ high = ( request & 0xFFFF0000 ) >> 16 ;
+ request &= _IOCTYPE_MASK;
+
+ Printf("Other IOCTL device=%d request=%c|%d flags=%x size =%d\n",
+ device, (request >> 8) & BYTE, request & BYTE,
+ (high & ~_IOCPARM_MASK ),
+ (high & _IOCPARM_MASK )
+ );
+ break;
+#endif
+ }
+ Printf("\n");
+}
+
+
+#endif /* SYSCALLS_SUPPORT */
--- /dev/null
+/*
+ * kernel.c for mdb
+ */
+
+#include "mdb.h"
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#define ptrace mdbtrace
+#include <sys/ptrace.h>
+#include "proto.h"
+
+#include <kernel/const.h>
+#include <kernel/type.h>
+#include <kernel/proc.h>
+
+/* Define these here */
+/* buffer for proc and pointer to proc */
+
+#define SIZ (1 + sizeof(struct proc)/sizeof(long))
+
+struct proc *prc;
+long lbuf[SIZ];
+
+PRIVATE char segment_name[] = "TDS";
+
+/*
+ * Display memory maps
+ */
+PUBLIC void disp_maps()
+{
+ int i;
+ long int vir, phy, len;
+
+ Printf("\t Virtual\t Physical\tLength\n");
+ Printf("\t address\t address\n");
+ for (i = 0; i < strlen(segment_name); i++) {
+ vir = (long) prc->p_memmap[i].mem_vir << CLICK_SHIFT;
+ phy = (long) prc->p_memmap[i].mem_phys << CLICK_SHIFT;
+ len = (long) prc->p_memmap[i].mem_len << CLICK_SHIFT;
+ Printf("%c:\t0x%08.8lx\t0x%08.8lx\t%8ld (0x%08.8lx)\n",
+ segment_name[i], vir, phy, len, len);
+ }
+}
+
+PUBLIC void update()
+{
+ int i;
+
+ for (i = 0; i < (SIZ - 1); i++)
+ lbuf[i] = ptrace(T_GETUSER, curpid, (long) (i * sizeof(long)), 0L);
+
+ st_addr = (long) prc->p_memmap[T].mem_vir << CLICK_SHIFT;
+ et_addr = st_addr + ( (long) prc->p_memmap[T].mem_len << CLICK_SHIFT );
+
+ sd_addr = (long) prc->p_memmap[D].mem_vir << CLICK_SHIFT;
+ ed_addr = end_addr =
+ sd_addr + ( (long) prc->p_memmap[D].mem_len << CLICK_SHIFT );
+
+ sk_addr = (long) prc->p_memmap[S].mem_vir << CLICK_SHIFT;
+ sk_size = (long) prc->p_memmap[S].mem_len << CLICK_SHIFT;
+
+#ifdef MINIX_PC
+ if ( end_addr < et_addr ) end_addr = et_addr;
+#endif
+
+}
+
+PUBLIC int disp_regs()
+{
+ int i;
+
+ if (curpid <= 0) {
+ Printf("No active process.\n");
+ return 1;
+ }
+
+/* Look at kernel/type.h see how this data from the stackframe is laid out */
+
+#if defined(MINIX_PC) && defined(__i86)
+ Printf("\
+ es ds di si bp bx dx cx ax ip cs psw sp ss\
+\n");
+ for (i = 0; i < 16; i++)
+ if ( i != 5 && i != 10 ) Printf("%04x ", ((reg_t *) &prc->p_reg)[i]);
+ Printf("\n");
+#endif
+
+#if defined(MINIX_PC) && defined(__i386)
+ Printf("\n");
+ Printf("\
+ fs gs ds es edi esi ebp ebx edx\n");
+ for (i = 0; i < 8; i++)
+ if ( i != 6 ) Printf("%08lx ", ((reg_t *) &prc->p_reg)[i]);
+ Printf("\n\
+ ecx eax eip cs psw esp ss\n");
+ for (; i < 16; i++)
+ if ( i != 10 ) Printf("%08lx ", ((reg_t *) &prc->p_reg)[i]);
+ Printf("\n");
+#endif
+
+#ifdef MINIX_ST
+ Printf("\npc=%lx psw=%x\n\n",(long)PC_MEMBER(prc), PSW_MEMBER(prc));
+ Printf(
+" 0 1 2 3 4 5 6 7\nD");
+ for (i = 0; i < 8; i++) Printf(" %08lx", ((reg_t *) &prc->p_reg)[i]);
+ Printf("\nA");
+ for (; i < NR_REGS; i++) Printf(" %08lx", ((reg_t *) &prc->p_reg)[i]);
+ Printf(" %08lx\n\n", (long)SP_MEMBER(prc));
+#endif
+ return 0;
+}
+
+/* System dependent core */
+
+#ifdef MINIX_PC
+
+#ifdef __i386
+PRIVATE char regs[] = "fs gs ds es di si bp bx dx cx ax ip cs ps sp ss";
+#else
+PRIVATE char regs[] = "es ds di si bp bx dx cx ax ip cs ps sp ss";
+#endif
+
+/* Get register for pid at offset k */
+PUBLIC long get_reg(pid, k)
+int pid;
+long k;
+{
+ long off;
+ long val;
+ int reg_size;
+
+ /* Calculate size of register */
+ reg_size = (k < N_REG16 * 2) ? 2 : sizeof(reg_t);
+
+ /* Adjust offset */
+ off = k - (k & (sizeof(long) - 1));
+
+ val = ptrace(T_GETUSER, pid, off, 0L);
+
+ if (k & (sizeof(long) - 1))
+ val >>= BITSIZE(reg_size);
+ else
+ val &= MASK(reg_size);
+ return val;
+}
+
+
+/* Set register for pid at offset k */
+PUBLIC void set_reg(pid, k, value)
+int pid;
+long k;
+long value;
+{
+ long off;
+
+ /* Adjust offset */
+ off = k - (k & (sizeof(long) - 1));
+
+ ptrace(T_SETUSER, pid, off, value);
+
+}
+
+
+PUBLIC long reg_addr(s)
+char *s;
+{
+ long val;
+ char *t;
+ char *send;
+ char q[3];
+
+ if (*s == ' ')
+ mdb_error("Invalid syntax\n");
+ q[0] = tolower(*s);
+ q[1] = tolower(*++s);
+ q[2] = '\0';
+
+ t = regs;
+ send = regs + sizeof(regs);
+ while (t < send) {
+ if (strncmp(q, t, 2) == 0) {
+ val = (long) (t - regs);
+ val /= 3L;
+ if (val < N_REG16 - 1)
+ val = val * 2;
+ else
+ val = (N_REG16 - 1) * 2 +
+ (val - N_REG16 + 1) * sizeof(reg_t);
+ return val;
+ }
+ t += 3;
+ }
+ Printf("Unknown register: %s", q);
+ mdb_error("\n");
+}
+
+
+PUBLIC int outsegreg(num)
+off_t num;
+{
+/* print segment register */
+
+ if ((num % HCLICK_SIZE) != 0 || num >= 0x100000)
+ {
+ Printf("%08x",num);
+ return 8;
+ }
+ Printf("%04x", (u16_t) (num / HCLICK_SIZE) );
+ return 4;
+}
+
+#endif
+
+#ifdef MINIX_ST
+
+/* Get register for pid at offset k */
+PUBLIC long get_reg(pid, k)
+int pid;
+long k;
+{
+ return ptrace(T_GETUSER, pid, k, 0L);
+}
+
+PUBLIC long reg_addr(s)
+char *s;
+{
+ long val;
+
+ switch (*s++) {
+ case 'a':
+ case 'A': val = 32; break;
+ case 'd':
+ case 'D': val = 0; break;
+ case 'P':
+ case 'p': if (*s != 'c' && *s != 'C') goto error;
+ return 64;
+ break;
+ default: goto error;
+ }
+ if (*s >= '0' && *s <= '7')
+ return val + 4 * (*s - '0');
+error:
+ Printf("Unknown register: %2.2s", s);
+ mdb_error("\n");
+}
+
+#endif
--- /dev/null
+.TH MDB 1
+.SH NAME
+mdb \- Minix debugger
+.SH SYNOPSIS
+.B mdb
+.RB [ \-fc ]
+.I file
+.br
+.B mdb
+.BR [-L|-l]log\-file
+.I exec-file
+.RI [ core\-file ]
+.RI [ @command\-file ]
+.SH DESCRIPTION
+.de SP
+.if t .sp 0.4
+.if n .sp
+..
+.B mdb
+is the Minix debugger.
+.SH OPTIONS
+Its command line options are:
+.TP
+.B \-f
+Just examine the specified file.
+.TP
+.B \-c
+Examine 'core' file. No exec-file will be supplied.
+.TP
+.B \-Llog\-file
+Log to file only
+.TP
+.B \-llog\-file
+Log to file.
+.SP
+.IR exec\-file
+Unless the -c option has been specified, the exec-file is required.
+.SP
+.IR core\-file
+The core-file is optional.
+.SP
+If the core-file is supplied,
+.B mdb
+assumes that the user wishes to examine the core file.
+Otherwise
+.B mdb
+assumes that the user will run the exec-file and trace it.
+.SP
+.IR @command\-file
+.B mdb
+executes command from command-file.
+.SH OVERVIEW
+.br
+.B mdb
+commands are of the form:
+.I [ expression ]
+.I command
+.SP
+.I expression
+can be of the form:
+.IP
+.I address
+which defaults to text segment
+.IP
+address
+.I overriden
+by
+.I T:
+for Text segment
+or
+.I D:
+for Data segment
+or
+.I S:
+for Stack segment
+.IP
+.I symbol
+where
+.B mdb
+does a lookup for the symbol first as a
+.I text
+symbol and then as a
+.I data
+symbol.
+.SP
+.TP
+.I command
+.SP
+The help command is ?.
+.SP
+For detailed help on a command type:
+.I command ?.
+.SP
+A semi-colon can be used to separate commands on a line.
+.SP
+.SH MDB COMMANDS
+.SP
+! Shell escape
+.SP
+# Set Variable or register
+.SP
+Tt Current call / Backtrace all
+.SP
+/nsf Display for n size s with format f
+.SP
+Xx [n] Disasm / & display reg for n instructions
+.SP
+Rr a Run / with arguments a
+.SP
+Cc [n] Continue with current signal / no signal n times
+.SP
+Ii [n] Single step with / no signal for n instructions
+.SP
+Mm t n Trace until / Stop when modified t type for n instructions
+.SP
+k Kill
+.SP
+Bb Display / Set Break-pt
+.SP
+Dd Delete all / one break-points
+.SP
+P Toggle Pagging
+.SP
+Ll name Log to file name / and to standard output
+.SP
+Vv Toggle debug flag / Version info
+.SP
+V Version info
+.SP
+e [t] List symbols for type t
+.SP
+y Print segment mappings
+.SP
+s [n] Dump stack for n words
+.SP
+z [a] Trace syscalls with address a
+.SP
+? Help - short help
+.SP
+@ file Execute commands from file
+.SP
+Qq Quit / and kill traced process
+.SP
+.SH "SEE ALSO"
+.SP
+trace(2).
+.SH DIAGNOSTICS
+
+.SH NOTES
+
+.SH BUGS
+
+.SH AUTHOR
+Philip Murton and others
--- /dev/null
+/*
+ * mdb.c - MINIX program debugger
+ *
+ * Written by Bruce D. Szablak
+ *
+ * This free software is provided for non-commerical use. No warrantee
+ * of fitness for any use is implied. You get what you pay for. Anyone
+ * may make modifications and distribute them, but please keep this header
+ * in the distribution.
+ */
+
+/*
+ * Originally ported to MINIX-PC and MINIX-386 by Bruce Evans.
+ * NB: the original sym.c and mdbdis86.c come from his 'db'
+ *
+ * Added by Philip Murton:
+ *
+ * 2.0 'Core' file functions
+ * 2.1 Support for GNU exec
+ * 2.2 Changes for Minix 1.6.x Beta
+ * 2.3 Changes for Minix 1.7.0 and trace syscalls
+ * 2.4 Changes for Minix 1.7.2 and clean up
+ * 2.5.1 Add better help
+ * 2.5.2 Added io.c for logging options
+ * 2.5.3 Minor changes and tested with Minix 1.7.4
+ * 2.5.4 Command arguments processing improved (Thanks to Will Rose)
+ * 2.6.0 Final Version for MINIX CD (Sept/96)
+ */
+
+#define _MAIN_MDB
+#include "mdb.h"
+
+#include <minix/type.h>
+
+#include <stdio.h>
+#include <signal.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <errno.h>
+#include <sys/wait.h>
+#define ptrace mdbtrace
+#include <sys/ptrace.h>
+#include <setjmp.h>
+#include "proto.h"
+
+#include <kernel/const.h>
+#include <kernel/type.h>
+#include <kernel/proc.h>
+
+/* buffer for proc and pointer to proc */
+extern struct proc *prc;
+
+#define MAXLINE 128
+#define MAXARG 20
+
+PRIVATE unsigned long lastexp = 0L; /* last expression and segment */
+PRIVATE int lastseg = NOSEG;
+PRIVATE char *prog; /* prog name */
+PRIVATE char sbuf[MAXLINE];
+PRIVATE char cbuf[MAXLINE];
+PRIVATE char *cmd; /* current command */
+PRIVATE char *cmdstart; /* start of command */
+PRIVATE jmp_buf mainlp;
+
+
+struct b_pnt {
+ struct b_pnt *nxt, *prv;
+ long addr;
+ long oldval;
+ char cmd[1];
+} *b_head, *curpnt;
+
+_PROTOTYPE( void main , (int argc, char *argv[]));
+
+FORWARD _PROTOTYPE( void cleanup , (void));
+FORWARD _PROTOTYPE( void freepnt , (struct b_pnt *pnt ));
+FORWARD _PROTOTYPE( void findbpnt , (int verbose ));
+FORWARD _PROTOTYPE( int exebpnt , (int restart ));
+FORWARD _PROTOTYPE( void catch , (int sig ));
+FORWARD _PROTOTYPE( int run , (char *name , char *argstr , int tflg ));
+FORWARD _PROTOTYPE( int dowait , (void));
+FORWARD _PROTOTYPE( void backtrace , (int all ));
+FORWARD _PROTOTYPE( void modify , (long addr , int cnt , int verbose , int size ));
+FORWARD _PROTOTYPE( void display , (long addr , int req ));
+FORWARD _PROTOTYPE( void fill , (long addr , int req ));
+FORWARD _PROTOTYPE( void dorun , (char *cmd ));
+FORWARD _PROTOTYPE( void not_for_core , (void));
+FORWARD _PROTOTYPE( void command , (void));
+
+
+PRIVATE void cleanup()
+{
+ curpid = 0;
+ curpnt = NULL;
+ while (b_head) freepnt(b_head);
+}
+
+PRIVATE void findbpnt(verbose)
+int verbose;
+{
+ for (curpnt = b_head; curpnt; curpnt = curpnt->nxt) {
+ if (curpnt->addr == PC_MEMBER(prc) - BREAKPOINT_ADVANCE) {
+ ptrace(T_SETINS, curpid, curpnt->addr, curpnt->oldval);
+ ptrace(T_SETUSER, curpid, PC_OFF, curpnt->addr);
+#if SYSCALLS_SUPPORT
+ if( syscalls )
+ do_syscall(curpnt->addr);
+ else if (curpnt->cmd[0] != '\n')
+#else
+ if (curpnt->cmd[0] != '\n')
+#endif
+ cmd = strcpy(cbuf, curpnt->cmd);
+ else if (verbose)
+ Printf("Breakpoint hit.\n");
+ return;
+ }
+ }
+ if (verbose) Printf("Unknown breakpoint hit.\n");
+}
+
+PRIVATE int exebpnt(restart)
+int restart;
+{
+ ptrace(T_STEP, curpid, 0L, (long) restart);
+ if (dowait() == 0) return TRUE;
+ ptrace(T_SETINS, curpid, curpnt->addr, BREAK(curpnt->oldval));
+ curpnt = NULL;
+ return FALSE;
+}
+
+
+PRIVATE void freepnt(pnt)
+struct b_pnt *pnt;
+{
+ if (pnt->prv)
+ pnt->prv->nxt = pnt->nxt;
+ else
+ b_head = pnt->nxt;
+ if (pnt->nxt) pnt->nxt->prv = pnt->prv;
+ if (curpid > 0) ptrace(T_SETINS, curpid, pnt->addr, pnt->oldval);
+ free(pnt);
+ if (pnt == curpnt) curpnt = NULL;
+}
+
+
+PUBLIC long breakpt(addr, cmd)
+long addr;
+char *cmd;
+{
+ struct b_pnt *new;
+
+ if (curpid <= 0) {
+ Printf("No active process.\n");
+ return 0L;
+ }
+ for (new = b_head; new; new = new->nxt)
+ if (new->addr == addr) {
+ Printf("Breakpoint already exists here.\n");
+ return 0L;
+ }
+ new = (struct b_pnt *) malloc(sizeof(struct b_pnt) + strlen(cmd));
+ if (new == NULL) {
+ Printf("No room for new breakpoint.\n");
+ return 0L;
+ }
+ new->nxt = b_head;
+ new->prv = 0;
+ if (b_head) b_head->prv = new;
+ b_head = new;
+ new->addr = addr;
+ strcpy(new->cmd, cmd);
+ new->oldval = ptrace(T_GETINS, curpid, addr, 0L);
+ ptrace(T_SETINS, curpid, addr, BREAK(new->oldval));
+ if (ptrace(T_GETINS, curpid, addr, 0L) != BREAK(new->oldval)) {
+ do_error("Can't set breakpoint");
+ freepnt(new);
+ return 0L;
+ }
+ return new->oldval;
+}
+
+PRIVATE void catch(sig)
+int sig;
+{
+ signal(sig, catch);
+ if (sig == SIGINT || sig == SIGQUIT) return;
+ tstart(T_EXIT, 0, sig, 0);
+ exit(0);
+}
+
+
+PRIVATE int dowait()
+{
+ int stat;
+
+ if (corepid > 0) return cursig = 0;
+ while (wait(&stat) != curpid) {};
+ if ( WIFEXITED(stat) ) {
+ if (WEXITSTATUS(stat) != 127)
+ Printf("child exited with status %d\n", WEXITSTATUS(stat));
+ cleanup();
+ return 0;
+ }
+ if ( WIFSIGNALED(stat) ) {
+ Printf("child terminated by signal %d\n", WTERMSIG(stat) );
+ if (_LOW(stat) & 0x80) Printf("(core dumped)\n");
+ cleanup();
+ return 0;
+ }
+ return cursig = WSTOPSIG(stat);
+}
+
+
+
+PUBLIC void tstart(req, verbose, val, cnt)
+int req, verbose, val, cnt;
+{
+ if (curpid == 0) {
+ if (verbose) Printf("No active process.\n");
+ return;
+ }
+ if (req == T_EXIT) {
+ ptrace(T_EXIT, curpid, 0L, (long) val);
+ dowait();
+ return;
+ }
+ if (cnt == 0) cnt = 1;
+ do {
+ if (curpnt) {
+ if (exebpnt(val)) return;
+ if (req == T_RESUME) cnt++;
+ val = 0;
+ } else {
+ ptrace(req, curpid, 0L, (long) val);
+ if (dowait() == 0) return;
+ val = 0;
+ switch (cursig) {
+ case SIGEMT: /* breakpoint */
+ update();
+ findbpnt(cnt <= 1);
+ break;
+ case SIGTRAP: /* trace trap? */
+ if (req == T_STEP) break;
+ default: /* signal */
+ val = cursig;
+ break;
+ }
+ }
+ }
+ while (--cnt > 0);
+ update();
+ if ( verbose ) dasm((long) PC_MEMBER(prc), 1, 1);
+}
+
+PRIVATE int run(name, argstr, tflg)
+char *name, *argstr;
+int tflg;
+{
+ int procid;
+ char *argv[MAXARG], *inf = NULL, *outf = NULL;
+ int argc;
+
+ if ((procid = fork()) == 0) {
+ /* trace me */
+ if (tflg) ptrace(T_OK, 0, 0L, 0L);
+ argv[0] = name;
+ for (argc = 1;;) {
+ argstr = skip(argstr);
+ if (*argstr == '\n' || *argstr == ';') {
+ argv[argc] = 0;
+ if (inf) freopen(inf, "r", stdin);
+ if (outf) freopen(outf, "w", stdout);
+ if (tflg) {
+ execv(name, argv);
+ do_error("execv");
+ } else {
+ execvp(name, argv);
+ do_error("execvp");
+ }
+ exit(127);
+ }
+ if (*argstr == '<')
+ inf = argstr + 1;
+ else if (*argstr == '>')
+ outf = argstr + 1;
+ else if (argc == MAXARG) {
+ Printf("Too many arguments.\n");
+ exit(127);
+ } else
+ argv[argc++] = argstr;
+ while (!isspace(*argstr)) argstr++;
+ if (*argstr == '\n') argstr[1] = '\n', argstr[2] = 0;
+ *argstr++ = 0;
+ }
+ }
+ if (procid < 0) do_error("Fork failed.\n");
+ return procid;
+}
+
+
+PRIVATE void dorun(cmd)
+char *cmd;
+{
+ if (curpid = run(prog, cmd, 1)) {
+ if (dowait()) {
+ ptrace(T_SETUSER, curpid, BP_OFF, 0L);
+ update();
+ Printf("Process stopped.\n");
+ }
+ }
+}
+
+/*
+ * backtrace - inspect the stack
+ */
+PRIVATE void backtrace(all)
+int all;
+{
+ unsigned long pc, bp, off, val, obp;
+
+ if (curpid <= 0) {
+ Printf("No process.\n");
+ return;
+ }
+ pc = get_reg(curpid,PC_OFF);
+ bp = get_reg(curpid,BP_OFF);
+ if (bp == 0) {
+ Printf("No active frame.\n");
+ return;
+ }
+ errno = 0;
+ do {
+ symbolic(pc, '(');
+ pc = (ptrace(T_GETDATA, curpid, bp + ADDRSIZE, 0L)
+ >> SHIFT(ADDRSIZE)) & MASK(ADDRSIZE);
+ off = ptrace(T_GETINS, curpid, pc, 0L);
+#ifdef DEBUG
+ if(debug)
+ Printf("Return address %lx Value %lx\n",pc,off);
+#endif
+ obp = bp;
+ bp += 2 * ADDRSIZE;
+
+ /* Check for various instruction used to restore the stack.
+ * Should gives us the number of arguments.
+ * This is obvious dependent on interal features of the
+ * compiler used.
+ */
+ if (ADDQ(off)) off = ADDQ_CNT(off) + bp;
+#ifdef __mc68000__
+ else if (LEA(off))
+ off = LEA_DISP(off) + bp;
+#endif
+ else if (ADDA(off))
+ off = ADDA_CNT(ptrace(T_GETINS, curpid, pc + 2, 0L)) + bp;
+#if (CHIP == INTEL)
+ else if (INCSP2(off))
+ off = bp + 2*INTSIZE;
+ else if (POPBX2(off))
+ off = bp + 2*INTSIZE;
+ else if (POPCX2(off))
+ off = bp + 2*INTSIZE;
+ else if (POPBX(off))
+ off = bp + INTSIZE;
+ else if (POPCX(off))
+ off = bp + INTSIZE;
+#endif
+ else
+ goto skiplp;
+
+#ifdef DEBUG
+ if (debug)
+ Printf("Number of arguments: %d\n",(off-bp)/INTSIZE);
+#endif
+
+ for (;;) {
+ if (errno) return;
+ val = (ptrace(T_GETDATA, curpid, bp, 0L)
+ >> SHIFT(INTSIZE)) & MASK(INTSIZE);
+ Printf("0x%0*lx", 2 * INTSIZE, val);
+ bp += INTSIZE;
+ if (bp >= off) break;
+ Printf(",");
+ }
+
+skiplp:
+ Printf(")\n");
+ bp = (long) ( (reg_t) ptrace(T_GETDATA, curpid, obp, 0L) );
+#ifdef DEBUG
+ if(debug)
+ Printf("Old BP %lx New %lx\n",obp,bp);
+#endif
+ }
+ while (all && (reg_t) bp);
+}
+
+PRIVATE void modify(addr, cnt, verbose, size)
+long addr;
+int cnt, verbose, size;
+{
+ long curval, off;
+
+ if (curpid == 0) {
+ Printf("No active process.\n");
+ return;
+ }
+ curval = ptrace(T_GETDATA, curpid, addr, 0L) & MASK(size);
+ do {
+ if (cursig == SIGTRAP) cursig = 0;
+ if (verbose) {
+ off = get_reg(curpid, PC_OFF);
+ dasm(off, 1, 0);
+ }
+ if (curpnt && exebpnt(cursig))
+ return;
+ else {
+ ptrace(T_STEP, curpid, addr, 0L);
+ switch (dowait()) {
+ case 0:
+ return;
+ case SIGEMT:
+ update();
+ findbpnt(0);
+ break;
+ }
+ }
+ if (curval != ptrace(T_GETDATA, curpid, addr, 0L) & MASK(size)) {
+ Printf("Modification detected\n");
+ break;
+ }
+ }
+ while (--cnt);
+ update();
+ dasm((long) PC_MEMBER(prc), 1, 1);
+ return;
+}
+
+PRIVATE void display(addr, req)
+long addr;
+int req;
+{
+ int count, size, out, shift;
+ long val, msk;
+ char fmt;
+
+ if (curpid == 0) {
+ Printf("No active process\n");
+ return;
+ }
+ if (req == T_GETDATA && seg == T) req = T_GETINS;
+ count = strtol(cmd, &cmd, 0);
+ if (count == 0) count = 1;
+ cmd = skip(cmd);
+ if (*cmd == 'i' || *cmd == 'I') {
+ dasm(addr, count, *cmd == 'i');
+ return;
+ }
+ if (*cmd == 'y') {
+ symbolic(addr, '\n');
+ return;
+ }
+ switch (*cmd++) {
+ case 'b': size = sizeof(char); break;
+ case 'h': size = sizeof(short); break;
+ case 'l': size = sizeof(long); break;
+ default:
+ size = sizeof(int);
+ --cmd;
+ break;
+ }
+ switch (fmt = *cmd) {
+ case 'X':
+ case 'D':
+ size = sizeof(long);
+ break;
+ case 's':
+ addr = ptrace(req, curpid, addr, 0L);
+ req = T_GETDATA;
+ /* Fallthrough */
+ case 'a':
+ case 'c':
+ size = sizeof(char);
+ break;
+ }
+ out = 0;
+ msk = MASK(size);
+ shift = SHIFT(size);
+ do {
+ val = (ptrace(req, curpid, addr, 0L) >> shift) & msk;
+ if (out == 0) Printf("\n0x%0*lx: ", 2 * ADDRSIZE,
+ (addr >> SHIFT(ADDRSIZE)) & MASK(ADDRSIZE));
+ switch (fmt) {
+ case 'c':
+ Printf(isprint((int) (UCHAR(val))) ? " %c " : "\\%03o ",
+ (int) (UCHAR(val)));
+ if (++out == 8) out = 0;
+ break;
+ case 'u':
+ Printf("%12lu ", val);
+ if (++out == 4) out = 0;
+ break;
+ case 'x':
+ case 'X':
+ Printf("%*lx ", 2 * size, val);
+ if (++out == (size == 4 ? 4 : 8)) out = 0;
+ break;
+ case 'o':
+ Printf("%*lo ", 3 * size, val);
+ if (++out == (size == 4 ? 4 : 8)) out = 0;
+ break;
+ case 's':
+ case 'a':
+ if (val)
+ Printf("%c",val);
+ else
+ goto exitlp;
+ if (++out == 64) out = 0;
+ break;
+ default:
+ case 'd':
+ case 'D':
+ Printf("%12ld ", val);
+ if (++out == 4) out = 0;
+ break;
+ }
+ addr += size;
+ }
+ while (--count > 0 || fmt == 's' || fmt == 'a');
+exitlp:
+ Printf("\n");
+}
+
+PRIVATE void fill(addr, req)
+long addr;
+int req;
+{
+ int count, size, shift;
+ long val, msk, nval;
+
+ if (curpid == 0) {
+ Printf("No active process\n");
+ return;
+ }
+
+ if (req == T_GETDATA && seg == T) {
+ req = T_GETINS;
+ Printf("mdb: warning - modifying text\n");
+ }
+ count = strtol(cmd, &cmd, 0);
+ if ( count == 0 ) count = 1;
+ switch (*cmd++) {
+ case 'b': size = sizeof(char); break;
+ case 'h': size = sizeof(short); break;
+ case 'l': size = sizeof(long); break;
+ default:
+ size = sizeof(int);
+ --cmd;
+ break;
+ }
+ shift = SHIFT(size);
+ msk = MASK(size);
+ cmd = getexp(cmd, &nval, &seg);
+
+#ifdef DEBUG
+ if (debug)
+ Printf("Filling for Count=%d Size=%d val=%lx\n",count,size,nval);
+#endif
+
+ nval <<= shift;
+ do {
+ val = ptrace(req, curpid, addr, 0L) | (nval & msk);
+ val &= (nval | ~msk);
+ ptrace(req + 3, curpid, addr, val);
+ addr += size;
+ }
+ while (--count > 0);
+}
+
+PRIVATE void not_for_core()
+{
+ if (corepid > 0)
+ mdb_error("Illegal command for 'core' file\n");
+}
+
+PRIVATE void command()
+{
+ char c, *p;
+ int i;
+ int size;
+ int stat;
+ long exp, lj, lk;
+ struct b_pnt *bp;
+
+ seg = NOSEG; /* don't restrict segment expressions are in */
+ cmdstart = cmd = skip(cmd);
+ cmd = getexp(cmd, &exp, &seg);
+
+ if (cmd == cmdstart) {
+ /* Not an expression */
+ if (corepid < 0) { /* default to pc for running processs */
+ seg = T;
+ exp = PC_MEMBER(prc);
+ } else {
+ seg = lastseg;
+ exp = lastexp;
+ }
+
+ /* Is it a help command */
+ cmd = skip(cmd+1);
+ if (*cmd == '?') {
+ help_on(*cmdstart);
+ *cmd = '\n';
+ return;
+ }
+ else
+ cmd = cmdstart;
+ }
+
+ if (seg == NOSEG) seg = T; /* Absolute becomes Text */
+ lastexp = exp; /* save last expression */
+ lastseg = seg;
+#ifdef DEBUG
+ if(debug)
+ Printf("Current address 0x%0*lx and segment %d\n", 2 * ADDRSIZE, exp, seg);
+
+#endif
+
+ /* Check commands */
+ switch (c = *cmd++) {
+ case 'r': /* illegal for 'core' files */
+ case 'R':
+ case 'k':
+ case 'B':
+ case 'd':
+ case 'D': not_for_core();
+ break;
+
+ case 'b': /* illegal for 'core' files */
+ case 'c': /* Otherwise run process first */
+ case 'C':
+ case 'm':
+ case 'M':
+#if SYSCALLS_SUPPORT
+ case 'z':
+#endif
+ case 'i':
+ case 'I': not_for_core();
+ if (curpid <= 0) dorun("\n");
+ break;
+
+ case 's': if (curpid <= 0) dorun("\n");
+ break;
+
+ default: break;
+ }
+
+ switch (c) {
+ case '!': /* escape to shell */
+ if (cmd == cmdstart + 1) {
+ cmd = skip(cmd);
+ if (*cmd == '\n' || *cmd == ';') {
+ i = run("/bin/sh", "\n", 0);
+ } else {
+ for (p = cmd + 1; *p && !isspace(*p); p++) {
+ };
+ *p++ = 0;
+ i = run(cmd, *p ? p : "\n", 0);
+ }
+ if (i > 0) while (wait(&stat) != i) {};
+ break;
+ }
+ if (corepid > 0) longjmp(mainlp, 0);
+ break;
+ case 'T': /* top line of backtrace */
+ backtrace(0);
+ break;
+ case 't': /* back trace */
+ backtrace(1);
+ break;
+ case '/': /* print variable value */
+ display(exp, T_GETDATA);
+ break;
+ case 'x': /* print registers and instruction */
+ if (disp_regs()) break;
+ /* FALLTHROUGH */
+ case 'X': /* print instruction - X n [, n] */
+ lj = strtol(cmd, &cmd, 0);
+ lk = 0;
+ if (*cmd != '\0')
+ lk = strtol(++cmd, &cmd, 0);
+ if (curpid > 0)
+ dasm(exp + lk, lj ? lj : 1, 1);
+ else
+ Printf("No active process.\n");
+ break;
+ case 'R': /* run program with no args */
+ case 'r': /* run program with args (possibly defaulted) */
+ tstart(T_EXIT, 0, 0, 0);
+ if (c == 'r') {
+ cmd = skip(cmd);
+ if (*cmd == '\n' || *cmd == ';')
+ cmd = sbuf;
+ else
+ strcpy(sbuf, cmd);
+ } else {
+ cmd = "\n";
+ }
+ dorun(cmd);
+ break;
+ case 'c': /* continue program - ignore signal */
+ cursig = 0;
+ case 'C': /* continue program - handle signal */
+ i = 0;
+ if (seg == T && curpnt == 0 && cmd != cmdstart + 1) {
+ breakpt(exp, "\n");
+ curpnt = b_head;
+ ptrace(T_SETINS, curpid, curpnt->addr, curpnt->oldval);
+ i = 1;
+ }
+ tstart(T_RESUME, 1, cursig, (int) strtol(cmd, &cmd, 0));
+ /* remove temporary bp */
+ if (i) freepnt(b_head);
+ if (cursig == SIGEMT) return;
+ if (curpid) Printf("Process stopped by signal %d\n", cursig);
+ break;
+ case 'i': /* single step - ignore signal */
+ tstart(T_STEP, 1, 0, (int) strtol(cmd, &cmd, 0));
+ break;
+ case 'I': /* single step - handle signal */
+ tstart(T_STEP, 1, cursig, (int) strtol(cmd, &cmd, 0));
+ break;
+ case 'm': /* single step until location modified */
+ case 'M': /* single step until location modified - verbose */
+ cmd = skip(cmd);
+ switch (*cmd++) {
+ case 'b': size = sizeof(char); break;
+ case 'h': size = sizeof(short); break;
+ case 'l': size = sizeof(long); break;
+ default:
+ size = sizeof(int);
+ --cmd;
+ break;
+ }
+ modify(exp, (int) strtol(cmd, &cmd, 0), c == 'M', size);
+ break;
+ case 'k': /* kill current program */
+ tstart(T_EXIT, 1, 0, 0);
+ break;
+ case 'b': /* set a breakpoint at the given line */
+#ifdef MINIX_PC
+ if (seg != T || exp > end_addr ) {
+#else
+ if (seg != T || exp < st_addr || exp > et_addr ) {
+#endif
+ Printf("Address not in text space.\n");
+ return;
+ }
+ breakpt(exp, skip(cmd));
+ cmd = "\n";
+ return;
+ case 'B': /* print list of currently active breakpoints */
+ for (i = 1, bp = b_head; bp; bp = bp->nxt, i++) {
+ Printf("%2d: ", i);
+ symbolic((long) bp->addr, '\t');
+ Printf("(0x%lx)\t- %s", bp->addr, bp->cmd);
+ }
+ break;
+ case 'd': /* delete breakpoint */
+ if (seg == T) {
+ for (bp = b_head; bp && bp->addr != exp; bp = bp->nxt);
+ if (bp) {
+ freepnt(bp);
+ break;
+ }
+ }
+ Printf("No such breakpoint.\n");
+ break;
+ case 'D': /* delete all breakpoints */
+ while (b_head) freepnt(b_head);
+ break;
+ case 's':
+ dump_stack( strtol(cmd, &cmd, 0) );
+ break;
+ case 'P':
+ paging = !paging;
+ if (paging) Printf("Paging is ON\n");
+ break;
+ case 'l':
+ case 'L':
+ logging(c,skip(cmd));
+ break;
+#if SYSCALLS_SUPPORT
+ case 'z':
+ start_syscall( strtol(cmd, &cmd, 0) );
+ if ( syscalls )
+ Printf("Break point set - use the 'c n' command\n");
+ break;
+#endif
+ case 'q': /* quit */
+ tstart(T_EXIT, 0, 0, 0);
+ logging(c,cmd);
+ case 'Q':
+ exit(0);
+ break;
+ case '\n':
+ case ';':
+ if (isdigit(*cmdstart))
+ symbolic(exp, '\n');
+ else
+ Printf("0x%0*lx\n", 2 * ADDRSIZE, exp);
+ --cmd;
+ break;
+#ifdef DEBUG
+ case 'v': /* toggle debug */
+ debug = !debug;
+ if (debug) Printf("Debug flag ON\n");
+ break;
+#endif
+ case 'e': /* list symbols */
+ listsym(cmd);
+ break;
+ case 'y': /* print mapping */
+ prtmap();
+ break;
+ case '?': /* print help */
+ help_page();
+ break;
+ case 'V': /* print version info */
+ version_info();
+ break;
+ case '@': /* command file */
+ cmd = skip(cmd);
+ openin(cmd);
+ *cmd = '\n';
+ return;
+ case '#': /* set register or variable */
+ cmd = skip(cmd + 1);
+ if (*cmd == '$') {
+ cmd++;
+ i = reg_addr(cmd);
+ set_reg(curpid, i, strtol(cmd+2, &cmd, 0) );
+ update();
+ break;
+ }
+ cmd = getexp(cmd, &exp, &seg);
+ fill(exp, T_GETDATA);
+ break;
+ default:
+ help_page();
+ break;
+ }
+ while (*cmd != '\n' && *cmd != ';') ++cmd;
+ if (*cmd == ';') cmd = skip(cmd + 1);
+}
+
+PUBLIC void mdb_error(s)
+char *s;
+{
+ Printf("%s",s);
+ longjmp(mainlp, 0);
+}
+
+PUBLIC void main(argc, argv)
+int argc;
+char *argv[];
+{
+ int i, c;
+ char *p, *q, *r;
+ int opt_c = FALSE; /* load core file */
+ int opt_f = FALSE; /* load object file */
+ int opt_l = FALSE; /* log to file */
+ int opt_L = FALSE; /* log to file and screen */
+
+
+ prc = (struct proc *) lbuf;
+ strcpy(sbuf, "\n");
+ corepid = -1; /* set to indicate none */
+ prog = p = q = r = NULL;
+
+ if ( argc == 1 )
+ {
+ help_page();
+ exit(0);
+ }
+
+ /* Possible combinations of arguments:
+ * A single file name:
+ * If the name is 'core', the coreonly flag is set.
+ * The -c flag: examine a core file.
+ * One filename is required with this flag.
+ * The -f flag: examine an object file.
+ * One file name is required with this flag.
+ * The -L or -l flag: write to a log file.
+ * One file name is required with these flags.
+ * The -x flag: turn on debugging.
+ * Used for debugging, and followed by an integer
+ * argument which is the debugging level.
+ *
+ * If any files remain on the argument list, the first
+ * file is an executable, and the second a core file.
+ * If any filename starts with '@' it is assumed to
+ * to be a command file. Only one command file is
+ * loaded.
+ */
+
+ /* check for default file name and fake out getopt */
+ if (strcmp(argv[1], "core") == 0) {
+ for (i = argc ; i > 1 ; i--)
+ argv[i] = argv[i - 1];
+ argv[i] = "-c";
+ argc++;
+ }
+
+ /* parse options */
+ opterr = 0;
+ while ((i = getopt(argc, argv, "c:f:L:l:x:")) != EOF) {
+ switch (i & 0377) {
+ case 'c': /* examine a core file */
+ if (opt_c == TRUE || opt_f == TRUE) {
+ help_page();
+ exit(1);
+ }
+ p = optarg;
+ opt_c = TRUE;
+ break;
+ case 'f': /* examine an object file */
+ if (opt_c == TRUE || opt_f == TRUE) {
+ help_page();
+ exit(1);
+ }
+ p = optarg;
+ opt_f = TRUE;
+ break;
+ case 'l': /* start logging */
+ if (opt_l == TRUE || opt_L == TRUE) {
+ help_page();
+ exit(1);
+ }
+ opt_l = TRUE;
+ logging(i, optarg);
+ break;
+ case 'L': /* start logging */
+ if (opt_l == TRUE || opt_L == TRUE) {
+ help_page();
+ exit(1);
+ }
+ opt_L = TRUE;
+ logging(i, optarg);
+ break;
+#ifdef DEBUG
+ case 'x': /* set debug level */
+ debug = atoi(optarg);
+ break;
+#endif
+ case '?': /* default arguments arrive here */
+ default:
+ help_page();
+ exit(1);
+ }
+ }
+
+ /* can't cope without filenames */
+ if (!opt_c && !opt_f && optind >= argc) {
+ help_page();
+ exit(1);
+ }
+
+ /* any remaining arguments are (optional) file names */
+ for (i = optind ; i < argc ; i++) {
+ if (*argv[i] == '@') { /* command file */
+ if (r == NULL) r = argv[i] + 1;
+ }
+ /* you can't combine a -c or -f object file and a core file */
+ else if (!opt_c && !opt_f && p == NULL) p = argv[i];
+ else if (q == NULL) q = argv[i]; /* core file */
+ }
+
+ /* initialise stuff - fairly tricky logic */
+ coreonly = opt_c;
+ fileonly = opt_f;
+ /* when examining files, prog == NULL */
+ if (!opt_c && !opt_f) {
+ prog = p;
+ syminit(prog);
+ }
+
+ /* file_init is called for non-core files.
+ * It is very similar to core_init. It opens the file and set
+ * various pointers so that we can read it using the same routines
+ * as a core file.
+ * NB: Currently there is no special provision to handle object files.
+ */
+
+ /* A comment from Will Rose:
+ * It would be nice to have
+ * symbol tables available when reading a core
+ * or a.out, either as part of the executable or
+ * as a separate file.
+ * At least three separate types of file structure
+ * may be used by mdb - core files, a.out files, and
+ * object files (which may have several flavours).
+ * A set of routines is needed for each type, with
+ * a function switch table initialised when mdb is
+ * started up.
+ */
+
+ if (opt_c) lastexp = core_init(p);
+ if (opt_f) lastexp = file_init(p);
+ if (q != NULL) lastexp = core_init(q);
+ if (r != NULL) openin(r);
+ for (i = 1; i < _NSIG; i++) signal(i, catch);
+
+ setjmp(mainlp);
+
+ while (get_cmd( cbuf, MAXLINE ) != NULL) {
+ if (strlen(cbuf) == sizeof(cbuf) - 1) {
+ Printf("Command line too long.\n");
+ continue;
+ }
+ cmd = cbuf;
+ command();
+ while (*cmd != '\n') command();
+ }
+ tstart(T_EXIT, 0, 0, 0);
+ exit(0);
+}
--- /dev/null
+/*
+ * mdb.h for mdb
+ */
+#define MDBVERSION "2.6"
+#define MDBBUILD 0
+
+#define MINIX_SYMBOLS 1
+#define GNU_SYMBOLS 2
+
+/*
+ * Handle options here
+ */
+#ifndef GNU_SUPPORT
+#define GNU_SUPPORT 0
+#endif
+
+#ifndef SYSCALLS_SUPPORT
+#define SYSCALLS_SUPPORT 0
+#endif
+
+#ifdef DEBUG
+#undef DEBUG
+#endif
+
+#ifdef NDEBUG
+#undef DEBUG
+#else
+#define DEBUG 1
+#endif
+
+#ifdef __i386
+#define EXTRA_SYMBOLS GNU_SUPPORT
+#else
+#define EXTRA_SYMBOLS 0
+#endif
+
+
+#include <minix/config.h>
+#include <ansi.h>
+#include <sys/types.h>
+
+#include <minix/const.h>
+#include <minix/type.h>
+
+#include <limits.h>
+#include <errno.h>
+#include <minix/ipc.h>
+#include <timers.h>
+
+#undef printf /* defined as printk in <minix/const.h> */
+
+#if (CHIP == M68000)
+#define __mc68000__ /* controls processor-dependent stuff */
+#if (MACHINE == ATARI)
+#define MINIX_ST /* controls system-dependent stuff */
+#else
+#error "only the MINIX_ST 1.5.x implementation works on 68K's"
+#endif
+#endif
+
+#if (CHIP == INTEL)
+#if (MACHINE == IBM_PC)
+#define MINIX_PC
+#else
+#error "only the MINIX_PC 1.5.x and later versions works on *86's"
+#endif
+#endif
+
+#ifdef MINIX_ST
+#define BP_OFF ((long)&((struct proc *)0)->p_reg.a6)
+#define PC_MEMBER(rp) ((rp)->p_reg.pc)
+#define PC_OFF ((long)&((struct proc *)0)->p_reg.pc)
+#define SP_MEMBER(rp) ((rp)->p_reg.sp)
+#define PSW_MEMBER(rp) ((rp)->p_reg.psw)
+#endif
+
+#ifdef MINIX_PC
+#define BP_OFF ((long)&((struct proc *)0)->p_reg.fp)
+#define PC_MEMBER(rp) ((rp)->p_reg.pc)
+#define PC_OFF ((long)&((struct proc *)0)->p_reg.pc)
+#endif
+
+#define ADDRSIZE _WORD_SIZE
+#define BITSIZE(size) (8 * (size))
+#define INTSIZE (sizeof(int)) /* not quite right for cross-debugger */
+#define LONGSIZE (sizeof(long))
+#define UCHAR(x) ((x) & 0xFF)
+#define NOSEG (-1) /* no segment */
+
+/* use hardware codes for segments for simplest decoding */
+#define CSEG 0x2E /* 8088 through 80386 */
+#define DSEG 0x3E
+
+#if (CHIP == INTEL )
+#ifdef __i86
+#define N_REG16 2
+#endif
+#ifdef __i386
+#define N_REG16 4 /* 16 bit registers at start of stackframe */
+#endif
+#ifndef N_REG16
+#error "N_REG16 not defined"
+#endif
+#endif
+
+#if (CHIP == INTEL )
+#define ADDA(l) ((u16_t) (l) == 0xC481)
+
+#ifdef __i386
+#define ADDA_CNT(l) ((i32_t) (l))
+#else
+#define ADDA_CNT(l) ((i16_t) (l))
+#endif
+
+#define ADDQ(l) ((u16_t) (l) == 0xC483)
+#define ADDQ_CNT(l) (((((l) >> 16) + 128) & 0x000000FF) - 128)
+#define BREAK(l) (0x000000CC | ((l) & 0xFFFFFF00))
+#define BREAKPOINT_ADVANCE 1
+#define INCSP2(l) ((u16_t) (l) == 0x4444)
+#define POPBX2(l) ((u16_t) (l) == 0x5B5B)
+#define POPBX(l) ( (l & 0xFF) == 0x5B)
+
+/* Added for ANSI CC */
+#define POPCX2(l) ((u16_t) (l) == 0x5959)
+#define POPCX(l) ( (l & 0xFF) == 0x59)
+
+#endif
+
+#ifdef __mc68000__
+#define ADDA(l) ((int)((l) >> 16) == 0xDFFC)
+#define ADDA_CNT(l) (l)
+#define ADDQ(l) (((l >> 16) & 0xF13F) == 0x500F)
+#define ADDQ_CNT(l) (((((l) >> 25) - 1) & 7) + 1)
+#define BREAK(l) (0xA0000000 | ((l) & 0xFFFF))
+#define BREAKPOINT_ADVANCE 0
+#define BYTES_SWAPPED /* this assumes WORDS_SWAPPED too */
+#define LEA(l) (((l) >> 16) == 0x4FEF)
+#define LEA_DISP(l) ((long)( l & 0xFFFF))
+#endif
+
+#define MASK(size) ((size) >= LONGSIZE ? -1L : (1L << BITSIZE(size)) - 1)
+
+#ifdef BYTES_SWAPPED
+#define SHIFT(size) BITSIZE(LONGSIZE - (size))
+#else
+#define SHIFT(size) (0)
+#endif
+
+#ifdef _MAIN_MDB
+#undef EXTERN
+#define EXTERN
+#endif
+
+extern long lbuf[]; /* buffer for proc */
+
+EXTERN long st_addr; /* starting address of text */
+EXTERN long et_addr; /* ending address of text */
+EXTERN long sd_addr; /* starting address of data */
+EXTERN long ed_addr; /* ending address of data */
+EXTERN long end_addr; /* ending address of text/data */
+EXTERN long sk_addr; /* starting address of stack */
+EXTERN long sk_size; /* size of stack */
+EXTERN int curpid; /* current pid of process/core */
+EXTERN int corepid; /* pid of core file */
+EXTERN int coreonly; /* core file only */
+EXTERN int fileonly; /* file only */
+EXTERN int cursig; /* current signal */
+EXTERN int seg; /* segment */
+EXTERN int is_separate; /* separate I & D */
+EXTERN int paging; /* paging flag */
+#ifdef DEBUG
+EXTERN int debug; /* debug flag */
+#endif
+#if SYSCALLS_SUPPORT
+EXTERN int syscalls; /* trace syscalls */
+#endif
+
+#ifdef _MAIN_MDB
+#undef EXTERN
+#define EXTERN extern
+#endif
+
--- /dev/null
+/*
+ * mdbdis86.c for mdb.c - 8086-386 and 8087 disassembler
+ * From Bruce Evans db
+ */
+
+#include "mdb.h"
+#include <stddef.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include "proto.h"
+
+struct address_s
+{
+ off_t off;
+ off_t base;
+};
+
+PRIVATE int bits32;
+PRIVATE struct address_s uptr;
+
+FORWARD _PROTOTYPE( u8_t get8, (void) );
+FORWARD _PROTOTYPE( u16_t get16, (void) );
+FORWARD _PROTOTYPE( u32_t get32, (void) );
+FORWARD _PROTOTYPE( u8_t peek_byte, (off_t addr) );
+FORWARD _PROTOTYPE( u16_t peek_word, (off_t addr) );
+FORWARD _PROTOTYPE( int puti, (void) );
+FORWARD _PROTOTYPE( int outsegaddr, (struct address_s *addr) );
+FORWARD _PROTOTYPE( int outssegaddr, (struct address_s *addr) );
+FORWARD _PROTOTYPE( int show1instruction , (void));
+
+/************************* UNASM ******************************/
+
+
+#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
+
+typedef unsigned opcode_pt; /* promote to unsigned and not int */
+
+typedef int reg_pt;
+typedef int su16_t;
+typedef int su8_pt;
+
+FORWARD _PROTOTYPE( su8_pt get8s , (void));
+FORWARD _PROTOTYPE( void getmodregrm , (void));
+FORWARD _PROTOTYPE( void i_00_to_3f , (opcode_pt opc ));
+FORWARD _PROTOTYPE( void i_40_to_5f , (opcode_pt opc ));
+FORWARD _PROTOTYPE( void i_60_to_6f , (opcode_pt opc ));
+FORWARD _PROTOTYPE( void i_70_to_7f , (opcode_pt opc ));
+FORWARD _PROTOTYPE( void i_80 , (opcode_pt opc ));
+FORWARD _PROTOTYPE( void i_88 , (opcode_pt opc ));
+FORWARD _PROTOTYPE( void i_90 , (opcode_pt opc ));
+FORWARD _PROTOTYPE( void i_98 , (opcode_pt opc ));
+FORWARD _PROTOTYPE( void i_a0 , (opcode_pt opc ));
+FORWARD _PROTOTYPE( void i_a8 , (opcode_pt opc ));
+FORWARD _PROTOTYPE( void i_b0 , (opcode_pt opc ));
+FORWARD _PROTOTYPE( void i_b8 , (opcode_pt opc ));
+FORWARD _PROTOTYPE( void i_c0 , (opcode_pt opc ));
+FORWARD _PROTOTYPE( void i_c8 , (opcode_pt opc ));
+FORWARD _PROTOTYPE( void i_d0 , (opcode_pt opc ));
+FORWARD _PROTOTYPE( void i_d8 , (opcode_pt opc ));
+FORWARD _PROTOTYPE( void i_e0 , (opcode_pt opc ));
+FORWARD _PROTOTYPE( void i_e8 , (opcode_pt opc ));
+FORWARD _PROTOTYPE( void i_f0 , (opcode_pt opc ));
+FORWARD _PROTOTYPE( void i_f8 , (opcode_pt opc ));
+FORWARD _PROTOTYPE( void outad , (opcode_pt opc ));
+FORWARD _PROTOTYPE( void outad1 , (opcode_pt opc ));
+FORWARD _PROTOTYPE( void outalorx , (opcode_pt opc ));
+FORWARD _PROTOTYPE( void outax , (void));
+FORWARD _PROTOTYPE( void outbptr , (void));
+FORWARD _PROTOTYPE( void outbwptr , (opcode_pt opc ));
+FORWARD _PROTOTYPE( void outea , (opcode_pt wordflags ));
+FORWARD _PROTOTYPE( void outf1 , (void));
+FORWARD _PROTOTYPE( void out32offset , (void));
+FORWARD _PROTOTYPE( void outfishy , (void));
+FORWARD _PROTOTYPE( void outgetaddr , (void));
+FORWARD _PROTOTYPE( void outimmed , (opcode_pt signwordflag ));
+FORWARD _PROTOTYPE( void outpc , (off_t pc ));
+FORWARD _PROTOTYPE( void outsegpc , (void));
+FORWARD _PROTOTYPE( void oututstr , (char *s ));
+FORWARD _PROTOTYPE( void outword , (void));
+FORWARD _PROTOTYPE( void outwptr , (void));
+FORWARD _PROTOTYPE( void outwsize , (void));
+FORWARD _PROTOTYPE( void pagef , (void));
+FORWARD _PROTOTYPE( void shift , (opcode_pt opc ));
+FORWARD _PROTOTYPE( void checkmemory , (void));
+FORWARD _PROTOTYPE( void CL , (void));
+FORWARD _PROTOTYPE( void Eb , (void));
+FORWARD _PROTOTYPE( void Ev , (void));
+FORWARD _PROTOTYPE( void EvGv , (void));
+FORWARD _PROTOTYPE( void EvIb , (void));
+FORWARD _PROTOTYPE( void Ew , (void));
+FORWARD _PROTOTYPE( void EwRw , (void));
+FORWARD _PROTOTYPE( void Gv , (void));
+FORWARD _PROTOTYPE( void Gv1 , (void));
+FORWARD _PROTOTYPE( void GvEv , (void));
+FORWARD _PROTOTYPE( void GvEw , (void));
+FORWARD _PROTOTYPE( void GvM , (void));
+FORWARD _PROTOTYPE( void GvMa , (void));
+FORWARD _PROTOTYPE( void GvMp , (void));
+FORWARD _PROTOTYPE( void Ib , (void));
+FORWARD _PROTOTYPE( void Iw , (void));
+FORWARD _PROTOTYPE( void Iv , (void));
+FORWARD _PROTOTYPE( void Jb , (void));
+FORWARD _PROTOTYPE( void Jv , (void));
+FORWARD _PROTOTYPE( void Ms , (void));
+
+_PROTOTYPE( typedef void (*pfv_t),(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 data_seg; /* data segment (munged name for asld) */
+PRIVATE unsigned hasize; /* half address size in bits */
+PRIVATE unsigned hdefsize;
+PRIVATE unsigned hosize; /* half operand size in bits */
+ /* for easy index into reg tables */
+PRIVATE opcode_pt mod;
+PRIVATE off_t offtable[2];
+PRIVATE off_t *offptr;
+PRIVATE off_t *off1ptr;
+PRIVATE opcode_pt reg;
+PRIVATE opcode_pt rm;
+
+PRIVATE su8_pt get8s()
+{
+ u8_t 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;
+
+ 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;
+ }
+}
+
+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");
+ case 2:
+ outwptr();
+ break;
+ case 8:
+ outustr("q");
+ outwptr();
+ break;
+ case 10:
+ outustr("t");
+ outbptr();
+ 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;
+ reg_pt index;
+ opcode_pt ss;
+ opcode_pt ssindexbase;
+
+ 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('+');
+#if (_WORD_SIZE == 4)
+ out32offset();
+#else
+ outgetaddr();
+#endif
+ }
+ outbyte(RINDIRECT);
+ if (hasize == 16 && rm == 4 && index == 4 && ss != 0)
+ outfishy();
+ }
+}
+
+PRIVATE void outf1()
+{
+ outustr("st(");
+ outbyte((int) (rm + '0'));
+ outbyte(')');
+}
+
+#if (_WORD_SIZE == 4)
+
+PRIVATE void out32offset()
+{
+ off_t off;
+
+ if (hasize == 16)
+ off = get32();
+ else
+ outfishy();
+
+ outh32(off);
+}
+#endif
+
+PRIVATE void outfishy()
+{
+ outustr("\t???");
+}
+
+PRIVATE void outgetaddr()
+{
+ off_t off;
+
+ if (hasize == 16)
+ off = get32();
+ else
+ off = get16();
+
+ if ( finds_data(off,data_seg) )
+ *offptr++ = off;
+ else if (hasize == 16)
+ outh32(off);
+ else
+ outh16((u16_t) 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_t) byte);
+ }
+ else
+ Iv();
+ }
+ else
+ Ib();
+}
+
+PRIVATE void outpc(pc)
+off_t pc;
+{
+ if (hosize == 8)
+ pc = (u16_t) pc;
+
+ if ( finds_pc(pc) )
+ *offptr++ = pc;
+ else if (hosize == 16)
+ outh32(pc);
+ else
+ outh16((u16_t) pc);
+}
+
+PRIVATE void outsegpc()
+{
+ off_t oldbase;
+ off_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 */
+ outbyte(':');
+ outpc(pc);
+ 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;
+ int 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;
+ }
+ }
+ else
+ outstr(fishy);
+}
+
+PRIVATE int puti()
+{
+ static int hadprefix;
+ opcode_pt opcode;
+
+more:
+ offptr = offtable;
+ opcode = get8();
+ 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 (hosize == 16)
+ outh32(get32());
+ else
+ Iw();
+}
+
+PRIVATE void Jb()
+{
+ off_t pcjump;
+
+ pcjump = get8s();
+ outpc(pcjump + uptr.off);
+}
+
+PRIVATE void Jv()
+{
+ off_t pcjump;
+
+ if (hosize == 16)
+ pcjump = get32();
+ else
+ pcjump = (su16_t) get16();
+ outpc(pcjump + uptr.off);
+}
+
+PRIVATE void Ms()
+{
+ Ev();
+ checkmemory();
+}
+
+/********************* DASM ******************************/
+
+PUBLIC long dasm( addr, count, symflg )
+long addr;
+int count;
+int symflg;
+{
+#if (_WORD_SIZE == 4)
+ bits32 = TRUE; /* Set mode */
+#else
+ bits32 = FALSE;
+#endif
+ uptr.off = addr;
+ uptr.base = 0; /* not known */
+ while ( count-- != 0 && show1instruction() )
+ ;
+}
+
+
+PRIVATE int show1instruction()
+{
+ register int column;
+ int idone;
+ static char line[81];
+ int maxcol;
+ struct address_s newuptr;
+ struct address_s olduptr;
+
+ outbyte('\r');
+ do
+ {
+ if ( text_symbol(uptr.off) ) {
+ outbyte(':');
+ outbyte('\n');
+ }
+ olduptr = uptr;
+ openstring(line);
+ idone = puti();
+ line[stringpos()] = 0;
+ closestring();
+ newuptr = uptr;
+ uptr = olduptr;
+ column = outssegaddr(&uptr);
+ while (uptr.off != newuptr.off)
+ {
+ outh8(get8());
+ column += 2;
+ }
+ maxcol = bits32 ? 24 : 16;
+ while (column < maxcol)
+ {
+ outtab();
+ column += 8;
+ }
+ outtab();
+ outstr(line);
+ outbyte('\n');
+ }
+ while (!idone); /* eat all prefixes */
+ return TRUE;
+}
+
+
+PRIVATE u8_t get8()
+{
+/* get 8 bits current instruction pointer and advance pointer */
+
+ u8_t temp;
+
+ temp = peek_byte(uptr.off + uptr.base);
+ ++uptr.off;
+ return temp;
+}
+
+PRIVATE u16_t get16()
+{
+/* get 16 bits from current instruction pointer and advance pointer */
+
+ u16_t temp;
+
+ temp = peek_word(uptr.off + uptr.base);
+ uptr.off += 2;
+ return temp;
+}
+
+PRIVATE u32_t get32()
+{
+/* get 32 bits from current instruction pointer and advance pointer */
+
+ u32_t temp;
+
+ temp = peek_dword(uptr.off + uptr.base);
+ uptr.off += 4;
+ return temp;
+}
+
+
+PRIVATE int outsegaddr(addr)
+struct address_s *addr;
+{
+/* print segmented address */
+
+ int bytes_printed;
+
+ bytes_printed = 2;
+ bytes_printed = outsegreg(addr->base);
+ if (bytes_printed > 4)
+ outbyte('+');
+ else
+ outbyte(':');
+ ++bytes_printed;
+ if (addr->off >= 0x10000)
+ {
+ outh32(addr->off);
+ return bytes_printed + 8;
+ }
+ outh16((u16_t) addr->off);
+ return bytes_printed + 4;
+}
+
+PRIVATE int outssegaddr(addr)
+struct address_s *addr;
+{
+/* print 32 bit segmented address and 2 spaces */
+
+ int bytes_printed;
+
+ bytes_printed = outsegaddr(addr);
+ outspace();
+ outspace();
+ return bytes_printed + 2;
+}
+
+PRIVATE u8_t peek_byte(addr)
+off_t addr;
+{
+ return (u8_t) peek_dword(addr) & 0xFF; /* 8 bits only */
+}
+
+PRIVATE u16_t peek_word(addr)
+off_t addr;
+{
+ return (u16_t) peek_dword(addr);
+}
--- /dev/null
+/*
+ * mdbexp.c - MINIX expresion parser
+ *
+ * Written by Bruce D. Szablak
+ *
+ * This free software is provided for non-commerical use. No warrantee
+ * of fitness for any use is implied. You get what you pay for. Anyone
+ * may make modifications and distribute them, but please keep this header
+ * in the distribution.
+ */
+
+#include "mdb.h"
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "proto.h"
+
+FORWARD _PROTOTYPE(long value , (char *s , char **s_p , int *seg_p ));
+FORWARD _PROTOTYPE(long lookup , (char *s , char **s_p , int *seg_p ));
+
+#define idchar(c) (isalpha(c) || isdigit(c) || (c) == '_')
+
+/*
+ * Get an expression for mdb
+ */
+PUBLIC char *getexp(buf, exp_p, seg_p)
+char *buf;
+int *seg_p;
+long *exp_p;
+{
+ long v = 0L;
+
+ buf = skip(buf);
+ if ((isalpha(*buf) && (isspace(buf[1]) || buf[1] == ';'))
+ || *buf == '\n'
+ || *buf == ';'
+ || *buf == '/'
+ || *buf == '!'
+ || *buf == '?'
+ || *buf == '@'
+ || *buf == '#') {
+ *exp_p = 0L;
+ return buf;
+ }
+ v = value(buf, &buf, seg_p);
+ buf = skip(buf);
+ if (*buf == '+')
+ v += value(skip(buf + 1), &buf, seg_p);
+ else if (*buf == '-')
+ v -= value(skip(buf + 1), &buf, seg_p);
+ *exp_p = v;
+ return skip(buf);
+}
+
+/*
+ * Get value
+ *
+ * \c escaped characters
+ * digits number
+ * $xx registers
+ * \n 0L
+ * then calls lookup for symbols
+ */
+PRIVATE long value(s, s_p, seg_p)
+char *s, **s_p;
+int *seg_p;
+{
+ long k;
+
+ if (*s == '\'') { /* handle character constants here */
+ *s_p = s + 2;
+ return s[1];
+ }
+ if (*s == '-' || isdigit(*s))
+ return strtol(s, s_p, 0);
+ if (*s == '$') {
+ k = reg_addr(s + 1);
+ *s_p = s + 3;
+ return get_reg(curpid, k);
+ k = reg_addr(s + 1);
+ *s_p = s + 3;
+ return get_reg(curpid, k);
+ }
+ if (*s == '\n') {
+ *s_p = s + 1;
+ return 0L;
+ }
+ return lookup(s, s_p, seg_p);
+}
+
+/*
+ * Lookup symbol - return value
+ * Handle special cases: _start T: D: S:
+ * then call symbolvalue()
+ */
+PRIVATE long lookup(s, s_p, seg_p)
+char *s, **s_p;
+int *seg_p;
+{
+ long value;
+ char c;
+ int l;
+
+ for (l = 1; idchar(s[l]); ++l) {}
+ c = s[l];
+ s[l] = 0;
+
+ if (strcmp("_start", s) == 0) {
+ *seg_p = T;
+ if (c == ':') c = '+';
+ *(*s_p = s + 6) = c;
+ return st_addr;
+ }
+ if (strcmp("T", s) == 0) {
+ *seg_p = T;
+ if (c == ':') c = '+';
+ *(*s_p = s + 1) = c;
+ return st_addr;
+ }
+ if (strcmp("D", s) == 0) {
+ *seg_p = D;
+ if (c == ':') c = '+';
+ *(*s_p = s + 1) = c;
+ return sd_addr;
+ }
+ if (strcmp("S", s) == 0) {
+ *seg_p = S;
+ if (c == ':') c = '+';
+ *(*s_p = s + 1) = c;
+ return sk_addr;
+ }
+
+ if ((value = symbolvalue(s, TRUE)) != 0L) {
+ *seg_p = T;
+ *(*s_p = s + l) = c;
+ return value;
+ }
+
+ if ((value = symbolvalue(s, FALSE)) != 0L) {
+ *seg_p = D;
+ *(*s_p = s + l) = c;
+ return value;
+ }
+
+ Printf("%s: ", s);
+ mdb_error("symbol not found\n");
+}
+
+/* Skip spaces */
+PUBLIC char *skip(s)
+register char *s;
+{
+ while (isspace(*s)) ++s;
+ return *s ? s : s - 1;
+}
+
--- /dev/null
+/*
+ * misc.c for mdb
+ */
+
+#include "mdb.h"
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#define ptrace mdbtrace
+#include <sys/ptrace.h>
+#include "proto.h"
+
+FORWARD _PROTOTYPE( void pr_ascii , (long val , int size ));
+
+/* Print ascii */
+PRIVATE void pr_ascii(val, size)
+long val;
+int size;
+{
+ int i;
+ int v;
+ int sh;
+
+#ifdef BYTES_SWAPPED
+ sh = 8 * size;
+#else
+ sh = 0;
+#endif
+
+ for (i = 0; i < size; i++) {
+ v = (int) (val >> sh) & 0xFF;
+#ifdef BYTES_SWAPPED
+ sh -= 8;
+#else
+ sh += 8;
+#endif
+ Printf(isprint(v) ? "%c" : "\\%03o", v);
+ }
+ Printf("\n");
+}
+
+/* Dump stack */
+PUBLIC void dump_stack(cnt)
+long cnt;
+{
+ vir_bytes v, vi;
+ long val, sp;
+ int num, size, nmode;
+
+ size = INTSIZE; /* size of stack element */
+ num = (int) cnt;
+ if (num <= 0) num = 0;
+ if (num > sk_size) num = (int) sk_size / size;
+ nmode = num; /* Save mode */
+
+ /* Get current SP */
+ sp = get_reg(curpid, reg_addr("sp"));
+
+ /* Starting address is top of stack seg -1 */
+ vi = (vir_bytes) sk_addr + (vir_bytes) sk_size - size;
+
+ /* Ending address */
+ v = (vir_bytes) end_addr;
+ if (nmode == 0) v = MAX(v, sp);
+
+ Printf("Stack Dump SP=%*lx\nAddr\tHex\tAscii\n", 2 * size, sp);
+ do {
+ val = (ptrace(T_GETDATA, curpid, (long) vi, 0L) >> SHIFT(size))
+ & MASK(size);
+ Printf("%*lx\t", 2 * ADDRSIZE, (vi >> SHIFT(ADDRSIZE))
+ & MASK(ADDRSIZE));
+ Printf("%*lx\t", 2 * size, val);
+ pr_ascii(val, size);
+ num -= 1;
+ vi -= size;
+ } while (vi >= v && (nmode ? num > 0 : 1));
+
+}
+
+
+/* Get file size */
+PUBLIC off_t file_size(fd)
+int fd;
+{
+struct stat st;
+
+ if(fstat(fd,&st) <0 ) {
+ Printf("Cannot stat\n");
+ return 0L;
+ }
+ else
+ return st.st_size;
+}
+
+/* Print help page */
+PUBLIC void help_page()
+{
+ outstr("\nHelp for mdb. For more details, type 'command ?'\n");
+ outstr("!#\t- Shell escape / Set Variable or register\n");
+ outstr("Tt\t- Current call / Backtrace all\n");
+ outstr("/nsf\t- Display for n size s with format f\n");
+ outstr("Xx [n]\t- Disasm / & display reg for n instructions\n");
+ outstr("Rr a\t- Run / with arguments a\n");
+ outstr("Cc [n]\t- Continue with current signal / no signal n times\n");
+ outstr("Ii [n]\t- Single step with / no signal for n instructions\n");
+ outstr("Mm t n\t- Trace until / Stop when modified t type for n instructions\n");
+ outstr("k \t- Kill traced process\n");
+ outstr("Bb\t- Display / Set Break-pt\n");
+ outstr("Dd\t- Delete all / one break-points\n");
+ outstr("P\t- Toggle Paging\n");
+ outstr("Ll name\t- Log to file name / and to standard output\n");
+#ifdef DEBUG
+ outstr("Vv\t- Version info / Toggle debug flag\n");
+#else
+ outstr("V\t- Version info\n");
+#endif
+ outstr("e [t]\t- List symbols for type t\n");
+ outstr("y\t- Print segment mappings\n");
+ outstr("s [n]\t- Dump stack for n words\n");
+#if SYSCALLS_SUPPORT
+ outstr("z [a]\t- Trace syscalls with address a\n");
+#endif
+ outstr("? \t- Help - this screen\n");
+ outstr("@ file\t- Execute commands from file\n");
+ outstr("Qq\t- Quit / and kill traced process\n");
+#ifdef DEBUG
+ outstr("Usage: mdb -x debug-level [-Ll]logfile exec-file core-file @command-file\n");
+#else
+ outstr("Usage: mdb [-Ll]logfile exec-file core-file @command-file\n");
+#endif
+ outstr(" mdb [-fc] file\n");
+}
+
+PUBLIC void version_info()
+{
+ Printf("\nmdb version %s.%d for Minix", MDBVERSION, MDBBUILD );
+ Printf(" %s.%s", OS_RELEASE, OS_VERSION);
+#ifdef MINIX_PC
+#ifdef __i386
+ Printf(" (32-bit)");
+#else
+ Printf(" (16-bit)");
+#endif
+#endif
+#ifdef MINIX_ST
+ Printf("-ST");
+#endif
+ Printf("\n");
+}
+
+/* Print help message on command */
+PUBLIC void help_on(h)
+int h;
+{
+
+ switch (h) {
+ case '/':
+ outstr("<address> /nsf\t- Display for n items of size s with format f from address\n");
+ outstr("\t n defaults to 1\n");
+ outstr("\t s defaults to size of int\n");
+ outstr("\t can be b for byte h for short l for long\n");
+ outstr("\t f defaults to d for decimal\n");
+ outstr("\t can be x X o d D c s or u as in printf\n");
+ outstr("\t y treat value as address\n");
+ outstr("\t i disasm\n");
+ break;
+ case '@':
+ outstr("@ file\t- Execute commands from file\n");
+ break;
+ case '#':
+ outstr("# <address> cs value\t- Set Variable(s) at address to value\n");
+ outstr("\t\t\t for c count and size s\n");
+ outstr("\t\t\t b for byte h for short or l for long\n");
+ outstr("\t\t\t Count or size must be specified\n");
+ outstr("# $xx value\t\t- Set register $xx to value\n");
+ break;
+ case 'C':
+ outstr("C [n]\t- Continue with curent signal n times\n");
+ outstr("\t n defaults to 1\n");
+ break;
+ case 'c':
+ outstr("c [n]\t- Continue with no signal n times\n");
+ outstr("\t n defaults to 1\n");
+ break;
+ case 'e':
+ outstr("e [t]\t- List symbols for type t\n");
+ break;
+ case 's':
+ outstr("s [n]\t- Dump stack for n words\n");
+ outstr("\t n defaults to whole stack\n");
+ break;
+ case 'I':
+ outstr("I n\t- Single step with signal for n instructions n defaults to 1\n");
+ break;
+ case 'i':
+ outstr("i n\t- Single step with no signal for n instructions n defaults to 1\n");
+ break;
+ case 'M':
+ case 'm':
+ if ( h == 'M')
+ outstr("<address> M t n\t- Trace until\n");
+ else
+ outstr("<address> m t n\t- Stop when\n");
+ outstr("\t\t<address> is modified t type for n instructions\n");
+ outstr("\t\tn defaults to 1\n");
+ outstr("\t\tb for byte h for short l for long defaults to size of int\n");
+ break;
+ case 'T':
+ outstr("T\t- Display current call\n");
+ break;
+ case 't':
+ outstr("t\t- Backtrace all calls\n");
+ break;
+ case '!':
+ outstr("![command]\t- Shell escape or spawn command\n");
+ break;
+ case 'R':
+ outstr("R\t- Run the exec-file\n");
+ break;
+ case 'r':
+ outstr("r [arguments]\t- Run the exec-file with arguments\n");
+ break;
+ case 'k':
+ outstr("k\t- Kill traced process\n");
+ break;
+ case 'B':
+ outstr("B\t- Display all the Break points\n");
+ break;
+ case 'b':
+ outstr("<address> b [commands]\t- Set Break-pt at address\n");
+ outstr("\t\t\t commands will be executed by mdb at break-pt\n");
+ break;
+ case 'D':
+ outstr("D\t- Delete all break-points\n");
+ break;
+ case 'd':
+ outstr("<address> d\t- Delete one break-point at address\n");
+ break;
+ case 'q':
+ outstr("q\t- Quit mdb (and kill traced program)\n");
+ break;
+ case 'Q':
+ outstr("Q\t- Quit mdb immediately\n");
+ break;
+ case 'P':
+ outstr("P\t- Toggle Paging\n");
+ outstr("\t Defaults is OFF\n");
+ break;
+ case 'L':
+ outstr("L name\t- Log to file name\n");
+ outstr("L\t- Reset output to standard output\n");
+ break;
+ case 'l':
+ outstr("l name\t- Log to file name and standard output\n");
+ outstr("l\t- Reset output to standard output\n");
+ outstr("\t Defaults to none\n");
+ break;
+#ifdef DEBUG
+ case 'v':
+ outstr("v\t- Toggle debug flag\n");
+ break;
+#endif
+ case 'V':
+ outstr("V\t- Print Version Information for mdb\n");
+ break;
+ case 'X':
+ outstr("<address> X [n] [offset]\t- Disasm for n instructions\n");
+ outstr("\t\t\t Starting at address+offset\n");
+ break;
+ case 'x':
+ outstr("<address> x [n] offset\t- Disasm & display registers for n instructions\n");
+ outstr("\t\t\t Starting at address+offset\n");
+ break;
+ case 'y':
+ outstr("y\t- Print segment mappings\n");
+ break;
+#if SYSCALLS_SUPPORT
+ case 'z':
+ outstr("z [address]\t- Trace system calls using address\n");
+ outstr("\t\t If the exec-file has symbols, mdb looks for __sendrec\n");
+ break;
+#endif
+ default:
+ Printf("No help on command '%c' is available\n",h);
+ break;
+ }
+}
+
--- /dev/null
+/*
+ * proto.h for mdb
+ */
+
+/* core.c */
+
+_PROTOTYPE( void prtmap, (void) );
+_PROTOTYPE( unsigned long core_init, (char *filename) );
+_PROTOTYPE( unsigned long file_init, (char *filename) );
+_PROTOTYPE( long read_core, (int req, long addr, long data) );
+
+/* mdb.c */
+
+_PROTOTYPE( void mdb_error, (char *s) );
+_PROTOTYPE( long breakpt , (long addr , char *cmd ));
+_PROTOTYPE( void tstart , (int req , int verbose , int val , int cnt ));
+
+/* io.c */
+
+_PROTOTYPE( char *get_cmd , (char *cbuf, int csize) );
+_PROTOTYPE( void openin , (char *s ));
+_PROTOTYPE( void logging, (int c, char *name) );
+_PROTOTYPE( void do_error, (char *message) );
+_PROTOTYPE( int Printf, (const char *format, ...));
+_PROTOTYPE( void outbyte, (int byte) );
+_PROTOTYPE( void outcomma, (void) );
+_PROTOTYPE( void outh8, (unsigned num) );
+_PROTOTYPE( void outh16, (unsigned num) );
+_PROTOTYPE( void outh32, (unsigned num) );
+_PROTOTYPE( void outh4, (unsigned num) );
+_PROTOTYPE( void outspace, (void) );
+_PROTOTYPE( void outstr, (char *s) );
+_PROTOTYPE( void outtab, (void) );
+_PROTOTYPE( void outustr, (char *s) );
+_PROTOTYPE( void closestring, (void) );
+_PROTOTYPE( int mytolower, (int ch) );
+_PROTOTYPE( void openstring, (char *string) );
+_PROTOTYPE( int stringpos, (void) );
+_PROTOTYPE( int stringtab, (void) );
+
+/* mdbdis86.c */
+
+_PROTOTYPE( long dasm, (long addr, int count, int symflg) );
+
+/* mdbexp.c */
+
+_PROTOTYPE( char *getexp, (char *buf, long *exp_p, int *seg_p) );
+_PROTOTYPE( char *skip, (char *s) );
+
+/* kernel.c */
+_PROTOTYPE( long get_reg, (int pid, long k) );
+_PROTOTYPE( void set_reg, (int pid, long k, long value) );
+_PROTOTYPE( long reg_addr, (char *s) );
+_PROTOTYPE( int disp_regs, (void) );
+_PROTOTYPE( int outsegreg, (off_t num) );
+_PROTOTYPE( void update , (void));
+_PROTOTYPE( void disp_maps , (void));
+
+/* misc.c */
+
+_PROTOTYPE( void dump_stack, (long count) );
+_PROTOTYPE( off_t file_size, (int fd) );
+_PROTOTYPE( void help_on, (int h) );
+_PROTOTYPE( void version_info, (void) );
+_PROTOTYPE( void help_page, (void) );
+
+#if EXTRA_SYMBOLS
+/* gnu_sym.c */
+_PROTOTYPE( void gnu_init, (char *filename) );
+_PROTOTYPE( long gnu_symbolvalue, (char *name, int is_text ) );
+_PROTOTYPE( void gnu_symbolic, (off_t value, int separator) );
+_PROTOTYPE( void gnu_listsym, (int tchar) );
+_PROTOTYPE( int gnu_text_symbol, (off_t value) );
+_PROTOTYPE( int gnu_finds_pc, (off_t pc) );
+_PROTOTYPE( int gnu_finds_data, (off_t off, int data_seg) );
+#endif /* EXTRA_SYMBOLS */
+
+/* sym.c */
+_PROTOTYPE( void syminit, (char *filename) );
+_PROTOTYPE( long symbolvalue, (char *name, int is_text ) );
+_PROTOTYPE( void printhex, (off_t v) );
+_PROTOTYPE( void symbolic, (off_t value, int separator) );
+_PROTOTYPE( void listsym, (char *cmd) );
+_PROTOTYPE( int text_symbol, (off_t value) );
+_PROTOTYPE( int finds_pc, (off_t pc) );
+_PROTOTYPE( int finds_data, (off_t off, int data_seg) );
+
+/* trace.c */
+_PROTOTYPE( long mdbtrace, (int req, int pid, long addr, long data) );
+_PROTOTYPE( u32_t peek_dword, (off_t addr));
+
+#if SYSCALLS_SUPPORT
+
+/* syscalls.c */
+_PROTOTYPE( void start_syscall, (long addr) );
+_PROTOTYPE( void do_syscall, (long addr) );
+
+/* decode.c */
+_PROTOTYPE( void decode_message, (unsigned addr) );
+_PROTOTYPE( void decode_result, (void) );
+
+/* ioctl.c */
+_PROTOTYPE( void decode_ioctl, (int sr, message *m) );
+
+#endif /* SYSCALLS_SUPPORT */
--- /dev/null
+.TH PTRACE 2
+.SH NAME
+ptrace \- ptrace system call.
+.SH SYNOPSIS
+.ft B
+.nf
+.sp
+#include <sys/ptrace.h>
+
+long ptrace( int req, pid_t pid, long addr, long data)
+
+.fi
+.ft P
+.SH DESCRIPTION
+.sp
+Ptrace(2) is called with following arguments:
+.sp
+.br
+req
+request
+.br
+pid
+process id
+.br
+addr
+address
+.br
+data
+data
+.br
+.SH REQUESTS
+.sp
+.I
+T_STOP
+stop the process.
+.br
+.I
+T_OK
+enable tracing by parent for this process.
+.br
+.I
+T_GETINS
+return value from instruction space
+.br
+.I
+T_GETDATA
+return value from data space.
+.br
+.I
+T_GETUSER
+return value from process table. See proc.h in kernel.
+.br
+.I
+T_SETINS
+set value from instruction space.
+.br
+.I
+T_SETDATA
+set value from data space.
+.br
+.I
+T_SETUSER
+set value in process table.
+.br
+.I
+T_RESUME
+resume execution.
+.br
+.I
+T_EXIT
+exit. Turn off tracing.
+.br
+.I
+T_STEP
+set trace bit to enable single step.
+.SH "SEE ALSO"
+.sp
+mdb(1)
+.SH DIAGNOSTICS
+.sp
+errno is set by ptrace().
+.SH FILES
+.sp
+/usr/src/kernel/proc.h for process table info.
+
+
+
--- /dev/null
+r 10
+y
+__sendrec b
+B
+c
+x 2
+t
+q
+
--- /dev/null
+/*
+ * sym.c for mdb
+ */
+
+#include "mdb.h"
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <a.out.h>
+#include "proto.h"
+
+#if GNU_SUPPORT
+#define ZMAGIC 0413
+#define NMAGIC 0410
+#define QMAGIC 0314
+#endif
+
+struct symtab_s
+{
+ struct nlist *start;
+ struct nlist *end;
+ int text;
+ int data;
+ unsigned nsym;
+};
+
+PRIVATE struct symtab_s symtab;
+PRIVATE int type_of_exec;
+
+FORWARD _PROTOTYPE( int check_exec, (struct exec *hdr) );
+FORWARD _PROTOTYPE( void sortsyms , (struct nlist *array , struct nlist *top ));
+FORWARD _PROTOTYPE( int symeq , (char *t , struct nlist *sp ));
+FORWARD _PROTOTYPE( int symprefix , (char *t , struct nlist *sp ));
+FORWARD _PROTOTYPE( struct nlist *findsname, (char *name, int is_text, int allflag) );
+FORWARD _PROTOTYPE( void outsym, (struct nlist *sp, off_t off) );
+FORWARD _PROTOTYPE( struct nlist *findsval, (off_t value, int where) );
+
+PUBLIC void syminit( filename )
+char *filename;
+{
+ int fd;
+ struct exec header;
+ register struct symtab_s *tp;
+
+ tp = &symtab;
+ if ( (fd = open( filename, O_RDONLY)) < 0) {
+ fprintf(stderr, "Couldn't open %s.\n", filename);
+ perror(filename);
+ exit(1);
+ }
+
+ if( read( fd, (char *) &header, sizeof header ) != sizeof header )
+ {
+ fprintf(stderr, "Couldn't read %d bytes from %s.\n", sizeof(header), filename);
+ close( fd );
+ exit(1);
+ }
+ type_of_exec = check_exec(&header);
+
+#if EXTRA_SYMBOLS
+ if ( type_of_exec == GNU_SYMBOLS) {
+ close(fd);
+ gnu_init(filename);
+ return;
+ }
+#endif
+
+ /* For MINIX EXEC */
+ if ( lseek( fd, A_SYMPOS( header ), 0 ) != A_SYMPOS( header ) )
+ {
+ do_error( "mdb - reading header" );
+ close( fd );
+ exit(1);
+ }
+ if ( (int) header.a_syms < 0 ||
+ (unsigned) header.a_syms != header.a_syms ||
+ (tp->start = (struct nlist *) malloc( (unsigned) header.a_syms ))
+ == (struct nlist *) NULL &&
+ header.a_syms != 0 )
+ {
+ Printf("mdb: no room for symbol table" );
+ close( fd );
+ return;
+ }
+ if ( read( fd, (char *) tp->start, (int) header.a_syms ) < 0 )
+ {
+ do_error( "mdb - reading symbol table" );
+ close( fd );
+ return;
+ }
+ close( fd );
+ tp->nsym = (unsigned) header.a_syms / sizeof (struct nlist);
+ tp->end = tp->start + tp->nsym;
+ tp->text = 0x07;
+ tp->data = 0x0F;
+
+ /* sort on value only, name search not used much and storage a problem */
+ Printf("Sorting %d MINIX symbols ....", tp->nsym );
+ sortsyms( tp->start, tp->end );
+ Printf("\n");
+}
+
+/* Check exec file
+ * return type of exec
+ * or exit
+ */
+PRIVATE int check_exec(hdr)
+struct exec *hdr;
+{
+long magic;
+
+ /* Check MAGIC number */
+ if (hdr->a_magic[0] != A_MAGIC0 || hdr->a_magic[1] != A_MAGIC1) {
+#if GNU_SUPPORT
+ memcpy(&magic, hdr, sizeof(long));
+ /* Clear bits */
+ magic &= 0xFFFF;
+
+ if ( magic == ZMAGIC || magic == QMAGIC ) {
+ is_separate = FALSE;
+ return GNU_SYMBOLS;
+ }
+ if ( magic == NMAGIC ) {
+ is_separate = TRUE;
+ return GNU_SYMBOLS;
+ }
+#endif
+ Printf("mdb: invalid magic number in exec header - %02x %02x\n",
+ hdr->a_magic[0],
+ hdr->a_magic[1]);
+ exit(1);
+ }
+
+ /* Check CPU */
+#if (CHIP == INTEL)
+#if (_WORD_SIZE == 4)
+ if (hdr->a_cpu != A_I80386)
+#else
+ if (hdr->a_cpu != A_I8086)
+#endif
+#endif
+#if (CHIP == M68000)
+ if (hdr->a_cpu != A_M68K)
+#endif
+ {
+ Printf("mdb: invalid cpu in exec header - %04x\n",
+ hdr->a_cpu);
+ exit(1);
+ }
+
+ is_separate = FALSE;
+#ifdef MINIX_PC
+ if (hdr->a_flags & A_SEP)
+ is_separate = TRUE;
+#endif
+/*
+ * A_EXEC is not being set by current cc
+ * It was set in Minix 1.5.0
+ */
+#if 0
+ /* Check flags - separate I & D or not */
+ if (hdr->a_flags & A_EXEC)
+ is_separate = FALSE;
+ else {
+ Printf("mdb: object file not exec %04x\n",
+ hdr->a_flags);
+ exit(1);
+ }
+#endif
+ return MINIX_SYMBOLS;
+}
+
+
+PUBLIC long symbolvalue( name, is_text )
+char *name;
+int is_text;
+{
+register struct nlist *sp;
+
+#if EXTRA_SYMBOLS
+ if ( type_of_exec == GNU_SYMBOLS )
+ return gnu_symbolvalue( name, is_text );
+#endif
+
+ /* For MINIX EXEC */
+ sp = findsname(name, is_text, 0);
+ if (sp != NULL)
+ return sp->n_value;
+ else
+ return 0L;
+}
+
+PRIVATE struct nlist *findsname( name, is_text, allflag )
+char *name;
+int is_text;
+int allflag;
+{
+ char *s;
+ unsigned char sclass;
+ int schar;
+ char *send;
+ register struct nlist *sp;
+ register struct symtab_s *tp;
+
+ tp = &symtab;
+ if ( allflag )
+ {
+ /* find and print all matching symbols */
+ for ( sp = tp->start; sp < tp->end; ++sp )
+ {
+ if ( symprefix( name, sp ) )
+ {
+ sp = sp;
+ for ( s = sp->n_name, send = s + sizeof sp->n_name;
+ *s != 0 && s < send; ++s )
+ outbyte( *s );
+ for ( ; s <= send; ++s )
+ outspace();
+ switch( sp->n_sclass & N_SECT )
+ {
+ case N_ABS: schar = 'a'; break;
+ case N_TEXT: schar = 't'; break;
+ case N_DATA: schar = 'd'; break;
+ case N_BSS: schar = 'b'; break;
+ default: schar = '?'; break;
+ }
+ if ( (sp->n_sclass & N_CLASS) == C_EXT && schar != '?' )
+ schar += 'A' - 'a';
+ outbyte( schar );
+ outspace();
+#if (_WORD_SIZE == 2)
+ outh16( (u16_t) sp->n_value );
+#else
+ outh32( sp->n_value );
+#endif
+ outbyte('\n');
+ }
+ }
+ }
+ else
+ {
+ /* find symbol by dumb linear search */
+ for ( sp = tp->start; sp < tp->end; ++sp )
+ {
+ sclass = sp->n_sclass & N_SECT;
+ if ( (is_text && sclass == N_TEXT ||
+ !is_text && (sclass == N_DATA || sclass == N_BSS)) &&
+ symeq( name, sp ) )
+ return sp;
+ }
+ }
+ return NULL;
+}
+
+PRIVATE struct nlist *findsval( value, where )
+off_t value;
+int where;
+{
+ int left;
+ int middle;
+ int right;
+ unsigned char sclass;
+ register struct nlist *sp;
+ register struct symtab_s *tp;
+
+ tp = &symtab;
+
+ /* find last symbol with value <= desired one by binary search */
+ for ( left = 0, right = tp->nsym - 1; left <= right; )
+ {
+ middle = (left + right) / 2;
+ sp = tp->start + middle;
+ if ( value < sp->n_value )
+ right = middle - 1;
+ else
+ left = middle + 1;
+ }
+ if ( right >= 0 )
+ /* otherwise tp->start + right may wrap around to > tp->start !! */
+ for ( sp = tp->start + right; sp >= tp->start; --sp )
+ {
+ if ( (sp->n_sclass & N_CLASS) != C_EXT ) continue;
+ sclass = sp->n_sclass & N_SECT;
+ if ( (where == CSEG && sclass == N_TEXT ||
+ where != CSEG && (sclass == N_DATA || sclass == N_BSS)) )
+ return sp;
+ }
+ return NULL;
+}
+
+
+PUBLIC void printhex(v)
+off_t v;
+{
+ if ( v >= 65536L )
+ outh32( v );
+ else if ( v >= 256 )
+ outh16( (u16_t) v );
+ else
+ outh8( (u8_t) v );
+}
+
+
+PRIVATE void outsym( sp, off )
+struct nlist *sp;
+off_t off;
+{
+ register char *s;
+ char *send;
+
+ for ( s = sp->n_name, send = s + sizeof sp->n_name; *s != 0 && s < send; ++s )
+ outbyte( *s );
+ if ( (off -= sp->n_value) != 0 )
+ {
+ outbyte( '+' );
+ printhex(off);
+ }
+}
+
+/* shell sort symbols on value */
+
+PRIVATE void sortsyms( array, top )
+struct nlist *array;
+struct nlist *top;
+{
+ int gap;
+ int i;
+ int j;
+ register struct nlist *left;
+ register struct nlist *right;
+ struct nlist swaptemp;
+ int size;
+
+ size = top - array;
+ /* choose gaps according to Knuth V3 p95 */
+ for ( gap = 1, i = 4; (j = 3 * i + 1) < size; gap = i, i = j )
+ ;
+ do
+ {
+ for ( j = gap; j < size; ++j )
+ for ( i = j - gap; i >= 0; i -= gap )
+ {
+ left = array + i;
+ right = array + (i + gap);
+ if ( (off_t) left->n_value <=
+ right->n_value )
+ break;
+ swaptemp = *left;
+ *left = *right;
+ *right = swaptemp;
+ }
+ }
+ while ( (gap /= 3) != 0 );
+}
+
+PUBLIC void symbolic( value, separator )
+off_t value;
+int separator;
+{
+ register struct nlist *sp;
+ long off;
+
+#if EXTRA_SYMBOLS
+ if ( type_of_exec == GNU_SYMBOLS ) {
+ gnu_symbolic( value, separator );
+ return;
+ }
+#endif
+
+ /* For MINIX EXEC */
+
+ if (value < st_addr || value > end_addr) {
+ outstr("0x");
+ printhex(value);
+ outbyte(separator);
+ return;
+ }
+
+ if ( (sp = findsval( value, CSEG )) != NULL )
+ {
+ outsym( sp, value );
+ }
+ else if ( (sp = findsval( value, DSEG )) != NULL )
+ {
+ outsym( sp, value );
+ }
+ else
+ {
+ outstr("_start");
+ off = value - st_addr;
+ if ( off != 0 )
+ {
+ outbyte( '+' );
+ printhex(off);
+ }
+ }
+ outbyte( separator );
+}
+
+
+PRIVATE int symeq( t, sp )
+register char *t;
+struct nlist *sp;
+{
+ return strncmp( t, sp->n_name, sizeof sp->n_name ) == 0;
+}
+
+PRIVATE int symprefix( t, sp )
+register char *t;
+struct nlist *sp;
+{
+ register char *s;
+ char *send;
+
+ for ( ; *t == '_'; ++t )
+ ;
+ for ( s = sp->n_name, send = s + sizeof sp->n_name;
+ s < send && *s == '_'; ++s )
+ ;
+ return strncmp( s, t, (size_t)(send - s) ) == 0;
+}
+
+
+
+/* list all symbols - test for selection criteria */
+
+PUBLIC void listsym(cmd)
+char *cmd;
+{
+ register struct symtab_s *tp;
+ register struct nlist *sp;
+ char *s;
+ char *send;
+ char schar;
+ char tchar;
+
+ /* set selection */
+ cmd = skip(cmd+1);
+ if( *cmd == '\n' || *cmd == ';' )
+ tchar = '*';
+ else
+ tchar = *cmd;
+
+#if EXTRA_SYMBOLS
+ if ( type_of_exec == GNU_SYMBOLS ) {
+ gnu_listsym(tchar);
+ return;
+ }
+#endif
+
+ /* For MINIX EXEC */
+
+ tp = &symtab;
+ for ( sp = tp->start; sp < tp->end; ++sp )
+ {
+ switch( sp->n_sclass & N_SECT )
+ {
+ case N_ABS: schar = 'a'; break;
+ case N_TEXT: schar = 't'; break;
+ case N_DATA: schar = 'd'; break;
+ case N_BSS: schar = 'b'; break;
+ default: schar = '?'; break;
+ }
+
+ if ( (sp->n_sclass & N_CLASS) == C_EXT && schar != '?' )
+ schar += 'A' - 'a';
+
+ /* check for selection */
+ if ( tchar != '*' && schar != tchar)
+ continue;
+
+ /* print symbol type and value */
+ for ( s = sp->n_name, send = s + sizeof sp->n_name;
+ *s != 0 && s < send; ++s ) outbyte( *s );
+ for ( ; s <= send; ++s ) outspace();
+ outbyte( schar );
+ outspace();
+#if (_WORD_SIZE == 2)
+ outh16( (u16_t) sp->n_value );
+#else
+ outh32( sp->n_value );
+#endif
+ outbyte('\n');
+ }
+}
+
+
+PUBLIC int text_symbol(value)
+off_t value;
+{
+struct nlist *sp;
+
+#if EXTRA_SYMBOLS
+ if ( type_of_exec == GNU_SYMBOLS )
+ return gnu_text_symbol(value);
+#endif
+
+ if ((sp = findsval(value, CSEG)) != NULL && sp->n_value == value)
+ {
+ outsym(sp, value);
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+PUBLIC int finds_data(off,data_seg)
+off_t off;
+int data_seg;
+{
+struct nlist *sp;
+
+#if EXTRA_SYMBOLS
+ if ( type_of_exec == GNU_SYMBOLS )
+ return gnu_finds_data(off,data_seg);
+#endif
+
+ if ((sp = findsval(off, data_seg)) != NULL)
+ {
+ outsym(sp, off);
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+PUBLIC int finds_pc(pc)
+off_t pc;
+{
+struct nlist *sp;
+
+#if EXTRA_SYMBOLS
+ if ( type_of_exec == GNU_SYMBOLS )
+ return gnu_finds_pc(pc);
+#endif
+
+ if ((sp = findsval(pc, CSEG)) != NULL)
+ {
+ outsym(sp, pc);
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
--- /dev/null
+/*
+ * syscall.c for mdb
+ */
+#include "mdb.h"
+#ifdef SYSCALLS_SUPPORT
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/ptrace.h>
+#include "proto.h"
+
+#define SYSCALL_NAME "__sendrec"
+#ifdef __i386
+#define SYSCALL_OFFSET 0xF
+#define SYSCALL_OLD 0x21CD
+#else
+#define SYSCALL_OFFSET 0xE
+#define SYSCALL_OLD 0x20CD
+#endif
+
+PRIVATE long intaddr;
+
+PUBLIC void start_syscall(addr)
+long addr;
+{
+long old;
+
+ syscalls = FALSE;
+
+ if ( addr == 0 ) {
+ intaddr = symbolvalue( SYSCALL_NAME, TRUE );
+ if ( intaddr == 0 )
+ return;
+ intaddr += SYSCALL_OFFSET;
+ }
+ else {
+ intaddr = addr;
+ Printf("Using %lx as syscall address\n",addr);
+ }
+
+ old = breakpt(intaddr,"\n");
+
+ /* Check instruction */
+ if ( (old & 0xFFFF) == SYSCALL_OLD)
+ syscalls = TRUE;
+
+}
+
+PUBLIC void do_syscall(addr)
+long addr;
+{
+ unsigned reg_ax,reg_bx;
+
+ if ( addr != intaddr ) return;
+
+ Printf("syscall to ");
+
+ reg_ax = get_reg(curpid,reg_addr("AX"));
+
+ switch (reg_ax) {
+ case 0: Printf(" MM ");
+ break;
+ case 1: Printf(" FS ");
+ break;
+ case 2: Printf(" INET ");
+ break;
+ default: Printf("Invalid dest = %d", reg_ax);
+ exit(0);
+ }
+
+
+ reg_bx = get_reg(curpid,reg_addr("BX"));
+ decode_message(reg_bx);
+
+ /* Single step */
+ tstart(T_STEP, 0, 0, 1);
+
+ /* Check return code */
+ reg_ax = get_reg(curpid,reg_addr("AX"));
+ if ( reg_ax != 0 )
+ Printf("syscall failed AX=%d\n",reg_ax);
+ else
+ decode_result();
+}
+
+#endif /* SYSCALLS_SUPPORT */
--- /dev/null
+/*
+ * trace.c for mdb
+ */
+
+#include "mdb.h"
+#include <stdio.h>
+#include <sys/ptrace.h>
+#include "proto.h"
+
+/* mdbtrace()
+ * Call ptrace and check for error if debugging running process
+ * Otherwise read 'core' file
+ */
+PUBLIC long mdbtrace(req, pid, addr, data)
+int req, pid;
+long addr, data;
+{
+ long val;
+ int i;
+ int segment;
+
+#ifdef DEBUG
+ if (debug) Printf("ptrace: req=%d pid=%d addr=%lx data=%lx\n",
+ req, pid, addr, data);
+#endif
+
+ if (corepid < 0)
+ {
+ errno = 0;
+ /* Call normal ptrace and check for error */
+ val = ptrace(req, pid, addr, data);
+ if (errno != 0) {
+ do_error("mdb ptrace error ");
+ mdb_error("\n");
+ }
+#ifdef DEBUG
+ if (debug) Printf("ptrace: val=>%lx\n", val);
+#endif
+ return val;
+ }
+ else
+ return read_core(req, addr, data);
+}
+
+/* Used by disassembler */
+PUBLIC u32_t peek_dword(addr)
+off_t addr;
+{
+ return mdbtrace(T_GETINS, curpid, addr, 0L);
+}
+