From 01b6e6077502fadff0a0f8a5c2e4a7daf079721d Mon Sep 17 00:00:00 2001 From: Alexis Ehret <08a@riseup.net> Date: Tue, 28 Sep 2021 07:36:46 +0200 Subject: [PATCH] Refactor elf plugin interface (#1728) * get_sdb * check_buffer * load_buffer * baddr * boffset * binsym * entries * headers * create * fields --- librz/bin/format/elf/elf.c | 87 +--- librz/bin/format/elf/elf.h | 18 + librz/bin/format/elf/elf64_ehdr.c | 6 + librz/bin/format/elf/elf_ehdr.c | 219 +++++++++ librz/bin/format/elf/elf_specs.h | 15 + librz/bin/meson.build | 2 + librz/bin/p/bin_cgc.c | 4 - librz/bin/p/bin_elf.c | 202 +------- librz/bin/p/bin_elf.inc | 743 ++++++++++++++++-------------- librz/bin/p/bin_elf64.c | 196 +------- test/db/cmd/cmd_i | 30 +- test/db/cmd/metadata | 2 +- test/db/formats/elf/thumb | 2 +- test/db/tools/rz_bin | 34 +- 14 files changed, 696 insertions(+), 864 deletions(-) create mode 100644 librz/bin/format/elf/elf64_ehdr.c create mode 100644 librz/bin/format/elf/elf_ehdr.c diff --git a/librz/bin/format/elf/elf.c b/librz/bin/format/elf/elf.c index 0c3d371691..d95a439f76 100644 --- a/librz/bin/format/elf/elf.c +++ b/librz/bin/format/elf/elf.c @@ -151,93 +151,8 @@ static bool init_ehdr_sdb(ELFOBJ *bin) { sdb_set(bin->kv, "elf_type.cparse", sdb_elf_type_cparse, 0); } -static bool is_valid_elf_ident(ut8 *e_ident) { - return !memcmp(e_ident, ELFMAG, SELFMAG) || !memcmp(e_ident, CGCMAG, SCGCMAG); -} - -static bool init_ehdr_ident(ELFOBJ *bin) { - memset(&bin->ehdr, 0, sizeof(Elf_(Ehdr))); - - if (rz_buf_read_at(bin->b, 0, bin->ehdr.e_ident, EI_NIDENT) < 0) { - RZ_LOG_WARN("Failed to read ELF header e_ident.\n") - return false; - } - - if (!is_valid_elf_ident(bin->ehdr.e_ident)) { - RZ_LOG_WARN("Invalid ELF identification.\n"); - return false; - } - - bin->big_endian = bin->ehdr.e_ident[EI_DATA] == ELFDATA2MSB; - - return true; -} - -static bool init_ehdr_other_aux(ELFOBJ *bin, ut64 *offset) { - return Elf_(rz_bin_elf_read_half)(bin, offset, &bin->ehdr.e_type) && - Elf_(rz_bin_elf_read_half)(bin, offset, &bin->ehdr.e_machine) && - Elf_(rz_bin_elf_read_word)(bin, offset, &bin->ehdr.e_version) && - Elf_(rz_bin_elf_read_addr)(bin, offset, &bin->ehdr.e_entry) && - Elf_(rz_bin_elf_read_off)(bin, offset, &bin->ehdr.e_phoff) && - Elf_(rz_bin_elf_read_off)(bin, offset, &bin->ehdr.e_shoff) && - Elf_(rz_bin_elf_read_word)(bin, offset, &bin->ehdr.e_flags) && - Elf_(rz_bin_elf_read_half)(bin, offset, &bin->ehdr.e_ehsize) && - Elf_(rz_bin_elf_read_half)(bin, offset, &bin->ehdr.e_phentsize); -} - -static bool is_tiny_elf(ELFOBJ *bin) { - return bin->size == 45; -} - -static Elf_(Half) get_tiny_elf_phnum(ELFOBJ *bin) { - ut64 offset = 44; - - ut8 tmp; - if (Elf_(rz_bin_elf_read_char)(bin, &offset, &tmp)) { - return tmp; - } - - return 0; -} - -static bool init_ehdr_other(ELFOBJ *bin) { - ut64 offset = EI_NIDENT; - - if (!init_ehdr_other_aux(bin, &offset)) { - RZ_LOG_WARN("Failed to read beginning of the ELF header (until e_phnum).\n") - return false; - } - - if (!Elf_(rz_bin_elf_read_half)(bin, &offset, &bin->ehdr.e_phnum)) { - RZ_LOG_WARN("Failed to read ELF header (e_phnum).\n") - } - - if (!Elf_(rz_bin_elf_read_half)(bin, &offset, &bin->ehdr.e_shentsize)) { - RZ_LOG_WARN("Failed to read ELF header (e_shentsize).\n") - } - - if (!Elf_(rz_bin_elf_read_half)(bin, &offset, &bin->ehdr.e_shnum)) { - RZ_LOG_WARN("Failed to read ELF header (e_shnum).\n") - } - - if (!Elf_(rz_bin_elf_read_half)(bin, &offset, &bin->ehdr.e_shstrndx)) { - RZ_LOG_WARN("Failed to read ELF header (e_shstrndx).\n") - } - - if (is_tiny_elf(bin)) { - RZ_LOG_WARN("The binary seems to be a tiny elf (45 bytes). Reload e_phnum value.\n"); - bin->ehdr.e_phnum = get_tiny_elf_phnum(bin); - } - - return true; -} - static bool init_ehdr(ELFOBJ *bin) { - if (!init_ehdr_ident(bin)) { - return false; - } - - if (!init_ehdr_other(bin)) { + if (!Elf_(rz_bin_elf_get_ehdr)(bin)) { return false; } diff --git a/librz/bin/format/elf/elf.h b/librz/bin/format/elf/elf.h index 2d017077e5..2e82441fe7 100644 --- a/librz/bin/format/elf/elf.h +++ b/librz/bin/format/elf/elf.h @@ -244,6 +244,24 @@ bool Elf_(rz_bin_elf_get_dt_info)(RZ_NONNULL ELFOBJ *bin, ut64 key, RZ_OUT ut64 bool Elf_(rz_bin_elf_has_dt_dynamic)(RZ_NONNULL ELFOBJ *bin); void Elf_(rz_bin_elf_dt_dynamic_free)(RzBinElfDtDynamic *ptr); +// elf_ehdr.c +RZ_OWN char *Elf_(rz_bin_elf_get_e_ehsize_as_string)(RZ_NONNULL ELFOBJ *bin); +RZ_OWN char *Elf_(rz_bin_elf_get_e_entry_as_string)(RZ_NONNULL ELFOBJ *bin); +RZ_OWN char *Elf_(rz_bin_elf_get_e_flags_as_string)(RZ_NONNULL ELFOBJ *bin); +RZ_OWN char *Elf_(rz_bin_elf_get_e_indent_as_string)(RZ_NONNULL ELFOBJ *bin); +RZ_OWN char *Elf_(rz_bin_elf_get_e_machine_as_string)(RZ_NONNULL ELFOBJ *bin); +RZ_OWN char *Elf_(rz_bin_elf_get_e_phentsize_as_string)(RZ_NONNULL ELFOBJ *bin); +RZ_OWN char *Elf_(rz_bin_elf_get_e_phnum_as_string)(RZ_NONNULL ELFOBJ *bin); +RZ_OWN char *Elf_(rz_bin_elf_get_e_phoff_as_string)(RZ_NONNULL ELFOBJ *bin); +RZ_OWN char *Elf_(rz_bin_elf_get_e_shentsize_as_string)(RZ_NONNULL ELFOBJ *bin); +RZ_OWN char *Elf_(rz_bin_elf_get_e_shnum_as_string)(RZ_NONNULL ELFOBJ *bin); +RZ_OWN char *Elf_(rz_bin_elf_get_e_shoff_as_string)(RZ_NONNULL ELFOBJ *bin); +RZ_OWN char *Elf_(rz_bin_elf_get_e_shstrndx_as_string)(RZ_NONNULL ELFOBJ *bin); +RZ_OWN char *Elf_(rz_bin_elf_get_e_type_as_string)(RZ_NONNULL ELFOBJ *bin); +RZ_OWN char *Elf_(rz_bin_elf_get_e_version_as_string)(RZ_NONNULL ELFOBJ *bin); +bool Elf_(rz_bin_elf_get_ehdr)(RZ_NONNULL ELFOBJ *bin); +bool Elf_(rz_bin_elf_print_ehdr)(ELFOBJ *bin, RZ_NONNULL PrintfCallback cb); + // elf_hash.c bool Elf_(rz_bin_elf_get_gnu_hash_table)(RZ_NONNULL ELFOBJ *bin, RzBinElfGnuHashTable *result); bool Elf_(rz_bin_elf_get_hash_table)(RZ_NONNULL ELFOBJ *bin, RzBinElfHashTable *result); diff --git a/librz/bin/format/elf/elf64_ehdr.c b/librz/bin/format/elf/elf64_ehdr.c new file mode 100644 index 0000000000..0869ae84aa --- /dev/null +++ b/librz/bin/format/elf/elf64_ehdr.c @@ -0,0 +1,6 @@ +// SPDX-FileCopyrightText: 2021 08A <08A@riseup.net> +// SPDX-FileCopyrightText: 2021 RizinOrg +// SPDX-License-Identifier: LGPL-3.0-only + +#define RZ_BIN_ELF64 1 +#include "elf_ehdr.c" diff --git a/librz/bin/format/elf/elf_ehdr.c b/librz/bin/format/elf/elf_ehdr.c new file mode 100644 index 0000000000..960b602521 --- /dev/null +++ b/librz/bin/format/elf/elf_ehdr.c @@ -0,0 +1,219 @@ +// SPDX-FileCopyrightText: 2021 08A <08A@riseup.net> +// SPDX-FileCopyrightText: 2021 RizinOrg +// SPDX-License-Identifier: LGPL-3.0-only + +#include "elf.h" + +static Elf_(Half) get_tiny_elf_phnum(ELFOBJ *bin) { + ut64 offset = 44; + + ut8 tmp; + if (!Elf_(rz_bin_elf_read_char)(bin, &offset, &tmp)) { + RZ_LOG_WARN("Failed to read ELF header (e_phnum) in tiny elf mode.\n") + } + + return tmp; +} + +static bool is_tiny_elf(ELFOBJ *bin) { + return bin->size == 45; +} + +static bool read_ehdr_other_aux(ELFOBJ *bin, ut64 *offset) { + return Elf_(rz_bin_elf_read_half)(bin, offset, &bin->ehdr.e_type) && + Elf_(rz_bin_elf_read_half)(bin, offset, &bin->ehdr.e_machine) && + Elf_(rz_bin_elf_read_word)(bin, offset, &bin->ehdr.e_version) && + Elf_(rz_bin_elf_read_addr)(bin, offset, &bin->ehdr.e_entry) && + Elf_(rz_bin_elf_read_off)(bin, offset, &bin->ehdr.e_phoff) && + Elf_(rz_bin_elf_read_off)(bin, offset, &bin->ehdr.e_shoff) && + Elf_(rz_bin_elf_read_word)(bin, offset, &bin->ehdr.e_flags) && + Elf_(rz_bin_elf_read_half)(bin, offset, &bin->ehdr.e_ehsize) && + Elf_(rz_bin_elf_read_half)(bin, offset, &bin->ehdr.e_phentsize); +} + +static bool read_ehdr_other(ELFOBJ *bin) { + ut64 offset = EI_NIDENT; + + if (!read_ehdr_other_aux(bin, &offset)) { + RZ_LOG_WARN("Failed to read beginning of the ELF header (until e_phnum).\n") + return false; + } + + if (!Elf_(rz_bin_elf_read_half)(bin, &offset, &bin->ehdr.e_phnum)) { + RZ_LOG_WARN("Failed to read ELF header (e_phnum).\n") + } + + if (!Elf_(rz_bin_elf_read_half)(bin, &offset, &bin->ehdr.e_shentsize)) { + RZ_LOG_WARN("Failed to read ELF header (e_shentsize).\n") + } + + if (!Elf_(rz_bin_elf_read_half)(bin, &offset, &bin->ehdr.e_shnum)) { + RZ_LOG_WARN("Failed to read ELF header (e_shnum).\n") + } + + if (!Elf_(rz_bin_elf_read_half)(bin, &offset, &bin->ehdr.e_shstrndx)) { + RZ_LOG_WARN("Failed to read ELF header (e_shstrndx).\n") + } + + if (is_tiny_elf(bin)) { + RZ_LOG_WARN("The binary seems to be a tiny elf (45 bytes). Reload e_phnum value.\n"); + bin->ehdr.e_phnum = get_tiny_elf_phnum(bin); + } + + return true; +} + +static bool is_valid_elf_ident(ut8 *e_ident) { + return !memcmp(e_ident, ELFMAG, SELFMAG) || !memcmp(e_ident, CGCMAG, SCGCMAG); +} + +static bool print_ehdr_aux(ELFOBJ *bin, PrintfCallback cb, ut64 offset, const char *name, char *(*get_value)(ELFOBJ *bin)) { + char *tmp = get_value(bin); + if (!tmp) { + return false; + } + + cb("0x%08" PFMT64x " %-10s %s\n", offset, name, tmp); + + free(tmp); + return true; +} + +RZ_OWN char *Elf_(rz_bin_elf_get_e_ehsize_as_string)(RZ_NONNULL ELFOBJ *bin) { + rz_return_val_if_fail(bin, NULL); + + return rz_str_newf("%d", bin->ehdr.e_ehsize); +} + +RZ_OWN char *Elf_(rz_bin_elf_get_e_entry_as_string)(RZ_NONNULL ELFOBJ *bin) { + rz_return_val_if_fail(bin, NULL); + + return rz_str_newf("0x%08" PFMT64x, (ut64)bin->ehdr.e_entry); +} + +RZ_OWN char *Elf_(rz_bin_elf_get_e_flags_as_string)(RZ_NONNULL ELFOBJ *bin) { + rz_return_val_if_fail(bin, NULL); + + return rz_str_newf("0x%04x", bin->ehdr.e_flags); +} + +RZ_OWN char *Elf_(rz_bin_elf_get_e_indent_as_string)(RZ_NONNULL ELFOBJ *bin) { + rz_return_val_if_fail(bin, NULL); + + return rz_str_newf("%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x", + bin->ehdr.e_ident[0], + bin->ehdr.e_ident[1], + bin->ehdr.e_ident[2], + bin->ehdr.e_ident[3], + bin->ehdr.e_ident[4], + bin->ehdr.e_ident[5], + bin->ehdr.e_ident[6], + bin->ehdr.e_ident[7], + bin->ehdr.e_ident[8], + bin->ehdr.e_ident[9], + bin->ehdr.e_ident[10], + bin->ehdr.e_ident[11], + bin->ehdr.e_ident[12], + bin->ehdr.e_ident[13], + bin->ehdr.e_ident[14], + bin->ehdr.e_ident[15]); +} + +RZ_OWN char *Elf_(rz_bin_elf_get_e_machine_as_string)(RZ_NONNULL ELFOBJ *bin) { + rz_return_val_if_fail(bin, NULL); + + return rz_str_newf("0x%04x", bin->ehdr.e_machine); +} + +RZ_OWN char *Elf_(rz_bin_elf_get_e_phentsize_as_string)(RZ_NONNULL ELFOBJ *bin) { + rz_return_val_if_fail(bin, NULL); + + return rz_str_newf("%d", bin->ehdr.e_phentsize); +} + +RZ_OWN char *Elf_(rz_bin_elf_get_e_phnum_as_string)(RZ_NONNULL ELFOBJ *bin) { + rz_return_val_if_fail(bin, NULL); + + return rz_str_newf("%d", bin->ehdr.e_phnum); +} + +RZ_OWN char *Elf_(rz_bin_elf_get_e_phoff_as_string)(RZ_NONNULL ELFOBJ *bin) { + rz_return_val_if_fail(bin, NULL); + + return rz_str_newf("0x%08" PFMT64x, (ut64)bin->ehdr.e_phoff); +} + +RZ_OWN char *Elf_(rz_bin_elf_get_e_shentsize_as_string)(RZ_NONNULL ELFOBJ *bin) { + rz_return_val_if_fail(bin, NULL); + + return rz_str_newf("%d", bin->ehdr.e_shentsize); +} + +RZ_OWN char *Elf_(rz_bin_elf_get_e_shnum_as_string)(RZ_NONNULL ELFOBJ *bin) { + rz_return_val_if_fail(bin, NULL); + + return rz_str_newf("%d", bin->ehdr.e_shnum); +} + +RZ_OWN char *Elf_(rz_bin_elf_get_e_shoff_as_string)(RZ_NONNULL ELFOBJ *bin) { + rz_return_val_if_fail(bin, NULL); + + return rz_str_newf("0x%08" PFMT64x, (ut64)bin->ehdr.e_shoff); +} + +RZ_OWN char *Elf_(rz_bin_elf_get_e_shstrndx_as_string)(RZ_NONNULL ELFOBJ *bin) { + rz_return_val_if_fail(bin, NULL); + + return rz_str_newf("%d", bin->ehdr.e_shstrndx); +} + +RZ_OWN char *Elf_(rz_bin_elf_get_e_type_as_string)(RZ_NONNULL ELFOBJ *bin) { + rz_return_val_if_fail(bin, NULL); + + return rz_str_newf("0x%04x", bin->ehdr.e_type); +} + +RZ_OWN char *Elf_(rz_bin_elf_get_e_version_as_string)(RZ_NONNULL ELFOBJ *bin) { + rz_return_val_if_fail(bin, NULL); + + return rz_str_newf("0x%08x", bin->ehdr.e_version); +} + +bool Elf_(rz_bin_elf_get_ehdr)(RZ_NONNULL ELFOBJ *bin) { + rz_return_val_if_fail(bin, false); + + memset(&bin->ehdr, 0, sizeof(Elf_(Ehdr))); + + if (rz_buf_read_at(bin->b, 0, bin->ehdr.e_ident, EI_NIDENT) < EI_NIDENT) { + RZ_LOG_WARN("Failed to read ELF header e_ident.\n") + return false; + } + + if (!is_valid_elf_ident(bin->ehdr.e_ident)) { + RZ_LOG_WARN("Invalid ELF identification.\n"); + return false; + } + + bin->big_endian = bin->ehdr.e_ident[EI_DATA] == ELFDATA2MSB; + + return read_ehdr_other(bin); +} + +bool Elf_(rz_bin_elf_print_ehdr)(ELFOBJ *bin, RZ_NONNULL PrintfCallback cb) { + rz_return_val_if_fail(bin && cb, false); + + return print_ehdr_aux(bin, cb, E_IDENT_OFFSET, "MAGIC", Elf_(rz_bin_elf_get_e_indent_as_string)) && + print_ehdr_aux(bin, cb, E_TYPE_OFFSET, "Type", Elf_(rz_bin_elf_get_e_type_as_string)) && + print_ehdr_aux(bin, cb, E_MACHINE_OFFSET, "Machine", Elf_(rz_bin_elf_get_e_machine_as_string)) && + print_ehdr_aux(bin, cb, E_VERSION_OFFSET, "Version", Elf_(rz_bin_elf_get_e_version_as_string)) && + print_ehdr_aux(bin, cb, E_ENTRYPOINT_OFFSET, "Entrypoint", Elf_(rz_bin_elf_get_e_entry_as_string)) && + print_ehdr_aux(bin, cb, E_PHOFF_OFFSET, "PhOff", Elf_(rz_bin_elf_get_e_phoff_as_string)) && + print_ehdr_aux(bin, cb, E_SHOFF_OFFSET, "ShOff", Elf_(rz_bin_elf_get_e_shoff_as_string)) && + print_ehdr_aux(bin, cb, E_FLAGS_OFFSET, "Flags", Elf_(rz_bin_elf_get_e_flags_as_string)) && + print_ehdr_aux(bin, cb, E_EHSIZE_OFFSET, "EhSize", Elf_(rz_bin_elf_get_e_ehsize_as_string)) && + print_ehdr_aux(bin, cb, E_PHENTSIZE_OFFSET, "PhentSize", Elf_(rz_bin_elf_get_e_phentsize_as_string)) && + print_ehdr_aux(bin, cb, E_PHNUM_OFFSET, "PhNum", Elf_(rz_bin_elf_get_e_phnum_as_string)) && + print_ehdr_aux(bin, cb, E_SHENTSIZE_OFFSET, "ShentSize", Elf_(rz_bin_elf_get_e_shentsize_as_string)) && + print_ehdr_aux(bin, cb, E_SHNUM_OFFSET, "ShNum", Elf_(rz_bin_elf_get_e_shnum_as_string)) && + print_ehdr_aux(bin, cb, E_SHSTRNDX_OFFSET, "ShStrndx", Elf_(rz_bin_elf_get_e_shstrndx_as_string)); +} diff --git a/librz/bin/format/elf/elf_specs.h b/librz/bin/format/elf/elf_specs.h index 4cad98b7aa..ab52baa792 100644 --- a/librz/bin/format/elf/elf_specs.h +++ b/librz/bin/format/elf/elf_specs.h @@ -42,6 +42,21 @@ #define ELF_M_INFO ELF32_M_INFO #endif +#define E_IDENT_OFFSET offsetof(Elf_(Ehdr), e_ident) +#define E_TYPE_OFFSET offsetof(Elf_(Ehdr), e_type) +#define E_MACHINE_OFFSET offsetof(Elf_(Ehdr), e_machine) +#define E_VERSION_OFFSET offsetof(Elf_(Ehdr), e_version) +#define E_ENTRYPOINT_OFFSET offsetof(Elf_(Ehdr), e_entry) +#define E_PHOFF_OFFSET offsetof(Elf_(Ehdr), e_phoff) +#define E_SHOFF_OFFSET offsetof(Elf_(Ehdr), e_shoff) +#define E_FLAGS_OFFSET offsetof(Elf_(Ehdr), e_flags) +#define E_EHSIZE_OFFSET offsetof(Elf_(Ehdr), e_ehsize) +#define E_PHENTSIZE_OFFSET offsetof(Elf_(Ehdr), e_phentsize) +#define E_PHNUM_OFFSET offsetof(Elf_(Ehdr), e_phnum) +#define E_SHENTSIZE_OFFSET offsetof(Elf_(Ehdr), e_shentsize) +#define E_SHNUM_OFFSET offsetof(Elf_(Ehdr), e_shnum) +#define E_SHSTRNDX_OFFSET offsetof(Elf_(Ehdr), e_shstrndx) + /* MingW doesn't define __BEGIN_DECLS / __END_DECLS. */ #ifndef __BEGIN_DECLS #ifdef __cplusplus diff --git a/librz/bin/meson.build b/librz/bin/meson.build index 683d7df05f..a09664298a 100644 --- a/librz/bin/meson.build +++ b/librz/bin/meson.build @@ -80,6 +80,8 @@ rz_bin_sources = [ 'format/elf/elf64_corefile.c', 'format/elf/elf_dynamic.c', 'format/elf/elf64_dynamic.c', + 'format/elf/elf_ehdr.c', + 'format/elf/elf64_ehdr.c', 'format/elf/elf_hash.c', 'format/elf/elf64_hash.c', 'format/elf/elf_imports.c', diff --git a/librz/bin/p/bin_cgc.c b/librz/bin/p/bin_cgc.c index c27b38fe46..8b76a260b1 100644 --- a/librz/bin/p/bin_cgc.c +++ b/librz/bin/p/bin_cgc.c @@ -7,10 +7,6 @@ extern struct rz_bin_dbginfo_t rz_bin_dbginfo_elf; -static void destroy(RzBinFile *bf) { - Elf_(rz_bin_elf_free)(bf->o->bin_obj); -} - static bool check_buffer(RzBuffer *buf) { ut8 tmp[SCGCMAG + 1]; int r = rz_buf_read_at(buf, 0, tmp, sizeof(tmp)); diff --git a/librz/bin/p/bin_elf.c b/librz/bin/p/bin_elf.c index 865aa3e6b4..a6ee5ca1fd 100644 --- a/librz/bin/p/bin_elf.c +++ b/librz/bin/p/bin_elf.c @@ -5,204 +5,8 @@ #include "bin_elf.inc" -static void destroy(RzBinFile *bf) { - Elf_(rz_bin_elf_free)(bf->o->bin_obj); -} - -static void headers32(RzBinFile *bf) { -#define p bf->rbin->cb_printf - ut32 magic; - if (!rz_buf_read_le32_at(bf->buf, 0, &magic)) { - return; - } - p("0x00000000 ELF MAGIC 0x%08x\n", magic); - - ut16 type; - if (!rz_buf_read_le16_at(bf->buf, 0x10, &type)) { - return; - } - p("0x00000010 Type 0x%04x\n", type); - - ut16 machine; - if (!rz_buf_read_le16_at(bf->buf, 0x12, &machine)) { - return; - } - p("0x00000012 Machine 0x%04x\n", machine); - - ut32 version; - if (!rz_buf_read_le32_at(bf->buf, 0x14, &version)) { - return; - } - p("0x00000014 Version 0x%08x\n", version); - - ut32 entry; - if (!rz_buf_read_le32_at(bf->buf, 0x18, &entry)) { - return; - } - p("0x00000018 Entrypoint 0x%08x\n", entry); - - ut32 phoff; - if (!rz_buf_read_le32_at(bf->buf, 0x1c, &phoff)) { - return; - } - p("0x0000001c PhOff 0x%08x\n", phoff); - - ut32 shoff; - if (!rz_buf_read_le32_at(bf->buf, 0x20, &shoff)) { - return; - } - p("0x00000020 ShOff 0x%08x\n", shoff); - - ut32 flags; - if (!rz_buf_read_le32_at(bf->buf, 0x24, &flags)) { - return; - } - p("0x00000024 Flags 0x%08x\n", flags); - - ut16 ehsize; - if (!rz_buf_read_le16_at(bf->buf, 0x28, &ehsize)) { - return; - } - p("0x00000028 EhSize %d\n", ehsize); - - ut16 phentsize; - if (!rz_buf_read_le16_at(bf->buf, 0x2a, &phentsize)) { - return; - } - p("0x0000002a PhentSize %d\n", phentsize); - - ut16 phnum; - if (!rz_buf_read_le16_at(bf->buf, 0x2c, &phnum)) { - return; - } - p("0x0000002c PhNum %d\n", phnum); - - ut16 shentsize; - if (!rz_buf_read_le16_at(bf->buf, 0x2e, &shentsize)) { - return; - } - p("0x0000002e ShentSize %d\n", shentsize); - - ut16 shnum; - if (!rz_buf_read_le16_at(bf->buf, 0x30, &shnum)) { - return; - } - p("0x00000030 ShNum %d\n", shnum); - - ut16 shrstrndx; - if (!rz_buf_read_le16_at(bf->buf, 0x32, &shrstrndx)) { - return; - } - p("0x00000032 ShrStrndx %d\n", shrstrndx); -} - static bool check_buffer(RzBuffer *buf) { - ut8 b[5] = { 0 }; - rz_buf_read_at(buf, 0, b, sizeof(b)); - return !memcmp(b, ELFMAG, SELFMAG) && b[4] != 2; -} - -extern struct rz_bin_dbginfo_t rz_bin_dbginfo_elf; - -static RzBuffer *create(RzBin *bin, const ut8 *code, int codelen, const ut8 *data, int datalen, RzBinArchOptions *opt) { - rz_return_val_if_fail(bin && opt && opt->arch, NULL); - - ut32 filesize, code_va, code_pa, phoff; - ut32 p_start, p_phoff, p_phdr; - ut32 p_ehdrsz, p_phdrsz; - ut16 ehdrsz, phdrsz; - ut32 p_vaddr, p_paddr, p_fs, p_fs2; - ut32 baddr; - RzBuffer *buf = rz_buf_new_with_bytes(NULL, 0); - - bool is_arm = !strcmp(opt->arch, "arm"); - // XXX: hardcoded - if (is_arm) { - baddr = 0x40000; - } else { - baddr = 0x8048000; - } - -#define B(x, y) rz_buf_append_bytes(buf, (const ut8 *)(x), y) -#define D(x) rz_buf_append_ut32(buf, x) -#define H(x) rz_buf_append_ut16(buf, x) -#define Z(x) rz_buf_append_nbytes(buf, x) -#define W(x, y, z) rz_buf_write_at(buf, x, (const ut8 *)(y), z) -#define WZ(x, y) \ - p_tmp = rz_buf_size(buf); \ - Z(x); \ - W(p_tmp, y, strlen(y)) - - B("\x7F" - "ELF" - "\x01\x01\x01\x00", - 8); - Z(8); - H(2); // ET_EXEC - if (is_arm) { - H(40); // e_machne = EM_ARM - } else { - H(3); // e_machne = EM_I386 - } - - D(1); - p_start = rz_buf_size(buf); - D(-1); // _start - p_phoff = rz_buf_size(buf); - D(-1); // phoff -- program headers offset - D(0); // shoff -- section headers offset - D(0); // flags - p_ehdrsz = rz_buf_size(buf); - H(-1); // ehdrsz - p_phdrsz = rz_buf_size(buf); - H(-1); // phdrsz - H(1); - H(0); - H(0); - H(0); - // phdr: - p_phdr = rz_buf_size(buf); - D(1); - D(0); - p_vaddr = rz_buf_size(buf); - D(-1); // vaddr = $$ - p_paddr = rz_buf_size(buf); - D(-1); // paddr = $$ - p_fs = rz_buf_size(buf); - D(-1); // filesize - p_fs2 = rz_buf_size(buf); - D(-1); // filesize - D(5); // flags - D(0x1000); // align - - ehdrsz = p_phdr; - phdrsz = rz_buf_size(buf) - p_phdr; - code_pa = rz_buf_size(buf); - code_va = code_pa + baddr; - phoff = 0x34; //p_phdr ; - filesize = code_pa + codelen + datalen; - - W(p_start, &code_va, 4); - W(p_phoff, &phoff, 4); - W(p_ehdrsz, &ehdrsz, 2); - W(p_phdrsz, &phdrsz, 2); - - code_va = baddr; // hack - W(p_vaddr, &code_va, 4); - code_pa = baddr; // hack - W(p_paddr, &code_pa, 4); - - W(p_fs, &filesize, 4); - W(p_fs2, &filesize, 4); - - B(code, codelen); - - if (data && datalen > 0) { - //ut32 data_section = buf->length; - eprintf("Warning: DATA section not support for ELF yet\n"); - B(data, datalen); - } - return buf; + return check_buffer_aux(buf) == ELFCLASS32; } RzBinPlugin rz_bin_plugin_elf = { @@ -224,11 +28,11 @@ RzBinPlugin rz_bin_plugin_elf = { .imports = &imports, .info = &info, .fields = &fields, - .header = &headers32, + .header = &headers, .size = &size, .libs = &libs, .relocs = &relocs, - .create = &create, + .create = &create_elf, .file_type = &get_file_type, .regstate = ®state, .section_type_to_string = &Elf_(rz_bin_elf_section_type_to_string), diff --git a/librz/bin/p/bin_elf.inc b/librz/bin/p/bin_elf.inc index 620ff5b6ec..d740de20b6 100644 --- a/librz/bin/p/bin_elf.inc +++ b/librz/bin/p/bin_elf.inc @@ -13,13 +13,354 @@ #include "elf/elf.h" #include +#define rz_bin_file_get_elf(bf) ((ELFOBJ *)bf->o->bin_obj) + #define VFILE_NAME_RELOC_TARGETS "reloc-targets" #define VFILE_NAME_PATCHED "patched" +#ifdef RZ_BIN_ELF64 +#define rz_buf_append_word rz_buf_append_ut64 +#else +#define rz_buf_append_word rz_buf_append_ut32 +#endif + static RzBinInfo *info(RzBinFile *bf); static void patch_relocs(RzBinFile *bf, struct Elf_(rz_bin_elf_obj_t) * bin); static RzList *imports(RzBinFile *bf); +struct special_symbol_translation { + RzBinSpecialSymbol symbol; + ut64 (*get_addr)(ELFOBJ *bin); +}; + +static struct special_symbol_translation special_symbol_translation_table[] = { + { RZ_BIN_SPECIAL_SYMBOL_ENTRY, Elf_(rz_bin_elf_get_entry_offset) }, + { RZ_BIN_SPECIAL_SYMBOL_MAIN, Elf_(rz_bin_elf_get_main_offset) }, + { RZ_BIN_SPECIAL_SYMBOL_INIT, Elf_(rz_bin_elf_get_init_offset) }, + { RZ_BIN_SPECIAL_SYMBOL_FINI, Elf_(rz_bin_elf_get_fini_offset) }, +}; + +static Sdb *get_sdb(RzBinFile *bf) { + rz_return_val_if_fail(bf && bf->o && bf->o->bin_obj, NULL); + + ELFOBJ *bin = rz_bin_file_get_elf(bf); + return bin->kv; +} + +#ifndef RZ_BIN_CGC +static int check_buffer_aux(RzBuffer *buf) { + rz_return_val_if_fail(buf, ELFCLASSNONE); + + ut8 tmp[SELFMAG + 1] = { 0 }; + + if (rz_buf_read_at(buf, 0, tmp, SELFMAG + 1) < 0) { + return ELFCLASSNONE; + } + + if (memcmp(tmp, ELFMAG, SELFMAG)) { + return ELFCLASSNONE; + } + + return tmp[SELFMAG]; +} +#endif + +static bool load_buffer(RZ_UNUSED RzBinFile *bf, RzBinObject *obj, RzBuffer *buf, RZ_UNUSED Sdb *sdb) { + rz_return_val_if_fail(obj, NULL); + + ELFOBJ *bin = Elf_(rz_bin_elf_new_buf)(buf, &obj->opts); + if (!bin) { + return false; + } + + obj->bin_obj = bin; + return true; +} + +static ut64 baddr(RzBinFile *bf) { + rz_return_val_if_fail(bf && bf->o, UT64_MAX); + + ELFOBJ *bin = rz_bin_file_get_elf(bf); + return Elf_(rz_bin_elf_get_baddr)(bin); +} + +static ut64 boffset(RzBinFile *bf) { + rz_return_val_if_fail(bf && bf->o, UT64_MAX); + + ELFOBJ *bin = rz_bin_file_get_elf(bf); + return Elf_(rz_bin_elf_get_boffset)(bin); +} + +static ut64 binsym_aux(ELFOBJ *bin, RzBinSpecialSymbol sym) { + for (size_t i = 0; i < RZ_ARRAY_SIZE(special_symbol_translation_table); i++) { + if (sym == special_symbol_translation_table[i].symbol) { + return special_symbol_translation_table[i].get_addr(bin); + } + } + + return UT64_MAX; +} + +static RzBinAddr *rz_bin_addr_new_aux(ELFOBJ *bin, ut64 paddr, ut64 vaddr) { + RzBinAddr *result = RZ_NEW0(RzBinAddr); + if (!result) { + return NULL; + } + + result->paddr = paddr; + result->vaddr = vaddr; + result->bits = bin->bits; + + if (Elf_(rz_bin_elf_is_arm_binary_supporting_thumb)(bin)) { + rz_bin_elf_fix_arm_thumb_object_dispatch(result); + } + + return result; +} + +static RzBinAddr *rz_bin_addr_new_from_paddr(ELFOBJ *bin, ut64 paddr) { + ut64 vaddr = Elf_(rz_bin_elf_p2v_new)(bin, paddr); + if (vaddr == UT64_MAX) { + vaddr = paddr; + } + + return rz_bin_addr_new_aux(bin, paddr, vaddr); +} + +static RzBinAddr *rz_bin_addr_new_from_vaddr(ELFOBJ *bin, ut64 vaddr) { + ut64 paddr = Elf_(rz_bin_elf_v2p_new)(bin, vaddr); + + return rz_bin_addr_new_aux(bin, paddr, vaddr); +} + +static RzBinAddr *binsym(RzBinFile *bf, RzBinSpecialSymbol sym) { + rz_return_val_if_fail(bf && bf->o && bf->o, NULL); + + ELFOBJ *bin = rz_bin_file_get_elf(bf); + + ut64 paddr = binsym_aux(bin, sym); + if (paddr == UT64_MAX) { + return NULL; + } + + return rz_bin_addr_new_from_paddr(bin, paddr); +} + +static void add_constructor(ELFOBJ *bin, ut64 addr, ut64 size, int type, RzList *result) { + ut64 constructor_offset = Elf_(rz_bin_elf_v2p_new)(bin, addr); + if (constructor_offset == UT64_MAX) { + return; + } + + ut64 pos = 0; + + while (pos < size) { + ut64 offset = constructor_offset + pos; + + Elf_(Addr) vaddr; + if (!Elf_(rz_bin_elf_read_addr)(bin, &offset, &vaddr)) { + break; + } + + if (!vaddr) { + pos += sizeof(Elf_(Addr)); + continue; + } + + RzBinAddr *tmp = rz_bin_addr_new_from_vaddr(bin, vaddr); + if (!tmp) { + break; + } + + tmp->hpaddr = constructor_offset + pos; + tmp->hvaddr = addr + pos; + tmp->type = type; + + rz_list_append(result, tmp); + + pos += sizeof(Elf_(Addr)); + } +} + +static void add_constructors(ELFOBJ *bin, RzList *result) { + ut64 addr, size; + + if (Elf_(rz_bin_elf_get_dt_info)(bin, DT_PREINIT_ARRAY, &addr) && Elf_(rz_bin_elf_get_dt_info)(bin, DT_PREINIT_ARRAYSZ, &size)) { + add_constructor(bin, addr, size, RZ_BIN_ENTRY_TYPE_PREINIT, result); + } + + if (Elf_(rz_bin_elf_get_dt_info)(bin, DT_INIT_ARRAY, &addr) && Elf_(rz_bin_elf_get_dt_info)(bin, DT_INIT_ARRAYSZ, &size)) { + add_constructor(bin, addr, size, RZ_BIN_ENTRY_TYPE_INIT, result); + } + + if (Elf_(rz_bin_elf_get_dt_info)(bin, DT_FINI_ARRAY, &addr) && Elf_(rz_bin_elf_get_dt_info)(bin, DT_FINI_ARRAYSZ, &size)) { + add_constructor(bin, addr, size, RZ_BIN_ENTRY_TYPE_FINI, result); + } +} + +static void add_entry_offset(ELFOBJ *bin, RzList *result) { + ut64 paddr = Elf_(rz_bin_elf_get_entry_offset)(bin); + if (paddr == UT64_MAX) { + return; + } + + RzBinAddr *tmp = rz_bin_addr_new_from_paddr(bin, paddr); + if (!tmp) { + return; + } + + tmp->hpaddr = E_ENTRYPOINT_OFFSET; + tmp->hvaddr = bin->baddr + tmp->hpaddr; + + if (tmp->vaddr != (ut64)bin->ehdr.e_entry && Elf_(rz_bin_elf_is_executable)(bin)) { + eprintf("Cannot determine entrypoint, using 0x%08" PFMT64x ".\n", tmp->vaddr); + } + + rz_list_append(result, tmp); +} + +static void add_java_libraries(ELFOBJ *bin, RzList *result) { + RzBinElfSymbol *symbol; + rz_bin_elf_foreach_symbols(bin, symbol) { + if (symbol->name && rz_str_startswith(symbol->name, "Java") && rz_str_endswith(symbol->name, "_init")) { + RzBinAddr *tmp = rz_bin_addr_new_from_paddr(bin, symbol->paddr); + tmp->type = RZ_BIN_ENTRY_TYPE_INIT; + + rz_list_append(result, tmp); + break; + } + } +} + +static RzList *entries(RzBinFile *bf) { + rz_return_val_if_fail(bf && bf->o, NULL); + + ELFOBJ *bin = rz_bin_file_get_elf(bf); + + RzList *result = rz_list_newf((RzListFree)free); + if (!result) { + return NULL; + } + + add_entry_offset(bin, result); + add_java_libraries(bin, result); + add_constructors(bin, result); + + return result; +} + +#ifndef RZ_BIN_CGC +static void headers(RzBinFile *bf) { + rz_return_if_fail(bf && bf->o && bf->o->bin_obj); + + ELFOBJ *bin = rz_bin_file_get_elf(bf); + + Elf_(rz_bin_elf_print_ehdr)(bin, bf->rbin->cb_printf); +} + +static bool create_set_e_ident(RzBuffer *result) { + return rz_buf_append_bytes(result, (ut8 *)ELFMAG, SELFMAG) && +#ifdef RZ_BIN_ELF64 + rz_buf_append_bytes(result, (ut8 *)"\x2\x1\x1\x0", 4) && +#else + rz_buf_append_bytes(result, (ut8 *)"\x1\x1\x1\x0", 4) && +#endif + rz_buf_append_nbytes(result, 8); +} + +static bool create_set_e_machine(RzBuffer *result, bool is_arm) { +#ifdef RZ_BIN_ELF64 + return rz_buf_append_ut16(result, EM_X86_64); +#else + if (is_arm) { + return rz_buf_append_ut16(result, EM_ARM); + } + + return rz_buf_append_ut16(result, EM_386); +#endif +} + +static bool create_set_ehdr(RzBuffer *result, bool is_arm) { + return create_set_e_ident(result) && + rz_buf_append_ut16(result, ET_EXEC) && + create_set_e_machine(result, is_arm) && + rz_buf_append_ut32(result, EV_CURRENT) && + rz_buf_append_word(result, sizeof(Elf_(Ehdr)) + sizeof(Elf_(Phdr))) && // e_entry + rz_buf_append_word(result, sizeof(Elf_(Ehdr))) && // e_phoff + rz_buf_append_word(result, 0) && // e_shoff + rz_buf_append_ut32(result, 0) && // e_flags + rz_buf_append_ut16(result, sizeof(Elf_(Ehdr))) && // e_ehsize + rz_buf_append_ut16(result, sizeof(Elf_(Phdr))) && // e_phentsize + rz_buf_append_ut16(result, 1) && // e_phnum + rz_buf_append_ut16(result, 0) && // e_shentsize + rz_buf_append_ut16(result, 0) && // e_shnum + rz_buf_append_ut16(result, 0); // e_shstrndx +} + +static bool create_set_phdr(RzBuffer *result, Elf_(Word) baddr, int codelen) { + ut64 length = sizeof(Elf_(Ehdr)) + sizeof(Elf_(Phdr)) + codelen; + + return rz_buf_append_ut32(result, PT_LOAD) && +#ifdef RZ_BIN_ELF64 + rz_buf_append_ut32(result, PF_X | PF_R) && + rz_buf_append_ut64(result, 0) && // p_offset + rz_buf_append_ut64(result, baddr) && // p_vaddr + rz_buf_append_ut64(result, baddr) && // p_paddr + rz_buf_append_ut64(result, length) && // p_filesz + rz_buf_append_ut64(result, length) && // p_memsz + rz_buf_append_ut64(result, 0x200000); // p_align +#else + rz_buf_append_ut32(result, 0) && // p_offset + rz_buf_append_ut32(result, baddr) && // p_vaddr + rz_buf_append_ut32(result, baddr) && // p_paddr + rz_buf_append_ut32(result, length) && // p_filesz + rz_buf_append_ut32(result, length) && // p_memsz + rz_buf_append_ut32(result, PF_X | PF_R) && // p_flags + rz_buf_append_ut64(result, 0x1000); // p_align +#endif +} + +static Elf_(Word) create_get_baddr(bool is_arm) { +#ifdef RZ_BIN_ELF64 + return 0x400000LL; +#else + if (is_arm) { + return 0x40000; + } + + return 0x8048000; +#endif +} + +static RzBuffer *create_elf(RzBin *bin, const ut8 *code, int codelen, const ut8 *data, int datalen, RzBinArchOptions *opt) { + rz_return_val_if_fail(bin && opt && opt->arch, NULL); + + RzBuffer *result = rz_buf_new_with_bytes(NULL, 0); + + bool is_arm = !strcmp(opt->arch, "arm"); + Elf_(Word) baddr = create_get_baddr(is_arm); + + if (!create_set_ehdr(result, is_arm) || + !create_set_phdr(result, baddr, codelen) || + !rz_buf_append_bytes(result, code, codelen)) { + rz_buf_free(result); + return NULL; + } + + if (data && datalen > 0) { + //ut32 data_section = buf->length; + eprintf("Warning: DATA section not support for ELF yet\n"); + rz_buf_append_bytes(result, data, datalen); + } + + return result; +} +#endif + +static void destroy(RzBinFile *bf) { + Elf_(rz_bin_elf_free)(bf->o->bin_obj); +} + static RzBinSymbol *convert_symbol(ELFOBJ *bin, RzBinElfSymbol *elf_symbol) { RzBinSymbol *result = RZ_NEW0(RzBinSymbol); if (!result) { @@ -122,69 +463,6 @@ static char *setphname(ut16 mach, Elf_(Word) ptyp) { return strdup("UNKNOWN"); } -static Sdb *get_sdb(RzBinFile *bf) { - RzBinObject *o = bf->o; - if (o && o->bin_obj) { - struct Elf_(rz_bin_elf_obj_t) *bin = (struct Elf_(rz_bin_elf_obj_t) *)o->bin_obj; - return bin->kv; - } - return NULL; -} - -static bool load_buffer(RzBinFile *bf, RzBinObject *obj, RzBuffer *buf, Sdb *sdb) { - ELFOBJ *res = Elf_(rz_bin_elf_new_buf)(buf, &obj->opts); - if (res) { - obj->bin_obj = res; - return true; - } - - return false; -} - -static ut64 baddr(RzBinFile *bf) { - return Elf_(rz_bin_elf_get_baddr)(bf->o->bin_obj); -} - -static ut64 boffset(RzBinFile *bf) { - return Elf_(rz_bin_elf_get_boffset)(bf->o->bin_obj); -} - -static RzBinAddr *binsym(RzBinFile *bf, RzBinSpecialSymbol sym) { - struct Elf_(rz_bin_elf_obj_t) *obj = bf->o->bin_obj; - RzBinAddr *ret = NULL; - ut64 addr = 0LL; - - switch (sym) { - case RZ_BIN_SPECIAL_SYMBOL_ENTRY: - addr = Elf_(rz_bin_elf_get_entry_offset)(bf->o->bin_obj); - break; - case RZ_BIN_SPECIAL_SYMBOL_MAIN: - addr = Elf_(rz_bin_elf_get_main_offset)(bf->o->bin_obj); - break; - case RZ_BIN_SPECIAL_SYMBOL_INIT: - addr = Elf_(rz_bin_elf_get_init_offset)(bf->o->bin_obj); - break; - case RZ_BIN_SPECIAL_SYMBOL_FINI: - addr = Elf_(rz_bin_elf_get_fini_offset)(bf->o->bin_obj); - break; - default: - break; - } - if (addr && addr != UT64_MAX && (ret = RZ_NEW0(RzBinAddr))) { - struct Elf_(rz_bin_elf_obj_t) *bin = bf->o->bin_obj; - ret->paddr = addr; - ret->vaddr = Elf_(rz_bin_elf_p2v_new)(obj, addr); - ret->bits = obj->bits; - if (ret->vaddr == UT64_MAX) { - ret->vaddr = addr; - } - if (Elf_(rz_bin_elf_is_arm_binary_supporting_thumb)(bin)) { - rz_bin_elf_fix_arm_thumb_object_dispatch(ret); - } - } - return ret; -} - static bool is_wordable_section(const char *name) { if (!strcmp(name, ".init_array")) { return true; @@ -893,141 +1171,6 @@ static RzList *sections(RzBinFile *bf) { return ret; } -static RzBinAddr *newEntry(RzBinFile *bf, ut64 hpaddr, ut64 hvaddr, ut64 vaddr, int type, int bits) { - rz_return_val_if_fail(bf && bf->o && bf->o->bin_obj, NULL); - - struct Elf_(rz_bin_elf_obj_t) *obj = bf->o->bin_obj; - RzBinAddr *ptr = RZ_NEW0(RzBinAddr); - if (ptr) { - ptr->paddr = Elf_(rz_bin_elf_v2p_new)(obj, vaddr); - ptr->vaddr = vaddr; - ptr->hpaddr = hpaddr; - ptr->hvaddr = hvaddr; - ptr->bits = bits; - ptr->type = type; - //realign due to thumb - if (bits == 16 && Elf_(rz_bin_elf_is_thumb_addr)(ptr->vaddr)) { - ptr->paddr--; - ptr->vaddr--; - } - } - return ptr; -} - -static void process_constructors(RzBinFile *bf, RzList *ret, int bits) { - RzList *secs = sections(bf); - RzListIter *iter; - RzBinSection *sec; - int i, type; - rz_list_foreach (secs, iter, sec) { - type = -1; - if (!strcmp(sec->name, ".fini_array")) { - type = RZ_BIN_ENTRY_TYPE_FINI; - } else if (!strcmp(sec->name, ".init_array")) { - type = RZ_BIN_ENTRY_TYPE_INIT; - } else if (!strcmp(sec->name, ".preinit_array")) { - type = RZ_BIN_ENTRY_TYPE_PREINIT; - } - if (type != -1) { - ut8 *buf = calloc(sec->size, 1); - if (!buf) { - continue; - } - (void)rz_buf_read_at(bf->buf, sec->paddr, buf, sec->size); - if (bits == 32) { - for (i = 0; (i + 3) < sec->size; i += 4) { - ut32 addr32 = rz_read_le32(buf + i); - if (addr32) { - RzBinAddr *ba = newEntry(bf, sec->paddr + i, sec->vaddr + i, - (ut64)addr32, type, bits); - rz_list_append(ret, ba); - } - } - } else { - for (i = 0; (i + 7) < sec->size; i += 8) { - ut64 addr64 = rz_read_le64(buf + i); - if (addr64) { - RzBinAddr *ba = newEntry(bf, sec->paddr + i, sec->vaddr + i, - addr64, type, bits); - rz_list_append(ret, ba); - } - } - } - free(buf); - } - } - rz_list_free(secs); -} - -static RzList *entries(RzBinFile *bf) { - rz_return_val_if_fail(bf && bf->o && bf->o->bin_obj, NULL); - - RzBinAddr *ptr = NULL; - ELFOBJ *obj = bf->o->bin_obj; - RzList *ret = rz_list_newf((RzListFree)free); - if (!ret) { - return NULL; - } - ut64 pa = Elf_(rz_bin_elf_get_entry_offset)(obj); - if (pa != UT64_MAX) { - if (!(ptr = RZ_NEW0(RzBinAddr))) { - return ret; - } - ptr->paddr = pa; - ptr->vaddr = Elf_(rz_bin_elf_p2v_new)(obj, ptr->paddr); - ptr->hpaddr = 0x18; // e_entry offset in ELF header - ptr->hvaddr = UT64_MAX; - ptr->bits = obj->bits; - - if (ptr->vaddr != (ut64)obj->ehdr.e_entry && Elf_(rz_bin_elf_is_executable)(obj)) { - eprintf("Cannot determine entrypoint, using 0x%08" PFMT64x ".\n", ptr->vaddr); - } - - if (bf->o->sections) { - RzListIter *iter; - RzBinSection *section; - rz_list_foreach_prev(bf->o->sections, iter, section) { - if (!strcmp(section->name, "ehdr")) { - ptr->hvaddr = section->vaddr + ptr->hpaddr; - break; - } - } - } - - if (Elf_(rz_bin_elf_is_arm_binary_supporting_thumb)(obj)) { - rz_bin_elf_fix_arm_thumb_object_dispatch(ptr); - } - - rz_list_append(ret, ptr); - } - - // add entrypoint for jni libraries - // NOTE: this is slow, we shouldnt find for java constructors here - if (!Elf_(rz_bin_elf_has_symbols)(obj)) { - return ret; - } - - RzBinElfSymbol *symbol; - rz_bin_elf_foreach_symbols(obj, symbol) { - if (symbol->name && !strncmp(symbol->name, "Java", 4)) { - if (rz_str_endswith(symbol->name, "_init")) { - if (!(ptr = RZ_NEW0(RzBinAddr))) { - return ret; - } - ptr->paddr = symbol->paddr; - ptr->vaddr = symbol->vaddr; - ptr->hpaddr = UT64_MAX; - ptr->type = RZ_BIN_ENTRY_TYPE_INIT; - rz_list_append(ret, ptr); - break; - } - } - } - int bin_bits = obj->bits; - process_constructors(bf, ret, bin_bits < 32 ? 32 : bin_bits); - return ret; -} - static RzList *symbols(RzBinFile *bf) { rz_return_val_if_fail(bf && bf->o && bf->o->bin_obj, NULL); @@ -1308,167 +1451,63 @@ static RzBinInfo *info(RzBinFile *bf) { return ret; } +static bool add_fields_aux(ELFOBJ *bin, RzList *result, ut64 offset, size_t size, const char *name, char *(get_value)(ELFOBJ *bin), const char *fmt) { + char *value = get_value(bin); + if (!value) { + return false; + } + + RzBinField *field = rz_bin_field_new(offset, offset, size, name, value, fmt, false); + if (!field) { + free(value); + return false; + } + + if (!rz_list_append(result, field)) { + rz_bin_field_free(field); + free(value); + return false; + } + + free(value); + return true; +} + +static bool add_fields(ELFOBJ *bin, RzList *result) { + size_t size = bin->ehdr.e_ident[EI_CLASS] == ELFCLASS64 ? 8 : 4; + + return add_fields_aux(bin, result, E_IDENT_OFFSET, 16, "MAGIC", Elf_(rz_bin_elf_get_e_indent_as_string), "x") && + add_fields_aux(bin, result, E_TYPE_OFFSET, 2, "Type", Elf_(rz_bin_elf_get_e_type_as_string), "x") && + add_fields_aux(bin, result, E_MACHINE_OFFSET, 2, "Machine", Elf_(rz_bin_elf_get_e_machine_as_string), "x") && + add_fields_aux(bin, result, E_VERSION_OFFSET, 4, "Version", Elf_(rz_bin_elf_get_e_version_as_string), "x") && + add_fields_aux(bin, result, E_ENTRYPOINT_OFFSET, size, "Entrypoint", Elf_(rz_bin_elf_get_e_entry_as_string), "x") && + add_fields_aux(bin, result, E_PHOFF_OFFSET, size, "PhOff", Elf_(rz_bin_elf_get_e_phoff_as_string), "x") && + add_fields_aux(bin, result, E_SHOFF_OFFSET, size, "ShOff", Elf_(rz_bin_elf_get_e_shoff_as_string), "x") && + add_fields_aux(bin, result, E_FLAGS_OFFSET, 4, "Flags", Elf_(rz_bin_elf_get_e_flags_as_string), "x") && + add_fields_aux(bin, result, E_EHSIZE_OFFSET, 2, "EhSize", Elf_(rz_bin_elf_get_e_ehsize_as_string), "x") && + add_fields_aux(bin, result, E_PHENTSIZE_OFFSET, 2, "PhentSize", Elf_(rz_bin_elf_get_e_phentsize_as_string), "d") && + add_fields_aux(bin, result, E_PHNUM_OFFSET, 2, "PhNum", Elf_(rz_bin_elf_get_e_phnum_as_string), "d") && + add_fields_aux(bin, result, E_SHENTSIZE_OFFSET, 2, "ShentSize", Elf_(rz_bin_elf_get_e_shentsize_as_string), "d") && + add_fields_aux(bin, result, E_SHNUM_OFFSET, 2, "ShNum", Elf_(rz_bin_elf_get_e_shnum_as_string), "d") && + add_fields_aux(bin, result, E_SHSTRNDX_OFFSET, 2, "ShStrndx", Elf_(rz_bin_elf_get_e_shstrndx_as_string), "d"); +} + static RzList *fields(RzBinFile *bf) { - RzList *ret = rz_list_newf((RzListFree)rz_bin_field_free); - if (!ret) { + rz_return_val_if_fail(bf && bf->o && bf->o->bin_obj, NULL); + + ELFOBJ *bin = rz_bin_file_get_elf(bf); + + RzList *result = rz_list_newf((RzListFree)rz_bin_field_free); + if (!result) { return NULL; } -#define ROW(name, siz, val, fmt) \ - rz_list_append(ret, rz_bin_field_new(addr, addr, siz, name, sdb_fmt("0x%08" PFMT64x, (ut64)val), fmt, false)); - - if (rz_buf_size(bf->buf) < sizeof(Elf_(Ehdr))) { - return ret; - } - - ut32 magic; - ut64 addr = 0; - if (!rz_buf_read_le32_at(bf->buf, addr, &magic)) { - rz_list_free(ret); - return NULL; - } - ROW("ELF", 4, magic, "x"); - - ut16 type; - addr += 0x10; - if (!rz_buf_read_le16_at(bf->buf, addr, &type)) { - rz_list_free(ret); - return NULL; - } - ROW("Type", 2, type, "x"); - - ut16 machine; - addr += 0x2; - if (!rz_buf_read_le16_at(bf->buf, addr, &machine)) { - rz_list_free(ret); - return NULL; - } - ROW("Machine", 2, machine, "x"); - - ut32 version; - addr += 0x2; - if (!rz_buf_read_le32_at(bf->buf, addr, &version)) { - rz_list_free(ret); - return NULL; - } - ROW("Version", 4, version, "x"); - - ut8 tmp; - if (!rz_buf_read8_at(bf->buf, 0x04, &tmp)) { - rz_list_free(ret); + if (!add_fields(bin, result)) { + rz_list_free(result); return NULL; } - if (tmp == 1) { - ut32 entry; - addr += 0x4; - if (!rz_buf_read_le32_at(bf->buf, addr, &entry)) { - rz_list_free(ret); - return NULL; - } - ROW("Entry point", 4, entry, "x"); - - ut32 phoff; - addr += 0x4; - if (!rz_buf_read_le32_at(bf->buf, addr, &phoff)) { - rz_list_free(ret); - return NULL; - } - ROW("PhOff", 4, phoff, "x"); - - ut32 shoff; - addr += 0x4; - if (!rz_buf_read_le32_at(bf->buf, addr, &shoff)) { - rz_list_free(ret); - return NULL; - } - ROW("ShOff", 4, shoff, "x"); - - addr += 0x4; - } else { - ut64 entry; - addr += 0x4; - if (!rz_buf_read_le64_at(bf->buf, addr, &entry)) { - rz_list_free(ret); - return NULL; - } - ROW("Entry point", 8, entry, "x"); - - ut64 phoff; - addr += 0x8; - if (!rz_buf_read_le64_at(bf->buf, addr, &phoff)) { - rz_list_free(ret); - return NULL; - } - ROW("PhOff", 8, phoff, "x"); - - ut64 shoff; - addr += 0x8; - if (!rz_buf_read_le64_at(bf->buf, addr, &shoff)) { - rz_list_free(ret); - return NULL; - } - ROW("ShOff", 8, shoff, "x"); - - addr += 0x8; - } - - ut32 flags; - if (!rz_buf_read_le32_at(bf->buf, addr, &flags)) { - rz_list_free(ret); - return NULL; - } - ROW("Flags", 4, flags, "x"); - - ut16 ehsize; - addr += 0x4; - if (!rz_buf_read_le16_at(bf->buf, addr, &ehsize)) { - rz_list_free(ret); - return NULL; - } - ROW("EhSize", 2, ehsize, "x"); - - ut16 phentsize; - addr += 0x2; - if (!rz_buf_read_le16_at(bf->buf, addr, &phentsize)) { - rz_list_free(ret); - return NULL; - } - ROW("PhentSize", 2, phentsize, "x"); - - ut16 phnum; - addr += 0x2; - if (!rz_buf_read_le16_at(bf->buf, addr, &phnum)) { - rz_list_free(ret); - return NULL; - } - ROW("PhNum", 2, phnum, "x"); - - ut16 shentsize; - addr += 0x2; - if (!rz_buf_read_le16_at(bf->buf, addr, &shentsize)) { - rz_list_free(ret); - return NULL; - } - ROW("ShentSize", 2, shentsize, "x"); - - ut16 shnum; - addr += 0x2; - if (!rz_buf_read_le16_at(bf->buf, addr, &shnum)) { - rz_list_free(ret); - return NULL; - } - ROW("ShNum", 2, shnum, "x"); - - ut16 shrstrndx; - addr += 0x2; - if (!rz_buf_read_le16_at(bf->buf, addr, &shrstrndx)) { - rz_list_free(ret); - return NULL; - } - ROW("ShrStrndx", 2, shrstrndx, "x"); - - return ret; + return result; } static ut64 size(RzBinFile *bf) { diff --git a/librz/bin/p/bin_elf64.c b/librz/bin/p/bin_elf64.c index 8da8010ec2..61714d5b6c 100644 --- a/librz/bin/p/bin_elf64.c +++ b/librz/bin/p/bin_elf64.c @@ -5,198 +5,14 @@ #define RZ_BIN_ELF64 1 #include "bin_elf.inc" -static void destroy(RzBinFile *bf) { - Elf_(rz_bin_elf_free)(bf->o->bin_obj); +static bool check_buffer(RzBuffer *buf) { + return check_buffer_aux(buf) == ELFCLASS64; } -static bool check_buffer(RzBuffer *b) { - ut8 buf[5] = { 0 }; - if (rz_buf_size(b) > 4) { - rz_buf_read_at(b, 0, buf, sizeof(buf)); - if (!memcmp(buf, "\x7F\x45\x4c\x46\x02", 5)) { - return true; - } - } - return false; -} - -extern struct rz_bin_dbginfo_t rz_bin_dbginfo_elf64; - static ut64 get_elf_vaddr64(RzBinFile *bf, ut64 baddr, ut64 paddr, ut64 vaddr) { //NOTE(aaSSfxxx): since RVA is vaddr - "official" image base, we just need to add imagebase to vaddr - struct Elf_(rz_bin_elf_obj_t) *obj = bf->o->bin_obj; - return obj->baddr - obj->boffset + vaddr; -} - -static void headers64(RzBinFile *bf) { -#define p bf->rbin->cb_printf - ut32 magic; - if (!rz_buf_read_le32_at(bf->buf, 0, &magic)) { - return; - } - p("0x00000000 ELF64 0x%08x\n", magic); - - ut16 type; - if (!rz_buf_read_le16_at(bf->buf, 0x10, &type)) { - return; - } - p("0x00000010 Type 0x%04x\n", type); - - ut16 machine; - if (!rz_buf_read_le16_at(bf->buf, 0x12, &machine)) { - return; - } - p("0x00000012 Machine 0x%04x\n", machine); - - ut32 version; - if (!rz_buf_read_le32_at(bf->buf, 0x14, &version)) { - return; - } - p("0x00000014 Version 0x%08x\n", version); - - ut64 entry; - if (!rz_buf_read_le64_at(bf->buf, 0x18, &entry)) { - return; - } - p("0x00000018 Entrypoint 0x%08" PFMT64x "\n", entry); - - ut64 phoff; - if (!rz_buf_read_le64_at(bf->buf, 0x20, &phoff)) { - return; - } - p("0x00000020 PhOff 0x%08" PFMT64x "\n", phoff); - - ut64 shoff; - if (!rz_buf_read_le64_at(bf->buf, 0x28, &shoff)) { - return; - } - p("0x00000028 ShOff 0x%08" PFMT64x "\n", shoff); - - ut32 flags; - if (!rz_buf_read_le32_at(bf->buf, 0x30, &flags)) { - return; - } - p("0x00000030 Flags 0x%08x\n", flags); - - ut16 ehsize; - if (!rz_buf_read_le16_at(bf->buf, 0x34, &ehsize)) { - return; - } - p("0x00000034 EhSize %d\n", ehsize); - - ut16 phentsize; - if (!rz_buf_read_le16_at(bf->buf, 0x36, &phentsize)) { - return; - } - p("0x00000036 PhentSize %d\n", phentsize); - - ut16 phnum; - if (!rz_buf_read_le16_at(bf->buf, 0x38, &phnum)) { - return; - } - p("0x00000038 PhNum %d\n", phnum); - - ut16 shentsize; - if (!rz_buf_read_le16_at(bf->buf, 0x3a, &shentsize)) { - return; - } - p("0x0000003a ShentSize %d\n", shentsize); - - ut16 shnum; - if (!rz_buf_read_le16_at(bf->buf, 0x3c, &shnum)) { - return; - } - p("0x0000003c ShNum %d\n", shnum); - - ut16 shrstrndx; - if (!rz_buf_read_le16_at(bf->buf, 0x3e, &shrstrndx)) { - return; - } - p("0x0000003e ShrStrndx %d\n", shrstrndx); -} - -static RzBuffer *create(RzBin *bin, const ut8 *code, int codelen, const ut8 *data, int datalen, RzBinArchOptions *opt) { - ut32 p_start, p_phoff, p_phdr; - ut32 p_vaddr, p_paddr, p_fs, p_fs2; - ut32 p_ehdrsz, p_phdrsz; - ut64 filesize, code_va, code_pa, phoff; - ut16 ehdrsz, phdrsz; - ut64 baddr = 0x400000LL; - RzBuffer *buf = rz_buf_new_with_bytes(NULL, 0); - -#define B(x, y) rz_buf_append_bytes(buf, (const ut8 *)(x), y) -#define Q(x) rz_buf_append_ut64(buf, x) -#define D(x) rz_buf_append_ut32(buf, x) -#define H(x) rz_buf_append_ut16(buf, x) -#define Z(x) rz_buf_append_nbytes(buf, x) -#define W(x, y, z) rz_buf_write_at(buf, x, (const ut8 *)(y), z) - - /* Ehdr */ - B("\x7F" - "ELF" - "\x02\x01\x01\x00", - 8); // e_ident (ei_class = ELFCLASS64) - Z(8); - H(2); // e_type = ET_EXEC - H(62); // e_machine = EM_X86_64 - D(1); // e_version = EV_CURRENT - p_start = rz_buf_size(buf); - Q(-1); // e_entry = 0xFFFFFFFF - p_phoff = rz_buf_size(buf); - Q(-1); // e_phoff = 0xFFFFFFFF - Q(0); // e_shoff = 0xFFFFFFFF - D(0); // e_flags - p_ehdrsz = rz_buf_size(buf); - H(-1); // e_ehsize = 0xFFFFFFFF - p_phdrsz = rz_buf_size(buf); - H(-1); // e_phentsize = 0xFFFFFFFF - H(1); // e_phnum - H(0); // e_shentsize - H(0); // e_shnum - H(0); // e_shstrndx - - /* Phdr */ - p_phdr = rz_buf_size(buf); - D(1); // p_type - D(5); // p_flags = PF_R | PF_X - Q(0); // p_offset - p_vaddr = rz_buf_size(buf); - Q(-1); // p_vaddr = 0xFFFFFFFF - p_paddr = rz_buf_size(buf); - Q(-1); // p_paddr = 0xFFFFFFFF - p_fs = rz_buf_size(buf); - Q(-1); // p_filesz - p_fs2 = rz_buf_size(buf); - Q(-1); // p_memsz - Q(0x200000); // p_align - - /* Calc fields */ - ehdrsz = p_phdr; - phdrsz = rz_buf_size(buf) - p_phdr; - code_pa = rz_buf_size(buf); - code_va = code_pa + baddr; - phoff = p_phdr; - filesize = code_pa + codelen + datalen; - - /* Write fields */ - W(p_start, &code_va, 8); - W(p_phoff, &phoff, 8); - W(p_ehdrsz, &ehdrsz, 2); - W(p_phdrsz, &phdrsz, 2); - W(p_fs, &filesize, 8); - W(p_fs2, &filesize, 8); - - W(p_vaddr, &baddr, 8); - W(p_paddr, &baddr, 8); - - /* Append code */ - B(code, codelen); - - if (data && datalen > 0) { - eprintf("Warning: DATA section not support for ELF yet\n"); - B(data, datalen); - } - return buf; + ELFOBJ *bin = bf->o->bin_obj; + return bin->baddr - bin->boffset + vaddr; } RzBinPlugin rz_bin_plugin_elf64 = { @@ -218,11 +34,11 @@ RzBinPlugin rz_bin_plugin_elf64 = { .minstrlen = 4, .info = &info, .fields = &fields, - .header = &headers64, + .header = &headers, .size = &size, .libs = &libs, .relocs = &relocs, - .create = &create, + .create = &create_elf, .get_vaddr = &get_elf_vaddr64, .file_type = &get_file_type, .regstate = ®state, diff --git a/test/db/cmd/cmd_i b/test/db/cmd/cmd_i index 8ea553e3b1..fb79d444a4 100644 --- a/test/db/cmd/cmd_i +++ b/test/db/cmd/cmd_i @@ -76,20 +76,20 @@ NAME=ih (file x86) FILE=bins/elf/analysis/x86-helloworld-gcc CMDS=ihq EXPECT=<