Move elf arm functions in librz/bin/format/elf/elf_arm.c

This commit is contained in:
Alexis Ehret 2021-08-05 12:48:29 +02:00
parent ca6323e6f8
commit 3b09213cde
9 changed files with 142 additions and 150 deletions

View file

@ -419,6 +419,7 @@ static bool init(ELFOBJ *bin, RzBinObjectLoadOptions *options) {
bin->notes = Elf_(rz_bin_elf_notes_new)(bin);
bin->symbols = Elf_(rz_bin_elf_symbols_new)(bin);
bin->bits = Elf_(rz_bin_elf_get_bits)(bin);
bin->imports = Elf_(rz_bin_elf_analyse_imports)(bin);
return true;

View file

@ -198,6 +198,16 @@ void Elf_(rz_bin_elf_free)(RZ_NONNULL ELFOBJ *bin);
ut64 Elf_(rz_bin_elf_p2v_new)(RZ_NONNULL ELFOBJ *bin, ut64 paddr);
ut64 Elf_(rz_bin_elf_v2p_new)(RZ_NONNULL ELFOBJ *bin, ut64 vaddr);
// elf_arm.c
#define rz_bin_elf_fix_arm_thumb_object_dispatch(object) \
Elf_(rz_bin_elf_fix_arm_thumb_object)(&object->paddr, &object->vaddr, &object->bits)
bool Elf_(rz_bin_elf_is_arm_binary_supporting_thumb)(RZ_NONNULL ELFOBJ *bin);
bool Elf_(rz_bin_elf_is_thumb_addr)(ut64 addr);
void Elf_(rz_bin_elf_fix_arm_thumb_addr)(ut64 *addr);
void Elf_(rz_bin_elf_fix_arm_thumb_object)(ut64 *paddr, ut64 *vaddr, int *bits);
void Elf_(rz_bin_elf_fix_arm_thumb_symbol)(RZ_NONNULL RzBinSymbol *symbol);
// elf_corefile.c
ut64 Elf_(rz_bin_elf_get_sp_val)(RZ_NONNULL ELFOBJ *bin);
@ -303,8 +313,8 @@ void Elf_(rz_bin_elf_strtab_free)(RzBinElfStrtab *ptr);
typedef bool (*RzBinElfSymbolFilter)(ELFOBJ *bin, Elf_(Sym) * entry, bool is_dynamic);
Elf_(Word) Elf_(rz_bin_elf_get_number_of_dynamic_symbols)(RZ_NONNULL ELFOBJ *bin);
RZ_OWN RzVector *Elf_(rz_bin_elf_compute_symbols)(ELFOBJ *bin, RzBinElfSymbolFilter filter);
RZ_BORROW RzBinElfSymbol *Elf_(rz_bin_elf_get_symbol)(RZ_NONNULL ELFOBJ *bin, ut32 ordinal);
RZ_OWN RzVector *Elf_(rz_bin_elf_compute_symbols)(ELFOBJ *bin, RzBinElfSymbolFilter filter);
RZ_OWN RzVector *Elf_(rz_bin_elf_symbols_new)(RZ_NONNULL ELFOBJ *bin);
bool Elf_(rz_bin_elf_has_symbols)(RZ_NONNULL ELFOBJ *bin);

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_arm.c"

View file

@ -0,0 +1,57 @@
// 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 bool start_a_sequence_of_instruction(RzBinSymbol *symbol) {
return strlen(symbol->name) > 3 && rz_str_startswith(symbol->name, "$a.");
}
static bool start_a_sequence_of_thumb_instruction(RzBinSymbol *symbol) {
return strlen(symbol->name) > 3 && rz_str_startswith(symbol->name, "$t.");
}
static bool start_a_sequence_of_data(RzBinSymbol *symbol) {
return strlen(symbol->name) > 3 && rz_str_startswith(symbol->name, "$d.");
}
bool Elf_(rz_bin_elf_is_arm_binary_supporting_thumb)(RZ_NONNULL ELFOBJ *bin) {
rz_return_val_if_fail(bin, false);
return bin->ehdr.e_machine == EM_ARM;
}
bool Elf_(rz_bin_elf_is_thumb_addr)(ut64 addr) {
return addr != UT64_MAX && addr & 1;
}
void Elf_(rz_bin_elf_fix_arm_thumb_addr)(ut64 *addr) {
rz_return_if_fail(Elf_(rz_bin_elf_is_thumb_addr(*addr)));
*addr -= 1;
}
void Elf_(rz_bin_elf_fix_arm_thumb_object)(RZ_NONNULL ut64 *paddr, RZ_NONNULL ut64 *vaddr, RZ_NONNULL int *bits) {
rz_return_if_fail(paddr && vaddr && bits);
*bits = 32;
if (Elf_(rz_bin_elf_is_thumb_addr)(*paddr)) {
Elf_(rz_bin_elf_fix_arm_thumb_addr)(paddr);
*bits = 16;
}
if (Elf_(rz_bin_elf_is_thumb_addr)(*vaddr)) {
Elf_(rz_bin_elf_fix_arm_thumb_addr)(vaddr);
*bits = 16;
}
}
void Elf_(rz_bin_elf_fix_arm_thumb_symbol)(RZ_NONNULL RzBinSymbol *symbol) {
rz_return_if_fail(symbol && symbol->name);
if (start_a_sequence_of_instruction(symbol)) {
symbol->bits = 32;
} else if (start_a_sequence_of_thumb_instruction(symbol) || !start_a_sequence_of_data(symbol)) {
rz_bin_elf_fix_arm_thumb_object_dispatch(symbol);
}
}

