Skip to content

Commit

Permalink
Filter out special symbols in ELF (radareorg#13173)
Browse files Browse the repository at this point in the history
* Filter out special symbols in ELF

* No need to add the special case '\0'

* Keep special symbols, but do not process them

* Refactoring

* Make sure s->type is not NULL

* Do not print special symbols in rad mode

* Avoid double check

* Fix PR's comments
  • Loading branch information
ret2libc authored Mar 3, 2019
1 parent 7fdf247 commit 33c678f
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 67 deletions.
68 changes: 48 additions & 20 deletions libr/bin/format/elf/elf.c
Original file line number Diff line number Diff line change
Expand Up @@ -2817,8 +2817,33 @@ RBinElfSection* Elf_(r_bin_elf_get_sections)(ELFOBJ *bin) {
return ret;
}

static bool is_special_arm_symbol(ELFOBJ *bin, Elf_(Sym) *sym, const char *name) {
if (name[0] != '$') {
return false;
}
switch (name[1]) {
case 'a':
case 't':
case 'd':
return name[2] == '\0' && ELF_ST_TYPE (sym->st_info) == STT_NOTYPE &&
ELF_ST_BIND (sym->st_info) == STB_LOCAL &&
ELF_ST_VISIBILITY (sym->st_info) == STV_DEFAULT;
default:
return false;
}
}

static bool is_special_symbol(ELFOBJ *bin, Elf_(Sym) *sym, const char *name) {
switch (bin->ehdr.e_machine) {
case EM_ARM:
return is_special_arm_symbol (bin, sym, name);
default:
return false;
}
}

static const char *bind2str(Elf_(Sym) *sym) {
switch (ELF_ST_BIND(sym->st_info)) {
switch (ELF_ST_BIND (sym->st_info)) {
case STB_LOCAL: return R_BIN_BIND_LOCAL_STR;
case STB_GLOBAL: return R_BIN_BIND_GLOBAL_STR;
case STB_WEAK: return R_BIN_BIND_WEAK_STR;
Expand All @@ -2831,27 +2856,30 @@ static const char *bind2str(Elf_(Sym) *sym) {
}
}

static const char *type2str(Elf_(Sym) *sym) {
static const char *type2str(ELFOBJ *bin, struct r_bin_elf_symbol_t *ret, Elf_(Sym) *sym) {
if (bin && ret && is_special_symbol (bin, sym, ret->name)) {
return R_BIN_TYPE_SPECIAL_SYM_STR;
}
switch (ELF_ST_TYPE (sym->st_info)) {
case STT_NOTYPE: return R_BIN_TYPE_NOTYPE_STR;
case STT_OBJECT: return R_BIN_TYPE_OBJECT_STR;
case STT_FUNC: return R_BIN_TYPE_FUNC_STR;
case STT_NOTYPE: return R_BIN_TYPE_NOTYPE_STR;
case STT_OBJECT: return R_BIN_TYPE_OBJECT_STR;
case STT_FUNC: return R_BIN_TYPE_FUNC_STR;
case STT_SECTION: return R_BIN_TYPE_SECTION_STR;
case STT_FILE: return R_BIN_TYPE_FILE_STR;
case STT_COMMON: return R_BIN_TYPE_COMMON_STR;
case STT_TLS: return R_BIN_TYPE_TLS_STR;
case STT_NUM: return R_BIN_TYPE_NUM_STR;
case STT_LOOS: return R_BIN_TYPE_LOOS_STR;
case STT_HIOS: return R_BIN_TYPE_HIOS_STR;
case STT_LOPROC: return R_BIN_TYPE_LOPROC_STR;
case STT_HIPROC: return R_BIN_TYPE_HIPROC_STR;
default: return R_BIN_TYPE_UNKNOWN_STR;
case STT_FILE: return R_BIN_TYPE_FILE_STR;
case STT_COMMON: return R_BIN_TYPE_COMMON_STR;
case STT_TLS: return R_BIN_TYPE_TLS_STR;
case STT_NUM: return R_BIN_TYPE_NUM_STR;
case STT_LOOS: return R_BIN_TYPE_LOOS_STR;
case STT_HIOS: return R_BIN_TYPE_HIOS_STR;
case STT_LOPROC: return R_BIN_TYPE_LOPROC_STR;
case STT_HIPROC: return R_BIN_TYPE_HIPROC_STR;
default: return R_BIN_TYPE_UNKNOWN_STR;
}
}

static void fill_symbol_bind_and_type (struct r_bin_elf_symbol_t *ret, Elf_(Sym) *sym) {
static void fill_symbol_bind_and_type(ELFOBJ *bin, struct r_bin_elf_symbol_t *ret, Elf_(Sym) *sym) {
ret->bind = bind2str (sym);
ret->type = type2str (sym);
ret->type = type2str (bin, ret, sym);
}

static RBinElfSymbol* get_symbols_from_phdr(ELFOBJ *bin, int type) {
Expand Down Expand Up @@ -2966,7 +2994,7 @@ static RBinElfSymbol* get_symbols_from_phdr(ELFOBJ *bin, int type) {
// since we don't know the size of the sym table in this case,
// let's stop at the first invalid entry
if (!strcmp (bind2str (&sym[i]), R_BIN_BIND_UNKNOWN_STR) ||
!strcmp (type2str (&sym[i]), R_BIN_TYPE_UNKNOWN_STR)) {
!strcmp (type2str (NULL, NULL, &sym[i]), R_BIN_TYPE_UNKNOWN_STR)) {
goto done;
}
tmp_offset = Elf_(r_bin_elf_v2p_new) (bin, toffset);
Expand Down Expand Up @@ -2999,7 +3027,7 @@ static RBinElfSymbol* get_symbols_from_phdr(ELFOBJ *bin, int type) {
ret[ret_ctr].ordinal = i;
ret[ret_ctr].in_shdr = false;
ret[ret_ctr].name[ELF_STRING_LENGTH - 2] = '\0';
fill_symbol_bind_and_type (&ret[ret_ctr], &sym[i]);
fill_symbol_bind_and_type (bin, &ret[ret_ctr], &sym[i]);
ret[ret_ctr].is_sht_null = is_sht_null;
ret[ret_ctr].is_vaddr = is_vaddr;
ret[ret_ctr].last = 0;
Expand Down Expand Up @@ -3380,7 +3408,7 @@ static RBinElfSymbol* Elf_(_r_bin_elf_get_symbols_imports)(ELFOBJ *bin, int type
while (!ret[++j].last && j < prev_ret_size) {
if (ret[j].offset == ret[ret_ctr].offset &&
strcmp (ret[j].name, "") != 0 && strcmp (ret[j].name, &strtab[st_name]) == 0
&& strcmp (ret[j].type, type2str (&sym[k])) == 0) {
&& strcmp (ret[j].type, type2str (NULL, NULL, &sym[k])) == 0) {
found = true;
break;
}
Expand All @@ -3395,7 +3423,7 @@ static RBinElfSymbol* Elf_(_r_bin_elf_get_symbols_imports)(ELFOBJ *bin, int type
}
ret[ret_ctr].ordinal = k;
ret[ret_ctr].name[ELF_STRING_LENGTH - 2] = '\0';
fill_symbol_bind_and_type (&ret[ret_ctr], &sym[k]);
fill_symbol_bind_and_type (bin, &ret[ret_ctr], &sym[k]);
ret[ret_ctr].is_sht_null = is_sht_null;
ret[ret_ctr].is_vaddr = is_vaddr;
ret[ret_ctr].last = 0;
Expand Down
103 changes: 56 additions & 47 deletions libr/core/cbin.c
Original file line number Diff line number Diff line change
Expand Up @@ -1408,6 +1408,10 @@ static bool is_section_symbol(RBinSymbol *s) {
return (s->type && !strcmp (s->type, R_BIN_TYPE_SECTION_STR));
}

static bool is_special_symbol(RBinSymbol *s) {
return s->type && !strcmp (s->type, R_BIN_TYPE_SPECIAL_SYM_STR);
}

static bool is_section_reloc(RBinReloc *r) {
return is_section_symbol (r->symbol);
}
Expand Down Expand Up @@ -1946,10 +1950,11 @@ static int bin_symbols(RCore *r, int mode, ut64 laddr, int va, ut64 at, const ch
}
snInit (r, &sn, symbol, lang);

if (IS_MODE_SET (mode) && (is_section_symbol (symbol) || is_file_symbol (symbol))) {
if (IS_MODE_SET (mode) && (is_section_symbol (symbol) || is_file_symbol (symbol) || is_special_symbol (symbol))) {
/*
* Skip section symbols because they will have their own flag.
* Skip also file symbols because not useful for now.
* Skip special symbols we do not want to flag them, as they are better used as analysis hints.
*/
} else if (IS_MODE_SET (mode)) {
if (is_arm && info->bits < 33) { // 16 or 32
Expand Down Expand Up @@ -2049,61 +2054,65 @@ static int bin_symbols(RCore *r, int mode, ut64 laddr, int va, ut64 at, const ch
const char *name = sn.demname? sn.demname: r_symbol_name;
r_cons_printf ("%s\n", name);
} else if (IS_MODE_RAD (mode)) {
RBinFile *binfile;
RBinPlugin *plugin;
char *name = strdup (sn.demname? sn.demname: r_symbol_name);
r_name_filter (name, -1);
if (!strncmp (name, "imp.", 4)) {
if (lastfs != 'i') {
r_cons_printf ("fs imports\n");
}
lastfs = 'i';
} else {
if (lastfs != 's') {
r_cons_printf ("fs %s\n",
exponly? "exports": "symbols");
}
lastfs = 's';
}
if (r->bin->prefix) {
if (symbol->dup_count) {
r_cons_printf ("f %s.sym.%s_%d %u 0x%08"PFMT64x"\n",
r->bin->prefix, name, symbol->dup_count, symbol->size, addr);
/* Skip special symbols because we do not flag them and
* they shouldn't be printed in the rad format either */
if (!is_special_symbol (symbol)) {
RBinFile *binfile;
RBinPlugin *plugin;
char *name = strdup (sn.demname? sn.demname: r_symbol_name);
r_name_filter (name, -1);
if (!strncmp (name, "imp.", 4)) {
if (lastfs != 'i') {
r_cons_printf ("fs imports\n");
}
lastfs = 'i';
} else {
r_cons_printf ("f %s.sym.%s %u 0x%08"PFMT64x"\n",
r->bin->prefix, name, symbol->size, addr);
if (lastfs != 's') {
r_cons_printf ("fs %s\n",
exponly? "exports": "symbols");
}
lastfs = 's';
}
} else {
if (*name) {
if (r->bin->prefix) {
if (symbol->dup_count) {
r_cons_printf ("f sym.%s_%d %u 0x%08"PFMT64x"\n",
name, symbol->dup_count, symbol->size, addr);
r_cons_printf ("f %s.sym.%s_%d %u 0x%08" PFMT64x "\n",
r->bin->prefix, name, symbol->dup_count, symbol->size, addr);
} else {
r_cons_printf ("f sym.%s %u 0x%08"PFMT64x"\n",
name, symbol->size, addr);
r_cons_printf ("f %s.sym.%s %u 0x%08" PFMT64x "\n",
r->bin->prefix, name, symbol->size, addr);
}
} else {
// we dont want unnamed symbol flags
}
}
binfile = r_core_bin_cur (r);
plugin = r_bin_file_cur_plugin (binfile);
if (plugin && plugin->name) {
if (!strncmp (plugin->name, "pe", 2)) {
char *p, *module = strdup (r_symbol_name);
p = strstr (module, ".dll_");
if (p) {
const char *symname = p + 5;
*p = 0;
if (r->bin->prefix) {
r_cons_printf ("k bin/pe/%s/%d=%s.%s\n",
module, symbol->ordinal, r->bin->prefix, symname);
if (*name) {
if (symbol->dup_count) {
r_cons_printf ("f sym.%s_%d %u 0x%08" PFMT64x "\n",
name, symbol->dup_count, symbol->size, addr);
} else {
r_cons_printf ("k bin/pe/%s/%d=%s\n",
module, symbol->ordinal, symname);
r_cons_printf ("f sym.%s %u 0x%08" PFMT64x "\n",
name, symbol->size, addr);
}
} else {
// we dont want unnamed symbol flags
}
}
binfile = r_core_bin_cur (r);
plugin = r_bin_file_cur_plugin (binfile);
if (plugin && plugin->name) {
if (r_str_startswith (plugin->name, "pe")) {
char *module = strdup (r_symbol_name);
char *p = strstr (module, ".dll_");
if (p) {
const char *symname = p + 5;
*p = 0;
if (r->bin->prefix) {
r_cons_printf ("k bin/pe/%s/%d=%s.%s\n",
module, symbol->ordinal, r->bin->prefix, symname);
} else {
r_cons_printf ("k bin/pe/%s/%d=%s\n",
module, symbol->ordinal, symname);
}
}
free (module);
}
free (module);
}
}
} else {
Expand Down
1 change: 1 addition & 0 deletions libr/include/r_bin.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ R_LIB_VERSION_HEADER (r_bin);
#define R_BIN_TYPE_HIOS_STR "HIOS"
#define R_BIN_TYPE_LOPROC_STR "LOPROC"
#define R_BIN_TYPE_HIPROC_STR "HIPROC"
#define R_BIN_TYPE_SPECIAL_SYM_STR "SPECIAL_SYM"
#define R_BIN_TYPE_UNKNOWN_STR "UNK"

enum {
Expand Down

0 comments on commit 33c678f

Please sign in to comment.