Skip to content

Commit

Permalink
Add cache for source line
Browse files Browse the repository at this point in the history
  • Loading branch information
imbillow committed Jan 19, 2024
1 parent 13fde3b commit 956cc7e
Show file tree
Hide file tree
Showing 5 changed files with 176 additions and 51 deletions.
153 changes: 125 additions & 28 deletions librz/bin/dbginfo.c
Original file line number Diff line number Diff line change
Expand Up @@ -239,13 +239,117 @@ RZ_DEPRECATE RZ_API bool rz_bin_addr2line(RzBin *bin, ut64 addr, char *file, int
return false;
}

RZ_DEPRECATE RZ_API char *rz_bin_addr2text(RzBin *bin, ut64 addr, int origin) {
static inline bool read_next_line(FILE *fd, ut64 *psize, RzStrBuf *sb) {
rz_return_val_if_fail(fd && sb, NULL);

ut64 size = 0;
char buf[1024] = { 0 };
while (true) {
ut64 r = fread(buf, 1, sizeof(buf) - 1, fd);
if (ferror(fd) || r <= 0) {
return false;
}
char *p = buf;
char *q = NULL;
do {
q = memchr(p, '\n', r);
p = q + 1;
if (q) {
ut64 sz = q - buf;
size += sz;
fseek(fd, -(long)(r - 1 - sz), SEEK_CUR);
if (ferror(fd)) {
return false;
}
rz_strbuf_append_n(sb, buf, sz);
if (psize) {
*psize = size;
}
return true;
}
size += r;
rz_strbuf_append_n(sb, buf, r);
} while (p - buf <= r && q);
}
return false;
}

static char *read_line(const char *file, int line, RzBinSourceLineCache *cache) {
rz_return_val_if_fail(file, NULL);
if (!(cache && cache->items)) {
rz_file_slurp_line(file, line, 0);
}
bool found = false;
bool found_off = false;
RzStrBuf sb = { 0 };
rz_strbuf_init(&sb);
RzBinSourceLineCacheItem *item = ht_pp_find(cache->items, file, &found);
if (found) {
if (!(item && item->fd)) {
return NULL;
} else {
ut64 offset = ht_uu_find(item->line_by_ln, line, &found_off);
if (!found_off) {
goto build;
}
fseek(item->fd, (long)offset, SEEK_SET);
read_next_line(item->fd, NULL, &sb);
return rz_strbuf_drain_nofree(&sb);
}
} else {
build:
if (!rz_file_exists(file)) {
ht_pp_insert(cache->items, file, NULL);
return NULL;
}
item = RZ_NEW0(RzBinSourceLineCacheItem);
if (!item) {
goto err;
}
item->fd = rz_sys_fopen(file, "r");
if (!item->fd) {
goto err;
}
item->line_by_ln = ht_uu_new0();
if (!item->line_by_ln) {
goto err;
}

ut64 i = 1;
ut64 offset = 0;
while (i < line) {
ut64 tmp_sz = 0;
sb.len = sb.ptrlen = 0;
if (!read_next_line(item->fd, &tmp_sz, &sb)) {
goto err;
}
++i;
offset += tmp_sz + 1;
}
ht_uu_update(item->line_by_ln, line, offset);
ht_pp_update(cache->items, file, item);

sb.len = sb.ptrlen = 0;
read_next_line(item->fd, NULL, &sb);
return rz_strbuf_drain_nofree(&sb);
}
err:
if (item) {
ht_uu_free(item->line_by_ln);
fclose(item->fd);
}
free(item);
rz_strbuf_fini(&sb);
return NULL;
}

RZ_DEPRECATE RZ_API char *rz_bin_addr2text(RzBin *bin, ut64 addr, RzDebugInfoOption opt) {
rz_return_val_if_fail(bin, NULL);
if (!bin->cur || !bin->cur->o || !bin->cur->o->lines) {
if(!(bin->cur && bin->cur->o && bin->cur->o->lines)){
return NULL;
}
const RzBinSourceLineSample *s = rz_bin_source_line_info_get_first_at(bin->cur->o->lines, addr);
if (s && s->address != addr) {
if (!(s && s->address == addr)) {
// consider only exact matches, not inside of samples
return NULL;
}
Expand All @@ -255,31 +359,24 @@ RZ_DEPRECATE RZ_API char *rz_bin_addr2text(RzBin *bin, ut64 addr, int origin) {
if (!s) {
return NULL;
}
const char *file_nopath;
if (origin > 1) {
file_nopath = s->file;
} else {
file_nopath = strrchr(s->file, '/');
if (file_nopath) {
file_nopath++;
} else {
file_nopath = s->file;
}
}
const char *filepath = opt.abspath ? s->file : rz_file_basename(s->file);
if (!s->line) {
return strdup(file_nopath);
}
char *out = rz_file_slurp_line(s->file, s->line, 0);
if (out) {
rz_str_trim(out);
if (origin) {
char *res = rz_str_newf("%s:%d %s",
file_nopath, s->line,
out ? out : "");
free(out);
out = res;
}
return out;
return strdup(filepath);
}
return rz_str_newf("%s:%" PFMT32u, file_nopath, s->line);

RzStrBuf sb = { 0 };
rz_strbuf_initf(&sb, "%s:%" PFMT32u, filepath, s->line);
if (!opt.file) {
return rz_strbuf_drain_nofree(&sb);
}

char *out = read_line(s->file, s->line, &opt.cache);
if (!out) {
return rz_strbuf_drain_nofree(&sb);
}

rz_str_trim(out);
rz_strbuf_appendf(&sb, " %s", out);
free(out);
return rz_strbuf_drain_nofree(&sb);
}
46 changes: 27 additions & 19 deletions librz/core/disasm.c
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,8 @@ typedef struct {
int tracespace;
int cyclespace;
int show_indent;
ut32 debuginfo;
RzDebugInfoOption debuginfo;

bool show_size;
bool show_trace;
bool show_family;
Expand Down Expand Up @@ -281,13 +282,6 @@ static inline void set_flag(uint32_t *flags, uint32_t flag, bool value) {
}
}

enum debuginfo_flag_enum_t {
DEBUGINFO = 1 << 0,
DEBUGINFO_ABSPATH = 1 << 1,
DEBUGINFO_FILE = 1 << 2,
DEBUGINFO_LINES = 1 << 3,
};

static void ds_setup_print_pre(RzDisasmState *ds, bool tail, bool middle);
static void ds_setup_pre(RzDisasmState *ds, bool tail, bool middle);
static void ds_print_pre(RzDisasmState *ds, bool fcnline);
Expand Down Expand Up @@ -566,6 +560,22 @@ static void ds_print_esil_analysis_fini(RzDisasmState *ds) {
}
}

static void RzBinSourceLineCacheItem_free(RzBinSourceLineCacheItem *x) {
if (!x) {
return;
}
fclose(x->fd);
ht_uu_free(x->line_by_ln);
free(x);
}

static void RzBinSourceLineCacheItem_HtPPKv_free(HtPPKv *x) {
if (!x) {
return;
}
RzBinSourceLineCacheItem_free(x->value);
}

static RzDisasmState *ds_init(RzCore *core) {
RzDisasmState *ds = RZ_NEW0(RzDisasmState);
if (!ds) {
Expand Down Expand Up @@ -631,10 +641,11 @@ static RzDisasmState *ds_init(RzCore *core) {
ds->tracespace = rz_config_get_i(core->config, "asm.tracespace");
ds->cyclespace = rz_config_get_i(core->config, "asm.cyclespace");

set_flag(&ds->debuginfo, DEBUGINFO, rz_config_get_b(core->config, "asm.debuginfo"));
set_flag(&ds->debuginfo, DEBUGINFO_FILE, rz_config_get_b(core->config, "asm.debuginfo.file"));
set_flag(&ds->debuginfo, DEBUGINFO_ABSPATH, rz_config_get_b(core->config, "asm.debuginfo.abspath"));
set_flag(&ds->debuginfo, DEBUGINFO_LINES, rz_config_get_b(core->config, "asm.debuginfo.lines"));
ds->debuginfo.enable = rz_config_get_b(core->config, "asm.debuginfo");
ds->debuginfo.file = rz_config_get_b(core->config, "asm.debuginfo.file");
ds->debuginfo.abspath = rz_config_get_b(core->config, "asm.debuginfo.abspath");
ds->debuginfo.lines = rz_config_get_b(core->config, "asm.debuginfo.lines");
ds->debuginfo.cache.items = ht_pp_new(NULL, RzBinSourceLineCacheItem_HtPPKv_free, NULL);

ds->show_lines_call = ds->show_lines ? rz_config_get_b(core->config, "asm.lines.call") : false;
ds->show_lines_ret = ds->show_lines ? rz_config_get_b(core->config, "asm.lines.ret") : false;
Expand Down Expand Up @@ -838,6 +849,7 @@ static void ds_free(RzDisasmState *ds) {
ds_reflines_fini(ds);
ds_print_esil_analysis_fini(ds);
sdb_free(ds->ssa);
ht_pp_free(ds->debuginfo.cache.items);
free(ds->comment);
free(ds->line);
free(ds->line_col);
Expand Down Expand Up @@ -3699,16 +3711,12 @@ static void ds_align_comment(RzDisasmState *ds) {
}

static void ds_print_debuginfo(RzDisasmState *ds) {
if (!(ds->debuginfo & DEBUGINFO)) {
if (!ds->debuginfo.enable)
return;
}

if (ds->debuginfo & DEBUGINFO_LINES) {
// TODO: cache value in ds
int file_and_abspath = (ds->debuginfo & DEBUGINFO_FILE) ? 1 : 0;
file_and_abspath += (ds->debuginfo & DEBUGINFO_ABSPATH) ? 1 : 0;
if (ds->debuginfo.lines) {
free(ds->sl);
ds->sl = rz_bin_addr2text(ds->core->bin, ds->at, file_and_abspath);
ds->sl = rz_bin_addr2text(ds->core->bin, ds->at, ds->debuginfo);
if (RZ_STR_ISEMPTY(ds->sl))
return;
if (ds->osl && !(ds->osl && strcmp(ds->sl, ds->osl)))
Expand Down
21 changes: 19 additions & 2 deletions librz/include/rz_bin.h
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ typedef enum {
} RzBinLanguage;

#define RZ_BIN_LANGUAGE_MASK(x) ((x) & ~RZ_BIN_LANGUAGE_BLOCKS)
#define RZ_BIN_LANGUAGE_HAS_BLOCKS(x) ((x)&RZ_BIN_LANGUAGE_BLOCKS)
#define RZ_BIN_LANGUAGE_HAS_BLOCKS(x) ((x) & RZ_BIN_LANGUAGE_BLOCKS)

enum {
RZ_BIN_CLASS_PRIVATE,
Expand Down Expand Up @@ -503,6 +503,23 @@ typedef struct rz_bin_source_line_info_builder_t {
RzStrConstPool filename_pool;
} RzBinSourceLineInfoBuilder;

typedef struct {
FILE *fd;
HtUU /*<ut64, ut64>*/ *line_by_ln;
} RzBinSourceLineCacheItem;

typedef struct {
HtPP /*<const char*, RzBinSourceLineCacheItem *>*/ *items;
} RzBinSourceLineCache;

typedef struct {
RzBinSourceLineCache cache;
bool enable : 1;
bool file : 1;
bool abspath : 1;
bool lines : 1;
} RzDebugInfoOption;

RZ_API void rz_bin_source_line_info_builder_init(RzBinSourceLineInfoBuilder *builder);
RZ_API void rz_bin_source_line_info_builder_fini(RzBinSourceLineInfoBuilder *builder);
RZ_API void rz_bin_source_line_info_builder_push_sample(RzBinSourceLineInfoBuilder *builder, ut64 address, ut32 line, ut32 column, const char *file);
Expand Down Expand Up @@ -1018,7 +1035,7 @@ RZ_API RZ_BORROW RzBinSection *rz_bin_get_section_at(RzBinObject *o, ut64 off, i

/* dbginfo.c */
RZ_DEPRECATE RZ_API bool rz_bin_addr2line(RzBin *bin, ut64 addr, char *file, int len, int *line);
RZ_DEPRECATE RZ_API char *rz_bin_addr2text(RzBin *bin, ut64 addr, int origin);
RZ_DEPRECATE RZ_API char *rz_bin_addr2text(RzBin *bin, ut64 addr, RzDebugInfoOption opt);

/* filter.c */
RZ_API void rz_bin_load_filter(RzBin *bin, ut64 rules);
Expand Down
5 changes: 4 additions & 1 deletion librz/main/rz-bin.c
Original file line number Diff line number Diff line change
Expand Up @@ -586,7 +586,10 @@ static int rabin_do_operation(RzBin *bin, const char *op, int rad, const char *o

static int rabin_show_srcline(RzBin *bin, ut64 at) {
char *srcline;
if (at != UT64_MAX && (srcline = rz_bin_addr2text(bin, at, true))) {
RzDebugInfoOption option = { 0 };
option.file = true;
option.abspath = true;
if (at != UT64_MAX && (srcline = rz_bin_addr2text(bin, at, option))) {
printf("%s\n", srcline);
free(srcline);
return true;
Expand Down
2 changes: 1 addition & 1 deletion test/db/tools/rz_bin
Original file line number Diff line number Diff line change
Expand Up @@ -1037,7 +1037,7 @@ RUN

NAME=rz-bin -d
FILE=bins/elf/analysis/dwarftest
CMDS=!rz-bin -d ${RZ_FILE} | grep -c "0x00400535 /tmp/r2-regressions/.//dwarftest.c"
CMDS=!rz-bin -d ${RZ_FILE} | grep -c "0x00400535 /tmp/r2-regressions/./dwarftest.c"
EXPECT=<<EOF
1
EOF
Expand Down

0 comments on commit 956cc7e

Please sign in to comment.