Remove unmaintained "ack" size nm mdb
Change-Id: Iba84fd51f16577e6123148d4505c7687ea1c071d
This commit is contained in:
parent
0aadbb872f
commit
14f89a8efe
30 changed files with 8 additions and 6437 deletions
|
@ -16,13 +16,13 @@ SUBDIR= add_route arp ash at backup basename btrace \
|
||||||
less loadkeys loadramdisk logger look lp \
|
less loadkeys loadramdisk logger look lp \
|
||||||
lpd lspci mail MAKEDEV \
|
lpd lspci mail MAKEDEV \
|
||||||
mesg mined mkfifo \
|
mesg mined mkfifo \
|
||||||
mount mt netconf nice acknm nohup \
|
mount mt netconf nice nohup \
|
||||||
nonamed od paste patch \
|
nonamed od paste patch \
|
||||||
ping postinstall poweroff pr prep printroot \
|
ping postinstall poweroff pr prep printroot \
|
||||||
profile progressbar pr_routes ps pwdauth \
|
profile progressbar pr_routes ps pwdauth \
|
||||||
ramdisk rarpd rawspeed rcp readclock \
|
ramdisk rarpd rawspeed rcp readclock \
|
||||||
reboot remsync rev rget rlogin \
|
reboot remsync rev rget rlogin \
|
||||||
rotate rsh rshd service setup shar acksize \
|
rotate rsh rshd service setup shar \
|
||||||
sleep slip spell split sprofalyze sprofdiff srccrc \
|
sleep slip spell split sprofalyze sprofdiff srccrc \
|
||||||
stty svclog svrctl swifi synctree sysenv \
|
stty svclog svrctl swifi synctree sysenv \
|
||||||
syslogd tail tcpd tcpdp tcpstat tee telnet \
|
syslogd tail tcpd tcpdp tcpstat tee telnet \
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
PROG= acknm
|
|
||||||
MAN=
|
|
||||||
|
|
||||||
.include <bsd.prog.mk>
|
|
|
@ -1,226 +0,0 @@
|
||||||
/* nm - print name list. Author: Dick van Veen */
|
|
||||||
|
|
||||||
/* Dick van Veen: veench@cs.vu.nl */
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <a.out.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
/* Read the name list in memory, sort it, and print it. */
|
|
||||||
|
|
||||||
/* Nm [-gnopru] [file] ...
|
|
||||||
*
|
|
||||||
* flags:
|
|
||||||
* -d address in decimal
|
|
||||||
* -g print only external symbols.
|
|
||||||
* -n sort numerically rather than alphabetically.
|
|
||||||
* -o prepend file name to each line rather than only once.
|
|
||||||
* -p don't sort, pint n symbol-table order.
|
|
||||||
* -r sort in reverse order.
|
|
||||||
* -u print only undefined symbols.
|
|
||||||
*
|
|
||||||
* - when no file name is present, a.out is assumed.
|
|
||||||
*
|
|
||||||
* NOTE: no archives are supported because assembly files don't
|
|
||||||
* have symbol tables.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define A_OUT "a.out"
|
|
||||||
|
|
||||||
int d_flag;
|
|
||||||
int g_flag;
|
|
||||||
int n_flag;
|
|
||||||
int o_flag;
|
|
||||||
int p_flag;
|
|
||||||
int r_flag;
|
|
||||||
int u_flag;
|
|
||||||
|
|
||||||
char io_buf[BUFSIZ]; /* io buffer */
|
|
||||||
struct exec header; /* header of a.out file */
|
|
||||||
int stbl_elems; /* #elements in symbol table */
|
|
||||||
|
|
||||||
int main(int argc, char **argv);
|
|
||||||
int nm_sort(const void *tmp_stbl1, const void *tmp_stbl2);
|
|
||||||
void nm(char *file);
|
|
||||||
int read_header(int fd);
|
|
||||||
void nm_print(char *file, struct nlist *stbl);
|
|
||||||
|
|
||||||
int main(argc, argv)
|
|
||||||
int argc;
|
|
||||||
char **argv;
|
|
||||||
{
|
|
||||||
argv++;
|
|
||||||
while (*argv != 0 && **argv == '-') {
|
|
||||||
*argv += 1;
|
|
||||||
while (**argv != '\0') {
|
|
||||||
switch (**argv) {
|
|
||||||
case 'd': d_flag = 1; break;
|
|
||||||
case 'g': g_flag = 1; break;
|
|
||||||
case 'n': n_flag = 1; break;
|
|
||||||
case 'o': o_flag = 1; break;
|
|
||||||
case 'p': p_flag = 1; break;
|
|
||||||
case 'r': r_flag = 1; break;
|
|
||||||
case 'u': u_flag = 1; break;
|
|
||||||
default:
|
|
||||||
fprintf(stderr, "illegal flag: -%c\n", **argv);
|
|
||||||
exit(-1);
|
|
||||||
}
|
|
||||||
*argv += 1;
|
|
||||||
}
|
|
||||||
argv++;
|
|
||||||
}
|
|
||||||
setbuf(stdin, io_buf);
|
|
||||||
if (*argv == 0)
|
|
||||||
nm(A_OUT);
|
|
||||||
else
|
|
||||||
while (*argv != 0) {
|
|
||||||
nm(*argv);
|
|
||||||
argv++;
|
|
||||||
}
|
|
||||||
return(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
int nm_sort(tmp_stbl1, tmp_stbl2)
|
|
||||||
const void *tmp_stbl1, *tmp_stbl2;
|
|
||||||
{
|
|
||||||
|
|
||||||
struct nlist *stbl1 = (struct nlist *)tmp_stbl1;
|
|
||||||
struct nlist *stbl2 = (struct nlist *)tmp_stbl2;
|
|
||||||
int cmp;
|
|
||||||
|
|
||||||
if (n_flag) { /* sort numerically */
|
|
||||||
if ((stbl1->n_sclass & N_SECT) <
|
|
||||||
(stbl2->n_sclass & N_SECT))
|
|
||||||
cmp = -1;
|
|
||||||
else if ((stbl1->n_sclass & N_SECT) >
|
|
||||||
(stbl2->n_sclass & N_SECT))
|
|
||||||
cmp = 1;
|
|
||||||
else if (stbl1->n_value < stbl2->n_value)
|
|
||||||
cmp = -1;
|
|
||||||
else if (stbl1->n_value > stbl2->n_value)
|
|
||||||
cmp = 1;
|
|
||||||
else
|
|
||||||
cmp = strncmp(stbl1->n_name, stbl2->n_name, (size_t)8);
|
|
||||||
} else {
|
|
||||||
cmp = strncmp(stbl1->n_name, stbl2->n_name, (size_t)8);
|
|
||||||
if (cmp == 0) {
|
|
||||||
if (stbl1->n_value < stbl2->n_value)
|
|
||||||
cmp = -1;
|
|
||||||
else if (stbl1->n_value > stbl2->n_value)
|
|
||||||
cmp = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (r_flag) cmp = -cmp; /* reverse sort */
|
|
||||||
return(cmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
void nm(file)
|
|
||||||
char *file;
|
|
||||||
{
|
|
||||||
struct nlist *stbl;
|
|
||||||
int fd;
|
|
||||||
|
|
||||||
fd = open(file, O_RDONLY);
|
|
||||||
if (fd == -1) {
|
|
||||||
fprintf(stderr, "can't open %s\n", file);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (read_header(fd)) {
|
|
||||||
fprintf(stderr, "%s: no executable file\n", file);
|
|
||||||
close(fd);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (header.a_syms == 0) {
|
|
||||||
close(fd);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if ((size_t) header.a_syms != header.a_syms) {
|
|
||||||
fprintf(stderr, "%s: symbol table too large to allocate\n", file);
|
|
||||||
close(fd);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if ((int) header.a_syms != header.a_syms) {
|
|
||||||
/* This is necessary because we are too lazy to iterate the read. */
|
|
||||||
fprintf(stderr, "%s: symbol table too large to read\n", file);
|
|
||||||
close(fd);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
stbl = (struct nlist *) malloc((size_t) header.a_syms);
|
|
||||||
if (stbl == NULL) {
|
|
||||||
fprintf(stderr, "%s: can't allocate symbol table\n", file);
|
|
||||||
close(fd);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (read(fd, (char *) stbl, (unsigned) header.a_syms) != header.a_syms) {
|
|
||||||
fprintf(stderr, "%s: can't read symbol table\n", file);
|
|
||||||
free(stbl);
|
|
||||||
close(fd);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
stbl_elems = (int) header.a_syms / sizeof(struct nlist);
|
|
||||||
if (!p_flag) qsort(stbl, (size_t)stbl_elems, sizeof(struct nlist), nm_sort);
|
|
||||||
nm_print(file, stbl);
|
|
||||||
free(stbl);
|
|
||||||
close(fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
int read_header(fd)
|
|
||||||
int fd;
|
|
||||||
{
|
|
||||||
if (read(fd, (char *) &header, sizeof(struct exec)) != sizeof(struct exec))
|
|
||||||
return(1);
|
|
||||||
if (BADMAG(header)) return(1);
|
|
||||||
lseek(fd, A_SYMPOS(header), SEEK_SET);
|
|
||||||
|
|
||||||
return(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void nm_print(file, stbl)
|
|
||||||
char *file;
|
|
||||||
register struct nlist *stbl;
|
|
||||||
{
|
|
||||||
struct nlist *last;
|
|
||||||
char name[9];
|
|
||||||
int n_sclass;
|
|
||||||
char type;
|
|
||||||
|
|
||||||
name[8] = '\0';
|
|
||||||
if (!o_flag) printf("%s:\n", file);
|
|
||||||
for (last = &stbl[stbl_elems]; stbl != last; stbl++) {
|
|
||||||
if (g_flag && (stbl->n_sclass & N_CLASS) != C_EXT) continue;
|
|
||||||
if (u_flag && (stbl->n_sclass & N_SECT) != N_UNDF) continue;
|
|
||||||
|
|
||||||
n_sclass = stbl->n_sclass & N_SECT;
|
|
||||||
if (n_sclass == N_ABS)
|
|
||||||
type = 'a';
|
|
||||||
else if (n_sclass == N_TEXT)
|
|
||||||
type = 't';
|
|
||||||
else if (n_sclass == N_DATA)
|
|
||||||
type = 'd';
|
|
||||||
else if (n_sclass == N_BSS)
|
|
||||||
type = 'b';
|
|
||||||
else
|
|
||||||
type = 'u';
|
|
||||||
if ((stbl->n_sclass & N_CLASS) == C_EXT) type += 'A' - 'a';
|
|
||||||
strncpy(name, stbl->n_name, (size_t)8);
|
|
||||||
if (d_flag) {
|
|
||||||
/* Offsets in decimal. */
|
|
||||||
if (o_flag)
|
|
||||||
printf("%s:%08ld %c %s\n",file,stbl->n_value,type,name);
|
|
||||||
else
|
|
||||||
printf("%08ld %c %s\n", stbl->n_value, type, name);
|
|
||||||
} else {
|
|
||||||
/* Offsets in hex. */
|
|
||||||
if (o_flag)
|
|
||||||
printf("%s:%08lx %c %s\n",file,stbl->n_value,type,name);
|
|
||||||
else
|
|
||||||
printf("%08lx %c %s\n", stbl->n_value, type, name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,4 +0,0 @@
|
||||||
PROG= acksize
|
|
||||||
MAN=
|
|
||||||
|
|
||||||
.include <bsd.prog.mk>
|
|
|
@ -1,64 +0,0 @@
|
||||||
/* size - tell size of an object file Author: Andy Tanenbaum */
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <a.out.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
int heading; /* set when heading printed */
|
|
||||||
int error;
|
|
||||||
|
|
||||||
int main(int argc, char **argv);
|
|
||||||
void size(char *name);
|
|
||||||
|
|
||||||
int main(argc, argv)
|
|
||||||
int argc;
|
|
||||||
char *argv[];
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (argc == 1) {
|
|
||||||
size("a.out");
|
|
||||||
exit(error);
|
|
||||||
}
|
|
||||||
for (i = 1; i < argc; i++) size(argv[i]);
|
|
||||||
return(error);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void size(name)
|
|
||||||
char *name;
|
|
||||||
{
|
|
||||||
int fd, separate;
|
|
||||||
long dynam, allmem;
|
|
||||||
struct exec exec;
|
|
||||||
|
|
||||||
if ((fd = open(name, O_RDONLY)) < 0) {
|
|
||||||
fprintf(stderr, "size: can't open %s\n", name);
|
|
||||||
error = 1;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (read(fd, (char *)&exec, sizeof(struct exec)) != sizeof(struct exec)) {
|
|
||||||
fprintf(stderr, "size: %s: header too short\n", name);
|
|
||||||
error = 1;
|
|
||||||
close(fd);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (BADMAG(exec)) {
|
|
||||||
fprintf(stderr, "size: %s not an object file\n", name);
|
|
||||||
error = 1;
|
|
||||||
close(fd);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
separate = (exec.a_flags & A_SEP ? 1 : 0);
|
|
||||||
dynam = exec.a_total - exec.a_text - exec.a_data - exec.a_bss;
|
|
||||||
if (separate) dynam += exec.a_text;
|
|
||||||
allmem = (separate ? exec.a_total + exec.a_text : exec.a_total);
|
|
||||||
if (heading++ == 0) printf(" text data bss stack memory\n");
|
|
||||||
printf("%7ld %7ld %7ld %8ld %8ld %s\n",
|
|
||||||
exec.a_text, exec.a_data, exec.a_bss, dynam, allmem, name);
|
|
||||||
close(fd);
|
|
||||||
}
|
|
|
@ -1,35 +0,0 @@
|
||||||
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
|
|
||||||
core.c core file functions
|
|
||||||
decode.c Optional for syscalls support
|
|
||||||
gnu_sym.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
|
|
||||||
proto.h Prototypes
|
|
||||||
sample sample command file
|
|
||||||
sym.c Symbolic names read from exec file
|
|
||||||
syscalls.c Optional for syscalls support
|
|
||||||
trace.c ptrace() called here
|
|
||||||
|
|
|
@ -1,25 +0,0 @@
|
||||||
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
|
|
||||||
|
|
|
@ -1,30 +0,0 @@
|
||||||
#
|
|
||||||
# Makefile for mdb
|
|
||||||
#
|
|
||||||
#
|
|
||||||
#
|
|
||||||
# i) For GNU_EXEC Support, uncomment:
|
|
||||||
#
|
|
||||||
FOR_GNU= gnu_sym.c
|
|
||||||
DEF_GNU= -DGNU_SUPPORT
|
|
||||||
#
|
|
||||||
# ii) For tracing of syscalls, uncomment:
|
|
||||||
#
|
|
||||||
#FOR_SYSCALLS= syscalls.c decode.c ioctl.c
|
|
||||||
#DEF_SYSCALLS= -DSYSCALLS_SUPPORT
|
|
||||||
#
|
|
||||||
# iii) For no debugging of mdb, uncomment:
|
|
||||||
#
|
|
||||||
#DEF_DEBUG= -DNDEBUG
|
|
||||||
|
|
||||||
EXTRA_SRCS= ${FOR_GNU} ${FOR_SYSCALLS}
|
|
||||||
EXTRA_DEFS= ${DEF_GNU} ${DEF_SYSCALLS} ${DEF_DEBUG}
|
|
||||||
CPPFLAGS+= -I${NETBSDSRCDIR} -I${NETBSDSRCDIR}/servers \
|
|
||||||
${EXTRA_DEFS}
|
|
||||||
|
|
||||||
PROG= mdb
|
|
||||||
SRCS= mdb.c mdbexp.c kernel.o sym.c trace.c core.c misc.c io.c
|
|
||||||
SRCS+= mdbdis86.c
|
|
||||||
SRCS+= ${EXTRA_SRCS}
|
|
||||||
|
|
||||||
.include <bsd.prog.mk>
|
|
|
@ -1,32 +0,0 @@
|
||||||
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
|
|
||||||
|
|
||||||
|
|
|
@ -1,388 +0,0 @@
|
||||||
/*
|
|
||||||
* core.c for mdb
|
|
||||||
*
|
|
||||||
* reads information from 'core' file
|
|
||||||
* Partly derived from 'adb' by D. Dugger.
|
|
||||||
*/
|
|
||||||
#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 <machine/archtypes.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
|
|
||||||
|
|
||||||
static struct file {
|
|
||||||
int fid;
|
|
||||||
char *name;
|
|
||||||
long cblock;
|
|
||||||
unsigned long tmap[3];
|
|
||||||
unsigned long dmap[3];
|
|
||||||
unsigned 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]
|
|
||||||
|
|
||||||
static long cnt[3]; /* Sizes of segments */
|
|
||||||
static int h_size; /* Size of core header */
|
|
||||||
static 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
|
|
||||||
|
|
||||||
static int kernel_info(int fd );
|
|
||||||
static void setmap(struct file *fp );
|
|
||||||
static void read_info(struct file *fp );
|
|
||||||
static void ill_addr(long d , int segment );
|
|
||||||
static long map_addr(long d , int segment );
|
|
||||||
static unsigned long c_status(void);
|
|
||||||
static long getn(long d, int s);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* set and display mapping for core file
|
|
||||||
*/
|
|
||||||
static 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 = 0;
|
|
||||||
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 */
|
|
||||||
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 */
|
|
||||||
static 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
|
|
||||||
*/
|
|
||||||
static 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 */
|
|
||||||
static 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[] */
|
|
||||||
static 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
|
|
||||||
*/
|
|
||||||
static 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 */
|
|
||||||
static void read_info(fp)
|
|
||||||
struct file *fp;
|
|
||||||
{
|
|
||||||
struct mem_map seg[NR_LOCAL_SEGS];
|
|
||||||
int r;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
lseek(fp->fid, 0L, 0L);
|
|
||||||
|
|
||||||
/* First read memory map of all segments. */
|
|
||||||
if (read(fp->fid, (char *) 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) 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) seg[T].mem_vir << CLICK_SHIFT;
|
|
||||||
et_addr = st_addr + ((long) seg[T].mem_len << CLICK_SHIFT);
|
|
||||||
|
|
||||||
sd_addr = (long) seg[D].mem_vir << CLICK_SHIFT;
|
|
||||||
end_addr = ed_addr =
|
|
||||||
sd_addr + ((long) seg[D].mem_len << CLICK_SHIFT);
|
|
||||||
|
|
||||||
sk_addr = (long) seg[S].mem_vir << CLICK_SHIFT;
|
|
||||||
sk_size = (long) seg[S].mem_len << CLICK_SHIFT;
|
|
||||||
|
|
||||||
setmap(fp);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* initialization for core files
|
|
||||||
* returns PC address from core file
|
|
||||||
*/
|
|
||||||
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 = 0;
|
|
||||||
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.
|
|
||||||
*/
|
|
||||||
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 = 0;
|
|
||||||
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()
|
|
||||||
*/
|
|
||||||
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");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,360 +0,0 @@
|
||||||
/*
|
|
||||||
* 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"
|
|
||||||
|
|
||||||
static void get_message(message *m, unsigned bx);
|
|
||||||
static void get_data(char *s, unsigned bx, int cnt);
|
|
||||||
|
|
||||||
static message sent;
|
|
||||||
static message recv;
|
|
||||||
static unsigned saved_addr;
|
|
||||||
static 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",
|
|
||||||
MINIX_GETPID, NOP, NOP, "MINIX_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"
|
|
||||||
};
|
|
||||||
|
|
||||||
static 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);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
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 */
|
|
|
@ -1,439 +0,0 @@
|
||||||
/*
|
|
||||||
* 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>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <compat/a.out.h>
|
|
||||||
#include "proto.h"
|
|
||||||
|
|
||||||
#define NN_UNDF 0
|
|
||||||
#define NN_ABS 2
|
|
||||||
#define NN_TEXT 4
|
|
||||||
#define NN_DATA 6
|
|
||||||
#define NN_BSS 8
|
|
||||||
#define NN_FN 15
|
|
||||||
#define NN_EXT 1
|
|
||||||
#define NN_TYPE 036
|
|
||||||
|
|
||||||
struct newnlist {
|
|
||||||
union {
|
|
||||||
char *n_name;
|
|
||||||
struct newnlist *n_next;
|
|
||||||
long n_strx;
|
|
||||||
} n_un;
|
|
||||||
unsigned char n_type;
|
|
||||||
char n_other;
|
|
||||||
short n_desc;
|
|
||||||
unsigned long n_value;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct symtab_s
|
|
||||||
{
|
|
||||||
struct newnlist *start;
|
|
||||||
struct newnlist *end;
|
|
||||||
unsigned int nsym;
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct symtab_s symtab;
|
|
||||||
|
|
||||||
static void gnu_sort(struct newnlist *array , struct newnlist *top );
|
|
||||||
static int gnu_symeq(char *t , struct newnlist *sp );
|
|
||||||
static int gnu_symprefix(char *t , struct newnlist *sp );
|
|
||||||
static struct newnlist *gnu_sname(char *name, int is_text, int
|
|
||||||
allflag);
|
|
||||||
static struct newnlist *gnu_sval(off_t value, int where);
|
|
||||||
static void gnu_sym(struct newnlist *sp, off_t off);
|
|
||||||
|
|
||||||
|
|
||||||
void gnu_init( filename )
|
|
||||||
char *filename;
|
|
||||||
{
|
|
||||||
struct exec header;
|
|
||||||
unsigned int string_size;
|
|
||||||
char *names;
|
|
||||||
struct newnlist *p;
|
|
||||||
int fd;
|
|
||||||
register struct symtab_s *tp;
|
|
||||||
|
|
||||||
tp = &symtab;
|
|
||||||
if ( (fd = open( filename, O_RDONLY)) < 0 ||
|
|
||||||
read( fd, (char *) &header, sizeof header ) != sizeof header )
|
|
||||||
{
|
|
||||||
do_error( "gnu_load - reading header" );
|
|
||||||
if ( fd >= 0) close( fd );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( (string_size = lseek( fd, 0, SEEK_END ) ) == -1 )
|
|
||||||
{
|
|
||||||
do_error( "gnu_load - determining file size" );
|
|
||||||
close( fd );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
string_size -= A_SYMPOS( header );
|
|
||||||
|
|
||||||
if ( (int) header.a_syms < 0 ||
|
|
||||||
(unsigned) header.a_syms != header.a_syms ||
|
|
||||||
(tp->start = (struct newnlist *) malloc( string_size ))
|
|
||||||
== (struct newnlist *) NULL &&
|
|
||||||
header.a_syms != 0 )
|
|
||||||
{
|
|
||||||
do_error( "gnu_load - allocating memory" );
|
|
||||||
close( fd );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( lseek( fd, A_SYMPOS( header ), SEEK_SET ) != A_SYMPOS( header ) )
|
|
||||||
{
|
|
||||||
do_error( "gnu_load - reading header" );
|
|
||||||
close( fd );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( read( fd, (char *) tp->start, string_size ) < 0 )
|
|
||||||
{
|
|
||||||
do_error( "gnu_load - reading symbols" );
|
|
||||||
close( fd );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
close( fd );
|
|
||||||
|
|
||||||
tp->nsym = (unsigned int) header.a_syms / sizeof (struct newnlist);
|
|
||||||
tp->end = tp->start + tp->nsym;
|
|
||||||
|
|
||||||
names = (char *) tp->start + header.a_syms;
|
|
||||||
|
|
||||||
for ( p = tp->start; p < tp->end; p++)
|
|
||||||
if(p->n_un.n_strx)
|
|
||||||
p->n_un.n_name = names + p->n_un.n_strx;
|
|
||||||
else
|
|
||||||
p->n_un.n_name = "";
|
|
||||||
|
|
||||||
/* 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");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
long gnu_symbolvalue( name, is_text )
|
|
||||||
char *name;
|
|
||||||
int is_text;
|
|
||||||
{
|
|
||||||
register struct newnlist *sp;
|
|
||||||
sp = gnu_sname(name,is_text,0);
|
|
||||||
if (sp != NULL)
|
|
||||||
return sp->n_value;
|
|
||||||
else
|
|
||||||
return 0L;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static struct newnlist *gnu_sname( name, is_text, allflag )
|
|
||||||
char *name;
|
|
||||||
int is_text;
|
|
||||||
int allflag;
|
|
||||||
{
|
|
||||||
char *s;
|
|
||||||
unsigned char sclass;
|
|
||||||
int schar;
|
|
||||||
char *send;
|
|
||||||
register struct newnlist *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 & NN_TYPE )
|
|
||||||
{
|
|
||||||
case NN_ABS: schar = 'a'; break;
|
|
||||||
case NN_TEXT: schar = 't'; break;
|
|
||||||
case NN_DATA: schar = 'd'; break;
|
|
||||||
case NN_BSS: schar = 'b'; break;
|
|
||||||
default: schar = '?'; break;
|
|
||||||
}
|
|
||||||
if ( (sp->n_type & NN_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 & NN_TYPE;
|
|
||||||
if ( (is_text && sclass == NN_TEXT ||
|
|
||||||
!is_text && (sclass == NN_DATA ||
|
|
||||||
sclass == NN_BSS)) &&
|
|
||||||
gnu_symeq( name, sp ) )
|
|
||||||
return sp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct newnlist *gnu_sval( value, where )
|
|
||||||
off_t value;
|
|
||||||
int where;
|
|
||||||
{
|
|
||||||
int left;
|
|
||||||
int middle;
|
|
||||||
int right;
|
|
||||||
unsigned char sclass;
|
|
||||||
register struct newnlist *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 & NN_EXT) ) continue;
|
|
||||||
sclass = sp->n_type & NN_TYPE;
|
|
||||||
if ( (where == CSEG && sclass == NN_TEXT) ||
|
|
||||||
(where != CSEG &&
|
|
||||||
(sclass == NN_DATA || sclass == NN_BSS)) )
|
|
||||||
return sp;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void gnu_sym( sp, off )
|
|
||||||
struct newnlist *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 */
|
|
||||||
|
|
||||||
static void gnu_sort( array, top )
|
|
||||||
struct newnlist *array;
|
|
||||||
struct newnlist *top;
|
|
||||||
{
|
|
||||||
int gap;
|
|
||||||
int i;
|
|
||||||
int j;
|
|
||||||
register struct newnlist *left;
|
|
||||||
register struct newnlist *right;
|
|
||||||
struct newnlist 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 );
|
|
||||||
}
|
|
||||||
|
|
||||||
void gnu_symbolic( value, separator )
|
|
||||||
off_t value;
|
|
||||||
int separator;
|
|
||||||
{
|
|
||||||
register struct newnlist *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 );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int gnu_symeq( t, sp )
|
|
||||||
register char *t;
|
|
||||||
struct newnlist *sp;
|
|
||||||
{
|
|
||||||
return strncmp( t, sp->n_un.n_name, strlen(t) ) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int gnu_symprefix( t, sp )
|
|
||||||
register char *t;
|
|
||||||
struct newnlist *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 */
|
|
||||||
|
|
||||||
void gnu_listsym( tchar )
|
|
||||||
char tchar;
|
|
||||||
{
|
|
||||||
register struct symtab_s *tp;
|
|
||||||
register struct newnlist *sp;
|
|
||||||
char *s;
|
|
||||||
char *send;
|
|
||||||
char schar;
|
|
||||||
|
|
||||||
outbyte('\n');
|
|
||||||
tp = &symtab;
|
|
||||||
for ( sp = tp->start; sp < tp->end; ++sp )
|
|
||||||
{
|
|
||||||
switch( sp->n_type & NN_TYPE )
|
|
||||||
{
|
|
||||||
case NN_ABS: schar = 'a'; break;
|
|
||||||
case NN_TEXT: schar = 't'; break;
|
|
||||||
case NN_DATA: schar = 'd'; break;
|
|
||||||
case NN_BSS: schar = 'b'; break;
|
|
||||||
default: schar = '?'; break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( (sp->n_type & NN_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');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int gnu_text_symbol(value)
|
|
||||||
off_t value;
|
|
||||||
{
|
|
||||||
struct newnlist *sp;
|
|
||||||
|
|
||||||
if ((sp = gnu_sval(value, CSEG)) != NULL && sp->n_value == value)
|
|
||||||
{
|
|
||||||
gnu_sym(sp, value);
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
int gnu_finds_data(off,data_seg)
|
|
||||||
off_t off;
|
|
||||||
int data_seg;
|
|
||||||
{
|
|
||||||
struct newnlist *sp;
|
|
||||||
|
|
||||||
if ((sp = gnu_sval(off, data_seg)) != NULL)
|
|
||||||
{
|
|
||||||
gnu_sym(sp, off);
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
int gnu_finds_pc(pc)
|
|
||||||
off_t pc;
|
|
||||||
{
|
|
||||||
struct newnlist *sp;
|
|
||||||
|
|
||||||
if ((sp = gnu_sval(pc, CSEG)) != NULL)
|
|
||||||
{
|
|
||||||
gnu_sym(sp, pc);
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* EXTRA_SYMBOLS */
|
|
|
@ -1,294 +0,0 @@
|
||||||
/*
|
|
||||||
* 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
|
|
||||||
|
|
||||||
static int forceupper = FALSE;
|
|
||||||
static int someupper = FALSE;
|
|
||||||
static int stringcount = 0;
|
|
||||||
static char *string_ptr = NULL; /* stringptr ambiguous at 8th char */
|
|
||||||
static char *stringstart = NULL;
|
|
||||||
|
|
||||||
static char outbuf[OUTBUFSIZE];
|
|
||||||
static FILE *cmdfile = stdin;
|
|
||||||
static FILE *outfile = stdout;
|
|
||||||
static FILE *logfile;
|
|
||||||
static int lineno;
|
|
||||||
|
|
||||||
int _doprnt(const char *format, va_list ap, FILE *stream );
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
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()
|
|
||||||
*/
|
|
||||||
int Printf(const char *format, ...)
|
|
||||||
{
|
|
||||||
va_list ap;
|
|
||||||
int retval;
|
|
||||||
va_start(ap, format);
|
|
||||||
|
|
||||||
retval = vsnprintf(outbuf, OUTBUFSIZE, format, ap);
|
|
||||||
va_end(ap);
|
|
||||||
|
|
||||||
outstr(outbuf);
|
|
||||||
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Set logging options
|
|
||||||
*/
|
|
||||||
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 */
|
|
||||||
void do_error(m)
|
|
||||||
char *m;
|
|
||||||
{
|
|
||||||
outstr(m);
|
|
||||||
outstr(": ");
|
|
||||||
outstr(strerror(errno));
|
|
||||||
outstr("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
void closestring()
|
|
||||||
{
|
|
||||||
/* close string device */
|
|
||||||
|
|
||||||
stringcount = 0;
|
|
||||||
stringstart = string_ptr = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
int mytolower(ch)
|
|
||||||
int ch;
|
|
||||||
{
|
|
||||||
/* convert char to lower case */
|
|
||||||
|
|
||||||
if (ch >= 'A' && ch <= 'Z')
|
|
||||||
ch += 'a' - 'A';
|
|
||||||
return ch;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void openstring(string)
|
|
||||||
char *string;
|
|
||||||
{
|
|
||||||
/* open string device */
|
|
||||||
|
|
||||||
stringcount = 0;
|
|
||||||
stringstart = string_ptr = string;
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void outcomma()
|
|
||||||
{
|
|
||||||
/* print comma */
|
|
||||||
|
|
||||||
outbyte(',');
|
|
||||||
}
|
|
||||||
|
|
||||||
static char hexdigits[] = "0123456789ABCDEF";
|
|
||||||
void outh4(num)
|
|
||||||
unsigned num;
|
|
||||||
{
|
|
||||||
/* print 4 bits hex */
|
|
||||||
|
|
||||||
outbyte(hexdigits[num % 16]);
|
|
||||||
}
|
|
||||||
|
|
||||||
void outh8(num)
|
|
||||||
unsigned num;
|
|
||||||
{
|
|
||||||
/* print 8 bits hex */
|
|
||||||
|
|
||||||
outh4(num / 16);
|
|
||||||
outh4(num);
|
|
||||||
}
|
|
||||||
|
|
||||||
void outh16(num)
|
|
||||||
unsigned num;
|
|
||||||
{
|
|
||||||
/* print 16 bits hex */
|
|
||||||
|
|
||||||
outh8(num / 256);
|
|
||||||
outh8(num);
|
|
||||||
}
|
|
||||||
|
|
||||||
void outh32(num)
|
|
||||||
unsigned num;
|
|
||||||
{
|
|
||||||
/* print 32 bits hex */
|
|
||||||
|
|
||||||
outh16((u16_t) (num >> 16));
|
|
||||||
outh16((u16_t) num);
|
|
||||||
}
|
|
||||||
|
|
||||||
void outspace()
|
|
||||||
{
|
|
||||||
/* print space */
|
|
||||||
|
|
||||||
outbyte(' ');
|
|
||||||
}
|
|
||||||
|
|
||||||
void outstr(s)
|
|
||||||
register char *s;
|
|
||||||
{
|
|
||||||
/* print string */
|
|
||||||
|
|
||||||
while (*s)
|
|
||||||
outbyte(*s++);
|
|
||||||
}
|
|
||||||
|
|
||||||
void outtab()
|
|
||||||
{
|
|
||||||
/* print tab */
|
|
||||||
|
|
||||||
outbyte('\t');
|
|
||||||
}
|
|
||||||
|
|
||||||
void outustr(s)
|
|
||||||
register char *s;
|
|
||||||
{
|
|
||||||
/* print string, perhaps converting case to upper */
|
|
||||||
|
|
||||||
forceupper = someupper;
|
|
||||||
while (*s)
|
|
||||||
outbyte(*s++);
|
|
||||||
forceupper = FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int stringpos()
|
|
||||||
{
|
|
||||||
/* return current offset of string device */
|
|
||||||
|
|
||||||
return string_ptr - stringstart;
|
|
||||||
}
|
|
||||||
|
|
||||||
int stringtab()
|
|
||||||
{
|
|
||||||
/* return current "tab" spot of string device */
|
|
||||||
|
|
||||||
return stringcount;
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,67 +0,0 @@
|
||||||
/*
|
|
||||||
* 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"
|
|
||||||
|
|
||||||
static int get_request;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* decode ioctl call
|
|
||||||
* send or receive = 'R' or 'S'
|
|
||||||
*/
|
|
||||||
void decode_ioctl(sr, m)
|
|
||||||
int sr;
|
|
||||||
message *m;
|
|
||||||
{
|
|
||||||
int request, device;
|
|
||||||
int high;
|
|
||||||
long spek, flags;
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
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 )
|
|
||||||
);
|
|
||||||
Printf("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* SYSCALLS_SUPPORT */
|
|
|
@ -1,250 +0,0 @@
|
||||||
/*
|
|
||||||
* 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 <machine/archtypes.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];
|
|
||||||
|
|
||||||
static char segment_name[] = "TDS";
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Display memory maps
|
|
||||||
*/
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
static char regs[] = "fs gs ds es di si bp bx dx cx ax ip cs ps sp ss";
|
|
||||||
#else
|
|
||||||
static char regs[] = "es ds di si bp bx dx cx ax ip cs ps sp ss";
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Get register for pid at offset k */
|
|
||||||
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 */
|
|
||||||
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);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
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");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
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 */
|
|
||||||
long get_reg(pid, k)
|
|
||||||
int pid;
|
|
||||||
long k;
|
|
||||||
{
|
|
||||||
return ptrace(T_GETUSER, pid, k, 0L);
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
|
@ -1,154 +0,0 @@
|
||||||
.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
|
|
1029
commands/mdb/mdb.c
1029
commands/mdb/mdb.c
File diff suppressed because it is too large
Load diff
|
@ -1,162 +0,0 @@
|
||||||
/*
|
|
||||||
* 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 <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 defined(__i386__)
|
|
||||||
#define MINIX_PC
|
|
||||||
#else
|
|
||||||
#error "Unsupported arch"
|
|
||||||
#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 (sizeof(void *))
|
|
||||||
#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 defined(__i386__)
|
|
||||||
#define N_REG16 4 /* 16 bit registers at start of stackframe */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(__i386__)
|
|
||||||
#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
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,157 +0,0 @@
|
||||||
/*
|
|
||||||
* 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"
|
|
||||||
|
|
||||||
static long value(char *s , char **s_p , int *seg_p );
|
|
||||||
static long lookup(char *s , char **s_p , int *seg_p );
|
|
||||||
|
|
||||||
#define idchar(c) (isalpha(c) || isdigit(c) || (c) == '_')
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Get an expression for mdb
|
|
||||||
*/
|
|
||||||
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
|
|
||||||
*/
|
|
||||||
static 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()
|
|
||||||
*/
|
|
||||||
static 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 */
|
|
||||||
char *skip(s)
|
|
||||||
register char *s;
|
|
||||||
{
|
|
||||||
while (isspace(*s)) ++s;
|
|
||||||
return *s ? s : s - 1;
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,290 +0,0 @@
|
||||||
/*
|
|
||||||
* misc.c for mdb
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "mdb.h"
|
|
||||||
#include <ctype.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <sys/param.h>
|
|
||||||
#define ptrace mdbtrace
|
|
||||||
#include <sys/ptrace.h>
|
|
||||||
#include "proto.h"
|
|
||||||
|
|
||||||
static void pr_ascii(long val , int size );
|
|
||||||
|
|
||||||
/* Print ascii */
|
|
||||||
static 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 */
|
|
||||||
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 */
|
|
||||||
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 */
|
|
||||||
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");
|
|
||||||
}
|
|
||||||
|
|
||||||
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 */
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,105 +0,0 @@
|
||||||
/*
|
|
||||||
* proto.h for mdb
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* core.c */
|
|
||||||
|
|
||||||
void prtmap(void);
|
|
||||||
unsigned long core_init(char *filename);
|
|
||||||
unsigned long file_init(char *filename);
|
|
||||||
long read_core(int req, long addr, long data);
|
|
||||||
|
|
||||||
/* mdb.c */
|
|
||||||
|
|
||||||
void mdb_error(char *s);
|
|
||||||
long breakpt(long addr , char *cmd );
|
|
||||||
void tstart(int req , int verbose , int val , int cnt );
|
|
||||||
|
|
||||||
/* io.c */
|
|
||||||
|
|
||||||
char *get_cmd(char *cbuf, int csize);
|
|
||||||
void openin(char *s );
|
|
||||||
void logging(int c, char *name);
|
|
||||||
void do_error(char *message);
|
|
||||||
int Printf(const char *format, ...);
|
|
||||||
void outbyte(int byte);
|
|
||||||
void outcomma(void);
|
|
||||||
void outh8(unsigned num);
|
|
||||||
void outh16(unsigned num);
|
|
||||||
void outh32(unsigned num);
|
|
||||||
void outh4(unsigned num);
|
|
||||||
void outspace(void);
|
|
||||||
void outstr(char *s);
|
|
||||||
void outtab(void);
|
|
||||||
void outustr(char *s);
|
|
||||||
void closestring(void);
|
|
||||||
int mytolower(int ch);
|
|
||||||
void openstring(char *string);
|
|
||||||
int stringpos(void);
|
|
||||||
int stringtab(void);
|
|
||||||
|
|
||||||
/* mdbdis86.c */
|
|
||||||
|
|
||||||
long dasm(long addr, int count, int symflg);
|
|
||||||
|
|
||||||
/* mdbexp.c */
|
|
||||||
|
|
||||||
char *getexp(char *buf, long *exp_p, int *seg_p);
|
|
||||||
char *skip(char *s);
|
|
||||||
|
|
||||||
/* kernel.c */
|
|
||||||
long get_reg(int pid, long k);
|
|
||||||
void set_reg(int pid, long k, long value);
|
|
||||||
long reg_addr(char *s);
|
|
||||||
int disp_regs(void);
|
|
||||||
int outsegreg(off_t num);
|
|
||||||
void update(void);
|
|
||||||
void disp_maps(void);
|
|
||||||
|
|
||||||
/* misc.c */
|
|
||||||
|
|
||||||
void dump_stack(long count);
|
|
||||||
off_t file_size(int fd);
|
|
||||||
void help_on(int h);
|
|
||||||
void version_info(void);
|
|
||||||
void help_page(void);
|
|
||||||
|
|
||||||
#if EXTRA_SYMBOLS
|
|
||||||
/* gnu_sym.c */
|
|
||||||
void gnu_init(char *filename);
|
|
||||||
long gnu_symbolvalue(char *name, int is_text );
|
|
||||||
void gnu_symbolic(off_t value, int separator);
|
|
||||||
void gnu_listsym(int tchar);
|
|
||||||
int gnu_text_symbol(off_t value);
|
|
||||||
int gnu_finds_pc(off_t pc);
|
|
||||||
int gnu_finds_data(off_t off, int data_seg);
|
|
||||||
#endif /* EXTRA_SYMBOLS */
|
|
||||||
|
|
||||||
/* sym.c */
|
|
||||||
void syminit(char *filename);
|
|
||||||
long symbolvalue(char *name, int is_text );
|
|
||||||
void printhex(off_t v);
|
|
||||||
void symbolic(off_t value, int separator);
|
|
||||||
void listsym(char *cmd);
|
|
||||||
int text_symbol(off_t value);
|
|
||||||
int finds_pc(off_t pc);
|
|
||||||
int finds_data(off_t off, int data_seg);
|
|
||||||
|
|
||||||
/* trace.c */
|
|
||||||
long mdbtrace(int req, int pid, long addr, long data);
|
|
||||||
u32_t peek_dword(off_t addr);
|
|
||||||
|
|
||||||
#if SYSCALLS_SUPPORT
|
|
||||||
|
|
||||||
/* syscalls.c */
|
|
||||||
void start_syscall(long addr);
|
|
||||||
void do_syscall(long addr);
|
|
||||||
|
|
||||||
/* decode.c */
|
|
||||||
void decode_message(unsigned addr);
|
|
||||||
void decode_result(void);
|
|
||||||
|
|
||||||
/* ioctl.c */
|
|
||||||
void decode_ioctl(int sr, message *m);
|
|
||||||
|
|
||||||
#endif /* SYSCALLS_SUPPORT */
|
|
|
@ -1,9 +0,0 @@
|
||||||
r 10
|
|
||||||
y
|
|
||||||
__sendrec b
|
|
||||||
B
|
|
||||||
c
|
|
||||||
x 2
|
|
||||||
t
|
|
||||||
q
|
|
||||||
|
|
|
@ -1,517 +0,0 @@
|
||||||
/*
|
|
||||||
* 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"
|
|
||||||
|
|
||||||
struct symtab_s
|
|
||||||
{
|
|
||||||
struct nlist *start;
|
|
||||||
struct nlist *end;
|
|
||||||
int text;
|
|
||||||
int data;
|
|
||||||
unsigned nsym;
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct symtab_s symtab;
|
|
||||||
static int type_of_exec;
|
|
||||||
|
|
||||||
static int check_exec(struct exec *hdr);
|
|
||||||
static void sortsyms(struct nlist *array , struct nlist *top );
|
|
||||||
static int symeq(char *t , struct nlist *sp );
|
|
||||||
static int symprefix(char *t , struct nlist *sp );
|
|
||||||
static struct nlist *findsname(char *name, int is_text, int allflag);
|
|
||||||
static void outsym(struct nlist *sp, off_t off);
|
|
||||||
static struct nlist *findsval(off_t value, int where);
|
|
||||||
|
|
||||||
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
|
|
||||||
*/
|
|
||||||
static 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) {
|
|
||||||
Printf("mdb: invalid magic number in exec header - %02x %02x\n",
|
|
||||||
hdr->a_magic[0],
|
|
||||||
hdr->a_magic[1]);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check CPU */
|
|
||||||
#if defined(__i386__)
|
|
||||||
if (hdr->a_cpu != A_I80386)
|
|
||||||
#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
|
|
||||||
|
|
||||||
#if GNU_SUPPORT
|
|
||||||
if (hdr->a_flags & A_NSYM)
|
|
||||||
return GNU_SYMBOLS;
|
|
||||||
#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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
static 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();
|
|
||||||
outh32( sp->n_value );
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
static 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void printhex(v)
|
|
||||||
off_t v;
|
|
||||||
{
|
|
||||||
if ( v >= 65536L )
|
|
||||||
outh32( v );
|
|
||||||
else if ( v >= 256 )
|
|
||||||
outh16( (u16_t) v );
|
|
||||||
else
|
|
||||||
outh8( (u8_t) v );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static 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 */
|
|
||||||
|
|
||||||
static 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 );
|
|
||||||
}
|
|
||||||
|
|
||||||
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 );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int symeq( t, sp )
|
|
||||||
register char *t;
|
|
||||||
struct nlist *sp;
|
|
||||||
{
|
|
||||||
return strncmp( t, sp->n_name, sizeof sp->n_name ) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static 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 */
|
|
||||||
|
|
||||||
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();
|
|
||||||
outh32( sp->n_value );
|
|
||||||
outbyte('\n');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
|
@ -1,85 +0,0 @@
|
||||||
/*
|
|
||||||
* 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
|
|
||||||
|
|
||||||
static long intaddr;
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
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(" PM ");
|
|
||||||
break;
|
|
||||||
case 1: Printf(" VFS ");
|
|
||||||
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 */
|
|
|
@ -1,51 +0,0 @@
|
||||||
/*
|
|
||||||
* 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
|
|
||||||
*/
|
|
||||||
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 */
|
|
||||||
u32_t peek_dword(addr)
|
|
||||||
off_t addr;
|
|
||||||
{
|
|
||||||
return mdbtrace(T_GETINS, curpid, addr, 0L);
|
|
||||||
}
|
|
||||||
|
|
|
@ -208,8 +208,8 @@
|
||||||
./usr/benchmarks/unixbench/testdir/sort.src minix-sys
|
./usr/benchmarks/unixbench/testdir/sort.src minix-sys
|
||||||
./usr/benchmarks/unixbench/tmp minix-sys
|
./usr/benchmarks/unixbench/tmp minix-sys
|
||||||
./usr/bin minix-sys
|
./usr/bin minix-sys
|
||||||
./usr/bin/acknm minix-sys
|
./usr/bin/acknm minix-sys obsolete
|
||||||
./usr/bin/acksize minix-sys
|
./usr/bin/acksize minix-sys obsolete
|
||||||
./usr/bin/addr2line minix-sys binutils
|
./usr/bin/addr2line minix-sys binutils
|
||||||
./usr/bin/add_route minix-sys
|
./usr/bin/add_route minix-sys
|
||||||
./usr/bin/apropos minix-sys
|
./usr/bin/apropos minix-sys
|
||||||
|
@ -1759,7 +1759,7 @@
|
||||||
./usr/man/man1 minix-sys
|
./usr/man/man1 minix-sys
|
||||||
./usr/man/man1/..1 minix-sys
|
./usr/man/man1/..1 minix-sys
|
||||||
./usr/man/man1/[.1 minix-sys
|
./usr/man/man1/[.1 minix-sys
|
||||||
./usr/man/man1/acksize.1 minix-sys
|
./usr/man/man1/acksize.1 minix-sys obsolete
|
||||||
./usr/man/man1/addr2line.1 minix-sys binutils
|
./usr/man/man1/addr2line.1 minix-sys binutils
|
||||||
./usr/man/man1/apropos.1 minix-sys
|
./usr/man/man1/apropos.1 minix-sys
|
||||||
./usr/man/man1/ar.1 minix-sys binutils
|
./usr/man/man1/ar.1 minix-sys binutils
|
||||||
|
@ -1959,7 +1959,7 @@
|
||||||
./usr/man/man1/nbperf.1 minix-sys
|
./usr/man/man1/nbperf.1 minix-sys
|
||||||
./usr/man/man1/newgrp.1 minix-sys
|
./usr/man/man1/newgrp.1 minix-sys
|
||||||
./usr/man/man1/nice.1 minix-sys
|
./usr/man/man1/nice.1 minix-sys
|
||||||
./usr/man/man1/nm.1 minix-sys
|
./usr/man/man1/nm.1 minix-sys obsolete
|
||||||
./usr/man/man1/nohup.1 minix-sys
|
./usr/man/man1/nohup.1 minix-sys
|
||||||
./usr/man/man1/objcopy.1 minix-sys binutils
|
./usr/man/man1/objcopy.1 minix-sys binutils
|
||||||
./usr/man/man1/objdump.1 minix-sys binutils
|
./usr/man/man1/objdump.1 minix-sys binutils
|
||||||
|
|
|
@ -11,11 +11,11 @@ MAN= ash.1 at.1 basename.1 \
|
||||||
last.1 loadfont.1 loadkeys.1 logger.1 \
|
last.1 loadfont.1 loadkeys.1 logger.1 \
|
||||||
look.1 lp.1 lspci.1 mail.1 \
|
look.1 lp.1 lspci.1 mail.1 \
|
||||||
mesg.1 mixer.1 \
|
mesg.1 mixer.1 \
|
||||||
mkproto.1 mount.1 mt.1 nice.1 nm.1 nohup.1 od.1 \
|
mkproto.1 mount.1 mt.1 nice.1 nohup.1 od.1 \
|
||||||
paste.1 ping.1 playwave.1 pr.1 prep.1 \
|
paste.1 ping.1 playwave.1 pr.1 prep.1 \
|
||||||
profile.1 ps.1 rcp.1 recwave.1 \
|
profile.1 ps.1 rcp.1 recwave.1 \
|
||||||
remsync.1 rget.1 rlogin.1 rsh.1 rz.1 \
|
remsync.1 rget.1 rlogin.1 rsh.1 rz.1 \
|
||||||
shar.1 acksize.1 sleep.1 spell.1 \
|
shar.1 sleep.1 spell.1 \
|
||||||
split.1 stty.1 svc.1 svrctl.1 \
|
split.1 stty.1 svc.1 svrctl.1 \
|
||||||
synctree.1 sysenv.1 sz.1 tail.1 tee.1 telnet.1 template.1 \
|
synctree.1 sysenv.1 sz.1 tail.1 tee.1 telnet.1 template.1 \
|
||||||
term.1 termcap.1 tget.1 time.1 tr.1 true.1 \
|
term.1 termcap.1 tget.1 time.1 tr.1 true.1 \
|
||||||
|
|
|
@ -1,41 +0,0 @@
|
||||||
.TH ACKSIZE 1
|
|
||||||
.SH NAME
|
|
||||||
acksize \- print text, data, and bss size of a program
|
|
||||||
.SH SYNOPSIS
|
|
||||||
\fBacksize\fR [\fIfile\fR] ...\fR
|
|
||||||
.br
|
|
||||||
.de FL
|
|
||||||
.TP
|
|
||||||
\\fB\\$1\\fR
|
|
||||||
\\$2
|
|
||||||
..
|
|
||||||
.de EX
|
|
||||||
.TP 20
|
|
||||||
\\fB\\$1\\fR
|
|
||||||
# \\$2
|
|
||||||
..
|
|
||||||
.SH EXAMPLES
|
|
||||||
.TP 20
|
|
||||||
.B acksize file
|
|
||||||
# Print the size of \fIfile\fP
|
|
||||||
.SH DESCRIPTION
|
|
||||||
.PP
|
|
||||||
The text, data, bss, and total sizes for each argument are printed.
|
|
||||||
If no arguments are present,
|
|
||||||
.I a.out
|
|
||||||
is assumed.
|
|
||||||
The amount of memory available for combined stack and data segment growth
|
|
||||||
is printed in the column \&'stack.\&'
|
|
||||||
This is the value manipulated by the
|
|
||||||
.I chmem
|
|
||||||
command.
|
|
||||||
The total amount of memory allocated to the program when it is loaded is
|
|
||||||
listed under \&'memory.\&'
|
|
||||||
This value is just the sum of the other four columns.
|
|
||||||
.SH "SEE ALSO"
|
|
||||||
.BR anm (1),
|
|
||||||
.BR asize (1),
|
|
||||||
.BR ar (1),
|
|
||||||
.BR chmem (1),
|
|
||||||
.BR install (1),
|
|
||||||
.BR nm (1).
|
|
|
@ -1,58 +0,0 @@
|
||||||
.TH NM 1
|
|
||||||
.SH NAME
|
|
||||||
nm \- print name list
|
|
||||||
.SH SYNOPSIS
|
|
||||||
\fBnm\fR [\fB\-dgnopru\fR]\fR [\fIfile\fR] ...\fR
|
|
||||||
.br
|
|
||||||
.de FL
|
|
||||||
.TP
|
|
||||||
\\fB\\$1\\fR
|
|
||||||
\\$2
|
|
||||||
..
|
|
||||||
.de EX
|
|
||||||
.TP 20
|
|
||||||
\\fB\\$1\\fR
|
|
||||||
# \\$2
|
|
||||||
..
|
|
||||||
.SH OPTIONS
|
|
||||||
.TP 5
|
|
||||||
.B \-d
|
|
||||||
# Print the offsets in decimal instead of in hex
|
|
||||||
.TP 5
|
|
||||||
.B \-g
|
|
||||||
# Print only external symbols
|
|
||||||
.TP 5
|
|
||||||
.B \-n
|
|
||||||
# Sort numerically rather than alphabetically
|
|
||||||
.TP 5
|
|
||||||
.B \-o
|
|
||||||
# Prepend file name to each line rather than only once
|
|
||||||
.TP 5
|
|
||||||
.B \-p
|
|
||||||
# Do not sort, print in symbol-table order
|
|
||||||
.TP 5
|
|
||||||
.B \-r
|
|
||||||
# Sort in reverse order
|
|
||||||
.TP 5
|
|
||||||
.B \-u
|
|
||||||
# Print only undefined symbols
|
|
||||||
.SH EXAMPLES
|
|
||||||
.TP 20
|
|
||||||
.B nm \-n a.out
|
|
||||||
# Print all symbols in numerical order
|
|
||||||
.TP 20
|
|
||||||
.B nm \-dg a.out
|
|
||||||
# Print globals alphabetically in decimal
|
|
||||||
.SH DESCRIPTION
|
|
||||||
.PP
|
|
||||||
\fINm\fR prints the symbol table of executable files when it is available.
|
|
||||||
If no file is given, the symbols in \fIa.out\fR are used.
|
|
||||||
The format of the table
|
|
||||||
is somewhat compatible with the one produced by \fIasld\fR when used with
|
|
||||||
the \fB\-s\fR option. The symbol table can be added with \fIast\fR.
|
|
||||||
Assembly language files do not have symbol tables.
|
|
||||||
.SH "SEE ALSO"
|
|
||||||
.BR anm (1),
|
|
||||||
.BR asize (1),
|
|
||||||
.BR ar (1),
|
|
||||||
.BR size (1).
|
|
Loading…
Reference in a new issue