[9] | 1 | /*
|
---|
| 2 | * misc.c for mdb
|
---|
| 3 | */
|
---|
| 4 |
|
---|
| 5 | #include "mdb.h"
|
---|
| 6 | #include <ctype.h>
|
---|
| 7 | #include <stdio.h>
|
---|
| 8 | #include <stdlib.h>
|
---|
| 9 | #include <sys/stat.h>
|
---|
| 10 | #define ptrace mdbtrace
|
---|
| 11 | #include <sys/ptrace.h>
|
---|
| 12 | #include "proto.h"
|
---|
| 13 |
|
---|
| 14 | FORWARD _PROTOTYPE( void pr_ascii , (long val , int size ));
|
---|
| 15 |
|
---|
| 16 | /* Print ascii */
|
---|
| 17 | PRIVATE void pr_ascii(val, size)
|
---|
| 18 | long val;
|
---|
| 19 | int size;
|
---|
| 20 | {
|
---|
| 21 | int i;
|
---|
| 22 | int v;
|
---|
| 23 | int sh;
|
---|
| 24 |
|
---|
| 25 | #ifdef BYTES_SWAPPED
|
---|
| 26 | sh = 8 * size;
|
---|
| 27 | #else
|
---|
| 28 | sh = 0;
|
---|
| 29 | #endif
|
---|
| 30 |
|
---|
| 31 | for (i = 0; i < size; i++) {
|
---|
| 32 | v = (int) (val >> sh) & 0xFF;
|
---|
| 33 | #ifdef BYTES_SWAPPED
|
---|
| 34 | sh -= 8;
|
---|
| 35 | #else
|
---|
| 36 | sh += 8;
|
---|
| 37 | #endif
|
---|
| 38 | Printf(isprint(v) ? "%c" : "\\%03o", v);
|
---|
| 39 | }
|
---|
| 40 | Printf("\n");
|
---|
| 41 | }
|
---|
| 42 |
|
---|
| 43 | /* Dump stack */
|
---|
| 44 | PUBLIC void dump_stack(cnt)
|
---|
| 45 | long cnt;
|
---|
| 46 | {
|
---|
| 47 | vir_bytes v, vi;
|
---|
| 48 | long val, sp;
|
---|
| 49 | int num, size, nmode;
|
---|
| 50 |
|
---|
| 51 | size = INTSIZE; /* size of stack element */
|
---|
| 52 | num = (int) cnt;
|
---|
| 53 | if (num <= 0) num = 0;
|
---|
| 54 | if (num > sk_size) num = (int) sk_size / size;
|
---|
| 55 | nmode = num; /* Save mode */
|
---|
| 56 |
|
---|
| 57 | /* Get current SP */
|
---|
| 58 | sp = get_reg(curpid, reg_addr("sp"));
|
---|
| 59 |
|
---|
| 60 | /* Starting address is top of stack seg -1 */
|
---|
| 61 | vi = (vir_bytes) sk_addr + (vir_bytes) sk_size - size;
|
---|
| 62 |
|
---|
| 63 | /* Ending address */
|
---|
| 64 | v = (vir_bytes) end_addr;
|
---|
| 65 | if (nmode == 0) v = MAX(v, sp);
|
---|
| 66 |
|
---|
| 67 | Printf("Stack Dump SP=%*lx\nAddr\tHex\tAscii\n", 2 * size, sp);
|
---|
| 68 | do {
|
---|
| 69 | val = (ptrace(T_GETDATA, curpid, (long) vi, 0L) >> SHIFT(size))
|
---|
| 70 | & MASK(size);
|
---|
| 71 | Printf("%*lx\t", 2 * ADDRSIZE, (vi >> SHIFT(ADDRSIZE))
|
---|
| 72 | & MASK(ADDRSIZE));
|
---|
| 73 | Printf("%*lx\t", 2 * size, val);
|
---|
| 74 | pr_ascii(val, size);
|
---|
| 75 | num -= 1;
|
---|
| 76 | vi -= size;
|
---|
| 77 | } while (vi >= v && (nmode ? num > 0 : 1));
|
---|
| 78 |
|
---|
| 79 | }
|
---|
| 80 |
|
---|
| 81 |
|
---|
| 82 | /* Get file size */
|
---|
| 83 | PUBLIC off_t file_size(fd)
|
---|
| 84 | int fd;
|
---|
| 85 | {
|
---|
| 86 | struct stat st;
|
---|
| 87 |
|
---|
| 88 | if(fstat(fd,&st) <0 ) {
|
---|
| 89 | Printf("Cannot stat\n");
|
---|
| 90 | return 0L;
|
---|
| 91 | }
|
---|
| 92 | else
|
---|
| 93 | return st.st_size;
|
---|
| 94 | }
|
---|
| 95 |
|
---|
| 96 | /* Print help page */
|
---|
| 97 | PUBLIC void help_page()
|
---|
| 98 | {
|
---|
| 99 | outstr("\nHelp for mdb. For more details, type 'command ?'\n");
|
---|
| 100 | outstr("!#\t- Shell escape / Set Variable or register\n");
|
---|
| 101 | outstr("Tt\t- Current call / Backtrace all\n");
|
---|
| 102 | outstr("/nsf\t- Display for n size s with format f\n");
|
---|
| 103 | outstr("Xx [n]\t- Disasm / & display reg for n instructions\n");
|
---|
| 104 | outstr("Rr a\t- Run / with arguments a\n");
|
---|
| 105 | outstr("Cc [n]\t- Continue with current signal / no signal n times\n");
|
---|
| 106 | outstr("Ii [n]\t- Single step with / no signal for n instructions\n");
|
---|
| 107 | outstr("Mm t n\t- Trace until / Stop when modified t type for n instructions\n");
|
---|
| 108 | outstr("k \t- Kill traced process\n");
|
---|
| 109 | outstr("Bb\t- Display / Set Break-pt\n");
|
---|
| 110 | outstr("Dd\t- Delete all / one break-points\n");
|
---|
| 111 | outstr("P\t- Toggle Paging\n");
|
---|
| 112 | outstr("Ll name\t- Log to file name / and to standard output\n");
|
---|
| 113 | #ifdef DEBUG
|
---|
| 114 | outstr("Vv\t- Version info / Toggle debug flag\n");
|
---|
| 115 | #else
|
---|
| 116 | outstr("V\t- Version info\n");
|
---|
| 117 | #endif
|
---|
| 118 | outstr("e [t]\t- List symbols for type t\n");
|
---|
| 119 | outstr("y\t- Print segment mappings\n");
|
---|
| 120 | outstr("s [n]\t- Dump stack for n words\n");
|
---|
| 121 | #if SYSCALLS_SUPPORT
|
---|
| 122 | outstr("z [a]\t- Trace syscalls with address a\n");
|
---|
| 123 | #endif
|
---|
| 124 | outstr("? \t- Help - this screen\n");
|
---|
| 125 | outstr("@ file\t- Execute commands from file\n");
|
---|
| 126 | outstr("Qq\t- Quit / and kill traced process\n");
|
---|
| 127 | #ifdef DEBUG
|
---|
| 128 | outstr("Usage: mdb -x debug-level [-Ll]logfile exec-file core-file @command-file\n");
|
---|
| 129 | #else
|
---|
| 130 | outstr("Usage: mdb [-Ll]logfile exec-file core-file @command-file\n");
|
---|
| 131 | #endif
|
---|
| 132 | outstr(" mdb [-fc] file\n");
|
---|
| 133 | }
|
---|
| 134 |
|
---|
| 135 | PUBLIC void version_info()
|
---|
| 136 | {
|
---|
| 137 | Printf("\nmdb version %s.%d for Minix", MDBVERSION, MDBBUILD );
|
---|
| 138 | Printf(" %s.%s", OS_RELEASE, OS_VERSION);
|
---|
| 139 | #ifdef MINIX_PC
|
---|
| 140 | #ifdef __i386
|
---|
| 141 | Printf(" (32-bit)");
|
---|
| 142 | #else
|
---|
| 143 | Printf(" (16-bit)");
|
---|
| 144 | #endif
|
---|
| 145 | #endif
|
---|
| 146 | #ifdef MINIX_ST
|
---|
| 147 | Printf("-ST");
|
---|
| 148 | #endif
|
---|
| 149 | Printf("\n");
|
---|
| 150 | }
|
---|
| 151 |
|
---|
| 152 | /* Print help message on command */
|
---|
| 153 | PUBLIC void help_on(h)
|
---|
| 154 | int h;
|
---|
| 155 | {
|
---|
| 156 |
|
---|
| 157 | switch (h) {
|
---|
| 158 | case '/':
|
---|
| 159 | outstr("<address> /nsf\t- Display for n items of size s with format f from address\n");
|
---|
| 160 | outstr("\t n defaults to 1\n");
|
---|
| 161 | outstr("\t s defaults to size of int\n");
|
---|
| 162 | outstr("\t can be b for byte h for short l for long\n");
|
---|
| 163 | outstr("\t f defaults to d for decimal\n");
|
---|
| 164 | outstr("\t can be x X o d D c s or u as in printf\n");
|
---|
| 165 | outstr("\t y treat value as address\n");
|
---|
| 166 | outstr("\t i disasm\n");
|
---|
| 167 | break;
|
---|
| 168 | case '@':
|
---|
| 169 | outstr("@ file\t- Execute commands from file\n");
|
---|
| 170 | break;
|
---|
| 171 | case '#':
|
---|
| 172 | outstr("# <address> cs value\t- Set Variable(s) at address to value\n");
|
---|
| 173 | outstr("\t\t\t for c count and size s\n");
|
---|
| 174 | outstr("\t\t\t b for byte h for short or l for long\n");
|
---|
| 175 | outstr("\t\t\t Count or size must be specified\n");
|
---|
| 176 | outstr("# $xx value\t\t- Set register $xx to value\n");
|
---|
| 177 | break;
|
---|
| 178 | case 'C':
|
---|
| 179 | outstr("C [n]\t- Continue with curent signal n times\n");
|
---|
| 180 | outstr("\t n defaults to 1\n");
|
---|
| 181 | break;
|
---|
| 182 | case 'c':
|
---|
| 183 | outstr("c [n]\t- Continue with no signal n times\n");
|
---|
| 184 | outstr("\t n defaults to 1\n");
|
---|
| 185 | break;
|
---|
| 186 | case 'e':
|
---|
| 187 | outstr("e [t]\t- List symbols for type t\n");
|
---|
| 188 | break;
|
---|
| 189 | case 's':
|
---|
| 190 | outstr("s [n]\t- Dump stack for n words\n");
|
---|
| 191 | outstr("\t n defaults to whole stack\n");
|
---|
| 192 | break;
|
---|
| 193 | case 'I':
|
---|
| 194 | outstr("I n\t- Single step with signal for n instructions n defaults to 1\n");
|
---|
| 195 | break;
|
---|
| 196 | case 'i':
|
---|
| 197 | outstr("i n\t- Single step with no signal for n instructions n defaults to 1\n");
|
---|
| 198 | break;
|
---|
| 199 | case 'M':
|
---|
| 200 | case 'm':
|
---|
| 201 | if ( h == 'M')
|
---|
| 202 | outstr("<address> M t n\t- Trace until\n");
|
---|
| 203 | else
|
---|
| 204 | outstr("<address> m t n\t- Stop when\n");
|
---|
| 205 | outstr("\t\t<address> is modified t type for n instructions\n");
|
---|
| 206 | outstr("\t\tn defaults to 1\n");
|
---|
| 207 | outstr("\t\tb for byte h for short l for long defaults to size of int\n");
|
---|
| 208 | break;
|
---|
| 209 | case 'T':
|
---|
| 210 | outstr("T\t- Display current call\n");
|
---|
| 211 | break;
|
---|
| 212 | case 't':
|
---|
| 213 | outstr("t\t- Backtrace all calls\n");
|
---|
| 214 | break;
|
---|
| 215 | case '!':
|
---|
| 216 | outstr("![command]\t- Shell escape or spawn command\n");
|
---|
| 217 | break;
|
---|
| 218 | case 'R':
|
---|
| 219 | outstr("R\t- Run the exec-file\n");
|
---|
| 220 | break;
|
---|
| 221 | case 'r':
|
---|
| 222 | outstr("r [arguments]\t- Run the exec-file with arguments\n");
|
---|
| 223 | break;
|
---|
| 224 | case 'k':
|
---|
| 225 | outstr("k\t- Kill traced process\n");
|
---|
| 226 | break;
|
---|
| 227 | case 'B':
|
---|
| 228 | outstr("B\t- Display all the Break points\n");
|
---|
| 229 | break;
|
---|
| 230 | case 'b':
|
---|
| 231 | outstr("<address> b [commands]\t- Set Break-pt at address\n");
|
---|
| 232 | outstr("\t\t\t commands will be executed by mdb at break-pt\n");
|
---|
| 233 | break;
|
---|
| 234 | case 'D':
|
---|
| 235 | outstr("D\t- Delete all break-points\n");
|
---|
| 236 | break;
|
---|
| 237 | case 'd':
|
---|
| 238 | outstr("<address> d\t- Delete one break-point at address\n");
|
---|
| 239 | break;
|
---|
| 240 | case 'q':
|
---|
| 241 | outstr("q\t- Quit mdb (and kill traced program)\n");
|
---|
| 242 | break;
|
---|
| 243 | case 'Q':
|
---|
| 244 | outstr("Q\t- Quit mdb immediately\n");
|
---|
| 245 | break;
|
---|
| 246 | case 'P':
|
---|
| 247 | outstr("P\t- Toggle Paging\n");
|
---|
| 248 | outstr("\t Defaults is OFF\n");
|
---|
| 249 | break;
|
---|
| 250 | case 'L':
|
---|
| 251 | outstr("L name\t- Log to file name\n");
|
---|
| 252 | outstr("L\t- Reset output to standard output\n");
|
---|
| 253 | break;
|
---|
| 254 | case 'l':
|
---|
| 255 | outstr("l name\t- Log to file name and standard output\n");
|
---|
| 256 | outstr("l\t- Reset output to standard output\n");
|
---|
| 257 | outstr("\t Defaults to none\n");
|
---|
| 258 | break;
|
---|
| 259 | #ifdef DEBUG
|
---|
| 260 | case 'v':
|
---|
| 261 | outstr("v\t- Toggle debug flag\n");
|
---|
| 262 | break;
|
---|
| 263 | #endif
|
---|
| 264 | case 'V':
|
---|
| 265 | outstr("V\t- Print Version Information for mdb\n");
|
---|
| 266 | break;
|
---|
| 267 | case 'X':
|
---|
| 268 | outstr("<address> X [n] [offset]\t- Disasm for n instructions\n");
|
---|
| 269 | outstr("\t\t\t Starting at address+offset\n");
|
---|
| 270 | break;
|
---|
| 271 | case 'x':
|
---|
| 272 | outstr("<address> x [n] offset\t- Disasm & display registers for n instructions\n");
|
---|
| 273 | outstr("\t\t\t Starting at address+offset\n");
|
---|
| 274 | break;
|
---|
| 275 | case 'y':
|
---|
| 276 | outstr("y\t- Print segment mappings\n");
|
---|
| 277 | break;
|
---|
| 278 | #if SYSCALLS_SUPPORT
|
---|
| 279 | case 'z':
|
---|
| 280 | outstr("z [address]\t- Trace system calls using address\n");
|
---|
| 281 | outstr("\t\t If the exec-file has symbols, mdb looks for __sendrec\n");
|
---|
| 282 | break;
|
---|
| 283 | #endif
|
---|
| 284 | default:
|
---|
| 285 | Printf("No help on command '%c' is available\n",h);
|
---|
| 286 | break;
|
---|
| 287 | }
|
---|
| 288 | }
|
---|
| 289 |
|
---|