import of mdb (minix debugger), some ptrace and signals unbreaking

seem to have made it work (runtime debugging and core reading).
This commit is contained in:
Ben Gras 2005-08-04 08:44:16 +00:00
parent 693c7abe2a
commit 5e3b213f05
25 changed files with 6673 additions and 0 deletions

View file

@ -46,6 +46,7 @@ all install clean::
cd kermit && $(MAKE) $@ cd kermit && $(MAKE) $@
cd m4 && $(MAKE) $@ cd m4 && $(MAKE) $@
cd make && $(MAKE) $@ cd make && $(MAKE) $@
cd mdb && $(MAKE) $@
cd mined && $(MAKE) $@ cd mined && $(MAKE) $@
cd patch && $(MAKE) $@ cd patch && $(MAKE) $@
cd ps && $(MAKE) $@ cd ps && $(MAKE) $@

38
commands/mdb/Dist Normal file
View file

@ -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

25
commands/mdb/MDB.TXT Normal file
View file

@ -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

130
commands/mdb/Makefile Normal file
View file

@ -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

32
commands/mdb/README Normal file
View file

@ -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

297
commands/mdb/a.out.h Normal file
View file

@ -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
#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. */
#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__ */

394
commands/mdb/core.c Normal file
View file

@ -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");
}
}

360
commands/mdb/decode.c Normal file
View file

@ -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 */

76
commands/mdb/gnu_load.c Normal file
View file

@ -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;
}

365
commands/mdb/gnu_sym.c Normal file
View file

@ -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 */

303
commands/mdb/io.c Normal file
View file

@ -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;
}

146
commands/mdb/ioctl.c Normal file
View file

@ -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 */

249
commands/mdb/kernel.c Normal file
View file

@ -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

154
commands/mdb/mdb.1 Normal file
View file

@ -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

1028
commands/mdb/mdb.c Normal file

File diff suppressed because it is too large Load diff

182
commands/mdb/mdb.h Normal file
View file

@ -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

1564
commands/mdb/mdbdis86.c Normal file

File diff suppressed because it is too large Load diff

157
commands/mdb/mdbexp.c Normal file
View file

@ -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;
}

289
commands/mdb/misc.c Normal file
View file

@ -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;
}
}

105
commands/mdb/proto.h Normal file
View file

@ -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 */

87
commands/mdb/ptrace.2 Normal file
View file

@ -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.

9
commands/mdb/sample Normal file
View file

@ -0,0 +1,9 @@
r 10
y
__sendrec b
B
c
x 2
t
q

546
commands/mdb/sym.c Normal file
View file

@ -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;
}

85
commands/mdb/syscalls.c Normal file
View file

@ -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 */

51
commands/mdb/trace.c Normal file
View file

@ -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);
}