|
|
1.1 root 1: /*
2: * db/db1.c
3: * A debugger.
4: * Initialization and command line parsing.
5: */
6:
7: #include <stddef.h>
8: #include <canon.h>
9: #include <signal.h>
10: #include <sys/core.h>
11: #include <sys/uproc.h>
12: #include "db.h"
13:
14: int
15: main(argc, argv) int argc; char *argv[];
16: {
17: signal(SIGINT, &arm_sigint);
18: signal(SIGQUIT, SIG_IGN);
19: initialize();
20: setup(argc, argv);
21: process();
22: }
23:
24: /*
25: * Catch and flag interrupts (SIGINT).
26: */
27: void
28: arm_sigint()
29: {
30: signal(SIGINT, &arm_sigint);
31: intflag++;
32: }
33:
34: /*
35: * Canonicalize an l.out header.
36: */
37: void
38: canlout()
39: {
40: register int i;
41:
42: canint(ldh.l_magic);
43: canint(ldh.l_flag);
44: canint(ldh.l_machine);
45: canvaddr(ldh.l_entry);
46: for (i=0; i<NLSEG; i++)
47: cansize(ldh.l_ssize[i]);
48: }
49:
50: /*
51: * Initialize segment formats, clear the breakpoint table,
52: * invalidate the child process register image.
53: */
54: void
55: initialize()
56: {
57: init_mch();
58: strcpy(seg_format[DSEG], "w"); /* patched in set_prog() if COFF */
59: strcpy(seg_format[ISEG], "i");
60: strcpy(seg_format[USEG], "w"); /* patched in set_prog() if COFF */
61: bpt_init();
62: reg_flag = R_INVALID;
63: }
64:
65: /*
66: * Leave.
67: */
68: void
69: leave()
70: {
71: killc();
72: exit(0);
73: }
74:
75: /*
76: * Open the given file.
77: * If 'rflag' is set, the file is opened for read only.
78: */
79: FILE *
80: openfile(name, rflag) char *name; int rflag;
81: {
82: register FILE *fp;
83:
84: #if __I386__
85: again:
86: #endif
87: if (!rflag && (fp = fopen(name, "r+w")) != (FILE *)NULL)
88: return fp;
89: else if ((fp = fopen(name, "r")) != (FILE *)NULL) {
90: if (!rflag)
91: printr("%s: opened read only", name);
92: return fp;
93: }
94: #if __I386__
95: if (strcmp(name, DEFLT_OBJ) == 0) {
96: name = DEFLT_OBJ2; /* l.out not found, try a.out */
97: goto again;
98: }
99: #endif
100: panic("Cannot open %s", name);
101: }
102:
103: /*
104: * Set up segmentation for a core dump.
105: * The registers are also read.
106: * hal improved the core file format 4/93 for COHERENT V4.0.1r75.
107: * Compiling without -DOLD_CORE builds db which groks only the new format.
108: * Compiling with -DOLD_CORE builds db which groks both old and new formats.
109: * This hack should disappear when the old format becomes irrelevant.
110: */
111: void
112: set_core(name) char *name;
113: {
114: struct ch_info ch_info;
115: long offset;
116: register unsigned i;
117: register char *cp;
118: register ADDR_T size;
119: register off_t offt;
120: ADDR_T regl; /* an address, int * in <sys/uproc.h> */
121: int iflag, textflag;
122: int signo;
123: char ucomm[U_COMM_LEN+1];
124: SR usegs[NUSEG];
125:
126: /* Open the core file. */
127: cfn = name;
128: cfp = openfile(name, rflag);
129:
130: /* Read the core file header and set uproc offset. */
131: if (fread(&ch_info, sizeof ch_info, 1, cfp) != 1)
132: panic("Cannot read core file header");
133: #if !OLD_CORE
134: if (ch_info.ch_magic != CORE_MAGIC)
135: panic("Not a core file");
136: offset = ch_info.ch_info_len + ch_info.ch_uproc_offset;
137: #else
138: if (ch_info.ch_magic == CORE_MAGIC)
139: offset = ch_info.ch_info_len + ch_info.ch_uproc_offset;
140: else
141: offset = (long)U_OFFSET;
142: #endif
143:
144: /* Read the file name from the core file. */
145: if (fseek(cfp, offset+offsetof(UPROC, u_comm[0]), SEEK_SET) != -1
146: && (cp = lfn) != NULL
147: && fread(ucomm, sizeof(ucomm), 1, cfp) == 1) {
148:
149: /* Compare object filename to core filename. */
150: while (strchr(cp, '/') != NULL)
151: cp = strchr(cp, '/') + 1; /* skip past '/' */
152: if (strncmp(cp, ucomm, sizeof(ucomm)) != 0) {
153: ucomm[U_COMM_LEN] = '\0';
154: printr("Core file name \"%s\" different from object file name \"%s\"",
155: ucomm, lfn);
156: }
157: }
158:
159: /* Read the core file segment information. */
160: if (fseek(cfp, offset+offsetof(UPROC, u_segl[0]), SEEK_SET) == -1
161: || fread(usegs, sizeof(usegs), 1, cfp) != 1)
162: panic("Bad core file");
163:
164: /* Read the core file signal number and register pointer. */
165: if (fseek(cfp, offset+offsetof(UPROC, u_signo), SEEK_SET) == -1
166: || fread(&signo, sizeof(signo), 1, cfp) != 1)
167: panic("cannot read signo");
168: dbprintf(("signo=%d\n", signo));
169: if (fread(®l, sizeof(regl), 1, cfp) != 1)
170: panic("cannot read regl");
171: regl &= (NBPC - 1);
172: #if OLD_CORE
173: if (ch_info.ch_magic == CORE_MAGIC)
174: regl += ch_info.ch_info_len;
175: #else
176: regl += ch_info.ch_info_len;
177: #endif
178: dbprintf(("regl=%d\n", regl));
179:
180: #if __I386__
181: /* Adjust the i386 stack segment base. */
182: usegs[SISTACK].sr_base -= usegs[SISTACK].sr_size;
183: dbprintf(("adjust usegs[SISTACK].sr_base to %x\n", usegs[SISTACK].sr_base));
184: #endif
185:
186: /*
187: * The new core dump format might or might not include the text segment
188: * but does not include a flag stating if it has been dumped (oops);
189: * this decides if text is present/absent by adding up segment sizes.
190: * Presumably it should be setting SRFDUMP flag correctly instead...
191: */
192: textflag = 0;
193: #if OLD_CORE
194: if (ch_info.ch_magic == CORE_MAGIC) {
195: #endif
196: offt = usegs[0].sr_size + ch_info.ch_info_len;
197: for (i=1; i<NUSEG; i++) {
198: if (usegs[i].sr_segp == (SEG *)NULL)
199: continue;
200: if ((~usegs[i].sr_flag) & (SRFDUMP|SRFPMAP))
201: continue;
202: offt += usegs[i].sr_size;
203: }
204: fseek(cfp, 0L, SEEK_END);
205: textflag = (ftell(cfp) != offt);
206: dbprintf(("cfp_len=%lx offt=%lx textflag=%d", ftell(cfp), offt, textflag));
207: #if OLD_CORE
208: }
209: #endif
210:
211: /* Set up segmentation. */
212: iflag = ISPACE == DSPACE;
213: map_set(USEG, MIN_ADDR, (ADDR_T)UPASIZE, (off_t)regl, MAP_CORE);
214: map_clear(DSEG, endpure);
215: offt = usegs[0].sr_size;
216: #if OLD_CORE
217: if (ch_info.ch_magic == CORE_MAGIC)
218: offt += ch_info.ch_info_len;
219: #else
220: offt += ch_info.ch_info_len;
221: #endif
222: if (textflag) {
223: /* Map the text segment. */
224: map_clear(ISEG, NULL);
225: size = usegs[SISTEXT].sr_size;
226: map_set(ISEG, (ADDR_T)usegs[SISTEXT].sr_base, size, offt, MAP_CORE);
227: offt += size;
228: }
229: for (i=1; i<NUSEG; i++) {
230: if (usegs[i].sr_segp == (SEG *)NULL)
231: continue;
232: if ((~usegs[i].sr_flag) & (SRFDUMP|SRFPMAP))
233: continue;
234: size = usegs[i].sr_size;
235: map_set(DSEG, (ADDR_T)usegs[i].sr_base, size, offt, MAP_CORE);
236: offt += size;
237: }
238: if (iflag)
239: ISPACE = DSPACE;
240: get_regs(R_ALL); /* read the registers */
241: if (!rflag)
242: set_sig(signo); /* correct signal number */
243: }
244:
245: /*
246: * Set up segmentation for an ordinary file.
247: * This is really easy.
248: */
249: void
250: set_file(name) char *name;
251: {
252: lfp = openfile(name, rflag);
253: map_set(DSEG, MIN_ADDR, MAX_ADDR, (off_t)0, MAP_PROG);
254: ISPACE = DSPACE;
255: }
256:
257: /*
258: * Setup object file "name".
259: * The flag is bit mapped:
260: * 1 bit read symbol table
261: * 2 bit read segment information
262: */
263: void
264: set_prog(name, flag) char *name; int flag;
265: {
266: dbprintf(("set_prog(%s, %d)\n", name, flag));
267: lfp = openfile(name, (flag&2) ? rflag : 1);
268: if (fread(&coff_hdr, sizeof(coff_hdr), 1, lfp) != 1)
269: panic("Cannot read object file header");
270: if (coff_hdr.f_magic == C_386_MAGIC) {
271: /* The object is a COFF file. */
272: dbprintf(("IS_COFF!\n"));
273: file_type = COFF_FILE;
274: addr_fmt = ADDR_FMT;
275: aop_size = 32;
276: strcpy(seg_format[DSEG], "l");
277: strcpy(seg_format[USEG], "l");
278: } else {
279: /* Not a COFF file, might be an l.out. */
280: if (fseek(lfp, 0L, SEEK_SET) == -1
281: || fread(&ldh, sizeof(ldh), 1, lfp) != 1)
282: panic("Cannot read object file");
283: canlout();
284: if (ldh.l_magic != L_MAGIC)
285: panic("Bad object file");
286:
287: /* The object is an l.out file. */
288: dbprintf(("IS_LOUT!\n"));
289: file_type = LOUT_FILE;
290: addr_fmt = ADDR16_FMT;
291: aop_size = 16;
292: }
293: if ((flag&1) != 0 && !sflag) {
294: sfp = lfp;
295: if (IS_LOUT) {
296: nsyms = ldh.l_ssize[L_SYM] / sizeof(struct ldsym);
297: if (nsyms != 0)
298: read_lout_sym((long) sizeof(ldh)
299: + ldh.l_ssize[L_SHRI] + ldh.l_ssize[L_PRVI]
300: + ldh.l_ssize[L_SHRD] + ldh.l_ssize[L_PRVD]);
301: } else {
302: if (coff_hdr.f_nsyms != 0)
303: read_coff_sym();
304: }
305: }
306: if ((flag&2) != 0) {
307: lfn = name;
308: if (IS_LOUT)
309: setloutseg();
310: else
311: setcoffseg();
312: }
313: }
314:
315: /*
316: * Setup arguments.
317: */
318: void
319: setup(argc, argv) int argc; char *argv[];
320: {
321: register char *cp;
322: register int c;
323: register int t;
324: register int u;
325: register int tflag;
326:
327: t = '\0';
328: tflag = 0;
329:
330: /* Process command line switches -[cdefkorstV]. */
331: for (; argc > 1; argc--, argv++) {
332: cp = argv[1];
333: if (*cp++ != '-')
334: break;
335: while ((c = *cp++) != '\0') {
336: switch (c) {
337: case 'c':
338: case 'd':
339: case 'e':
340: case 'f':
341: case 'k':
342: case 'o':
343: /* only one of [cdefko] is allowed */
344: if (t != '\0')
345: usage();
346: t = c;
347: continue;
348: case 'p':
349: if (argc < 3)
350: usage();
351: --argc;
352: prompt = argv[2];
353: ++argv;
354: continue;
355: case 'r':
356: rflag = 1;
357: continue;
358: case 's':
359: sflag = 1;
360: continue;
361: case 't':
362: tflag = 1;
363: continue;
364: case 'V':
365: fprintf(stderr,
366: "db: " MCHNAME " "
367: #if DEBUG
368: "DEBUG "
369: #endif
370: #ifdef NOCANON
371: /* "NOCANON " */
372: #endif
373: #ifdef NOFP
374: "NOFP "
375: #endif
376: "V%s\n", VERSION);
377: continue;
378: default:
379: usage();
380: }
381: }
382: }
383: switch (t) {
384: case '\0':
385: switch (argc) {
386: case 1:
387: set_prog(DEFLT_OBJ, 3);
388: set_core(DEFLT_AUX);
389: break;
390: case 2:
391: set_prog(argv[1], 3);
392: break;
393: case 3:
394: set_prog(argv[1], 3);
395: set_core(argv[2]);
396: break;
397: default:
398: usage();
399: }
400: break;
401: case 'c':
402: switch (argc) {
403: case 1:
404: set_prog(DEFLT_OBJ, 3);
405: set_core(DEFLT_AUX);
406: break;
407: case 2:
408: set_core(argv[1]);
409: break;
410: case 3:
411: set_prog(argv[1], 3);
412: set_core(argv[2]);
413: break;
414: default:
415: usage();
416: }
417: break;
418: case 'd':
419: switch (argc) {
420: case 1:
421: set_prog("/coherent", 3);
422: setdump("/dev/dump");
423: break;
424: case 3:
425: set_prog(argv[1], 3);
426: setdump(argv[2]);
427: break;
428: default:
429: usage();
430: }
431: break;
432: case 'e':
433: if (argc < 2)
434: usage();
435: set_prog(argv[1], 3);
436: if (startc(&argv[1], NULL, NULL, 0) == 0)
437: leave();
438: break;
439: case 'f':
440: switch (argc) {
441: case 2:
442: set_file(argv[1]);
443: break;
444: case 3:
445: set_prog(argv[1], 1);
446: set_file(argv[2]);
447: break;
448: default:
449: usage();
450: }
451: break;
452: case 'k':
453: switch (argc) {
454: case 1:
455: set_prog("/coherent", 1);
456: setkmem("/dev/mem");
457: break;
458: case 2:
459: setkmem(argv[1]);
460: break;
461: case 3:
462: set_prog(argv[1], 1);
463: setkmem(argv[2]);
464: break;
465: default:
466: usage();
467: }
468: break;
469: case 'o':
470: switch (argc) {
471: case 1:
472: set_prog(DEFLT_OBJ, 3);
473: break;
474: case 2:
475: set_prog(argv[1], 3);
476: break;
477: case 3:
478: set_prog(argv[1], 1);
479: set_prog(argv[2], 2);
480: break;
481: default:
482: usage();
483: }
484: }
485: if (tflag) {
486: if ((u=open("/dev/tty", 2)) < 0)
487: panic("Cannot open /dev/tty");
488: dup2(u, 0);
489: dup2(u, 1);
490: dup2(u, 2);
491: }
492: }
493:
494: /*
495: * Check for interrupts and clear flag.
496: */
497: int
498: testint()
499: {
500: register int n;
501:
502: if ((n = intflag) != 0) {
503: printf("Interrupted\n");
504: intflag = 0;
505: }
506: return n;
507: }
508:
509: /*
510: * Generate a verbose usage message.
511: */
512: void
513: usage()
514: {
515: panic(
516: "Usage: db [ -cdefkorst ] [ [ mapfile ] program ]\n"
517: "Options:\n"
518: "\t-c\tprogram is a core file\n"
519: "\t-d\tprogram is a system dump; mapfile defaults to /coherent\n"
520: "\t-e\tNext argument is object file and rest of command line is passed\n"
521: "\t\tto the child process\n"
522: "\t-f\tprogram is binary data (an ordinary file)\n"
523: "\t-k\tprogram is a kernel process; mapfile defaults to /coherent\n"
524: "\t-o\tprogram is an object file\n"
525: "\t-p str\tUse str as interactive command prompt (default: \"db: \")\n"
526: "\t-r\tAccess all files read-only\n"
527: "\t-s\tDo not load symbol table\n"
528: "\t-t\tPerform input and output via /dev/tty\n"
529: "\tmapfile defaults to a.out or l.out.\n"
530: "\tprogram defaults to core.\n"
531: "Examples:\n"
532: "\tdb prog\t\tExamine, patch, execute \"prog\" under db control\n"
533: "\tdb prog core\tExamine postmortem core dump \"core\",\n"
534: "\t\t\tusing symbol table from \"prog\"\n"
535: "\tdb -e prog *.c\tExecute \"prog\" under db control with args *.c\n"
536: "\tdb -f file\tExamine and patch \"file\" as stream of bytes\n"
537: );
538: }
539:
540: /* end of db/db1.c */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.