View file

@ -16,10 +16,6 @@
#define COMPUTE_PLTGOT_POSITION(rel, pltgot_addr, n_initial_unused_entries) \
((rel->vaddr - pltgot_addr - n_initial_unused_entries * sizeof(Elf_(Addr))) / sizeof(Elf_(Addr)))
static bool is_thumb_symbol(ut64 plt_addr) {
return plt_addr & 1;
}
static ut64 get_got_entry(ELFOBJ *bin, RzBinElfReloc *rel) {
Elf_(Addr) addr;
@ -218,7 +214,7 @@ static ut64 get_import_addr_arm(ELFOBJ *bin, RzBinElfReloc *rel) {
switch (rel->type) {
case RZ_ARM_JUMP_SLOT:
plt_addr += pos * 12 + 20;
if (is_thumb_symbol(plt_addr)) {
if (Elf_(rz_bin_elf_is_thumb_addr)(plt_addr)) {
plt_addr--;
}
return plt_addr;

View file

@ -463,7 +463,7 @@ static ut64 get_main_offset_arm_glibc_non_thumb(ELFOBJ *bin, ut64 entry, ut8 *bu
static ut64 get_main_offset_arm_glibc(ELFOBJ *bin, ut64 entry, ut8 *buf) {
// ARM Glibc
if (entry & 1) {
if (Elf_(rz_bin_elf_is_thumb_addr)(entry)) {
return get_main_offset_arm_glibc_thumb(bin, entry, buf);
} else {
return get_main_offset_arm_glibc_non_thumb(bin, entry, buf);
@ -574,7 +574,7 @@ static int get_bits_common(ELFOBJ *bin) {
static bool has_thumb_symbol(ELFOBJ *bin) {
RzBinElfSymbol *symbol;
rz_bin_elf_foreach_symbols(bin, symbol) {
if (symbol->paddr & 1) {
if (Elf_(rz_bin_elf_is_thumb_addr)(symbol->paddr) || Elf_(rz_bin_elf_is_thumb_addr)(symbol->vaddr)) {
return true;
}
}
@ -582,10 +582,6 @@ static bool has_thumb_symbol(ELFOBJ *bin) {
return false;
}
static bool arch_is_arm(ELFOBJ *bin) {
return bin->ehdr.e_machine == EM_ARM;
}
static int get_bits_mips_common(Elf_(Word) mips_type) {
for (size_t i = 0; i < RZ_ARRAY_SIZE(mips_bits_translation_table); i++) {
if (mips_type == mips_bits_translation_table[i].type) {
@ -1699,12 +1695,13 @@ int Elf_(rz_bin_elf_get_bits)(RZ_NONNULL ELFOBJ *bin) {
}
/* Hack for Thumb */
if (arch_is_arm(bin)) {
if (bin->ehdr.e_type != ET_EXEC && has_thumb_symbol(bin)) {
if (Elf_(rz_bin_elf_is_arm_binary_supporting_thumb)(bin)) {
if (!Elf_(rz_bin_elf_is_static)(bin) && has_thumb_symbol(bin)) {
return 16;
}
if (Elf_(rz_bin_elf_get_entry_offset)(bin) & 1) {
ut64 entry = Elf_(rz_bin_elf_get_entry_offset)(bin);
if (Elf_(rz_bin_elf_is_thumb_addr)(entry)) {
return 16;
}
}

View file

@ -312,9 +312,9 @@ static bool set_elf_symbol_name(ELFOBJ *bin, struct symbols_segment *segment, Rz
static bool convert_elf_symbol_entry(ELFOBJ *bin, struct symbols_segment *segment, RzBinElfSymbol *elf_symbol, Elf_(Sym) * symbol, size_t ordinal) {
RzBinElfSection *section = Elf_(rz_bin_elf_get_section)(bin, symbol->st_shndx);
elf_symbol->size = symbol->st_size;
elf_symbol->ordinal = ordinal;
elf_symbol->bind = symbol_bind_to_str(symbol);
elf_symbol->ordinal = ordinal;
elf_symbol->size = symbol->st_size;
if (Elf_(rz_bin_elf_is_relocatable)(bin) && section) {
elf_symbol->paddr = section->offset + symbol->st_value;
@ -457,40 +457,6 @@ static bool get_section_elf_symbols(ELFOBJ *bin, RzVector *result, RzBinElfSymbo
return true;
}
RZ_OWN RzVector *Elf_(rz_bin_elf_compute_symbols)(ELFOBJ *bin, RzBinElfSymbolFilter filter) {
RzVector *result = rz_vector_new(sizeof(RzBinElfSymbol), elf_symbol_fini, NULL);
if (!result) {
return NULL;
}
HtUU *set = ht_uu_new0();
if (!set) {
rz_vector_free(result);
return NULL;
}
if (!get_dynamic_elf_symbols(bin, result, filter, set)) {
rz_vector_free(result);
ht_uu_free(set);
return NULL;
}
if (!get_section_elf_symbols(bin, result, filter, set)) {
rz_vector_free(result);
ht_uu_free(set);
return NULL;
}
ht_uu_free(set);
if (!rz_vector_len(result)) {
rz_vector_free(result);
return NULL;
}
return result;
}
static bool filter_symbol(RZ_UNUSED ELFOBJ *bin, Elf_(Sym) * symbol, RZ_UNUSED bool is_dynamic) {
return symbol->st_shndx != SHT_NULL;
}
@ -538,9 +504,38 @@ RZ_BORROW RzBinElfSymbol *Elf_(rz_bin_elf_get_symbol)(RZ_NONNULL ELFOBJ *bin, ut
return NULL;
}
RZ_BORROW RzVector *Elf_(rz_bin_elf_get_symbols)(RZ_NONNULL ELFOBJ *bin) {
rz_return_val_if_fail(bin, NULL);
return bin->symbols;
RZ_OWN RzVector *Elf_(rz_bin_elf_compute_symbols)(ELFOBJ *bin, RzBinElfSymbolFilter filter) {
RzVector *result = rz_vector_new(sizeof(RzBinElfSymbol), elf_symbol_fini, NULL);
if (!result) {
return NULL;
}
HtUU *set = ht_uu_new0();
if (!set) {
rz_vector_free(result);
return NULL;
}
if (!get_dynamic_elf_symbols(bin, result, filter, set)) {
rz_vector_free(result);
ht_uu_free(set);
return NULL;
}
if (!get_section_elf_symbols(bin, result, filter, set)) {
rz_vector_free(result);
ht_uu_free(set);
return NULL;
}
ht_uu_free(set);
if (!rz_vector_len(result)) {
rz_vector_free(result);
return NULL;
}
return result;
}
RZ_OWN RzVector *Elf_(rz_bin_elf_symbols_new)(RZ_NONNULL ELFOBJ *bin) {

View file

@ -73,6 +73,8 @@ rz_bin_sources = [
'format/dmp/dmp64.c',
'format/elf/elf.c',
'format/elf/elf64.c',
'format/elf/elf_arm.c',
'format/elf/elf64_arm.c',
'format/elf/elf_corefile.c',
'format/elf/elf64_corefile.c',
'format/elf/elf_dynamic.c',

View file

@ -20,87 +20,24 @@ static RzBinInfo *info(RzBinFile *bf);
static void patch_relocs(RzBinFile *bf, struct Elf_(rz_bin_elf_obj_t) * bin);
static RzList *imports(RzBinFile *bf);
static void fix_thumb_symbol(RzBinSymbol *symbol) {
symbol->bits = 16;
if (symbol->vaddr & 1) {
symbol->vaddr--;
}
if (symbol->paddr & 1) {
symbol->paddr--;
}
}
static bool start_a_sequence_of_instruction(const char *name) {
return strlen(name) > 3 && rz_str_startswith(name, "$a.");
}
static bool start_a_sequence_of_thumb_instruction(const char *name) {
return strlen(name) > 3 && rz_str_startswith(name, "$t.");
}
static bool start_a_sequence_of_data(const char *name) {
return strlen(name) > 3 && rz_str_startswith(name, "$d.");
}
static void set_arm_basic_symbol_bits(ELFOBJ *bin, RzBinSymbol *symbol) {
int bin_bits = Elf_(rz_bin_elf_get_bits)(bin);
symbol->bits = bin_bits;
if (bin_bits != 64) {
symbol->bits = 32;
if (symbol->paddr != UT64_MAX) {
if (symbol->vaddr & 1) {
symbol->vaddr--;
symbol->bits = 16;
}
if (symbol->paddr & 1) {
symbol->paddr--;
symbol->bits = 16;
}
}
}
}
static void set_arm_symbol_bits(ELFOBJ *bin, RzBinSymbol *symbol) {
const char *name = symbol->name;
if (start_a_sequence_of_instruction(name)) {
symbol->bits = 32;
} else if (start_a_sequence_of_thumb_instruction(name)) {
fix_thumb_symbol(symbol);
} else if (!start_a_sequence_of_data(name)) {
set_arm_basic_symbol_bits(bin, symbol);
}
}
static void set_common_parameter(RzBinElfSymbol *elf_symbol, RzBinSymbol *symbol) {
symbol->paddr = elf_symbol->paddr;
symbol->vaddr = elf_symbol->vaddr;
symbol->name = rz_str_new(elf_symbol->name);
symbol->forwarder = "NONE";
symbol->bind = elf_symbol->bind;
symbol->type = elf_symbol->type;
symbol->size = elf_symbol->size;
symbol->ordinal = elf_symbol->ordinal;
}
static bool is_arm_symbol(ELFOBJ *bin, RzBinElfSymbol *symbol) {
return bin->ehdr.e_machine == EM_ARM && symbol->name;
}
static RzBinSymbol *convert_symbol(ELFOBJ *bin, RzBinElfSymbol *elf_symbol) {
RzBinSymbol *result = RZ_NEW0(RzBinSymbol);
if (!result) {
return NULL;
}
set_common_parameter(elf_symbol, result);
result->paddr = elf_symbol->paddr;
result->vaddr = elf_symbol->vaddr;
result->name = rz_str_new(elf_symbol->name);
result->forwarder = "NONE";
result->bind = elf_symbol->bind;
result->type = elf_symbol->type;
result->size = elf_symbol->size;
result->ordinal = elf_symbol->ordinal;
result->bits = bin->bits;
if (is_arm_symbol(bin, elf_symbol)) {
set_arm_symbol_bits(bin, result);
if (Elf_(rz_bin_elf_is_arm_binary_supporting_thumb)(bin)) {
Elf_(rz_bin_elf_fix_arm_thumb_symbol)(result);
}
return result;
@ -235,16 +172,14 @@ static RzBinAddr *binsym(RzBinFile *bf, RzBinSpecialSymbol sym) {
}
if (addr && addr != UT64_MAX && (ret = RZ_NEW0(RzBinAddr))) {
struct Elf_(rz_bin_elf_obj_t) *bin = bf->o->bin_obj;
bool is_arm = bin->ehdr.e_machine == EM_ARM;
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 (is_arm && addr & 1) {
ret->bits = 16;
ret->vaddr--;
ret->paddr--;
if (Elf_(rz_bin_elf_is_arm_binary_supporting_thumb)(bin)) {
rz_bin_elf_fix_arm_thumb_object_dispatch(ret);
}
}
return ret;
@ -774,13 +709,14 @@ static void patch_relocs(RzBinFile *bf, ELFOBJ *bin) {
plt_entry_addr = sym_addr;
}
} else {
RzBinSymbol *symbol = get_symbol(bin, reloc->sym);
RzBinElfSymbol *symbol = Elf_(rz_bin_elf_get_symbol)(bin, reloc->sym);
if (symbol) {
sym_addr = symbol->vaddr;
if (Elf_(rz_bin_elf_is_arm_binary_supporting_thumb)(bin) && Elf_(rz_bin_elf_is_thumb_addr)(sym_addr)) {
Elf_(rz_bin_elf_fix_arm_thumb_addr)(&sym_addr);
}
plt_entry_addr = sym_addr;
}
rz_bin_symbol_free(symbol);
}
}
// TODO relocation types B, L
@ -1037,7 +973,7 @@ static RzBinAddr *newEntry(RzBinFile *bf, ut64 hpaddr, ut64 hvaddr, ut64 vaddr,
ptr->bits = bits;
ptr->type = type;
//realign due to thumb
if (bits == 16 && ptr->vaddr & 1) {
if (bits == 16 && Elf_(rz_bin_elf_is_thumb_addr)(ptr->vaddr)) {
ptr->paddr--;
ptr->vaddr--;
}
@ -1108,6 +1044,7 @@ static RzList *entries(RzBinFile *bf) {
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);
@ -1123,20 +1060,11 @@ static RzList *entries(RzBinFile *bf) {
}
}
}
if (obj->ehdr.e_machine == EM_ARM) {
int bin_bits = Elf_(rz_bin_elf_get_bits)(obj);
if (bin_bits != 64) {
ptr->bits = 32;
if (ptr->vaddr & 1) {
ptr->vaddr--;
ptr->bits = 16;
}
if (ptr->paddr & 1) {
ptr->paddr--;
ptr->bits = 16;
}
}
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);
}