Added dump of segments
git-svn-id: svn://svn.cc65.org/cc65/trunk@239 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
parent
a63d35278c
commit
f91833caef
3 changed files with 235 additions and 22 deletions
213
src/od65/dump.c
213
src/od65/dump.c
|
@ -36,8 +36,11 @@
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
/* common */
|
/* common */
|
||||||
|
#include "exprdefs.h"
|
||||||
|
#include "filepos.h"
|
||||||
#include "objdefs.h"
|
#include "objdefs.h"
|
||||||
#include "optdefs.h"
|
#include "optdefs.h"
|
||||||
|
#include "segdefs.h"
|
||||||
#include "xmalloc.h"
|
#include "xmalloc.h"
|
||||||
|
|
||||||
/* od65 */
|
/* od65 */
|
||||||
|
@ -59,8 +62,8 @@ static void DumpObjHeaderSection (const char* Name,
|
||||||
/* Dump a header section */
|
/* Dump a header section */
|
||||||
{
|
{
|
||||||
printf (" %s:\n", Name);
|
printf (" %s:\n", Name);
|
||||||
printf (" Offset: %8lu\n", Offset);
|
printf (" Offset:%24lu\n", Offset);
|
||||||
printf (" Size: %8lu\n", Size);
|
printf (" Size: %24lu\n", Size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -84,6 +87,125 @@ static char* TimeToStr (unsigned long Time)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void SkipExpr (FILE* F)
|
||||||
|
/* Skip an expression from the given file */
|
||||||
|
{
|
||||||
|
/* Read the node tag and handle NULL nodes */
|
||||||
|
unsigned char Op = Read8 (F);
|
||||||
|
if (Op == EXPR_NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check the tag and handle the different expression types */
|
||||||
|
if (EXPR_IS_LEAF (Op)) {
|
||||||
|
switch (Op) {
|
||||||
|
|
||||||
|
case EXPR_LITERAL:
|
||||||
|
(void) Read32Signed (F);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EXPR_SYMBOL:
|
||||||
|
/* Read the import number */
|
||||||
|
(void) Read16 (F);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EXPR_SEGMENT:
|
||||||
|
/* Read the segment number */
|
||||||
|
(void) Read8 (F);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
Error ("Invalid expression op: %02X", Op);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
/* 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_LITERAL8:
|
||||||
|
Size = Read8 (F);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FRAG_LITERAL16:
|
||||||
|
Size = Read16 (F);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FRAG_LITERAL24:
|
||||||
|
Size = Read24 (F);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FRAG_LITERAL32:
|
||||||
|
Size = Read32 (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 = Read16 (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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void DumpObjHeader (FILE* F, unsigned long Offset)
|
void DumpObjHeader (FILE* F, unsigned long Offset)
|
||||||
/* Dump the header of the given object file */
|
/* Dump the header of the given object file */
|
||||||
{
|
{
|
||||||
|
@ -101,13 +223,13 @@ void DumpObjHeader (FILE* F, unsigned long Offset)
|
||||||
printf (" Header:\n");
|
printf (" Header:\n");
|
||||||
|
|
||||||
/* Magic */
|
/* Magic */
|
||||||
printf (" Magic: 0x%08lX\n", H.Magic);
|
printf (" Magic:%17s0x%08lX\n", "", H.Magic);
|
||||||
|
|
||||||
/* Version */
|
/* Version */
|
||||||
printf (" Version: %10u\n", H.Version);
|
printf (" Version:%25u\n", H.Version);
|
||||||
|
|
||||||
/* Flags */
|
/* Flags */
|
||||||
printf (" Flags: 0x%04X (", H.Flags);
|
printf (" Flags:%21s0x%04X (", "", H.Flags);
|
||||||
if (H.Flags & OBJ_FLAGS_DBGINFO) {
|
if (H.Flags & OBJ_FLAGS_DBGINFO) {
|
||||||
printf ("OBJ_FLAGS_DBGINFO");
|
printf ("OBJ_FLAGS_DBGINFO");
|
||||||
}
|
}
|
||||||
|
@ -183,10 +305,10 @@ void DumpObjOptions (FILE* F, unsigned long Offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Print the header */
|
/* Print the header */
|
||||||
printf (" Option %u:\n", I);
|
printf (" Index:%27u\n", I);
|
||||||
|
|
||||||
/* Print the data */
|
/* Print the data */
|
||||||
printf (" Type: 0x%02X (%s)\n", Type, TypeDesc);
|
printf (" Type:%22s0x%02X (%s)\n", "", Type, TypeDesc);
|
||||||
switch (ArgType) {
|
switch (ArgType) {
|
||||||
|
|
||||||
case OPT_ARGSTR:
|
case OPT_ARGSTR:
|
||||||
|
@ -251,7 +373,7 @@ void DumpObjFiles (FILE* F, unsigned long Offset)
|
||||||
unsigned Len = strlen (Name);
|
unsigned Len = strlen (Name);
|
||||||
|
|
||||||
/* Print the header */
|
/* Print the header */
|
||||||
printf (" File %u:\n", I);
|
printf (" Index:%27u\n", I);
|
||||||
|
|
||||||
/* Print the data */
|
/* Print the data */
|
||||||
printf (" Name:%*s\"%s\"\n", 24-Len, "", Name);
|
printf (" Name:%*s\"%s\"\n", 24-Len, "", Name);
|
||||||
|
@ -265,3 +387,78 @@ 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;
|
||||||
|
|
||||||
|
/* Seek to the header position */
|
||||||
|
FileSeek (F, Offset);
|
||||||
|
|
||||||
|
/* Read the header */
|
||||||
|
ReadObjHeader (F, &H);
|
||||||
|
|
||||||
|
/* Seek to the start of the options */
|
||||||
|
FileSeek (F, Offset + H.SegOffs);
|
||||||
|
|
||||||
|
/* Output a header */
|
||||||
|
printf (" Segments:\n");
|
||||||
|
|
||||||
|
/* Read the number of files and print it */
|
||||||
|
Count = Read8 (F);
|
||||||
|
printf (" Count:%27u\n", Count);
|
||||||
|
|
||||||
|
/* Read and print all options */
|
||||||
|
for (I = 0; I < Count; ++I) {
|
||||||
|
|
||||||
|
/* Read the data for one segments */
|
||||||
|
char* Name = ReadMallocedStr (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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Print the header */
|
||||||
|
printf (" Index:%27u\n", I);
|
||||||
|
|
||||||
|
/* Print the data */
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Print the fragment count */
|
||||||
|
printf (" Fragment count:%16u\n", FragCount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -57,6 +57,9 @@ void DumpObjOptions (FILE* F, unsigned long Offset);
|
||||||
void DumpObjFiles (FILE* F, unsigned long Offset);
|
void DumpObjFiles (FILE* F, unsigned long Offset);
|
||||||
/* Dump the source files */
|
/* Dump the source files */
|
||||||
|
|
||||||
|
void DumpObjSegments (FILE* F, unsigned long Offset);
|
||||||
|
/* Dump the segments in the object file */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* End of dump.h */
|
/* End of dump.h */
|
||||||
|
|
|
@ -79,7 +79,8 @@ static void Usage (void)
|
||||||
"Long options:\n"
|
"Long options:\n"
|
||||||
" --dump-files\t\tDump the source files\n"
|
" --dump-files\t\tDump the source files\n"
|
||||||
" --dump-header\t\tDump the object file header\n"
|
" --dump-header\t\tDump the object file header\n"
|
||||||
" --dump-options\t\tDump object file options\n"
|
" --dump-options\tDump object file options\n"
|
||||||
|
" --dump-segments\tDump the segments in the file\n"
|
||||||
" --help\t\tHelp (this text)\n"
|
" --help\t\tHelp (this text)\n"
|
||||||
" --version\t\tPrint the version number and exit\n",
|
" --version\t\tPrint the version number and exit\n",
|
||||||
ProgName);
|
ProgName);
|
||||||
|
@ -111,6 +112,14 @@ static void OptDumpOptions (const char* Opt, const char* Arg)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void OptDumpSegments (const char* Opt, const char* Arg)
|
||||||
|
/* Dump the segments in the object file */
|
||||||
|
{
|
||||||
|
What |= D_SEGMENTS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void OptHelp (const char* Opt, const char* Arg)
|
static void OptHelp (const char* Opt, const char* Arg)
|
||||||
/* Print usage information and exit */
|
/* Print usage information and exit */
|
||||||
{
|
{
|
||||||
|
@ -170,6 +179,9 @@ static void DumpFile (const char* Name)
|
||||||
if (What & D_FILES) {
|
if (What & D_FILES) {
|
||||||
DumpObjFiles (F, 0);
|
DumpObjFiles (F, 0);
|
||||||
}
|
}
|
||||||
|
if (What & D_SEGMENTS) {
|
||||||
|
DumpObjSegments (F, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Close the file */
|
/* Close the file */
|
||||||
|
@ -186,6 +198,7 @@ int main (int argc, char* argv [])
|
||||||
{ "--dump-files", 0, OptDumpFiles },
|
{ "--dump-files", 0, OptDumpFiles },
|
||||||
{ "--dump-header", 0, OptDumpHeader },
|
{ "--dump-header", 0, OptDumpHeader },
|
||||||
{ "--dump-options", 0, OptDumpOptions },
|
{ "--dump-options", 0, OptDumpOptions },
|
||||||
|
{ "--dump-segments", 0, OptDumpSegments },
|
||||||
{ "--help", 0, OptHelp },
|
{ "--help", 0, OptHelp },
|
||||||
{ "--version", 0, OptVersion },
|
{ "--version", 0, OptVersion },
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Reference in a new issue