1/*****************************************************************************/
2/* */
3/* dump.c */
4/* */
5/* Dump subroutines for the od65 object file dump utility */
6/* */
7/* */
8/* */
9/* (C) 2002-2012, Ullrich von Bassewitz */
10/* Roemerstrasse 52 */
11/* D-70794 Filderstadt */
12/* EMail: uz@cc65.org */
13/* */
14/* */
15/* This software is provided 'as-is', without any expressed or implied */
16/* warranty. In no event will the authors be held liable for any damages */
17/* arising from the use of this software. */
18/* */
19/* Permission is granted to anyone to use this software for any purpose, */
20/* including commercial applications, and to alter it and redistribute it */
21/* freely, subject to the following restrictions: */
22/* */
23/* 1. The origin of this software must not be misrepresented; you must not */
24/* claim that you wrote the original software. If you use this software */
25/* in a product, an acknowledgment in the product documentation would be */
26/* appreciated but is not required. */
27/* 2. Altered source versions must be plainly marked as such, and must not */
28/* be misrepresented as being the original software. */
29/* 3. This notice may not be removed or altered from any source */
30/* distribution. */
31/* */
32/*****************************************************************************/
33
34
35
36#include <string.h>
37#include <time.h>
38
39/* common */
40#include "addrsize.h"
41#include "cddefs.h"
42#include "coll.h"
43#include "exprdefs.h"
44#include "filepos.h"
45#include "lidefs.h"
46#include "objdefs.h"
47#include "optdefs.h"
48#include "scopedefs.h"
49#include "symdefs.h"
50#include "xmalloc.h"
51
52/* od65 */
53#include "error.h"
54#include "fileio.h"
55#include "dump.h"
56
57
58
59/*****************************************************************************/
60/* Code */
61/*****************************************************************************/
62
63
64
65static void DestroyStrPool (Collection* C)
66/* Free all strings in the given pool plus the item pointers. Note: The
67** collection may not be reused later.
68*/
69{
70 unsigned I;
71 for (I = 0; I < CollCount (C); ++I) {
72 xfree (CollAtUnchecked (C, I));
73 }
74 DoneCollection (C);
75}
76
77
78
79static const char* GetString (const Collection* C, unsigned Index)
80/* Get a string from a collection. In fact, this function calls CollConstAt,
81** but will print a somewhat more readable error message if the index is out
82** of bounds.
83*/
84{
85 if (Index >= CollCount (C)) {
86 Error ("Invalid string index (%u) - file corrupt!", Index);
87 }
88 return CollConstAt (C, Index);
89}
90
91
92
93static void DumpObjHeaderSection (const char* Name,
94 unsigned long Offset,
95 unsigned long Size)
96/* Dump a header section */
97{
98 printf (" %s:\n", Name);
99 printf (" Offset:%24lu\n", Offset);
100 printf (" Size: %24lu\n", Size);
101}
102
103
104
105static char* TimeToStr (unsigned long Time)
106/* Convert the time into a string and return it */
107{
108 /* Get the time and convert to string */
109 time_t T = (time_t) Time;
110 char* S = asctime (localtime (&T));
111
112 /* Remove the trailing newline */
113 unsigned Len = strlen (S);
114 if (Len > 0 && S[Len-1] == '\n') {
115 S[Len-1 ] = '\0';
116 }
117
118 /* Return the time string */
119 return S;
120}
121
122
123
124static void SkipLineInfoList (FILE* F)
125/* Skip a line info list from the given file */
126{
127 /* Count preceeds the list */
128 unsigned long Count = ReadVar (F);
129
130 /* Skip indices */
131 while (Count--) {
132 (void) ReadVar (F);
133 }
134}
135
136
137
138static void SkipSpanList (FILE* F)
139/* Skip a span list from the given file */
140{
141 /* Count preceeds the list */
142 unsigned long Count = ReadVar (F);
143
144 /* Skip indices */
145 while (Count--) {
146 (void) ReadVar (F);
147 }
148}
149
150
151
152static void SkipExpr (FILE* F)
153/* Skip an expression from the given file */
154{
155 /* Read the node tag and handle NULL nodes */
156 unsigned char Op = Read8 (F);
157 if (Op == EXPR_NULL) {
158 return;
159 }
160
161 /* Check the tag and handle the different expression types */
162 if (EXPR_IS_LEAF (Op)) {
163 switch (Op) {
164
165 case EXPR_LITERAL:
166 (void) Read32Signed (F);
167 break;
168
169 case EXPR_SYMBOL:
170 /* Read the import number */
171 (void) ReadVar (F);
172 break;
173
174 case EXPR_SECTION:
175 case EXPR_BANK:
176 /* Read the segment number */
177 (void) ReadVar (F);
178 break;
179
180 default:
181 Error ("Invalid expression op: %02X", Op);
182
183 }
184
185 } else {
186
187 /* Not a leaf node */
188 SkipExpr (F);
189 SkipExpr (F);
190 }
191}
192
193
194
195static 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
251static 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
267void 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
329void 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
417void 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
467void DumpObjSegments (FILE* F, unsigned long Offset)
468/* Dump the segments in the object file */
469{
470 ObjHeader H;
471 Collection StrPool = AUTO_COLLECTION_INITIALIZER;
472 unsigned Count;
473 unsigned I;
474
475 /* Seek to the header position and read the header */
476 FileSetPos (F, Offset);
477 ReadObjHeader (F, &H);
478
479 /* Seek to the start of the string pool and read it */
480 FileSetPos (F, Offset + H.StrPoolOffs);
481 ReadStrPool (F, &StrPool);
482
483 /* Seek to the start of the segments */
484 FileSetPos (F, Offset + H.SegOffs);
485
486 /* Output a header */
487 printf (" Segments:\n");
488
489 /* Read the number of segments and print it */
490 Count = ReadVar (F);
491 printf (" Count:%27u\n", Count);
492
493 /* Read and print all segments */
494 for (I = 0; I < Count; ++I) {
495
496 /* Read the data for one segments */
497 unsigned long DataSize = Read32 (F);
498 unsigned long NextSeg = ftell (F) + DataSize;
499 const char* Name = GetString (&StrPool, ReadVar (F));
500 unsigned Len = strlen (Name);
501 unsigned Flags = ReadVar (F);
502 unsigned long Size = ReadVar (F);
503 unsigned long Align = ReadVar (F);
504 unsigned char AddrSize = Read8 (F);
505 unsigned long FragCount = ReadVar (F);
506
507 /* Print the header */
508 printf (" Index:%27u\n", I);
509
510 /* Print the data */
511 printf (" Name:%*s\"%s\"\n", (int)(24-Len), "", Name);
512 printf (" Flags:%25u\n", Flags);
513 printf (" Size:%26lu\n", Size);
514 printf (" Alignment:%21lu\n", Align);
515 printf (" Address size:%14s0x%02X (%s)\n", "", AddrSize,
516 AddrSizeToStr (AddrSize));
517 printf (" Fragment count:%16lu\n", FragCount);
518
519 /* Seek to the end of the segment data (start of next) */
520 FileSetPos (F, NextSeg);
521 }
522
523 /* Destroy the string pool */
524 DestroyStrPool (&StrPool);
525}
526
527
528
529void DumpObjImports (FILE* F, unsigned long Offset)
530/* Dump the imports in the object file */
531{
532 ObjHeader H;
533 Collection StrPool = AUTO_COLLECTION_INITIALIZER;
534 unsigned Count;
535 unsigned I;
536
537 /* Seek to the header position and read the header */
538 FileSetPos (F, Offset);
539 ReadObjHeader (F, &H);
540
541 /* Seek to the start of the string pool and read it */
542 FileSetPos (F, Offset + H.StrPoolOffs);
543 ReadStrPool (F, &StrPool);
544
545 /* Seek to the start of the imports */
546 FileSetPos (F, Offset + H.ImportOffs);
547
548 /* Output a header */
549 printf (" Imports:\n");
550
551 /* Read the number of imports and print it */
552 Count = ReadVar (F);
553 printf (" Count:%27u\n", Count);
554
555 /* Read and print all imports */
556 for (I = 0; I < Count; ++I) {
557
558 /* Read the data for one import */
559 unsigned char AddrSize = Read8 (F);
560 const char* Name = GetString (&StrPool, ReadVar (F));
561 unsigned Len = strlen (Name);
562
563 /* Skip both line info lists */
564 SkipLineInfoList (F);
565 SkipLineInfoList (F);
566
567 /* Print the header */
568 printf (" Index:%27u\n", I);
569
570 /* Print the data */
571 printf (" Address size:%14s0x%02X (%s)\n", "", AddrSize,
572 AddrSizeToStr (AddrSize));
573 printf (" Name:%*s\"%s\"\n", (int)(24-Len), "", Name);
574 }
575
576 /* Destroy the string pool */
577 DestroyStrPool (&StrPool);
578}
579
580
581
582void DumpObjExports (FILE* F, unsigned long Offset)
583/* Dump the exports in the object file */
584{
585 ObjHeader H;
586 Collection StrPool = AUTO_COLLECTION_INITIALIZER;
587 unsigned Count;
588 unsigned I;
589
590 /* Seek to the header position and read the header */
591 FileSetPos (F, Offset);
592 ReadObjHeader (F, &H);
593
594 /* Seek to the start of the string pool and read it */
595 FileSetPos (F, Offset + H.StrPoolOffs);
596 ReadStrPool (F, &StrPool);
597
598 /* Seek to the start of the exports */
599 FileSetPos (F, Offset + H.ExportOffs);
600
601 /* Output a header */
602 printf (" Exports:\n");
603
604 /* Read the number of exports and print it */
605 Count = ReadVar (F);
606 printf (" Count:%27u\n", Count);
607
608 /* Read and print all exports */
609 for (I = 0; I < Count; ++I) {
610
611 unsigned long Value = 0;
612 unsigned long Size = 0;
613 unsigned char ConDes[CD_TYPE_COUNT];
614 const char* Name;
615 unsigned Len;
616
617
618 /* Read the data for one export */
619 unsigned Type = ReadVar (F);
620 unsigned char AddrSize = Read8 (F);
621 ReadData (F, ConDes, SYM_GET_CONDES_COUNT (Type));
622 Name = GetString (&StrPool, ReadVar (F));
623 Len = strlen (Name);
624 if (SYM_IS_CONST (Type)) {
625 Value = Read32 (F);
626 } else {
627 SkipExpr (F);
628 }
629 if (SYM_HAS_SIZE (Type)) {
630 Size = ReadVar (F);
631 }
632
633 /* Skip both line infos lists */
634 SkipLineInfoList (F);
635 SkipLineInfoList (F);
636
637 /* Print the header */
638 printf (" Index:%27u\n", I);
639
640 /* Print the data */
641 printf (" Type:%22s0x%02X (%s)\n", "", Type, GetExportFlags (Type, ConDes));
642 printf (" Address size:%14s0x%02X (%s)\n", "", AddrSize,
643 AddrSizeToStr (AddrSize));
644 printf (" Name:%*s\"%s\"\n", (int)(24-Len), "", Name);
645 if (SYM_IS_CONST (Type)) {
646 printf (" Value:%15s0x%08lX (%lu)\n", "", Value, Value);
647 }
648 if (SYM_HAS_SIZE (Type)) {
649 printf (" Size:%16s0x%04lX (%lu)\n", "", Size, Size);
650 }
651 }
652
653 /* Destroy the string pool */
654 DestroyStrPool (&StrPool);
655}
656
657
658
659void DumpObjDbgSyms (FILE* F, unsigned long Offset)
660/* Dump the debug symbols from an object file */
661{
662 ObjHeader H;
663 Collection StrPool = AUTO_COLLECTION_INITIALIZER;
664 unsigned Count;
665 unsigned I;
666
667 /* Seek to the header position and read the header */
668 FileSetPos (F, Offset);
669 ReadObjHeader (F, &H);
670
671 /* Seek to the start of the string pool and read it */
672 FileSetPos (F, Offset + H.StrPoolOffs);
673 ReadStrPool (F, &StrPool);
674
675 /* Seek to the start of the debug syms */
676 FileSetPos (F, Offset + H.DbgSymOffs);
677
678 /* Output a header */
679 printf (" Debug symbols:\n");
680
681 /* Check if the object file was compiled with debug info */
682 if ((H.Flags & OBJ_FLAGS_DBGINFO) == 0) {
683 /* Print that there no debug symbols and bail out */
684 printf (" Count:%27u\n", 0);
685 return;
686 }
687
688 /* Read the number of exports and print it */
689 Count = ReadVar (F);
690 printf (" Count:%27u\n", Count);
691
692 /* Read and print all debug symbols */
693 for (I = 0; I < Count; ++I) {
694
695 unsigned long Value = 0;
696 unsigned long Size = 0;
697 unsigned ImportId = 0;
698 unsigned ExportId = 0;
699
700 /* Read the data for one symbol */
701 unsigned Type = ReadVar (F);
702 unsigned char AddrSize = Read8 (F);
703 unsigned long Owner = ReadVar (F);
704 const char* Name = GetString (&StrPool, ReadVar (F));
705 unsigned Len = strlen (Name);
706 if (SYM_IS_CONST (Type)) {
707 Value = Read32 (F);
708 } else {
709 SkipExpr (F);
710 }
711 if (SYM_HAS_SIZE (Type)) {
712 Size = ReadVar (F);
713 }
714 if (SYM_IS_IMPORT (Type)) {
715 ImportId = ReadVar (F);
716 }
717 if (SYM_IS_EXPORT (Type)) {
718 ExportId = ReadVar (F);
719 }
720
721 /* Skip both line info lists */
722 SkipLineInfoList (F);
723 SkipLineInfoList (F);
724
725 /* Print the header */
726 printf (" Index:%27u\n", I);
727
728 /* Print the data */
729 printf (" Type:%22s0x%02X (%s)\n", "", Type, GetExportFlags (Type, 0));
730 printf (" Address size:%14s0x%02X (%s)\n", "", AddrSize,
731 AddrSizeToStr (AddrSize));
732 printf (" Owner:%25lu\n", Owner);
733 printf (" Name:%*s\"%s\"\n", (int)(24-Len), "", Name);
734 if (SYM_IS_CONST (Type)) {
735 printf (" Value:%15s0x%08lX (%lu)\n", "", Value, Value);
736 }
737 if (SYM_HAS_SIZE (Type)) {
738 printf (" Size:%20s0x%04lX (%lu)\n", "", Size, Size);
739 }
740 if (SYM_IS_IMPORT (Type)) {
741 printf (" Import:%24u\n", ImportId);
742 }
743 if (SYM_IS_EXPORT (Type)) {
744 printf (" Export:%24u\n", ExportId);
745 }
746 }
747
748 /* Destroy the string pool */
749 DestroyStrPool (&StrPool);
750}
751
752
753
754void DumpObjLineInfo (FILE* F, unsigned long Offset)
755/* Dump the line info from an object file */
756{
757 ObjHeader H;
758 Collection StrPool = AUTO_COLLECTION_INITIALIZER;
759 unsigned Count;
760 unsigned I;
761
762 /* Seek to the header position and read the header */
763 FileSetPos (F, Offset);
764 ReadObjHeader (F, &H);
765
766 /* Seek to the start of the string pool and read it */
767 FileSetPos (F, Offset + H.StrPoolOffs);
768 ReadStrPool (F, &StrPool);
769
770 /* Seek to the start of line infos */
771 FileSetPos (F, Offset + H.LineInfoOffs);
772
773 /* Output a header */
774 printf (" Line info:\n");
775
776 /* Check if the object file was compiled with debug info */
777 if ((H.Flags & OBJ_FLAGS_DBGINFO) == 0) {
778 /* Print that there no line infos and bail out */
779 printf (" Count:%27u\n", 0);
780 return;
781 }
782
783 /* Read the number of line infos and print it */
784 Count = ReadVar (F);
785 printf (" Count:%27u\n", Count);
786
787 /* Read and print all line infos */
788 for (I = 0; I < Count; ++I) {
789
790 FilePos Pos;
791 unsigned Type;
792
793 /* File position of line info */
794 ReadFilePos (F, &Pos);
795
796 /* Type of line info */
797 Type = ReadVar (F);
798
799 /* Skip the spans */
800 SkipSpanList (F);
801
802 /* Print the header */
803 printf (" Index:%27u\n", I);
804
805 /* Print the data */
806 printf (" Type:%26u\n", LI_GET_TYPE (Type));
807 printf (" Count:%25u\n", LI_GET_COUNT (Type));
808 printf (" Line:%26u\n", Pos.Line);
809 printf (" Col:%27u\n", Pos.Col);
810 printf (" Name:%26u\n", Pos.Name);
811 }
812
813 /* Destroy the string pool */
814 DestroyStrPool (&StrPool);
815}
816
817
818
819void DumpObjScopes (FILE* F, unsigned long Offset)
820/* Dump the scopes from an object file */
821{
822 ObjHeader H;
823 Collection StrPool = AUTO_COLLECTION_INITIALIZER;
824 unsigned Count;
825 unsigned I;
826
827 /* Seek to the header position and read the header */
828 FileSetPos (F, Offset);
829 ReadObjHeader (F, &H);
830
831 /* Seek to the start of the string pool and read it */
832 FileSetPos (F, Offset + H.StrPoolOffs);
833 ReadStrPool (F, &StrPool);
834
835 /* Seek to the start of scopes */
836 FileSetPos (F, Offset + H.ScopeOffs);
837
838 /* Output a header */
839 printf (" Scopes:\n");
840
841 /* Check if the object file was compiled with debug info */
842 if ((H.Flags & OBJ_FLAGS_DBGINFO) == 0) {
843 /* Print that there no scopes and bail out */
844 printf (" Count:%27u\n", 0);
845 return;
846 }
847
848 /* Read the number of scopes and print it */
849 Count = ReadVar (F);
850 printf (" Count:%27u\n", Count);
851
852 /* Read and print all scopes */
853 for (I = 0; I < Count; ++I) {
854
855 const char* Name;
856 unsigned Len;
857
858 /* Read the data */
859 unsigned ParentId = ReadVar (F);
860 unsigned LexicalLevel = ReadVar (F);
861 unsigned Flags = ReadVar (F);
862 const char* ScopeType = GetScopeType (ReadVar (F));
863
864 /* Print the header */
865 printf (" Index:%27u\n", I);
866
867 /* Print the data */
868 printf (" Parent id:%21u\n", ParentId);
869 printf (" Lexical level:%17u\n", LexicalLevel);
870 printf (" Flags:%21s0x%02X\n", "", Flags);
871 printf (" Type:%26s\n", ScopeType);
872
873 /* Resolve and print the name */
874 Name = GetString (&StrPool, ReadVar (F));
875 Len = strlen (Name);
876 printf (" Name:%*s\"%s\"\n", (int)(24-Len), "", Name);
877
878 /* Size */
879 if (SCOPE_HAS_SIZE (Flags)) {
880 unsigned long Size = ReadVar (F);
881 printf (" Size:%20s0x%04lX (%lu)\n", "", Size, Size);
882 }
883
884 /* Label */
885 if (SCOPE_HAS_LABEL (Flags)) {
886 unsigned LabelId = ReadVar (F);
887 printf (" Label id:%22u\n", LabelId);
888 }
889
890 /* Skip the spans */
891 SkipSpanList (F);
892 }
893
894 /* Destroy the string pool */
895 DestroyStrPool (&StrPool);
896}
897
898
899
900void DumpObjSegSize (FILE* F, unsigned long Offset)
901/* Dump the sizes of the segment in the object file */
902{
903 ObjHeader H;
904 Collection StrPool = AUTO_COLLECTION_INITIALIZER;
905 unsigned Count;
906
907 /* Seek to the header position and read the header */
908 FileSetPos (F, Offset);
909 ReadObjHeader (F, &H);
910
911 /* Seek to the start of the string pool and read it */
912 FileSetPos (F, Offset + H.StrPoolOffs);
913 ReadStrPool (F, &StrPool);
914
915 /* Seek to the start of the segments */
916 FileSetPos (F, Offset + H.SegOffs);
917
918 /* Output a header */
919 printf (" Segment sizes:\n");
920
921 /* Read the number of segments */
922 Count = ReadVar (F);
923
924 /* Read and print the sizes of all segments */
925 while (Count--) {
926
927 unsigned long Size;
928
929 /* Read the data for one segment */
930 unsigned long DataSize = Read32 (F);
931 unsigned long NextSeg = ftell (F) + DataSize;
932 const char* Name = GetString (&StrPool, ReadVar (F));
933 unsigned Len = strlen (Name);
934
935 /* Skip segment flags, read size */
936 (void) ReadVar (F);
937 Size = ReadVar (F);
938
939 /* Skip alignment, type and fragment count */
940 (void) ReadVar (F);
941 (void) Read8 (F);
942 (void) ReadVar (F);
943
944 /* Print the size for this segment */
945 printf (" %s:%*s%6lu\n", Name, (int)(24-Len), "", Size);
946
947 /* Seek to the end of the segment data (start of next) */
948 FileSetPos (F, NextSeg);
949 }
950
951 /* Destroy the string pool */
952 DestroyStrPool (&StrPool);
953}
954