#include #include #include #include #include #include #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; }