291 lines
		
	
	
		
			7.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			291 lines
		
	
	
		
			7.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /* 
 | |
|  *  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;
 | |
|   }
 | |
| }
 | |
| 
 | 
