mirror of
https://github.com/radareorg/radare2.git
synced 2024-11-23 21:29:49 +00:00
This commit is the first attempt to improve relocation recognition when dealing with relocatables elf-files
This commit is contained in:
parent
150f8d9faf
commit
b0c6ae4409
@ -35,7 +35,9 @@ static int format_output (char mode, const char *s) {
|
||||
float f = (float)num->fvalue;
|
||||
ut8 *p = (ut8*)&f;
|
||||
printf ("Fx%02x%02x%02x%02x\n", p[3], p[2], p[1], p[0]);
|
||||
} else printf ("0x%"PFMT64x"\n", n);
|
||||
} else {
|
||||
printf ("0x%"PFMT64x"\n", n);
|
||||
}
|
||||
} break;
|
||||
case 'F': {
|
||||
float *f = (float*)&n;
|
||||
|
@ -497,16 +497,16 @@ static int r_bin_object_set_items(RBinFile *binfile, RBinObject *o) {
|
||||
}
|
||||
o->info = cp->info? cp->info (binfile): NULL;
|
||||
if (cp->libs) o->libs = cp->libs (binfile);
|
||||
if (cp->relocs) {
|
||||
o->relocs = cp->relocs (binfile);
|
||||
REBASE_PADDR (o, o->relocs, RBinReloc);
|
||||
}
|
||||
if (cp->sections) {
|
||||
o->sections = cp->sections (binfile);
|
||||
REBASE_PADDR (o, o->sections, RBinSection);
|
||||
if (bin->filter)
|
||||
r_bin_filter_sections (o->sections);
|
||||
}
|
||||
if (cp->relocs) {
|
||||
o->relocs = cp->relocs (binfile);
|
||||
REBASE_PADDR (o, o->relocs, RBinReloc);
|
||||
}
|
||||
if (cp->strings) {
|
||||
o->strings = cp->strings (binfile);
|
||||
} else {
|
||||
@ -1272,6 +1272,25 @@ R_API RList *r_bin_get_libs(RBin *bin) {
|
||||
return o? o->libs: NULL;
|
||||
}
|
||||
|
||||
|
||||
R_API RList * r_bin_patch_relocs(RBin *bin) {
|
||||
RBinObject *o = r_bin_cur_object (bin);
|
||||
//r_bin_object_set_items set o->relocs but there we don't have access to io
|
||||
//so we need to be run from bin_relocs, free the previous reloc and get the patched ones
|
||||
static bool first = true;
|
||||
if (first && o->plugin && o->plugin->patch_relocs) {
|
||||
RList *tmp = o->plugin->patch_relocs (bin);
|
||||
first = false;
|
||||
if (!tmp) return o->relocs;
|
||||
r_list_free (o->relocs);
|
||||
o->relocs = tmp;
|
||||
REBASE_PADDR (o, o->relocs, RBinReloc);
|
||||
first = false;
|
||||
return o->relocs;
|
||||
}
|
||||
return o->relocs;
|
||||
}
|
||||
|
||||
R_API RList *r_bin_get_relocs(RBin *bin) {
|
||||
RBinObject *o = r_bin_cur_object (bin);
|
||||
return o? o->relocs: NULL;
|
||||
|
@ -817,6 +817,7 @@ static int elf_init(struct Elf_(r_bin_elf_obj_t) *bin) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
ut64 Elf_(r_bin_elf_get_section_offset)(struct Elf_(r_bin_elf_obj_t) *bin, const char *section_name) {
|
||||
RBinElfSection *section = get_section_by_name (bin, section_name);
|
||||
if (!section) return UT64_MAX;
|
||||
@ -1022,7 +1023,7 @@ int Elf_(r_bin_elf_has_relro)(struct Elf_(r_bin_elf_obj_t) *bin) {
|
||||
/*
|
||||
To compute the base address, one determines the memory
|
||||
address associated with the lowest p_vaddr value for a
|
||||
PT_LOAD segment. One then btains the base address by
|
||||
PT_LOAD segment. One then obtains the base address by
|
||||
truncating the memory address to the nearest multiple
|
||||
of the maximum page size
|
||||
*/
|
||||
@ -1030,7 +1031,9 @@ of the maximum page size
|
||||
ut64 Elf_(r_bin_elf_get_baddr)(struct Elf_(r_bin_elf_obj_t) *bin) {
|
||||
int i;
|
||||
ut64 tmp, base = UT64_MAX;
|
||||
if (bin && bin->phdr) {
|
||||
if (!bin)
|
||||
return 0;
|
||||
if (bin->phdr) {
|
||||
for (i = 0; i < bin->ehdr.e_phnum; i++) {
|
||||
if (bin->phdr[i].p_type == PT_LOAD) {
|
||||
tmp = (ut64)bin->phdr[i].p_vaddr & ELF_PAGE_MASK;
|
||||
@ -1039,6 +1042,11 @@ ut64 Elf_(r_bin_elf_get_baddr)(struct Elf_(r_bin_elf_obj_t) *bin) {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (base == UT64_MAX && bin->ehdr.e_type == ET_REL) {
|
||||
//we return our own base address for ET_REL type
|
||||
//we act as a loader for ELF
|
||||
return 0x08000000;
|
||||
}
|
||||
return base == UT64_MAX ? 0 : base;
|
||||
}
|
||||
|
||||
@ -1665,6 +1673,7 @@ RBinElfReloc* Elf_(r_bin_elf_get_relocs)(struct Elf_(r_bin_elf_obj_t) *bin) {
|
||||
|
||||
reloc_num = get_relocs_num (bin);
|
||||
if (!reloc_num) return NULL;
|
||||
bin->reloc_num = reloc_num;
|
||||
|
||||
ret = (RBinElfReloc*)calloc ((size_t)reloc_num + 1, sizeof(RBinElfReloc));
|
||||
if (!ret) return NULL;
|
||||
@ -1688,16 +1697,17 @@ RBinElfReloc* Elf_(r_bin_elf_get_relocs)(struct Elf_(r_bin_elf_obj_t) *bin) {
|
||||
if (j + res > g_sections[i].size) {
|
||||
eprintf ("Warning: malformed file, relocation entry #%u is partially beyond the end of section %u.\n", rel, i);
|
||||
}
|
||||
ret[rel].rva = ret[rel].offset;
|
||||
if (is_rela) {
|
||||
if (ret[rel].type != R_386_IRELATIVE && ret[rel].type != R_X86_64_IRELATIVE) {
|
||||
// IREL relocations are not really RELA, the addend field is just
|
||||
// repurposed for the ifunc pointer.
|
||||
ret[rel].rva += section_text_offset;
|
||||
ret[rel].sto = section_text_offset;
|
||||
if (bin->ehdr.e_type == ET_REL) {
|
||||
if (g_sections[i].info < bin->ehdr.e_shnum) {
|
||||
ret[rel].rva = bin->shdr[g_sections[i].info].sh_offset + ret[rel].offset;
|
||||
ret[rel].rva = Elf_(r_bin_elf_p2v) (bin, ret[rel].rva);
|
||||
} else {
|
||||
ret[rel].rva = ret[rel].offset;
|
||||
}
|
||||
} else {
|
||||
ret[rel].rva = ret[rel].offset;
|
||||
ret[rel].offset = Elf_(r_bin_elf_v2p) (bin, ret[rel].offset);
|
||||
}
|
||||
ret[rel].offset = Elf_(r_bin_elf_v2p) (bin, ret[rel].offset);
|
||||
ret[rel].last = 0;
|
||||
if (res < 0) break;
|
||||
rel++;
|
||||
@ -1834,10 +1844,16 @@ RBinElfSection* Elf_(r_bin_elf_get_sections)(struct Elf_(r_bin_elf_obj_t) *bin)
|
||||
|
||||
for (i = 0; i < bin->ehdr.e_shnum; i++) {
|
||||
ret[i].offset = bin->shdr[i].sh_offset;
|
||||
ret[i].rva = bin->shdr[i].sh_addr;
|
||||
ret[i].size = bin->shdr[i].sh_size;
|
||||
ret[i].align = bin->shdr[i].sh_addralign;
|
||||
ret[i].flags = bin->shdr[i].sh_flags;
|
||||
ret[i].link = bin->shdr[i].sh_link;
|
||||
ret[i].info = bin->shdr[i].sh_info;
|
||||
if (bin->ehdr.e_type == ET_REL) {
|
||||
ret[i].rva = bin->baddr + bin->shdr[i].sh_offset;
|
||||
} else {
|
||||
ret[i].rva = bin->shdr[i].sh_addr;
|
||||
}
|
||||
nidx = bin->shdr[i].sh_name;
|
||||
#define SHNAME (int)bin->shdr[i].sh_name
|
||||
#define SHNLEN ELF_STRING_LENGTH - 4
|
||||
@ -1850,9 +1866,14 @@ RBinElfSection* Elf_(r_bin_elf_get_sections)(struct Elf_(r_bin_elf_obj_t) *bin)
|
||||
if (bin->shstrtab && (SHNAME > 0) && (SHNAME < SHSIZE)) {
|
||||
strncpy (ret[i].name, &bin->shstrtab[SHNAME], SHNLEN);
|
||||
} else {
|
||||
snprintf (unknown_s, sizeof (unknown_s)-4, "unknown%d", unknown_c);
|
||||
strncpy (ret[i].name, unknown_s, sizeof (ret[i].name)-4);
|
||||
unknown_c++;
|
||||
if (bin->shdr[i].sh_type == SHT_NULL) {
|
||||
//to follow the same behaviour as readelf
|
||||
strncpy (ret[i].name, "", sizeof (ret[i].name) - 4);
|
||||
} else {
|
||||
snprintf (unknown_s, sizeof (unknown_s)-4, "unknown%d", unknown_c);
|
||||
strncpy (ret[i].name, unknown_s, sizeof (ret[i].name)-4);
|
||||
unknown_c++;
|
||||
}
|
||||
}
|
||||
}
|
||||
ret[i].name[ELF_STRING_LENGTH-2] = '\0';
|
||||
@ -2010,19 +2031,10 @@ RBinElfSymbol* Elf_(r_bin_elf_get_symbols)(struct Elf_(r_bin_elf_obj_t) *bin, in
|
||||
Elf_(Shdr) *strtab_section = NULL;
|
||||
Elf_(Sym) *sym = NULL;
|
||||
char *strtab = NULL;
|
||||
RBinElfSection* section_text = NULL;
|
||||
ut64 section_text_offset = 0LL;
|
||||
|
||||
if (!bin || !bin->shdr || bin->ehdr.e_shnum == 0 || bin->ehdr.e_shnum == 0xffff)
|
||||
return get_symbols_from_phdr (bin, type);
|
||||
|
||||
if (bin->ehdr.e_type == ET_REL) {
|
||||
section_text = get_section_by_name(bin, ".text");
|
||||
if (section_text && section_text->offset != -1) {
|
||||
section_text_offset = section_text->offset;
|
||||
}
|
||||
}
|
||||
|
||||
if (!UT32_MUL (&shdr_size, bin->ehdr.e_shnum, sizeof (Elf_(Shdr))))
|
||||
return false;
|
||||
if (shdr_size + 8 > bin->size)
|
||||
@ -2036,7 +2048,7 @@ RBinElfSymbol* Elf_(r_bin_elf_get_symbols)(struct Elf_(r_bin_elf_obj_t) *bin, in
|
||||
continue;
|
||||
}
|
||||
// hack to avoid asan cry
|
||||
if ((bin->shdr[i].sh_link*sizeof(Elf_(Shdr)))>= shdr_size) {
|
||||
if ((bin->shdr[i].sh_link * sizeof(Elf_(Shdr))) >= shdr_size) {
|
||||
/* oops. fix out of range pointers */
|
||||
continue;
|
||||
}
|
||||
@ -2048,7 +2060,7 @@ RBinElfSymbol* Elf_(r_bin_elf_get_symbols)(struct Elf_(r_bin_elf_obj_t) *bin, in
|
||||
return NULL;
|
||||
}
|
||||
if (!strtab) {
|
||||
if ((strtab = (char *)calloc (1, 8+strtab_section->sh_size)) == NULL) {
|
||||
if ((strtab = (char *)calloc (1, 8 + strtab_section->sh_size)) == NULL) {
|
||||
eprintf ("malloc (syms strtab)");
|
||||
goto beach;
|
||||
}
|
||||
@ -2108,16 +2120,19 @@ RBinElfSymbol* Elf_(r_bin_elf_get_symbols)(struct Elf_(r_bin_elf_obj_t) *bin, in
|
||||
//int idx = sym[k].st_shndx;
|
||||
tsize = sym[k].st_size;
|
||||
toffset = (ut64)sym[k].st_value; //-sym_offset; // + (ELF_ST_TYPE(sym[k].st_info) == STT_FUNC?sym_offset:data_offset);
|
||||
} else continue;
|
||||
#if SKIP_SYMBOLS_WITH_VALUE
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (bin->ehdr.e_type == ET_REL) {
|
||||
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;
|
||||
} else {
|
||||
ret[ret_ctr].offset = Elf_(r_bin_elf_v2p) (bin, toffset);
|
||||
}
|
||||
|
||||
/* skip symbols with value */
|
||||
if (sym[k].st_value) continue;
|
||||
#endif
|
||||
ret[ret_ctr].offset = Elf_(r_bin_elf_v2p) (bin, toffset);
|
||||
if (section_text) ret[ret_ctr].offset += section_text_offset;
|
||||
ret[ret_ctr].size = tsize;
|
||||
if (sym[k].st_name+2 > strtab_section->sh_size) {
|
||||
if (sym[k].st_name + 2 > strtab_section->sh_size) {
|
||||
eprintf ("Warning: index out of strtab range\n");
|
||||
goto beach;
|
||||
}
|
||||
@ -2259,7 +2274,12 @@ static int is_in_vphdr (Elf_(Phdr) *p, ut64 addr) {
|
||||
ut64 Elf_(r_bin_elf_p2v) (struct Elf_(r_bin_elf_obj_t) *bin, ut64 paddr) {
|
||||
int i;
|
||||
|
||||
if (!bin) return paddr;
|
||||
if (!bin || !bin->phdr) {
|
||||
if (bin->ehdr.e_type == ET_REL) {
|
||||
return bin->baddr + paddr;
|
||||
}
|
||||
return paddr;
|
||||
}
|
||||
for (i = 0; i < bin->ehdr.e_phnum; ++i) {
|
||||
Elf_(Phdr) *p = &bin->phdr[i];
|
||||
if (!p) break;
|
||||
@ -2277,7 +2297,12 @@ ut64 Elf_(r_bin_elf_p2v) (struct Elf_(r_bin_elf_obj_t) *bin, ut64 paddr) {
|
||||
ut64 Elf_(r_bin_elf_v2p) (struct Elf_(r_bin_elf_obj_t) *bin, ut64 vaddr) {
|
||||
int i;
|
||||
|
||||
if (!bin || !bin->phdr) return vaddr;
|
||||
if (!bin || !bin->phdr) {
|
||||
if (bin->ehdr.e_type == ET_REL) {
|
||||
return vaddr - bin->baddr;
|
||||
}
|
||||
return vaddr;
|
||||
}
|
||||
for (i = 0; i < bin->ehdr.e_phnum; ++i) {
|
||||
Elf_(Phdr) *p = &bin->phdr[i];
|
||||
if (!p) break;
|
||||
|
@ -21,6 +21,8 @@ typedef struct r_bin_elf_section_t {
|
||||
ut64 size;
|
||||
ut64 align;
|
||||
ut32 flags;
|
||||
ut32 link;
|
||||
ut32 info;
|
||||
char name[ELF_STRING_LENGTH];
|
||||
int last;
|
||||
} RBinElfSection;
|
||||
@ -82,6 +84,7 @@ struct Elf_(r_bin_elf_obj_t) {
|
||||
Elf_(Dyn) *dyn_buf;
|
||||
int dyn_entries;
|
||||
int is_rela;
|
||||
ut32 reloc_num;
|
||||
|
||||
ut64 version_info[DT_VERSIONTAGNUM];
|
||||
|
||||
|
@ -5,6 +5,8 @@
|
||||
#include <r_util.h>
|
||||
#include <r_lib.h>
|
||||
#include <r_bin.h>
|
||||
#include <r_io.h>
|
||||
#include <r_cons.h>
|
||||
#include "elf/elf.h"
|
||||
|
||||
#define ELFOBJ struct Elf_(r_bin_elf_obj_t)
|
||||
@ -142,7 +144,6 @@ static RList* sections(RBinFile *arch) {
|
||||
ret->free = free;
|
||||
if ((section = Elf_(r_bin_elf_get_sections) (obj))) {
|
||||
for (i = 0; !section[i].last; i++) {
|
||||
if (!section[i].size) continue;
|
||||
if (!(ptr = R_NEW0 (RBinSection)))
|
||||
break;
|
||||
strncpy (ptr->name, (char*)section[i].name, R_BIN_SIZEOF_STRINGS);
|
||||
@ -156,8 +157,11 @@ static RList* sections(RBinFile *arch) {
|
||||
ptr->srwx |= R_BIN_SCN_EXECUTABLE;
|
||||
if (R_BIN_ELF_SCN_IS_WRITABLE (section[i].flags))
|
||||
ptr->srwx |= R_BIN_SCN_WRITABLE;
|
||||
if (R_BIN_ELF_SCN_IS_READABLE (section[i].flags))
|
||||
if (R_BIN_ELF_SCN_IS_READABLE (section[i].flags)) {
|
||||
ptr->srwx |= R_BIN_SCN_READABLE;
|
||||
if (obj->ehdr.e_type == ET_REL)
|
||||
ptr->srwx |= R_BIN_SCN_MAP;
|
||||
}
|
||||
r_list_append (ret, ptr);
|
||||
}
|
||||
free (section);
|
||||
@ -248,7 +252,9 @@ static RList* sections(RBinFile *arch) {
|
||||
ptr->vaddr = obj->baddr;
|
||||
ptr->size = ehdr_size;
|
||||
ptr->vsize = ehdr_size;
|
||||
ptr->add = false;
|
||||
ptr->add = true;
|
||||
if (obj->ehdr.e_type == ET_REL)
|
||||
ptr->add = true;
|
||||
ptr->srwx = R_BIN_SCN_READABLE | R_BIN_SCN_WRITABLE | R_BIN_SCN_MAP;
|
||||
r_list_append (ret, ptr);
|
||||
}
|
||||
@ -421,13 +427,6 @@ static RBinReloc *reloc_convert(struct Elf_(r_bin_elf_obj_t) *bin, RBinElfReloc
|
||||
}
|
||||
r->vaddr = rel->rva;
|
||||
r->paddr = rel->offset;
|
||||
// if object file
|
||||
if (bin->ehdr.e_type == ET_REL) {
|
||||
ut64 text;
|
||||
if ((text = Elf_ (r_bin_elf_get_section_offset) (bin, ".text")) != -1) {
|
||||
r->vaddr += text;
|
||||
}
|
||||
}
|
||||
|
||||
#define SET(T) r->type = R_BIN_RELOC_ ## T; r->additive = 0; return r
|
||||
#define ADD(T, A) r->type = R_BIN_RELOC_ ## T; r->addend += A; r->additive = !rel->is_rela; return r
|
||||
@ -488,12 +487,6 @@ static RBinReloc *reloc_convert(struct Elf_(r_bin_elf_obj_t) *bin, RBinElfReloc
|
||||
}
|
||||
break;
|
||||
default: break;
|
||||
#if 0
|
||||
if (!(str = Elf_(r_bin_elf_get_machine_name) (bin)))
|
||||
break;
|
||||
eprintf("TODO(eddyb): uninmplemented ELF reloc_convert for %s\n", str);
|
||||
free(str);
|
||||
#endif
|
||||
}
|
||||
|
||||
#undef SET
|
||||
@ -507,34 +500,147 @@ static RList* relocs(RBinFile *arch) {
|
||||
RList *ret = NULL;
|
||||
RBinReloc *ptr = NULL;
|
||||
RBinElfReloc *relocs = NULL;
|
||||
struct Elf_(r_bin_elf_obj_t) *bin = NULL;
|
||||
ut64 got_addr;
|
||||
int i;
|
||||
|
||||
if (!arch || !arch->o || !arch->o->bin_obj)
|
||||
return NULL;
|
||||
bin = arch->o->bin_obj;
|
||||
if (!(ret = r_list_new ()))
|
||||
return NULL;
|
||||
ret->free = free;
|
||||
/* FIXME: This is a _temporary_ fix/workaround to prevent a use-after-
|
||||
* free detected by ASan that would corrupt the relocation names */
|
||||
r_list_free (imports (arch));
|
||||
|
||||
#if 1
|
||||
if ((got_addr = Elf_ (r_bin_elf_get_section_addr) (arch->o->bin_obj, ".got")) == -1) {
|
||||
got_addr = Elf_ (r_bin_elf_get_section_addr) (arch->o->bin_obj, ".got.plt");
|
||||
got_addr = 0;
|
||||
if ((got_addr = Elf_(r_bin_elf_get_section_addr) (bin, ".got")) == -1) {
|
||||
got_addr = Elf_(r_bin_elf_get_section_addr) (bin, ".got.plt");
|
||||
if (got_addr == -1)
|
||||
got_addr = 0;
|
||||
}
|
||||
if (got_addr < 1 && bin->ehdr.e_type == ET_REL) {
|
||||
got_addr = Elf_(r_bin_elf_get_section_addr) (bin, ".got.r2");
|
||||
if (got_addr == -1)
|
||||
got_addr = 0;
|
||||
}
|
||||
|
||||
if (arch->o) {
|
||||
if (!(relocs = Elf_(r_bin_elf_get_relocs) (arch->o->bin_obj)))
|
||||
if (!(relocs = Elf_(r_bin_elf_get_relocs) (bin)))
|
||||
return ret;
|
||||
for (i = 0; !relocs[i].last; i++) {
|
||||
if (!(ptr = reloc_convert (arch->o->bin_obj,
|
||||
&relocs[i], got_addr)))
|
||||
if (!(ptr = reloc_convert (bin, &relocs[i], got_addr)))
|
||||
continue;
|
||||
r_list_append (ret, ptr);
|
||||
}
|
||||
free (relocs);
|
||||
}
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define write_into_reloc() \
|
||||
do { \
|
||||
ut8 *buf = malloc (strlen (s) + 1); \
|
||||
if (!buf) break; \
|
||||
int len = r_hex_str2bin (s, buf); \
|
||||
iob->write_at (iob->io, rel->rva, buf, len); \
|
||||
free (buf); \
|
||||
} while (0) \
|
||||
|
||||
static void __patch_reloc (RIOBind *iob, RBinElfReloc *rel, ut64 vaddr) {
|
||||
static int times = 0;
|
||||
char s[64];
|
||||
times++;
|
||||
switch (rel->type) {
|
||||
case R_X86_64_PC32: //R_386_PC32 both have the same value
|
||||
{
|
||||
ut64 num = vaddr - (rel->rva + 4);
|
||||
num = ((num << 8) & 0xFF00FF00 ) | ((num >> 8) & 0xFF00FF);
|
||||
//if s is equal to 0x42d we should get 0x042d that is why %04
|
||||
snprintf (s, sizeof (s), "%04"PFMT64x, num);
|
||||
write_into_reloc();
|
||||
}
|
||||
break;
|
||||
case R_X86_64_32S:
|
||||
{
|
||||
st32 num = r_swap_st32(vaddr);
|
||||
snprintf (s, sizeof (s), "%08x", num);
|
||||
write_into_reloc();
|
||||
}
|
||||
break;
|
||||
case R_X86_64_64: //R_386_32
|
||||
{
|
||||
ut64 num = r_swap_ut64(vaddr);
|
||||
snprintf (s, sizeof (s), "%08"PFMT64x, num);
|
||||
write_into_reloc();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
//eprintf ("relocation %d not handle at this time\n", rel->type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static RList* patch_relocs(RBin *b) {
|
||||
RList *ret = NULL;
|
||||
RBinReloc *ptr = NULL;
|
||||
RIO *io = NULL;
|
||||
RBinObject *obj = NULL;
|
||||
struct Elf_(r_bin_elf_obj_t) *bin = NULL;
|
||||
RIOSection *g = NULL, *s = NULL;
|
||||
RListIter *iter;
|
||||
RBinElfReloc *relcs = NULL;
|
||||
int i;
|
||||
ut64 n_off, n_vaddr, vaddr, size, sym_addr = 0, offset = 0;
|
||||
if (!b)
|
||||
return NULL;
|
||||
io = b->iob.get_io(&b->iob);
|
||||
if (!io)
|
||||
return NULL;
|
||||
obj = r_bin_cur_object (b);
|
||||
if (!obj)
|
||||
return NULL;
|
||||
bin = obj->bin_obj;
|
||||
if (bin->ehdr.e_type != ET_REL)
|
||||
return NULL;
|
||||
if (!io->cached) {
|
||||
eprintf (Color_YELLOW"Warning: run r2 with -e io.cache=true to fix relocations in disassembly"Color_RESET"\n");
|
||||
//return without patch
|
||||
return relocs (r_bin_cur(b));
|
||||
}
|
||||
r_list_foreach (io->sections, iter, s) {
|
||||
if (s->offset > offset) {
|
||||
offset = s->offset;
|
||||
g = s;
|
||||
}
|
||||
}
|
||||
if (!g)
|
||||
return NULL;
|
||||
n_off = g->offset + g->size;
|
||||
n_vaddr = g->vaddr + g->vsize;
|
||||
//reserve at least that space
|
||||
size = bin->reloc_num * 4;
|
||||
if (!b->iob.section_add (io, n_off, n_vaddr, size, size, R_BIN_SCN_READABLE|R_BIN_SCN_MAP, ".got.r2", 0, io->desc->fd))
|
||||
return NULL;
|
||||
if (!(relcs = Elf_(r_bin_elf_get_relocs) (bin)))
|
||||
return NULL;
|
||||
if (!(ret = r_list_newf ((RListFree)free)))
|
||||
return NULL;
|
||||
vaddr = n_vaddr;
|
||||
for (i = 0; !relcs[i].last; i++) {
|
||||
if (relcs[i].sym) {
|
||||
if (relcs[i].sym < bin->imports_by_ord_size && bin->imports_by_ord[relcs[i].sym])
|
||||
sym_addr = 0;
|
||||
else if (relcs[i].sym < bin->symbols_by_ord_size && bin->symbols_by_ord[relcs[i].sym])
|
||||
sym_addr = bin->symbols_by_ord[relcs[i].sym]->vaddr;
|
||||
}
|
||||
__patch_reloc (&b->iob, &relcs[i], sym_addr ? sym_addr : vaddr);
|
||||
if (!(ptr = reloc_convert (bin, &relcs[i], n_vaddr)))
|
||||
continue;
|
||||
ptr->vaddr = sym_addr ? sym_addr : vaddr;
|
||||
if (!sym_addr)
|
||||
vaddr += 4;
|
||||
r_list_append (ret, ptr);
|
||||
sym_addr = 0;
|
||||
}
|
||||
free (relcs);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -791,6 +897,7 @@ RBinPlugin r_bin_plugin_elf = {
|
||||
.size = &size,
|
||||
.libs = &libs,
|
||||
.relocs = &relocs,
|
||||
.patch_relocs = &patch_relocs,
|
||||
.dbginfo = &r_bin_dbginfo_elf,
|
||||
.create = &create,
|
||||
.write = &r_bin_write_elf,
|
||||
|
@ -133,6 +133,7 @@ RBinPlugin r_bin_plugin_elf64 = {
|
||||
.size = &size,
|
||||
.libs = &libs,
|
||||
.relocs = &relocs,
|
||||
.patch_relocs = &patch_relocs,
|
||||
.dbginfo = &r_bin_dbginfo_elf64,
|
||||
.create = &create,
|
||||
.write = &r_bin_write_elf64,
|
||||
|
@ -869,14 +869,19 @@ static void set_bin_relocs (RCore *r, RBinReloc *reloc, ut64 addr, Sdb **db, cha
|
||||
static int bin_relocs(RCore *r, int mode, int va) {
|
||||
RList *relocs;
|
||||
RListIter *iter;
|
||||
RBinReloc *reloc;
|
||||
RBinReloc *reloc = NULL;
|
||||
Sdb *db = NULL;
|
||||
char *sdb_module = NULL;
|
||||
int i = 0;
|
||||
|
||||
va = VA_TRUE; // XXX relocs always vaddr?
|
||||
|
||||
if ((relocs = r_bin_get_relocs (r->bin)) == NULL) return false;
|
||||
//this has been created for reloc object files
|
||||
relocs = r_bin_patch_relocs (r->bin);
|
||||
if (!relocs) {
|
||||
relocs = r_bin_get_relocs (r->bin);
|
||||
if (!relocs)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (IS_MODE_RAD (mode)) r_cons_printf ("fs relocs\n");
|
||||
if (IS_MODE_NORMAL (mode)) r_cons_printf ("[Relocations]\n");
|
||||
@ -887,8 +892,7 @@ static int bin_relocs(RCore *r, int mode, int va) {
|
||||
if (IS_MODE_SET (mode)) {
|
||||
set_bin_relocs (r, reloc, addr, &db, &sdb_module);
|
||||
} else if (IS_MODE_SIMPLE (mode)) {
|
||||
r_cons_printf ("0x%08"PFMT64x" %s\n", addr,
|
||||
reloc->import ? reloc->import->name : "");
|
||||
r_cons_printf ("0x%08"PFMT64x" %s\n", addr, reloc->import ? reloc->import->name : "");
|
||||
} else if (IS_MODE_RAD (mode)) {
|
||||
char *reloc_name = get_reloc_name (reloc, addr);
|
||||
if (reloc_name) {
|
||||
@ -918,6 +922,8 @@ static int bin_relocs(RCore *r, int mode, int va) {
|
||||
addr, reloc->paddr, bin_reloc_type_name (reloc));
|
||||
if (reloc->import && reloc->import->name[0]) {
|
||||
r_cons_printf (" %s", reloc->import->name);
|
||||
} else if (reloc->symbol && reloc->symbol->name[0]) {
|
||||
r_cons_printf (" %s", reloc->symbol->name);
|
||||
}
|
||||
if (reloc->addend) {
|
||||
if (reloc->import && reloc->addend > 0) {
|
||||
@ -1531,8 +1537,7 @@ static int bin_sections(RCore *r, int mode, ut64 laddr, int va, ut64 at, const c
|
||||
}
|
||||
r_meta_add (r->anal, R_META_TYPE_COMMENT, addr, addr, str);
|
||||
if (section->add)
|
||||
r_io_section_add (r->io, section->paddr, addr, section->size,
|
||||
section->vsize, section->srwx, section->name, 0, fd);
|
||||
r_io_section_add (r->io, section->paddr, addr, section->size, section->vsize, section->srwx, section->name, 0, fd);
|
||||
} else if (IS_MODE_SIMPLE (mode)) {
|
||||
char *hashstr = NULL;
|
||||
if (chksum) {
|
||||
@ -1673,12 +1678,16 @@ static int bin_fields(RCore *r, int mode, int va) {
|
||||
if (IS_MODE_JSON (mode)) r_cons_printf ("[");
|
||||
else if (IS_MODE_RAD (mode)) r_cons_printf ("fs header\n");
|
||||
else if (IS_MODE_NORMAL (mode)) r_cons_printf ("[Header fields]\n");
|
||||
//why this? there is an overlap in bin_sections with ehdr
|
||||
//because there can't be two sections with the same name
|
||||
#if 0
|
||||
else if (IS_MODE_SET (mode)) {
|
||||
// XXX: Need more flags??
|
||||
// this will be set even if the binary does not have an ehdr
|
||||
int fd = r_core_file_cur_fd(r);
|
||||
r_io_section_add (r->io, 0, baddr, size, size, 7, "ehdr", 0, fd);
|
||||
}
|
||||
#endif
|
||||
r_list_foreach (fields, iter, field) {
|
||||
ut64 addr = rva (bin, field->paddr, field->vaddr, va);
|
||||
|
||||
@ -1990,7 +1999,7 @@ static void bin_elf_versioninfo(RCore *r) {
|
||||
snprintf (path_entry, sizeof (path_entry), "%s/entry%d", path, num_entry++);
|
||||
if (!(sdb = sdb_ns_path (r->sdb, path_entry, 0)))
|
||||
break;
|
||||
|
||||
|
||||
r_cons_printf (" %03x: ", sdb_num_get (sdb, "idx", 0));
|
||||
const char *value = NULL;
|
||||
|
||||
@ -2097,6 +2106,8 @@ R_API int r_core_bin_info(RCore *core, int action, int mode, int va, RCoreBinFil
|
||||
ret &= bin_pdb (core, mode);
|
||||
if ((action & R_CORE_BIN_ACC_ENTRIES))
|
||||
ret &= bin_entry (core, mode, loadaddr, va);
|
||||
if ((action & R_CORE_BIN_ACC_SECTIONS))
|
||||
ret &= bin_sections (core, mode, loadaddr, va, at, name, chksum);
|
||||
if ((action & R_CORE_BIN_ACC_RELOCS))
|
||||
ret &= bin_relocs (core, mode, va);
|
||||
if ((action & R_CORE_BIN_ACC_IMPORTS))
|
||||
@ -2105,8 +2116,6 @@ R_API int r_core_bin_info(RCore *core, int action, int mode, int va, RCoreBinFil
|
||||
ret &= bin_exports (core, mode, loadaddr, va, at, name);
|
||||
if ((action & R_CORE_BIN_ACC_SYMBOLS))
|
||||
ret &= bin_symbols (core, mode, loadaddr, va, at, name);
|
||||
if ((action & R_CORE_BIN_ACC_SECTIONS))
|
||||
ret &= bin_sections (core, mode, loadaddr, va, at, name, chksum);
|
||||
if ((action & R_CORE_BIN_ACC_FIELDS))
|
||||
ret &= bin_fields (core, mode, va);
|
||||
if ((action & R_CORE_BIN_ACC_LIBS))
|
||||
|
@ -15,9 +15,9 @@ R_API int r_core_setup_debugger (RCore *r, const char *debugbackend, bool attach
|
||||
|
||||
pid = *p; // 1st element in debugger's struct must be int
|
||||
r_config_set (r->config, "io.ff", "true");
|
||||
if (is_gdb)
|
||||
if (is_gdb)
|
||||
r_core_cmd (r, "dh gdb", 0);
|
||||
else
|
||||
else
|
||||
r_core_cmdf (r, "dh %s", debugbackend);
|
||||
//this makes to attach twice showing warnings in the output
|
||||
//we get "resource busy" so it seems isn't an issue
|
||||
@ -41,7 +41,7 @@ R_API int r_core_setup_debugger (RCore *r, const char *debugbackend, bool attach
|
||||
r_core_cmd (r, "sr PC", 0);
|
||||
if (r_config_get_i (r->config, "dbg.status"))
|
||||
r_config_set (r->config, "cmd.prompt", ".dr*;drd;sr PC;pi 1;s-");
|
||||
else
|
||||
else
|
||||
r_config_set (r->config, "cmd.prompt", ".dr*");
|
||||
r_config_set (r->config, "cmd.vprompt", ".dr*");
|
||||
return true;
|
||||
@ -253,49 +253,38 @@ R_API int r_core_seek_archbits (RCore *core, ut64 addr) {
|
||||
|
||||
R_API bool r_core_seek(RCore *core, ut64 addr, bool rb) {
|
||||
RIOSection *newsection;
|
||||
ut64 old = core->offset;
|
||||
ut64 ret;
|
||||
ut64 ret, old = core->offset;
|
||||
|
||||
core->offset = addr;
|
||||
/* XXX unnecesary call */
|
||||
//r_io_use_fd (core->io, core->file->desc);
|
||||
core->io->section = core->section; // HACK
|
||||
ret = r_io_seek (core->io, addr, R_IO_SEEK_SET);
|
||||
newsection = core->io->section;
|
||||
|
||||
if (ret == UT64_MAX) {
|
||||
//eprintf ("RET =%d %llx\n", ret, addr);
|
||||
/*
|
||||
XXX handle read errors correctly
|
||||
if (core->io->ff) {
|
||||
core->offset = addr;
|
||||
} else return false;
|
||||
*/
|
||||
//core->offset = addr;
|
||||
if (!core->io->va)
|
||||
return false;
|
||||
//memset (core->block, 0xff, core->blocksize);
|
||||
} else core->offset = addr;
|
||||
} else {
|
||||
core->offset = addr;
|
||||
}
|
||||
if (rb) {
|
||||
ret = r_core_block_read (core, 0);
|
||||
if (core->io->ff) {
|
||||
if (ret<1 || ret > core->blocksize)
|
||||
if (ret < 1 || ret > core->blocksize)
|
||||
memset (core->block, 0xff, core->blocksize);
|
||||
else memset (core->block+ret, 0xff, core->blocksize-ret);
|
||||
else
|
||||
memset (core->block+ret, 0xff, core->blocksize-ret);
|
||||
ret = core->blocksize;
|
||||
core->offset = addr;
|
||||
} else {
|
||||
if (ret<1) {
|
||||
if (ret < 1)
|
||||
core->offset = old;
|
||||
//eprintf ("Cannot read block at 0x%08"PFMT64x"\n", addr);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (core->section != newsection) {
|
||||
r_core_seek_archbits (core, core->offset);
|
||||
core->section = newsection;
|
||||
}
|
||||
return (ret==-1)? false: true;
|
||||
return (ret == -1)? false: true;
|
||||
}
|
||||
|
||||
R_API int r_core_seek_delta(RCore *core, st64 addr) {
|
||||
|
@ -140,7 +140,7 @@ typedef struct r_bin_object_t {
|
||||
RList/*<??>*/ *entries;
|
||||
RList/*<??>*/ *fields;
|
||||
RList/*<??>*/ *libs;
|
||||
RList/*<??>*/ *relocs;
|
||||
RList/*<RBinReloc>*/ *relocs;
|
||||
RList/*<??>*/ *strings;
|
||||
RList/*<RBinClass>*/ *classes;
|
||||
RList/*<RBinDwarfRow>*/ *lines;
|
||||
@ -271,6 +271,7 @@ typedef struct r_bin_plugin_t {
|
||||
RList* (*relocs)(RBinFile *arch);
|
||||
RList* (*classes)(RBinFile *arch);
|
||||
RList* (*mem)(RBinFile *arch);
|
||||
RList* (*patch_relocs)(RBin *bin);
|
||||
int (*demangle_type)(const char *str);
|
||||
struct r_bin_dbginfo_t *dbginfo;
|
||||
struct r_bin_write_t *write;
|
||||
@ -470,6 +471,7 @@ 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 ut64 r_bin_get_size (RBin *bin);
|
||||
R_API RList* r_bin_patch_relocs(RBin *bin);
|
||||
R_API RList* r_bin_get_relocs(RBin *bin);
|
||||
R_API RList* r_bin_get_sections(RBin *bin);
|
||||
R_API RList* /*<RBinClass>*/r_bin_get_classes(RBin *bin);
|
||||
|
@ -743,6 +743,14 @@ R_API const ut8 *r_uleb128 (const ut8 *data, int datalen, ut64 *v);
|
||||
R_API const ut8 *r_uleb128_decode (const ut8 *data, int *datalen, ut64 *v);
|
||||
R_API const ut8 *r_uleb128_encode (const ut64 s, int *len);
|
||||
R_API const ut8 *r_leb128 (const ut8 *data, st64 *v);
|
||||
|
||||
/*swap*/ //inline?
|
||||
R_API ut16 r_swap_ut16(ut16 val);
|
||||
R_API st16 r_swap_st16(st16 val);
|
||||
R_API ut32 r_swap_ut32(ut32 val);
|
||||
R_API st32 r_swap_st32(st32 val);
|
||||
R_API ut64 r_swap_ut64(ut64 val);
|
||||
R_API st64 r_swap_st64(st64 val);
|
||||
#endif
|
||||
|
||||
/* constr */
|
||||
|
@ -33,7 +33,8 @@ R_API void r_io_cache_commit(RIO *io, ut64 from, ut64 to) {
|
||||
if (c->from >= from && c->to <= to) {
|
||||
if (!r_io_write_at (io, c->from, c->data, c->size))
|
||||
eprintf ("Error writing change at 0x%08"PFMT64x"\n", c->from);
|
||||
else c->written = true;
|
||||
else
|
||||
c->written = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -783,7 +783,8 @@ R_API ut64 r_io_seek(RIO *io, ut64 offset, int whence) {
|
||||
if (io->plugin && io->plugin->lseek)
|
||||
ret = io->plugin->lseek (io, io->desc, offset, whence);
|
||||
// XXX can be problematic on w32..so no 64 bit offset?
|
||||
else ret = (ut64)lseek (io->desc->fd, offset, posix_whence);
|
||||
else
|
||||
ret = (ut64)lseek (io->desc->fd, offset, posix_whence);
|
||||
if (ret != UT64_MAX) {
|
||||
if (whence == R_IO_SEEK_SET)
|
||||
io->off = offset; // FIX linux-arm-32-bs at 0x10000
|
||||
|
@ -292,7 +292,8 @@ static ut64 r_io_def_mmap_seek(RIO *io, RIOMMapFileObj *mmo, ut64 offset, int wh
|
||||
}
|
||||
|
||||
static ut64 r_io_def_mmap_lseek(RIO *io, RIODesc *fd, ut64 offset, int whence) {
|
||||
if (!fd || !fd->data) return UT64_MAX;
|
||||
if (!fd || !fd->data)
|
||||
return UT64_MAX;
|
||||
return r_io_def_mmap_seek (io, (RIOMMapFileObj *)fd->data, offset, whence);
|
||||
}
|
||||
|
||||
|
@ -56,10 +56,11 @@ static RIOSection *findMatching (RIO *io, ut64 paddr, ut64 vaddr, ut64 size, ut6
|
||||
R_API RIOSection *r_io_section_add(RIO *io, ut64 offset, ut64 vaddr, ut64 size, ut64 vsize, int rwx, const char *name, ut32 bin_id, int fd) {
|
||||
int update = 0;
|
||||
RIOSection *s;
|
||||
if (size==0 || size>0xf0000000) {
|
||||
if (size>0 && size != UT64_MAX && size != UT32_MAX)
|
||||
eprintf ("Invalid size (0x%08"PFMT64x") for section '%s' at 0x%08"PFMT64x"\n",
|
||||
size, name, vaddr);
|
||||
if (size == 0 || size > 0xf0000000) {
|
||||
if (size > 0 && size != UT64_MAX && size != UT32_MAX)
|
||||
eprintf ("Invalid size (0x%08" PFMT64x
|
||||
") for section '%s' at 0x%08" PFMT64x "\n",
|
||||
size, name, vaddr);
|
||||
return NULL;
|
||||
}
|
||||
s = findMatching (io, offset, vaddr, size, vsize, rwx, name);
|
||||
@ -70,7 +71,9 @@ R_API RIOSection *r_io_section_add(RIO *io, ut64 offset, ut64 vaddr, ut64 size,
|
||||
if (s == NULL) {
|
||||
s = R_NEW0 (RIOSection);
|
||||
s->id = io->next_section_id++;
|
||||
} else update = 1;
|
||||
} else {
|
||||
update = 1;
|
||||
}
|
||||
s->offset = offset;
|
||||
s->vaddr = vaddr;
|
||||
s->size = size;
|
||||
|
@ -12,6 +12,7 @@ OBJS+=strpool.o bitmap.o strht.o p_date.o p_format.o print.o
|
||||
OBJS+=p_seven.o slist.o randomart.o log.o zip.o debruijn.o
|
||||
OBJS+=utf8.o strbuf.o lib.o name.o spaces.o
|
||||
OBJS+=diff.o bdiff.o stack.o queue.o tree.o des.o
|
||||
OBJS+=swap.o
|
||||
|
||||
# DO NOT BUILD r_big api (not yet used and its buggy)
|
||||
ifeq (1,0)
|
||||
|
35
libr/util/swap.c
Normal file
35
libr/util/swap.c
Normal file
@ -0,0 +1,35 @@
|
||||
#include <r_util.h>
|
||||
|
||||
|
||||
R_API ut16 r_swap_ut16(ut16 val) {
|
||||
return (val << 8) | (val >> 8 );
|
||||
}
|
||||
|
||||
R_API st16 r_swap_st16(st16 val) {
|
||||
val = ((val << 8) & 0xFF00FF00 ) | ((val >> 8) & 0xFF00FF );
|
||||
return (val << 16) | (val >> 16);
|
||||
}
|
||||
|
||||
R_API ut32 r_swap_ut32(ut32 val) {
|
||||
val = ((val << 8) & 0xFF00FF00 ) | ((val >> 8) & 0xFF00FF );
|
||||
return (val << 16) | (val >> 16);
|
||||
}
|
||||
|
||||
R_API st32 r_swap_st32(st32 val) {
|
||||
val = ((val << 8) & 0xFF00FF00) | ((val >> 8) & 0xFF00FF );
|
||||
return (val << 16) | ((val >> 16) & 0xFFFF);
|
||||
}
|
||||
|
||||
|
||||
R_API ut64 r_swap_ut64(ut64 val) {
|
||||
val = ((val << 8) & 0xFF00FF00FF00FF00ULL ) | ((val >> 8) & 0x00FF00FF00FF00FFULL );
|
||||
val = ((val << 16) & 0xFFFF0000FFFF0000ULL ) | ((val >> 16) & 0x0000FFFF0000FFFFULL );
|
||||
return (val << 32) | (val >> 32);
|
||||
}
|
||||
|
||||
R_API st64 r_swap_st64(st64 val) {
|
||||
val = ((val << 8) & 0xFF00FF00FF00FF00ULL ) | ((val >> 8) & 0x00FF00FF00FF00FFULL );
|
||||
val = ((val << 16) & 0xFFFF0000FFFF0000ULL ) | ((val >> 16) & 0x0000FFFF0000FFFFULL );
|
||||
return (val << 32) | ((val >> 32) & 0xFFFFFFFFULL);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user