Remove unmaintained "ack" size nm mdb

Change-Id: Iba84fd51f16577e6123148d4505c7687ea1c071d
This commit is contained in:
Antoine Leca 2013-01-25 13:15:14 +00:00 committed by Gerrit Code Review
parent 0aadbb872f
commit 14f89a8efe
30 changed files with 8 additions and 6437 deletions

View file

@ -16,13 +16,13 @@ SUBDIR= add_route arp ash at backup basename btrace \
less loadkeys loadramdisk logger look lp \
lpd lspci mail MAKEDEV \
mesg mined mkfifo \
mount mt netconf nice acknm nohup \
mount mt netconf nice nohup \
nonamed od paste patch \
ping postinstall poweroff pr prep printroot \
profile progressbar pr_routes ps pwdauth \
ramdisk rarpd rawspeed rcp readclock \
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 \
stty svclog svrctl swifi synctree sysenv \
syslogd tail tcpd tcpdp tcpstat tee telnet \

View file

@ -1,4 +0,0 @@
PROG= acknm
MAN=
.include <bsd.prog.mk>

View file

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

View file

@ -1,4 +0,0 @@
PROG= acksize
MAN=
.include <bsd.prog.mk>

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

File diff suppressed because it is too large Load diff

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -208,8 +208,8 @@
./usr/benchmarks/unixbench/testdir/sort.src minix-sys
./usr/benchmarks/unixbench/tmp minix-sys
./usr/bin minix-sys
./usr/bin/acknm minix-sys
./usr/bin/acksize minix-sys
./usr/bin/acknm minix-sys obsolete
./usr/bin/acksize minix-sys obsolete
./usr/bin/addr2line minix-sys binutils
./usr/bin/add_route minix-sys
./usr/bin/apropos minix-sys
@ -1759,7 +1759,7 @@
./usr/man/man1 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/apropos.1 minix-sys
./usr/man/man1/ar.1 minix-sys binutils
@ -1959,7 +1959,7 @@
./usr/man/man1/nbperf.1 minix-sys
./usr/man/man1/newgrp.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/objcopy.1 minix-sys binutils
./usr/man/man1/objdump.1 minix-sys binutils

View file

@ -11,11 +11,11 @@ MAN= ash.1 at.1 basename.1 \
last.1 loadfont.1 loadkeys.1 logger.1 \
look.1 lp.1 lspci.1 mail.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 \
profile.1 ps.1 rcp.1 recwave.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 \
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 \

View file

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

View file

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