summaryrefslogtreecommitdiff
path: root/src/objdump.c
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2008-01-02 17:44:39 +0000
committerUlrich Drepper <drepper@redhat.com>2008-01-02 17:44:39 +0000
commit3cbdd387c752999255aea91600b5cfdefbeac7d0 (patch)
tree50c18bd26f8cd31f4c1aa3ce1d78bb98548659ba /src/objdump.c
parentad024afc93dcd0f4797b3e80bfb6b80c34da5c12 (diff)
downloadelfutils-3cbdd387c752999255aea91600b5cfdefbeac7d0.tar.gz
propagate from branch 'com.redhat.elfutils.disasm' (head d15b4eb794e81e477f9896fe82a74cb5ecf4514c)
to branch 'com.redhat.elfutils' (head eaacbf01f8cc89d043ec6eca9b5e35cb5c4cde06)
Diffstat (limited to 'src/objdump.c')
-rw-r--r--src/objdump.c86
1 files changed, 82 insertions, 4 deletions
diff --git a/src/objdump.c b/src/objdump.c
index 8c62ee28..92ab84f8 100644
--- a/src/objdump.c
+++ b/src/objdump.c
@@ -681,12 +681,87 @@ show_full_content (Ebl *ebl, const char *fname, uint32_t shstrndx)
}
+struct disasm_info
+{
+ GElf_Addr addr;
+ const uint8_t *cur;
+ const uint8_t *last_end;
+};
+
+
+// XXX This is not the preferred output for all architectures. Needs
+// XXX customization, too.
static int
-show_disasm (Ebl *ebl __attribute__ ((unused)),
- const char *fname __attribute__ ((unused)),
- uint32_t shstrndx __attribute__ ((unused)))
+disasm_output (char *buf, size_t buflen, void *arg)
{
- /// XXX For now nothing.
+ struct disasm_info *info = (struct disasm_info *) arg;
+
+ printf ("%8" PRIx64 ": ", (uint64_t) info->addr);
+ size_t cnt;
+ for (cnt = 0; cnt < (size_t) MIN (info->cur - info->last_end, 8); ++cnt)
+ printf (" %02" PRIx8, info->last_end[cnt]);
+ printf ("%*s %.*s\n",
+ (int) (8 - cnt) * 3 + 1, "", (int) buflen, buf);
+
+ info->addr += cnt;
+
+ /* We limit the number of bytes printed before the mnemonic to 8.
+ Print the rest on a separate, following line. */
+ if (info->cur - info->last_end > 8)
+ {
+ printf ("%8" PRIx64 ": ", (uint64_t) info->addr);
+ for (; cnt < (size_t) (info->cur - info->last_end); ++cnt)
+ printf (" %02" PRIx8, info->last_end[cnt]);
+ putchar_unlocked ('\n');
+ info->addr += info->cur - info->last_end - 8;
+ }
+
+ info->last_end = info->cur;
+
+ return 0;
+}
+
+
+static int
+show_disasm (Ebl *ebl, const char *fname, uint32_t shstrndx)
+{
+ DisasmCtx_t *ctx = disasm_begin (ebl, ebl->elf, NULL /* XXX TODO */);
+ if (ctx == NULL)
+ error (EXIT_FAILURE, 0, gettext ("cannot disassemble"));
+
+ Elf_Scn *scn = NULL;
+ while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
+ {
+ GElf_Shdr shdr_mem;
+ GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+
+ if (shdr == NULL)
+ INTERNAL_ERROR (fname);
+
+ if (shdr->sh_type == SHT_PROGBITS && shdr->sh_size > 0
+ && (shdr->sh_flags & SHF_EXECINSTR) != 0)
+ {
+ if (! section_match (ebl->elf, elf_ndxscn (scn), shdr, shstrndx))
+ continue;
+
+ Elf_Data *data = elf_getdata (scn, NULL);
+ if (data == NULL)
+ continue;
+
+ printf ("Disassembly of section %s:\n\n",
+ elf_strptr (ebl->elf, shstrndx, shdr->sh_name));
+
+ struct disasm_info info;
+ info.addr = shdr->sh_addr;
+ info.last_end = info.cur = data->d_buf;
+
+ disasm_cb (ctx, &info.cur, info.cur + data->d_size, info.addr,
+ "%7m%e %.1o%e,%.2o%e,%.3o%e", disasm_output, &info,
+ NULL /* XXX */);
+ }
+ }
+
+ (void) disasm_end (ctx);
return 0;
}
@@ -735,3 +810,6 @@ handle_elf (Elf *elf, const char *prefix, const char *fname,
return result;
}
+
+
+#include "debugpred.h"