]> Zhao Yanbai Git Server - minix.git/commitdiff
import of mdb (minix debugger), some ptrace and signals unbreaking
authorBen Gras <ben@minix3.org>
Thu, 4 Aug 2005 08:44:16 +0000 (08:44 +0000)
committerBen Gras <ben@minix3.org>
Thu, 4 Aug 2005 08:44:16 +0000 (08:44 +0000)
seem to have made it work (runtime debugging and core reading).

25 files changed:
commands/Makefile
commands/mdb/Dist [new file with mode: 0644]
commands/mdb/MDB.TXT [new file with mode: 0644]
commands/mdb/Makefile [new file with mode: 0644]
commands/mdb/README [new file with mode: 0644]
commands/mdb/a.out.h [new file with mode: 0644]
commands/mdb/core.c [new file with mode: 0644]
commands/mdb/decode.c [new file with mode: 0644]
commands/mdb/gnu_load.c [new file with mode: 0644]
commands/mdb/gnu_sym.c [new file with mode: 0644]
commands/mdb/io.c [new file with mode: 0644]
commands/mdb/ioctl.c [new file with mode: 0644]
commands/mdb/kernel.c [new file with mode: 0644]
commands/mdb/mdb.1 [new file with mode: 0644]
commands/mdb/mdb.c [new file with mode: 0644]
commands/mdb/mdb.h [new file with mode: 0644]
commands/mdb/mdbdis86.c [new file with mode: 0644]
commands/mdb/mdbexp.c [new file with mode: 0644]
commands/mdb/misc.c [new file with mode: 0644]
commands/mdb/proto.h [new file with mode: 0644]
commands/mdb/ptrace.2 [new file with mode: 0644]
commands/mdb/sample [new file with mode: 0644]
commands/mdb/sym.c [new file with mode: 0644]
commands/mdb/syscalls.c [new file with mode: 0644]
commands/mdb/trace.c [new file with mode: 0644]

index 43b7d6c85aa56883cb47b117ff455e285fc55423..8390508b78b682df11059b6376741c2214f800df 100755 (executable)
@@ -46,6 +46,7 @@ all install clean::
        cd kermit && $(MAKE) $@
        cd m4 && $(MAKE) $@
        cd make && $(MAKE) $@
+       cd mdb && $(MAKE) $@
        cd mined && $(MAKE) $@
        cd patch && $(MAKE) $@
        cd ps && $(MAKE) $@
