]> git.sur5r.net Git - cc65/blob - src/od65/dump.c
66af0b5432c17d36489e8e804776d3bae93feeab
[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 SkipSpanList (FILE* F)
140 /* Skip a span list from the given file */
141 {
142     /* Count preceeds the list */
143     unsigned long Count = ReadVar (F);
144
145     /* Skip indices */
146     while (Count--) {
147         (void) ReadVar (F);
148     }
149 }
150
151
152
153 static void SkipExpr (FILE* F)
154 /* Skip an expression from the given file */
155 {
156     /* Read the node tag and handle NULL nodes */
157     unsigned char Op = Read8 (F);
158     if (Op == EXPR_NULL) {
159         return;
160     }
161
162     /* Check the tag and handle the different expression types */
163     if (EXPR_IS_LEAF (Op)) {
164         switch (Op) {
165
166             case EXPR_LITERAL:
167                 (void) Read32Signed (F);
168                 break;
169
170             case EXPR_SYMBOL:
171                 /* Read the import number */
172                 (void) ReadVar (F);
173                 break;
174
175             case EXPR_SECTION:
176                 /* Read the segment number */
177                 (void) Read8 (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 long Size      = ReadVar (F);
502         unsigned long Align     = ReadVar (F);
503         unsigned char AddrSize  = Read8 (F);
504         unsigned long FragCount = ReadVar (F);
505
506         /* Print the header */
507         printf ("    Index:%27u\n", I);
508
509         /* Print the data */
510         printf ("      Name:%*s\"%s\"\n", (int)(24-Len), "", Name);
511         printf ("      Size:%26lu\n", Size);
512         printf ("      Alignment:%21lu\n", Align);
513         printf ("      Address size:%14s0x%02X  (%s)\n", "", AddrSize,
514                 AddrSizeToStr (AddrSize));
515         printf ("      Fragment count:%16lu\n", FragCount);
516
517         /* Seek to the end of the segment data (start of next) */
518         FileSetPos (F, NextSeg);
519     }
520
521     /* Destroy the string pool */
522     DestroyStrPool (&StrPool);
523 }
524
525
526
527 void DumpObjImports (FILE* F, unsigned long Offset)
528 /* Dump the imports in the object file */
529 {
530     ObjHeader  H;
531     Collection StrPool = AUTO_COLLECTION_INITIALIZER;
532     unsigned   Count;
533     unsigned   I;
534
535     /* Seek to the header position and read the header */
536     FileSetPos (F, Offset);
537     ReadObjHeader (F, &H);
538
539     /* Seek to the start of the string pool and read it */
540     FileSetPos (F, Offset + H.StrPoolOffs);
541     ReadStrPool (F, &StrPool);
542
543     /* Seek to the start of the imports */
544     FileSetPos (F, Offset + H.ImportOffs);
545
546     /* Output a header */
547     printf ("  Imports:\n");
548
549     /* Read the number of imports and print it */
550     Count = ReadVar (F);
551     printf ("    Count:%27u\n", Count);
552
553     /* Read and print all imports */
554     for (I = 0; I < Count; ++I) {
555
556         /* Read the data for one import */
557         unsigned char AddrSize = Read8 (F);
558         const char*   Name     = GetString (&StrPool, ReadVar (F));
559         unsigned      Len      = strlen (Name);
560
561         /* Skip both line info lists */
562         SkipLineInfoList (F);
563         SkipLineInfoList (F);
564
565         /* Print the header */
566         printf ("    Index:%27u\n", I);
567
568         /* Print the data */
569         printf ("      Address size:%14s0x%02X  (%s)\n", "", AddrSize,
570                 AddrSizeToStr (AddrSize));
571         printf ("      Name:%*s\"%s\"\n", (int)(24-Len), "", Name);
572     }
573
574     /* Destroy the string pool */
575     DestroyStrPool (&StrPool);
576 }
577
578
579
580 void DumpObjExports (FILE* F, unsigned long Offset)
581 /* Dump the exports in the object file */
582 {
583     ObjHeader   H;
584     Collection  StrPool = AUTO_COLLECTION_INITIALIZER;
585     unsigned    Count;
586     unsigned    I;
587
588     /* Seek to the header position and read the header */
589     FileSetPos (F, Offset);
590     ReadObjHeader (F, &H);
591
592     /* Seek to the start of the string pool and read it */
593     FileSetPos (F, Offset + H.StrPoolOffs);
594     ReadStrPool (F, &StrPool);
595
596     /* Seek to the start of the exports */
597     FileSetPos (F, Offset + H.ExportOffs);
598
599     /* Output a header */
600     printf ("  Exports:\n");
601
602     /* Read the number of exports and print it */
603     Count = ReadVar (F);
604     printf ("    Count:%27u\n", Count);
605
606     /* Read and print all exports */
607     for (I = 0; I < Count; ++I) {
608
609         unsigned long   Value = 0;
610         unsigned long   Size = 0;
611         unsigned char   ConDes[CD_TYPE_COUNT];
612         const char*     Name;
613         unsigned        Len;
614
615
616         /* Read the data for one export */
617         unsigned Type          = ReadVar (F);
618         unsigned char AddrSize = Read8 (F);
619         ReadData (F, ConDes, SYM_GET_CONDES_COUNT (Type));
620         Name  = GetString (&StrPool, ReadVar (F));
621         Len   = strlen (Name);
622         if (SYM_IS_CONST (Type)) {
623             Value = Read32 (F);
624         } else {
625             SkipExpr (F);
626         }
627         if (SYM_HAS_SIZE (Type)) {
628             Size = ReadVar (F);
629         }
630
631         /* Skip both line infos lists */
632         SkipLineInfoList (F);
633         SkipLineInfoList (F);
634
635         /* Print the header */
636         printf ("    Index:%27u\n", I);
637
638         /* Print the data */
639         printf ("      Type:%22s0x%02X  (%s)\n", "", Type, GetExportFlags (Type, ConDes));
640         printf ("      Address size:%14s0x%02X  (%s)\n", "", AddrSize,
641                 AddrSizeToStr (AddrSize));
642         printf ("      Name:%*s\"%s\"\n", (int)(24-Len), "", Name);
643         if (SYM_IS_CONST (Type)) {
644             printf ("      Value:%15s0x%08lX  (%lu)\n", "", Value, Value);
645         }
646         if (SYM_HAS_SIZE (Type)) {
647             printf ("      Size:%16s0x%04lX  (%lu)\n", "", Size, Size);
648         }
649     }
650
651     /* Destroy the string pool */
652     DestroyStrPool (&StrPool);
653 }
654
655
656
657 void DumpObjDbgSyms (FILE* F, unsigned long Offset)
658 /* Dump the debug symbols from an object file */
659 {
660     ObjHeader   H;
661     Collection  StrPool = AUTO_COLLECTION_INITIALIZER;
662     unsigned    Count;
663     unsigned    I;
664
665     /* Seek to the header position and read the header */
666     FileSetPos (F, Offset);
667     ReadObjHeader (F, &H);
668
669     /* Seek to the start of the string pool and read it */
670     FileSetPos (F, Offset + H.StrPoolOffs);
671     ReadStrPool (F, &StrPool);
672
673     /* Seek to the start of the debug syms */
674     FileSetPos (F, Offset + H.DbgSymOffs);
675
676     /* Output a header */
677     printf ("  Debug symbols:\n");
678
679     /* Check if the object file was compiled with debug info */
680     if ((H.Flags & OBJ_FLAGS_DBGINFO) == 0) {
681         /* Print that there no debug symbols and bail out */
682         printf ("    Count:%27u\n", 0);
683         return;
684     }
685
686     /* Read the number of exports and print it */
687     Count = ReadVar (F);
688     printf ("    Count:%27u\n", Count);
689
690     /* Read and print all debug symbols */
691     for (I = 0; I < Count; ++I) {
692
693         unsigned long   Value = 0;
694         unsigned long   Size = 0;
695         unsigned        ImportId = 0;
696         unsigned        ExportId = 0;
697
698         /* Read the data for one symbol */
699         unsigned Type          = ReadVar (F);
700         unsigned char AddrSize = Read8 (F);
701         unsigned long Owner    = ReadVar (F);
702         const char*   Name     = GetString (&StrPool, ReadVar (F));
703         unsigned      Len      = strlen (Name);
704         if (SYM_IS_CONST (Type)) {
705             Value = Read32 (F);
706         } else {
707             SkipExpr (F);
708         }
709         if (SYM_HAS_SIZE (Type)) {
710             Size = ReadVar (F);
711         }
712         if (SYM_IS_IMPORT (Type)) {
713             ImportId = ReadVar (F);
714         }
715         if (SYM_IS_EXPORT (Type)) {
716             ExportId = ReadVar (F);
717         }
718
719         /* Skip both line info lists */
720         SkipLineInfoList (F);
721         SkipLineInfoList (F);
722
723         /* Print the header */
724         printf ("    Index:%27u\n", I);
725
726         /* Print the data */
727         printf ("      Type:%22s0x%02X  (%s)\n", "", Type, GetExportFlags (Type, 0));
728         printf ("      Address size:%14s0x%02X  (%s)\n", "", AddrSize,
729                 AddrSizeToStr (AddrSize));
730         printf ("      Owner:%25lu\n", Owner);
731         printf ("      Name:%*s\"%s\"\n", (int)(24-Len), "", Name);
732         if (SYM_IS_CONST (Type)) {
733             printf ("      Value:%15s0x%08lX  (%lu)\n", "", Value, Value);
734         }
735         if (SYM_HAS_SIZE (Type)) {
736             printf ("      Size:%20s0x%04lX  (%lu)\n", "", Size, Size);
737         }
738         if (SYM_IS_IMPORT (Type)) {
739             printf ("      Import:%24u\n", ImportId);
740         }
741         if (SYM_IS_EXPORT (Type)) {
742             printf ("      Export:%24u\n", ExportId);
743         }
744     }
745
746     /* Destroy the string pool */
747     DestroyStrPool (&StrPool);
748 }
749
750
751
752 void DumpObjLineInfo (FILE* F, unsigned long Offset)
753 /* Dump the line info from an object file */
754 {
755     ObjHeader   H;
756     Collection  StrPool = AUTO_COLLECTION_INITIALIZER;
757     unsigned    Count;
758     unsigned    I;
759
760     /* Seek to the header position and read the header */
761     FileSetPos (F, Offset);
762     ReadObjHeader (F, &H);
763
764     /* Seek to the start of the string pool and read it */
765     FileSetPos (F, Offset + H.StrPoolOffs);
766     ReadStrPool (F, &StrPool);
767
768     /* Seek to the start of line infos */
769     FileSetPos (F, Offset + H.LineInfoOffs);
770
771     /* Output a header */
772     printf ("  Line info:\n");
773
774     /* Check if the object file was compiled with debug info */
775     if ((H.Flags & OBJ_FLAGS_DBGINFO) == 0) {
776         /* Print that there no line infos and bail out */
777         printf ("    Count:%27u\n", 0);
778         return;
779     }
780
781     /* Read the number of line infos and print it */
782     Count = ReadVar (F);
783     printf ("    Count:%27u\n", Count);
784
785     /* Read and print all line infos */
786     for (I = 0; I < Count; ++I) {
787
788         FilePos   Pos;
789         unsigned  Type;
790
791         /* File position of line info */
792         ReadFilePos (F, &Pos);
793
794         /* Type of line info */
795         Type = ReadVar (F);
796
797         /* Skip the spans */
798         SkipSpanList (F);
799
800         /* Print the header */
801         printf ("    Index:%27u\n", I);
802
803         /* Print the data */
804         printf ("      Type:%26u\n", LI_GET_TYPE (Type));
805         printf ("      Count:%25u\n", LI_GET_COUNT (Type));
806         printf ("      Line:%26u\n", Pos.Line);
807         printf ("      Col:%27u\n", Pos.Col);
808         printf ("      Name:%26u\n", Pos.Name);
809     }
810
811     /* Destroy the string pool */
812     DestroyStrPool (&StrPool);
813 }
814
815
816
817 void DumpObjScopes (FILE* F, unsigned long Offset)
818 /* Dump the scopes from an object file */
819 {
820     ObjHeader   H;
821     Collection  StrPool = AUTO_COLLECTION_INITIALIZER;
822     unsigned    Count;
823     unsigned    I;
824
825     /* Seek to the header position and read the header */
826     FileSetPos (F, Offset);
827     ReadObjHeader (F, &H);
828
829     /* Seek to the start of the string pool and read it */
830     FileSetPos (F, Offset + H.StrPoolOffs);
831     ReadStrPool (F, &StrPool);
832
833     /* Seek to the start of scopes */
834     FileSetPos (F, Offset + H.ScopeOffs);
835
836     /* Output a header */
837     printf ("  Scopes:\n");
838
839     /* Check if the object file was compiled with debug info */
840     if ((H.Flags & OBJ_FLAGS_DBGINFO) == 0) {
841         /* Print that there no scopes and bail out */
842         printf ("    Count:%27u\n", 0);
843         return;
844     }
845
846     /* Read the number of scopes and print it */
847     Count = ReadVar (F);
848     printf ("    Count:%27u\n", Count);
849
850     /* Read and print all scopes */
851     for (I = 0; I < Count; ++I) {
852
853         const char*     Name;
854         unsigned        Len;
855
856         /* Read the data */
857         unsigned        ParentId = ReadVar (F);
858         unsigned        LexicalLevel = ReadVar (F);
859         unsigned        Flags = ReadVar (F);
860         const char*     ScopeType = GetScopeType (ReadVar (F));
861
862         /* Print the header */
863         printf ("    Index:%27u\n", I);
864
865         /* Print the data */
866         printf ("      Parent id:%21u\n",       ParentId);
867         printf ("      Lexical level:%17u\n",   LexicalLevel);
868         printf ("      Flags:%21s0x%02X\n",     "", Flags);
869         printf ("      Type:%26s\n",            ScopeType);
870
871         /* Resolve and print the name */
872         Name = GetString (&StrPool, ReadVar (F));
873         Len  = strlen (Name);
874         printf ("      Name:%*s\"%s\"\n", (int)(24-Len), "", Name);
875
876         /* Size */
877         if (SCOPE_HAS_SIZE (Flags)) {
878             unsigned long Size = ReadVar (F);
879             printf ("      Size:%20s0x%04lX  (%lu)\n", "", Size, Size);
880         }
881
882         /* Label */
883         if (SCOPE_HAS_LABEL (Flags)) {
884             unsigned LabelId = ReadVar (F);
885             printf ("      Label id:%22u\n", LabelId);
886         }
887
888         /* Skip the spans */
889         SkipSpanList (F);
890     }
891
892     /* Destroy the string pool */
893     DestroyStrPool (&StrPool);
894 }
895
896
897
898 void DumpObjSegSize (FILE* F, unsigned long Offset)
899 /* Dump the sizes of the segment in the object file */
900 {
901     ObjHeader   H;
902     Collection  StrPool = AUTO_COLLECTION_INITIALIZER;
903     unsigned    Count;
904
905     /* Seek to the header position and read the header */
906     FileSetPos (F, Offset);
907     ReadObjHeader (F, &H);
908
909     /* Seek to the start of the string pool and read it */
910     FileSetPos (F, Offset + H.StrPoolOffs);
911     ReadStrPool (F, &StrPool);
912
913     /* Seek to the start of the segments */
914     FileSetPos (F, Offset + H.SegOffs);
915
916     /* Output a header */
917     printf ("  Segment sizes:\n");
918
919     /* Read the number of segments */
920     Count = ReadVar (F);
921
922     /* Read and print the sizes of all segments */
923     while (Count--) {
924
925         /* Read the data for one segments */
926         unsigned long DataSize = Read32 (F);
927         unsigned long NextSeg  = ftell (F) + DataSize;
928         const char*   Name     = GetString (&StrPool, ReadVar (F));
929         unsigned      Len      = strlen (Name);
930         unsigned long Size     = ReadVar (F);
931
932         /* Skip alignment, type and fragment count */
933         (void) ReadVar (F);
934         (void) Read8 (F);
935         (void) ReadVar (F);
936
937         /* Print the size for this segment */
938         printf ("    %s:%*s%6lu\n", Name, (int)(24-Len), "", Size);
939
940         /* Seek to the end of the segment data (start of next) */
941         FileSetPos (F, NextSeg);
942     }
943
944     /* Destroy the string pool */
945     DestroyStrPool (&StrPool);
946 }
947
948
949
950