mirror of
https://github.com/radareorg/radare2.git
synced 2024-12-12 07:26:42 +00:00
RBin: improving versioninfo
Store ELF versioninfo in Sdb. Display VS_FIXEDFILEINFO for PE.
This commit is contained in:
parent
b9c34953a1
commit
ab5792d132
@ -318,7 +318,11 @@ static int init_dynamic_section (struct Elf_(r_bin_elf_obj_t) *bin) {
|
||||
case DT_STRTAB: strtabaddr = Elf_(r_bin_elf_v2p) (bin, dyn[i].d_un.d_ptr); break;
|
||||
case DT_STRSZ: strsize = dyn[i].d_un.d_val; break;
|
||||
case DT_PLTREL: bin->is_rela = dyn[i].d_un.d_val; break;
|
||||
default: break;
|
||||
default:
|
||||
if ((dyn[i].d_tag >= DT_VERSYM) && (dyn[i].d_tag <= DT_VERNEEDNUM)) {
|
||||
bin->version_info[DT_VERSIONTAGIDX (dyn[i].d_tag)] = dyn[i].d_un.d_val;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!strtabaddr || strtabaddr > bin->size ||
|
||||
@ -368,134 +372,368 @@ static RBinElfSection* get_section_by_name(struct Elf_(r_bin_elf_obj_t) *bin, co
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* TODO : expose the versioninfo inside RBinObject instead of eprintf */
|
||||
static char *get_ver_flags (ut32 flags)
|
||||
{
|
||||
static char buff[32];
|
||||
buff[0] = 0;
|
||||
|
||||
static void store_versioninfo_gnu_versym(struct Elf_(r_bin_elf_obj_t) *bin, Elf_(Shdr) *shdr) {
|
||||
int i;
|
||||
const char *section_name = "";
|
||||
Elf_(Shdr) *link_shdr = NULL;
|
||||
const char *link_section_name = "";
|
||||
int num_entries = shdr->sh_size / sizeof (Elf_(Versym));
|
||||
ut8 *data = calloc (num_entries, sizeof (short));
|
||||
if (shdr->sh_link > bin->ehdr.e_shnum) {
|
||||
free (data);
|
||||
return;
|
||||
if (flags == 0)
|
||||
return "none";
|
||||
|
||||
if (flags & VER_FLG_BASE)
|
||||
strcat (buff, "BASE ");
|
||||
|
||||
if (flags & VER_FLG_WEAK) {
|
||||
if (flags & VER_FLG_BASE)
|
||||
strcat (buff, "| ");
|
||||
|
||||
strcat (buff, "WEAK ");
|
||||
}
|
||||
link_shdr = &bin->shdr[shdr->sh_link];
|
||||
|
||||
if (flags & ~(VER_FLG_BASE | VER_FLG_WEAK))
|
||||
strcat (buff, "| <unknown>");
|
||||
|
||||
return buff;
|
||||
}
|
||||
|
||||
static Sdb *store_versioninfo_gnu_versym(struct Elf_(r_bin_elf_obj_t) *bin, Elf_(Shdr) *shdr, int sz) {
|
||||
if (!bin->version_info[DT_VERSIONTAGIDX (DT_VERSYM)])
|
||||
return NULL;
|
||||
|
||||
if (shdr->sh_link > bin->ehdr.e_shnum)
|
||||
return NULL;
|
||||
|
||||
int i;
|
||||
int num_entries = shdr->sh_size / sizeof (Elf_(Versym));
|
||||
const char *section_name = "";
|
||||
const char *link_section_name = "";
|
||||
Elf_(Shdr) *link_shdr = &bin->shdr[shdr->sh_link];
|
||||
|
||||
Sdb *sdb = sdb_new0();
|
||||
|
||||
if (!sdb)
|
||||
return NULL;
|
||||
|
||||
ut8 *edata = calloc (num_entries, sizeof (ut16));
|
||||
ut16 *data = calloc (num_entries, sizeof (ut16));
|
||||
|
||||
ut64 off = Elf_(r_bin_elf_v2p) (bin, bin->version_info[DT_VERSIONTAGIDX (DT_VERSYM)]);
|
||||
|
||||
if (bin->shstrtab && shdr->sh_name < bin->shstrtab_size)
|
||||
section_name = &bin->shstrtab[shdr->sh_name];
|
||||
|
||||
if (bin->shstrtab && link_shdr->sh_name < bin->shstrtab_size)
|
||||
link_section_name = &bin->shstrtab[link_shdr->sh_name];
|
||||
|
||||
r_buf_read_at (bin->b, off, edata, sizeof (ut16) * num_entries);
|
||||
sdb_set (sdb, "section_name", section_name, 0);
|
||||
sdb_num_set (sdb, "num_entries", num_entries, 0);
|
||||
sdb_num_set (sdb, "addr", shdr->sh_addr, 0);
|
||||
sdb_num_set (sdb, "offset", shdr->sh_offset, 0);
|
||||
sdb_num_set (sdb, "link", shdr->sh_link, 0);
|
||||
sdb_set (sdb, "link_section_name", link_section_name, 0);
|
||||
|
||||
for (i = num_entries; i--;)
|
||||
data[i] = *(ut16*)&edata[i * sizeof (ut16)];
|
||||
|
||||
free (edata);
|
||||
edata = NULL;
|
||||
|
||||
for (i = 0; i < num_entries; i += 4) {
|
||||
int j;
|
||||
int check_def;
|
||||
char key[32] = {0};
|
||||
Sdb *sdb_entry = sdb_new0 ();
|
||||
snprintf (key, sizeof (key), "entry%d", i / 4);
|
||||
sdb_ns_set (sdb, key, sdb_entry);
|
||||
sdb_num_set (sdb_entry, "idx", i, 0);
|
||||
|
||||
for (j = 0; (j < 4) && (i + j) < num_entries; ++j) {
|
||||
char tmp_val[64] = {0};
|
||||
snprintf (key, sizeof (key), "value%d", j);
|
||||
switch (data[i + j]) {
|
||||
case 0:
|
||||
sdb_set (sdb_entry, key, "0 (*local*)", 0);
|
||||
break;
|
||||
case 1:
|
||||
sdb_set (sdb_entry, key, "1 (*global*)", 0);
|
||||
break;
|
||||
default:
|
||||
snprintf (tmp_val, sizeof (tmp_val), "%x ", data[i+j] & 0x7FFF);
|
||||
check_def = true;
|
||||
|
||||
if (bin->version_info[DT_VERSIONTAGIDX (DT_VERNEED)]) {
|
||||
Elf_(Verneed) vn;
|
||||
ut64 offset;
|
||||
|
||||
offset = Elf_(r_bin_elf_v2p) (bin, bin->version_info[DT_VERSIONTAGIDX (DT_VERNEED)]);
|
||||
do {
|
||||
Elf_(Vernaux) vna;
|
||||
ut64 a_off;
|
||||
|
||||
if (!r_buf_read_at (bin->b, offset, (ut8*)&vn, sizeof (vn))) {
|
||||
eprintf ("Warning: Cannot read Verneed for Versym\n");
|
||||
goto beach;
|
||||
}
|
||||
|
||||
a_off = offset + vn.vn_aux;
|
||||
|
||||
do {
|
||||
if (!r_buf_read_at (bin->b, a_off, (ut8*)&vna, sizeof (vna))) {
|
||||
eprintf ("Warning: Cannot read Vernaux for Versym\n");
|
||||
goto beach;
|
||||
}
|
||||
|
||||
a_off += vna.vna_next;
|
||||
} while (vna.vna_other != data[i + j] && vna.vna_next != 0);
|
||||
|
||||
if (vna.vna_other == data[i + j]) {
|
||||
char val[64] = {0};
|
||||
snprintf (val, sizeof (val), "%s(%s)", tmp_val, bin->strtab + vna.vna_name);
|
||||
sdb_set (sdb_entry, key, val, 0);
|
||||
check_def = false;
|
||||
break;
|
||||
}
|
||||
|
||||
offset += vn.vn_next;
|
||||
} while (vn.vn_next);
|
||||
}
|
||||
|
||||
ut64 vinfoaddr = bin->version_info[DT_VERSIONTAGIDX (DT_VERDEF)];
|
||||
|
||||
if (check_def && data[i + j] != 0x8001 && vinfoaddr) {
|
||||
Elf_(Verdef) vd;
|
||||
ut64 offset;
|
||||
|
||||
offset = Elf_(r_bin_elf_v2p) (bin, vinfoaddr);
|
||||
|
||||
do {
|
||||
if (!r_buf_read_at (bin->b, offset, (ut8*)&vd, sizeof (vd))) {
|
||||
eprintf ("Warning: Cannot read Verdef for Versym\n");
|
||||
goto beach;
|
||||
}
|
||||
|
||||
offset += vd.vd_next;
|
||||
} while (vd.vd_ndx != (data[i + j] & 0x7FFF) && vd.vd_next != 0);
|
||||
|
||||
if (vd.vd_ndx == (data[i + j] & 0x7FFF)) {
|
||||
Elf_(Verdaux) vda;
|
||||
ut64 off_vda = offset - vd.vd_next + vd.vd_aux;
|
||||
char val[64] = {0};
|
||||
|
||||
if (!(r_buf_read_at (bin->b, off_vda, (ut8*)&vda, sizeof (vda)))) {
|
||||
eprintf ("Warning: Cannot read Verdaux for Versym\n");
|
||||
goto beach;
|
||||
}
|
||||
|
||||
const char *name = bin->strtab + vda.vda_name;
|
||||
snprintf (val, sizeof (val), "%s(%s%-*s)", tmp_val, name, (int)(12 - strlen (name)), ")");
|
||||
sdb_set (sdb_entry, key, val, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
beach:
|
||||
free (data);
|
||||
return sdb;
|
||||
}
|
||||
|
||||
static Sdb *store_versioninfo_gnu_verdef(struct Elf_(r_bin_elf_obj_t) *bin, Elf_(Shdr) *shdr, int sz) {
|
||||
const char *section_name = "";
|
||||
const char *link_section_name = "";
|
||||
Elf_(Shdr) *link_shdr = &bin->shdr[shdr->sh_link];
|
||||
Sdb *sdb = sdb_new0 ();
|
||||
int i;
|
||||
int cnt;
|
||||
Elf_(Verdef) *defs = calloc (shdr->sh_size, sizeof (char));
|
||||
if (bin->shstrtab && shdr->sh_name < bin->shstrtab_size) {
|
||||
section_name = &bin->shstrtab[shdr->sh_name];
|
||||
} else {
|
||||
section_name = "";
|
||||
}
|
||||
if (bin->shstrtab && link_shdr->sh_name < bin->shstrtab_size) {
|
||||
link_section_name = &bin->shstrtab[link_shdr->sh_name];
|
||||
} else {
|
||||
link_section_name = "";
|
||||
}
|
||||
if (!defs) {
|
||||
eprintf ("Warning: Cannot allocate memory (Check Elf_(Verdef))\n");
|
||||
sdb_free (sdb);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
IFDBG eprintf ("Version symbols section '%s' contains %d entries:\n", section_name, num_entries);
|
||||
IFDBG eprintf (" Addr: 0x%08"PFMT64x" Offset: 0x%08"PFMT64x" Link: %x (%s)\n",
|
||||
(ut64)shdr->sh_addr, (ut64)shdr->sh_offset, (ut32)shdr->sh_link, link_section_name);
|
||||
for (i = num_entries; i--;) {
|
||||
//r_buf_read_at (bin->b, , &data[i], 1);
|
||||
}
|
||||
for (i = 0; i < num_entries; i += 4) {
|
||||
int j;
|
||||
IFDBG eprintf (" %03x:", i);
|
||||
for (j = 0; (j < 4) && (i + j) < num_entries; ++j) {
|
||||
if (data[i + j] == 0) {
|
||||
IFDBG eprintf (" 0 (*local*) ");
|
||||
} else if (data[i + j] == 1) {
|
||||
IFDBG eprintf (" 1 (*global*) ");
|
||||
} else {
|
||||
ut16 *d = (ut16*) (data + i + j);
|
||||
//eprintf ("%4x%c", data[i + j] & 0x7FFF, data[i + j] & 0x8000 ? 'h' : ' ');
|
||||
IFDBG eprintf ("%4x%c", *d & 0x7FFF, *d & 0x8000 ? 'h' : ' ');
|
||||
}
|
||||
sdb_set (sdb, "section_name", section_name, 0);
|
||||
sdb_num_set (sdb, "entries", shdr->sh_info, 0);
|
||||
sdb_num_set (sdb, "addr", shdr->sh_addr, 0);
|
||||
sdb_num_set (sdb, "offset", shdr->sh_offset, 0);
|
||||
sdb_num_set (sdb, "link", shdr->sh_link, 0);
|
||||
sdb_set (sdb, "link_section_name", link_section_name, 0);
|
||||
|
||||
r_buf_read_at (bin->b, shdr->sh_offset, (ut8*)defs, shdr->sh_size);
|
||||
for (cnt = 0, i = 0; cnt < shdr->sh_info; ++cnt) {
|
||||
Sdb *sdb_verdef = sdb_new0 ();
|
||||
char *vstart = ((char*)defs) + i;
|
||||
char key[32] = {0};
|
||||
Elf_(Verdef) *verdef = (Elf_(Verdef)*)vstart;
|
||||
Elf_(Verdaux) *aux = NULL;
|
||||
int j = 0;
|
||||
int isum = 0;
|
||||
|
||||
sdb_num_set (sdb_verdef, "idx", i, 0);
|
||||
sdb_num_set (sdb_verdef, "vd_version", verdef->vd_version, 0);
|
||||
sdb_num_set (sdb_verdef, "vd_ndx", verdef->vd_ndx, 0);
|
||||
sdb_num_set (sdb_verdef, "vd_cnt", verdef->vd_cnt, 0);
|
||||
sdb_set (sdb_verdef, "vda_name", &bin->dynstr[aux->vda_name], 0);
|
||||
sdb_set (sdb_verdef, "flags", get_ver_flags (verdef->vd_flags), 0);
|
||||
|
||||
vstart += verdef->vd_aux;
|
||||
aux = (Elf_(Verdaux)*)vstart;
|
||||
isum = i + verdef->vd_aux;
|
||||
|
||||
for (j = 1; j < verdef->vd_cnt; ++j) {
|
||||
Sdb *sdb_parent = sdb_new0 ();
|
||||
isum += aux->vda_next;
|
||||
vstart += aux->vda_next;
|
||||
aux = (Elf_(Verdaux)*)vstart;
|
||||
sdb_num_set (sdb_parent, "idx", isum, 0);
|
||||
sdb_num_set (sdb_parent, "parent", j, 0);
|
||||
sdb_set (sdb_parent, "vda_name", &bin->dynstr[aux->vda_name], 0);
|
||||
snprintf (key, sizeof (key), "parent%d", j - 1);
|
||||
sdb_ns_set (sdb_verdef, key, sdb_parent);
|
||||
}
|
||||
IFDBG eprintf ("\n");
|
||||
|
||||
i += verdef->vd_next;
|
||||
snprintf (key, sizeof (key), "verdef%d", cnt);
|
||||
sdb_ns_set (sdb, key, sdb_verdef);
|
||||
}
|
||||
free (data);
|
||||
free (defs);
|
||||
return sdb;
|
||||
}
|
||||
|
||||
static void store_versioninfo_gnu_verdef(struct Elf_(r_bin_elf_obj_t) *bin, Elf_(Shdr) *shdr) {
|
||||
const char *section_name = NULL;
|
||||
if (shdr->sh_name > bin->shstrtab_size)
|
||||
return;
|
||||
section_name = &bin->shstrtab[shdr->sh_name];
|
||||
IFDBG eprintf ("Version definition section '%s' contains %d entries:\n", section_name, shdr->sh_info);
|
||||
}
|
||||
|
||||
static void store_versioninfo_gnu_verneed(struct Elf_(r_bin_elf_obj_t) *bin, Elf_(Shdr) *shdr) {
|
||||
int sz = shdr->sh_size;
|
||||
static Sdb *store_versioninfo_gnu_verneed(struct Elf_(r_bin_elf_obj_t) *bin, Elf_(Shdr) *shdr, int sz) {
|
||||
ut8 *need = NULL;
|
||||
ut8 *vend = NULL;
|
||||
const char *section_name = NULL;
|
||||
const char *section_name = "";
|
||||
Elf_(Shdr) *link_shdr = &bin->shdr[shdr->sh_link];
|
||||
const char *link_section_name = "";
|
||||
int i;
|
||||
int cnt;
|
||||
if (shdr->sh_name > bin->ehdr.e_shnum)
|
||||
return;
|
||||
need = malloc (sz);
|
||||
if (!need) return;
|
||||
section_name = &bin->shstrtab[shdr->sh_name];
|
||||
IFDBG eprintf ("Version needs section '%s' contains %d entries:\n", section_name, shdr->sh_info);
|
||||
IFDBG eprintf (" Addr: 0x%08"PFMT64x, (ut64)shdr->sh_addr);
|
||||
IFDBG eprintf (" Offset: 0x%08"PFMT64x" Link to section: %x (%s)\n",
|
||||
(ut64)shdr->sh_offset, shdr->sh_link, section_name);
|
||||
if (shdr->sh_offset > bin->size || shdr->sh_offset + sz > bin->size)
|
||||
return;
|
||||
if (shdr->sh_offset + sz < sz)
|
||||
return;
|
||||
if (r_buf_read_at (bin->b, shdr->sh_offset, need, sz) != sz) {
|
||||
eprintf ("Cannot read section headers\n");
|
||||
free (need);
|
||||
return;
|
||||
|
||||
Sdb *sdb = sdb_new0 ();
|
||||
if (!sdb)
|
||||
return NULL;
|
||||
|
||||
if (bin->shstrtab && shdr->sh_name < bin->shstrtab_size) {
|
||||
section_name = &bin->shstrtab[shdr->sh_name];
|
||||
}
|
||||
vend = need + sz;
|
||||
if (bin->shstrtab && link_shdr->sh_name < bin->shstrtab_size) {
|
||||
link_section_name = &bin->shstrtab[link_shdr->sh_name];
|
||||
}
|
||||
if (!(need = calloc (shdr->sh_size, sizeof (char)))) {
|
||||
eprintf ("Warning: Cannot allocate memory for Elf_(Verneed)\n");
|
||||
sdb_free (sdb);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sdb_set (sdb, "section_name", section_name, 0);
|
||||
sdb_num_set (sdb, "num_entries", shdr->sh_info, 0);
|
||||
sdb_num_set (sdb, "addr", shdr->sh_addr, 0);
|
||||
sdb_num_set (sdb, "offset", shdr->sh_offset, 0);
|
||||
sdb_num_set (sdb, "link", shdr->sh_link, 0);
|
||||
sdb_set (sdb, "link_section_name", link_section_name, 0);
|
||||
|
||||
r_buf_read_at (bin->b, shdr->sh_offset, need, shdr->sh_size);
|
||||
//XXX we should use DT_VERNEEDNUM instead of sh_info
|
||||
//TODO https://sourceware.org/ml/binutils/2014-11/msg00353.html
|
||||
for (i = 0, cnt = 0; i < sz && cnt < shdr->sh_info; ++cnt) {
|
||||
int j, isum;
|
||||
for (i = 0, cnt = 0; cnt < shdr->sh_info; ++cnt) {
|
||||
int j;
|
||||
int isum;
|
||||
ut8 *vstart = need + i;
|
||||
Elf_(Verneed) *entry = (Elf_(Verneed)*)(vstart);
|
||||
IFDBG eprintf (" %#x: Version: %d", i, entry->vn_version);
|
||||
IFDBG eprintf (" Cnt: %d\n", entry->vn_cnt);
|
||||
char key[32] = {0};
|
||||
Sdb *sdb_version = sdb_new0 ();
|
||||
sdb_num_set (sdb_version, "vn_version", entry->vn_version, 0);
|
||||
sdb_num_set (sdb_version, "idx", i, 0);
|
||||
|
||||
if (bin->dynstr)
|
||||
sdb_set (sdb_version, "file_name", &bin->dynstr[entry->vn_file], 0);
|
||||
|
||||
sdb_num_set (sdb_version, "cnt", entry->vn_cnt, 0);
|
||||
|
||||
vstart += entry->vn_aux;
|
||||
for (j = 0, isum = i + entry->vn_aux; j < entry->vn_cnt && (j + entry->vn_aux +i + sizeof(Elf_(Vernaux))) < sz; j++) {
|
||||
|
||||
for (j = 0, isum = i + entry->vn_aux; j < entry->vn_cnt; ++j) {
|
||||
Sdb *sdb_vernaux = sdb_new0 ();
|
||||
Elf_(Vernaux) *aux = (Elf_(Vernaux)*)(vstart);
|
||||
if (vstart + sizeof (Elf_(Vernaux)) > vend)
|
||||
break;
|
||||
IFDBG eprintf (" Flags: %x Version: %d\n", (ut32)aux->vna_flags, aux->vna_other);
|
||||
if (aux->vna_next > 0) {
|
||||
isum += aux->vna_next;
|
||||
vstart += aux->vna_next;
|
||||
} else {
|
||||
break;
|
||||
|
||||
if (bin->dynstr) {
|
||||
sdb_num_set (sdb_vernaux, "idx", isum, 0);
|
||||
sdb_set (sdb_vernaux, "name", &bin->dynstr[aux->vna_name], 0);
|
||||
}
|
||||
sdb_set (sdb_vernaux, "flags", get_ver_flags (aux->vna_flags), 0);
|
||||
sdb_num_set (sdb_vernaux, "version", aux->vna_other, 0);
|
||||
|
||||
isum += aux->vna_next;
|
||||
vstart += aux->vna_next;
|
||||
snprintf (key, sizeof (key), "vernaux%d", j);
|
||||
sdb_ns_set (sdb_version, key, sdb_vernaux);
|
||||
}
|
||||
if (entry->vn_next < 1) {
|
||||
eprintf ("Invalid next pointer in auxiliary version\n");
|
||||
break;
|
||||
}
|
||||
|
||||
i += entry->vn_next;
|
||||
|
||||
snprintf (key, sizeof (key), "version%d", cnt );
|
||||
sdb_ns_set (sdb, key, sdb_version);
|
||||
}
|
||||
free (need);
|
||||
return sdb;
|
||||
}
|
||||
|
||||
static void store_versioninfo(struct Elf_(r_bin_elf_obj_t) *bin) {
|
||||
static Sdb *store_versioninfo(struct Elf_(r_bin_elf_obj_t) *bin) {
|
||||
int i;
|
||||
if (!bin || !bin->shdr)
|
||||
return;
|
||||
Sdb *sdb_versioninfo = sdb_new0 ();
|
||||
int num_verdef = 0;
|
||||
int num_verneed = 0;
|
||||
int num_versym = 0;
|
||||
|
||||
if (!bin || !bin->shdr || !sdb_versioninfo)
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < bin->ehdr.e_shnum; ++i) {
|
||||
if (bin->shdr[i].sh_type == SHT_GNU_verdef) {
|
||||
store_versioninfo_gnu_verdef (bin, &bin->shdr[i]);
|
||||
} else if (bin->shdr[i].sh_type == SHT_GNU_verneed) {
|
||||
store_versioninfo_gnu_verneed (bin, &bin->shdr[i]);
|
||||
} else if (bin->shdr[i].sh_type == SHT_GNU_versym) {
|
||||
store_versioninfo_gnu_versym (bin, &bin->shdr[i]);
|
||||
Sdb *sdb = NULL;
|
||||
char key[32] = {0};
|
||||
|
||||
switch (bin->shdr[i].sh_type) {
|
||||
case SHT_GNU_verdef:
|
||||
sdb = store_versioninfo_gnu_verdef (bin, &bin->shdr[i], bin->shdr[i].sh_size);
|
||||
snprintf (key, sizeof (key), "verdef%d", num_verdef++);
|
||||
sdb_ns_set (sdb_versioninfo, key, sdb);
|
||||
break;
|
||||
case SHT_GNU_verneed:
|
||||
sdb = store_versioninfo_gnu_verneed (bin, &bin->shdr[i], bin->shdr[i].sh_size);
|
||||
snprintf (key, sizeof (key), "verneed%d", num_verneed++);
|
||||
sdb_ns_set (sdb_versioninfo, key, sdb);
|
||||
break;
|
||||
case SHT_GNU_versym:
|
||||
sdb = store_versioninfo_gnu_versym (bin, &bin->shdr[i], bin->shdr[i].sh_size);
|
||||
snprintf (key, sizeof (key), "versym%d", num_versym++);
|
||||
sdb_ns_set (sdb_versioninfo, key, sdb);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return sdb_versioninfo;
|
||||
}
|
||||
|
||||
static int init_dynstr(struct Elf_(r_bin_elf_obj_t) *bin) {
|
||||
int i;
|
||||
for (i = 0; i < bin->ehdr.e_shnum; ++i) {
|
||||
const char *section_name = &bin->shstrtab[bin->shdr[i].sh_name];
|
||||
if (bin->shdr[i].sh_type == SHT_STRTAB && !strcmp (section_name, ".dynstr")) {
|
||||
if (!(bin->dynstr = calloc (bin->shdr[i].sh_size, sizeof (char)))) {
|
||||
eprintf("Warning: Cannot allocate memory for dynamic strings\n");
|
||||
return 0;
|
||||
}
|
||||
r_buf_read_at (bin->b, bin->shdr[i].sh_offset, (ut8*)bin->dynstr, bin->shdr[i].sh_size);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int elf_init(struct Elf_(r_bin_elf_obj_t) *bin) {
|
||||
@ -506,6 +744,8 @@ static int elf_init(struct Elf_(r_bin_elf_obj_t) *bin) {
|
||||
bin->strtab_size = 0;
|
||||
bin->strtab_section = NULL;
|
||||
bin->dyn_buf = NULL;
|
||||
bin->dynstr = NULL;
|
||||
memset (bin->version_info, 0, DT_VERSIONTAGNUM);
|
||||
|
||||
/* bin is not an ELF */
|
||||
if (!init_ehdr (bin))
|
||||
@ -516,6 +756,8 @@ static int elf_init(struct Elf_(r_bin_elf_obj_t) *bin) {
|
||||
eprintf ("Warning: Cannot initialize section headers\n");
|
||||
if (!init_strtab (bin))
|
||||
eprintf ("Warning: Cannot initialize strings table\n");
|
||||
if (!init_dynstr (bin))
|
||||
eprintf ("Warning: Cannot initialize dynamic strings\n");
|
||||
bin->baddr = Elf_(r_bin_elf_get_baddr) (bin);
|
||||
if (!init_dynamic_section (bin) && !Elf_(r_bin_elf_get_static)(bin))
|
||||
eprintf ("Warning: Cannot initialize dynamic section\n");
|
||||
@ -528,7 +770,7 @@ static int elf_init(struct Elf_(r_bin_elf_obj_t) *bin) {
|
||||
|
||||
bin->boffset = Elf_(r_bin_elf_get_boffset) (bin);
|
||||
|
||||
store_versioninfo (bin);
|
||||
sdb_ns_set (bin->kv, "versioninfo", store_versioninfo (bin));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -83,6 +83,10 @@ struct Elf_(r_bin_elf_obj_t) {
|
||||
int dyn_entries;
|
||||
int is_rela;
|
||||
|
||||
ut64 version_info[DT_VERSIONTAGNUM];
|
||||
|
||||
char *dynstr;
|
||||
|
||||
RBinImport **imports_by_ord;
|
||||
size_t imports_by_ord_size;
|
||||
RBinSymbol **symbols_by_ord;
|
||||
|
132
libr/core/bin.c
132
libr/core/bin.c
@ -1885,10 +1885,34 @@ static void bin_pe_versioninfo(RCore *r) {
|
||||
const char *format_version = "bin/cur/info/vs_version_info/VS_VERSIONINFO%d";
|
||||
const char *format_stringtable = "%s/string_file_info/stringtable%d";
|
||||
const char *format_string = "%s/string%d";
|
||||
r_cons_printf ("=== VS_VERSIONINFO ===\n\n");
|
||||
do {
|
||||
char path_version[256] = {0};
|
||||
snprintf (path_version, sizeof (path_version), format_version, num_version);
|
||||
sdb = sdb_ns_path (r->sdb, path_version, 0);
|
||||
if (!(sdb = sdb_ns_path (r->sdb, path_version, 0)))
|
||||
break;
|
||||
r_cons_printf ("# VS_FIXEDFILEINFO\n\n");
|
||||
char path_fixedfileinfo[256] = {0};
|
||||
snprintf (path_fixedfileinfo, sizeof (path_fixedfileinfo), "%s/fixed_file_info", path_version);
|
||||
if (!(sdb = sdb_ns_path (r->sdb, path_fixedfileinfo, 0)))
|
||||
break;
|
||||
|
||||
r_cons_printf ("Signature: %s\n", sdb_const_get (sdb, "Signature", 0));
|
||||
r_cons_printf ("StrucVersion: %s\n", sdb_const_get (sdb, "FileVersionMS", 0));
|
||||
r_cons_printf ("FileVersionMS: %s\n", sdb_const_get (sdb, "FileVersionMS", 0));
|
||||
r_cons_printf ("FileVersionLS: %s\n", sdb_const_get (sdb, "FileVersionLS", 0));
|
||||
r_cons_printf ("ProductVersionMS: %s\n", sdb_const_get (sdb, "ProductVersionMS", 0));
|
||||
r_cons_printf ("ProductVersionLS: %s\n", sdb_const_get (sdb, "ProductVersionLS", 0));
|
||||
r_cons_printf ("FileFlagsMask: %s\n", sdb_const_get (sdb, "FileFlagsMask", 0));
|
||||
r_cons_printf ("FileFlags: %s\n", sdb_const_get (sdb, "FileFlags", 0));
|
||||
r_cons_printf ("FileOS: %s\n", sdb_const_get (sdb, "FileOS", 0));
|
||||
r_cons_printf ("FileType: %s\n", sdb_const_get (sdb, "FileType", 0));
|
||||
r_cons_printf ("FileSubType: %s\n", sdb_const_get (sdb, "FileSubType", 0));
|
||||
r_cons_printf ("FileDateMS: %s\n", sdb_const_get (sdb, "FileDateMS", 0));
|
||||
r_cons_printf ("FileDateLS: %s\n", sdb_const_get (sdb, "FileDateLS", 0));
|
||||
r_cons_printf ("\n");
|
||||
|
||||
r_cons_printf ("# StringTable\n\n");
|
||||
for (num_stringtable = 0; sdb; ++num_stringtable) {
|
||||
char path_stringtable[256] = {0};
|
||||
snprintf (path_stringtable, sizeof (path_stringtable), format_stringtable, path_version, num_stringtable);
|
||||
@ -1902,13 +1926,20 @@ static void bin_pe_versioninfo(RCore *r) {
|
||||
int lenval = 0;
|
||||
ut8 *key_utf16 = sdb_decode (sdb_const_get (sdb, "key", 0), &lenkey);
|
||||
ut8 *val_utf16 = sdb_decode (sdb_const_get (sdb, "value", 0), &lenval);
|
||||
char *key = r_str_utf16_decode (key_utf16, lenkey);
|
||||
char *val = r_str_utf16_decode (val_utf16, lenval);
|
||||
r_cons_printf ("%s: %s\n", key, val);
|
||||
ut8 *key_utf8 = calloc (lenkey * 2, 1);
|
||||
ut8 *val_utf8 = calloc (lenval * 2, 1);
|
||||
|
||||
if (r_str_utf16_to_utf8 (key_utf8, lenkey * 2, key_utf16, lenkey, true) < 0
|
||||
|| r_str_utf16_to_utf8 (val_utf8, lenval * 2, val_utf16, lenval, true) < 0) {
|
||||
eprintf ("Warning: Cannot decode utf16 to utf8\n");
|
||||
} else {
|
||||
r_cons_printf ("%s: %s\n", (char*)key_utf8, (char*)val_utf8);
|
||||
}
|
||||
|
||||
free (key_utf8);
|
||||
free (val_utf8);
|
||||
free (key_utf16);
|
||||
free (val_utf16);
|
||||
free (key);
|
||||
free (val);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1917,6 +1948,95 @@ static void bin_pe_versioninfo(RCore *r) {
|
||||
}
|
||||
|
||||
static void bin_elf_versioninfo(RCore *r) {
|
||||
const char *format = "bin/cur/info/versioninfo/%s%d";
|
||||
char path[256] = {0};
|
||||
int num_versym = 0;
|
||||
int num_verneed = 0;
|
||||
int num_entry = 0;
|
||||
Sdb *sdb = NULL;
|
||||
|
||||
do {
|
||||
snprintf (path, sizeof (path), format, "versym", num_versym++);
|
||||
if (!(sdb = sdb_ns_path (r->sdb, path, 0)))
|
||||
break;
|
||||
|
||||
ut64 addr = sdb_num_get (sdb, "addr", 0);
|
||||
ut64 offset = sdb_num_get (sdb, "offset", 0);
|
||||
ut64 link = sdb_num_get (sdb, "link", 0);
|
||||
ut64 num_entries = sdb_num_get (sdb, "num_entries", 0);
|
||||
const char *section_name = sdb_const_get (sdb, "section_name", 0);
|
||||
const char *link_section_name = sdb_const_get (sdb, "link_section_name", 0);
|
||||
|
||||
r_cons_printf ("Version symbols section '%s' contains %d entries:\n", section_name, num_entries);
|
||||
r_cons_printf (" Addr: 0x%08"PFMT64x" Offset: 0x%08"PFMT64x" Link: %x (%s)\n",
|
||||
(ut64)addr, (ut64)offset, (ut32)link, link_section_name);
|
||||
|
||||
do {
|
||||
int num_val = 0;
|
||||
char path_entry[256] = {0};
|
||||
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;
|
||||
|
||||
do {
|
||||
char key[32] = {0};
|
||||
snprintf (key, sizeof (key), "value%d", num_val++);
|
||||
|
||||
if ((value = sdb_const_get (sdb, key, 0)))
|
||||
r_cons_printf ("%s ", value);
|
||||
} while (value);
|
||||
r_cons_printf ("\n");
|
||||
} while (sdb);
|
||||
r_cons_printf ("\n\n");
|
||||
} while (sdb);
|
||||
|
||||
do {
|
||||
int num_version = 0;
|
||||
char path_version[256] = {0};
|
||||
snprintf (path, sizeof (path), format, "verneed", num_verneed++);
|
||||
if (!(sdb = sdb_ns_path (r->sdb, path, 0)))
|
||||
break;
|
||||
|
||||
r_cons_printf ("Version need section '%s' contains %d entries:\n",
|
||||
sdb_const_get (sdb, "section_name", 0), sdb_num_get (sdb, "num_entries", 0));
|
||||
|
||||
r_cons_printf (" Addr: %p", (void*)sdb_num_get (sdb, "addr", 0));
|
||||
|
||||
r_cons_printf (" Offset: %#x Link to section: %x (%s)\n",
|
||||
sdb_num_get (sdb, "offset", 0), sdb_num_get (sdb, "link", 0),
|
||||
sdb_const_get (sdb, "link_section_name", 0));
|
||||
|
||||
do {
|
||||
snprintf (path_version, sizeof (path_version), "%s/version%d", path, num_version++);
|
||||
const char *filename = NULL;
|
||||
char path_vernaux[256] = {0};
|
||||
int num_vernaux = 0;
|
||||
if (!(sdb = sdb_ns_path (r->sdb, path_version, 0)))
|
||||
break;
|
||||
|
||||
r_cons_printf (" %#06x: Version: %d",
|
||||
sdb_num_get (sdb, "idx", 0), sdb_num_get (sdb, "vn_version", 0));
|
||||
|
||||
if ((filename = sdb_const_get (sdb, "file_name", 0)))
|
||||
r_cons_printf (" File: %s", filename);
|
||||
|
||||
r_cons_printf (" Cnt: %d\n", sdb_num_get (sdb, "cnt", 0));
|
||||
do {
|
||||
snprintf (path_vernaux, sizeof (path_vernaux), "%s/vernaux%d", path_version, num_vernaux++);
|
||||
if (!(sdb = sdb_ns_path (r->sdb, path_vernaux, 0)))
|
||||
break;
|
||||
|
||||
r_cons_printf (" %#06x: Name: %s",
|
||||
sdb_num_get (sdb, "idx", 0), sdb_const_get (sdb, "name", 0));
|
||||
|
||||
r_cons_printf (" Flags: %s Version: %d\n",
|
||||
sdb_const_get (sdb, "flags", 0), sdb_num_get (sdb, "version", 0));
|
||||
} while (sdb);
|
||||
} while (sdb);
|
||||
} while (sdb);
|
||||
}
|
||||
|
||||
static void bin_mach0_versioninfo(RCore *r) {
|
||||
|
@ -453,7 +453,7 @@ static int cmd_info(void *data, const char *input) {
|
||||
"ir|iR", "", "Relocs",
|
||||
"is", "", "Symbols",
|
||||
"iS ", "[entropy,sha1]", "Sections (choose which hash algorithm to use)",
|
||||
"iV", "", "Display file version info)",
|
||||
"iV", "", "Display file version info",
|
||||
"iz", "", "Strings in data sections",
|
||||
"izz", "", "Search for Strings in the whole binary",
|
||||
NULL
|
||||
|
@ -573,6 +573,7 @@ R_API char *r_str_escape_dot(const char *buf);
|
||||
R_API void r_str_uri_decode(char *buf);
|
||||
R_API char *r_str_uri_encode (const char *buf);
|
||||
R_API char *r_str_utf16_decode (const ut8 *s, int len);
|
||||
R_API int r_str_utf16_to_utf8 (ut8 *dst, int len_dst, const ut8 *src, int len_src, int little_endian);
|
||||
R_API char *r_str_utf16_encode (const char *s, int len);
|
||||
R_API char *r_str_home(const char *str);
|
||||
R_API int r_str_nlen (const char *s, int n);
|
||||
|
@ -1547,6 +1547,74 @@ R_API char *r_str_uri_encode (const char *s) {
|
||||
return realloc (od, strlen (od)+1); // FIT
|
||||
}
|
||||
|
||||
R_API int r_str_utf16_to_utf8 (ut8 *dst, int len_dst, const ut8 *src, int len_src, int little_endian) {
|
||||
ut8 *outstart = dst;
|
||||
const ut8 *processed = src;
|
||||
ut8 *outend = dst + len_dst;
|
||||
ut16 *in = (ut16*)src;
|
||||
ut16 *inend;
|
||||
ut32 c, d, inlen;
|
||||
ut8 *tmp;
|
||||
int bits;
|
||||
|
||||
if ((len_src % 2) == 1)
|
||||
len_src--;
|
||||
inlen = len_src / 2;
|
||||
inend = in + inlen;
|
||||
while ((in < inend) && (dst - outstart + 5 < len_dst)) {
|
||||
if (little_endian) {
|
||||
c= *in++;
|
||||
} else {
|
||||
tmp = (ut8*) in;
|
||||
c = *tmp++;
|
||||
c = c | (((ut32)*tmp) << 8);
|
||||
in++;
|
||||
}
|
||||
if ((c & 0xFC00) == 0xD800) { /* surrogates */
|
||||
if (in >= inend) { /* (in > inend) shouldn't happens */
|
||||
break;
|
||||
}
|
||||
if (little_endian) {
|
||||
d = *in++;
|
||||
} else {
|
||||
tmp = (ut8*) in;
|
||||
d = *tmp++;
|
||||
d = d | (((ut32)*tmp) << 8);
|
||||
in++;
|
||||
}
|
||||
if ((d & 0xFC00) == 0xDC00) {
|
||||
c &= 0x03FF;
|
||||
c <<= 10;
|
||||
c |= d & 0x03FF;
|
||||
c += 0x10000;
|
||||
}
|
||||
else {
|
||||
len_dst = dst - outstart;
|
||||
len_src = processed - src;
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
|
||||
/* assertion: c is a single UTF-4 value */
|
||||
if (dst >= outend)
|
||||
break;
|
||||
|
||||
if (c < 0x80) { *dst++ = c; bits= -6; }
|
||||
else if (c < 0x800) { *dst++ = ((c >> 6) & 0x1F) | 0xC0; bits = 0; }
|
||||
else if (c < 0x10000) { *dst++ = ((c >> 12) & 0x0F) | 0xE0; bits = 6; }
|
||||
else { *dst++ = ((c >> 18) & 0x07) | 0xF0; bits = 12; }
|
||||
|
||||
for (; bits >= 0; bits-= 6) {
|
||||
if (dst >= outend)
|
||||
break;
|
||||
*dst++ = ((c >> bits) & 0x3F) | 0x80;
|
||||
}
|
||||
processed = (const unsigned char*) in;
|
||||
}
|
||||
len_dst = dst - outstart;
|
||||
return len_dst;
|
||||
}
|
||||
|
||||
R_API char *r_str_utf16_decode (const ut8 *s, int len) {
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
|
Loading…
Reference in New Issue
Block a user