Refactor elf plugin interface (#1728)

* get_sdb
* check_buffer
* load_buffer
* baddr
* boffset
* binsym
* entries
* headers
* create
* fields
This commit is contained in:
Alexis Ehret 2021-09-28 07:36:46 +02:00 committed by GitHub
parent d5f1aea595
commit 01b6e60775
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 696 additions and 864 deletions

View file

@ -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;
}

View file

@ -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);

View file

@ -0,0 +1,6 @@
// SPDX-FileCopyrightText: 2021 08A <08A@riseup.net>
// SPDX-FileCopyrightText: 2021 RizinOrg <info@rizin.re>
// SPDX-License-Identifier: LGPL-3.0-only
#define RZ_BIN_ELF64 1
#include "elf_ehdr.c"

View file

@ -0,0 +1,219 @@
// SPDX-FileCopyrightText: 2021 08A <08A@riseup.net>
// SPDX-FileCopyrightText: 2021 RizinOrg <info@rizin.re>
// 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));
}

View file

@ -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

View file

@ -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',

View file

@ -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));

View file

@ -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 = &regstate,
.section_type_to_string = &Elf_(rz_bin_elf_section_type_to_string),

View file

@ -13,13 +13,354 @@
#include "elf/elf.h"
#include <ht_uu.h>
#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) {

View file

@ -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 = &regstate,

View file

@ -76,20 +76,20 @@ NAME=ih (file x86)
FILE=bins/elf/analysis/x86-helloworld-gcc
CMDS=ihq
EXPECT=<<EOF
0x00000000 0x00000000 ELF; 0x464c457f
0x00000010 0x00000010 Type; 0x00000002
0x00000012 0x00000012 Machine; 0x00000003
0x00000000 0x00000000 MAGIC; 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
0x00000010 0x00000010 Type; 0x0002
0x00000012 0x00000012 Machine; 0x0003
0x00000014 0x00000014 Version; 0x00000001
0x00000018 0x00000018 Entry point; 0x08048300
0x00000018 0x00000018 Entrypoint; 0x08048300
0x0000001c 0x0000001c PhOff; 0x00000034
0x00000020 0x00000020 ShOff; 0x000007cc
0x00000024 0x00000024 Flags; 0x00000000
0x00000028 0x00000028 EhSize; 0x00000034
0x0000002a 0x0000002a PhentSize; 0x00000020
0x0000002c 0x0000002c PhNum; 0x00000008
0x0000002e 0x0000002e ShentSize; 0x00000028
0x00000030 0x00000030 ShNum; 0x0000001e
0x00000032 0x00000032 ShrStrndx; 0x0000001b
0x00000024 0x00000024 Flags; 0x0000
0x00000028 0x00000028 EhSize; 52
0x0000002a 0x0000002a PhentSize; 32
0x0000002c 0x0000002c PhNum; 8
0x0000002e 0x0000002e ShentSize; 40
0x00000030 0x00000030 ShNum; 30
0x00000032 0x00000032 ShStrndx; 27
EOF
RUN
@ -3992,20 +3992,20 @@ NAME=iH (file x86_64)
FILE=bins/elf/analysis/hello-linux-x86_64
CMDS=iH
EXPECT=<<EOF
0x00000000 ELF64 0x464c457f
0x00000000 MAGIC 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
0x00000010 Type 0x0002
0x00000012 Machine 0x003e
0x00000014 Version 0x00000001
0x00000018 Entrypoint 0x00400410
0x00000020 PhOff 0x00000040
0x00000028 ShOff 0x00000a30
0x00000030 Flags 0x00000000
0x00000030 Flags 0x0000
0x00000034 EhSize 64
0x00000036 PhentSize 56
0x00000038 PhNum 8
0x0000003a ShentSize 64
0x0000003c ShNum 30
0x0000003e ShrStrndx 27
0x0000003e ShStrndx 27
EOF
RUN
@ -4818,6 +4818,8 @@ vaddr paddr target type name
0x000003f0 16 sym.imp.puts
0x00000400 16 sym.imp.__libc_start_main
0x00000420 1 entry0
0x00000500 1 entry.fini0
0x00000550 1 entry.init0
0x00000590 256 main
0x00000590 60 sym.main
0x0000064c 4 obj._IO_stdin_used

View file

@ -702,7 +702,7 @@ C.
EOF
EXPECT=<<EOF
0x0007a23c ascii[13] "match_symbol"
0x00083fc4 data Cd 4
0x00083fc4 CCu "[14] -rw- section size 4 named .init_array"
0x00083fc4 data Cd 4
EOF
RUN

View file

@ -14,8 +14,8 @@ CMDS=iee
EXPECT=<<EOF
vaddr paddr hvaddr haddr type
-------------------------------------------------
0x000002e4 0x000002e4 0x00001ed0 0x00000ed0 fini
0x00000344 0x00000344 0x00001ed8 0x00000ed8 init
0x000002e4 0x000002e4 0x00001ed0 0x00000ed0 fini
EOF
RUN

View file

@ -616,22 +616,22 @@ vaddr paddr type name
0x080496a8 0x000006a8 SET_32 __libc_start_main
[Fields]
paddr name vaddr comment
---------------------------------------------
0x00000000 ELF 0x00000000 0x464c457f
0x00000010 Type 0x00000010 0x00000002
0x00000012 Machine 0x00000012 0x00000003
0x00000014 Version 0x00000014 0x00000001
0x00000018 Entry point 0x00000018 0x08048300
0x0000001c PhOff 0x0000001c 0x00000034
0x00000020 ShOff 0x00000020 0x000007cc
0x00000024 Flags 0x00000024 0x00000000
0x00000028 EhSize 0x00000028 0x00000034
0x0000002a PhentSize 0x0000002a 0x00000020
0x0000002c PhNum 0x0000002c 0x00000008
0x0000002e ShentSize 0x0000002e 0x00000028
0x00000030 ShNum 0x00000030 0x0000001e
0x00000032 ShrStrndx 0x00000032 0x0000001b
paddr name vaddr comment
---------------------------------------------------------------------------------
0x00000000 MAGIC 0x00000000 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
0x00000010 Type 0x00000010 0x0002
0x00000012 Machine 0x00000012 0x0003
0x00000014 Version 0x00000014 0x00000001
0x00000018 Entrypoint 0x00000018 0x08048300
0x0000001c PhOff 0x0000001c 0x00000034
0x00000020 ShOff 0x00000020 0x000007cc
0x00000024 Flags 0x00000024 0x0000
0x00000028 EhSize 0x00000028 52
0x0000002a PhentSize 0x0000002a 32
0x0000002c PhNum 0x0000002c 8
0x0000002e ShentSize 0x0000002e 40
0x00000030 ShNum 0x00000030 30
0x00000032 ShStrndx 0x00000032 27
[Libs]
library
@ -1239,4 +1239,4 @@ CMDS=<<EOF
EOF
EXPECT=<<EOF
EOF
RUN
RUN