Add em22 compile, change EM machine executable format to put proc table in text
[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                 struct proc pt;
185
186                 read_proctab(pi, &pt);
187                 sprintf(pr_descr, "(%ld,%ld)",
188                                 pi, (long)pt.pr_nloc);
189         }
190         else {
191                 sprintf(pr_descr, "%ld >>>> ILLEGAL <<<<", pi);
192         }
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)));
195         
196         LOG((" d2 "));
197         return addr - rsbsize;
198 }
199
200 PRIVATE char *displ_code(rsbcode)
201         int rsbcode;
202 {
203         switch (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<<";
209         }
210         /*NOTREACHED*/
211 }
212
213 PRIVATE std_left_undefs(nundef, addr)
214         int nundef;
215         ptr addr;
216 {
217         /* handle pending undefineds */
218         switch (nundef) {
219         case 1:
220                 break;
221         case 2:
222                 LOG((" d2    %10lu    undef", addr));
223                 break;
224         default:
225                 LOG((" d2         | | |    | | |"));
226                 LOG((" d2    %10lu    undef (%s)",
227                                 addr, displ_undefs(nundef, addr)));
228                 break;
229         }
230 }
231
232 PRIVATE FRA_dump()
233 {
234         register int addr;
235
236         LOG((" d2        FRA: size = %d, %s",
237                         FRASize, FRA_def ? "defined" : "undefined"));
238
239         for (addr = 0; addr < FRASize; addr++) {
240                 FRA_item(addr);
241         }
242 }
243
244 PRIVATE FRA_item(addr)
245         int addr;
246 {
247         if (    is_wordaligned(addr)
248         &&      is_in_FRA(addr, psize)
249         &&      FRAd_bytes(addr, (int)(addr + psize), SH_DATAP|SH_INSP)
250         ) {
251                 /* print a pointer value */
252                 LOG((" d2        FRA[%1d]      %3lu    [%10lu]  (%-s)",
253                         addr,
254                         btol(FRA[addr]),
255                         p_in_FRA(addr),
256                         displ_sh(FRA_sh[addr], FRA[addr])));
257         }
258         else
259         if (    is_wordaligned(addr)
260         &&      is_in_FRA(addr, wsize)
261         &&      FRAd_bytes(addr, (int)(addr + wsize), SH_INT)
262         ) {
263                 /* print a word value */
264                 LOG((" d2        FRA[%1d]      %3lu    [%10ld]  (%-s)",
265                         addr,
266                         btol(FRA[addr]),
267                         w_in_FRA(addr),
268                         displ_sh(FRA_sh[addr], FRA[addr])));
269         }
270         else {
271                 /* just print the byte */
272                 LOG((" d2        FRA[%1d]      %3lu                  (%-s)",
273                         addr,
274                         btol(FRA[addr]),
275                         displ_sh(FRA_sh[addr], FRA[addr])));
276         }
277 }
278
279
280 /******** Global Data Area Dump ********/
281
282 gdad_all(low, high)
283         ptr low, high;
284 {
285         register ptr addr;
286         register int nundef = 0;
287         
288         if (!check_log(" +1 "))
289                 return;
290         
291         if (low == 0 && high == 0)
292                 high = HB;
293         
294         LOG((" +1 "));
295         LOG((" +1 . . GDA_DUMP[%ld/%ld] . . INR = %lu . . GDA_DUMP . .",
296                                 wsize, psize, inr));
297         LOG((" +1 ----------------------------------------------------------------"));
298         LOG((" +1       ADDRESS     BYTE     WORD VALUE   SHADOW"));
299         
300         /* dump global data area contents */
301         addr = low;
302         while (addr < min(HB, high)) {
303                 if (dt_sh(addr) == UNDEFINED) {
304                         if (nundef++ == 0)
305                                 LOG((" +1    %10lu    undef", addr));
306                 }
307                 else {
308                         if (nundef) {
309                                 gdad_left_undefs(nundef, addr-1);
310                                 nundef = 0;
311                         }
312                         gdad_item(addr);
313                 }
314                 addr++;
315         }
316         if (nundef)
317                     gdad_left_undefs(nundef, addr-1);
318         LOG((" +1 ----------------------------------------------------------------"));
319         LOG((" +1 "));
320 }
321
322 PRIVATE gdad_item(addr)
323         ptr addr;
324 {
325         if (    is_wordaligned(addr)
326         &&      is_in_data(addr, psize)
327         &&      dtd_bytes(addr, addr + psize, SH_DATAP|SH_INSP)
328         ) {
329                 /* print a pointer value */
330                 LOG((" +1    %10lu      %3lu    [%10lu]  (%-s)",
331                         addr,
332                         btol(data_loc(addr)),
333                         p_in_data(addr),
334                         displ_sh(dt_sh(addr), data_loc(addr))));
335         }
336         else
337         if (    is_wordaligned(addr)
338         &&      is_in_data(addr, wsize)
339         &&      dtd_bytes(addr, addr + wsize, SH_INT)
340         ) {
341                 /* print a word value */
342                 LOG((" +1    %10lu      %3lu    [%10ld]  (%-s)",
343                         addr,
344                         btol(data_loc(addr)),
345                         w_in_data(addr),
346                         displ_sh(dt_sh(addr), data_loc(addr))));
347         }
348         else {
349                 /* just print the byte */
350                 LOG((" +1    %10lu      %3lu                  (%-s)",
351                         addr,
352                         btol(data_loc(addr)),
353                         displ_sh(dt_sh(addr), data_loc(addr))));
354         }
355 }
356
357 PRIVATE gdad_left_undefs(nundef, addr)
358         int nundef;
359         ptr addr;
360 {
361         /* handle pending undefineds */
362         switch (nundef) {
363         case 1:
364                 break;
365         case 2:
366                 LOG((" +1    %10lu    undef", addr));
367                 break;
368         default:
369                 LOG((" +1         | | |    | | |"));
370                 LOG((" +1    %10lu    undef (%s)",
371                                 addr, displ_undefs(nundef, addr)));
372                 break;
373         }
374 }
375
376 /******** Heap Area Dump ********/
377
378 hpd_all()
379 {
380         register ptr addr;
381         register int nundef = 0;
382         
383         if (!check_log(" *1 "))
384                 return;
385
386         LOG((" *1 "));
387         LOG((" *1 . . HEAP_DUMP[%ld/%ld] . . INR = %lu . . HEAP_DUMP . .",
388                                 wsize, psize, inr));
389         LOG((" *1 ----------------------------------------------------------------"));
390         LOG((" *1       ADDRESS     BYTE     WORD VALUE   SHADOW"));
391         
392         /* dump heap contents */
393         for (addr = HB; addr < HP; addr++) {
394                 if (dt_sh(addr) == UNDEFINED) {
395                         if (nundef++ == 0)
396                                 LOG((" *1    %10lu    undef", addr));
397                 }
398                 else {
399                         if (nundef) {
400                                 hpd_left_undefs(nundef, addr-1);
401                                 nundef = 0;
402                         }
403                         hpd_item(addr);
404                 }
405         }
406         if (nundef)
407                 hpd_left_undefs(nundef, addr-1);
408         LOG((" *1 ----------------------------------------------------------------"));
409         LOG((" *1 "));
410 }
411
412 PRIVATE hpd_item(addr)
413         ptr addr;
414 {
415         if (    is_wordaligned(addr)
416         &&      is_in_data(addr, psize)
417         &&      dtd_bytes(addr, addr + psize, SH_DATAP|SH_INSP)
418         ) {
419                 /* print a pointer value */
420                 LOG((" *1    %10lu      %3lu    [%10lu]  (%-s)",
421                         addr,
422                         btol(data_loc(addr)),
423                         p_in_data(addr),
424                         displ_sh(dt_sh(addr), data_loc(addr))));
425         }
426         else
427         if (    is_wordaligned(addr)
428         &&      is_in_data(addr, wsize)
429         &&      dtd_bytes(addr, addr + wsize, SH_INT)
430         ) {
431                 /* print a word value */
432                 LOG((" *1    %10lu      %3lu    [%10ld]  (%-s)",
433                         addr,
434                         btol(data_loc(addr)),
435                         w_in_data(addr),
436                         displ_sh(dt_sh(addr), data_loc(addr))));
437         }
438         else {
439                 /* just print the byte */
440                 LOG((" *1    %10lu      %3lu                  (%-s)",
441                         addr,
442                         btol(data_loc(addr)),
443                         displ_sh(dt_sh(addr), data_loc(addr))));
444         }
445 }
446
447 PRIVATE hpd_left_undefs(nundef, addr)
448         int nundef;
449         ptr addr;
450 {
451         /* handle pending undefineds */
452         switch (nundef) {
453         case 1:
454                 break;
455         case 2:
456                 LOG((" *1    %10lu    undef", addr));
457                 break;
458         default:
459                 LOG((" *1         | | |    | | |"));
460                 LOG((" *1    %10lu    undef (%s)",
461                                 addr, displ_undefs(nundef, addr)));
462                 break;
463         }
464 }
465
466
467 /* Service routines */
468
469 PRIVATE int std_bytes(low, high, bits)
470         ptr low, high;
471         int bits;
472 {
473         /*      True if all stack bytes from low to high-1 have one of the
474                 bits in bits on.
475         */
476         int byte = bits;
477
478         while (low < high) {
479                 byte &= st_sh(low);
480                 low++;
481         }
482
483         return byte & bits;
484 }
485
486 PRIVATE int dtd_bytes(low, high, bits)
487         ptr low, high;
488         int bits;
489 {
490         /*      True if all data bytes from low to high-1 have one of the
491                 bits in bits on.
492         */
493         int byte = bits;
494
495         while (low < high) {
496                 byte &= dt_sh(low);
497                 low++;
498         }
499
500         return byte & bits;
501 }
502
503 PRIVATE int FRAd_bytes(low, high, bits)
504         int low, high;
505         int bits;
506 {
507         /*      True if all data bytes from low to high-1 have one of the
508                 bits in bits on.
509         */
510         int byte = bits;
511
512         while (low < high) {
513                 byte &= FRA_sh[low];
514                 low++;
515         }
516
517         return byte & bits;
518 }
519
520 PRIVATE char *                          /* transient */
521 displ_undefs(nundef, addr)
522         int nundef;
523         ptr addr;
524 {
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:
527                         |             nundef               |
528                         |left|          wrds            |right
529                         .....|........|........|........|...
530                         a
531                         d
532                         d
533                         r
534                 This takes some arithmetic.
535         */
536         static char buf[30];
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;
540
541         if (wrds == 0) {
542                 sprintf(buf, "%d byte%s",
543                         nundef, nundef == 1 ? "" : "s");
544         }
545         else if (left == 0 && right == 0) {
546                 sprintf(buf, "%d word%s",
547                         wrds, wrds == 1 ? "" : "s");
548         }
549         else if (left == 0) {
550                 sprintf(buf, "%d word%s + %d byte%s",
551                         wrds, wrds == 1 ? "" : "s",
552                         right, right == 1 ? "" : "s");
553         }
554         else if (right == 0) {
555                 sprintf(buf, "%d byte%s + %d word%s",
556                         left, left == 1 ? "" : "s",
557                         wrds, wrds == 1 ? "" : "s");
558         }
559         else {
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");
564         }
565         return buf;
566 }
567
568 PRIVATE char *
569 displ_fil(fil)                          /* transient */
570         ptr fil;
571 {       /*      Returns a buffer containing a representation of the
572                 filename derived from FIL-value fil.
573         */
574         static char buf[40];
575         char *bp = &buf[0];
576         int ch;
577         
578         if (!fil)
579                 return "NULL";
580         if (fil >= HB)
581                 return "***NOT IN GDA***";
582         
583         *bp++ = '"';
584         while (in_gda(fil) && (ch = data_loc(fil))) {
585                 if (bp < &buf[sizeof buf-1]) {
586                         *bp++ = (ch < 040 || ch > 126 ? '?' : ch);
587                 }
588                 fil++;
589         }
590         if (bp < &buf[sizeof buf-1])
591                 *bp++ = '"';
592         *bp++ = '\0';
593         return &buf[0];
594 }
595
596 PRIVATE char *
597 displ_sh(shadow, byte)                          /* transient */
598         char shadow;
599         int byte;
600 {       /*      Returns a buffer containing a description of the
601                 shadow byte.
602         */
603         static char buf[32];
604         register char *bufp;
605         int check = 0;
606
607         bufp = buf;
608         if (shadow & SH_INT) {
609                 *bufp++ = 'I';
610                 *bufp++ = 'n';
611                 check++;
612         }
613         if (shadow & SH_FLOAT) {
614                 *bufp++ = 'F';
615                 *bufp++ = 'l';
616         }
617         if (shadow & SH_DATAP) {
618                 *bufp++ = 'D';
619                 *bufp++ = 'p';
620         }
621         if (shadow & SH_INSP) {
622                 *bufp++ = 'I';
623                 *bufp++ = 'p';
624         }
625
626         if (shadow & SH_PROT) {
627                 *bufp++ = ',';
628                 *bufp++ = ' ';
629                 *bufp++ = 'P';
630                 *bufp++ = 'r';
631                 *bufp++ = 'o';
632                 *bufp++ = 't';
633         }
634
635         if (check && isascii(byte) && isprint(byte)) {
636                 *bufp++ = ',';
637                 *bufp++ = ' ';
638                 *bufp++ = byte;
639                 *bufp++ = ' ';
640         }
641         *bufp = 0;
642         return (buf);
643 }
644
645 #endif  /* LOGGING */
646