mirror of
https://github.com/radareorg/radare2.git
synced 2024-12-01 09:00:46 +00:00
Improve Xcode symbols parser ##bin
By abstracting the underlying CoreSymbolication element.
This commit is contained in:
parent
8903071055
commit
8e8cce50b4
374
libr/bin/format/mach0/coresymbolication.c
Normal file
374
libr/bin/format/mach0/coresymbolication.c
Normal file
@ -0,0 +1,374 @@
|
||||
/* radare - LGPL - Copyright 2020 - mrmacete */
|
||||
|
||||
#include <r_types.h>
|
||||
#include <r_util.h>
|
||||
#include <r_hash.h>
|
||||
#include "coresymbolication.h"
|
||||
|
||||
#define R_CS_EL_OFF_SEGS 0x58
|
||||
#define R_CS_EL_SIZE_SEG 0x20
|
||||
#define R_CS_EL_SIZE_SECT_64 0x18
|
||||
#define R_CS_EL_SIZE_SECT_32 0x10
|
||||
#define R_CS_EL_SIZE_SYM 0x18
|
||||
#define R_CS_EL_SIZE_LSYM 0x24
|
||||
#define R_CS_EL_SIZE_LINFO 0x14
|
||||
|
||||
static RCoreSymCacheElementHdr *r_coresym_cache_element_header_new(RBuffer *buf, size_t off, int bits) {
|
||||
RCoreSymCacheElementHdr *hdr = R_NEW0 (RCoreSymCacheElementHdr);
|
||||
if (hdr && r_buf_fread_at (buf, off, (ut8 *)hdr, "13i16c5i", 1) == sizeof (RCoreSymCacheElementHdr)) {
|
||||
return hdr;
|
||||
}
|
||||
free (hdr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void r_coresym_cache_element_segment_fini(RCoreSymCacheElementSegment *seg) {
|
||||
if (seg) {
|
||||
free (seg->name);
|
||||
}
|
||||
}
|
||||
|
||||
static void r_coresym_cache_element_section_fini(RCoreSymCacheElementSection *sec) {
|
||||
if (sec) {
|
||||
free (sec->name);
|
||||
}
|
||||
}
|
||||
|
||||
static void r_coresym_cache_element_flc_fini(RCoreSymCacheElementFLC *flc) {
|
||||
if (flc) {
|
||||
free (flc->file);
|
||||
}
|
||||
}
|
||||
|
||||
static void r_coresym_cache_element_symbol_fini(RCoreSymCacheElementSymbol *sym) {
|
||||
if (sym) {
|
||||
free (sym->name);
|
||||
free (sym->mangled_name);
|
||||
}
|
||||
}
|
||||
|
||||
static void r_coresym_cache_element_lined_symbol_fini(RCoreSymCacheElementLinedSymbol *sym) {
|
||||
if (sym) {
|
||||
r_coresym_cache_element_symbol_fini (&sym->sym);
|
||||
r_coresym_cache_element_flc_fini (&sym->flc);
|
||||
}
|
||||
}
|
||||
|
||||
static void r_coresym_cache_element_line_info_fini(RCoreSymCacheElementLineInfo *line) {
|
||||
if (line) {
|
||||
r_coresym_cache_element_flc_fini (&line->flc);
|
||||
}
|
||||
}
|
||||
|
||||
void r_coresym_cache_element_free(RCoreSymCacheElement *element) {
|
||||
if (!element) {
|
||||
return;
|
||||
}
|
||||
size_t i;
|
||||
if (element->segments) {
|
||||
for (i = 0; i < element->hdr->n_segments; i++) {
|
||||
r_coresym_cache_element_segment_fini (&element->segments[i]);
|
||||
}
|
||||
}
|
||||
if (element->sections) {
|
||||
for (i = 0; i < element->hdr->n_sections; i++) {
|
||||
r_coresym_cache_element_section_fini (&element->sections[i]);
|
||||
}
|
||||
}
|
||||
if (element->symbols) {
|
||||
for (i = 0; i < element->hdr->n_symbols; i++) {
|
||||
r_coresym_cache_element_symbol_fini (&element->symbols[i]);
|
||||
}
|
||||
}
|
||||
if (element->lined_symbols) {
|
||||
for (i = 0; i < element->hdr->n_lined_symbols; i++) {
|
||||
r_coresym_cache_element_lined_symbol_fini (&element->lined_symbols[i]);
|
||||
}
|
||||
}
|
||||
if (element->line_info) {
|
||||
for (i = 0; i < element->hdr->n_line_info; i++) {
|
||||
r_coresym_cache_element_line_info_fini (&element->line_info[i]);
|
||||
}
|
||||
}
|
||||
free (element->segments);
|
||||
free (element->sections);
|
||||
free (element->symbols);
|
||||
free (element->lined_symbols);
|
||||
free (element->line_info);
|
||||
free (element->hdr);
|
||||
free (element->file_name);
|
||||
free (element->binary_version);
|
||||
free (element);
|
||||
}
|
||||
|
||||
ut64 r_coresym_cache_element_pa2va(RCoreSymCacheElement *element, ut64 pa) {
|
||||
size_t i;
|
||||
for (i = 0; i < element->hdr->n_segments; i++) {
|
||||
RCoreSymCacheElementSegment *seg = &element->segments[i];
|
||||
if (seg->size == 0) {
|
||||
continue;
|
||||
}
|
||||
if (seg->paddr < pa && pa < seg->paddr + seg->size) {
|
||||
return pa - seg->paddr + seg->vaddr;
|
||||
}
|
||||
}
|
||||
return pa;
|
||||
}
|
||||
|
||||
static void meta_add_fileline(RBinFile *bf, ut64 vaddr, ut32 size, RCoreSymCacheElementFLC *flc) {
|
||||
Sdb *s = bf->sdb_addrinfo;
|
||||
if (!s) {
|
||||
return;
|
||||
}
|
||||
char aoffset[64];
|
||||
ut64 cursor = vaddr;
|
||||
ut64 end = cursor + R_MAX (size, 1);
|
||||
char *fileline = r_str_newf ("%s:%d", flc->file, flc->line);
|
||||
while (cursor < end) {
|
||||
char *aoffsetptr = sdb_itoa (cursor, aoffset, 16);
|
||||
if (!aoffsetptr) {
|
||||
break;
|
||||
}
|
||||
sdb_set (s, aoffsetptr, fileline, 0);
|
||||
sdb_set (s, fileline, aoffsetptr, 0);
|
||||
cursor += 2;
|
||||
}
|
||||
free (fileline);
|
||||
}
|
||||
|
||||
static char *str_dup_safe(const ut8 *b, const ut8 *str, const ut8 *end) {
|
||||
if (str >= b && str < end) {
|
||||
int len = r_str_nlen ((const char *)str, end - str);
|
||||
if (len) {
|
||||
return r_str_ndup ((const char *)str, len);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static char *str_dup_safe_fixed(const ut8 *b, const ut8 *str, ut64 len, const ut8 *end) {
|
||||
if (str >= b && str + len < end) {
|
||||
char *result = calloc (1, len + 1);
|
||||
if (result) {
|
||||
r_str_ncpy (result, (const char *)str, len);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
RCoreSymCacheElement *r_coresym_cache_element_new(RBinFile *bf, RBuffer *buf, ut64 off, int bits) {
|
||||
RCoreSymCacheElement *result = NULL;
|
||||
ut8 *b = NULL;
|
||||
RCoreSymCacheElementHdr *hdr = r_coresym_cache_element_header_new (buf, off, bits);
|
||||
if (!hdr) {
|
||||
return NULL;
|
||||
}
|
||||
if (hdr->version != 1) {
|
||||
eprintf ("Unsupported CoreSymbolication cache version (%d)\n", hdr->version);
|
||||
goto beach;
|
||||
}
|
||||
if (hdr->size == 0 || hdr->size > r_buf_size (buf) - off) {
|
||||
eprintf ("Corrupted CoreSymbolication header: size out of bounds (0x%x)\n", hdr->size);
|
||||
goto beach;
|
||||
}
|
||||
result = R_NEW0 (RCoreSymCacheElement);
|
||||
if (!result) {
|
||||
goto beach;
|
||||
}
|
||||
result->hdr = hdr;
|
||||
b = malloc (hdr->size);
|
||||
if (!b) {
|
||||
goto beach;
|
||||
}
|
||||
if (r_buf_read_at (buf, off, b, hdr->size) != hdr->size) {
|
||||
goto beach;
|
||||
}
|
||||
ut8 *end = b + hdr->size;
|
||||
if (hdr->file_name_off) {
|
||||
result->file_name = str_dup_safe (b, b + (size_t)hdr->file_name_off, end);
|
||||
}
|
||||
if (hdr->version_off) {
|
||||
result->binary_version = str_dup_safe (b, b + (size_t)hdr->version_off, end);
|
||||
}
|
||||
const size_t word_size = bits / 8;
|
||||
ut64 page_zero_size = 0;
|
||||
size_t page_zero_idx = 0;
|
||||
if (hdr->n_segments > 0) {
|
||||
result->segments = R_NEWS0 (RCoreSymCacheElementSegment, hdr->n_segments);
|
||||
if (!result->segments) {
|
||||
goto beach;
|
||||
}
|
||||
size_t i;
|
||||
ut8 *cursor = b + R_CS_EL_OFF_SEGS;
|
||||
for (i = 0; i < hdr->n_segments && cursor < end; i++) {
|
||||
RCoreSymCacheElementSegment *seg = &result->segments[i];
|
||||
seg->paddr = seg->vaddr = r_read_le64 (cursor);
|
||||
cursor += 8;
|
||||
if (cursor >= end) {
|
||||
break;
|
||||
}
|
||||
seg->size = seg->vsize = r_read_le64 (cursor);
|
||||
cursor += 8;
|
||||
if (cursor >= end) {
|
||||
break;
|
||||
}
|
||||
seg->name = str_dup_safe_fixed (b, cursor, 16, end);
|
||||
cursor += 16;
|
||||
if (!seg->name) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!strcmp (seg->name, "__PAGEZERO")) {
|
||||
page_zero_size = seg->size;
|
||||
page_zero_idx = i;
|
||||
seg->paddr = seg->vaddr = 0;
|
||||
seg->size = 0;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < hdr->n_segments && page_zero_size > 0; i++) {
|
||||
if (i == page_zero_idx) {
|
||||
continue;
|
||||
}
|
||||
RCoreSymCacheElementSegment *seg = &result->segments[i];
|
||||
if (seg->vaddr < page_zero_size) {
|
||||
seg->vaddr += page_zero_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
const ut64 start_of_sections = (ut64)hdr->n_segments * R_CS_EL_SIZE_SEG + R_CS_EL_OFF_SEGS;
|
||||
if (hdr->n_sections > 0) {
|
||||
result->sections = R_NEWS0 (RCoreSymCacheElementSection, hdr->n_sections);
|
||||
if (!result->sections) {
|
||||
goto beach;
|
||||
}
|
||||
size_t i;
|
||||
ut8 *cursor = b + start_of_sections;
|
||||
for (i = 0; i < hdr->n_sections && cursor < end; i++) {
|
||||
ut8 *sect_start = cursor;
|
||||
RCoreSymCacheElementSection *sect = &result->sections[i];
|
||||
sect->vaddr = sect->paddr = r_read_ble (cursor, false, bits);
|
||||
if (sect->vaddr < page_zero_size) {
|
||||
sect->vaddr += page_zero_size;
|
||||
}
|
||||
cursor += word_size;
|
||||
if (cursor >= end) {
|
||||
break;
|
||||
}
|
||||
sect->size = r_read_ble (cursor, false, bits);
|
||||
cursor += word_size;
|
||||
if (cursor >= end) {
|
||||
break;
|
||||
}
|
||||
ut64 sect_name_off = r_read_ble (cursor, false, bits);
|
||||
cursor += word_size;
|
||||
if (bits == 32) {
|
||||
cursor += word_size;
|
||||
}
|
||||
sect->name = str_dup_safe (b, sect_start + (size_t)sect_name_off, end);
|
||||
}
|
||||
}
|
||||
const ut64 sect_size = (bits == 32) ? R_CS_EL_SIZE_SECT_32 : R_CS_EL_SIZE_SECT_64;
|
||||
const ut64 start_of_symbols = start_of_sections + (ut64)hdr->n_sections * sect_size;
|
||||
if (hdr->n_symbols) {
|
||||
result->symbols = R_NEWS0 (RCoreSymCacheElementSymbol, hdr->n_symbols);
|
||||
if (!result->symbols) {
|
||||
goto beach;
|
||||
}
|
||||
size_t i;
|
||||
ut8 *cursor = b + start_of_symbols;
|
||||
for (i = 0; i < hdr->n_symbols && cursor + R_CS_EL_SIZE_SYM <= end; i++) {
|
||||
RCoreSymCacheElementSymbol *sym = &result->symbols[i];
|
||||
sym->paddr = r_read_le32 (cursor);
|
||||
sym->size = r_read_le32 (cursor + 0x4);
|
||||
sym->unk1 = r_read_le32 (cursor + 0x8);
|
||||
size_t name_off = r_read_le32 (cursor + 0xc);
|
||||
size_t mangled_name_off = r_read_le32 (cursor + 0x10);
|
||||
sym->unk2 = (st32)r_read_le32 (cursor + 0x14);
|
||||
sym->name = str_dup_safe (b, cursor + name_off, end);
|
||||
if (!sym->name) {
|
||||
cursor += R_CS_EL_SIZE_SYM;
|
||||
continue;
|
||||
}
|
||||
sym->mangled_name = str_dup_safe (b, cursor + mangled_name_off, end);
|
||||
if (!sym->mangled_name) {
|
||||
cursor += R_CS_EL_SIZE_SYM;
|
||||
continue;
|
||||
}
|
||||
cursor += R_CS_EL_SIZE_SYM;
|
||||
}
|
||||
}
|
||||
const ut64 start_of_lined_symbols = start_of_symbols + (ut64)hdr->n_symbols * R_CS_EL_SIZE_SYM;
|
||||
if (hdr->n_lined_symbols) {
|
||||
result->lined_symbols = R_NEWS0 (RCoreSymCacheElementLinedSymbol, hdr->n_lined_symbols);
|
||||
if (!result->lined_symbols) {
|
||||
goto beach;
|
||||
}
|
||||
size_t i;
|
||||
ut8 *cursor = b + start_of_lined_symbols;
|
||||
for (i = 0; i < hdr->n_lined_symbols && cursor + R_CS_EL_SIZE_LSYM <= end; i++) {
|
||||
RCoreSymCacheElementLinedSymbol *lsym = &result->lined_symbols[i];
|
||||
lsym->sym.paddr = r_read_le32 (cursor);
|
||||
lsym->sym.size = r_read_le32 (cursor + 0x4);
|
||||
lsym->sym.unk1 = r_read_le32 (cursor + 0x8);
|
||||
size_t name_off = r_read_le32 (cursor + 0xc);
|
||||
size_t mangled_name_off = r_read_le32 (cursor + 0x10);
|
||||
lsym->sym.unk2 = (st32)r_read_le32 (cursor + 0x14);
|
||||
size_t file_name_off = r_read_le32 (cursor + 0x18);
|
||||
lsym->flc.line = r_read_le32 (cursor + 0x1c);
|
||||
lsym->flc.col = r_read_le32 (cursor + 0x20);
|
||||
lsym->sym.name = str_dup_safe (b, cursor + name_off, end);
|
||||
if (!lsym->sym.name) {
|
||||
cursor += R_CS_EL_SIZE_LSYM;
|
||||
continue;
|
||||
}
|
||||
lsym->sym.mangled_name = str_dup_safe (b, cursor + mangled_name_off, end);
|
||||
if (!lsym->sym.mangled_name) {
|
||||
cursor += R_CS_EL_SIZE_LSYM;
|
||||
continue;
|
||||
}
|
||||
lsym->flc.file = str_dup_safe (b, cursor + file_name_off, end);
|
||||
if (!lsym->flc.file) {
|
||||
cursor += R_CS_EL_SIZE_LSYM;
|
||||
continue;
|
||||
}
|
||||
cursor += R_CS_EL_SIZE_LSYM;
|
||||
meta_add_fileline (bf, r_coresym_cache_element_pa2va (result, lsym->sym.paddr), lsym->sym.size, &lsym->flc);
|
||||
}
|
||||
}
|
||||
const ut64 start_of_line_info = start_of_lined_symbols + (ut64)hdr->n_lined_symbols * R_CS_EL_SIZE_LSYM;
|
||||
if (hdr->n_line_info) {
|
||||
result->line_info = R_NEWS0 (RCoreSymCacheElementLineInfo, hdr->n_line_info);
|
||||
if (!result->line_info) {
|
||||
goto beach;
|
||||
}
|
||||
size_t i;
|
||||
ut8 *cursor = b + start_of_line_info;
|
||||
for (i = 0; i < hdr->n_line_info && cursor + R_CS_EL_SIZE_LINFO <= end; i++) {
|
||||
RCoreSymCacheElementLineInfo *info = &result->line_info[i];
|
||||
info->paddr = r_read_le32 (cursor);
|
||||
info->size = r_read_le32 (cursor + 4);
|
||||
size_t file_name_off = r_read_le32 (cursor + 8);
|
||||
info->flc.line = r_read_le32 (cursor + 0xc);
|
||||
info->flc.col = r_read_le32 (cursor + 0x10);
|
||||
info->flc.file = str_dup_safe (b, cursor + file_name_off, end);
|
||||
if (!info->flc.file) {
|
||||
break;
|
||||
}
|
||||
cursor += R_CS_EL_SIZE_LINFO;
|
||||
meta_add_fileline (bf, r_coresym_cache_element_pa2va (result, info->paddr), info->size, &info->flc);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO:
|
||||
* Figure out the meaning of the 2 arrays of hdr->n_symbols
|
||||
* 32-bit integers located at the end of line info.
|
||||
* Those are the last info before the strings at the end.
|
||||
*/
|
||||
|
||||
beach:
|
||||
free (b);
|
||||
return result;
|
||||
}
|
||||
|
85
libr/bin/format/mach0/coresymbolication.h
Normal file
85
libr/bin/format/mach0/coresymbolication.h
Normal file
@ -0,0 +1,85 @@
|
||||
#include <r_bin.h>
|
||||
#include <r_types.h>
|
||||
|
||||
#ifndef _INCLUDE_R_BIN_CORESYMBOLICATION_H
|
||||
#define _INCLUDE_R_BIN_CORESYMBOLICATION_H
|
||||
|
||||
typedef struct r_coresym_cache_element_hdr_t {
|
||||
ut32 version;
|
||||
ut32 size;
|
||||
ut32 n_segments;
|
||||
ut32 n_sections;
|
||||
ut32 n_symbols;
|
||||
ut32 n_lined_symbols;
|
||||
ut32 n_line_info;
|
||||
ut32 f;
|
||||
ut32 g;
|
||||
ut32 h;
|
||||
ut32 file_name_off;
|
||||
ut32 version_off;
|
||||
ut32 k;
|
||||
ut8 uuid[16];
|
||||
ut32 cputype;
|
||||
ut32 cpusubtype;
|
||||
ut32 o;
|
||||
ut32 strings_off;
|
||||
ut32 p;
|
||||
} RCoreSymCacheElementHdr;
|
||||
|
||||
typedef struct r_coresym_cache_element_segment_t {
|
||||
ut64 paddr;
|
||||
ut64 vaddr;
|
||||
ut64 size;
|
||||
ut64 vsize;
|
||||
char *name;
|
||||
} RCoreSymCacheElementSegment;
|
||||
|
||||
typedef struct r_coresym_cache_element_section_t {
|
||||
ut64 paddr;
|
||||
ut64 vaddr;
|
||||
ut64 size;
|
||||
char *name;
|
||||
} RCoreSymCacheElementSection;
|
||||
|
||||
typedef struct r_coresym_cache_element_flc_t {
|
||||
char *file;
|
||||
ut32 line;
|
||||
ut32 col;
|
||||
} RCoreSymCacheElementFLC;
|
||||
|
||||
typedef struct r_coresym_cache_element_line_info_t {
|
||||
ut32 paddr;
|
||||
ut32 size;
|
||||
RCoreSymCacheElementFLC flc;
|
||||
} RCoreSymCacheElementLineInfo;
|
||||
|
||||
typedef struct r_coresym_cache_element_symbol_t {
|
||||
ut32 paddr;
|
||||
ut32 size;
|
||||
ut32 unk1;
|
||||
char *name;
|
||||
char *mangled_name;
|
||||
st32 unk2;
|
||||
} RCoreSymCacheElementSymbol;
|
||||
|
||||
typedef struct r_coresym_cache_element_lined_symbol_t {
|
||||
RCoreSymCacheElementSymbol sym;
|
||||
RCoreSymCacheElementFLC flc;
|
||||
} RCoreSymCacheElementLinedSymbol;
|
||||
|
||||
typedef struct r_coresym_cache_element_t {
|
||||
RCoreSymCacheElementHdr *hdr;
|
||||
char *file_name;
|
||||
char *binary_version;
|
||||
RCoreSymCacheElementSegment *segments;
|
||||
RCoreSymCacheElementSection *sections;
|
||||
RCoreSymCacheElementSymbol *symbols;
|
||||
RCoreSymCacheElementLinedSymbol *lined_symbols;
|
||||
RCoreSymCacheElementLineInfo *line_info;
|
||||
} RCoreSymCacheElement;
|
||||
|
||||
R_API RCoreSymCacheElement *r_coresym_cache_element_new(RBinFile *bf, RBuffer *buf, ut64 off, int bits);
|
||||
R_API void r_coresym_cache_element_free(RCoreSymCacheElement *element);
|
||||
R_API ut64 r_coresym_cache_element_pa2va(RCoreSymCacheElement *element, ut64 pa);
|
||||
|
||||
#endif
|
@ -57,6 +57,7 @@ r_bin_sources = [
|
||||
'p/bin_smd.c',
|
||||
'p/bin_sms.c',
|
||||
'p/bin_spc700.c',
|
||||
'p/bin_symbols.c',
|
||||
'p/bin_te.c',
|
||||
'p/bin_vsf.c',
|
||||
'p/bin_wasm.c',
|
||||
@ -84,6 +85,7 @@ r_bin_sources = [
|
||||
'format/elf/elf64.c',
|
||||
'format/elf/elf64_write.c',
|
||||
'format/elf/elf_write.c',
|
||||
'format/mach0/coresymbolication.c',
|
||||
'format/mach0/dyldcache.c',
|
||||
'format/mach0/fatmach0.c',
|
||||
'format/mach0/mach0.c',
|
||||
|
@ -4,20 +4,13 @@
|
||||
#include <r_util.h>
|
||||
#include <r_lib.h>
|
||||
#include <r_bin.h>
|
||||
#include <sdb/ht_uu.h>
|
||||
#include "../i/private.h"
|
||||
#include "mach0/coresymbolication.h"
|
||||
|
||||
// enable debugging messages
|
||||
#define D if (0)
|
||||
|
||||
static bool is64 = false;
|
||||
static ut64 dwordsBeginAt = UT64_MAX;
|
||||
static ut64 stringsBeginAt = UT64_MAX;
|
||||
static ut64 symbolsBeginAt = UT64_MAX;
|
||||
// static ut64 symbolsCount = UT64_MAX;
|
||||
static RList *globalSymbols = NULL;
|
||||
|
||||
#define SECTIONS_BEGIN 0x220
|
||||
#define SEGMENTS_BEGIN 0x1b0
|
||||
#define R_UUID_LENGTH 33
|
||||
|
||||
typedef struct symbols_header_t {
|
||||
ut32 magic;
|
||||
@ -31,6 +24,21 @@ typedef struct symbols_header_t {
|
||||
int size;
|
||||
} SymbolsHeader;
|
||||
|
||||
typedef struct symbols_metadata_t { // 0x40
|
||||
ut32 cputype;
|
||||
ut32 subtype;
|
||||
ut32 n_segments;
|
||||
ut32 namelen;
|
||||
ut32 name;
|
||||
bool valid;
|
||||
ut32 size;
|
||||
//RList *segments;
|
||||
ut32 addr;
|
||||
int bits;
|
||||
const char *arch;
|
||||
const char *cpu;
|
||||
} SymbolsMetadata;
|
||||
|
||||
// header starts at offset 0 and ends at offset 0x40
|
||||
static SymbolsHeader parseHeader(RBuffer *buf) {
|
||||
ut8 b[64];
|
||||
@ -50,65 +58,6 @@ static SymbolsHeader parseHeader(RBuffer *buf) {
|
||||
return sh;
|
||||
}
|
||||
|
||||
typedef struct symbols_metadata_t { // 0x40
|
||||
ut32 cputype;
|
||||
ut32 subtype;
|
||||
ut32 n_segments;
|
||||
ut32 namelen;
|
||||
ut32 name;
|
||||
bool valid;
|
||||
ut32 size;
|
||||
RList *segments;
|
||||
ut32 addr;
|
||||
int bits;
|
||||
const char *arch;
|
||||
const char *cpu;
|
||||
} SymbolsMetadata;
|
||||
|
||||
// this is_segment concept is a bad idea imho
|
||||
static RBinSection *newSection(const char *name, ut32 from, ut32 to, bool is_segment) {
|
||||
RBinSection *s = R_NEW0 (RBinSection);
|
||||
if (!s) {
|
||||
return NULL;
|
||||
}
|
||||
s->name = strdup (name);
|
||||
s->size = to - from + 1;
|
||||
s->vsize = s->size;
|
||||
s->paddr = from;
|
||||
s->vaddr = from;
|
||||
s->add = true;
|
||||
s->perm = strstr (name, "TEXT")? 5: 4;
|
||||
s->is_segment = is_segment;
|
||||
return s;
|
||||
}
|
||||
|
||||
static RList *parseSegments(RBuffer *buf, int off, int count) {
|
||||
ut8 *b = calloc (count, 32);
|
||||
(void)r_buf_read_at (buf, off, b, count * 32);
|
||||
int x = off;
|
||||
int X = 0;
|
||||
int i;
|
||||
RList *segments = r_list_newf ((RListFree)r_bin_section_free);
|
||||
if (!segments) {
|
||||
return NULL;
|
||||
}
|
||||
// eprintf ("Segments: %d\n", count);
|
||||
for (i = 0; i < count; i++) {
|
||||
int A = r_read_le32 (b + X + 16);
|
||||
int B = r_read_le32 (b + X + 16 + 8);
|
||||
// eprintf ("0x%08x segment 0x%08x 0x%08x %s\n",
|
||||
// x, A, A + B, b + X);
|
||||
const char *cname = (const char *)(b + X);
|
||||
char *name = r_str_ndup (cname, r_str_nlen (cname, 16));
|
||||
RBinSection *section = newSection (name, A, A + B, true);
|
||||
free (name);
|
||||
r_list_append (segments, section);
|
||||
x += 32;
|
||||
X += 32;
|
||||
}
|
||||
return segments;
|
||||
}
|
||||
|
||||
static const char *typeString(ut32 n, int *bits) {
|
||||
*bits = 32;
|
||||
if (n == 12) { // CPU_SUBTYPE_ARM_V7) {
|
||||
@ -116,12 +65,10 @@ static const char *typeString(ut32 n, int *bits) {
|
||||
}
|
||||
if (n == 0x0100000c) { // arm64
|
||||
*bits = 64;
|
||||
is64 = true;
|
||||
return "arm";
|
||||
}
|
||||
if (n == 0x0200000c) { // arm64-32
|
||||
// TODO: must change bits
|
||||
is64 = false;
|
||||
*bits = 64;
|
||||
return "arm";
|
||||
}
|
||||
@ -155,14 +102,14 @@ static SymbolsMetadata parseMetadata(RBuffer *buf, int off) {
|
||||
// eprintf ("0x%08x strlen %d\n", 0x4c, sm.namelen);
|
||||
// eprintf ("0x%08x filename %s\n", 0x50, b + 16);
|
||||
int delta = 16;
|
||||
sm.segments = parseSegments (buf, off + sm.namelen + delta, sm.n_segments);
|
||||
sm.size = (sm.n_segments * 32) + 120;
|
||||
//sm.segments = parseSegments (buf, off + sm.namelen + delta, sm.n_segments);
|
||||
sm.size = (sm.n_segments * 32) + sm.namelen + delta;
|
||||
|
||||
// hack to detect format
|
||||
ut32 nm, nm2, nm3;
|
||||
r_buf_read_at (buf, off + sm.size, (ut8*)&nm, sizeof (nm));
|
||||
r_buf_read_at (buf, off + sm.size + 4, (ut8*)&nm2, sizeof (nm2));
|
||||
r_buf_read_at (buf, off + sm.size + 8, (ut8*)&nm3, sizeof (nm3));
|
||||
r_buf_read_at (buf, off + sm.size, (ut8 *)&nm, sizeof (nm));
|
||||
r_buf_read_at (buf, off + sm.size + 4, (ut8 *)&nm2, sizeof (nm2));
|
||||
r_buf_read_at (buf, off + sm.size + 8, (ut8 *)&nm3, sizeof (nm3));
|
||||
// eprintf ("0x%x next %x %x %x\n", off + sm.size, nm, nm2, nm3);
|
||||
if (r_read_le32 (&nm3) != 0xa1b22b1a) {
|
||||
sm.size -= 8;
|
||||
@ -171,8 +118,6 @@ static SymbolsMetadata parseMetadata(RBuffer *buf, int off) {
|
||||
return sm;
|
||||
}
|
||||
|
||||
#define O(x, y) x.addr + r_offsetof (x, y)
|
||||
|
||||
static void printSymbolsHeader(SymbolsHeader sh) {
|
||||
// eprintf ("0x%08x version 0x%x\n", 4, sh.version);
|
||||
eprintf ("0x%08x uuid ", 24);
|
||||
@ -187,85 +132,85 @@ static void printSymbolsHeader(SymbolsHeader sh) {
|
||||
// eprintf ("0x%08x slotsize %d\n", 0x2e, sh.slotsize); // r_read_le16 (b+ 0x2e));
|
||||
}
|
||||
|
||||
static RList *parseStrings(RBuffer *buf, int string_section, int string_section_end) {
|
||||
int sss = string_section_end + string_section;
|
||||
if (sss < 1) {
|
||||
static RBinSection *bin_section_from_section(RCoreSymCacheElementSection *sect) {
|
||||
if (!sect->name) {
|
||||
return NULL;
|
||||
}
|
||||
char *b = calloc (1, sss);
|
||||
if (!b) {
|
||||
RBinSection *s = R_NEW0 (RBinSection);
|
||||
if (!s) {
|
||||
return NULL;
|
||||
}
|
||||
int o = 0;
|
||||
char *s = b;
|
||||
char *os = s;
|
||||
int nstrings = 0;
|
||||
|
||||
int available = r_buf_read_at (buf, string_section, (ut8 *)b, sss);
|
||||
if (available != sss) {
|
||||
sss = available;
|
||||
}
|
||||
if (sss < 1) {
|
||||
eprintf ("Cannot read strings at 0x%08" PFMT64x "\n", (ut64)string_section);
|
||||
free (b);
|
||||
return NULL;
|
||||
}
|
||||
RList *res = r_list_newf ((RListFree)r_bin_string_free);
|
||||
int i;
|
||||
char *s_end = s + sss;
|
||||
for (i = 0; true; i++) {
|
||||
o = s - os;
|
||||
if (string_section + o + 8 > string_section_end) {
|
||||
break;
|
||||
}
|
||||
if (s + 4 > s_end) {
|
||||
break;
|
||||
}
|
||||
nstrings++;
|
||||
// eprintf ("0x%08x 0x%08x %s\n", o + string_section, o, s);
|
||||
RBinString *bs = R_NEW0 (RBinString);
|
||||
if (!bs) {
|
||||
break;
|
||||
}
|
||||
bs->string = strdup (s);
|
||||
// eprintf ("%s\n", s);
|
||||
bs->vaddr = o + string_section;
|
||||
bs->paddr = o + string_section;
|
||||
bs->ordinal = i;
|
||||
bs->length = strlen (s);
|
||||
r_list_append (res, bs);
|
||||
s += bs->length + 1;
|
||||
}
|
||||
free (b);
|
||||
return res;
|
||||
s->name = r_str_ndup (sect->name, 256);
|
||||
s->size = sect->size;
|
||||
s->vsize = s->size;
|
||||
s->paddr = sect->paddr;
|
||||
s->vaddr = sect->vaddr;
|
||||
s->add = true;
|
||||
s->perm = strstr (s->name, "TEXT") ? 5 : 4;
|
||||
s->is_segment = false;
|
||||
return s;
|
||||
}
|
||||
|
||||
typedef struct symbols_dragons_t {
|
||||
int foo;
|
||||
ut32 addr;
|
||||
ut32 size;
|
||||
ut32 n_sections;
|
||||
ut32 n_segments;
|
||||
ut32 n_symbols;
|
||||
} SymbolsDragons;
|
||||
static RBinSection *bin_section_from_segment(RCoreSymCacheElementSegment *seg) {
|
||||
if (!seg->name) {
|
||||
return NULL;
|
||||
}
|
||||
RBinSection *s = R_NEW0 (RBinSection);
|
||||
if (!s) {
|
||||
return NULL;
|
||||
}
|
||||
s->name = r_str_ndup (seg->name, 16);
|
||||
s->size = seg->size;
|
||||
s->vsize = seg->vsize;
|
||||
s->paddr = seg->paddr;
|
||||
s->vaddr = seg->vaddr;
|
||||
s->add = true;
|
||||
s->perm = strstr (s->name, "TEXT") ? 5 : 4;
|
||||
s->is_segment = true;
|
||||
return s;
|
||||
}
|
||||
|
||||
static SymbolsDragons parseDragons(RBuffer *buf, int off, int bits) {
|
||||
SymbolsDragons sd = { 0 };
|
||||
sd.addr = off;
|
||||
sd.size = 1;
|
||||
static RBinSymbol *bin_symbol_from_symbol(RCoreSymCacheElement *element, RCoreSymCacheElementSymbol *s) {
|
||||
if (!s->name && !s->mangled_name) {
|
||||
return NULL;
|
||||
}
|
||||
RBinSymbol *sym = R_NEW0 (RBinSymbol);
|
||||
if (sym) {
|
||||
if (s->name && s->mangled_name) {
|
||||
sym->dname = strdup (s->name);
|
||||
sym->name = strdup (s->mangled_name);
|
||||
} else if (s->name) {
|
||||
sym->name = strdup (s->name);
|
||||
} else if (s->mangled_name) {
|
||||
sym->name = s->mangled_name;
|
||||
}
|
||||
sym->paddr = s->paddr;
|
||||
sym->vaddr = r_coresym_cache_element_pa2va (element, s->paddr);
|
||||
sym->size = s->size;
|
||||
sym->type = R_BIN_TYPE_FUNC_STR;
|
||||
sym->bind = "NONE";
|
||||
}
|
||||
return sym;
|
||||
}
|
||||
|
||||
static RCoreSymCacheElement *parseDragons(RBinFile *bf, RBuffer *buf, int off, int bits) {
|
||||
D eprintf ("Dragons at 0x%x\n", off);
|
||||
const int size = r_buf_size (buf) - off;
|
||||
if (size < 1) {
|
||||
return sd;
|
||||
ut64 size = r_buf_size (buf);
|
||||
if (off >= size) {
|
||||
return NULL;
|
||||
}
|
||||
size -= off;
|
||||
if (!size) {
|
||||
return NULL;
|
||||
}
|
||||
ut8 *b = malloc (size);
|
||||
if (!b) {
|
||||
return sd;
|
||||
return NULL;
|
||||
}
|
||||
int available = r_buf_read_at (buf, off, b, size);
|
||||
if (available != size) {
|
||||
eprintf ("Warning: r_buf_read_at failed\n");
|
||||
return sd;
|
||||
return NULL;
|
||||
}
|
||||
#if 0
|
||||
// after the list of sections, there's a bunch of unknown
|
||||
@ -302,7 +247,7 @@ static SymbolsDragons parseDragons(RBuffer *buf, int off, int bits) {
|
||||
available = r_buf_read_at (buf, off - 8, b, size);
|
||||
if (available != size) {
|
||||
eprintf ("Warning: r_buf_read_at failed\n");
|
||||
return sd;
|
||||
return NULL;
|
||||
}
|
||||
if (!memcmp ("\x1a\x2b\xb2\xa1", b, 4)) { // 0x130 ?
|
||||
off -= 8;
|
||||
@ -315,165 +260,8 @@ static SymbolsDragons parseDragons(RBuffer *buf, int off, int bits) {
|
||||
const int e0ss = r_read_le32 (b + 12);
|
||||
eprintf ("0x%08x eoss 0x%x\n", off + 12, e0ss);
|
||||
}
|
||||
sd.n_segments = r_read_le32 (b + 24);
|
||||
sd.n_sections = r_read_le32 (b + 28);
|
||||
parseSegments (buf, SEGMENTS_BEGIN, sd.n_segments);
|
||||
|
||||
sd.n_symbols = r_read_le32 (b + 0x20); // depends on nsections
|
||||
if (sd.n_symbols > 1024 * 1024) {
|
||||
eprintf ("Warning: too many symbols %d, truncated to 2048\n", sd.n_symbols);
|
||||
sd.n_symbols = 2048;
|
||||
}
|
||||
sd.addr = off;
|
||||
sd.size = 0x70 - 8; // SEGMENTS_BEGIN - off;
|
||||
sd.size += sd.n_segments * 32;
|
||||
if (is64) {
|
||||
sd.size += sd.n_sections * 24;
|
||||
} else {
|
||||
sd.size += sd.n_sections * 16;
|
||||
}
|
||||
free (b);
|
||||
return sd;
|
||||
}
|
||||
|
||||
static RBinSymbol *newSymbol(RBinString *s, ut64 addr, ut64 size) {
|
||||
RBinSymbol *sym = R_NEW0 (RBinSymbol);
|
||||
if (sym) {
|
||||
sym->name = s? s->string: NULL;
|
||||
sym->paddr = addr;
|
||||
sym->vaddr = addr;
|
||||
sym->size = size;
|
||||
sym->type = R_BIN_TYPE_FUNC_STR;
|
||||
sym->bind = "NONE";
|
||||
}
|
||||
return sym;
|
||||
}
|
||||
|
||||
static RList *parseSections(RBuffer *b, int x, int n_sections, RList *strings) {
|
||||
// eprintf ("Sections\n");
|
||||
int buf_sz = r_buf_size (b);
|
||||
char *buf = malloc (buf_sz);
|
||||
if (!buf) {
|
||||
return NULL;
|
||||
}
|
||||
bool must_free = false;
|
||||
if (!strings) {
|
||||
strings = parseStrings (b, stringsBeginAt, buf_sz);
|
||||
if (strings) {
|
||||
must_free = true;
|
||||
}
|
||||
}
|
||||
// hack
|
||||
r_buf_read_at (b, x, (ut8 *)buf, 4);
|
||||
if (buf[0] == '_') {
|
||||
x += 16;
|
||||
}
|
||||
RList *res = r_list_newf ((RListFree)r_bin_section_free);
|
||||
int i;
|
||||
r_buf_read_at (b, x, (ut8 *)buf, buf_sz);
|
||||
int off = 0;
|
||||
for (i = 0; i < n_sections; i++) {
|
||||
off = i * 16;
|
||||
if (off + 8 >= buf_sz) {
|
||||
break;
|
||||
}
|
||||
RBinString *name = strings? r_list_get_n (strings, i): NULL;
|
||||
const char *namestr = name? name->string: "";
|
||||
ut32 A = r_read_le32 (buf + off);
|
||||
ut32 B = r_read_le32 (buf + off + 4);
|
||||
//ut32 C = r_read_le32 (buf + off + 8);
|
||||
// ut32 D = r_read_le32 (buf + off + 12);
|
||||
// eprintf ("0x%08"PFMT64x" addr=0x%08x size=0x%08x unk=0x%08x zero=0x%08x %s\n",
|
||||
// (ut64)x + i + off, A, B, C, D, namestr);
|
||||
RBinSection *section = newSection (namestr, A, A + B, 0);
|
||||
r_list_append (res, section);
|
||||
}
|
||||
if (must_free) {
|
||||
r_list_free (strings);
|
||||
}
|
||||
free (buf);
|
||||
return res;
|
||||
}
|
||||
|
||||
static RList *parseSymbols(RBuffer *buf, int x, ut64 *eof, int count) {
|
||||
// eprintf ("Symbols\n");
|
||||
const int structSize = 24; // is64? 24: 24;
|
||||
if (eof) {
|
||||
*eof = x + (count * structSize);
|
||||
}
|
||||
//eprintf ("symbols table2 count %d\n", count);
|
||||
ut8 *b = calloc (structSize, count);
|
||||
if (!b) {
|
||||
return NULL;
|
||||
}
|
||||
RList *symbols = r_list_newf (r_bin_symbol_free);
|
||||
r_buf_read_at (buf, x, b, count * structSize);
|
||||
int i;
|
||||
for (i = 0; i < count; i++) {
|
||||
int n = (i * structSize);
|
||||
const ut32 A = r_read_le32 (b + n); // offset in memory
|
||||
const ut32 B = r_read_le32 (b + n + 4); // size of the symbol
|
||||
// const ut32 C = r_read_le32 (b + n + 8); // magic number 334e4051 3ce4102 34e4020 34e4000 ...
|
||||
// const ut32 D = r_read_le32 (b + n + 12);
|
||||
// const ut32 E = r_read_le32 (b + n + 16);
|
||||
// int d = D - E;
|
||||
// eprintf ("0x%08"PFMT64x" %3d addr=0x%x size=%4d magic=0x%x %d %d d=%d\n",
|
||||
// (ut64) n + x, i, A, B, C, D, E, d);
|
||||
r_list_append (symbols, newSymbol (NULL, A, B));
|
||||
}
|
||||
// eprintf ("0x%x\n", end_offset);
|
||||
free (b);
|
||||
return symbols;
|
||||
}
|
||||
|
||||
static RList *filterSymbolStrings(RList *strings, int n_sections) {
|
||||
RListIter *iter;
|
||||
RBinString *s;
|
||||
RList *list = r_list_newf (NULL);
|
||||
r_list_foreach (strings, iter, s) {
|
||||
if (*s->string != '_' && !strstr (s->string, "$$")) {
|
||||
continue;
|
||||
}
|
||||
if (strchr (s->string, ' ')) {
|
||||
continue;
|
||||
}
|
||||
r_list_append (list, newSymbol (s, 0, 0));
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
// unknown data in this range
|
||||
// are those relocs or references?
|
||||
static void parseTable3(RBuffer *buf, int x) {
|
||||
// 0x1648 - 0x1c80
|
||||
const int dword_section = dwordsBeginAt;
|
||||
int dword_section_end = stringsBeginAt;
|
||||
int i, size = dword_section_end - dword_section;
|
||||
int min = -1;
|
||||
int max = -1;
|
||||
// eprintf ("table3 is buggy\n");
|
||||
ut8 *b = calloc (size, 1);
|
||||
if (!b) {
|
||||
return;
|
||||
}
|
||||
r_buf_read_at (buf, x, b, size);
|
||||
for (i = 0; i < size; i += 8) {
|
||||
// int o = i + dword_section;
|
||||
if (i + 4 >= size) {
|
||||
eprintf ("..skip..\n");
|
||||
continue;
|
||||
}
|
||||
int v = r_read_le32 (b + i);
|
||||
// int w = r_read_le32 (b + i + 4);
|
||||
// eprintf ("0x%08x 0x%x\t0x%x = %d\n", o, v, w, v - w);
|
||||
if (min == -1 || v < min) {
|
||||
min = v;
|
||||
}
|
||||
if (max == -1 || v > max) {
|
||||
max = v;
|
||||
}
|
||||
}
|
||||
free (b);
|
||||
return r_coresym_cache_element_new (bf, buf, off + 16, bits);
|
||||
}
|
||||
|
||||
static bool load_buffer(RBinFile *bf, void **bin_obj, RBuffer *buf, ut64 loadaddr, Sdb *sdb) {
|
||||
@ -488,7 +276,7 @@ static bool load_buffer(RBinFile *bf, void **bin_obj, RBuffer *buf, ut64 loadadd
|
||||
40 2621 d85b 2100 2000 0000 0000 0000 0000
|
||||
56 ffff ffff ffff ff7f 0c00 0000 0900 0000
|
||||
72 0400 0000 6800 0000 2f76 6172 2f66 6f6c .... 4, 104 /// 104 length string
|
||||
184
|
||||
184
|
||||
0x000000b8 5f5f 5445 5854 0000 0000 0000 0000 0000 0000 0000 0000 0000 0080 0000 0000 0000 __TEXT..........................
|
||||
0x000000d8 5f5f 4441 5441 0000 0000 0000 0000 0000 0080 0000 0000 0000 0040 0000 0000 0000 __DATA...................@......
|
||||
0x000000f8 5f5f 4c4c 564d 0000 0000 0000 0000 0000 00c0 0000 0000 0000 0000 0100 0000 0000 __LLVM..........................
|
||||
@ -502,71 +290,34 @@ static bool load_buffer(RBinFile *bf, void **bin_obj, RBuffer *buf, ut64 loadadd
|
||||
return false;
|
||||
}
|
||||
printSymbolsHeader (sh);
|
||||
|
||||
// 0x40 - contain list of segments
|
||||
SymbolsMetadata sm = parseMetadata (buf, 0x40);
|
||||
|
||||
// 0x138 - 0x220 // unknown information + duplicated list of segments
|
||||
SymbolsDragons sd = parseDragons (buf, sm.addr + sm.size, sm.bits);
|
||||
// eprintf ("sections: %d\n", sd.n_sections);
|
||||
// 0x220 - 0x3a0 // table of sections
|
||||
|
||||
// 0x3a0 - 0x1648 // table of dwords with -1
|
||||
// XXX this is hacky, do not hardcode
|
||||
symbolsBeginAt = sd.addr + sd.size; // is64? 0x458: 0x3a0;
|
||||
D eprintf ("Symbols at 0x%08x\n", (ut32)symbolsBeginAt);
|
||||
RList *symbols = parseSymbols (buf, symbolsBeginAt, &dwordsBeginAt, sd.n_symbols);
|
||||
D eprintf ("Dwords at 0x%08x\n", (ut32)dwordsBeginAt);
|
||||
stringsBeginAt = dwordsBeginAt + (sd.n_symbols * 8);
|
||||
D eprintf ("Strings at 0x%08x\n", (ut32)stringsBeginAt);
|
||||
|
||||
// 0x1648 - 0x1c80 // table of dword pairs (unknown data)
|
||||
parseTable3 (buf, dwordsBeginAt);
|
||||
|
||||
// 0x1c80 - EOF // strings
|
||||
RList *strings = parseStrings (buf, stringsBeginAt, stringsBeginAt + r_buf_size (buf));
|
||||
// RList *secs = parseSections (buf, SECTIONS_BEGIN, sd.n_sections, strings);
|
||||
// r_list_free (secs);
|
||||
if (strings) {
|
||||
RList *symbolStrings = filterSymbolStrings (strings, sd.n_sections);
|
||||
// eprintf ("Count strings: %d\n", r_list_length (strings));
|
||||
// eprintf ("Symbol strings: %d\n", r_list_length (symbolStrings));
|
||||
// name the symbols
|
||||
RListIter *iter;
|
||||
RBinSymbol *sym;
|
||||
int n = 0; // sections count
|
||||
r_list_foreach (symbols, iter, sym) {
|
||||
int m = n + sd.n_sections;
|
||||
RBinString *bs = r_list_get_n (symbolStrings, m);
|
||||
if (bs) {
|
||||
sym->name = strdup (bs->string);
|
||||
} else {
|
||||
sym->name = r_str_newf ("__unnamed_%d", n);
|
||||
}
|
||||
sym->ordinal = n;
|
||||
n++;
|
||||
}
|
||||
r_list_free (strings);
|
||||
r_list_free (symbolStrings);
|
||||
globalSymbols = symbols;
|
||||
RCoreSymCacheElement *element = parseDragons (bf, buf, sm.addr + sm.size, sm.bits);
|
||||
if (element) {
|
||||
*bin_obj = element;
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static RList *sections(RBinFile *bf) {
|
||||
SymbolsMetadata sm = parseMetadata (bf->buf, 0x40);
|
||||
SymbolsDragons sd = parseDragons (bf->buf, sm.addr + sm.size, sm.bits);
|
||||
RList *sections = parseSections (bf->buf, SECTIONS_BEGIN - 0x18, sd.n_sections, NULL);
|
||||
RList *res = r_list_newf ((RListFree)r_bin_section_free);
|
||||
RListIter *iter;
|
||||
RBinSection *s;
|
||||
r_list_foreach (sm.segments, iter, s) {
|
||||
r_list_append (res, s);
|
||||
r_return_val_if_fail (res && bf->o && bf->o->bin_obj, res);
|
||||
RCoreSymCacheElement *element = bf->o->bin_obj;
|
||||
size_t i;
|
||||
for (i = 0; i < element->hdr->n_segments; i++) {
|
||||
RCoreSymCacheElementSegment *seg = &element->segments[i];
|
||||
RBinSection *s = bin_section_from_segment (seg);
|
||||
if (s) {
|
||||
r_list_append (res, s);
|
||||
}
|
||||
}
|
||||
r_list_foreach (sections, iter, s) {
|
||||
r_list_append (res, s);
|
||||
for (i = 0; i < element->hdr->n_sections; i++) {
|
||||
RCoreSymCacheElementSection *sect = &element->sections[i];
|
||||
RBinSection *s = bin_section_from_section (sect);
|
||||
if (s) {
|
||||
r_list_append (res, s);
|
||||
}
|
||||
}
|
||||
r_list_free (sections);
|
||||
return res;
|
||||
}
|
||||
|
||||
@ -583,7 +334,7 @@ static RBinInfo *info(RBinFile *bf) {
|
||||
ret->file = strdup (bf->file);
|
||||
ret->bclass = strdup ("symbols");
|
||||
ret->os = strdup ("unknown");
|
||||
ret->arch = sm.arch? strdup (sm.arch): NULL;
|
||||
ret->arch = sm.arch ? strdup (sm.arch) : NULL;
|
||||
ret->bits = sm.bits;
|
||||
ret->type = strdup ("Symbols file");
|
||||
ret->subsystem = strdup ("llvm");
|
||||
@ -598,28 +349,89 @@ static bool check_buffer(RBuffer *b) {
|
||||
return !memcmp (buf, "\x02\xff\x01\xff", 4);
|
||||
}
|
||||
|
||||
static RList *strings(RBinFile *bf) {
|
||||
RListIter *iter;
|
||||
RList *list = r_list_newf (NULL);
|
||||
RList *strings = parseStrings (bf->buf, stringsBeginAt, r_buf_size (bf->buf));
|
||||
RBinString *s;
|
||||
// TODO do proper filter strings vs symbol filter string
|
||||
r_list_foreach (strings, iter, s) {
|
||||
if (*s->string != '_') {
|
||||
r_list_append (list, s);
|
||||
static RList *symbols(RBinFile *bf) {
|
||||
RList *res = r_list_newf ((RListFree)r_bin_symbol_free);
|
||||
r_return_val_if_fail (res && bf->o && bf->o->bin_obj, res);
|
||||
RCoreSymCacheElement *element = bf->o->bin_obj;
|
||||
size_t i;
|
||||
HtUU *hash = ht_uu_new0 ();
|
||||
if (!hash) {
|
||||
return res;
|
||||
}
|
||||
bool found = false;
|
||||
for (i = 0; i < element->hdr->n_lined_symbols; i++) {
|
||||
RCoreSymCacheElementSymbol *sym = (RCoreSymCacheElementSymbol *)&element->lined_symbols[i];
|
||||
ht_uu_find (hash, sym->paddr, &found);
|
||||
if (found) {
|
||||
continue;
|
||||
}
|
||||
RBinSymbol *s = bin_symbol_from_symbol (element, sym);
|
||||
if (s) {
|
||||
r_list_append (res, s);
|
||||
ht_uu_insert (hash, sym->paddr, 1);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
static RList *symbols(RBinFile *bf) {
|
||||
return globalSymbols;
|
||||
for (i = 0; i < element->hdr->n_symbols; i++) {
|
||||
RCoreSymCacheElementSymbol *sym = &element->symbols[i];
|
||||
ht_uu_find (hash, sym->paddr, &found);
|
||||
if (found) {
|
||||
continue;
|
||||
}
|
||||
RBinSymbol *s = bin_symbol_from_symbol (element, sym);
|
||||
if (s) {
|
||||
r_list_append (res, s);
|
||||
}
|
||||
}
|
||||
ht_uu_free (hash);
|
||||
return res;
|
||||
}
|
||||
|
||||
static ut64 size(RBinFile *bf) {
|
||||
return UT64_MAX;
|
||||
}
|
||||
|
||||
static void destroy(RBinFile *bf) {
|
||||
r_coresym_cache_element_free (bf->o->bin_obj);
|
||||
}
|
||||
|
||||
static void header(RBinFile *bf) {
|
||||
r_return_if_fail (bf && bf->o);
|
||||
|
||||
RCoreSymCacheElement *element = bf->o->bin_obj;
|
||||
if (!element) {
|
||||
return;
|
||||
}
|
||||
|
||||
RBin *bin = bf->rbin;
|
||||
PrintfCallback p = bin->cb_printf;
|
||||
PJ *pj = pj_new ();
|
||||
if (!pj) {
|
||||
return;
|
||||
}
|
||||
|
||||
pj_o (pj);
|
||||
pj_kn (pj, "cs_version", element->hdr->version);
|
||||
pj_kn (pj, "size", element->hdr->size);
|
||||
if (element->file_name) {
|
||||
pj_ks (pj, "name", element->file_name);
|
||||
}
|
||||
if (element->binary_version) {
|
||||
pj_ks (pj, "version", element->binary_version);
|
||||
}
|
||||
char uuidstr[R_UUID_LENGTH];
|
||||
r_hex_bin2str (element->hdr->uuid, 16, uuidstr);
|
||||
pj_ks (pj, "uuid", uuidstr);
|
||||
pj_kn (pj, "segments", element->hdr->n_segments);
|
||||
pj_kn (pj, "sections", element->hdr->n_sections);
|
||||
pj_kn (pj, "symbols", element->hdr->n_symbols);
|
||||
pj_kn (pj, "lined_symbols", element->hdr->n_lined_symbols);
|
||||
pj_kn (pj, "line_info", element->hdr->n_line_info);
|
||||
pj_end (pj);
|
||||
|
||||
p ("%s\n", pj_string (pj));
|
||||
pj_free (pj);
|
||||
}
|
||||
|
||||
RBinPlugin r_bin_plugin_symbols = {
|
||||
.name = "symbols",
|
||||
.desc = "Apple Symbols file",
|
||||
@ -628,10 +440,11 @@ RBinPlugin r_bin_plugin_symbols = {
|
||||
.check_buffer = &check_buffer,
|
||||
.symbols = &symbols,
|
||||
.sections = §ions,
|
||||
.strings = strings,
|
||||
.size = &size,
|
||||
.baddr = &baddr,
|
||||
.info = &info,
|
||||
.header = &header,
|
||||
.destroy = &destroy,
|
||||
};
|
||||
|
||||
#ifndef R2_PLUGIN_INCORE
|
||||
|
@ -1,4 +1,5 @@
|
||||
OBJ_SYMBOLS=bin_symbols.o
|
||||
OBJ_SYMBOLS+=../format/mach0/coresymbolication.o
|
||||
|
||||
STATIC_OBJ+=${OBJ_SYMBOLS}
|
||||
TARGET_SYMBOLS=bin_symbols.${EXT_SO}
|
||||
@ -7,4 +8,5 @@ ALL_TARGETS+=${TARGET_SYMBOLS}
|
||||
|
||||
${TARGET_SYMBOLS}: ${OBJ_SYMBOLS}
|
||||
-${CC} $(call libname,bin_mach0) ${CFLAGS} \
|
||||
${OBJ_SYMBOLS} $(LINK) $(LDFLAGS)
|
||||
${OBJ_SYMBOLS} ${SHLR}/sdb/src/libsdb.a \
|
||||
$(LINK) $(LDFLAGS)
|
||||
|
@ -167,6 +167,7 @@ bin_plugins = [
|
||||
'smd',
|
||||
'sms',
|
||||
'spc700',
|
||||
'symbols',
|
||||
'te',
|
||||
'vsf',
|
||||
'wasm',
|
||||
|
130
test/db/formats/mach0/coresymbolication
Normal file
130
test/db/formats/mach0/coresymbolication
Normal file
@ -0,0 +1,130 @@
|
||||
NAME=Xcode symbols cache (just open)
|
||||
FILE=bins/mach0/D9A37B67-F10A-35AA-A852-ABFBBECC03AE.symbols
|
||||
CMDS=q
|
||||
EXPECT=
|
||||
RUN
|
||||
|
||||
NAME=Xcode symbols cache (header)
|
||||
FILE=bins/mach0/D9A37B67-F10A-35AA-A852-ABFBBECC03AE.symbols
|
||||
CMDS=<<EOF
|
||||
ih
|
||||
EOF
|
||||
EXPECT=<<EOF
|
||||
{"cs_version":1,"size":7406,"name":"/System/Volumes/Data/Users/ftamagni/Library/Developer/Xcode/Archives/2020-05-12/TestRTTI 12-05-2020, 12.15.xcarchive/dSYMs/TestRTTI.app.dSYM/Contents/Resources/DWARF/TestRTTI","uuid":"d9a37b67f10a35aaa852abfbbecc03ae","segments":6,"sections":35,"symbols":67,"lined_symbols":0,"line_info":32}
|
||||
EOF
|
||||
RUN
|
||||
|
||||
NAME=Xcode symbols cache (segment and sections)
|
||||
FILE=bins/mach0/D9A37B67-F10A-35AA-A852-ABFBBECC03AE.symbols
|
||||
CMDS=<<EOF
|
||||
f~segment
|
||||
f~section
|
||||
EOF
|
||||
EXPECT=<<EOF
|
||||
0x00000000 0 segment.PAGEZERO
|
||||
0x100000000 32768 segment.TEXT
|
||||
0x100008000 16384 segment.DATA
|
||||
0x10000c000 81920 segment.LLVM
|
||||
0x100020000 4096 segment.LINKEDIT
|
||||
0x100021000 942080 segment.DWARF
|
||||
0x100000000 25544 section.MACH_HEADER
|
||||
0x1000063c8 412 section.TEXT___text
|
||||
0x100006564 144 section.TEXT___stubs
|
||||
0x1000065f4 168 section.TEXT___stub_helper
|
||||
0x10000669c 3366 section.TEXT___objc_methname
|
||||
0x1000073c2 112 section.TEXT___objc_classname
|
||||
0x100007432 2778 section.TEXT___objc_methtype
|
||||
0x100007f0c 144 section.TEXT___cstring
|
||||
0x100007f9c 100 section.TEXT___unwind_info
|
||||
0x100008000 8 section.DATA___got
|
||||
0x100008008 96 section.DATA___la_symbol_ptr
|
||||
0x100008068 32 section.DATA___cfstring
|
||||
0x100008088 24 section.DATA___objc_classlist
|
||||
0x1000080a0 32 section.DATA___objc_protolist
|
||||
0x1000080c0 8 section.DATA___objc_imageinfo
|
||||
0x1000080c8 4872 section.DATA___objc_const
|
||||
0x1000093d0 32 section.DATA___objc_selrefs
|
||||
0x1000093f0 16 section.DATA___objc_classrefs
|
||||
0x100009400 8 section.DATA___objc_superrefs
|
||||
0x100009408 4 section.DATA___objc_ivar
|
||||
0x100009410 240 section.DATA___objc_data
|
||||
0x100009500 392 section.DATA___data
|
||||
0x10000c000 77261 section.LLVM___bundle
|
||||
0x100021000 42034 section.DWARF___debug_line
|
||||
0x10002b432 125245 section.DWARF___debug_pubtypes
|
||||
0x100049d6f 288036 section.DWARF___debug_info
|
||||
0x100090293 685 section.DWARF___debug_pubnames
|
||||
0x100090540 729 section.DWARF___debug_loc
|
||||
0x100090819 192 section.DWARF___debug_aranges
|
||||
0x1000908d9 1925 section.DWARF___debug_abbrev
|
||||
0x10009105e 342172 section.DWARF___debug_str
|
||||
0x1000e48fa 732 section.DWARF___apple_names
|
||||
0x1000e4bd6 36 section.DWARF___apple_namespac
|
||||
0x1000e4bfa 139417 section.DWARF___apple_types
|
||||
0x100106c93 156 section.DWARF___apple_objc
|
||||
EOF
|
||||
RUN
|
||||
|
||||
NAME=Xcode symbols cache (symbols)
|
||||
FILE=bins/mach0/D9A37B67-F10A-35AA-A852-ABFBBECC03AE.symbols
|
||||
CMDS=<<EOF
|
||||
is*~SceneDelegate
|
||||
EOF
|
||||
EXPECT=<<EOF
|
||||
"f sym.__SceneDelegate_scene:willConnectToSession:options: 4 0x100006514"
|
||||
"f sym.__SceneDelegate_sceneDidDisconnect: 4 0x100006518"
|
||||
"f sym.__SceneDelegate_sceneDidBecomeActive: 4 0x10000651c"
|
||||
"f sym.__SceneDelegate_sceneWillResignActive: 4 0x100006520"
|
||||
"f sym.__SceneDelegate_sceneWillEnterForeground: 4 0x100006524"
|
||||
"f sym.__SceneDelegate_sceneDidEnterBackground: 4 0x100006528"
|
||||
"f sym.__SceneDelegate_window 16 0x10000652c"
|
||||
"f sym.__SceneDelegate_setWindow: 20 0x10000653c"
|
||||
"f sym.__SceneDelegate_.cxx_destruct 20 0x100006550"
|
||||
"f sym.__OBJC_LABEL_PROTOCOL___UISceneDelegate 8 0x1000080b0"
|
||||
"f sym.__OBJC_LABEL_PROTOCOL___UIWindowSceneDelegate 8 0x1000080b8"
|
||||
"f sym.__OBJC___PROTOCOL_REFS_UISceneDelegate 24 0x100008f50"
|
||||
"f sym.__OBJC___PROTOCOL_INSTANCE_METHODS_OPT_UISceneDelegate 296 0x100008f68"
|
||||
"f sym.__OBJC___PROTOCOL_METHOD_TYPES_UISceneDelegate 96 0x100009090"
|
||||
"f sym.__OBJC___PROTOCOL_REFS_UIWindowSceneDelegate 24 0x1000090f0"
|
||||
"f sym.__OBJC___PROTOCOL_INSTANCE_METHODS_OPT_UIWindowSceneDelegate 128 0x100009108"
|
||||
"f sym.__OBJC___PROP_LIST_UIWindowSceneDelegate 24 0x100009188"
|
||||
"f sym.__OBJC___PROTOCOL_METHOD_TYPES_UIWindowSceneDelegate 40 0x1000091a0"
|
||||
"f sym.__OBJC_CLASS_PROTOCOLS___SceneDelegate 24 0x1000091c8"
|
||||
"f sym.__OBJC_METACLASS_RO___SceneDelegate 72 0x1000091e0"
|
||||
"f sym.__OBJC___INSTANCE_METHODS_SceneDelegate 224 0x100009228"
|
||||
"f sym.__OBJC___INSTANCE_VARIABLES_SceneDelegate 40 0x100009308"
|
||||
"f sym.__OBJC___PROP_LIST_SceneDelegate 88 0x100009330"
|
||||
"f sym.__OBJC_CLASS_RO___SceneDelegate 72 0x100009388"
|
||||
"f sym._OBJC_IVAR___SceneDelegate._window 4 0x100009408"
|
||||
"f sym._OBJC_METACLASS___SceneDelegate 40 0x1000094b0"
|
||||
"f sym._OBJC_CLASS___SceneDelegate 40 0x1000094d8"
|
||||
"f sym.__OBJC_PROTOCOL___UISceneDelegate 96 0x1000095c8"
|
||||
"f sym.__OBJC_PROTOCOL___UIWindowSceneDelegate 96 0x100009628"
|
||||
EOF
|
||||
RUN
|
||||
|
||||
NAME=Xcode symbols cache (line numbers)
|
||||
FILE=bins/mach0/D9A37B67-F10A-35AA-A852-ABFBBECC03AE.symbols
|
||||
CMDS=<<EOF
|
||||
CL `is~viewDidLoad[2]`
|
||||
CL 0x100006430
|
||||
EOF
|
||||
EXPECT=<<EOF
|
||||
file: /Users/ftamagni/src/TestRTTI/TestRTTI/ViewController.m
|
||||
line: 17
|
||||
file: /Users/ftamagni/src/TestRTTI/TestRTTI/AppDelegate.m
|
||||
line: 30
|
||||
EOF
|
||||
RUN
|
||||
|
||||
NAME=Xcode symbols cache (flags)
|
||||
FILE=bins/mach0/D9A37B67-F10A-35AA-A852-ABFBBECC03AE.symbols
|
||||
CMDS=<<EOF
|
||||
fdj@0x100006430~{:
|
||||
EOF
|
||||
EXPECT=<<EOF
|
||||
offset: 4294992900
|
||||
name: sym.__AppDelegate_application:configurationForConnectingSceneSession:options:
|
||||
realname: -[AppDelegate application:configurationForConnectingSceneSession:options:]
|
||||
EOF
|
||||
RUN
|
Loading…
Reference in New Issue
Block a user