#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include "disasm.h"
#include "bool.h"
#define CODE_BUF_LEN 20
#define CLLD_MAGIC 0x434c4c44
#define GCCLDD_MAGIC 0x47430
#define TREAD(fp, ptr, type) \
(read ((fp), &(ptr), sizeof (type)) != sizeof (type))
#define DOCOL 0x02d9d
#define DOEXT0 0x02b88
#define DOIDNT 0x02e48
#define SEMI 0x0312b
static char *progname;
static unsigned char *code;
static void dump_file (int fp);
static void dump_code (unsigned long codestart,
unsigned long codeend);
static char *hexstr (unsigned long addr, int len);
static unsigned long read_nibbles (unsigned long addr, int len);
struct reloc
{
unsigned long offset;
struct reloc *next;
};
struct import
{
unsigned long offset;
int libnum;
unsigned long liboff;
struct import *next;
};
struct shlib
{
char *name;
struct import *imports;
struct shlib *next;
};
static char *loader = 0;
static char **libnames;
static struct shlib *libs = 0;
static unsigned int nshlibs = 0;
static struct reloc *relocs = 0;
static unsigned int nrelocs = 0;
static struct import *imports = 0;
static unsigned int nimports = 0;
int
main (int argc, char **argv)
{
char *objname;
char hpstr[8];
unsigned long magic;
unsigned long pc;
unsigned long base;
unsigned long offset;
unsigned long idlen;
unsigned long headlen;
unsigned long headoff;
unsigned long datalen;
unsigned long codestart;
unsigned long codeend;
int of;
unsigned int i, j;
struct stat st;
struct shlib *sh;
struct reloc *rel;
struct import *imp;
progname = strrchr (argv[0], '/');
if (progname)
progname++;
else
progname = argv[0];
if (argc < 2)
{
fprintf (stderr, "usage: %s object-file\n", progname);
exit (1);
}
objname = argv[1];
of = open (objname, O_RDONLY);
if (of < 0)
{
fprintf (stderr, "%s: can't open `%s'\n", progname, objname);
exit (1);
}
if (TREAD (of, magic, unsigned long))
{
fprintf (stderr, "%s: can't read magic number\n", progname);
exit (1);
}
if (magic == CLLD_MAGIC)
{
dump_file (of);
}
else
{
lseek (of, 0, SEEK_SET);
if (read (of, hpstr, 8) != 8)
{
fprintf (stderr, "%s: can't read HPHP48-X header\n", progname);
exit (1);
}
if (!strncmp (hpstr, "HPHP48-", 7))
{
fprintf (stdout, "HP48 binary Rev %c\n", hpstr[7]);
fstat (of, &st);
code = (unsigned char *) malloc (st.st_size - 8);
if (!code)
{
fprintf (stdout, "%s: can't malloc buffer\n", progname);
exit (1);
}
if (read (of, code, st.st_size - 8) != st.st_size - 8)
{
fprintf (stdout, "%s: can't read file\n", progname);
exit (1);
}
pc = 0;
if (DOCOL != read_nibbles (pc, 5))
{
fprintf (stdout, "%s: no Composite object\n", progname);
exit (1);
}
pc += 5;
while (DOIDNT == read_nibbles (pc, 5))
{
pc += 5;
idlen = read_nibbles (pc, 2);
pc += 2;
sh = (struct shlib *) malloc (sizeof (struct shlib));
sh->name = (char *) malloc (idlen + 1);
for (i = 0; i < idlen; i++)
{
sh->name[i] = (char)read_nibbles (pc, 2);
pc += 2;
}
sh->name[i] = '\0';
sh->imports = 0;
sh->next = libs;
libs = sh;
nshlibs++;
}
if (DOEXT0 == read_nibbles (pc, 5))
{
pc += 5;
datalen = read_nibbles (pc, 5);
codeend = pc + datalen;
pc += 5;
magic = read_nibbles (pc, 5);
pc += 5;
if (magic != GCCLDD_MAGIC)
{
fprintf (stdout, "%s: wrong magic number\n", progname);
exit (1);
}
libnames = (char **) malloc ((nshlibs + 1) * sizeof(char *));
if (!libnames)
{
fprintf (stderr, "%s: can't malloc libnames\n", progname);
exit (1);
}
libnames[0] = "main";
sh = libs;
i = 0;
while (sh)
{
fprintf (stdout, "Need shared library %d: `%s'\n", i, sh->name);
i++;
libnames[i] = sh->name;
sh = sh->next;
}
headlen = read_nibbles (pc, 5);
fprintf (stdout, "header length 0x%05lX\n", headlen);
codestart = headlen + pc;
headoff = pc + 5;
pc = codeend;
if (DOIDNT == read_nibbles (pc, 5))
{
pc += 5;
idlen = read_nibbles (pc, 2);
pc += 2;
loader = (char *)malloc (idlen + 1);
if (!loader)
{
fprintf (stderr, "%s: can't malloc loader name\n",
progname);
exit (1);
}
for (i = 0; i < idlen; i++)
{
loader[i] = read_nibbles (pc, 2);
pc += 2;
}
loader[i] = '\0';
}
if (loader)
fprintf (stdout, "Loader: `%s'\n", loader);
pc = headoff;
base = read_nibbles (pc, 5);
pc += 5;
fprintf (stdout, "start address 0x%05lX\n", base);
while ((offset = read_nibbles (pc, 5)) != 0x00000)
{
pc += 5;
rel = (struct reloc *) malloc (sizeof (struct reloc));
rel->offset = offset;
rel->next = relocs;
relocs = rel;
nrelocs++;
}
pc += 5;
rel = relocs;
i = 0;
while (rel)
{
fprintf (stdout, "Reloc %d: at 0x%05lX\n",
i, rel->offset);
i++;
rel = rel->next;
}
if (loader)
{
/* executable */
pc += 5; /* skip start address rep */
pc += 5 * nshlibs; /* skip shlib start addresses */
pc += 5; /* skip 0 */
while (read_nibbles (pc, 2) != 0x00)
{
imp = (struct import *) malloc (sizeof (struct import));
if (!imp)
{
fprintf (stderr, "%s: can't malloc import\n",
progname);
exit (1);
}
imp->libnum = (read_nibbles (pc, 2) - 1) / 5;
pc += 2;
imp->liboff = read_nibbles (pc, 5);
pc += 5;
imp->offset = read_nibbles (pc, 5);
pc += 5;
imp->next = imports;
imports = imp;
}
pc += 2;
sh = libs;
for (i = 0; i < nshlibs; i++)
{
while (read_nibbles (pc, 2) != 0x00)
{
imp = (struct import *)malloc(sizeof (struct import));
if (!imp)
{
fprintf (stderr, "%s: can't malloc import\n",
progname);
exit (1);
}
imp->libnum = (read_nibbles (pc, 2) - 1) / 5;
pc += 2;
imp->liboff = read_nibbles (pc, 5);
pc += 5;
imp->next = sh->imports;
sh->imports = imp;
}
pc += 2;
sh = sh->next;
}
imp = imports;
i = 0;
if (imp)
fprintf (stdout, "`%s' imports:\n", libnames[i]);
while (imp)
{
fprintf (stdout,
"Import %d: at 0x%05lX offset 0x%05lX into `%s'\n",
i, imp->offset, imp->liboff, libnames[imp->libnum]);
i++;
imp = imp->next;
}
sh = libs;
for (i = 0; i < nshlibs; i++)
{
fprintf (stdout, "`%s' imports:\n", sh->name);
imp = sh->imports;
j = 0;
while (imp)
{
fprintf (stdout,
"Import %d: offset 0x%05lX into `%s'\n",
j, imp->liboff, libnames[imp->libnum]);
j++;
imp = imp->next;
}
sh = sh->next;
}
}
else
{
/* shared lib */
while (pc < codestart)
{
offset = read_nibbles (pc, 5);
pc += 5;
imp = (struct import *) malloc (sizeof (struct import));
imp->offset = offset;
imp->liboff = 0;
imp->next = imports;
imports = imp;
nimports++;
}
imp = imports;
i = 0;
while (imp)
{
fprintf (stdout, "Import %d: at 0x%05lX\n",
i, imp->offset);
i++;
imp = imp->next;
}
}
fprintf (stdout, "Code len: 0x%05lX\n", codeend - codestart);
dump_code (codestart, codeend);
}
else
{
fprintf (stdout, "%s: no LibraryData found\n", progname);
exit (1);
}
}
else
{
fprintf (stdout, "%s: unknown object format\n", progname);
}
}
close (of);
return 0;
}
typedef union
{
unsigned long long l;
double d;
} l_or_d;
static void
dump_file (int fp)
{
long namlen;
long n;
int i, codlen;
unsigned long reloc;
unsigned long offset;
unsigned long size;
bool reloc_demand;
bool isfloat;
bool isnum;
bool isshared;
bool even;
l_or_d value;
char name[200];
if (TREAD (fp, namlen, long))
{
fprintf (stderr, "%s: can't read name length\n", progname);
exit (1);
}
if (read (fp, name, namlen) != namlen)
{
fprintf (stderr, "%s: can't read name\n", progname);
exit (1);
}
name [namlen] = '\0';
fprintf (stdout, "Name: `%s'\n", name);
if (TREAD (fp, n, long))
{
fprintf (stderr, "%s: can't read number of relocs\n", progname);
exit (1);
}
fprintf (stdout, "Relocs: %ld\n", n);
for (i = 0; i < n; i++)
{
if (TREAD (fp, reloc, unsigned long))
{
fprintf (stderr, "%s: can't read reloc %d\n", progname, i);
exit (1);
}
fprintf (stdout, "Reloc %d: at 0x%05lX\n", i, reloc);
}
if (TREAD (fp, n, long))
{
fprintf (stderr, "%s: can't read number of imports\n", progname);
exit (1);
}
fprintf (stdout, "Imports: %ld\n", n);
for (i = 0; i < n; i++)
{
if (TREAD (fp, offset, unsigned long))
{
fprintf (stderr, "%s: can't read offset %d\n", progname, i);
exit (1);
}
if (TREAD (fp, size, unsigned long))
{
fprintf (stderr, "%s: can't read size %d\n", progname, i);
exit (1);
}
if (TREAD (fp, namlen, long))
{
fprintf (stderr, "%s: can't read name length\n", progname);
exit (1);
}
if (read (fp, name, namlen) != namlen)
{
fprintf (stderr, "%s: can't read import %d\n", progname, i);
exit (1);
}
name [namlen] = '\0';
if (TREAD (fp, reloc_demand, bool))
{
fprintf (stderr, "%s: can't read reloc_demand %d\n", progname, i);
exit (1);
}
fprintf (stdout, "Import %d: `%s' offset 0x%05lX len 0x%05lX %s\n",
i, name, offset, size, reloc_demand ? "relocate" : "");
}
if (TREAD (fp, n, long))
{
fprintf (stderr, "%s: can't read number of symbols\n", progname);
exit (1);
}
fprintf (stdout, "Symbols: %ld\n", n);
for (i = 0; i < n; i++)
{
if (TREAD (fp, isfloat, bool))
{
fprintf (stderr, "%s: can't read float flag %d\n", progname, i);
exit (1);
}
if (TREAD (fp, value.l, unsigned long long))
{
fprintf (stderr, "%s: can't read symbol value %d\n", progname, i);
exit (1);
}
if (TREAD (fp, namlen, long))
{
fprintf (stderr, "%s: can't read name length\n", progname);
exit (1);
}
if (read (fp, name, namlen) != namlen)
{
fprintf (stderr, "%s: can't read import %d\n", progname, i);
exit (1);
}
name [namlen] = '\0';
if (TREAD (fp, isnum, bool))
{
fprintf (stderr, "%s: can't read float flag %d\n", progname, i);
exit (1);
}
fprintf (stdout, "Symbol %d: %s `%s'",
i, isnum ? (isfloat ? "float" : "int") : "function", name);
if (!isnum)
fprintf (stdout, " offset 0x%05lX\n", (unsigned long)value.l);
else
{
if (isfloat)
fprintf (stdout, " value %0.11E\n", value.d);
else
fprintf (stdout, " value %016llX\n", value.l);
}
}
if (TREAD (fp, isshared, bool))
{
fprintf (stderr, "%s: can't read shared flag\n", progname);
exit (1);
}
fprintf (stdout, "Shared: %s\n", isshared ? "yes" : "no");
if (TREAD (fp, even, bool))
{
fprintf (stderr, "%s: can't read even flag\n", progname);
exit (1);
}
if (TREAD (fp, n, unsigned long))
{
fprintf (stderr, "%s: can't read length of code\n", progname);
exit (1);
}
codlen = 2 * n;
if (!even)
codlen--;
fprintf (stdout, "Code len: 0x%05X\n", codlen);
code = (unsigned char *) malloc (n);
if (!code)
{
fprintf (stderr, "%s: can't malloc storage for code\n", progname);
exit (1);
}
if (read (fp, code, n) != n)
{
fprintf (stderr, "%s: can't read code\n", progname);
exit (1);
}
dump_code (0, codlen);
free (code);
}
static void
dump_code (unsigned long codestart, unsigned long codeend)
{
unsigned long addr = codestart;
unsigned long next;
char inst[200];
while (addr < codeend)
{
next = disassemble (addr, inst);
fprintf (stdout, "0x%05lX: %s %s\n", addr - codestart,
hexstr (addr, next - addr), inst);
addr = next;
}
}
unsigned int
read_nibble (unsigned long addr)
{
unsigned int nib;
nib = code [addr >> 1];
if (addr & 1)
nib = (nib >> 4) & 0x0f;
else
nib &= 0x0f;
return nib;
}
static unsigned long
read_nibbles (unsigned long addr, int len)
{
unsigned long res = 0;
addr += len;
while (len-- > 0)
{
res = (res << 4) | read_nibble (--addr);
}
return res;
}
static char *
hexstr (unsigned long addr, int len)
{
static char buf[200];
int i;
for (i = 0; i < len; i++)
{
buf[i] = read_nibble (addr + i);
if (buf[i] < 0x0a)
buf[i] += '0';
else
buf[i] += 'A' - (char)10;
}
for ( ; i < CODE_BUF_LEN; i++)
buf[i] = ' ';
buf[i] = '\0';
return buf;
}
syntax highlighted by Code2HTML, v. 0.9.1