Refactor elf plugin interface (#1728)
* get_sdb * check_buffer * load_buffer * baddr * boffset * binsym * entries * headers * create * fields
This commit is contained in:
parent
d5f1aea595
commit
01b6e60775
14 changed files with 696 additions and 864 deletions
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
6
librz/bin/format/elf/elf64_ehdr.c
Normal file
6
librz/bin/format/elf/elf64_ehdr.c
Normal 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"
|
||||
219
librz/bin/format/elf/elf_ehdr.c
Normal file
219
librz/bin/format/elf/elf_ehdr.c
Normal 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));
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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',
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in a new issue