]> git.sur5r.net Git - cc65/blobdiff - src/od65/dump.c
Improved code generation
[cc65] / src / od65 / dump.c
index d44e12efd9d7c4a96b436d84d2cbd64db5de8e8f..208c4bfbced706729d9211dc92495e43f471a528 100644 (file)
@@ -6,10 +6,10 @@
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 2000     Ullrich von Bassewitz                                        */
-/*              Wacholderweg 14                                              */
-/*              D-70597 Stuttgart                                            */
-/* EMail:       uz@musoftware.de                                             */
+/* (C) 2002-2003 Ullrich von Bassewitz                                       */
+/*               Römerstrasse 52                                             */
+/*               D-70794 Filderstadt                                         */
+/* EMail:        uz@cc65.org                                                 */
 /*                                                                           */
 /*                                                                           */
 /* This software is provided 'as-is', without any expressed or implied       */
@@ -37,7 +37,9 @@
 #include <time.h>
 
 /* common */
+#include "addrsize.h"
 #include "cddefs.h"
+#include "coll.h"
 #include "exprdefs.h"
 #include "filepos.h"
 #include "objdefs.h"
 
 
 /*****************************************************************************/
-/*                                  Code                                    */
+/*                                  Code                                    */
 /*****************************************************************************/
 
 
 
+static void DestroyStrPool (Collection* C)
+/* Free all strings in the given pool plus the item pointers. Note: The
+ * collection may not be reused later.
+ */
+{
+    unsigned I;
+    for (I = 0; I < CollCount (C); ++I) {
+        xfree (CollAtUnchecked (C, I));
+    }
+    DoneCollection (C);
+}
+
+
+
+static const char* GetString (const Collection* C, unsigned Index)
+/* Get a string from a collection. In fact, this function calls CollConstAt,
+ * but will print a somewhat more readable error message if the index is out
+ * of bounds.
+ */
+{
+    if (Index >= CollCount (C)) {
+        Error ("Invalid string index (%u) - file corrupt!", Index);
+    }
+    return CollConstAt (C, Index);
+}
+
+
+
 static void DumpObjHeaderSection (const char* Name,
                                  unsigned long Offset,
                                  unsigned long Size)
@@ -109,10 +139,10 @@ static void SkipExpr (FILE* F)
 
            case EXPR_SYMBOL:
                /* Read the import number */
-               (void) Read16 (F);
+               (void) ReadVar (F);
                break;
 
-           case EXPR_SEGMENT:
+           case EXPR_SECTION:
                /* Read the segment number */
                (void) Read8 (F);
                break;
@@ -127,72 +157,7 @@ static void SkipExpr (FILE* F)
        /* Not a leaf node */
                SkipExpr (F);
        SkipExpr (F);
-
-    }
-}
-
-
-
-static unsigned SkipFragment (FILE* F)
-/* Skip a fragment from the given file and return the size */
-{
-    FilePos Pos;
-    unsigned long Size;
-
-    /* Read the fragment type */
-    unsigned char Type = Read8 (F);
-
-    /* Handle the different fragment types */
-    switch (Type) {
-
-       case FRAG_LITERAL:
-                   Size = ReadVar (F);
-           break;
-
-       case FRAG_EXPR8:
-       case FRAG_EXPR16:
-       case FRAG_EXPR24:
-       case FRAG_EXPR32:
-       case FRAG_SEXPR8:
-       case FRAG_SEXPR16:
-       case FRAG_SEXPR24:
-       case FRAG_SEXPR32:
-           Size = Type & FRAG_BYTEMASK;
-           break;
-
-       case FRAG_FILL:
-           Size = ReadVar (F);
-           break;
-
-       default:
-           Error ("Unknown fragment type: 0x%02X", Type);
-           /* NOTREACHED */
-           return 0;
     }
-
-
-
-    /* Now read the fragment data */
-    switch (Type & FRAG_TYPEMASK) {
-
-       case FRAG_LITERAL:
-           /* Literal data */
-           FileSeek (F, ftell (F) + Size);
-           break;
-
-       case FRAG_EXPR:
-       case FRAG_SEXPR:
-           /* An expression */
-           SkipExpr (F);
-           break;
-
-    }
-
-    /* Skip the file position of the fragment */
-    ReadFilePos (F, &Pos);
-
-    /* Return the size */
-    return Size;
 }
 
 
