home *** CD-ROM | disk | FTP | other *** search
/ Enigma Amiga Life 113 / EnigmaAmiga113CD.iso / software / utilities / hunkfunc / source / hunkfunc.c next >
Encoding:
C/C++ Source or Header  |  2000-06-26  |  16.1 KB  |  625 lines

  1. #define NAME     "HunkFunc"
  2. #define REVISION "12"
  3.  
  4. /* Programmheader
  5.  
  6.     Name:        HunkFunk
  7.     Author:        SDI
  8.     Distribution:    PD
  9.     Description:    object/binary file scanner
  10.     Compileropts:    -
  11.     Linkeropts:    -gsi -l amiga
  12.  
  13.  1.0   12.02.98 : made with help of Olaf 'Olsen' Barthel's HunkFunk
  14.  1.1   23.03.98 : now prints reloc infos
  15.  1.2   23.11.98 : added new overlay format
  16.  1.3   09.12.98 : added CHIP, FAST, ADVISORY to CODE/DATA/BSS hunks
  17.  1.4   28.12.98 : unknown hunk now prints 8 digits
  18.  1.5   30.08.99 : 4 new switches for command line, fixed lots of stuff
  19.  1.6   13.09.99 : better support for Overlay files
  20.  1.7   15.09.99 : changed overlay support, added SOVT keyword
  21.  1.8   27.09.99 : displays extra stuff message
  22.  1.9   03.11.99 : added number of EXT_REF's
  23.  1.10  13.11.99 : added H&P EHF stuff
  24.  1.11  29.11.99 : added CTRL_C to reloc print
  25.  1.12  26.06.00 : added abort for defective relocs, fixed overflow bugs
  26. */
  27.  
  28. #include <proto/dos.h>
  29. #include <proto/exec.h>
  30. #include <exec/memory.h>
  31. #include <dos/doshunks.h>
  32. #include "SDI_version.h"
  33. #define SDI_TO_ANSI
  34. #include "SDI_ASM_STD_protos.h"
  35.  
  36. /* CHIP, FAST and ADVISORY information is repeated in hunk itself. If
  37. the word is used normally, the information is in second longword (size).
  38. If it is preceeded by a '_', the information is in first longword (hunk
  39. type). */
  40.  
  41. #define PARAM "FILE/M/A,SREL=SHOWRELOC/S,SSYM=SHOWSYMBOL/S,SEXT=SHOWEXTERN/S,SOVT=SHOWOVERLAYTABLE/S,STATS/S"
  42.  
  43. /* Some simple macros. */
  44. #define ReadLong(Type)      Read(FileHandle, (Type), 4)
  45. #define ReadWord(Type)      Read(FileHandle, (Type), 2)
  46. #define ReadName(Longs)   Read(FileHandle, NameString, 4 * (Longs))
  47. #define SkipLong(Longs)   Seek(FileHandle, 4 * (Longs), OFFSET_CURRENT)
  48. #define SkipWord(Words)      Seek(FileHandle, 2* (Words), OFFSET_CURRENT)
  49. #define SkipByte(Bytes)      Seek(FileHandle, (Bytes), OFFSET_CURRENT)
  50. #define MakeName(Longs)   NameString[(Longs) * 4] = 0
  51. #define GetHunkName(Type) HunkNames[(Type)-HUNK_UNIT]
  52. #define CTRL_C          (SetSignal(0L,0L) & SIGBREAKF_CTRL_C)
  53.  
  54. STRPTR HunkNames[] = { /* access them with HunkNames[Type-HUNK_UNIT] */
  55. "HUNK_UNIT",    "HUNK_NAME",    "HUNK_CODE",    "HUNK_DATA",    "HUNK_BSS", 
  56. "HUNK_(ABS)RELOC32",    "HUNK_(REL)RELOC16",    "HUNK_(REL)RELOC8",    "HUNK_EXT",    "HUNK_SYMBOL",
  57. "HUNK_DEBUG",    "HUNK_END",    "HUNK_HEADER",    "",        "HUNK_OVERLAY",
  58. "HUNK_BREAK",    "HUNK_DREL32",    "HUNK_DREL16",    "HUNK_DREL8",    "HUNK_LIB",
  59. "HUNK_INDEX",    "HUNK_RELOC32SHORT",    "HUNK_RELRELOC32",    "HUNK_ABSRELOC16",
  60. "HUNK_DREL32EXE"
  61. };
  62.  
  63. #define HUNK_DREL32EXE    (HUNK_ABSRELOC16+1)
  64.  
  65. #define HUNK_PPC_CODE    0x4E9
  66. #define HUNK_RELRELOC26    0x4EC
  67. #define EXT_RELREF26    229
  68.  
  69. struct Args {
  70.   STRPTR * files;
  71.   ULONG    showreloc;
  72.   ULONG    showsymbol;
  73.   ULONG    showextern;
  74.   ULONG       showoverlaytable;
  75.   ULONG    stats;
  76. };
  77.  
  78. struct Stats {
  79.   ULONG Header;
  80.   ULONG Unit;
  81.   ULONG Lib;
  82.   ULONG Code;
  83.   ULONG Data;
  84.   ULONG BSS;
  85.   ULONG Debug;
  86.   ULONG Symbol;
  87.   ULONG Extern;
  88.   ULONG Reloc;
  89.   ULONG NumSymbol;
  90.   ULONG NumReloc;
  91.   ULONG NumExtern;
  92.   ULONG CodeSize;
  93.   ULONG DataSize;
  94.   ULONG BSSSize;
  95.   ULONG DebugSize;
  96.   ULONG PPCCode;
  97.   ULONG PPCCodeSize;
  98. };
  99.  
  100. struct DosLibrary *DOSBase = 0;
  101. struct ExecBase * SysBase  = 0;
  102.  
  103. STRPTR GetTabs(STRPTR);
  104. void ShowStats(struct Stats *);
  105. LONG ProcessFile(ULONG, ULONG, ULONG, ULONG, ULONG, struct Stats *);
  106.  
  107. ULONG start(void)
  108. {
  109.   ULONG ret = RETURN_FAIL;
  110.   struct DosLibrary *dosbase;
  111.   SysBase = (*((struct ExecBase **) 4));
  112.  
  113.   { /* test for WB and reply startup-message */
  114.     struct Process *task;
  115.     if(!(task = (struct Process *) FindTask(0))->pr_CLI)
  116.     {
  117.       WaitPort(&task->pr_MsgPort);
  118.       Forbid();
  119.       ReplyMsg(GetMsg(&task->pr_MsgPort));
  120.       return RETURN_FAIL;
  121.     }
  122.   }
  123.  
  124.   if((dosbase = (struct DosLibrary *) OpenLibrary("dos.library", 37)))
  125.   {
  126.     struct Args args;
  127.     struct RDArgs *rda;
  128.  
  129.     DOSBase = dosbase;
  130.  
  131.     memset(&args, 0, sizeof(struct Args));
  132.     if((rda = ReadArgs(PARAM, (LONG *) &args, 0)))
  133.     {
  134.       ret = 0;
  135.       while(*args.files)
  136.       {
  137.         ULONG err, fh;
  138.  
  139.         if((fh = Open(*args.files, MODE_OLDFILE)))
  140.         {
  141.       struct Stats stats;
  142.  
  143.           Printf("File '%s':\n", *args.files);
  144.           memset(&stats, 0, sizeof(struct Stats));
  145.           err = ProcessFile(fh, args.showreloc, args.showsymbol, args.showextern, args.showoverlaytable, &stats);
  146.           if(err == 2)
  147.             Printf("Unexpected end of file.\n");
  148.           if(args.stats)
  149.             ShowStats(&stats);
  150.           Close(fh);
  151.         }
  152.         else
  153.           PrintFault(IoErr(), *args.files);
  154.         if(CTRL_C)
  155.           SetIoErr(ERROR_BREAK);
  156.         ++args.files;
  157.       }
  158.     }
  159.     
  160.     if(ret)
  161.       PrintFault(IoErr(), 0);
  162.  
  163.     CloseLibrary((struct Library *) dosbase);
  164.   }
  165.   return ret;
  166. }
  167.  
  168. STRPTR GetTabs(STRPTR NameString)
  169. {
  170.   ULONG i = 0;
  171.  
  172.   while(*(NameString++) && i < 24)
  173.    ++i;
  174.   i >>= 3;
  175.   
  176.   return "\t\t\t"+i;
  177. }
  178.  
  179. void ShowStats(struct Stats *stats)
  180. {
  181.   Printf("STATISTICS:\nFile type\t");
  182.   if(stats->PPCCode)
  183.     Printf("PPC-WOS Objectfile");
  184.   else if(stats->Header)
  185.     Printf("Executable");
  186.   else if(stats->Lib)
  187.     Printf("New style link library");
  188.   else if(stats->Unit > 1)
  189.     Printf("Old style link library");
  190.   else
  191.     Printf("Objectfile");
  192.   Printf("\n");
  193.  
  194.   Printf("HUNK_CODE\t%6ld with total %6ld ($%06lx) Bytes\n", stats->Code, stats->CodeSize, stats->CodeSize);
  195.   if(stats->PPCCode)
  196.     Printf("HUNK_PPC_CODE\t%6ld with total %6ld ($%06lx) Bytes\n", stats->PPCCode, stats->PPCCodeSize, stats->PPCCodeSize);
  197.   Printf("HUNK_DATA\t%6ld with total %6ld ($%06lx) Bytes\n", stats->Data, stats->DataSize, stats->DataSize);
  198.   Printf("HUNK_BSS\t%6ld with total %6ld ($%06lx) Bytes\n", stats->BSS, stats->BSSSize, stats->BSSSize);
  199.   Printf("HUNK_DEBUG\t%6ld with total %6ld ($%06lx) Bytes\n", stats->Debug, stats->DebugSize, stats->DebugSize);
  200.   Printf("HUNK_EXT\t%6ld with total %6ld entr%s\n", stats->Extern, stats->NumExtern, stats->NumExtern == 1 ? "y" : "ies");
  201.   Printf("HUNK_RELOC\t%6ld with total %6ld entr%s\n", stats->Reloc, stats->NumReloc, stats->NumReloc == 1 ? "y" : "ies");
  202.   Printf("HUNK_SYMBOL\t%6ld with total %6ld entr%s\n", stats->Symbol, stats->NumSymbol, stats->NumSymbol == 1 ? "y" : "ies");
  203. }
  204.  
  205. /* return 0 on error */
  206. LONG ProcessFile(ULONG FileHandle, ULONG showreloc, ULONG showsymbol, ULONG showextern, ULONG showoverlaytable,
  207. struct Stats *stats)
  208. {
  209.   ULONG Type, Data, i;
  210.   UBYTE NameString[257];
  211.  
  212.   while(!CTRL_C)
  213.   {
  214.     if((i = ReadLong(&Type)) != 4)
  215.     {
  216.       if(i)
  217.         Printf("There %s %ld extra byte%s at end of file.\n", i == 1 ? "is" : "are", i, i == 1 ? "" : "s");
  218.       return 0;
  219.     }
  220.  
  221.     if(Type == HUNK_DREL32 && stats->Header)
  222.       Type = HUNK_DREL32EXE;
  223.  
  224.     /* Look which type it is. */
  225.     switch(Type & 0xFFFF)
  226.     {
  227.     case HUNK_UNIT:
  228.       ++stats->Unit;
  229.       ReadLong(&Data);
  230.       if(Data)
  231.         ReadName(Data);
  232.       MakeName(Data);
  233.       Printf("%s\t\"%s\"\n\n", GetHunkName(Type), NameString);
  234.       break;
  235.     case HUNK_NAME:
  236.       ReadLong(&Data);
  237.       if(Data)
  238.         ReadName(Data);
  239.       MakeName(Data);
  240.       Printf("%s\t\"%s\"\n", GetHunkName(Type), NameString);
  241.       break;
  242.     case HUNK_LIB:
  243.       ++stats->Lib;
  244.       ReadLong(&Data);
  245.       Printf("%s\t%6ld ($%06lx) Bytes\n\n", GetHunkName(Type), Data, Data);
  246.       break;
  247.     case HUNK_INDEX:
  248.       {
  249.         UWORD dat2;
  250.  
  251.         ReadLong(&Data);
  252.         Printf("%s\t%6ld ($%06lx) Bytes\n", GetHunkName(Type), Data, Data);
  253.         ReadWord(&dat2);
  254.         SkipByte((Data*4)-2);
  255.     Printf("  Textsize =\t%6ld Bytes\n\n", dat2);
  256.       }
  257.       break;
  258.     case HUNK_CODE: case HUNK_DATA: case HUNK_BSS:
  259.       ReadLong(&Data);
  260.       i = Data;
  261.       Data <<= 2;
  262.       Data &= 0x7FFFFFFF;
  263.       switch(Type&0xFFFF)
  264.       {
  265.       case HUNK_CODE: ++stats->Code; stats->CodeSize += Data; SkipByte(Data); break;
  266.       case HUNK_DATA: ++stats->Data; stats->DataSize += Data; SkipByte(Data); break;
  267.       case HUNK_BSS: ++stats->BSS; stats->BSSSize += Data; break;
  268.       }
  269.       Printf("%s\t%6ld ($%06lx) Bytes", GetHunkName(Type), Data, Data);
  270.       if(Type & HUNKF_CHIP)        Printf(" _CHIP");
  271.       if(Type & HUNKF_FAST)        Printf(" _FAST");
  272.       if(Type & HUNKF_ADVISORY)     Printf(" _ADVISORY");
  273.       if(i & HUNKF_CHIP)        Printf(" CHIP");
  274.       if(i & HUNKF_FAST)        Printf(" FAST");
  275.       if(i & HUNKF_ADVISORY)         Printf(" ADVISORY");
  276.       Printf("\n");
  277.       break;
  278.     case HUNK_PPC_CODE:
  279.       ReadLong(&Data);
  280.       i = Data;
  281.       Data <<= 2;
  282.       Data &= 0x7FFFFFFF;
  283.       ++stats->PPCCode; stats->PPCCodeSize += Data;
  284.       SkipByte(Data);
  285.       Printf("HUNK_PPC_CODE\t%6ld ($%06lx) Bytes", Data, Data);
  286.       if(Type & HUNKF_CHIP)        Printf(" _CHIP");
  287.       if(Type & HUNKF_FAST)        Printf(" _FAST");
  288.       if(Type & HUNKF_ADVISORY)     Printf(" _ADVISORY");
  289.       if(i & HUNKF_CHIP)        Printf(" CHIP");
  290.       if(i & HUNKF_FAST)        Printf(" FAST");
  291.       if(i & HUNKF_ADVISORY)         Printf(" ADVISORY");
  292.       Printf("\n");
  293.       break;
  294.     case HUNK_RELRELOC32: case HUNK_ABSRELOC16: case HUNK_RELRELOC26:
  295.     case HUNK_RELOC32: case HUNK_RELOC16: case HUNK_RELOC8:
  296.     case HUNK_DREL32: case HUNK_DREL16: case HUNK_DREL8:
  297.       if(Type == HUNK_RELRELOC26)
  298.         Printf("HUNK_RELRELOC26\n");
  299.       else
  300.         Printf("%s\n", GetHunkName(Type));
  301.       ++stats->Reloc;
  302.  
  303.       do
  304.       {
  305.     if(ReadLong(&Data) != 4)
  306.       return 2;
  307.     if(Data)
  308.     {
  309.       ULONG dat2 = 0, dat3;
  310.       ReadLong(&dat2);
  311.       stats->NumReloc += Data;
  312.       Printf("  Summary\t%6ld entr%s to hunk %ld\n", Data,
  313.       Data == 1 ? "y" : "ies", dat2);
  314.       if(showreloc)
  315.       {
  316.         for(dat3 = Data; dat3 && !CTRL_C; --dat3)
  317.         {
  318.           if(ReadLong(&dat2) != 4)
  319.             return 2;
  320.           Printf("  Offset\t\t$%08lx\n", dat2);
  321.         }
  322.       }
  323.       else
  324.         SkipLong(Data);
  325.     }
  326.       } while(!CTRL_C && Data);
  327.       break;
  328.     case HUNK_RELOC32SHORT: case HUNK_DREL32EXE:
  329.       {
  330.         UWORD Data = 0;
  331.         ULONG nums = 0;
  332.         Printf("%s\n", GetHunkName(Type));
  333.         ++stats->Reloc;
  334.  
  335.         do
  336.         {
  337.       UWORD dat2 = 0;
  338.       ULONG dat3;
  339.       if(ReadWord(&Data) != 2)
  340.         return 2;
  341.       if(Data)
  342.       {
  343.             ReadWord(&dat2);
  344.             stats->NumReloc += Data;
  345.         Printf("  Summary\t%6ld entr%s to hunk %ld\n", Data,
  346.         Data == 1 ? "y" : "ies", dat2);
  347.         if(showreloc)
  348.         {
  349.           for(dat3 = Data; dat3 && !CTRL_C; --dat3)
  350.           {
  351.             if(ReadWord(&dat2) != 2)
  352.               return 2;
  353.             Printf("  Offset\t\t$%04lx\n", dat2);
  354.           }
  355.         }
  356.         else
  357.           SkipWord(Data);
  358.         nums += Data;
  359.       }
  360.         } while(!CTRL_C && Data);
  361.         if(!(nums & 1))
  362.           SkipWord(1);
  363.       }
  364.       break;
  365.     case HUNK_EXT:
  366.       Printf("HUNK_EXT\n");
  367.       ++stats->Extern;
  368.  
  369.       do
  370.       {
  371.     LONG i;
  372.  
  373.         ReadLong(&Data);
  374.         if(!Data)
  375.       break;
  376.     ++stats->NumExtern;
  377.     if(showextern)
  378.     {
  379.           switch((Data >> 24) & 0xFF)
  380.       {
  381.       case EXT_DEF:       Printf("  EXT_DEF"); break;
  382.       case EXT_ABS:       Printf("  EXT_ABS"); break;
  383.       case EXT_RES:       Printf("  EXT_RES"); break;
  384.       case EXT_REF32:     Printf("  EXT_REF32"); break;
  385.       case EXT_COMMON:    Printf("  EXT_COMMON"); break;
  386.       case EXT_REF16:     Printf("  EXT_REF16"); break;
  387.       case EXT_REF8:      Printf("  EXT_REF8"); break;
  388.       case EXT_DEXT32:    Printf("  EXT_DEXT32"); break;
  389.       case EXT_DEXT16:    Printf("  EXT_DEXT16"); break;
  390.       case EXT_DEXT8:     Printf("  EXT_DEXT8"); break;
  391.       case EXT_RELREF32:  Printf("  EXT_RELREF32"); break;
  392.       case EXT_RELREF26:  Printf("  EXT_RELREF26"); break;
  393.       case EXT_RELCOMMON: Printf("  EXT_RELCOMMON"); break;
  394.       default: Printf("  EXT_??? ($%02x)\n",(Data >> 24) & 0xFF);
  395.         break;
  396.           }
  397.         }
  398.  
  399.     /* Is it followed by a symbol name? */
  400.  
  401.     if(Data & 0xFFFFFF)
  402.     {
  403.       ReadName(Data & 0xFFFFFF);
  404.       MakeName(Data & 0xFFFFFF);
  405.       if(showextern)
  406.             Printf("\t%s", NameString);
  407.         }
  408.  
  409.     /* Remember extension type. */
  410.         i = (Data >> 24) & 0xFF;
  411.  
  412.     /* Display value of symbol. */
  413.         if(i == EXT_DEF || i == EXT_ABS || i == EXT_RES)
  414.         {
  415.       if(!(Data & 0xFFFFFF) && showextern)
  416.         Printf("\t???");
  417.  
  418.       ReadLong(&Data);
  419.       if(showextern)
  420.         Printf("%s= $%08lx", GetTabs(NameString), Data);
  421.     }
  422.  
  423.     /* Skip relocation information. */
  424.         if(i == EXT_REF32 || i == EXT_REF16 || i == EXT_REF8 ||
  425.         i == EXT_DEXT32 || i == EXT_DEXT16 || i == EXT_DEXT8 ||
  426.         i == EXT_RELREF32 || i == EXT_RELREF26)
  427.     {
  428.       ReadLong(&Data);
  429.       if(showextern)
  430.         Printf("%s= %ld entr%s", GetTabs(NameString), Data, Data == 1 ? "y" : "ies");
  431.       SkipLong(Data);
  432.     }
  433.  
  434.     /* Display size of common block. */
  435.         if(i == EXT_COMMON || i == EXT_RELCOMMON)
  436.     {
  437.       ReadLong(&Data);
  438.  
  439.       if(showextern)
  440.         Printf("\tSize = %ld Bytes", Data << 2);
  441.       ReadLong(&Data);
  442.       SkipLong(Data);
  443.     }
  444.     if(showextern)
  445.           Printf("\n");
  446.       } while(!CTRL_C);
  447.       break;
  448.     case HUNK_SYMBOL:
  449.       Printf("HUNK_SYMBOL\n");
  450.       ++stats->Symbol;
  451.  
  452.       do
  453.       {
  454.     ReadLong(&Data);
  455.  
  456.     if(!Data)
  457.       break;
  458.  
  459.     ++stats->NumSymbol;
  460.     /* Display name. */
  461.         ReadName(Data & 0xFFFFFF);
  462.         MakeName(Data & 0xFFFFFF);
  463.  
  464.     if(showsymbol)
  465.           Printf("  Symbol\t%s", NameString);
  466.  
  467.     /* Display value. */
  468.         ReadLong(&Data);
  469.  
  470.     if(showsymbol)
  471.       Printf("%s= $%08lx\n", GetTabs(NameString), Data);
  472.       } while(!CTRL_C);
  473.       break;
  474.     case HUNK_DEBUG:
  475.       ++stats->Debug;
  476.       ReadLong(&Data);
  477.       SkipLong(Data);
  478.       Data <<= 2;
  479.       stats->DebugSize += Data;
  480.       Printf("HUNK_DEBUG\t%6ld ($%06lx) Bytes\n", Data, Data);
  481.       break;
  482.     case HUNK_END:
  483.       Printf("HUNK_END\n\n");
  484.       break;
  485.     case HUNK_HEADER:
  486.       Printf("HUNK_HEADER\n");
  487.  
  488.       ++stats->Header;
  489.  
  490.       do
  491.       {
  492.         ULONG data2;
  493.  
  494.     if(ReadLong(&Data) != 4)
  495.       return 2;
  496.  
  497.     /* Display names of resident libraries. */
  498.         if(!Data)
  499.           break;
  500.  
  501.     if((data2 = Data) > 64)
  502.       data2 = 64;
  503.     Data -= data2;
  504.  
  505.     if(ReadName(data2) != 4*data2)
  506.       return 2;
  507.     if(Data && SkipLong(Data) < 0)
  508.       return 2;
  509.     MakeName(data2);
  510.  
  511.     Printf("  Name =\t%s\n", NameString);
  512.       } while(!CTRL_C);
  513.  
  514.       if(!CTRL_C)
  515.       {
  516.         LONG i,From,To;
  517.  
  518.         ReadLong(&Data);
  519.  
  520.     Printf("  Numhunks =\t%6ld (", Data);
  521.         ReadLong(&From);
  522.         Printf("%ld to ", From);
  523.         ReadLong(&To);
  524.         Printf("%ld)\n",To);
  525.  
  526.         /* Display hunk lengths/types. */
  527.         for(i = 0; !CTRL_C && i < To - From + 1; ++i)
  528.         {
  529.       ReadLong(&Data);
  530.           Printf("  Hunk %03ld =\t%6ld ($%06lx) Bytes", i,
  531.           (Data & 0x3FFFFFFF) << 2, (Data & 0x3FFFFFFF) << 2);
  532.  
  533.       if((Data & HUNKF_CHIP) && (Data & HUNKF_FAST))
  534.       {    /* extended type */
  535.         ULONG t;
  536.         ReadLong(&t);
  537.         Printf(" MEMTYPE($%08lx)", t);
  538.       }
  539.       else
  540.       {
  541.             if(Data & HUNKF_CHIP)    Printf(" CHIP");
  542.             if(Data & HUNKF_FAST)    Printf(" FAST");
  543.           }
  544.           if(Data & HUNKF_ADVISORY)    Printf(" ADVISORY");
  545.  
  546.       Printf("\n");
  547.         }
  548.         Printf("\n");
  549.       }
  550.       break;
  551.     case HUNK_OVERLAY:
  552.       {
  553.         LONG TabSize, Data, Data2 = 0;
  554.         ULONG *ovt = 0;
  555.         Printf("HUNK_OVERLAY\n");
  556.         ReadLong(&TabSize);
  557.  
  558.     Printf("  TableSize\t%6ld ($%06lx) Bytes\n", TabSize*4, TabSize*4);
  559.  
  560.     if(TabSize)
  561.     {
  562.       ReadLong(&Data2);
  563.       if(showoverlaytable && (ovt = (ULONG *) AllocVec(TabSize*4, MEMF_ANY)))
  564.         Read(FileHandle, ovt, TabSize*4);
  565.       else
  566.         SkipLong(TabSize);
  567.     }
  568.     ReadLong(&Data);
  569.     if(!TabSize && Data == HUNK_BREAK)
  570.     {
  571.       Data = Seek(FileHandle, 0, OFFSET_END);
  572.       Data = Seek(FileHandle, 0, OFFSET_END) - Data;
  573.       Printf("HUNK_BREAK\n\nLeft Space\t%6ld ($%06lx) Bytes\n", Data, Data);
  574.     }
  575.     else if(TabSize && Data >= HUNK_UNIT && Data <= HUNK_ABSRELOC16)
  576.     {
  577.       Seek(FileHandle, -4, OFFSET_CURRENT);
  578.       Printf("  Levels\t%6ld\n", Data2-2);
  579.       Printf("  Entries\t%6ld\n", (TabSize-Data2+1) >> 3);
  580.     }
  581.     else
  582.     {
  583.       Data = Seek(FileHandle, 0, OFFSET_END);
  584.       Data = Seek(FileHandle, 0, OFFSET_END) - Data;
  585.       Printf("  DataSize\t%6ld ($%06lx) Bytes\n", Data+8, Data+8);
  586.       if(ovt)
  587.       {
  588.         for(Data = TabSize-1; Data; --Data)
  589.           ovt[Data] = ovt[Data-1];
  590.         ovt[0] = Data2;
  591.       }
  592.     }
  593.     if(ovt)
  594.     {
  595.       Data2 = 0;
  596.       while(Data2 < TabSize)
  597.       {
  598.         Printf("  Data $%04lx\t", Data2*4);
  599.         for(Data = 0; Data < 4; ++Data)
  600.         {
  601.           if(Data2 < TabSize)
  602.           {
  603.             Printf("%08lx%s", ovt[Data2], Data2 < TabSize-1 ? " " : "");
  604.             ++Data2;
  605.           }
  606.         }
  607.         Printf("\n");
  608.       }
  609.       FreeVec(ovt);
  610.     }
  611.     Printf("\n");
  612.       }
  613.       break;
  614.     case HUNK_BREAK:
  615.       Printf("HUNK_BREAK\n\n");
  616.       break;
  617.     default:
  618.       Printf("HUNK_??? ($%08lx) - Aborting!\n\n", Type);
  619.       return 1;
  620.     }
  621.   }
  622.  
  623.   return 0;
  624. }
  625.