More ELF cleanups on the symbol allocation logic ##bin

This commit is contained in:
pancake 2023-03-27 15:20:42 +02:00 committed by GitHub
parent 8c73bc6d89
commit d7e70604ba
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 71 additions and 121 deletions

View File

@ -3613,40 +3613,6 @@ RBinSymbol *Elf_(_r_bin_elf_convert_symbol)(struct Elf_(r_bin_elf_obj_t) *bin,
return ptr; return ptr;
} }
static ut32 hashRBinElfSymbol(const void *obj) {
const RBinElfSymbol *symbol = (const RBinElfSymbol *)obj;
if (!symbol || R_STR_ISEMPTY (symbol->name)) {
return 0;
}
int hash = sdb_hash (symbol->name);
if (R_STR_ISNOTEMPTY (symbol->type)) {
hash ^= sdb_hash (symbol->type);
}
hash ^= (symbol->offset >> 32);
hash ^= (symbol->offset & UT32_MAX);
return hash;
}
static int cmp_RBinElfSymbol(const RBinElfSymbol *a, const RBinElfSymbol *b) {
if (a->offset != b->offset) {
return 1;
}
#if 0
// name is an array not a pointer
if (!a->name || !b->name) {
return 1;
}
#endif
int result = strcmp (a->name, b->name);
if (result != 0) {
return result;
}
if (!a->type || !b->type) {
return 1;
}
return strcmp (a->type, b->type);
}
static RBinElfSymbol* parse_gnu_debugdata(ELFOBJ *bin, size_t *ret_size) { static RBinElfSymbol* parse_gnu_debugdata(ELFOBJ *bin, size_t *ret_size) {
if (ret_size) { if (ret_size) {
*ret_size = 0; *ret_size = 0;
@ -3658,7 +3624,7 @@ static RBinElfSymbol* parse_gnu_debugdata(ELFOBJ *bin, size_t *ret_size) {
ut64 addr = bin->g_sections[i].offset; ut64 addr = bin->g_sections[i].offset;
ut64 size = bin->g_sections[i].size; ut64 size = bin->g_sections[i].size;
if (size < 10) { if (size < 10) {
return false; return NULL;
} }
ut8 *data = malloc (size + 1); ut8 *data = malloc (size + 1);
if (!data) { if (!data) {
@ -3714,27 +3680,19 @@ static bool section_matters(ELFOBJ *bin, int i, int type, ut32 shdr_size) {
// TODO: return RList<RBinSymbol*> .. or run a callback with that symbol constructed, so we don't have to do it twice // TODO: return RList<RBinSymbol*> .. or run a callback with that symbol constructed, so we don't have to do it twice
static RBinElfSymbol* Elf_(_r_bin_elf_get_symbols_imports)(ELFOBJ *bin, int type) { static RBinElfSymbol* Elf_(_r_bin_elf_get_symbols_imports)(ELFOBJ *bin, int type) {
r_return_val_if_fail (bin, NULL); r_return_val_if_fail (bin, NULL);
int tsize, nsym, ret_ctr = 0, i, j, k, newsize; size_t ret_ctr = 0; // amount of symbols stored in ret
size_t ret_size = 0; // size of ret allocation
int tsize, nsym, i, j, k;
RBinElfSymbol *ret = NULL; RBinElfSymbol *ret = NULL;
RBinElfSymbol *import_ret = NULL; RBinElfSymbol *import_ret = NULL;
RBinSymbol *import_sym_ptr = NULL; RBinSymbol *import_sym_ptr = NULL;
size_t ret_size = 0, import_ret_ctr = 0; size_t import_ret_ctr = 0;
Elf_(Sym) *sym = NULL; Elf_(Sym) *sym = NULL;
ut8 s[sizeof (Elf_(Sym))] = {0}; ut8 s[sizeof (Elf_(Sym))] = {0};
ut32 shdr_size = 0; ut32 shdr_size = 0;
ut64 toffset; ut64 toffset;
ut32 size = 0; ut32 size = 0;
char *strtab = NULL; char *strtab = NULL;
HtPP *symbol_map = NULL;
HtPPOptions symbol_map_options = {
.cmp = (HtPPListComparator)cmp_RBinElfSymbol,
.hashfn = hashRBinElfSymbol,
.dupkey = NULL,
.calcsizeK = NULL,
.calcsizeV = NULL,
.freefn = NULL,
.elem_size = sizeof (HtPPKv),
};
if (!bin->shdr || !bin->ehdr.e_shnum || bin->ehdr.e_shnum == 0xffff) { if (!bin->shdr || !bin->ehdr.e_shnum || bin->ehdr.e_shnum == 0xffff) {
R_LOG_DEBUG ("invalid section header value"); R_LOG_DEBUG ("invalid section header value");
@ -3749,46 +3707,40 @@ static RBinElfSymbol* Elf_(_r_bin_elf_get_symbols_imports)(ELFOBJ *bin, int type
return NULL; return NULL;
} }
// ret_size = amount of dbgsymbols in the array (not size of the array) // ret_size = amount of dbgsymbols in the array (not size of the array)
RBinElfSymbol *dbgsyms = parse_gnu_debugdata (bin, &ret_size); ret = parse_gnu_debugdata (bin, &ret_ctr);
if (dbgsyms) { ret_size = ret_ctr * sizeof (RBinElfSymbol);
ret = dbgsyms; int ret_last = ret_ctr;
ret_ctr = ret_size;
} else {
ret_ctr = 0;
ret_size = 0;
}
for (i = 0; i < bin->ehdr.e_shnum; i++) { for (i = 0; i < bin->ehdr.e_shnum; i++) {
if (!section_matters (bin, i, type, shdr_size)) { if (!section_matters (bin, i, type, shdr_size)) {
continue; continue;
} }
// process symbols in this section // process symbols in this section
Elf_(Shdr) *strtab_section = &bin->shdr[bin->shdr[i].sh_link]; Elf_(Shdr) *strtab_section = &bin->shdr[bin->shdr[i].sh_link];
if (strtab_section->sh_size > ST32_MAX || strtab_section->sh_size+8 > bin->size) { if (strtab_section->sh_size > ST32_MAX || strtab_section->sh_size + 8 > bin->size) {
R_LOG_ERROR ("size (syms strtab)"); R_LOG_ERROR ("size (syms strtab)");
free (ret); free (ret);
free (strtab); free (strtab);
return NULL; return NULL;
} }
if (!strtab) { if (!strtab) {
if (strtab_section->sh_offset > bin->size || strtab_section->sh_offset + strtab_section->sh_size > bin->size) {
goto beach;
}
if (!(strtab = (char *)calloc (1, 8 + strtab_section->sh_size))) { if (!(strtab = (char *)calloc (1, 8 + strtab_section->sh_size))) {
R_LOG_ERROR ("malloc (syms strtab)"); R_LOG_ERROR ("malloc (syms strtab)");
goto beach; goto beach;
} }
if (strtab_section->sh_offset > bin->size || if (r_buf_read_at (bin->b, strtab_section->sh_offset, (ut8*)strtab, strtab_section->sh_size) == -1) {
strtab_section->sh_offset + strtab_section->sh_size > bin->size) {
goto beach;
}
if (r_buf_read_at (bin->b, strtab_section->sh_offset,
(ut8*)strtab, strtab_section->sh_size) == -1) {
R_LOG_ERROR ("read (syms strtab)"); R_LOG_ERROR ("read (syms strtab)");
goto beach; goto beach;
} }
} }
{ // bounch check
newsize = 1 + bin->shdr[i].sh_size; int newsize = 1 + bin->shdr[i].sh_size;
if (newsize < 0 || newsize > bin->size) { if (newsize < 0 || newsize > bin->size) {
R_LOG_ERROR ("invalid shdr %d size", i); R_LOG_ERROR ("invalid shdr %d size", i);
goto beach; goto beach;
}
} }
nsym = (int)(bin->shdr[i].sh_size / sizeof (Elf_(Sym))); nsym = (int)(bin->shdr[i].sh_size / sizeof (Elf_(Sym)));
if (nsym < 1) { if (nsym < 1) {
@ -3848,23 +3800,26 @@ static RBinElfSymbol* Elf_(_r_bin_elf_get_symbols_imports)(ELFOBJ *bin, int type
sym[j].st_shndx = READ16 (s, k); sym[j].st_shndx = READ16 (s, k);
#endif #endif
} }
void *rett = realloc (ret, (ret_size + nsym) * sizeof (RBinElfSymbol)); int increment = (1 + nsym) * sizeof (RBinElfSymbol);
void *rett = realloc (ret, increment + ret_size);
if (!rett) { if (!rett) {
R_LOG_ERROR ("Cannot allocate %d symbols", (int)(nsym + ret_size)); R_LOG_ERROR ("Cannot allocate %d symbols", (int)(nsym + increment));
goto beach; goto beach;
} }
ret = rett; ret = rett;
memset (((ut8*)ret) + (ret_size * sizeof (RBinElfSymbol)), 0, ret_last = ret_ctr + nsym;
nsym * sizeof (RBinElfSymbol)); #if 0
size_t prev_ret_size = ret_size; memset (((ut8*)ret) + ret_size, 0, increment * sizeof (RBinElfSymbol));
ret_size += nsym; #else
symbol_map = ht_pp_new_opt (&symbol_map_options); int mi;
for (k = 0; k < prev_ret_size; k++) { for (mi = ret_ctr; mi < ret_last; mi++) {
if (ret[k].name[0]) { memset (&ret[mi], 0, sizeof (RBinElfSymbol));
ht_pp_insert (symbol_map, ret + k, ret + k); // ret[mi].name[0] = 0;
}
} }
for (k = 1; k < nsym; k++) { #endif
ret_size += increment;
for (k = 1; k < nsym; k++, ret_ctr++) {
RBinElfSymbol *es = &ret[ret_ctr];
bool is_sht_null = false; bool is_sht_null = false;
bool is_vaddr = false; bool is_vaddr = false;
bool is_imported = false; bool is_imported = false;
@ -3883,16 +3838,16 @@ static RBinElfSymbol* Elf_(_r_bin_elf_get_symbols_imports)(ELFOBJ *bin, int type
} }
if (is_bin_etrel (bin)) { if (is_bin_etrel (bin)) {
if (sym[k].st_shndx < bin->ehdr.e_shnum) { if (sym[k].st_shndx < bin->ehdr.e_shnum) {
ret[ret_ctr].offset = sym[k].st_value + bin->shdr[sym[k].st_shndx].sh_offset; es->offset = sym[k].st_value + bin->shdr[sym[k].st_shndx].sh_offset;
} }
} else { } else {
ret[ret_ctr].offset = Elf_(r_bin_elf_v2p_new) (bin, toffset); es->offset = Elf_(r_bin_elf_v2p_new) (bin, toffset);
if (ret[ret_ctr].offset == UT64_MAX) { if (es->offset == UT64_MAX) {
ret[ret_ctr].offset = toffset; es->offset = toffset;
is_vaddr = true; is_vaddr = true;
} }
} }
ret[ret_ctr].size = tsize; es->size = tsize;
if (sym[k].st_name + 1 > strtab_section->sh_size) { if (sym[k].st_name + 1 > strtab_section->sh_size) {
R_LOG_DEBUG ("index out of strtab range (%"PFMT64d" / %"PFMT64d")", R_LOG_DEBUG ("index out of strtab range (%"PFMT64d" / %"PFMT64d")",
(ut64)sym[k].st_name, (ut64)strtab_section->sh_size); (ut64)sym[k].st_name, (ut64)strtab_section->sh_size);
@ -3902,36 +3857,29 @@ static RBinElfSymbol* Elf_(_r_bin_elf_get_symbols_imports)(ELFOBJ *bin, int type
int st_name = sym[k].st_name; int st_name = sym[k].st_name;
int maxsize = R_MIN (r_buf_size (bin->b), strtab_section->sh_size); int maxsize = R_MIN (r_buf_size (bin->b), strtab_section->sh_size);
if (is_section_local_sym (bin, &sym[k])) { if (is_section_local_sym (bin, &sym[k])) {
const char *shname = &bin->shstrtab[bin->shdr[sym[k].st_shndx].sh_name]; const size_t sym_section = sym[k].st_shndx;
r_str_ncpy (ret[ret_ctr].name, shname, ELF_STRING_LENGTH - 1); const char *shname = &bin->shstrtab[bin->shdr[sym_section].sh_name];
r_str_ncpy (es->name, shname, ELF_STRING_LENGTH - 1);
} else if (st_name <= 0 || st_name >= maxsize) { } else if (st_name <= 0 || st_name >= maxsize) {
ret[ret_ctr].name[0] = 0; es->name[0] = 0;
} else { } else {
r_str_ncpy (ret[ret_ctr].name, &strtab[st_name], ELF_STRING_LENGTH - 1); r_str_ncpy (es->name, &strtab[st_name], ELF_STRING_LENGTH - 1);
ret[ret_ctr].type = type2str (bin, &ret[ret_ctr], &sym[k]); es->type = type2str (bin, es, &sym[k]);
if (ht_pp_find (symbol_map, &ret[ret_ctr], NULL)) {
memset (ret + ret_ctr, 0, sizeof (RBinElfSymbol));
continue;
}
} }
} }
ret[ret_ctr].ordinal = k; es->ordinal = k;
ret[ret_ctr].name[ELF_STRING_LENGTH - 1] = '\0'; es->name[ELF_STRING_LENGTH - 1] = '\0';
fill_symbol_bind_and_type (bin, &ret[ret_ctr], &sym[k]); fill_symbol_bind_and_type (bin, es, &sym[k]);
ret[ret_ctr].is_sht_null = is_sht_null; es->is_sht_null = is_sht_null;
ret[ret_ctr].is_vaddr = is_vaddr; es->is_vaddr = is_vaddr;
ret[ret_ctr].last = 0; es->last = 0;
ret[ret_ctr].is_imported = is_imported; es->is_imported = is_imported;
ret_ctr++;
if (type == R_BIN_ELF_IMPORT_SYMBOLS && is_imported) { if (type == R_BIN_ELF_IMPORT_SYMBOLS && is_imported) {
import_ret_ctr++; import_ret_ctr++;
} }
} }
R_FREE (strtab); R_FREE (strtab);
R_FREE (sym); R_FREE (sym);
ht_pp_free (symbol_map);
symbol_map = NULL;
if (type == R_BIN_ELF_IMPORT_SYMBOLS) { if (type == R_BIN_ELF_IMPORT_SYMBOLS) {
break; break;
} }
@ -3939,9 +3887,10 @@ static RBinElfSymbol* Elf_(_r_bin_elf_get_symbols_imports)(ELFOBJ *bin, int type
if (!ret) { if (!ret) {
return Elf_(get_phdr_symbols) (bin, type); return Elf_(get_phdr_symbols) (bin, type);
} }
ret[ret_ctr].last = 1; // ugly dirty hack :D if (ret_ctr > 0) {
int max = -1; RBinElfSymbol *es = &ret[ret_ctr];
RBinElfSymbol *aux = NULL; es->last = 1; // ugly dirty hack :D
}
nsym = Elf_(fix_symbols) (bin, ret_ctr, type, &ret); nsym = Elf_(fix_symbols) (bin, ret_ctr, type, &ret);
if (nsym == -1) { if (nsym == -1) {
goto beach; goto beach;
@ -3952,7 +3901,8 @@ static RBinElfSymbol* Elf_(_r_bin_elf_get_symbols_imports)(ELFOBJ *bin, int type
r_warn_if_fail (nsym >= ret_ctr); r_warn_if_fail (nsym >= ret_ctr);
import_ret_ctr += nsym - ret_ctr; import_ret_ctr += nsym - ret_ctr;
aux = ret; int max = -1;
RBinElfSymbol *aux = ret;
while (!aux->last) { while (!aux->last) {
if ((int)aux->ordinal > max) { if ((int)aux->ordinal > max) {
max = aux->ordinal; max = aux->ordinal;
@ -3992,7 +3942,6 @@ beach:
free (ret); free (ret);
free (sym); free (sym);
free (strtab); free (strtab);
ht_pp_free (symbol_map);
return NULL; return NULL;
} }

View File

@ -1,17 +1,13 @@
/* radare - LGPL - Copyright 2009-2021 - pancake */ /* radare - LGPL - Copyright 2009-2023 - pancake */
#include <r_cons.h> #include <r_cons.h>
#include <string.h>
#if R2__UNIX__
#include <errno.h>
#endif
#define I r_cons_singleton () #define I r_cons_singleton ()
// TODO: Support binary, use RBuffer and remove globals // TODO: Support binary, use RBuffer and remove globals
static char *readbuffer = NULL; static R_TH_LOCAL char *readbuffer = NULL;
static int readbuffer_length = 0; static R_TH_LOCAL int readbuffer_length = 0;
static bool bufactive = true; static R_TH_LOCAL bool bufactive = true;
#if 0 #if 0
//R2__UNIX__ //R2__UNIX__
@ -635,6 +631,7 @@ R_API int r_cons_readchar(void) {
// pselect (that is what pselect is for). // pselect (that is what pselect is for).
fd_set readfds; fd_set readfds;
sigset_t sigmask; sigset_t sigmask;
sigemptyset (&sigmask);
FD_ZERO (&readfds); FD_ZERO (&readfds);
FD_SET (STDIN_FILENO, &readfds); FD_SET (STDIN_FILENO, &readfds);
r_signal_sigmask (0, NULL, &sigmask); r_signal_sigmask (0, NULL, &sigmask);

View File

@ -3168,6 +3168,7 @@ nth paddr vaddr bind type size lib name
52 0x00000494 0x08048494 GLOBAL FUNC 0 _fini 52 0x00000494 0x08048494 GLOBAL FUNC 0 _fini
53 0x000006ac 0x080496ac GLOBAL NOTYPE 0 __data_start 53 0x000006ac 0x080496ac GLOBAL NOTYPE 0 __data_start
56 0x000006b0 0x080496b0 GLOBAL OBJ 0 __dso_handle 56 0x000006b0 0x080496b0 GLOBAL OBJ 0 __dso_handle
57 0x000004ac 0x080484ac GLOBAL OBJ 4 _IO_stdin_used
59 0x00000420 0x08048420 GLOBAL FUNC 97 __libc_csu_init 59 0x00000420 0x08048420 GLOBAL FUNC 97 __libc_csu_init
60 ---------- 0x080496b8 GLOBAL NOTYPE 0 _end 60 ---------- 0x080496b8 GLOBAL NOTYPE 0 _end
61 0x00000300 0x08048300 GLOBAL FUNC 0 _start 61 0x00000300 0x08048300 GLOBAL FUNC 0 _start

View File

@ -594,12 +594,12 @@ is~?
EOF EOF
EXPECT=<<EOF EXPECT=<<EOF
133 133
134 139
-- --
267 272
-- --
133 133
134 139
EOF EOF
RUN RUN

View File

@ -111,6 +111,8 @@ EXPECT=<<EOF
965 0x000c9420 0x000c9420 GLOBAL FUNC 12 __getpid 965 0x000c9420 0x000c9420 GLOBAL FUNC 12 __getpid
3577 0x000c9420 0x000c9420 LOCAL FUNC 12 __GI___getpid 3577 0x000c9420 0x000c9420 LOCAL FUNC 12 __GI___getpid
3807 0x000c9420 0x000c9420 LOCAL FUNC 12 __GI_getpid 3807 0x000c9420 0x000c9420 LOCAL FUNC 12 __GI_getpid
6267 0x000c9420 0x000c9420 WEAK FUNC 12 getpid
8102 0x000c9420 0x000c9420 GLOBAL FUNC 12 __getpid
0x000c9420 12 sym.getpid 0x000c9420 12 sym.getpid
0x000c9420 12 sym.__getpid 0x000c9420 12 sym.__getpid
0x000c9420 12 sym.__GI___getpid 0x000c9420 12 sym.__GI___getpid

View File

@ -111,7 +111,7 @@ NAME=rabin2 -s file elf
FILE=bins/elf/analysis/x86-helloworld-gcc FILE=bins/elf/analysis/x86-helloworld-gcc
CMDS=!!rabin2 -s ${R2_FILE}~? CMDS=!!rabin2 -s ${R2_FILE}~?
EXPECT=<<EOF EXPECT=<<EOF
68 69
EOF EOF
RUN RUN
@ -625,6 +625,7 @@ nth paddr vaddr bind type size lib name
52 0x00000494 0x08048494 GLOBAL FUNC 0 _fini 52 0x00000494 0x08048494 GLOBAL FUNC 0 _fini
53 0x000006ac 0x080496ac GLOBAL NOTYPE 0 __data_start 53 0x000006ac 0x080496ac GLOBAL NOTYPE 0 __data_start
56 0x000006b0 0x080496b0 GLOBAL OBJ 0 __dso_handle 56 0x000006b0 0x080496b0 GLOBAL OBJ 0 __dso_handle
57 0x000004ac 0x080484ac GLOBAL OBJ 4 _IO_stdin_used
59 0x00000420 0x08048420 GLOBAL FUNC 97 __libc_csu_init 59 0x00000420 0x08048420 GLOBAL FUNC 97 __libc_csu_init
60 ---------- 0x080496b8 GLOBAL NOTYPE 0 _end 60 ---------- 0x080496b8 GLOBAL NOTYPE 0 _end
61 0x00000300 0x08048300 GLOBAL FUNC 0 _start 61 0x00000300 0x08048300 GLOBAL FUNC 0 _start