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");
184 sprintf(pr_descr, "(%ld,%ld)",
185 pi, (long)proctab[pi].pr_nloc);
188 sprintf(pr_descr, "%ld >>>> ILLEGAL <<<<", pi);
190 LOG((" d1 >> RSB: code = %s, PI = %s, PC = %lu, LB = %lu, LIN = %lu, FIL = %s",
191 displ_code(code), pr_descr, pc, lb, lin, displ_fil(fil)));
194 return addr - rsbsize;
197 PRIVATE char *displ_code(rsbcode)
201 case RSB_STP: return "STP";
202 case RSB_CAL: return "CAL";
203 case RSB_RTT: return "RTT";
204 case RSB_NRT: return "NRT";
205 default: return ">>Bad RSB code<<";
210 PRIVATE std_left_undefs(nundef, addr)
214 /* handle pending undefineds */
219 LOG((" d2 %10lu undef", addr));
222 LOG((" d2 | | | | | |"));
223 LOG((" d2 %10lu undef (%s)",
224 addr, displ_undefs(nundef, addr)));
233 LOG((" d2 FRA: size = %d, %s",
234 FRASize, FRA_def ? "defined" : "undefined"));
236 for (addr = 0; addr < FRASize; addr++) {
241 PRIVATE FRA_item(addr)
244 if ( is_wordaligned(addr)
245 && is_in_FRA(addr, psize)
246 && FRAd_bytes(addr, (int)(addr + psize), SH_DATAP|SH_INSP)
248 /* print a pointer value */
249 LOG((" d2 FRA[%1d] %3lu [%10lu] (%-s)",
253 displ_sh(FRA_sh[addr], FRA[addr])));
256 if ( is_wordaligned(addr)
257 && is_in_FRA(addr, wsize)
258 && FRAd_bytes(addr, (int)(addr + wsize), SH_INT)
260 /* print a word value */
261 LOG((" d2 FRA[%1d] %3lu [%10ld] (%-s)",
265 displ_sh(FRA_sh[addr], FRA[addr])));
268 /* just print the byte */
269 LOG((" d2 FRA[%1d] %3lu (%-s)",
272 displ_sh(FRA_sh[addr], FRA[addr])));
277 /******** Global Data Area Dump ********/
283 register int nundef = 0;
285 if (!check_log(" +1 "))
288 if (low == 0 && high == 0)
292 LOG((" +1 . . GDA_DUMP[%ld/%ld] . . INR = %lu . . GDA_DUMP . .",
294 LOG((" +1 ----------------------------------------------------------------"));
295 LOG((" +1 ADDRESS BYTE WORD VALUE SHADOW"));
297 /* dump global data area contents */
299 while (addr < min(HB, high)) {
300 if (dt_sh(addr) == UNDEFINED) {
302 LOG((" +1 %10lu undef", addr));
306 gdad_left_undefs(nundef, addr-1);
314 gdad_left_undefs(nundef, addr-1);
315 LOG((" +1 ----------------------------------------------------------------"));
319 PRIVATE gdad_item(addr)
322 if ( is_wordaligned(addr)
323 && is_in_data(addr, psize)
324 && dtd_bytes(addr, addr + psize, SH_DATAP|SH_INSP)
326 /* print a pointer value */
327 LOG((" +1 %10lu %3lu [%10lu] (%-s)",
329 btol(data_loc(addr)),
331 displ_sh(dt_sh(addr), data_loc(addr))));
334 if ( is_wordaligned(addr)
335 && is_in_data(addr, wsize)
336 && dtd_bytes(addr, addr + wsize, SH_INT)
338 /* print a word value */
339 LOG((" +1 %10lu %3lu [%10ld] (%-s)",
341 btol(data_loc(addr)),
343 displ_sh(dt_sh(addr), data_loc(addr))));
346 /* just print the byte */
347 LOG((" +1 %10lu %3lu (%-s)",
349 btol(data_loc(addr)),
350 displ_sh(dt_sh(addr), data_loc(addr))));
354 PRIVATE gdad_left_undefs(nundef, addr)
358 /* handle pending undefineds */
363 LOG((" +1 %10lu undef", addr));
366 LOG((" +1 | | | | | |"));
367 LOG((" +1 %10lu undef (%s)",
368 addr, displ_undefs(nundef, addr)));
373 /******** Heap Area Dump ********/
378 register int nundef = 0;
380 if (!check_log(" *1 "))
384 LOG((" *1 . . HEAP_DUMP[%ld/%ld] . . INR = %lu . . HEAP_DUMP . .",
386 LOG((" *1 ----------------------------------------------------------------"));
387 LOG((" *1 ADDRESS BYTE WORD VALUE SHADOW"));
389 /* dump heap contents */
390 for (addr = HB; addr < HP; addr++) {
391 if (dt_sh(addr) == UNDEFINED) {
393 LOG((" *1 %10lu undef", addr));
397 hpd_left_undefs(nundef, addr-1);
404 hpd_left_undefs(nundef, addr-1);
405 LOG((" *1 ----------------------------------------------------------------"));
409 PRIVATE hpd_item(addr)
412 if ( is_wordaligned(addr)
413 && is_in_data(addr, psize)
414 && dtd_bytes(addr, addr + psize, SH_DATAP|SH_INSP)
416 /* print a pointer value */
417 LOG((" *1 %10lu %3lu [%10lu] (%-s)",
419 btol(data_loc(addr)),
421 displ_sh(dt_sh(addr), data_loc(addr))));
424 if ( is_wordaligned(addr)
425 && is_in_data(addr, wsize)
426 && dtd_bytes(addr, addr + wsize, SH_INT)
428 /* print a word value */
429 LOG((" *1 %10lu %3lu [%10ld] (%-s)",
431 btol(data_loc(addr)),
433 displ_sh(dt_sh(addr), data_loc(addr))));
436 /* just print the byte */
437 LOG((" *1 %10lu %3lu (%-s)",
439 btol(data_loc(addr)),
440 displ_sh(dt_sh(addr), data_loc(addr))));
444 PRIVATE hpd_left_undefs(nundef, addr)
448 /* handle pending undefineds */
453 LOG((" *1 %10lu undef", addr));
456 LOG((" *1 | | | | | |"));
457 LOG((" *1 %10lu undef (%s)",
458 addr, displ_undefs(nundef, addr)));
464 /* Service routines */
466 PRIVATE int std_bytes(low, high, bits)
470 /* True if all stack bytes from low to high-1 have one of the
483 PRIVATE int dtd_bytes(low, high, bits)
487 /* True if all data bytes from low to high-1 have one of the
500 PRIVATE int FRAd_bytes(low, high, bits)
504 /* True if all data bytes from low to high-1 have one of the
517 PRIVATE char * /* transient */
518 displ_undefs(nundef, addr)
522 /* Given the number of undefineds, we want to report the number
523 of words with the left-over numbers of bytes on both sides:
526 .....|........|........|........|...
531 This takes some arithmetic.
534 register int left = wsize - 1 - p2i(addr-1) % wsize;
535 register int wrds = (nundef-left) / wsize;
536 register int right = nundef - left - wrds*wsize;
539 sprintf(buf, "%d byte%s",
540 nundef, nundef == 1 ? "" : "s");
542 else if (left == 0 && right == 0) {
543 sprintf(buf, "%d word%s",
544 wrds, wrds == 1 ? "" : "s");
546 else if (left == 0) {
547 sprintf(buf, "%d word%s + %d byte%s",
548 wrds, wrds == 1 ? "" : "s",
549 right, right == 1 ? "" : "s");
551 else if (right == 0) {
552 sprintf(buf, "%d byte%s + %d word%s",
553 left, left == 1 ? "" : "s",
554 wrds, wrds == 1 ? "" : "s");
557 sprintf(buf, "%d byte%s + %d word%s + %d byte%s",
558 left, left == 1 ? "" : "s",
559 wrds, wrds == 1 ? "" : "s",
560 right, right == 1 ? "" : "s");
566 displ_fil(fil) /* transient */
568 { /* Returns a buffer containing a representation of the
569 filename derived from FIL-value fil.
578 return "***NOT IN GDA***";
581 while (in_gda(fil) && (ch = data_loc(fil))) {
582 if (bp < &buf[sizeof buf-1]) {
583 *bp++ = (ch < 040 || ch > 126 ? '?' : ch);
587 if (bp < &buf[sizeof buf-1])
594 displ_sh(shadow, byte) /* transient */
597 { /* Returns a buffer containing a description of the
605 if (shadow & SH_INT) {
610 if (shadow & SH_FLOAT) {
614 if (shadow & SH_DATAP) {
618 if (shadow & SH_INSP) {
623 if (shadow & SH_PROT) {
632 if (check && isascii(byte) && isprint(byte)) {