diff --git a/commands/mdb/Dist b/commands/mdb/Dist
new file mode 100644 (file)
index 0000000..2767dea
--- /dev/null
@@ -0,0 +1,38 @@
+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
+
diff --git a/commands/mdb/MDB.TXT b/commands/mdb/MDB.TXT
new file mode 100644 (file)
index 0000000..e4b27bd
--- /dev/null
@@ -0,0 +1,25 @@
+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
+
diff --git a/commands/mdb/Makefile b/commands/mdb/Makefile
new file mode 100644 (file)
index 0000000..7ab449a
--- /dev/null
@@ -0,0 +1,130 @@
+#
+# 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
+
diff --git a/commands/mdb/README b/commands/mdb/README
new file mode 100644 (file)
index 0000000..21600f6
--- /dev/null
@@ -0,0 +1,32 @@
+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
+
+
diff --git a/commands/mdb/a.out.h b/commands/mdb/a.out.h
new file mode 100644 (file)
index 0000000..521dc70
--- /dev/null
@@ -0,0 +1,297 @@
+/* 
+ * 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__ */
diff --git a/commands/mdb/core.c b/commands/mdb/core.c
new file mode 100644 (file)
index 0000000..4eda5af
--- /dev/null
@@ -0,0 +1,394 @@
+/* 
+ * 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");
+       }
+}
+
diff --git a/commands/mdb/decode.c b/commands/mdb/decode.c
new file mode 100644 (file)
index 0000000..7d37373
--- /dev/null
@@ -0,0 +1,360 @@
+/* 
+ * 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 */
diff --git a/commands/mdb/gnu_load.c b/commands/mdb/gnu_load.c
new file mode 100644 (file)
index 0000000..bc3e2ab
--- /dev/null
@@ -0,0 +1,76 @@
+/* 
+ * 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;
+}
diff --git a/commands/mdb/gnu_sym.c b/commands/mdb/gnu_sym.c
new file mode 100644 (file)
index 0000000..0dd2545
--- /dev/null
@@ -0,0 +1,365 @@
+/* 
+ * 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 */
diff --git a/commands/mdb/io.c b/commands/mdb/io.c
new file mode 100644 (file)
index 0000000..f99b128
--- /dev/null
@@ -0,0 +1,303 @@
+/* 
+ * 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;
+}
+
diff --git a/commands/mdb/ioctl.c b/commands/mdb/ioctl.c
new file mode 100644 (file)
index 0000000..4cc1d88
--- /dev/null
@@ -0,0 +1,146 @@
+/* 
+ * 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 */
diff --git a/commands/mdb/kernel.c b/commands/mdb/kernel.c
new file mode 100644 (file)
index 0000000..119a8e2
--- /dev/null
@@ -0,0 +1,249 @@
+/*
+ * 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
diff --git a/commands/mdb/mdb.1 b/commands/mdb/mdb.1
new file mode 100644 (file)
index 0000000..e7be50e
--- /dev/null
@@ -0,0 +1,154 @@
+.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
diff --git a/commands/mdb/mdb.c b/commands/mdb/mdb.c
new file mode 100644 (file)
index 0000000..e6f99c4
--- /dev/null
@@ -0,0 +1,1028 @@
+/*
+ * 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);
+}
diff --git a/commands/mdb/mdb.h b/commands/mdb/mdb.h
new file mode 100644 (file)
index 0000000..62cff88
--- /dev/null
@@ -0,0 +1,182 @@
+/*
+ * 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
+
diff --git a/commands/mdb/mdbdis86.c b/commands/mdb/mdbdis86.c
new file mode 100644 (file)
index 0000000..306a2c0
--- /dev/null
@@ -0,0 +1,1564 @@
+/* 
+ * 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);
+}
diff --git a/commands/mdb/mdbexp.c b/commands/mdb/mdbexp.c
new file mode 100644 (file)
index 0000000..91bfaaf
--- /dev/null
@@ -0,0 +1,157 @@
+/*
+ * 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;
+}
+
diff --git a/commands/mdb/misc.c b/commands/mdb/misc.c
new file mode 100644 (file)
index 0000000..f1c7324
--- /dev/null
@@ -0,0 +1,289 @@
+/* 
+ *  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;
+  }
+}
+
diff --git a/commands/mdb/proto.h b/commands/mdb/proto.h
new file mode 100644 (file)
index 0000000..0017522
--- /dev/null
@@ -0,0 +1,105 @@
+/* 
+ * 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 */
diff --git a/commands/mdb/ptrace.2 b/commands/mdb/ptrace.2
new file mode 100644 (file)
index 0000000..4c3e1b6
--- /dev/null
@@ -0,0 +1,87 @@
+.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. 
+
+
+
diff --git a/commands/mdb/sample b/commands/mdb/sample
new file mode 100644 (file)
index 0000000..b04edf9
--- /dev/null
@@ -0,0 +1,9 @@
+r 10 
+y
+__sendrec b 
+B
+c
+x 2
+t
+q
+
diff --git a/commands/mdb/sym.c b/commands/mdb/sym.c
new file mode 100644 (file)
index 0000000..32a7390
--- /dev/null
@@ -0,0 +1,546 @@
+/* 
+ * 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;
+}
diff --git a/commands/mdb/syscalls.c b/commands/mdb/syscalls.c
new file mode 100644 (file)
index 0000000..89862c1
--- /dev/null
@@ -0,0 +1,85 @@
+/* 
+ * 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 */
diff --git a/commands/mdb/trace.c b/commands/mdb/trace.c
new file mode 100644 (file)
index 0000000..66aae92
--- /dev/null
@@ -0,0 +1,51 @@
+/* 
+ * 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);
+}
+