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