Pristine Ack-5.5
[Ack-5.5.git] / util / int / dump.c
1 /*
2         For dumping the stack, GDA, heap and text segment.
3 */
4
5 /* $Id: dump.c,v 2.7 1994/06/24 10:47:08 ceriel Exp $ */
6
7 #include        <ctype.h>
8
9 #include        <em_abs.h>
10 #include        "logging.h"
11 #include        "global.h"
12 #include        "log.h"
13 #include        "memdirect.h"
14 #include        "mem.h"
15 #include        "fra.h"
16 #include        "text.h"
17 #include        "proctab.h"
18 #include        "shadow.h"
19 #include        "linfil.h"
20 #include        "rsb.h"
21
22 extern long inr;                        /* from log.c */
23
24 /****************************************************************
25  *      Dumping routines for debugging, in human-readable form. *
26  ****************************************************************/
27
28 #ifdef  LOGGING
29
30 /*      The file is repetitive and should probably be partly generated,
31         although it is not directly evident how.
32 */
33
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();
41
42 /******** Stack Dump ********/
43
44 std_all(sz, rawfl)
45         long sz;
46         int rawfl;
47 {
48         register ptr addr;
49         
50         if (!check_log(" d1 "))
51                 return;
52         
53         LOG((" d2 "));
54         LOG((" d2 . . STACK_DUMP[%ld/%ld%s] . . INR = %lu . . STACK_DUMP . .",
55                                 wsize, psize, rawfl ? ", raw" : "", inr));
56         LOG((" d2 ----------------------------------------------------------------"));
57
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)) {
62                 addr++;
63         }
64         /* find end of RSB backwards */
65         while (in_stack(addr) && is_st_prot(addr)) {
66                 addr++;
67         }
68         addr--;
69
70         /* dump the stack */
71         while (in_stack(addr)) {
72                 addr = std_raw(addr, rawfl);
73                 addr = std_rsb(addr);
74         }
75         FRA_dump();
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 ----------------------------------------------------------------"));
79         LOG((" d2 "));
80 }
81
82 PRIVATE ptr
83 std_raw(addr, rawfl)
84         ptr addr;
85         int rawfl;
86 {       /*      Produces a formatted dump of the stack segment starting
87                 at  addr, up to the Return Status Block (identified
88                 by protection bits)
89         */
90         register int nundef = 0;
91         
92         LOG((" d2       ADDRESS     BYTE     ITEM VALUE   SHADOW"));
93         
94         while ( in_stack(addr)
95         &&      (!is_st_prot(addr) || rawfl)
96         ) {
97                 if (st_sh(addr) == UNDEFINED) {
98                         if (nundef++ == 0)
99                                 LOG((" d2    %10lu    undef", addr));
100                 }
101                 else {
102                         if (nundef) {
103                                 std_left_undefs(nundef, addr + 1);
104                                 nundef = 0;
105                         }
106                         std_item(addr);
107                 }
108                 addr--;
109         }
110         if (nundef)
111                 std_left_undefs(nundef, addr + 1);
112         return addr;
113 }
114
115 PRIVATE std_item(addr)
116         ptr addr;
117 {
118         if (    is_wordaligned(addr)
119         &&      is_in_stack(addr, psize)
120         &&      std_bytes(addr, addr + psize, SH_DATAP|SH_INSP)
121         ) {
122                 /* print a pointer value */
123                 LOG((" d2    %10lu      %3lu    [%10lu]  (%-s)",
124                         addr,
125                         btol(stack_loc(addr)),
126                         p_in_stack(addr),
127                         displ_sh(st_sh(addr), stack_loc(addr))));
128         }
129         else
130         if (    is_wordaligned(addr)
131         &&      w_is_in_stack(addr)
132         &&      std_bytes(addr, addr + wsize, SH_INT)
133         ) {
134                 /* print a word value */
135                 LOG((" d2    %10lu      %3lu    [%10ld]  (%-s)",
136                         addr,
137                         btol(stack_loc(addr)),
138                         w_in_stack(addr),
139                         displ_sh(st_sh(addr), stack_loc(addr))));
140         }
141         else {
142                 /* just print the byte */
143                 LOG((" d2    %10lu      %3lu                  (%-s)",
144                         addr,
145                         btol(stack_loc(addr)),
146                         displ_sh(st_sh(addr), stack_loc(addr))));
147         }
148 }
149
150 PRIVATE ptr
151 std_rsb(addr)
152         ptr addr;
153 {       /*      Dumps the Return Status Block */
154         ptr dmp_lb;
155         int code;
156         long pi;
157         ptr pc;
158         ptr lb;
159         long lin;
160         ptr fil;
161         char pr_descr[300];
162         
163         if (!in_stack(addr))
164                 return addr;
165
166         dmp_lb = addr - (rsbsize-1);    /* pseudo local base */
167         if (!in_stack(dmp_lb)) {
168                 LOG((" d1 >>RSB: >>>> INCOMPLETE <<<<"));
169                 return dmp_lb;
170         }
171
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);
178
179         if (pi == -1) {
180                 sprintf(pr_descr, "uninit");
181         }
182         else
183         if (pi < NProc) {
184                 sprintf(pr_descr, "(%ld,%ld)",
185                                 pi, (long)proctab[pi].pr_nloc);
186         }
187         else {
188                 sprintf(pr_descr, "%ld >>>> ILLEGAL <<<<", pi);
189         }
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)));
192         
193         LOG((" d2 "));
194         return addr - rsbsize;
195 }
196
197 PRIVATE char *displ_code(rsbcode)
198         int rsbcode;
199 {
200         switch (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<<";
206         }
207         /*NOTREACHED*/
208 }
209
210 PRIVATE std_left_undefs(nundef, addr)
211         int nundef;
212         ptr addr;
213 {
214         /* handle pending undefineds */
215         switch (nundef) {
216         case 1:
217                 break;
218         case 2:
219                 LOG((" d2    %10lu    undef", addr));
220                 break;
221         default:
222                 LOG((" d2         | | |    | | |"));
223                 LOG((" d2    %10lu    undef (%s)",
224                                 addr, displ_undefs(nundef, addr)));
225                 break;
226         }
227 }
228
229 PRIVATE FRA_dump()
230 {
231         register int addr;
232
233         LOG((" d2        FRA: size = %d, %s",
234                         FRASize, FRA_def ? "defined" : "undefined"));
235
236         for (addr = 0; addr < FRASize; addr++) {
237                 FRA_item(addr);
238         }
239 }
240
241 PRIVATE FRA_item(addr)
242         int addr;
243 {
244         if (    is_wordaligned(addr)
245         &&      is_in_FRA(addr, psize)
246         &&      FRAd_bytes(addr, (int)(addr + psize), SH_DATAP|SH_INSP)
247         ) {
248                 /* print a pointer value */
249                 LOG((" d2        FRA[%1d]      %3lu    [%10lu]  (%-s)",
250                         addr,
251                         btol(FRA[addr]),
252                         p_in_FRA(addr),
253                         displ_sh(FRA_sh[addr], FRA[addr])));
254         }
255         else
256         if (    is_wordaligned(addr)
257         &&      is_in_FRA(addr, wsize)
258         &&      FRAd_bytes(addr, (int)(addr + wsize), SH_INT)
259         ) {
260                 /* print a word value */
261                 LOG((" d2        FRA[%1d]      %3lu    [%10ld]  (%-s)",
262                         addr,
263                         btol(FRA[addr]),
264                         w_in_FRA(addr),
265                         displ_sh(FRA_sh[addr], FRA[addr])));
266         }
267         else {
268                 /* just print the byte */
269                 LOG((" d2        FRA[%1d]      %3lu                  (%-s)",
270                         addr,
271                         btol(FRA[addr]),
272                         displ_sh(FRA_sh[addr], FRA[addr])));
273         }
274 }
275
276
277 /******** Global Data Area Dump ********/
278
279 gdad_all(low, high)
280         ptr low, high;
281 {
282         register ptr addr;
283         register int nundef = 0;
284         
285         if (!check_log(" +1 "))
286                 return;
287         
288         if (low == 0 && high == 0)
289                 high = HB;
290         
291         LOG((" +1 "));
292         LOG((" +1 . . GDA_DUMP[%ld/%ld] . . INR = %lu . . GDA_DUMP . .",
293                                 wsize, psize, inr));
294         LOG((" +1 ----------------------------------------------------------------"));
295         LOG((" +1       ADDRESS     BYTE     WORD VALUE   SHADOW"));
296         
297         /* dump global data area contents */
298         addr = low;
299         while (addr < min(HB, high)) {
300                 if (dt_sh(addr) == UNDEFINED) {
301                         if (nundef++ == 0)
302                                 LOG((" +1    %10lu    undef", addr));
303                 }
304                 else {
305                         if (nundef) {
306                                 gdad_left_undefs(nundef, addr-1);
307                                 nundef = 0;
308                         }
309                         gdad_item(addr);
310                 }
311                 addr++;
312         }
313         if (nundef)
314                     gdad_left_undefs(nundef, addr-1);
315         LOG((" +1 ----------------------------------------------------------------"));
316         LOG((" +1 "));
317 }
318
319 PRIVATE gdad_item(addr)
320         ptr addr;
321 {
322         if (    is_wordaligned(addr)
323         &&      is_in_data(addr, psize)
324         &&      dtd_bytes(addr, addr + psize, SH_DATAP|SH_INSP)
325         ) {
326                 /* print a pointer value */
327                 LOG((" +1    %10lu      %3lu    [%10lu]  (%-s)",
328                         addr,
329                         btol(data_loc(addr)),
330                         p_in_data(addr),
331                         displ_sh(dt_sh(addr), data_loc(addr))));
332         }
333         else
334         if (    is_wordaligned(addr)
335         &&      is_in_data(addr, wsize)
336         &&      dtd_bytes(addr, addr + wsize, SH_INT)
337         ) {
338                 /* print a word value */
339                 LOG((" +1    %10lu      %3lu    [%10ld]  (%-s)",
340                         addr,
341                         btol(data_loc(addr)),
342                         w_in_data(addr),
343                         displ_sh(dt_sh(addr), data_loc(addr))));
344         }
345         else {
346                 /* just print the byte */
347                 LOG((" +1    %10lu      %3lu                  (%-s)",
348                         addr,
349                         btol(data_loc(addr)),
350                         displ_sh(dt_sh(addr), data_loc(addr))));
351         }
352 }
353
354 PRIVATE gdad_left_undefs(nundef, addr)
355         int nundef;
356         ptr addr;
357 {
358         /* handle pending undefineds */
359         switch (nundef) {
360         case 1:
361                 break;
362         case 2:
363                 LOG((" +1    %10lu    undef", addr));
364                 break;
365         default:
366                 LOG((" +1         | | |    | | |"));
367                 LOG((" +1    %10lu    undef (%s)",
368                                 addr, displ_undefs(nundef, addr)));
369                 break;
370         }
371 }
372
373 /******** Heap Area Dump ********/
374
375 hpd_all()
376 {
377         register ptr addr;
378         register int nundef = 0;
379         
380         if (!check_log(" *1 "))
381                 return;
382
383         LOG((" *1 "));
384         LOG((" *1 . . HEAP_DUMP[%ld/%ld] . . INR = %lu . . HEAP_DUMP . .",
385                                 wsize, psize, inr));
386         LOG((" *1 ----------------------------------------------------------------"));
387         LOG((" *1       ADDRESS     BYTE     WORD VALUE   SHADOW"));
388         
389         /* dump heap contents */
390         for (addr = HB; addr < HP; addr++) {
391                 if (dt_sh(addr) == UNDEFINED) {
392                         if (nundef++ == 0)
393                                 LOG((" *1    %10lu    undef", addr));
394                 }
395                 else {
396                         if (nundef) {
397                                 hpd_left_undefs(nundef, addr-1);
398                                 nundef = 0;
399                         }
400                         hpd_item(addr);
401                 }
402         }
403         if (nundef)
404                 hpd_left_undefs(nundef, addr-1);
405         LOG((" *1 ----------------------------------------------------------------"));
406         LOG((" *1 "));
407 }
408
409 PRIVATE hpd_item(addr)
410         ptr addr;
411 {
412         if (    is_wordaligned(addr)
413         &&      is_in_data(addr, psize)
414         &&      dtd_bytes(addr, addr + psize, SH_DATAP|SH_INSP)
415         ) {
416                 /* print a pointer value */
417                 LOG((" *1    %10lu      %3lu    [%10lu]  (%-s)",
418                         addr,
419                         btol(data_loc(addr)),
420                         p_in_data(addr),
421                         displ_sh(dt_sh(addr), data_loc(addr))));
422         }
423         else
424         if (    is_wordaligned(addr)
425         &&      is_in_data(addr, wsize)
426         &&      dtd_bytes(addr, addr + wsize, SH_INT)
427         ) {
428                 /* print a word value */
429                 LOG((" *1    %10lu      %3lu    [%10ld]  (%-s)",
430                         addr,
431                         btol(data_loc(addr)),
432                         w_in_data(addr),
433                         displ_sh(dt_sh(addr), data_loc(addr))));
434         }
435         else {
436                 /* just print the byte */
437                 LOG((" *1    %10lu      %3lu                  (%-s)",
438                         addr,
439                         btol(data_loc(addr)),
440                         displ_sh(dt_sh(addr), data_loc(addr))));
441         }
442 }
443
444 PRIVATE hpd_left_undefs(nundef, addr)
445         int nundef;
446         ptr addr;
447 {
448         /* handle pending undefineds */
449         switch (nundef) {
450         case 1:
451                 break;
452         case 2:
453                 LOG((" *1    %10lu    undef", addr));
454                 break;
455         default:
456                 LOG((" *1         | | |    | | |"));
457                 LOG((" *1    %10lu    undef (%s)",
458                                 addr, displ_undefs(nundef, addr)));
459                 break;
460         }
461 }
462
463
464 /* Service routines */
465
466 PRIVATE int std_bytes(low, high, bits)
467         ptr low, high;
468         int bits;
469 {
470         /*      True if all stack bytes from low to high-1 have one of the
471                 bits in bits on.
472         */
473         int byte = bits;
474
475         while (low < high) {
476                 byte &= st_sh(low);
477                 low++;
478         }
479
480         return byte & bits;
481 }
482
483 PRIVATE int dtd_bytes(low, high, bits)
484         ptr low, high;
485         int bits;
486 {
487         /*      True if all data bytes from low to high-1 have one of the
488                 bits in bits on.
489         */
490         int byte = bits;
491
492         while (low < high) {
493                 byte &= dt_sh(low);
494                 low++;
495         }
496
497         return byte & bits;
498 }
499
500 PRIVATE int FRAd_bytes(low, high, bits)
501         int low, high;
502         int bits;
503 {
504         /*      True if all data bytes from low to high-1 have one of the
505                 bits in bits on.
506         */
507         int byte = bits;
508
509         while (low < high) {
510                 byte &= FRA_sh[low];
511                 low++;
512         }
513
514         return byte & bits;
515 }
516
517 PRIVATE char *                          /* transient */
518 displ_undefs(nundef, addr)
519         int nundef;
520         ptr addr;
521 {
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:
524                         |             nundef               |
525                         |left|          wrds            |right
526                         .....|........|........|........|...
527                         a
528                         d
529                         d
530                         r
531                 This takes some arithmetic.
532         */
533         static char buf[30];
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;
537
538         if (wrds == 0) {
539                 sprintf(buf, "%d byte%s",
540                         nundef, nundef == 1 ? "" : "s");
541         }
542         else if (left == 0 && right == 0) {
543                 sprintf(buf, "%d word%s",
544                         wrds, wrds == 1 ? "" : "s");
545         }
546         else if (left == 0) {
547                 sprintf(buf, "%d word%s + %d byte%s",
548                         wrds, wrds == 1 ? "" : "s",
549                         right, right == 1 ? "" : "s");
550         }
551         else if (right == 0) {
552                 sprintf(buf, "%d byte%s + %d word%s",
553                         left, left == 1 ? "" : "s",
554                         wrds, wrds == 1 ? "" : "s");
555         }
556         else {
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");
561         }
562         return buf;
563 }
564
565 PRIVATE char *
566 displ_fil(fil)                          /* transient */
567         ptr fil;
568 {       /*      Returns a buffer containing a representation of the
569                 filename derived from FIL-value fil.
570         */
571         static char buf[40];
572         char *bp = &buf[0];
573         int ch;
574         
575         if (!fil)
576                 return "NULL";
577         if (fil >= HB)
578                 return "***NOT IN GDA***";
579         
580         *bp++ = '"';
581         while (in_gda(fil) && (ch = data_loc(fil))) {
582                 if (bp < &buf[sizeof buf-1]) {
583                         *bp++ = (ch < 040 || ch > 126 ? '?' : ch);
584                 }
585                 fil++;
586         }
587         if (bp < &buf[sizeof buf-1])
588                 *bp++ = '"';
589         *bp++ = '\0';
590         return &buf[0];
591 }
592
593 PRIVATE char *
594 displ_sh(shadow, byte)                          /* transient */
595         char shadow;
596         int byte;
597 {       /*      Returns a buffer containing a description of the
598                 shadow byte.
599         */
600         static char buf[32];
601         register char *bufp;
602         int check = 0;
603
604         bufp = buf;
605         if (shadow & SH_INT) {
606                 *bufp++ = 'I';
607                 *bufp++ = 'n';
608                 check++;
609         }
610         if (shadow & SH_FLOAT) {
611                 *bufp++ = 'F';
612                 *bufp++ = 'l';
613         }
614         if (shadow & SH_DATAP) {
615                 *bufp++ = 'D';
616                 *bufp++ = 'p';
617         }
618         if (shadow & SH_INSP) {
619                 *bufp++ = 'I';
620                 *bufp++ = 'p';
621         }
622
623         if (shadow & SH_PROT) {
624                 *bufp++ = ',';
625                 *bufp++ = ' ';
626                 *bufp++ = 'P';
627                 *bufp++ = 'r';
628                 *bufp++ = 'o';
629                 *bufp++ = 't';
630         }
631
632         if (check && isascii(byte) && isprint(byte)) {
633                 *bufp++ = ',';
634                 *bufp++ = ' ';
635                 *bufp++ = byte;
636                 *bufp++ = ' ';
637         }
638         *bufp = 0;
639         return (buf);
640 }
641
642 #endif  /* LOGGING */
643