2 For dumping the stack, GDA, heap and text segment.
5 /* $Id: dump.c,v 2.7 1994/06/24 10:47:08 ceriel Exp $ */
13 #include "memdirect.h"
22 extern long inr; /* from log.c */
24 /****************************************************************
25 * Dumping routines for debugging, in human-readable form. *
26 ****************************************************************/
30 /* The file is repetitive and should probably be partly generated,
31 although it is not directly evident how.
34 PRIVATE char *displ_undefs(), *displ_fil(), *displ_sh(), *displ_code();
35 PRIVATE ptr std_raw(), std_rsb();
36 PRIVATE int std_bytes(), dtd_bytes(), FRAd_bytes();
37 PRIVATE std_item(), std_left_undefs();
38 PRIVATE gdad_item(), gdad_left_undefs();
39 PRIVATE hpd_item(), hpd_left_undefs();
40 PRIVATE FRA_dump(), FRA_item();
42 /******** Stack Dump ********/
50 if (!check_log(" d1 "))
54 LOG((" d2 . . STACK_DUMP[%ld/%ld%s] . . INR = %lu . . STACK_DUMP . .",
55 wsize, psize, rawfl ? ", raw" : "", inr));
56 LOG((" d2 ----------------------------------------------------------------"));
58 /* find a good start address */
59 addr = (sz && sz < ML - SP ? SP + sz : ML);
60 /* find RSB backwards */
61 while (in_stack(addr) && !is_st_prot(addr)) {
64 /* find end of RSB backwards */
65 while (in_stack(addr) && is_st_prot(addr)) {
71 while (in_stack(addr)) {
72 addr = std_raw(addr, rawfl);
76 LOG((" d1 >> AB = %lu, LB = %lu, SP = %lu, HP = %lu, LIN = %lu, FIL = %s",
77 AB, LB, SP, HP, getLIN(), displ_fil(getFIL())));
78 LOG((" d2 ----------------------------------------------------------------"));
86 { /* Produces a formatted dump of the stack segment starting
87 at addr, up to the Return Status Block (identified
90 register int nundef = 0;
92 LOG((" d2 ADDRESS BYTE ITEM VALUE SHADOW"));
94 while ( in_stack(addr)
95 && (!is_st_prot(addr) || rawfl)
97 if (st_sh(addr) == UNDEFINED) {
99 LOG((" d2 %10lu undef", addr));
103 std_left_undefs(nundef, addr + 1);
111 std_left_undefs(nundef, addr + 1);
115 PRIVATE std_item(addr)
118 if ( is_wordaligned(addr)
119 && is_in_stack(addr, psize)
120 && std_bytes(addr, addr + psize, SH_DATAP|SH_INSP)
122 /* print a pointer value */
123 LOG((" d2 %10lu %3lu [%10lu] (%-s)",
125 btol(stack_loc(addr)),
127 displ_sh(st_sh(addr), stack_loc(addr))));
130 if ( is_wordaligned(addr)
131 && w_is_in_stack(addr)
132 && std_bytes(addr, addr + wsize, SH_INT)
134 /* print a word value */
135 LOG((" d2 %10lu %3lu [%10ld] (%-s)",
137 btol(stack_loc(addr)),
139 displ_sh(st_sh(addr), stack_loc(addr))));
142 /* just print the byte */
143 LOG((" d2 %10lu %3lu (%-s)",
145 btol(stack_loc(addr)),
146 displ_sh(st_sh(addr), stack_loc(addr))));
153 { /* Dumps the Return Status Block */
166 dmp_lb = addr - (rsbsize-1); /* pseudo local base */
167 if (!in_stack(dmp_lb)) {
168 LOG((" d1 >>RSB: >>>> INCOMPLETE <<<<"));
172 code = (int)w_in_stack(dmp_lb + rsb_rsbcode);
173 pi = (long)p_in_stack(dmp_lb + rsb_PI);
174 pc = p_in_stack(dmp_lb + rsb_PC);
175 lb = p_in_stack(dmp_lb + rsb_LB);
176 lin = LIN_in_stack(dmp_lb + rsb_LIN);
177 fil = p_in_stack(dmp_lb + rsb_FIL);
180 sprintf(pr_descr, "uninit");
186 read_proctab(pi, &pt);
187 sprintf(pr_descr, "(%ld,%ld)",
188 pi, (long)pt.pr_nloc);
191 sprintf(pr_descr, "%ld >>>> ILLEGAL <<<<", pi);
193 LOG((" d1 >> RSB: code = %s, PI = %s, PC = %lu, LB = %lu, LIN = %lu, FIL = %s",
194 displ_code(code), pr_descr, pc, lb, lin, displ_fil(fil)));
197 return addr - rsbsize;
200 PRIVATE char *displ_code(rsbcode)
204 case RSB_STP: return "STP";
205 case RSB_CAL: return "CAL";
206 case RSB_RTT: return "RTT";
207 case RSB_NRT: return "NRT";
208 default: return ">>Bad RSB code<<";
213 PRIVATE std_left_undefs(nundef, addr)
217 /* handle pending undefineds */
222 LOG((" d2 %10lu undef", addr));
225 LOG((" d2 | | | | | |"));
226 LOG((" d2 %10lu undef (%s)",
227 addr, displ_undefs(nundef, addr)));
236 LOG((" d2 FRA: size = %d, %s",
237 FRASize, FRA_def ? "defined" : "undefined"));
239 for (addr = 0; addr < FRASize; addr++) {
244 PRIVATE FRA_item(addr)
247 if ( is_wordaligned(addr)
248 && is_in_FRA(addr, psize)
249 && FRAd_bytes(addr, (int)(addr + psize), SH_DATAP|SH_INSP)
251 /* print a pointer value */
252 LOG((" d2 FRA[%1d] %3lu [%10lu] (%-s)",
256 displ_sh(FRA_sh[addr], FRA[addr])));
259 if ( is_wordaligned(addr)
260 && is_in_FRA(addr, wsize)
261 && FRAd_bytes(addr, (int)(addr + wsize), SH_INT)
263 /* print a word value */
264 LOG((" d2 FRA[%1d] %3lu [%10ld] (%-s)",
268 displ_sh(FRA_sh[addr], FRA[addr])));
271 /* just print the byte */
272 LOG((" d2 FRA[%1d] %3lu (%-s)",
275 displ_sh(FRA_sh[addr], FRA[addr])));
280 /******** Global Data Area Dump ********/
286 register int nundef = 0;
288 if (!check_log(" +1 "))
291 if (low == 0 && high == 0)
295 LOG((" +1 . . GDA_DUMP[%ld/%ld] . . INR = %lu . . GDA_DUMP . .",
297 LOG((" +1 ----------------------------------------------------------------"));
298 LOG((" +1 ADDRESS BYTE WORD VALUE SHADOW"));
300 /* dump global data area contents */
302 while (addr < min(HB, high)) {
303 if (dt_sh(addr) == UNDEFINED) {
305 LOG((" +1 %10lu undef", addr));
309 gdad_left_undefs(nundef, addr-1);
317 gdad_left_undefs(nundef, addr-1);
318 LOG((" +1 ----------------------------------------------------------------"));
322 PRIVATE gdad_item(addr)
325 if ( is_wordaligned(addr)
326 && is_in_data(addr, psize)
327 && dtd_bytes(addr, addr + psize, SH_DATAP|SH_INSP)
329 /* print a pointer value */
330 LOG((" +1 %10lu %3lu [%10lu] (%-s)",
332 btol(data_loc(addr)),
334 displ_sh(dt_sh(addr), data_loc(addr))));
337 if ( is_wordaligned(addr)
338 && is_in_data(addr, wsize)
339 && dtd_bytes(addr, addr + wsize, SH_INT)
341 /* print a word value */
342 LOG((" +1 %10lu %3lu [%10ld] (%-s)",
344 btol(data_loc(addr)),
346 displ_sh(dt_sh(addr), data_loc(addr))));
349 /* just print the byte */
350 LOG((" +1 %10lu %3lu (%-s)",
352 btol(data_loc(addr)),
353 displ_sh(dt_sh(addr), data_loc(addr))));
357 PRIVATE gdad_left_undefs(nundef, addr)
361 /* handle pending undefineds */
366 LOG((" +1 %10lu undef", addr));
369 LOG((" +1 | | | | | |"));
370 LOG((" +1 %10lu undef (%s)",
371 addr, displ_undefs(nundef, addr)));
376 /******** Heap Area Dump ********/
381 register int nundef = 0;
383 if (!check_log(" *1 "))
387 LOG((" *1 . . HEAP_DUMP[%ld/%ld] . . INR = %lu . . HEAP_DUMP . .",
389 LOG((" *1 ----------------------------------------------------------------"));
390 LOG((" *1 ADDRESS BYTE WORD VALUE SHADOW"));
392 /* dump heap contents */
393 for (addr = HB; addr < HP; addr++) {
394 if (dt_sh(addr) == UNDEFINED) {
396 LOG((" *1 %10lu undef", addr));
400 hpd_left_undefs(nundef, addr-1);
407 hpd_left_undefs(nundef, addr-1);
408 LOG((" *1 ----------------------------------------------------------------"));
412 PRIVATE hpd_item(addr)
415 if ( is_wordaligned(addr)
416 && is_in_data(addr, psize)
417 && dtd_bytes(addr, addr + psize, SH_DATAP|SH_INSP)
419 /* print a pointer value */
420 LOG((" *1 %10lu %3lu [%10lu] (%-s)",
422 btol(data_loc(addr)),
424 displ_sh(dt_sh(addr), data_loc(addr))));
427 if ( is_wordaligned(addr)
428 && is_in_data(addr, wsize)
429 && dtd_bytes(addr, addr + wsize, SH_INT)
431 /* print a word value */
432 LOG((" *1 %10lu %3lu [%10ld] (%-s)",
434 btol(data_loc(addr)),
436 displ_sh(dt_sh(addr), data_loc(addr))));
439 /* just print the byte */
440 LOG((" *1 %10lu %3lu (%-s)",
442 btol(data_loc(addr)),
443 displ_sh(dt_sh(addr), data_loc(addr))));
447 PRIVATE hpd_left_undefs(nundef, addr)
451 /* handle pending undefineds */
456 LOG((" *1 %10lu undef", addr));
459 LOG((" *1 | | | | | |"));
460 LOG((" *1 %10lu undef (%s)",
461 addr, displ_undefs(nundef, addr)));
467 /* Service routines */
469 PRIVATE int std_bytes(low, high, bits)
473 /* True if all stack bytes from low to high-1 have one of the
486 PRIVATE int dtd_bytes(low, high, bits)
490 /* True if all data bytes from low to high-1 have one of the
503 PRIVATE int FRAd_bytes(low, high, bits)
507 /* True if all data bytes from low to high-1 have one of the
520 PRIVATE char * /* transient */
521 displ_undefs(nundef, addr)
525 /* Given the number of undefineds, we want to report the number
526 of words with the left-over numbers of bytes on both sides:
529 .....|........|........|........|...
534 This takes some arithmetic.
537 register int left = wsize - 1 - p2i(addr-1) % wsize;
538 register int wrds = (nundef-left) / wsize;
539 register int right = nundef - left - wrds*wsize;
542 sprintf(buf, "%d byte%s",
543 nundef, nundef == 1 ? "" : "s");
545 else if (left == 0 && right == 0) {
546 sprintf(buf, "%d word%s",
547 wrds, wrds == 1 ? "" : "s");
549 else if (left == 0) {
550 sprintf(buf, "%d word%s + %d byte%s",
551 wrds, wrds == 1 ? "" : "s",
552 right, right == 1 ? "" : "s");
554 else if (right == 0) {
555 sprintf(buf, "%d byte%s + %d word%s",
556 left, left == 1 ? "" : "s",
557 wrds, wrds == 1 ? "" : "s");
560 sprintf(buf, "%d byte%s + %d word%s + %d byte%s",
561 left, left == 1 ? "" : "s",
562 wrds, wrds == 1 ? "" : "s",
563 right, right == 1 ? "" : "s");
569 displ_fil(fil) /* transient */
571 { /* Returns a buffer containing a representation of the
572 filename derived from FIL-value fil.
581 return "***NOT IN GDA***";
584 while (in_gda(fil) && (ch = data_loc(fil))) {
585 if (bp < &buf[sizeof buf-1]) {
586 *bp++ = (ch < 040 || ch > 126 ? '?' : ch);
590 if (bp < &buf[sizeof buf-1])
597 displ_sh(shadow, byte) /* transient */
600 { /* Returns a buffer containing a description of the
608 if (shadow & SH_INT) {
613 if (shadow & SH_FLOAT) {
617 if (shadow & SH_DATAP) {
621 if (shadow & SH_INSP) {
626 if (shadow & SH_PROT) {
635 if (check && isascii(byte) && isprint(byte)) {