home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Geek Gadgets 1
/
ADE-1.bin
/
ade-dist
/
dumphunks-1.0-src.tgz
/
tar.out
/
contrib
/
dumphunks
/
dumphunks.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-09-28
|
12KB
|
565 lines
/*
* A quick and dirty program to dump the contents of an
* AmigaOS format object file or executable file in a
* human readable form, for people doing maintenance on
* tools that generate or read such formats.
*
* Fred Fish, March 1995
*
* FIXME: Use macros to access data in endian independant
* manner so can be used in cross environment.
*
*/
#include <stdio.h>
int code_flag; /* Don't dump code hunk */
int data_flag; /* Don't dump data hunk */
int debug_flag; /* Don't dump debug hunks */
int reloc_flag; /* Don't dump reloc hunks */
int symbol_flag; /* Don't dump symbol hunks */
int error_flag; /* Set if error occurs */
char *filename; /* Name of current input file */
int hunkcount;
#ifdef __STDC__
# define PARAMS(a) a
#else
# define PARAMS(a) ()
#endif
static void dump_file PARAMS ((FILE *fp));
static long readlong PARAMS ((FILE *fp));
static void dump_hunk_header PARAMS ((FILE *fp));
static void dump_string PARAMS ((FILE *fp, long count, int suppress));
static void dump_hunk PARAMS ((FILE *fp, long hunkid));
static void dump_counted_data PARAMS ((FILE *fp, long count, char* desc, int suppress));
static void dump_reloc_hunk PARAMS ((FILE *fp));
static void dump_symbols PARAMS ((FILE *fp));
static void dump_hunk_bss PARAMS ((FILE *fp));
static void dump_debug PARAMS ((FILE *fp));
static void dump_hunk_unit PARAMS ((FILE *fp));
static void dump_hunk_name PARAMS ((FILE *fp));
#define EMIT_OFFSET(fp) printf ("%8.8x: ", ftell (fp) - sizeof (long))
#define EMIT_VALUE(fp, val) EMIT_OFFSET (fp); printf ("%8.8x ", val)
#define HUNK_UNIT 0x03e7
#define HUNK_NAME 0x03e8
#define HUNK_CODE 0x03e9
#define HUNK_DATA 0x03ea
#define HUNK_BSS 0x03eb
#define HUNK_RELOC32 0x03ec
#define HUNK_RELOC16 0x03ed
#define HUNK_RELOC8 0x03ee
#define HUNK_EXT 0x03ef
#define HUNK_SYMBOL 0x03f0
#define HUNK_DEBUG 0x03f1
#define HUNK_END 0x03f2
#define HUNK_HEADER 0x03f3
#define HUNK_OVERLAY 0x03f5
#define HUNK_BREAK 0x03f6
#define SYMBOL_HUNK_TERMINATOR 0
#define EXT_SYMB 0x00
#define EXT_DEF 0x01
#define EXT_ABS 0x02
#define EXT_RES 0x03
#define EXT_REF32 0x81
#define EXT_COMMON 0x82
#define EXT_REF16 0x83
#define EXT_REF8 0x84
#define EXT_SASC86 0x86
int main (argc, argv)
int argc;
char *argv[];
{
int ch;
FILE *fp;
extern int optind;
extern char *optarg;
/* Process all command line arguments. */
while ((ch = getopt (argc, argv, "cdDhr")) != EOF)
{
switch (ch)
{
case 'c':
code_flag++;
break;
case 'd':
data_flag++;
break;
case 'D':
debug_flag++;
break;
case 'h':
code_flag++;
data_flag++;
debug_flag++;
reloc_flag++;
symbol_flag++;
break;
case 'r':
reloc_flag++;
break;
case 's':
symbol_flag++;
break;
case '?':
error_flag++;
break;
}
}
/* If error during command line argument parsing, give
usage message and exit with error. */
if (error_flag)
{
fflush (stdout);
fprintf (stderr, "usage: dumphunks [-cdDhr] <filetodump\n");
exit (1);
}
/* If there are arguments remaining on the command line, they
are filenames to process, so process each one. Otherwise,
process stdin. */
if (optind < argc)
{
for (; optind < argc; optind++)
{
filename = argv[optind];
fp = fopen (filename, "r");
if (fp != NULL)
{
dump_file (fp);
}
else
{
fprintf (stderr, "dumphunks: %s: can't open for read: ",
filename);
perror ("");
}
}
}
else
{
filename = "<stdin>";
dump_file (stdin);
}
/* All done, return success. */
return (0);
}
/*
* Dump the file. The first hunk has to be a HUNK_HEADER
* or HUNK_UNIT type hunk. Simply loop, dumping each
* hunk's contents.
*/
static void dump_file (fp)
FILE *fp;
{
long HunkID;
printf ("Dump of '%s':\n\n", filename);
HunkID = readlong (fp);
if ((HunkID != HUNK_HEADER) && (HunkID != HUNK_UNIT))
{
fflush (stdout);
fprintf (stderr, "dumphunks: %s: not correct format\n", filename);
exit (1);
}
do
{
dump_hunk (fp, HunkID);
if (hunkcount > 0)
{
HunkID = readlong (fp);
}
} while (hunkcount > 0);
}
static void dump_hunk (fp, HunkID)
FILE *fp;
long HunkID;
{
EMIT_VALUE (fp, HunkID);
switch (HunkID)
{
case HUNK_UNIT:
printf ("HUNK_UNIT\n");
dump_hunk_unit (fp);
break;
case HUNK_NAME:
printf ("HUNK_NAME\n");
dump_hunk_name (fp);
break;
case HUNK_CODE:
printf ("HUNK_CODE\n");
dump_counted_data (fp, 0, "code", code_flag);
break;
case HUNK_DATA:
printf ("HUNK_DATA\n");
dump_counted_data (fp, 0, "data", data_flag);
break;
case HUNK_BSS:
printf ("HUNK_BSS\n");
dump_hunk_bss (fp);
break;
case HUNK_RELOC32:
printf ("HUNK_RELOC32\n");
dump_reloc_hunk (fp);
break;
case HUNK_RELOC16:
printf ("HUNK_RELOC16\n");
dump_reloc_hunk (fp);
break;
case HUNK_RELOC8:
printf ("HUNK_RELOC8\n");
dump_reloc_hunk (fp);
break;
case HUNK_EXT:
printf ("HUNK_EXT\n");
dump_symbols (fp);
break;
case HUNK_SYMBOL:
printf ("HUNK_SYMBOL\n");
dump_symbols (fp);
break;
case HUNK_DEBUG:
printf ("HUNK_DEBUG\n");
dump_debug (fp);
break;
case HUNK_END:
printf ("HUNK_END\n");
hunkcount--;
break;
case HUNK_HEADER:
printf ("HUNK_HEADER\n");
dump_hunk_header (fp);
break;
case HUNK_OVERLAY:
printf ("HUNK_OVERLAY\n");
fflush (stdout);
fprintf (stderr, "can't handle HUNK_OVERLAY yet\n");
exit (1);
break;
case HUNK_BREAK:
printf ("HUNK_BREAK\n");
fflush (stdout);
fprintf (stderr, "can't handle HUNK_BREAK yet\n");
exit (1);
break;
default:
fflush (stdout);
fprintf (stderr, "unrecognized hunk id %x\n", HunkID);
exit (1);
}
}
static void dump_hunk_header (fp)
FILE *fp;
{
long val;
long tablesize;
int index;
while ((val = readlong (fp)) != 0)
{
EMIT_VALUE (fp, val);
printf ("Number of longwords of name\n");
dump_string (fp, val, 0);
}
EMIT_VALUE (fp, val);
printf ("Name list terminator\n");
hunkcount = tablesize = readlong (fp);
EMIT_VALUE (fp, tablesize);
printf ("Table size\n");
val = readlong (fp);
EMIT_VALUE (fp, val);
printf ("First Hunk F\n");
val = readlong (fp);
EMIT_VALUE (fp, val);
printf ("Last Hunk L\n");
for (index = 0; index < tablesize; index++)
{
val = readlong (fp);
EMIT_VALUE (fp, val);
printf ("Hunk[%d] size (%d)\n", index, val);
}
}
static long readlong (fp)
FILE *fp;
{
long temp;
char buf [256];
if (fread ((char *) &temp, sizeof (temp), 1, fp) != 1)
{
sprintf (buf, "dumphunks: can't read data at %x", ftell (fp));
perror (buf);
exit (1);
}
return (temp);
}
static void dump_string (fp, count, suppress)
FILE *fp;
long count;
int suppress;
{
union {
long longval;
char buf[4];
} val;
int chi;
for (; count > 0; count--)
{
val.longval = readlong (fp);
if (!suppress)
{
EMIT_VALUE (fp, val);
for (chi = 0; chi < 4; chi++)
{
if (isprint (val.buf[chi]))
{
printf ("'%c' ", val.buf[chi]);
}
else
{
printf ("'\\%3.3o' ", val.buf[chi]);
}
}
printf ("\n");
}
}
}
static void dump_counted_data (fp, count, desc, suppress)
FILE *fp;
long count;
char *desc;
int suppress;
{
long val;
int index;
if (count == 0)
{
count = readlong (fp);
if (!suppress)
{
EMIT_VALUE (fp, count);
printf ("Number of longwords of %s\n", desc);
}
}
for (index = 0; index < count; index++)
{
val = readlong (fp);
if (!suppress)
{
if ((index % 8) == 0)
{
if (index > 0)
{
printf ("\n");
}
EMIT_OFFSET (fp);
}
printf ("%8.8x ", val);
}
}
if (!suppress)
{
printf ("\n");
}
}
static void dump_reloc_hunk (fp)
FILE *fp;
{
long count;
long val;
int index;
while ((val = readlong (fp)) != 0)
{
count = val;
EMIT_VALUE (fp, count);
printf ("Number of relocations (%d)\n", count);
val = readlong (fp);
EMIT_VALUE (fp, val);
printf ("Relocate relative to hunk %d\n", val);
/* FIXME: Dump relocations in human readable form. */
dump_counted_data (fp, count, "relocation data", reloc_flag);
}
EMIT_VALUE (fp, val);
printf ("Reloc hunk terminator\n");
}
static void dump_symbols (fp)
FILE *fp;
{
long val;
int namelength;
int symtype;
int count;
int index;
unsigned long symcount = 0;
while ((val = readlong (fp)) != SYMBOL_HUNK_TERMINATOR)
{
symcount++;
/* First longword is type in upper byte and name length
(in longwords) in lower 3 bytes. */
namelength = val & 0xFFFFFF;
symtype = (val >> 24) & 0xFF;
if (!symbol_flag)
{
EMIT_VALUE (fp, val);
switch (symtype)
{
case EXT_SYMB:
printf ("EXT_SYMB");
break;
case EXT_DEF:
printf ("EXT_DEF");
break;
case EXT_ABS:
printf ("EXT_ABS");
break;
case EXT_RES:
printf ("EXT_RES");
break;
case EXT_REF32:
printf ("EXT_REF32");
break;
case EXT_COMMON:
printf ("EXT_COMMON");
break;
case EXT_REF16:
printf ("EXT_REF16");
break;
case EXT_REF8:
printf ("EXT_REF8");
break;
case EXT_SASC86:
printf ("EXT_SASC86");
break;
default:
fflush (stdout);
fprintf (stderr, "dumphunks: unknown symbol type %x\n", symtype);
exit (1);
}
printf ("; %d longwords of symbol name\n", namelength);
}
dump_string (fp, namelength, symbol_flag);
switch (symtype)
{
case EXT_SYMB:
case EXT_DEF:
case EXT_ABS:
case EXT_RES:
val = readlong (fp);
if (!symbol_flag)
{
EMIT_VALUE (fp, val);
printf ("Symbol value\n");
}
break;
case EXT_COMMON:
val = readlong (fp);
if (!symbol_flag)
{
EMIT_VALUE (fp, val);
printf ("Size of common block\n");
}
/* FALL THROUGH */
case EXT_REF32:
case EXT_REF16:
case EXT_REF8:
count = readlong (fp);
for (index = 0; index < count; index++)
{
val = readlong (fp);
if (!symbol_flag)
{
EMIT_VALUE (fp, val);
printf ("Symbol reference %d\n", index);
}
}
break;
case EXT_SASC86:
dump_counted_data (fp, 2, "sasc86", symbol_flag);
break;
}
}
EMIT_VALUE (fp, val);
printf ("Symbol hunk terminator (%lu symbols)\n", symcount);
}
static void dump_hunk_bss (fp)
FILE *fp;
{
long val;
val = readlong (fp);
EMIT_VALUE (fp, val);
printf ("Size of BSS block in longwords\n");
}
static void dump_debug (fp)
FILE *fp;
{
long val;
val = readlong (fp);
EMIT_VALUE (fp, val);
printf ("%d longwords of debugging data\n", val);
/* FIXME: Dump in human readable form. */
dump_counted_data (fp, val, "debugging data", debug_flag);
}
static void dump_hunk_unit (fp)
FILE *fp;
{
long val;
hunkcount++;
val = readlong (fp);
EMIT_VALUE (fp, val);
printf ("%d longwords of hunk unit name\n");
dump_string (fp, val, 0);
}
static void dump_hunk_name (fp)
FILE *fp;
{
long val;
val = readlong (fp);
EMIT_VALUE (fp, val);
printf ("%d longwords of hunk name\n");
dump_string (fp, val, 0);
}