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