]> git.sur5r.net Git - cc65/blob - src/od65/dump.c
add gotox, gotoy, and gotoxy
[cc65] / src / od65 / dump.c
1 /*****************************************************************************/
2 /*                                                                           */
3 /*                                  dump.c                                   */
4 /*                                                                           */
5 /*          Dump subroutines for the od65 object file dump utility           */
6 /*                                                                           */
7 /*                                                                           */
8 /*                                                                           */
9 /* (C) 2002-2012, Ullrich von Bassewitz                                      */
10 /*                Roemerstrasse 52                                           */
11 /*                D-70794 Filderstadt                                        */
12 /* EMail:         uz@cc65.org                                                */
13 /*                                                                           */
14 /*                                                                           */
15 /* This software is provided 'as-is', without any expressed or implied       */
16 /* warranty.  In no event will the authors be held liable for any damages    */
17 /* arising from the use of this software.                                    */
18 /*                                                                           */
19 /* Permission is granted to anyone to use this software for any purpose,     */
20 /* including commercial applications, and to alter it and redistribute it    */
21 /* freely, subject to the following restrictions:                            */
22 /*                                                                           */
23 /* 1. The origin of this software must not be misrepresented; you must not   */
24 /*    claim that you wrote the original software. If you use this software   */
25 /*    in a product, an acknowledgment in the product documentation would be  */
26 /*    appreciated but is not required.                                       */
27 /* 2. Altered source versions must be plainly marked as such, and must not   */
28 /*    be misrepresented as being the original software.                      */
29 /* 3. This notice may not be removed or altered from any source              */
30 /*    distribution.                                                          */
31 /*                                                                           */
32 /*****************************************************************************/
33
34
35
36 #include <string.h>
37 #include <time.h>
38
39 /* common */
40 #include "addrsize.h"
41 #include "cddefs.h"
42 #include "coll.h"
43 #include "exprdefs.h"
44 #include "filepos.h"
45 #include "lidefs.h"
46 #include "objdefs.h"
47 #include "optdefs.h"
48 #include "scopedefs.h"
49 #include "symdefs.h"
50 #include "xmalloc.h"
51
52 /* od65 */
53 #include "error.h"
54 #include "fileio.h"
55 #include "dump.h"
56
57
58
59 /*****************************************************************************/
60 /*                                   Code                                    */
61 /*****************************************************************************/
62
63
64
65 static void DestroyStrPool (Collection* C)
66 /* Free all strings in the given pool plus the item pointers. Note: The
67  * collection may not be reused later.
68  */
69 {
70     unsigned I;
71     for (I = 0; I < CollCount (C); ++I) {
72         xfree (CollAtUnchecked (C, I));
73     }
74     DoneCollection (C);
75 }
76
77
78
79 static const char* GetString (const Collection* C, unsigned Index)
80 /* Get a string from a collection. In fact, this function calls CollConstAt,
81  * but will print a somewhat more readable error message if the index is out
82  * of bounds.
83  */
84 {
85     if (Index >= CollCount (C)) {
86         Error ("Invalid string index (%u) - file corrupt!", Index);
87     }
88     return CollConstAt (C, Index);
89 }
90
91
92
93 static void DumpObjHeaderSection (const char* Name,
94                                   unsigned long Offset,
95                                   unsigned long Size)
96 /* Dump a header section */
97 {
98     printf ("    %s:\n", Name);
99     printf ("      Offset:%24lu\n", Offset);
100     printf ("      Size:  %24lu\n", Size);
101 }
102
103
104
105 static char* TimeToStr (unsigned long Time)
106 /* Convert the time into a string and return it */
107 {
108     /* Get the time and convert to string */
109     time_t T = (time_t) Time;
110     char*  S = asctime (localtime (&T));
111
112     /* Remove the trailing newline */
113     unsigned Len = strlen (S);
114     if (Len > 0 && S[Len-1] == '\n') {
115         S[Len-1 ] = '\0';
116     }
117
118     /* Return the time string */
119     return S;
120 }
121
122
123
124 static void SkipLineInfoList (FILE* F)
125 /* Skip a line info list from the given file */
126 {
127     /* Count preceeds the list */
128     unsigned long Count = ReadVar (F);
129
130     /* Skip indices */
131     while (Count--) {
132         (void) ReadVar (F);
133     }
134 }
135
136
137
138 static void SkipSpanList (FILE* F)
139 /* Skip a span list from the given file */
140 {
141     /* Count preceeds the list */
142     unsigned long Count = ReadVar (F);
143
144     /* Skip indices */
145     while (Count--) {
146         (void) ReadVar (F);
147     }
148 }
149
150
151
152 static void SkipExpr (FILE* F)
153 /* Skip an expression from the given file */
154 {
155     /* Read the node tag and handle NULL nodes */
156     unsigned char Op = Read8 (F);
157     if (Op == EXPR_NULL) {
158         return;
159     }
160
161     /* Check the tag and handle the different expression types */
162     if (EXPR_IS_LEAF (Op)) {
163         switch (Op) {
164
165             case EXPR_LITERAL:
166                 (void) Read32Signed (F);
167                 break;
168
169             case EXPR_SYMBOL:
170                 /* Read the import number */
171                 (void) ReadVar (F);
172                 break;
173
174             case EXPR_SECTION:
175             case EXPR_BANK:
176                 /* Read the segment number */
177                 (void) ReadVar (F);
178                 break;
179
180             default:
181                 Error ("Invalid expression op: %02X", Op);
182
183         }
184
185     } else {
186
187         /* Not a leaf node */
188         SkipExpr (F);
189         SkipExpr (F);
190     }
191 }
192
193
194
195 static const char* GetExportFlags (unsigned Flags, const unsigned char* ConDes)
196 /* Get the export flags as a (static) string */
197 {
198     /* Static buffer */
199     static char TypeDesc[256];
200     static char* T;
201
202     unsigned Count;
203     unsigned I;
204
205     /* Symbol type */
206     TypeDesc[0] = '\0';
207     switch (Flags & SYM_MASK_TYPE) {
208         case SYM_STD:         strcat (TypeDesc, "SYM_STD");         break;
209         case SYM_CHEAP_LOCAL: strcat (TypeDesc, "SYM_CHEAP_LOCAL"); break;
210     }
211
212     /* Symbol usage */
213     switch (Flags & SYM_MASK_LABEL) {
214         case SYM_EQUATE: strcat (TypeDesc, ",SYM_EQUATE"); break;
215         case SYM_LABEL:  strcat (TypeDesc, ",SYM_LABEL");  break;
216     }
217
218     /* Type of expression */
219     switch (Flags & SYM_MASK_VAL) {
220         case SYM_CONST: strcat (TypeDesc, ",SYM_CONST"); break;
221         case SYM_EXPR:  strcat (TypeDesc, ",SYM_EXPR");   break;
222     }
223
224     /* Size available? */
225     if (SYM_HAS_SIZE (Flags)) {
226         strcat (TypeDesc, ",SYM_SIZE");
227     }
228
229
230     /* Constructor/destructor declarations */
231     T = TypeDesc + strlen (TypeDesc);
232     Count = SYM_GET_CONDES_COUNT (Flags);
233     if (Count > 0 && ConDes) {
234         T += sprintf (T, ",SYM_CONDES=");
235         for (I = 0; I < Count; ++I) {
236             unsigned Type = CD_GET_TYPE (ConDes[I]);
237             unsigned Prio = CD_GET_PRIO (ConDes[I]);
238             if (I > 0) {
239                 *T++ = ',';
240             }
241             T += sprintf (T, "[%u,%u]", Type, Prio);
242         }
243     }
244
245     /* Return the result */
246     return TypeDesc;
247 }
248
249
250
251 static const char* GetScopeType (unsigned Type)
252 /* Return the name of a scope type */
253 {
254     switch (Type) {
255         case SCOPE_GLOBAL:      return "Global scope";
256         case SCOPE_FILE:        return "File scope";
257         case SCOPE_SCOPE:       return ".SCOPE or .PROC";
258         case SCOPE_STRUCT:      return ".STRUCT";
259         case SCOPE_ENUM:        return ".ENUM";
260         case SCOPE_UNDEF:       return "Undefined";
261         default:                return "Unknown scope type";
262     }
263 }
264
265
266
267 void DumpObjHeader (FILE* F, unsigned long Offset)
268 /* Dump the header of the given object file */
269 {
270     ObjHeader H;
271
272     /* Seek to the header position */
273     FileSetPos (F, Offset);
274
275     /* Read the header */
276     ReadObjHeader (F, &H);
277
278     /* Now dump the information */
279
280     /* Output a header */
281     printf ("  Header:\n");
282
283     /* Magic */
284     printf ("    Magic:%17s0x%08lX\n", "", H.Magic);
285
286     /* Version */
287     printf ("    Version:%25u\n", H.Version);
288
289     /* Flags */
290     printf ("    Flags:%21s0x%04X  (", "", H.Flags);
291     if (H.Flags & OBJ_FLAGS_DBGINFO) {
292         printf ("OBJ_FLAGS_DBGINFO");
293     }
294     printf (")\n");
295
296     /* Options */
297     DumpObjHeaderSection ("Options", H.OptionOffs, H.OptionSize);
298
299     /* Files */
300     DumpObjHeaderSection ("Files", H.FileOffs, H.FileSize);
301
302     /* Segments */
303     DumpObjHeaderSection ("Segments", H.SegOffs, H.SegSize);
304
305     /* Imports */
306     DumpObjHeaderSection ("Imports", H.ImportOffs, H.ImportSize);
307
308     /* Exports */
309     DumpObjHeaderSection ("Exports", H.ExportOffs, H.ExportSize);
310
311     /* Debug symbols */
312     DumpObjHeaderSection ("Debug symbols", H.DbgSymOffs, H.DbgSymSize);
313
314     /* Line infos */
315     DumpObjHeaderSection ("Line infos", H.LineInfoOffs, H.LineInfoSize);
316
317     /* String pool */
318     DumpObjHeaderSection ("String pool", H.StrPoolOffs, H.StrPoolSize);
319
320     /* Assertions */
321     DumpObjHeaderSection ("Assertions", H.AssertOffs, H.AssertSize);
322
323     /* Scopes */
324     DumpObjHeaderSection ("Scopes", H.ScopeOffs, H.ScopeSize);
325 }
326
327
328
329 void DumpObjOptions (FILE* F, unsigned long Offset)
330 /* Dump the file options */
331 {
332     ObjHeader  H;
333     Collection StrPool = AUTO_COLLECTION_INITIALIZER;
334     unsigned   Count;
335     unsigned   I;
336
337     /* Seek to the header position and read the header */
338     FileSetPos (F, Offset);
339     ReadObjHeader (F, &H);
340
341     /* Seek to the start of the string pool and read it */
342     FileSetPos (F, Offset + H.StrPoolOffs);
343     ReadStrPool (F, &StrPool);
344
345     /* Seek to the start of the options */
346     FileSetPos (F, Offset + H.OptionOffs);
347
348     /* Output a header */
349     printf ("  Options:\n");
350
351     /* Read the number of options and print it */
352     Count = ReadVar (F);
353     printf ("    Count:%27u\n", Count);
354
355     /* Read and print all options */
356     for (I = 0; I < Count; ++I) {
357
358         const char*   ArgStr;
359         unsigned      ArgLen;
360
361         /* Read the type of the option and the value */
362         unsigned char Type = Read8 (F);
363         unsigned long Val  = ReadVar (F);
364
365         /* Get the type of the argument */
366         unsigned char ArgType = Type & OPT_ARGMASK;
367
368         /* Determine which option follows */
369         const char* TypeDesc;
370         switch (Type) {
371             case OPT_COMMENT:   TypeDesc = "OPT_COMMENT";       break;
372             case OPT_AUTHOR:    TypeDesc = "OPT_AUTHOR";        break;
373             case OPT_TRANSLATOR:TypeDesc = "OPT_TRANSLATOR";    break;
374             case OPT_COMPILER:  TypeDesc = "OPT_COMPILER";      break;
375             case OPT_OS:        TypeDesc = "OPT_OS";            break;
376             case OPT_DATETIME:  TypeDesc = "OPT_DATETIME";      break;
377             default:            TypeDesc = "OPT_UNKNOWN";       break;
378         }
379
380         /* Print the header */
381         printf ("    Index:%27u\n", I);
382
383         /* Print the data */
384         printf ("      Type:%22s0x%02X  (%s)\n", "", Type, TypeDesc);
385         switch (ArgType) {
386
387             case OPT_ARGSTR:
388                 ArgStr = GetString (&StrPool, Val);
389                 ArgLen = strlen (ArgStr);
390                 printf ("      Data:%*s\"%s\"\n", (int)(24-ArgLen), "", ArgStr);
391                 break;
392
393             case OPT_ARGNUM:
394                 printf ("      Data:%26lu", Val);
395                 if (Type == OPT_DATETIME) {
396                     /* Print the time as a string */
397                     printf ("  (%s)", TimeToStr (Val));
398                 }
399                 printf ("\n");
400                 break;
401
402             default:
403                 /* Unknown argument type. This means that we cannot determine
404                  * the option length, so we cannot proceed.
405                  */
406                 Error ("Unknown option type: 0x%02X", Type);
407                 break;
408         }
409     }
410
411     /* Destroy the string pool */
412     DestroyStrPool (&StrPool);
413 }
414
415
416
417 void DumpObjFiles (FILE* F, unsigned long Offset)
418 /* Dump the source files */
419 {
420     ObjHeader  H;
421     Collection StrPool = AUTO_COLLECTION_INITIALIZER;
422     unsigned   Count;
423     unsigned   I;
424
425     /* Seek to the header position and read the header */
426     FileSetPos (F, Offset);
427     ReadObjHeader (F, &H);
428
429     /* Seek to the start of the string pool and read it */
430     FileSetPos (F, Offset + H.StrPoolOffs);
431     ReadStrPool (F, &StrPool);
432
433     /* Seek to the start of the source files */
434     FileSetPos (F, Offset + H.FileOffs);
435
436     /* Output a header */
437     printf ("  Files:\n");
438
439     /* Read the number of files and print it */
440     Count = ReadVar (F);
441     printf ("    Count:%27u\n", Count);
442
443     /* Read and print all files */
444     for (I = 0; I < Count; ++I) {
445
446         /* Read the data for one file */
447         const char*   Name  = GetString (&StrPool, ReadVar (F));
448         unsigned long MTime = Read32 (F);
449         unsigned long Size  = ReadVar (F);
450         unsigned      Len   = strlen (Name);
451
452         /* Print the header */
453         printf ("    Index:%27u\n", I);
454
455         /* Print the data */
456         printf ("      Name:%*s\"%s\"\n", (int)(24-Len), "", Name);
457         printf ("      Size:%26lu\n", Size);
458         printf ("      Modification time:%13lu  (%s)\n", MTime, TimeToStr (MTime));
459     }
460
461     /* Destroy the string pool */
462     DestroyStrPool (&StrPool);
463 }
464
465
466
467 void DumpObjSegments (FILE* F, unsigned long Offset)
468 /* Dump the segments in the object file */
469 {
470     ObjHeader  H;
471     Collection StrPool = AUTO_COLLECTION_INITIALIZER;
472     unsigned   Count;
473     unsigned   I;
474
475     /* Seek to the header position and read the header */
476     FileSetPos (F, Offset);
477     ReadObjHeader (F, &H);
478
479     /* Seek to the start of the string pool and read it */
480     FileSetPos (F, Offset + H.StrPoolOffs);
481     ReadStrPool (F, &StrPool);
482
483     /* Seek to the start of the segments */
484     FileSetPos (F, Offset + H.SegOffs);
485
486     /* Output a header */
487     printf ("  Segments:\n");
488
489     /* Read the number of segments and print it */
490     Count = ReadVar (F);
491     printf ("    Count:%27u\n", Count);
492
493     /* Read and print all segments */
494     for (I = 0; I < Count; ++I) {
495
496         /* Read the data for one segments */
497         unsigned long DataSize  = Read32 (F);
498         unsigned long NextSeg   = ftell (F) + DataSize;
499         const char*   Name      = GetString (&StrPool, ReadVar (F));
500         unsigned      Len       = strlen (Name);
501         unsigned      Flags     = ReadVar (F);
502         unsigned long Size      = ReadVar (F);
503         unsigned long Align     = ReadVar (F);
504         unsigned char AddrSize  = Read8 (F);
505         unsigned long FragCount = ReadVar (F);
506
507         /* Print the header */
508         printf ("    Index:%27u\n", I);
509
510         /* Print the data */
511         printf ("      Name:%*s\"%s\"\n", (int)(24-Len), "", Name);
512         printf ("      Flags:%25u\n", Flags);
513         printf ("      Size:%26lu\n", Size);
514         printf ("      Alignment:%21lu\n", Align);
515         printf ("      Address size:%14s0x%02X  (%s)\n", "", AddrSize,
516                 AddrSizeToStr (AddrSize));
517         printf ("      Fragment count:%16lu\n", FragCount);
518
519         /* Seek to the end of the segment data (start of next) */
520         FileSetPos (F, NextSeg);
521     }
522
523     /* Destroy the string pool */
524     DestroyStrPool (&StrPool);
525 }
526
527
528
529 void DumpObjImports (FILE* F, unsigned long Offset)
530 /* Dump the imports in the object file */
531 {
532     ObjHeader  H;
533     Collection StrPool = AUTO_COLLECTION_INITIALIZER;
534     unsigned   Count;
535     unsigned   I;
536
537     /* Seek to the header position and read the header */
538     FileSetPos (F, Offset);
539     ReadObjHeader (F, &H);
540
541     /* Seek to the start of the string pool and read it */
542     FileSetPos (F, Offset + H.StrPoolOffs);
543     ReadStrPool (F, &StrPool);
544
545     /* Seek to the start of the imports */
546     FileSetPos (F, Offset + H.ImportOffs);
547
548     /* Output a header */
549     printf ("  Imports:\n");
550
551     /* Read the number of imports and print it */
552     Count = ReadVar (F);
553     printf ("    Count:%27u\n", Count);
554
555     /* Read and print all imports */
556     for (I = 0; I < Count; ++I) {
557
558         /* Read the data for one import */
559         unsigned char AddrSize = Read8 (F);
560         const char*   Name     = GetString (&StrPool, ReadVar (F));
561         unsigned      Len      = strlen (Name);
562
563         /* Skip both line info lists */
564         SkipLineInfoList (F);
565         SkipLineInfoList (F);
566
567         /* Print the header */
568         printf ("    Index:%27u\n", I);
569
570         /* Print the data */
571         printf ("      Address size:%14s0x%02X  (%s)\n", "", AddrSize,
572                 AddrSizeToStr (AddrSize));
573         printf ("      Name:%*s\"%s\"\n", (int)(24-Len), "", Name);
574     }
575
576     /* Destroy the string pool */
577     DestroyStrPool (&StrPool);
578 }
579
580
581
582 void DumpObjExports (FILE* F, unsigned long Offset)
583 /* Dump the exports in the object file */
584 {
585     ObjHeader   H;
586     Collection  StrPool = AUTO_COLLECTION_INITIALIZER;
587     unsigned    Count;
588     unsigned    I;
589
590     /* Seek to the header position and read the header */
591     FileSetPos (F, Offset);
592     ReadObjHeader (F, &H);
593
594     /* Seek to the start of the string pool and read it */
595     FileSetPos (F, Offset + H.StrPoolOffs);
596     ReadStrPool (F, &StrPool);
597
598     /* Seek to the start of the exports */
599     FileSetPos (F, Offset + H.ExportOffs);
600
601     /* Output a header */
602     printf ("  Exports:\n");
603
604     /* Read the number of exports and print it */
605     Count = ReadVar (F);
606     printf ("    Count:%27u\n", Count);
607
608     /* Read and print all exports */
609     for (I = 0; I < Count; ++I) {
610
611         unsigned long   Value = 0;
612         unsigned long   Size = 0;
613         unsigned char   ConDes[CD_TYPE_COUNT];
614         const char*     Name;
615         unsigned        Len;
616
617
618         /* Read the data for one export */
619         unsigned Type          = ReadVar (F);
620         unsigned char AddrSize = Read8 (F);
621         ReadData (F, ConDes, SYM_GET_CONDES_COUNT (Type));
622         Name  = GetString (&StrPool, ReadVar (F));
623         Len   = strlen (Name);
624         if (SYM_IS_CONST (Type)) {
625             Value = Read32 (F);
626         } else {
627             SkipExpr (F);
628         }
629         if (SYM_HAS_SIZE (Type)) {
630             Size = ReadVar (F);
631         }
632
633         /* Skip both line infos lists */
634         SkipLineInfoList (F);
635         SkipLineInfoList (F);
636
637         /* Print the header */
638         printf ("    Index:%27u\n", I);
639
640         /* Print the data */
641         printf ("      Type:%22s0x%02X  (%s)\n", "", Type, GetExportFlags (Type, ConDes));
642         printf ("      Address size:%14s0x%02X  (%s)\n", "", AddrSize,
643                 AddrSizeToStr (AddrSize));
644         printf ("      Name:%*s\"%s\"\n", (int)(24-Len), "", Name);
645         if (SYM_IS_CONST (Type)) {
646             printf ("      Value:%15s0x%08lX  (%lu)\n", "", Value, Value);
647         }
648         if (SYM_HAS_SIZE (Type)) {
649             printf ("      Size:%16s0x%04lX  (%lu)\n", "", Size, Size);
650         }
651     }
652
653     /* Destroy the string pool */
654     DestroyStrPool (&StrPool);
655 }
656
657
658
659 void DumpObjDbgSyms (FILE* F, unsigned long Offset)
660 /* Dump the debug symbols from an object file */
661 {
662     ObjHeader   H;
663     Collection  StrPool = AUTO_COLLECTION_INITIALIZER;
664     unsigned    Count;
665     unsigned    I;
666
667     /* Seek to the header position and read the header */
668     FileSetPos (F, Offset);
669     ReadObjHeader (F, &H);
670
671     /* Seek to the start of the string pool and read it */
672     FileSetPos (F, Offset + H.StrPoolOffs);
673     ReadStrPool (F, &StrPool);
674
675     /* Seek to the start of the debug syms */
676     FileSetPos (F, Offset + H.DbgSymOffs);
677
678     /* Output a header */
679     printf ("  Debug symbols:\n");
680
681     /* Check if the object file was compiled with debug info */
682     if ((H.Flags & OBJ_FLAGS_DBGINFO) == 0) {
683         /* Print that there no debug symbols and bail out */
684         printf ("    Count:%27u\n", 0);
685         return;
686     }
687
688     /* Read the number of exports and print it */
689     Count = ReadVar (F);
690     printf ("    Count:%27u\n", Count);
691
692     /* Read and print all debug symbols */
693     for (I = 0; I < Count; ++I) {
694
695         unsigned long   Value = 0;
696         unsigned long   Size = 0;
697         unsigned        ImportId = 0;
698         unsigned        ExportId = 0;
699
700         /* Read the data for one symbol */
701         unsigned Type          = ReadVar (F);
702         unsigned char AddrSize = Read8 (F);
703         unsigned long Owner    = ReadVar (F);
704         const char*   Name     = GetString (&StrPool, ReadVar (F));
705         unsigned      Len      = strlen (Name);
706         if (SYM_IS_CONST (Type)) {
707             Value = Read32 (F);
708         } else {
709             SkipExpr (F);
710         }
711         if (SYM_HAS_SIZE (Type)) {
712             Size = ReadVar (F);
713         }
714         if (SYM_IS_IMPORT (Type)) {
715             ImportId = ReadVar (F);
716         }
717         if (SYM_IS_EXPORT (Type)) {
718             ExportId = ReadVar (F);
719         }
720
721         /* Skip both line info lists */
722         SkipLineInfoList (F);
723         SkipLineInfoList (F);
724
725         /* Print the header */
726         printf ("    Index:%27u\n", I);
727
728         /* Print the data */
729         printf ("      Type:%22s0x%02X  (%s)\n", "", Type, GetExportFlags (Type, 0));
730         printf ("      Address size:%14s0x%02X  (%s)\n", "", AddrSize,
731                 AddrSizeToStr (AddrSize));
732         printf ("      Owner:%25lu\n", Owner);
733         printf ("      Name:%*s\"%s\"\n", (int)(24-Len), "", Name);
734         if (SYM_IS_CONST (Type)) {
735             printf ("      Value:%15s0x%08lX  (%lu)\n", "", Value, Value);
736         }
737         if (SYM_HAS_SIZE (Type)) {
738             printf ("      Size:%20s0x%04lX  (%lu)\n", "", Size, Size);
739         }
740         if (SYM_IS_IMPORT (Type)) {
741             printf ("      Import:%24u\n", ImportId);
742         }
743         if (SYM_IS_EXPORT (Type)) {
744             printf ("      Export:%24u\n", ExportId);
745         }
746     }
747
748     /* Destroy the string pool */
749     DestroyStrPool (&StrPool);
750 }
751
752
753
754 void DumpObjLineInfo (FILE* F, unsigned long Offset)
755 /* Dump the line info from an object file */
756 {
757     ObjHeader   H;
758     Collection  StrPool = AUTO_COLLECTION_INITIALIZER;
759     unsigned    Count;
760     unsigned    I;
761
762     /* Seek to the header position and read the header */
763     FileSetPos (F, Offset);
764     ReadObjHeader (F, &H);
765
766     /* Seek to the start of the string pool and read it */
767     FileSetPos (F, Offset + H.StrPoolOffs);
768     ReadStrPool (F, &StrPool);
769
770     /* Seek to the start of line infos */
771     FileSetPos (F, Offset + H.LineInfoOffs);
772
773     /* Output a header */
774     printf ("  Line info:\n");
775
776     /* Check if the object file was compiled with debug info */
777     if ((H.Flags & OBJ_FLAGS_DBGINFO) == 0) {
778         /* Print that there no line infos and bail out */
779         printf ("    Count:%27u\n", 0);
780         return;
781     }
782
783     /* Read the number of line infos and print it */
784     Count = ReadVar (F);
785     printf ("    Count:%27u\n", Count);
786
787     /* Read and print all line infos */
788     for (I = 0; I < Count; ++I) {
789
790         FilePos   Pos;
791         unsigned  Type;
792
793         /* File position of line info */
794         ReadFilePos (F, &Pos);
795
796         /* Type of line info */
797         Type = ReadVar (F);
798
799         /* Skip the spans */
800         SkipSpanList (F);
801
802         /* Print the header */
803         printf ("    Index:%27u\n", I);
804
805         /* Print the data */
806         printf ("      Type:%26u\n", LI_GET_TYPE (Type));
807         printf ("      Count:%25u\n", LI_GET_COUNT (Type));
808         printf ("      Line:%26u\n", Pos.Line);
809         printf ("      Col:%27u\n", Pos.Col);
810         printf ("      Name:%26u\n", Pos.Name);
811     }
812
813     /* Destroy the string pool */
814     DestroyStrPool (&StrPool);
815 }
816
817
818
819 void DumpObjScopes (FILE* F, unsigned long Offset)
820 /* Dump the scopes from an object file */
821 {
822     ObjHeader   H;
823     Collection  StrPool = AUTO_COLLECTION_INITIALIZER;
824     unsigned    Count;
825     unsigned    I;
826
827     /* Seek to the header position and read the header */
828     FileSetPos (F, Offset);
829     ReadObjHeader (F, &H);
830
831     /* Seek to the start of the string pool and read it */
832     FileSetPos (F, Offset + H.StrPoolOffs);
833     ReadStrPool (F, &StrPool);
834
835     /* Seek to the start of scopes */
836     FileSetPos (F, Offset + H.ScopeOffs);
837
838     /* Output a header */
839     printf ("  Scopes:\n");
840
841     /* Check if the object file was compiled with debug info */
842     if ((H.Flags & OBJ_FLAGS_DBGINFO) == 0) {
843         /* Print that there no scopes and bail out */
844         printf ("    Count:%27u\n", 0);
845         return;
846     }
847
848     /* Read the number of scopes and print it */
849     Count = ReadVar (F);
850     printf ("    Count:%27u\n", Count);
851
852     /* Read and print all scopes */
853     for (I = 0; I < Count; ++I) {
854
855         const char*     Name;
856         unsigned        Len;
857
858         /* Read the data */
859         unsigned        ParentId = ReadVar (F);
860         unsigned        LexicalLevel = ReadVar (F);
861         unsigned        Flags = ReadVar (F);
862         const char*     ScopeType = GetScopeType (ReadVar (F));
863
864         /* Print the header */
865         printf ("    Index:%27u\n", I);
866
867         /* Print the data */
868         printf ("      Parent id:%21u\n",       ParentId);
869         printf ("      Lexical level:%17u\n",   LexicalLevel);
870         printf ("      Flags:%21s0x%02X\n",     "", Flags);
871         printf ("      Type:%26s\n",            ScopeType);
872
873         /* Resolve and print the name */
874         Name = GetString (&StrPool, ReadVar (F));
875         Len  = strlen (Name);
876         printf ("      Name:%*s\"%s\"\n", (int)(24-Len), "", Name);
877
878         /* Size */
879         if (SCOPE_HAS_SIZE (Flags)) {
880             unsigned long Size = ReadVar (F);
881             printf ("      Size:%20s0x%04lX  (%lu)\n", "", Size, Size);
882         }
883
884         /* Label */
885         if (SCOPE_HAS_LABEL (Flags)) {
886             unsigned LabelId = ReadVar (F);
887             printf ("      Label id:%22u\n", LabelId);
888         }
889
890         /* Skip the spans */
891         SkipSpanList (F);
892     }
893
894     /* Destroy the string pool */
895     DestroyStrPool (&StrPool);
896 }
897
898
899
900 void DumpObjSegSize (FILE* F, unsigned long Offset)
901 /* Dump the sizes of the segment in the object file */
902 {
903     ObjHeader   H;
904     Collection  StrPool = AUTO_COLLECTION_INITIALIZER;
905     unsigned    Count;
906
907     /* Seek to the header position and read the header */
908     FileSetPos (F, Offset);
909     ReadObjHeader (F, &H);
910
911     /* Seek to the start of the string pool and read it */
912     FileSetPos (F, Offset + H.StrPoolOffs);
913     ReadStrPool (F, &StrPool);
914
915     /* Seek to the start of the segments */
916     FileSetPos (F, Offset + H.SegOffs);
917
918     /* Output a header */
919     printf ("  Segment sizes:\n");
920
921     /* Read the number of segments */
922     Count = ReadVar (F);
923
924     /* Read and print the sizes of all segments */
925     while (Count--) {
926
927         unsigned long Size;
928
929         /* Read the data for one segment */
930         unsigned long DataSize = Read32 (F);
931         unsigned long NextSeg  = ftell (F) + DataSize;
932         const char*   Name     = GetString (&StrPool, ReadVar (F));
933         unsigned      Len      = strlen (Name);
934
935         /* Skip segment flags, read size */
936         (void) ReadVar (F);     
937         Size = ReadVar (F);
938
939         /* Skip alignment, type and fragment count */
940         (void) ReadVar (F);
941         (void) Read8 (F);
942         (void) ReadVar (F);
943
944         /* Print the size for this segment */
945         printf ("    %s:%*s%6lu\n", Name, (int)(24-Len), "", Size);
946
947         /* Seek to the end of the segment data (start of next) */
948         FileSetPos (F, NextSeg);
949     }
950
951     /* Destroy the string pool */
952     DestroyStrPool (&StrPool);
953 }
954
955
956
957