@@ -207,23 +172,17 @@ static const char* GetExportFlags (unsigned Flags, const unsigned char* ConDes)
     unsigned Count;
     unsigned I;
 
-    /* Adressing mode */
-    TypeDesc[0] = '\0';
-    switch (Flags & EXP_MASK_SIZE) {
-               case EXP_ABS:   strcat (TypeDesc, "EXP_ABS");           break;
-               case EXP_ZP:    strcat (TypeDesc, "EXP_ZP");            break;
-    }
-
     /* Type of expression */
+    TypeDesc[0] = '\0';
     switch (Flags & EXP_MASK_VAL) {
-               case EXP_CONST: strcat (TypeDesc, ",EXP_CONST");        break;
-               case EXP_EXPR:  strcat (TypeDesc, ",EXP_EXPR");         break;
+               case EXP_CONST: strcat (TypeDesc, "EXP_CONST"); break;
+               case EXP_EXPR:  strcat (TypeDesc, "EXP_EXPR");  break;
     }
 
     /* Constructor/destructor declarations */
     T = TypeDesc + strlen (TypeDesc);
     Count = GET_EXP_CONDES_COUNT (Flags);
-    if (Count > 0) {
+    if (Count > 0 && ConDes) {
        T += sprintf (T, ",EXP_CONDES=");
        for (I = 0; I < Count; ++I) {
            unsigned Type = CD_GET_TYPE (ConDes[I]);
@@ -247,7 +206,7 @@ void DumpObjHeader (FILE* F, unsigned long Offset)
     ObjHeader H;
 
     /* Seek to the header position */
-    FileSeek (F, Offset);
+    FileSetPos (F, Offset);
 
     /* Read the header */
     ReadObjHeader (F, &H);
@@ -287,6 +246,12 @@ void DumpObjHeader (FILE* F, unsigned long Offset)
 
     /* Debug symbols */
     DumpObjHeaderSection ("Debug symbols", H.DbgSymOffs, H.DbgSymSize);
+
+    /* Line infos */
+    DumpObjHeaderSection ("Line infos", H.LineInfoOffs, H.LineInfoSize);
+
+    /* String pool */
+    DumpObjHeaderSection ("String pool", H.StrPoolOffs, H.StrPoolSize);
 }
 
 
@@ -294,18 +259,21 @@ void DumpObjHeader (FILE* F, unsigned long Offset)
 void DumpObjOptions (FILE* F, unsigned long Offset)
 /* Dump the file options */
 {
-    ObjHeader H;
-    unsigned Count;
-    unsigned I;
-
-    /* Seek to the header position */
-    FileSeek (F, Offset);
+    ObjHeader  H;
+    Collection StrPool = AUTO_COLLECTION_INITIALIZER;
+    unsigned   Count;
+    unsigned   I;
 
-    /* Read the header */
+    /* Seek to the header position and read the header */
+    FileSetPos (F, Offset);
     ReadObjHeader (F, &H);
 
+    /* Seek to the start of the string pool and read it */
+    FileSetPos (F, Offset + H.StrPoolOffs);
+    ReadStrPool (F, &StrPool);
+
     /* Seek to the start of the options */
-    FileSeek (F, Offset + H.OptionOffs);
+    FileSetPos (F, Offset + H.OptionOffs);
 
     /* Output a header */
     printf ("  Options:\n");
@@ -317,49 +285,47 @@ void DumpObjOptions (FILE* F, unsigned long Offset)
     /* Read and print all options */
     for (I = 0; I < Count; ++I) {
 
-       unsigned long ArgNum;
-       char*         ArgStr;
-       unsigned      ArgLen;
+       const char*   ArgStr;
+       unsigned      ArgLen;
 
-       /* Read the type of the option */
-       unsigned char Type = Read8 (F);
+       /* Read the type of the option and the value */
+       unsigned char Type = Read8 (F);
+        unsigned long Val  = ReadVar (F);
 
                /* Get the type of the argument */
-       unsigned char ArgType = Type & OPT_ARGMASK;
+       unsigned char ArgType = Type & OPT_ARGMASK;
 
-       /* Determine which option follows */
-       const char* TypeDesc;
-       switch (Type) {
+       /* Determine which option follows */
+       const char* TypeDesc;
+       switch (Type) {
                    case OPT_COMMENT:   TypeDesc = "OPT_COMMENT";       break;
-           case OPT_AUTHOR:    TypeDesc = "OPT_AUTHOR";        break;
-           case OPT_TRANSLATOR:TypeDesc = "OPT_TRANSLATOR";    break;
-           case OPT_COMPILER:  TypeDesc = "OPT_COMPILER";      break;
-           case OPT_OS:        TypeDesc = "OPT_OS";            break;
-           case OPT_DATETIME:  TypeDesc = "OPT_DATETIME";      break;
-           default:            TypeDesc = "OPT_UNKNOWN";       break;
-       }
-
-       /* Print the header */
-       printf ("    Index:%27u\n", I);
-
-       /* Print the data */
-       printf ("      Type:%22s0x%02X  (%s)\n", "", Type, TypeDesc);
-       switch (ArgType) {
-
-           case OPT_ARGSTR:
-               ArgStr = ReadStr (F);
-               ArgLen = strlen (ArgStr);
-               printf ("      Data:%*s\"%s\"\n", 24-ArgLen, "", ArgStr);
-               xfree (ArgStr);
-               break;
-
-           case OPT_ARGNUM:
-               ArgNum = Read32 (F);
-               printf ("      Data:%26lu", ArgNum);
-               if (Type == OPT_DATETIME) {
-                   /* Print the time as a string */
-                   printf ("  (%s)", TimeToStr (ArgNum));
-               }
+           case OPT_AUTHOR:    TypeDesc = "OPT_AUTHOR";        break;
+           case OPT_TRANSLATOR:TypeDesc = "OPT_TRANSLATOR";    break;
+           case OPT_COMPILER:  TypeDesc = "OPT_COMPILER";      break;
+           case OPT_OS:        TypeDesc = "OPT_OS";            break;
+           case OPT_DATETIME:  TypeDesc = "OPT_DATETIME";      break;
+           default:            TypeDesc = "OPT_UNKNOWN";       break;
+       }
+
+       /* Print the header */
+       printf ("    Index:%27u\n", I);
+
+       /* Print the data */
+       printf ("      Type:%22s0x%02X  (%s)\n", "", Type, TypeDesc);
+       switch (ArgType) {
+
+           case OPT_ARGSTR:
+               ArgStr = GetString (&StrPool, Val);
+               ArgLen = strlen (ArgStr);
+               printf ("      Data:%*s\"%s\"\n", 24-ArgLen, "", ArgStr);
+               break;
+
+           case OPT_ARGNUM:
+               printf ("      Data:%26lu", Val);
+               if (Type == OPT_DATETIME) {
+                   /* Print the time as a string */
+                   printf ("  (%s)", TimeToStr (Val));
+               }
                printf ("\n");
                break;
 
@@ -371,6 +337,9 @@ void DumpObjOptions (FILE* F, unsigned long Offset)
                break;
        }
     }
+
+    /* Destroy the string pool */
+    DestroyStrPool (&StrPool);
 }
 
 
@@ -378,18 +347,21 @@ void DumpObjOptions (FILE* F, unsigned long Offset)
 void DumpObjFiles (FILE* F, unsigned long Offset)
 /* Dump the source files */
 {
-    ObjHeader H;
-    unsigned Count;
-    unsigned I;
+    ObjHeader  H;
+    Collection StrPool = AUTO_COLLECTION_INITIALIZER;
+    unsigned   Count;
+    unsigned   I;
 
-    /* Seek to the header position */
-    FileSeek (F, Offset);
-
-    /* Read the header */
+    /* Seek to the header position and read the header */
+    FileSetPos (F, Offset);
     ReadObjHeader (F, &H);
 
-    /* Seek to the start of the options */
-    FileSeek (F, Offset + H.FileOffs);
+    /* Seek to the start of the string pool and read it */
+    FileSetPos (F, Offset + H.StrPoolOffs);
+    ReadStrPool (F, &StrPool);
+
+    /* Seek to the start of the source files */
+    FileSetPos (F, Offset + H.FileOffs);
 
     /* Output a header */
     printf ("  Files:\n");
@@ -402,9 +374,9 @@ void DumpObjFiles (FILE* F, unsigned long Offset)
     for (I = 0; I < Count; ++I) {
 
        /* Read the data for one file */
+               const char*   Name  = GetString (&StrPool, ReadVar (F));
        unsigned long MTime = Read32 (F);
        unsigned long Size  = Read32 (F);
-       char*         Name  = ReadStr (F);
        unsigned      Len   = strlen (Name);
 
        /* Print the header */
@@ -414,10 +386,10 @@ void DumpObjFiles (FILE* F, unsigned long Offset)
        printf ("      Name:%*s\"%s\"\n", 24-Len, "", Name);
                printf ("      Size:%26lu\n", Size);
        printf ("      Modification time:%13lu  (%s)\n", MTime, TimeToStr (MTime));
-
-       /* Free the Name */
-       xfree (Name);
     }
+
+    /* Destroy the string pool */
+    DestroyStrPool (&StrPool);
 }
 
 
@@ -425,19 +397,21 @@ void DumpObjFiles (FILE* F, unsigned long Offset)
 void DumpObjSegments (FILE* F, unsigned long Offset)
 /* Dump the segments in the object file */
 {
-    ObjHeader H;
-    unsigned Count;
-    unsigned I;
-    unsigned FragCount;
+    ObjHeader  H;
+    Collection StrPool = AUTO_COLLECTION_INITIALIZER;
+    unsigned   Count;
+    unsigned   I;
 
-    /* Seek to the header position */
-    FileSeek (F, Offset);
-
-    /* Read the header */
+    /* Seek to the header position and read the header */
+    FileSetPos (F, Offset);
     ReadObjHeader (F, &H);
 
-    /* Seek to the start of the options */
-    FileSeek (F, Offset + H.SegOffs);
+    /* Seek to the start of the string pool and read it */
+    FileSetPos (F, Offset + H.StrPoolOffs);
+    ReadStrPool (F, &StrPool);
+
+    /* Seek to the start of the segments */
+    FileSetPos (F, Offset + H.SegOffs);
 
     /* Output a header */
     printf ("  Segments:\n");
@@ -450,21 +424,14 @@ void DumpObjSegments (FILE* F, unsigned long Offset)
     for (I = 0; I < Count; ++I) {
 
        /* Read the data for one segments */
-       char*         Name  = ReadStr (F);
-       unsigned      Len   = strlen (Name);
-       unsigned long Size  = Read32 (F);
-       unsigned      Align = (1U << Read8 (F));
-       unsigned char Type  = Read8 (F);
-
-       /* Get the description for the type */
-       const char* TypeDesc;
-       switch (Type) {
-           case SEGTYPE_DEFAULT:       TypeDesc = "SEGTYPE_DEFAULT";   break;
-           case SEGTYPE_ABS:           TypeDesc = "SEGTYPE_ABS";       break;
-           case SEGTYPE_ZP:            TypeDesc = "SEGTYPE_ZP";        break;
-           case SEGTYPE_FAR:           TypeDesc = "SEGTYPE_FAR";       break;
-           default:                    TypeDesc = "SEGTYPE_UNKNOWN";   break;
-       }
+        unsigned long DataSize  = Read32 (F);
+        unsigned long NextSeg   = ftell (F) + DataSize;
+               const char*   Name      = GetString (&StrPool, ReadVar (F));
+       unsigned      Len       = strlen (Name);
+       unsigned long Size      = Read32 (F);
+       unsigned      Align     = (1U << Read8 (F));
+               unsigned char AddrSize  = Read8 (F);
+        unsigned long FragCount = ReadVar (F);
 
        /* Print the header */
        printf ("    Index:%27u\n", I);
@@ -473,26 +440,16 @@ void DumpObjSegments (FILE* F, unsigned long Offset)
        printf ("      Name:%*s\"%s\"\n", 24-Len, "", Name);
                printf ("      Size:%26lu\n", Size);
        printf ("      Alignment:%21u\n", Align);
-       printf ("      Type:%22s0x%02X  (%s)\n", "", Type, TypeDesc);
-
-       /* Free the Name */
-       xfree (Name);
-
-       /* Skip the fragments for this segment, counting them */
-       FragCount = 0;
-       while (Size > 0) {
-           unsigned FragSize = SkipFragment (F);
-           if (FragSize > Size) {
-               /* OOPS - file data invalid */
-               Error ("Invalid fragment data - file corrupt!");
-           }
-           Size -= FragSize;
-           ++FragCount;
-       }
+       printf ("      Address size:%14s0x%02X  (%s)\n", "", AddrSize,
+                AddrSizeToStr (AddrSize));
+               printf ("      Fragment count:%16lu\n", FragCount);
 
-       /* Print the fragment count */
-               printf ("      Fragment count:%16u\n", FragCount);
+        /* Seek to the end of the segment data (start of next) */
+        FileSetPos (F, NextSeg);
     }
+
+    /* Destroy the string pool */
+    DestroyStrPool (&StrPool);
 }
 
 
@@ -500,19 +457,22 @@ void DumpObjSegments (FILE* F, unsigned long Offset)
 void DumpObjImports (FILE* F, unsigned long Offset)
 /* Dump the imports in the object file */
 {
-    ObjHeader H;
-    unsigned  Count;
-    unsigned  I;
-    FilePos   Pos;
-
-    /* Seek to the header position */
-    FileSeek (F, Offset);
-
-    /* Read the header */
+    ObjHeader  H;
+    Collection StrPool = AUTO_COLLECTION_INITIALIZER;
+    unsigned   Count;
+    unsigned   I;
+    FilePos    Pos;
+
+    /* Seek to the header position and read the header */
+    FileSetPos (F, Offset);
     ReadObjHeader (F, &H);
 
-    /* Seek to the start of the options */
-    FileSeek (F, Offset + H.ImportOffs);
+    /* Seek to the start of the string pool and read it */
+    FileSetPos (F, Offset + H.StrPoolOffs);
+    ReadStrPool (F, &StrPool);
+
+    /* Seek to the start of the imports */
+    FileSetPos (F, Offset + H.ImportOffs);
 
     /* Output a header */
     printf ("  Imports:\n");
@@ -524,31 +484,23 @@ void DumpObjImports (FILE* F, unsigned long Offset)
     /* Read and print all imports */
     for (I = 0; I < Count; ++I) {
 
-       const char* TypeDesc;
-
                /* Read the data for one import */
-               unsigned char Type  = Read8 (F);
-       char*         Name  = ReadStr (F);
-       unsigned      Len   = strlen (Name);
+               unsigned char AddrSize = Read8 (F);
+               const char*   Name     = GetString (&StrPool, ReadVar (F));
+       unsigned      Len      = strlen (Name);
        ReadFilePos (F, &Pos);
 
-       /* Get a description for the type */
-       switch (Type) {
-           case IMP_ZP:        TypeDesc = "IMP_ZP";            break;
-           case IMP_ABS:       TypeDesc = "IMP_ABS";           break;
-           default:            TypeDesc = "IMP_UNKNOWN";       break;
-       }
-
        /* Print the header */
        printf ("    Index:%27u\n", I);
 
        /* Print the data */
-               printf ("      Type:%22s0x%02X  (%s)\n", "", Type, TypeDesc);
+       printf ("      Address size:%14s0x%02X  (%s)\n", "", AddrSize,
+                AddrSizeToStr (AddrSize));
        printf ("      Name:%*s\"%s\"\n", 24-Len, "", Name);
-
-       /* Free the Name */
-       xfree (Name);
     }
+
+    /* Destroy the string pool */
+    DestroyStrPool (&StrPool);
 }
 
 
@@ -556,19 +508,22 @@ void DumpObjImports (FILE* F, unsigned long Offset)
 void DumpObjExports (FILE* F, unsigned long Offset)
 /* Dump the exports in the object file */
 {
-    ObjHeader    H;
-    unsigned     Count;
-    unsigned     I;
-    FilePos      Pos;
-
-    /* Seek to the header position */
-    FileSeek (F, Offset);
-
-    /* Read the header */
+    ObjHeader  H;
+    Collection  StrPool = AUTO_COLLECTION_INITIALIZER;
+    unsigned           Count;
+    unsigned           I;
+    FilePos            Pos;
+
+    /* Seek to the header position and read the header */
+    FileSetPos (F, Offset);
     ReadObjHeader (F, &H);
 
-    /* Seek to the start of the options */
-    FileSeek (F, Offset + H.ExportOffs);
+    /* Seek to the start of the string pool and read it */
+    FileSetPos (F, Offset + H.StrPoolOffs);
+    ReadStrPool (F, &StrPool);
+
+    /* Seek to the start of the exports */
+    FileSetPos (F, Offset + H.ExportOffs);
 
     /* Output a header */
     printf ("  Exports:\n");
@@ -581,17 +536,17 @@ void DumpObjExports (FILE* F, unsigned long Offset)
     for (I = 0; I < Count; ++I) {
 
        unsigned long   Value = 0;
-       int             HaveValue;
-       unsigned char   Type;
+       int             HaveValue;
        unsigned char   ConDes [CD_TYPE_COUNT];
-       char*           Name;
+               const char*     Name;
        unsigned        Len;
 
 
                /* Read the data for one export */
-               Type  = Read8 (F);
+               unsigned char Type = Read8 (F);
+        unsigned char AddrSize = Read8 (F);
        ReadData (F, ConDes, GET_EXP_CONDES_COUNT (Type));
-       Name  = ReadStr (F);
+               Name  = GetString (&StrPool, ReadVar (F));
        Len   = strlen (Name);
                if (IS_EXP_EXPR (Type)) {
            SkipExpr (F);
@@ -607,14 +562,16 @@ void DumpObjExports (FILE* F, unsigned long Offset)
 
        /* Print the data */
                printf ("      Type:%22s0x%02X  (%s)\n", "", Type, GetExportFlags (Type, ConDes));
+       printf ("      Address size:%14s0x%02X  (%s)\n", "", AddrSize,
+                AddrSizeToStr (AddrSize));
        printf ("      Name:%*s\"%s\"\n", 24-Len, "", Name);
        if (HaveValue) {
            printf ("      Value:%15s0x%08lX  (%lu)\n", "", Value, Value);
        }
-
-       /* Free the Name */
-       xfree (Name);
     }
+
+    /* Destroy the string pool */
+    DestroyStrPool (&StrPool);
 }
 
 
@@ -622,19 +579,22 @@ void DumpObjExports (FILE* F, unsigned long Offset)
 void DumpObjDbgSyms (FILE* F, unsigned long Offset)
 /* Dump the debug symbols from an object file */
 {
-    ObjHeader H;
-    unsigned  Count;
-    unsigned  I;
-    FilePos   Pos;
-
-    /* Seek to the header position */
-    FileSeek (F, Offset);
-
-    /* Read the header */
+    ObjHeader   H;
+    Collection  StrPool = AUTO_COLLECTION_INITIALIZER;
+    unsigned    Count;
+    unsigned    I;
+    FilePos     Pos;
+
+    /* Seek to the header position and read the header */
+    FileSetPos (F, Offset);
     ReadObjHeader (F, &H);
 
-    /* Seek to the start of the options */
-    FileSeek (F, Offset + H.DbgSymOffs);
+    /* Seek to the start of the string pool and read it */
+    FileSetPos (F, Offset + H.StrPoolOffs);
+    ReadStrPool (F, &StrPool);
+
+    /* Seek to the start of the debug syms */
+    FileSetPos (F, Offset + H.DbgSymOffs);
 
     /* Output a header */
     printf ("  Debug symbols:\n");
@@ -654,17 +614,13 @@ void DumpObjDbgSyms (FILE* F, unsigned long Offset)
     for (I = 0; I < Count; ++I) {
 
        unsigned long   Value = 0;
-       int             HaveValue;
-       unsigned char   Type;
-       unsigned char   ConDes [CD_TYPE_COUNT];
-       char*           Name;
-       unsigned        Len;
+       int             HaveValue;
 
                /* Read the data for one symbol */
-               Type  = Read8 (F);
-       ReadData (F, ConDes, GET_EXP_CONDES_COUNT (Type));
-       Name  = ReadStr (F);
-       Len   = strlen (Name);
+               unsigned char Type     = Read8 (F);
+        unsigned char AddrSize = Read8 (F);
+               const char*   Name     = GetString (&StrPool, ReadVar (F));
+       unsigned      Len      = strlen (Name);
        if (IS_EXP_EXPR (Type)) {
            SkipExpr (F);
            HaveValue = 0;
@@ -678,17 +634,126 @@ void DumpObjDbgSyms (FILE* F, unsigned long Offset)
        printf ("    Index:%27u\n", I);
 
        /* Print the data */
-               printf ("      Type:%22s0x%02X  (%s)\n", "", Type, GetExportFlags (Type, ConDes));
+               printf ("      Type:%22s0x%02X  (%s)\n", "", Type, GetExportFlags (Type, 0));
+       printf ("      Address size:%14s0x%02X  (%s)\n", "", AddrSize,
+                AddrSizeToStr (AddrSize));
        printf ("      Name:%*s\"%s\"\n", 24-Len, "", Name);
        if (HaveValue) {
            printf ("      Value:%15s0x%08lX  (%lu)\n", "", Value, Value);
        }
+    }
+
+    /* Destroy the string pool */
+    DestroyStrPool (&StrPool);
+}
+
+
+
+void DumpObjLineInfo (FILE* F, unsigned long Offset)
+/* Dump the line info from an object file */
+{
+    ObjHeader   H;
+    Collection  StrPool = AUTO_COLLECTION_INITIALIZER;
+    unsigned    Count;
+    unsigned    I;
+
+    /* Seek to the header position and read the header */
+    FileSetPos (F, Offset);
+    ReadObjHeader (F, &H);
+
+    /* Seek to the start of the string pool and read it */
+    FileSetPos (F, Offset + H.StrPoolOffs);
+    ReadStrPool (F, &StrPool);
+
+    /* Seek to the start of line infos */
+    FileSetPos (F, Offset + H.LineInfoOffs);
 
-       /* Free the Name */
-       xfree (Name);
+    /* Output a header */
+    printf ("  Line info:\n");
+
+    /* Check if the object file was compiled with debug info */
+    if ((H.Flags & OBJ_FLAGS_DBGINFO) == 0) {
+       /* Print that there no line infos and bail out */
+       printf ("    Count:%27u\n", 0);
+       return;
+    }
+
+    /* Read the number of line infos and print it */
+    Count = ReadVar (F);
+    printf ("    Count:%27u\n", Count);
+
+    /* Read and print all line infos */
+    for (I = 0; I < Count; ++I) {
+
+       FilePos   Pos;
+
+               /* Read one line info */
+       ReadFilePos (F, &Pos);
+
+       /* Print the header */
+       printf ("    Index:%27u\n", I);
+
+       /* Print the data */
+               printf ("      Line:%26lu\n", Pos.Line);
+               printf ("      Col:%27u\n", Pos.Col);
+               printf ("      Name:%26u\n", Pos.Name);
     }
+
+    /* Destroy the string pool */
+    DestroyStrPool (&StrPool);
 }
 
 
 
+void DumpObjSegSize (FILE* F, unsigned long Offset)
+/* Dump the sizes of the segment in the object file */
+{
+    ObjHeader   H;
+    Collection  StrPool = AUTO_COLLECTION_INITIALIZER;
+    unsigned    Count;
+
+    /* Seek to the header position and read the header */
+    FileSetPos (F, Offset);
+    ReadObjHeader (F, &H);
+
+    /* Seek to the start of the string pool and read it */
+    FileSetPos (F, Offset + H.StrPoolOffs);
+    ReadStrPool (F, &StrPool);
+
+    /* Seek to the start of the segments */
+    FileSetPos (F, Offset + H.SegOffs);
+
+    /* Output a header */
+    printf ("  Segment sizes:\n");
+
+    /* Read the number of segments */
+    Count = ReadVar (F);
+
+    /* Read and print the sizes of all segments */
+    while (Count--) {
+
+               /* Read the data for one segments */
+        unsigned long DataSize = Read32 (F);
+        unsigned long NextSeg  = ftell (F) + DataSize;
+       const char*   Name     = GetString (&StrPool, ReadVar (F));
+       unsigned      Len      = strlen (Name);
+       unsigned long Size     = Read32 (F);
+
+        /* Skip alignment, type and fragment count */
+        (void) Read8 (F);
+        (void) Read8 (F);
+        (void) ReadVar (F);
+
+       /* Print the size for this segment */
+       printf ("    %s:%*s%6lu\n", Name, 24-Len, "", Size);
+
+        /* Seek to the end of the segment data (start of next) */
+        FileSetPos (F, NextSeg);
+    }
+
+    /* Destroy the string pool */
+    DestroyStrPool (&StrPool);
+}
+
+