ref: fcf6344abaab925b58476fb5e9039b5b6deee11e
dir: /objdump/main.c/
#include <errno.h>
#include <limits.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "../inc/arg.h"
#include "../inc/scc.h"
#include "../inc/myro.h"
char *argv0;
static char *strings;
static size_t strsiz;
static char *
getstring(unsigned long off)
{
size_t n;
if ((int32_t) off == -1)
return "";
if (off < SIZE_MAX) {
for (n = off; n < strsiz && strings[n]; ++n)
;
if (n < strsiz)
return &strings[off];
}
fprintf(stderr, "objdump: wrong string offset %lu\n", off);
return "";
}
static void
printhdr(struct myrohdr *hdr)
{
printf("header:\n"
" magic: %02x %02x %02x %02x \"%4.4s\"\n"
" format: %lu (\"%s\")\n"
" entry: %llu\n"
" string table size: %llu\n"
" section table size: %llu\n"
" symbol table size: %llu\n"
" relocation table size: %llu\n",
hdr->magic[0], hdr->magic[1],
hdr->magic[2], hdr->magic[3],
hdr->magic,
hdr->format, getstring(hdr->format),
hdr->entry,
hdr->strsize,
hdr->secsize,
hdr->symsize,
hdr->relsize);
}
static void
printstrings(struct myrohdr *hdr)
{
size_t off, begin;;
char *s = NULL;
puts("strings:");
for (off = 0; off < strsiz; off++) {
if (s == NULL) {
s = &strings[off];
begin = off;
}
if (strings[off] == '\0') {
printf(" [%zd] \"%s\"\n", begin, s);
s = NULL;
}
}
}
static char *
sectflags(struct myrosect *sec)
{
static char flags[10];
char *s = flags + sizeof(flags);
if (sec->flags & MYROSEC_READ)
*--s = 'R';
if (sec->flags & MYROSEC_WRITE)
*--s = 'W';
if (sec->flags & MYROSEC_EXEC)
*--s = 'X';
if (sec->flags & MYROSEC_LOAD)
*--s = 'L';
if (sec->flags & MYROSEC_FILE)
*--s = 'F';
if (sec->flags & MYROSEC_ABS)
*--s = 'A';
return s;
}
static int
printsections(struct myrohdr *hdr, FILE *fp)
{
unsigned long long n, i;
struct myrosect sect;
printf("sections:\n"
" [Nr]\t%s\t%-16s\t%-16s\t%s\t%s\t%s\n",
"Name",
"Offset",
"Size",
"Fill",
"Align",
"Flags");
n = hdr->secsize / MYROSECT_SIZ;
for (i = 0; i < n; ++i) {
if (rdmyrosec(fp, §) < 0)
return -1;
printf(" [%2d]\t%s\t%016X\t%016X\t%02X\t%u\t%s\n",
i,
getstring(sect.name),
sect.offset,
sect.len,
sect.fill,
sect.aligment,
sectflags(§));
}
return 0;
}
static char *
symflags(struct myrosym *sym)
{
static char flags[10];
char *s = flags + sizeof(flags);
if (sym->flags & MYROSYM_DEDUP)
*--s = 'D';
if (sym->flags & MYROSYM_COMMON)
*--s = 'C';
if (sym->flags & MYROSYM_EXTERN)
*--s = 'G';
if (sym->flags & MYROSYM_UNDEF)
*s-- = 'U';
return s;
}
static int
printsymbols(struct myrohdr *hdr, FILE *fp)
{
unsigned long long n, i;
struct myrosym sym;
printf("symbols:\n"
" [Nr]\t%s\t%-16s\t%s\t%s\t%s\n",
"Name",
"Value",
"Section",
"Flags",
"Type");
n = hdr->symsize / MYROSYM_SIZ;
for (i = 0; i < n; ++i) {
if (rdmyrosym(fp, &sym) < 0)
return -1;
printf(" [%2u]\t%s\t%016X\t%u\t%s\t%s\n",
i,
getstring(sym.name),
sym.offset,
sym.section,
symflags(&sym),
getstring(sym.type));
}
return 0;
}
static int
printrelocs(struct myrohdr *hdr, FILE *fp)
{
unsigned long long n, i;
struct myrorel rel;
printf("relocs:\n"
" [Nr]\t%-16s\tType\tId\tSize\tNbits\tShift\n",
"Offset");
n = hdr->relsize / MYROREL_SIZ;
for (i = 0; i < n; ++i) {
if (rdmyrorel(fp, &rel) < 0)
return -1;
printf(" [%2d]\t%016llX\t%s\t%lu\t%u\t%u\t%u\n",
i,
rel.offset,
(rel.id & 1<<31) ? "section" : "symbol",
rel.id & ~(1<<31),
rel.size,
rel.nbits,
rel.shift);
}
return 0;
}
static int
printdata(struct myrohdr *hdr, FILE *fp)
{
unsigned long off;
int c, i, j;
puts("data:");
for (off = 0; ; off += 32) {
printf("\t%08x:", off);
for (i = 0; i < 2; i++) {
for (j = 0; j < 16; j++) {
if ((c = getc(fp)) == EOF)
goto exit_loop;
printf(" %02X", c);
}
putchar('\t');
}
putchar('\n');
}
exit_loop:
putchar('\n');
return (ferror(fp)) ? -1 : 0;
}
void
dump(char *fname)
{
FILE *fp;
struct myrohdr hdr;
if ((fp = fopen(fname, "rb")) == NULL)
goto wrong_file;
if (rdmyrohdr(fp, &hdr) < 0)
goto wrong_file;
if (strncmp(hdr.magic, MYROMAGIC, MYROMAGIC_SIZ)) {
fprintf(stderr,
"objdump: %s: File format not recognized\n",
fname);
goto close_file;
}
puts(fname);
if (hdr.strsize > SIZE_MAX) {
fprintf(stderr,
"objdump: %s: overflow in header\n",
fname, strerror(errno));
goto close_file;
}
strsiz = hdr.strsize;
if (strsiz > 0) {
strings = xmalloc(strsiz);
fread(strings, strsiz, 1, fp);
if (feof(fp))
goto wrong_file;
}
printhdr(&hdr);
printstrings(&hdr);
if (printsections(&hdr, fp) < 0)
goto wrong_file;
if (printsymbols(&hdr, fp) < 0)
goto wrong_file;
if (printrelocs(&hdr, fp) < 0)
goto wrong_file;
if (printdata(&hdr, fp) < 0)
goto wrong_file;
goto close_file;
wrong_file:
fprintf(stderr,
"objdump: %s: %s\n",
fname, strerror(errno));
close_file:
if (fp)
fclose(fp);
}
void
usage(void)
{
fputs("usage: objdump file ...\n", stderr);
exit(1);
}
int
main(int argc, char *argv[])
{
ARGBEGIN {
default:
usage();
} ARGEND
if (argc == 0)
dump("a.out");
else while (*argv) {
free(strings);
strings = NULL;
dump(*argv++);
}
if (fclose(stdout) == EOF)
die("objdump: stdout: %s", strerror(errno));
return 0;
}