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