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