* Add support for parsing relocs to r_bin

* Add flag -R to rabin2 to list relocs
* Implement reloc resolution in r_bin_elf for 32 & 64 bits
This commit is contained in:
Nibble 2010-09-10 11:11:38 +02:00
parent 2d2131607c
commit 5567da9538
17 changed files with 184 additions and 5 deletions

4
TODO
View File

@ -41,10 +41,10 @@ Build system:
TODO nibble
-----------
* r_bin->relocs // RList of relocations
* use r_anal_value everywhere in r_anal
* make x86_x86im the default backend for x86 analysis
* implement analysis for more instructions in x86_x86im
* use r_anal_value everywhere in r_anal
* r_bin->relocs // RList of relocations
* big-ssl.c big-gmp.c ...
* native fat bins support (push uncommited changes)
* diff code analysis

View File

@ -29,6 +29,7 @@
#define ACTION_SRCLINE 0x0400
#define ACTION_MAIN 0x0800
#define ACTION_EXTRACT 0x1000
#define ACTION_RELOCS 0x2000
static struct r_lib_t *l;
static struct r_bin_t *bin = NULL;
@ -53,6 +54,7 @@ static int rabin_show_help() {
" -I Binary info\n"
" -H Header fields\n"
" -l Linked libraries\n"
" -R Relocations\n"
" -O [str] Write/Extract operations (str=help for help)\n"
" -o [file] Output file for write operations (a.out by default)\n"
" -f [format] Override file format autodetection\n"
@ -144,6 +146,33 @@ static int rabin_show_libs() {
return R_TRUE;
}
static int rabin_show_relocs() {
RList *relocs;
RListIter *iter;
RBinReloc *reloc;
int i = 0;
ut64 baddr = gbaddr?gbaddr:r_bin_get_baddr (bin);
if ((relocs = r_bin_get_relocs (bin)) == NULL)
return R_FALSE;
if (rad) printf ("fs relocs\n");
else printf ("[Relocations]\n");
r_list_foreach (relocs, iter, reloc) {
if (rad) {
printf ("f reloc.%s @ 0x%08"PFMT64x"\n", reloc->name, va?baddr+reloc->rva:reloc->offset);
} else printf ("sym=%02i address=0x%08"PFMT64x" offset=0x%08"PFMT64x" type=0x%08x %s\n",
reloc->sym, baddr+reloc->rva, reloc->offset, reloc->type, reloc->name);
i++;
}
if (!rad) printf ("\n%i relocations\n", i);
return R_TRUE;
}
static int rabin_show_imports() {
RList *imports;
RListIter *iter;
@ -573,7 +602,7 @@ int main(int argc, char **argv)
r_lib_opendir (l, LIBDIR"/radare2/");
}
while ((c = getopt (argc, argv, "b:Mm:n:@:VisSzIHelwO:o:f:rvLhx")) != -1) {
while ((c = getopt (argc, argv, "b:Mm:n:@:VisSzIHelRwO:o:f:rvLhx")) != -1) {
switch(c) {
case 'm':
at = r_num_math (NULL, optarg);
@ -605,6 +634,9 @@ int main(int argc, char **argv)
case 'l':
action |= ACTION_LIBS;
break;
case 'R':
action |= ACTION_RELOCS;
break;
case 'x':
action |= ACTION_EXTRACT;
break;
@ -679,6 +711,8 @@ int main(int argc, char **argv)
rabin_show_fields();
if (action&ACTION_LIBS)
rabin_show_libs();
if (action&ACTION_RELOCS)
rabin_show_relocs();
if (action&ACTION_SRCLINE)
rabin_show_srcline(at);
if (action&ACTION_EXTRACT)

View File

@ -91,6 +91,8 @@ static void r_bin_init_items(RBin *bin) {
bin->info = bin->cur->info (bin);
if (bin->cur->libs)
bin->libs = bin->cur->libs (bin);
if (bin->cur->relocs)
bin->relocs = bin->cur->relocs (bin);
if (bin->cur->sections)
bin->sections = bin->cur->sections (bin);
if (bin->cur->strings)
@ -112,6 +114,8 @@ static void r_bin_free_items(RBin *bin) {
free (bin->info);
if (bin->libs)
r_list_free (bin->libs);
if (bin->relocs)
r_list_free (bin->relocs);
if (bin->sections)
r_list_free (bin->sections);
if (bin->strings)
@ -207,6 +211,10 @@ R_API RList* r_bin_get_libs(RBin *bin) {
return bin->libs;
}
R_API RList* r_bin_get_relocs(RBin *bin) {
return bin->relocs;
}
R_API RList* r_bin_get_sections(RBin *bin) {
return bin->sections;
}

View File

@ -486,6 +486,86 @@ char *Elf_(r_bin_elf_get_rpath)(struct Elf_(r_bin_elf_obj_t) *bin) {
return ret;
}
struct r_bin_elf_reloc_t* Elf_(r_bin_elf_get_relocs)(struct Elf_(r_bin_elf_obj_t) *bin) {
struct r_bin_elf_reloc_t *ret = NULL;
Elf_(Shdr) *strtab_section;
Elf_(Sym) *sym;
Elf_(Rel) *rel;
char *strtab;
int i, j, nrel, tsize, len, nsym;
if (!bin->shdr || !bin->strtab)
return NULL;
for (i = 0, nsym = 0; i < bin->ehdr.e_shnum; i++)
if (bin->shdr[i].sh_type == (bin->ehdr.e_type == ET_REL ? SHT_SYMTAB : SHT_DYNSYM)) {
strtab_section = &bin->shdr[bin->shdr[i].sh_link];
if ((strtab = (char *)malloc (8+strtab_section->sh_size)) == NULL) {
perror ("malloc (syms strtab)");
return NULL;
}
if (r_buf_read_at (bin->b, strtab_section->sh_offset, (ut8*)strtab, strtab_section->sh_size) == -1) {
eprintf ("Error: read (syms strtab)\n");
return NULL;
}
if ((sym = (Elf_(Sym) *)malloc (1+bin->shdr[i].sh_size)) == NULL) {
perror ("malloc (syms)");
return NULL;
}
nsym = (int)(bin->shdr[i].sh_size/sizeof (Elf_(Sym)));
if (r_buf_fread_at (bin->b, bin->shdr[i].sh_offset, (ut8*)sym,
#if R_BIN_ELF64
bin->endian?"I2cS2L":"i2cs2l",
#else
bin->endian?"3I2cS":"3i2cs",
#endif
nsym) == -1) {
eprintf ("Error: read (sym)\n");
return NULL;
}
}
for (i = 0; i < bin->ehdr.e_shnum; i++) {
if (!strcmp (&bin->strtab[bin->shdr[i].sh_name], ".rel.plt"))
tsize = sizeof (Elf_(Rel));
else if (!strcmp (&bin->strtab[bin->shdr[i].sh_name], ".rela.plt"))
tsize = sizeof (Elf_(Rela));
else continue;
if ((rel = (Elf_(Rel) *)malloc ((int)(bin->shdr[i].sh_size / tsize) * sizeof (Elf_(Rel)))) == NULL) {
perror ("malloc (rel)");
return NULL;
}
for (j = nrel = 0; j < bin->shdr[i].sh_size; j += tsize, nrel++) {
len = r_buf_fread_at (bin->b, bin->shdr[i].sh_offset + j, (ut8*)&rel[nrel],
#if R_BIN_ELF64
bin->endian?"2L":"2l",
#else
bin->endian?"2I":"2i",
#endif
1);
if (len == -1) {
eprintf ("Error: read (rel)\n");
return NULL;
}
}
if ((ret = (struct r_bin_elf_reloc_t *)malloc (nrel * sizeof (struct r_bin_elf_reloc_t))) == NULL) {
perror ("malloc (reloc)");
return NULL;
}
for (j = 0; j < nrel; j++) {
if (j < nsym) {
len = __strnlen (&strtab[sym[ELF_R_SYM (rel[j].r_info)].st_name], ELF_STRING_LENGTH-1);
memcpy (ret[j].name, &strtab[sym[ELF_R_SYM (rel[j].r_info)].st_name], len);
} else strncpy (ret[j].name, "unknown", ELF_STRING_LENGTH);
ret[j].sym = ELF_R_SYM (rel[j].r_info);
ret[j].type = ELF_R_TYPE (rel[j].r_info);
ret[j].offset = rel[j].r_offset - bin->baddr;
ret[j].last = 0;
}
ret[j].last = 1;
break;
}
return ret;
}
struct r_bin_elf_lib_t* Elf_(r_bin_elf_get_libs)(struct Elf_(r_bin_elf_obj_t) *bin) {
struct r_bin_elf_lib_t *ret = NULL;
Elf_(Dyn) *dyn = NULL;
@ -597,7 +677,7 @@ struct r_bin_elf_symbol_t* Elf_(r_bin_elf_get_symbols)(struct Elf_(r_bin_elf_obj
return NULL;
}
if (r_buf_read_at (bin->b, strtab_section->sh_offset, (ut8*)strtab, strtab_section->sh_size) == -1) {
eprintf ("Error: read (magic)\n");
eprintf ("Error: read (syms strtab)\n");
return NULL;
}
@ -613,7 +693,7 @@ struct r_bin_elf_symbol_t* Elf_(r_bin_elf_get_symbols)(struct Elf_(r_bin_elf_obj
bin->endian?"3I2cS":"3i2cs",
#endif
nsym) == -1) {
eprintf ("Error: read (ehdr)\n");
eprintf ("Error: read (sym)\n");
return NULL;
}
for (j = k = ret_ctr = 0; j < bin->shdr[i].sh_size; j += sizeof (Elf_(Sym)), k++) {
@ -725,6 +805,7 @@ struct Elf_(r_bin_elf_obj_t)* Elf_(r_bin_elf_new)(const char* file) {
if (!(bin = malloc (sizeof (struct Elf_(r_bin_elf_obj_t)))))
return NULL;
memset (bin, 0, sizeof (struct Elf_(r_bin_elf_obj_t)));
bin->file = file;
if (!(buf = (ut8*)r_file_slurp (file, &bin->size)))
return Elf_(r_bin_elf_free) (bin);

View File

@ -34,6 +34,14 @@ typedef struct r_bin_elf_symbol_t {
int last;
} RBinElfSymbol;
typedef struct r_bin_elf_reloc_t {
int sym;
int type;
ut64 offset;
int last;
char name[ELF_STRING_LENGTH];
} RBinElfReloc;
typedef struct r_bin_elf_field_t {
ut64 offset;
char name[ELF_STRING_LENGTH];
@ -79,6 +87,7 @@ char* Elf_(r_bin_elf_get_elf_class)(struct Elf_(r_bin_elf_obj_t) *bin);
int Elf_(r_bin_elf_get_bits)(struct Elf_(r_bin_elf_obj_t) *bin);
char* Elf_(r_bin_elf_get_osabi_name)(struct Elf_(r_bin_elf_obj_t) *bin);
int Elf_(r_bin_elf_is_big_endian)(struct Elf_(r_bin_elf_obj_t) *bin);
struct r_bin_elf_reloc_t* Elf_(r_bin_elf_get_relocs)(struct Elf_(r_bin_elf_obj_t) *bin);
struct r_bin_elf_lib_t* Elf_(r_bin_elf_get_libs)(struct Elf_(r_bin_elf_obj_t) *bin);
struct r_bin_elf_section_t* Elf_(r_bin_elf_get_sections)(struct Elf_(r_bin_elf_obj_t) *bin);
struct r_bin_elf_symbol_t* Elf_(r_bin_elf_get_symbols)(struct Elf_(r_bin_elf_obj_t) *bin, int type);

View File

@ -421,6 +421,7 @@ struct r_bin_java_obj_t* r_bin_java_new(const char* file) {
if (!(bin = malloc(sizeof(struct r_bin_java_obj_t))))
return NULL;
memset (bin, 0, sizeof (struct r_bin_java_obj_t));
bin->file = file;
if (!(buf = (ut8*)r_file_slurp(file, &bin->size)))
return r_bin_java_free(bin);

View File

@ -745,6 +745,7 @@ struct PE_(r_bin_pe_obj_t)* PE_(r_bin_pe_new)(const char* file)
if (!(bin = malloc(sizeof(struct PE_(r_bin_pe_obj_t)))))
return NULL;
memset (bin, 0, sizeof (struct PE_(r_bin_pe_obj_t)));
bin->file = file;
if (!(buf = (ut8*)r_file_slurp(file, &bin->size)))
return PE_(r_bin_pe_free)(bin);

View File

@ -46,6 +46,7 @@ struct r_bin_plugin_t r_bin_plugin_dummy = {
.info = NULL,
.fields = NULL,
.libs = NULL,
.relocs = NULL,
.meta = NULL,
.write = NULL,
};

View File

@ -155,6 +155,31 @@ static RList* libs(RBin *bin) {
return ret;
}
static RList* relocs(RBin *bin) {
RList *ret = NULL;
RBinReloc *ptr = NULL;
struct r_bin_elf_reloc_t *relocs = NULL;
int i;
if (!(ret = r_list_new ()))
return NULL;
ret->free = free;
if (!(relocs = Elf_(r_bin_elf_get_relocs) (bin->bin_obj)))
return ret;
for (i = 0; !relocs[i].last; i++) {
if (!(ptr = R_NEW (RBinReloc)))
break;
strncpy (ptr->name, relocs[i].name, R_BIN_SIZEOF_STRINGS);
ptr->rva = relocs[i].offset;
ptr->offset = relocs[i].offset;
ptr->type = relocs[i].type;
ptr->sym = relocs[i].sym;
r_list_append (ret, ptr);
}
free (relocs);
return ret;
}
static RBinInfo* info(RBin *bin) {
RBinInfo *ret = NULL;
char *str;
@ -265,6 +290,7 @@ struct r_bin_plugin_t r_bin_plugin_elf = {
.info = &info,
.fields = &fields,
.libs = &libs,
.relocs = &relocs,
.meta = &r_bin_meta_elf,
.write = &r_bin_write_elf,
};

View File

@ -38,6 +38,7 @@ struct r_bin_plugin_t r_bin_plugin_elf64 = {
.info = &info,
.fields = &fields,
.libs = &libs,
.relocs = &relocs,
.meta = &r_bin_meta_elf64,
.write = &r_bin_write_elf64,
};

View File

@ -65,6 +65,7 @@ struct r_bin_plugin_t r_bin_plugin_fatmach0 = {
.info = NULL,
.fields = NULL,
.libs = NULL,
.relocs = NULL,
.meta = NULL,
.write = NULL,
};

View File

@ -154,6 +154,7 @@ struct r_bin_plugin_t r_bin_plugin_java = {
.info = &info,
.fields = NULL,
.libs = NULL,
.relocs = NULL,
.meta = NULL,
.write = NULL,
};

View File

@ -217,6 +217,7 @@ struct r_bin_plugin_t r_bin_plugin_mach0 = {
.info = &info,
.fields = NULL,
.libs = &libs,
.relocs = NULL,
.meta = NULL,
.write = NULL,
};

View File

@ -35,6 +35,7 @@ struct r_bin_plugin_t r_bin_plugin_mach064 = {
.info = &info,
.fields = NULL,
.libs = &libs,
.relocs = NULL,
.meta = NULL,
.write = NULL,
};

View File

@ -243,6 +243,7 @@ struct r_bin_plugin_t r_bin_plugin_pe = {
.info = &info,
.fields = NULL,
.libs = &libs,
.relocs = NULL,
.meta = NULL,
.write = NULL,
};

View File

@ -38,6 +38,7 @@ struct r_bin_plugin_t r_bin_plugin_pe64 = {
.info = &info,
.fields = NULL,
.libs = &libs,
.relocs = NULL,
.meta = NULL,
.write = NULL,
};

View File

@ -35,6 +35,7 @@ typedef struct r_bin_t {
RList* strings;
RList* fields;
RList* libs;
RList* relocs;
RBuffer *buf;
void *user;
struct r_bin_plugin_t *cur;
@ -60,6 +61,7 @@ typedef struct r_bin_plugin_t {
struct r_bin_info_t* (*info)(RBin *bin);
RList* (*fields)(RBin *bin);
RList* (*libs)(RBin *bin);
RList* (*relocs)(RBin *bin);
struct r_bin_meta_t *meta;
struct r_bin_write_t *write;
struct list_head list;
@ -107,6 +109,14 @@ typedef struct r_bin_import_t {
ut64 hint;
} RBinImport;
typedef struct r_bin_reloc_t {
char name[R_BIN_SIZEOF_STRINGS];
ut64 rva;
ut64 offset;
int sym;
int type;
} RBinReloc;
typedef struct r_bin_string_t {
char string[R_BIN_SIZEOF_STRINGS];
ut64 rva;
@ -160,6 +170,7 @@ R_API RList* r_bin_get_fields(RBin *bin);
R_API RList* r_bin_get_imports(RBin *bin);
R_API RBinInfo* r_bin_get_info(RBin *bin);
R_API RList* r_bin_get_libs(RBin *bin);
R_API RList* r_bin_get_relocs(RBin *bin);
R_API RList* r_bin_get_sections(RBin *bin);
R_API RBinSection* r_bin_get_section_at(RBin *bin, ut64 off, int va);
R_API RList* r_bin_get_strings(RBin *bin);