mirror of
https://github.com/radareorg/radare2.git
synced 2024-11-28 15:41:38 +00:00
Initial implementation of the dyldcache symbols parsing
- Inspired by dsc_syms.c
This commit is contained in:
parent
7866fca330
commit
48896bdfb7
@ -936,7 +936,8 @@ static int init_items(struct MACH0_(obj_t)* bin) {
|
||||
lc.cmdsize = r_read_ble32 (&loadc[4], bin->big_endian);
|
||||
|
||||
if (lc.cmdsize < 1 || off + lc.cmdsize > bin->size) {
|
||||
bprintf ("Warning: mach0_header %d = cmdsize<1.\n", i);
|
||||
bprintf ("Warning: mach0_header %d = cmdsize<1. (0x%llx vs 0x%llx)\n", i,
|
||||
(ut64)(off + lc.cmdsize), (ut64)(bin->size));
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1245,16 +1246,17 @@ struct MACH0_(obj_t)* MACH0_(mach0_new)(const char* file, bool verbose) {
|
||||
memset (bin, 0, sizeof (struct MACH0_(obj_t)));
|
||||
bin->verbose = verbose;
|
||||
bin->file = file;
|
||||
if (!(buf = (ut8*)r_file_slurp(file, &bin->size)))
|
||||
if (!(buf = (ut8*)r_file_slurp (file, &bin->size))) {
|
||||
return MACH0_(mach0_free)(bin);
|
||||
}
|
||||
bin->b = r_buf_new ();
|
||||
if (!r_buf_set_bytes(bin->b, buf, bin->size)) {
|
||||
if (!r_buf_set_bytes (bin->b, buf, bin->size)) {
|
||||
free (buf);
|
||||
return MACH0_(mach0_free)(bin);
|
||||
}
|
||||
free (buf);
|
||||
bin->dyld_info = NULL;
|
||||
if (!init(bin)) {
|
||||
if (!init (bin)) {
|
||||
return MACH0_(mach0_free)(bin);
|
||||
}
|
||||
bin->imports_by_ord_size = 0;
|
||||
@ -1268,12 +1270,15 @@ struct MACH0_(obj_t)* MACH0_(new_buf)(RBuffer *buf, bool verbose) {
|
||||
return NULL;
|
||||
}
|
||||
bin->kv = sdb_new (NULL, "bin.mach0", 0);
|
||||
bin->b = r_buf_new ();
|
||||
bin->size = buf->length;
|
||||
bin->verbose = verbose;
|
||||
if (!r_buf_set_bytes (bin->b, buf->buf, bin->size)){
|
||||
// bin->b = r_buf_ref (buf);
|
||||
#if 1
|
||||
bin->b = r_buf_new ();
|
||||
if (!r_buf_set_bytes (bin->b, buf->buf, bin->size)) {
|
||||
return MACH0_(mach0_free) (bin);
|
||||
}
|
||||
#endif
|
||||
if (!init (bin)) {
|
||||
return MACH0_(mach0_free)(bin);
|
||||
}
|
||||
@ -1399,7 +1404,7 @@ static int parse_import_stub(struct MACH0_(obj_t)* bin, struct symbol_t *symbol,
|
||||
symbol->size = 0;
|
||||
stridx = bin->symtab[idx].n_strx;
|
||||
if (stridx >= 0 && stridx < bin->symstrlen) {
|
||||
symstr = (char *)bin->symstr+stridx;
|
||||
symstr = (char *)bin->symstr + stridx;
|
||||
} else {
|
||||
symstr = "???";
|
||||
}
|
||||
@ -1521,7 +1526,7 @@ struct symbol_t* MACH0_(get_symbols)(struct MACH0_(obj_t)* bin) {
|
||||
}
|
||||
stridx = bin->symtab[i].n_strx;
|
||||
if (stridx >= 0 && stridx < bin->symstrlen) {
|
||||
symstr = (char*)bin->symstr+stridx;
|
||||
symstr = (char*)bin->symstr + stridx;
|
||||
} else {
|
||||
symstr = "???";
|
||||
}
|
||||
@ -1669,7 +1674,7 @@ struct import_t* MACH0_(get_imports)(struct MACH0_(obj_t)* bin) {
|
||||
return NULL;
|
||||
}
|
||||
for (i = j = 0; i < bin->dysymtab.nundefsym; i++) {
|
||||
idx = bin->dysymtab.iundefsym +i;
|
||||
idx = bin->dysymtab.iundefsym + i;
|
||||
if (idx < 0 || idx >= bin->nsymtab) {
|
||||
bprintf ("WARNING: Imports index out of bounds. Ignoring relocs\n");
|
||||
free (imports);
|
||||
|
@ -203,4 +203,44 @@ struct cache_header {
|
||||
ut64 localSymbolsSize;
|
||||
};
|
||||
|
||||
// dupe?
|
||||
typedef struct {
|
||||
char magic[16];
|
||||
uint32_t mappingOffset;
|
||||
uint32_t mappingCount;
|
||||
uint32_t imagesOffset;
|
||||
uint32_t imagesCount;
|
||||
uint64_t dyldBaseAddress;
|
||||
uint64_t codeSignatureOffset;
|
||||
uint64_t codeSignatureSize;
|
||||
uint64_t slideInfoOffset;
|
||||
uint64_t slideInfoSize;
|
||||
uint64_t localSymbolsOffset;
|
||||
uint64_t localSymbolsSize;
|
||||
uint8_t uuid[16];
|
||||
uint64_t cacheType;
|
||||
uint32_t branchPoolsOffset;
|
||||
uint32_t branchPoolsCount;
|
||||
uint64_t accelerateInfoAddr;
|
||||
uint64_t accelerateInfoSize;
|
||||
uint64_t imagesTextOffset;
|
||||
uint64_t imagesTextCount;
|
||||
} cache_hdr_t;
|
||||
|
||||
typedef struct {
|
||||
uint64_t address;
|
||||
uint64_t size;
|
||||
uint64_t fileOffset;
|
||||
uint32_t maxProt;
|
||||
uint32_t initProt;
|
||||
} cache_map_t;
|
||||
|
||||
typedef struct {
|
||||
uint64_t address;
|
||||
uint64_t modTime;
|
||||
uint64_t inode;
|
||||
uint32_t pathFileOffset;
|
||||
uint32_t pad;
|
||||
} cache_img_t;
|
||||
|
||||
#endif
|
||||
|
@ -1,9 +1,34 @@
|
||||
/* radare2 - LGPL - Copyright 2009-2017 - nibble, pancake */
|
||||
/* radare2 - LGPL - Copyright 2018 - pancake */
|
||||
|
||||
#include <r_types.h>
|
||||
#include <r_util.h>
|
||||
#include <r_lib.h>
|
||||
#include <r_bin.h>
|
||||
// #include "../format/mach0/mach0_defines.h"
|
||||
#define R_BIN_MACH064 1
|
||||
#include "../format/mach0/mach0.h"
|
||||
|
||||
static void* addr2ptr(uint64_t addr, cache_hdr_t *hdr) {
|
||||
cache_map_t *map = (cache_map_t*)((const ut8*)hdr + hdr->mappingOffset);
|
||||
for(uint32_t i = 0; i < hdr->mappingCount; ++i) {
|
||||
if (addr >= map[i].address && addr < map[i].address + map[i].size) {
|
||||
return (void*)((const ut8*)hdr + map[i].fileOffset + (addr - map[i].address));
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static ut64 va2pa(uint64_t addr, void *cache) {
|
||||
cache_hdr_t *hdr = (cache_hdr_t*)cache;
|
||||
cache_map_t *map = (cache_map_t*)((uintptr_t)cache + hdr->mappingOffset);
|
||||
for(uint32_t i = 0; i < hdr->mappingCount; ++i) {
|
||||
if (addr >= map[i].address && addr < map[i].address + map[i].size) {
|
||||
return map[i].fileOffset + addr - map[i].address;
|
||||
// (void*)((uintptr_t)cache + map[i].fileOffset + (addr - map[i].address));
|
||||
}
|
||||
}
|
||||
return UT64_MAX;
|
||||
}
|
||||
|
||||
static bool dyld64 = false;
|
||||
|
||||
@ -12,7 +37,7 @@ static bool check_bytes(const ut8 *buf, ut64 length) {
|
||||
if (buf && length >= 32) {
|
||||
char arch[9] = { 0 };
|
||||
strncpy (arch, (const char *) buf + 9, R_MIN (length, sizeof (arch) - 1));
|
||||
rc = !memcmp (buf, "\x64\x79\x6c\x64", 4);
|
||||
rc = !memcmp (buf, "dyld", 4);
|
||||
if (rc) {
|
||||
dyld64 = strstr (arch, "64") != NULL;
|
||||
if (*arch) {
|
||||
@ -56,10 +81,10 @@ static RBinInfo *info(RBinFile *bf) {
|
||||
ret->bclass = strdup ("dyldcache");
|
||||
ret->rclass = strdup ("ios");
|
||||
ret->os = strdup ("iOS");
|
||||
ret->arch = strdup ("arm");
|
||||
ret->arch = strdup ("arm"); // XXX
|
||||
ret->machine = strdup (ret->arch);
|
||||
ret->subsystem = strdup ("xnu");
|
||||
ret->type = strdup ("LIBRARY CACHE");
|
||||
ret->type = strdup ("library-cache");
|
||||
ret->bits = dyld64? 64: 32;
|
||||
ret->has_va = true;
|
||||
ret->big_endian = big_endian;
|
||||
@ -67,35 +92,157 @@ static RBinInfo *info(RBinFile *bf) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static ut64 size(RBinFile *bf) {
|
||||
ut64 text, data, syms, spsz;
|
||||
int big_endian;
|
||||
if (!bf->o->info) {
|
||||
bf->o->info = info (bf);
|
||||
}
|
||||
if (!bf->o->info) {
|
||||
return 0;
|
||||
}
|
||||
big_endian = bf->o->info->big_endian;
|
||||
// TODO: reuse section list
|
||||
text = r_mem_get_num (bf->buf->buf + 4, 4, big_endian);
|
||||
data = r_mem_get_num (bf->buf->buf + 8, 4, big_endian);
|
||||
syms = r_mem_get_num (bf->buf->buf + 16, 4, big_endian);
|
||||
spsz = r_mem_get_num (bf->buf->buf + 24, 4, big_endian);
|
||||
return text + data + syms + spsz + (6 * 4);
|
||||
static void parse_mach0 (RList *ret, ut64 paddr, RBinFile *bf) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
static ut64 baddr(RBinFile *bf) {
|
||||
// XXX hardcoded
|
||||
return 0x180000000;
|
||||
}
|
||||
|
||||
#define USE_R2_API 0
|
||||
|
||||
void parse_mach064 (RList *ret, ut64 paddr, RBinFile *bf) {
|
||||
// eprintf ("MACH0 AT 0x%"PFMT64x"\n", paddr);
|
||||
int sz = 0;
|
||||
void *ptr = r_buf_get_at (bf->buf, paddr, &sz);
|
||||
#if USE_R2_API
|
||||
// XXX r2 api cannot load those mach0s because addresses are messed up
|
||||
sz = 1024*1024*1; // 1MB limit file size to 1MB to avoid slow copies.. this is a nice place to optimize unnecessary r_buf_new_from_bytes
|
||||
RBuffer *buf = r_buf_new_with_pointers (ptr, sz);
|
||||
struct MACH0_(obj_t) *res = MACH0_(new_buf) (buf, bf->rbin->verbose);
|
||||
if (!res) {
|
||||
return;
|
||||
}
|
||||
struct symbol_t *symbols = MACH0_(get_symbols) (res);
|
||||
eprintf ("mach0-64: b:%p r:%p s:%p\n", buf, res, symbols);
|
||||
if (!symbols) {
|
||||
return;
|
||||
}
|
||||
for (i = 0; !symbols[i].last; i++) {
|
||||
if (!symbols[i].name[0] || symbols[i].addr < 100) {
|
||||
continue;
|
||||
}
|
||||
RBinSymbol *sym = R_NEW0 (RBinSymbol);
|
||||
if (!sym) {
|
||||
break;
|
||||
}
|
||||
sym->name = strdup (symbols[i].name);
|
||||
eprintf ("-> %s\n", sym->name);
|
||||
sym->vaddr = symbols[i].addr;
|
||||
sym->paddr = symbols[i].offset + bf->o->boffset;
|
||||
sym->size = symbols[i].size;
|
||||
sym->ordinal = i;
|
||||
r_list_append (ret, sym);
|
||||
}
|
||||
free (symbols);
|
||||
r_buf_free (buf);
|
||||
MACH0_(free)(res);
|
||||
#else
|
||||
const ut8 * root = r_buf_get_at (bf->buf, 0, NULL);
|
||||
//printf("f sym.imp.%s 0 0x%llx\n", &strs[syms[n].n_un.n_strx + 1], syms[n].n_value);
|
||||
struct MACH0_(mach_header) *h64 = ptr;
|
||||
struct load_command *cmd = (struct load_command*)((const ut8*)ptr + 0x20);
|
||||
struct load_command *end = (struct load_command*)((const ut8*)cmd + h64->sizeofcmds);
|
||||
for (; cmd < end; cmd = (void *)((const ut8*)cmd + cmd->cmdsize)) {
|
||||
// eprintf ("%p 0x%x (%02x)\n", (void*)cmd - (void*)ptr + (void*)(size_t)paddr, cmd->cmd, LC_SYMTAB);
|
||||
if (cmd->cmd == LC_SYMTAB) {
|
||||
struct symtab_command *stab = (struct symtab_command*)(cmd);
|
||||
struct MACH0_(nlist) *syms = (struct MACH0_(nlist)*)((uintptr_t)root + stab->symoff);
|
||||
char *strs = (char*)((uintptr_t)root + stab->stroff);
|
||||
size_t n;
|
||||
for (n = 0; n < stab->nsyms; n++) {
|
||||
if ((syms[n].n_type & N_TYPE) != N_UNDF && (syms[n].n_type & N_EXT)) {
|
||||
if (false) { // strs[syms[n].n_un.n_strx] != '_')
|
||||
// LOG("Not a C symbol: %s", &strs[syms[n].n_un.n_strx]);
|
||||
} else {
|
||||
RBinSymbol *sym = R_NEW0 (RBinSymbol);
|
||||
if (sym) {
|
||||
sym->name = strdup (&strs [ syms[n].n_strx + 1]);
|
||||
// eprintf ("Sym 0x%llx %s\n", (ut64)(syms[n].n_value), sym->name);
|
||||
sym->vaddr = syms[n].n_value;
|
||||
sym->paddr = syms[n].n_value;
|
||||
// XXX THIs is unnecessarily slow! must be enums
|
||||
sym->bind = "PUBLIC";
|
||||
sym->type = "SYM";
|
||||
r_list_append (ret, sym);
|
||||
}
|
||||
//printf("f sym.imp.%s 0 0x%llx\n", &strs[syms[n].n_un.n_strx + 1], syms[n].n_value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((int)cmd->cmdsize < 1) {
|
||||
eprintf ("CMD Size FAIL %d\n", cmd->cmdsize);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static RList* sections(RBinFile *bf) {
|
||||
RList *ret = NULL;
|
||||
RBinSection *ptr = NULL;
|
||||
RBinObject *obj = bf ? bf->o : NULL;
|
||||
|
||||
ut64 vaddr = 0x180000000;
|
||||
if (!obj || !obj->bin_obj || !(ret = r_list_newf ((RListFree)free))) {
|
||||
return NULL;
|
||||
}
|
||||
if (!(ptr = R_NEW0 (RBinSection))) {
|
||||
return NULL;
|
||||
}
|
||||
r_str_ncpy (ptr->name, (char*)"text", R_BIN_SIZEOF_STRINGS);
|
||||
ptr->size = r_buf_size (bf->buf);
|
||||
ptr->vsize = ptr->size;
|
||||
ptr->paddr = 0;
|
||||
ptr->vaddr = vaddr;
|
||||
ptr->add = true;
|
||||
if (!ptr->vaddr) {
|
||||
ptr->vaddr = ptr->paddr;
|
||||
}
|
||||
ut32 srwx = 1 | 2 | 4;
|
||||
ptr->srwx = srwx | R_BIN_SCN_MAP;
|
||||
r_list_append (ret, ptr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static RList* symbols(RBinFile *bf) {
|
||||
RList *ret = r_list_newf (free);
|
||||
int cache_size = 0;
|
||||
const ut8 *cache = r_buf_get_at (bf->buf, 0, &cache_size);
|
||||
cache_hdr_t *hdr = (cache_hdr_t *)cache;
|
||||
cache_img_t *img = (cache_img_t*)((uintptr_t)cache + hdr->imagesOffset);
|
||||
int i;
|
||||
for (i = 0; i < hdr->imagesCount; i++) {
|
||||
ut32 *ptr = addr2ptr (img[i].address, (cache_hdr_t*)cache);
|
||||
ut64 pa = va2pa (img[i].address, (cache_hdr_t*)cache);
|
||||
switch (*(uint32_t*)ptr) {
|
||||
case MH_MAGIC:
|
||||
// parse_mach0 (ret, *ptr, bf);
|
||||
break;
|
||||
case MH_MAGIC_64:
|
||||
parse_mach064 (ret, pa, bf);
|
||||
break;
|
||||
default:
|
||||
eprintf ("Unknown sub-bin\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
RBinPlugin r_bin_plugin_dyldcache = {
|
||||
.name = "dyldcache",
|
||||
.desc = "dyldcache bin plugin",
|
||||
.license = "LGPL3",
|
||||
// .get_sdb = &get_sdb,
|
||||
.load = &load,
|
||||
.load_bytes = &load_bytes,
|
||||
// .size = &size,
|
||||
.entries = &entries,
|
||||
.baddr = &baddr,
|
||||
.symbols = &symbols,
|
||||
.sections = §ions,
|
||||
.check_bytes = &check_bytes,
|
||||
.info = &info,
|
||||
};
|
||||
|
@ -111,7 +111,7 @@ static RList* sections(RBinFile *bf) {
|
||||
if (!(ptr = R_NEW0 (RBinSection))) {
|
||||
break;
|
||||
}
|
||||
strncpy (ptr->name, (char*)sections[i].name, R_BIN_SIZEOF_STRINGS);
|
||||
r_str_ncpy (ptr->name, (char*)sections[i].name, R_BIN_SIZEOF_STRINGS);
|
||||
if (strstr (ptr->name, "la_symbol_ptr")) {
|
||||
#ifndef R_BIN_MACH064
|
||||
const int sz = 4;
|
||||
|
@ -212,7 +212,7 @@ static const char *help_msg_pf[] = {
|
||||
"pfo", " fdf_name", "Load a Format Definition File (fdf)",
|
||||
"pf.", "fmt_name.field_name=33", "Set new value for the specified field in named format",
|
||||
"pfv.", "fmt_name[.field]", "Print value(s) only for named format. Useful for one-liners",
|
||||
"pfs", " fmt_name|fmt", "Print the size of (named) format in bytes",
|
||||
"pfs", "[.fmt_name| fmt]", "Print the size of (named) format in bytes",
|
||||
NULL
|
||||
};
|
||||
|
||||
@ -975,8 +975,8 @@ static void cmd_print_format(RCore *core, const char *_input, int len) {
|
||||
if (*_input == '.') {
|
||||
_input++;
|
||||
val = sdb_get (core->print->formats, _input, NULL);
|
||||
if (val != NULL) {
|
||||
r_cons_printf ("%d byte(s)\n", r_print_format_struct_size (val, core->print, mode, 0));
|
||||
if (val) {
|
||||
r_cons_printf ("%d\n", r_print_format_struct_size (val, core->print, mode, 0));
|
||||
} else {
|
||||
eprintf ("Struct %s not defined\nUsage: pfs.struct_name | pfs format\n", _input);
|
||||
}
|
||||
@ -985,7 +985,7 @@ static void cmd_print_format(RCore *core, const char *_input, int len) {
|
||||
_input++;
|
||||
}
|
||||
if (*_input) {
|
||||
r_cons_printf ("%d byte(s)\n", r_print_format_struct_size (_input, core->print, mode, 0));
|
||||
r_cons_printf ("%d\n", r_print_format_struct_size (_input, core->print, mode, 0));
|
||||
} else {
|
||||
eprintf ("Struct %s not defined\nUsage: pfs.struct_name | pfs format\n", _input);
|
||||
}
|
||||
@ -1128,7 +1128,7 @@ static void cmd_print_format(RCore *core, const char *_input, int len) {
|
||||
// char *fields = NULL;
|
||||
*space++ = 0;
|
||||
// fields = strchr (space, ' ');
|
||||
if (strchr (name, '.') != NULL) {// || (fields != NULL && strchr(fields, '.') != NULL)) // if anon struct, then field can have '.'
|
||||
if (strchr (name, '.')) {// || (fields != NULL && strchr(fields, '.') != NULL)) // if anon struct, then field can have '.'
|
||||
eprintf ("Struct or fields name can not contain dot symbol (.)\n");
|
||||
} else {
|
||||
sdb_set (core->print->formats, name, space, 0);
|
||||
@ -1150,7 +1150,7 @@ static void cmd_print_format(RCore *core, const char *_input, int len) {
|
||||
/* This make sure the whole structure will be printed */
|
||||
const char *fmt = NULL;
|
||||
fmt = sdb_get (core->print->formats, name, NULL);
|
||||
if (fmt != NULL) {
|
||||
if (fmt) {
|
||||
int size = r_print_format_struct_size (fmt, core->print, mode, 0) + 10;
|
||||
if (size > core->blocksize) {
|
||||
r_core_block_size (core, size);
|
||||
@ -2962,7 +2962,7 @@ static void pr_bb(RCore *core, RAnalFunction *fcn, RAnalBlock *b, bool emu, ut64
|
||||
if (b->jump > b->addr) {
|
||||
RAnalBlock *jumpbb = r_anal_bb_get_jumpbb (fcn, b);
|
||||
if (jumpbb) {
|
||||
if (emu && core->anal->last_disasm_reg != NULL && !jumpbb->parent_reg_arena) {
|
||||
if (emu && core->anal->last_disasm_reg && !jumpbb->parent_reg_arena) {
|
||||
jumpbb->parent_reg_arena = r_reg_arena_dup (core->anal->reg, core->anal->last_disasm_reg);
|
||||
}
|
||||
if (jumpbb->parent_stackptr == INT_MAX) {
|
||||
@ -2978,7 +2978,7 @@ static void pr_bb(RCore *core, RAnalFunction *fcn, RAnalBlock *b, bool emu, ut64
|
||||
if (b->fail > b->addr) {
|
||||
RAnalBlock *failbb = r_anal_bb_get_failbb (fcn, b);
|
||||
if (failbb) {
|
||||
if (emu && core->anal->last_disasm_reg != NULL && !failbb->parent_reg_arena) {
|
||||
if (emu && core->anal->last_disasm_reg && !failbb->parent_reg_arena) {
|
||||
failbb->parent_reg_arena = r_reg_arena_dup (core->anal->reg, core->anal->last_disasm_reg);
|
||||
}
|
||||
if (failbb->parent_stackptr == INT_MAX) {
|
||||
|
@ -19,6 +19,7 @@ typedef struct r_buf_t {
|
||||
int fd;
|
||||
int Oxff;
|
||||
RList *sparse;
|
||||
int refctr;
|
||||
} RBuffer;
|
||||
|
||||
typedef struct r_buf_cache_t {
|
||||
@ -42,6 +43,7 @@ R_API RBuffer *r_buf_new_empty (ut64 len);
|
||||
R_API RBuffer *r_buf_mmap(const char *file, int flags);
|
||||
R_API RBuffer *r_buf_new_sparse(ut8 Oxff);
|
||||
R_API bool r_buf_dump (RBuffer *buf, const char *file);
|
||||
R_API RBuffer *r_buf_ref(RBuffer *b);
|
||||
/* methods */
|
||||
R_API bool r_buf_set_bits(RBuffer *b, ut64 at, const ut8* buf, int bitoff, int count);
|
||||
R_API int r_buf_set_bytes(RBuffer *b, const ut8 *buf, ut64 length);
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* radare - LGPL - Copyright 2009-2016 - pancake */
|
||||
/* radare - LGPL - Copyright 2009-2018 - pancake */
|
||||
|
||||
#include <r_types.h>
|
||||
#include <r_util.h>
|
||||
@ -143,6 +143,12 @@ R_API RBuffer *r_buf_new_with_string (const char *msg) {
|
||||
return r_buf_new_with_bytes ((const ut8*)msg, (ut64) strlen (msg));
|
||||
}
|
||||
|
||||
R_API RBuffer *r_buf_new_with_bufref(RBuffer *b) {
|
||||
RBuffer *buf = r_buf_new_with_pointers (b->buf, b->length);
|
||||
r_buf_ref (buf);
|
||||
return buf;
|
||||
}
|
||||
|
||||
R_API RBuffer *r_buf_new_with_buf(RBuffer *b) {
|
||||
return r_buf_new_with_bytes (b->buf, b->length);
|
||||
}
|
||||
@ -596,11 +602,11 @@ static int r_buf_fcpy_at (RBuffer *b, ut64 addr, ut8 *buf, const char *fmt, int
|
||||
|
||||
R_API ut8 *r_buf_get_at (RBuffer *b, ut64 addr, int *left) {
|
||||
if (b->empty) {
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
if (b->fd != -1) {
|
||||
eprintf ("r_buf_get_at not supported for r_buf_new_file\n");
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
if (addr == R_BUF_CUR) {
|
||||
addr = b->cur;
|
||||
@ -613,7 +619,7 @@ R_API ut8 *r_buf_get_at (RBuffer *b, ut64 addr, int *left) {
|
||||
if (left) {
|
||||
*left = b->length - addr;
|
||||
}
|
||||
return b->buf+addr;
|
||||
return b->buf + addr;
|
||||
}
|
||||
|
||||
//ret 0 if failed; ret copied length if successful
|
||||
@ -712,6 +718,10 @@ R_API void r_buf_free(RBuffer *b) {
|
||||
if (!b) {
|
||||
return;
|
||||
}
|
||||
if (b->refctr > 0) {
|
||||
b->refctr--;
|
||||
return;
|
||||
}
|
||||
if (!b->ro) {
|
||||
r_buf_deinit (b);
|
||||
}
|
||||
@ -778,3 +788,10 @@ R_API bool r_buf_resize (RBuffer *b, ut64 newsize) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
R_API RBuffer *r_buf_ref(RBuffer *b) {
|
||||
if (b) {
|
||||
b->refctr++;
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user