Skip to content

Commit

Permalink
Optimization
Browse files Browse the repository at this point in the history
  • Loading branch information
imbillow committed Jan 19, 2024
1 parent 4decb2c commit 0e71efd
Show file tree
Hide file tree
Showing 8 changed files with 214 additions and 211 deletions.
99 changes: 41 additions & 58 deletions librz/bin/dbginfo.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
// SPDX-License-Identifier: LGPL-3.0-only

#include <rz_types.h>
#include <rz_bin.h>
#include <rz_bin_source_line.h>
#include <ctype.h>

RZ_API void rz_bin_source_line_info_builder_init(RzBinSourceLineInfoBuilder *builder) {
rz_vector_init(&builder->samples, sizeof(RzBinSourceLineSample), NULL, NULL);
Expand Down Expand Up @@ -216,12 +217,14 @@ RZ_API const RzBinSourceLineSample *rz_bin_source_line_info_get_next(const RzBin
return next;
}

RZ_DEPRECATE RZ_API bool rz_bin_addr2line(RzBin *bin, ut64 addr, char *file, int len, int *line) {
rz_return_val_if_fail(bin, false);
if (!bin->cur || !bin->cur->o || !bin->cur->o->lines) {
return false;
}
const RzBinSourceLineSample *s = rz_bin_source_line_info_get_first_at(bin->cur->o->lines, addr);
RZ_API bool rz_bin_source_line_addr2line(
RZ_BORROW RZ_IN RZ_NONNULL const RzBinSourceLineInfo *sl,
ut64 addr,
RZ_BORROW RZ_OUT RZ_NULLABLE char *file,
int len,
RZ_BORROW RZ_OUT RZ_NULLABLE int *line) {
rz_return_val_if_fail(sl, false);
const RzBinSourceLineSample *s = rz_bin_source_line_info_get_first_at(sl, addr);
if (!s || s->address != addr) {
// consider only exact matches, not inside of samples
return false;
Expand All @@ -236,51 +239,40 @@ RZ_DEPRECATE RZ_API bool rz_bin_addr2line(RzBin *bin, ut64 addr, char *file, int
*file = 0;
}
}
return false;
return true;
}

static const char *cache_lines(RzBinSourceLineCacheItem *x, ut64 line) {
rz_warn_if_fail(line > x->cached_lines);
static char *str_trim_left_right(char *l, char *r) {
l = (char *)rz_str_trim_head_ro(l);
for (; r > l && isspace(*r); --r) {
*r = '\0';
}
return l;
}

static void cache_lines(RzBinSourceLineCacheItem *x) {
if (!x->file_content) {
return NULL;
}
bool found = false;
char *str = ht_up_find(x->line_by_ln, x->cached_lines, &found);
if (!(found && str)) {
rz_warn_if_reached();
return NULL;
return;
}

ut64 i = x->cached_lines;
char *p = str;
char *p = x->file_content;
char *q = NULL;
do {
q = strchr(p, '\n');
++i;
if (q) {
p = q + 1;
*q = '\0';
ht_up_update(x->line_by_ln, i, q + 1);
x->cached_lines = i;
if (!q) {
break;
}
*q = '\0';
p = str_trim_left_right(p, q);
rz_pvector_push(x->line_by_ln, p);
p = q + 1;
} while ((p && p - x->file_content < x->file_size));

str = ht_up_find(x->line_by_ln, line, &found);
if (!(found && str)) {
return NULL;
}
q = rz_str_trim_nc(str);
if (q != str) {
ht_up_update(x->line_by_ln, line, q);
}
return q;
}

static const char *read_line(const char *file, int line, RzBinSourceLineCache *cache) {
rz_return_val_if_fail(file, NULL);
rz_return_val_if_fail(file && line >= 1, NULL);
if (!(cache && cache->items)) {
rz_file_slurp_line(file, line, 0);
return rz_file_slurp_line(file, line, 0);
}
bool found = false;
char *content = NULL;
Expand All @@ -290,15 +282,7 @@ static const char *read_line(const char *file, int line, RzBinSourceLineCache *c
if (!(item && item->file_content)) {
return NULL;
} else {
char *str = ht_up_find(item->line_by_ln, line, NULL);
if (!str) {
return NULL;
}
char *q = rz_str_trim_nc(str);
if (q != str) {
ht_up_update(item->line_by_ln, line, q);
}
return q;
return rz_pvector_at(item->line_by_ln, line - 1);
}
} else {
content = rz_file_slurp(file, &sz);
Expand All @@ -312,36 +296,35 @@ static const char *read_line(const char *file, int line, RzBinSourceLineCache *c
}
item->file_content = content;
item->file_size = sz;
item->line_by_ln = ht_up_new0();
item->line_by_ln = rz_pvector_new(NULL);
if (!item->line_by_ln) {
goto err;
}
item->cached_lines = 1;
ht_up_update(item->line_by_ln, 1, item->file_content);
ht_pp_update(cache->items, file, item);
return cache_lines(item, line);

rz_pvector_reserve(item->line_by_ln, line);
cache_lines(item);
return rz_pvector_at(item->line_by_ln, line - 1);
}
err:
if (item) {
ht_up_free(item->line_by_ln);
rz_pvector_free(item->line_by_ln);
}
free(content);
free(item);
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)) {
return NULL;
}
const RzBinSourceLineSample *s = rz_bin_source_line_info_get_first_at(bin->cur->o->lines, addr);
RZ_API RZ_OWN char *rz_bin_source_line_addr2text(
RZ_BORROW RZ_IN RZ_NONNULL const RzBinSourceLineInfo *sl, ut64 addr, RzDebugInfoOption opt) {
rz_return_val_if_fail(sl, NULL);
const RzBinSourceLineSample *s = rz_bin_source_line_info_get_first_at(sl, addr);
if (!(s && s->address == addr)) {
// consider only exact matches, not inside of samples
return NULL;
}
while (s && !s->file) {
s = rz_bin_source_line_info_get_next(bin->cur->o->lines, s);
s = rz_bin_source_line_info_get_next(sl, s);
}
if (!s) {
return NULL;
Expand Down
6 changes: 5 additions & 1 deletion librz/core/cgraph.c
Original file line number Diff line number Diff line change
Expand Up @@ -416,8 +416,12 @@ static char *block_line(RzCore *core, ut64 addr, RzAnalysisBlock *bb) {
int line = 0, oline = 0, idx = 0;
int is_html = rz_cons_singleton()->is_html;
ut64 end = bb->addr + bb->size - 2;
RzBinObject *o = rz_bin_cur_object(core->bin);
RzBinSourceLineInfo *sl = o ? o->lines : NULL;
for (ut64 at = bb->addr; at < end; at += 2) {
rz_bin_addr2line(core->bin, at, file, sizeof(file) - 1, &line);
if (sl) {
rz_bin_source_line_addr2line(sl, at, file, sizeof(file) - 1, &line);
}
if (line != 0 && line != oline && strcmp(file, "??") != 0) {
file_str = rz_file_slurp_line(file, line, 0);
if (file_str) {
Expand Down
6 changes: 4 additions & 2 deletions librz/core/cmd/cmd_debug.c
Original file line number Diff line number Diff line change
Expand Up @@ -454,7 +454,9 @@ static bool step_line(RzCore *core, int times) {
}
file[0] = 0;
file2[0] = 0;
if (rz_bin_addr2line(core->bin, off, file, sizeof(file), &line)) {
RzBinObject *o = rz_bin_cur_object(core->bin);
RzBinSourceLineInfo *sl = o ? o->lines : NULL;
if (sl && rz_bin_source_line_addr2line(sl, off, file, sizeof(file), &line)) {
char *ptr = rz_file_slurp_line(file, line, 0);
RZ_LOG_INFO("--> 0x%08" PFMT64x " %s : %d\n", off, file, line);
RZ_LOG_INFO("--> %s\n", ptr);
Expand All @@ -467,7 +469,7 @@ static bool step_line(RzCore *core, int times) {
do {
rz_debug_step(core->dbg, 1);
off = rz_debug_reg_get(core->dbg, "PC");
if (!rz_bin_addr2line(core->bin, off, file2, sizeof(file2), &line2)) {
if (!(sl && rz_bin_source_line_addr2line(sl, off, file2, sizeof(file2), &line2))) {
if (find_meta) {
continue;
}
Expand Down
32 changes: 6 additions & 26 deletions librz/core/disasm.c
Original file line number Diff line number Diff line change
Expand Up @@ -271,17 +271,6 @@ typedef struct {
RzPVector /*<RzAnalysisDisasmText *>*/ *vec;
} RzDisasmState;

// Function to set or clear a flag based on a boolean value
static inline void set_flag(uint32_t *flags, uint32_t flag, bool value) {
if (value) {
// Set the flag
*flags |= flag;
} else {
// Clear the flag
*flags &= ~flag;
}
}

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 @@ -565,7 +554,7 @@ static void RzBinSourceLineCacheItem_free(RzBinSourceLineCacheItem *x) {
return;
}
free(x->file_content);
ht_up_free(x->line_by_ln);
rz_pvector_free(x->line_by_ln);
free(x);
}

Expand Down Expand Up @@ -3714,29 +3703,20 @@ static void ds_print_debuginfo(RzDisasmState *ds) {
if (!ds->debuginfo.enable)
return;

if (ds->debuginfo.lines) {
RzBinObject *o = rz_bin_cur_object(ds->core->bin);
RzBinSourceLineInfo *sl = o ? o->lines : NULL;
if (ds->debuginfo.lines && sl) {
free(ds->sl);
ds->sl = rz_bin_addr2text(ds->core->bin, ds->at, ds->debuginfo);
ds->sl = rz_bin_source_line_addr2text(sl, ds->at, ds->debuginfo);
if (RZ_STR_ISEMPTY(ds->sl))
return;
if (ds->osl && !(ds->osl && strcmp(ds->sl, ds->osl)))
return;
char *line = strdup(ds->sl);
rz_str_replace_char(line, '\t', ' ');
rz_str_replace_char(line, '\x1b', ' ');
rz_str_replace_char(line, '\r', ' ');
rz_str_replace_char(line, '\n', '\x00');
rz_str_trim(line);
if (RZ_STR_ISEMPTY(line)) {
free(line);
return;
}
ds_align_comment(ds);
theme_printf(comment, "; %s", line);
theme_printf(comment, "; %s", ds->sl);
free(ds->osl);
ds->osl = ds->sl;
ds->sl = NULL;
free(line);
}
}

Expand Down
1 change: 1 addition & 0 deletions librz/include/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ include_files = [
'rz_basefind.h',
'rz_bin.h',
'rz_bin_dwarf.h',
'rz_bin_source_line.h',
'rz_bind.h',
'rz_bp.h',
'rz_cmd.h',
Expand Down
104 changes: 1 addition & 103 deletions librz/include/rz_bin.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@
#include <rz_util/ht_pu.h>
#include <rz_demangler.h>
#include <rz_hash.h>
#include <rz_bin_source_line.h>

typedef struct rz_bin_t RzBin;
typedef struct rz_bin_file_t RzBinFile;
typedef struct rz_bin_source_line_info_t RzBinSourceLineInfo;
typedef struct rz_bin_reloc_storage_t RzBinRelocStorage;

#include <rz_bin_dwarf.h>
Expand Down Expand Up @@ -434,104 +434,6 @@ typedef struct rz_bin_trycatch_t {
RZ_API RzBinTrycatch *rz_bin_trycatch_new(ut64 source, ut64 from, ut64 to, ut64 handler, ut64 filter);
RZ_API void rz_bin_trycatch_free(RzBinTrycatch *tc);

/**
* \brief A single sample of source line info for a specific address
*
* If at least one of the line, column and file members is not 0/NULL, such a sample specifies the line info
* for all addresses greater or equal to address until the next address that has another sample.
*
* If all the members line, column and file are 0/NULL, then this is a closing sample, indicating that the
* previous entry stops here. The address is the first address **not contained** by the previous record.
* Such a case corresponds for example to what DW_LNE_end_sequence emits in Dwarf.
* Use rz_bin_source_line_sample_is_closing() for checking if a sample is closing.
*/
typedef struct rz_bin_source_line_sample_t {
/**
* The first address that is covered by the given line and column,
* or, if all other members are 0/NULL, this is the first.
*/
ut64 address;

/**
* If > 0, then indicates the line for the given address and the following.
* If == 0, then indicates that no line information is known.
*
* 32bit for this value is an intentional decision to lower memory consumption.
*/
ut32 line;

/**
* If > 0, then indicates the column.
* If == 0, then no column information is known.
*
* 32bit for this value is an intentional decision to lower memory consumption.
*/
ut32 column;

/**
* Filename, which must come out of the const pool of the owning
* RzBinSourceLineInfo or RzBinSourceLineInfoBuilder.
*/
const char *file;
} RzBinSourceLineSample;

/*
* see documentation of RzBinSourceLineSample about what closing exactly means.
*/
static inline bool rz_bin_source_line_sample_is_closing(const RzBinSourceLineSample *s) {
return !s->line && !s->column && !s->file;
}

struct rz_bin_source_line_info_t {
/**
* \brief All source line references for given adresses
*
* These elements must be sorted by address and addresses must be unique, so binary search can be applied.
* Source file information is not contained within this array because source file changes
* are generally much sparser than line changes.
*/
RzBinSourceLineSample *samples;
size_t samples_count;
RzStrConstPool filename_pool;
}; // RzBinSourceLineInfo

/**
* Temporary data structure for building an RzBinSourceLineInfo.
*/
typedef struct rz_bin_source_line_info_builder_t {
RzVector /*<RzBinSourceLineSample>*/ samples; //< may be unsorted and will be sorted in the finalization step
RzStrConstPool filename_pool;
} RzBinSourceLineInfoBuilder;

typedef struct {
char *file_content;
ut64 file_size;
ut64 cached_lines;
HtUP /*<ut64, const char *>*/ *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);
RZ_API RzBinSourceLineInfo *rz_bin_source_line_info_builder_build_and_fini(RzBinSourceLineInfoBuilder *builder);

RZ_API bool rz_bin_source_line_info_merge(RZ_BORROW RZ_NONNULL RzBinSourceLineInfo *dst, RZ_BORROW RZ_NONNULL RzBinSourceLineInfo *src);
RZ_API void rz_bin_source_line_info_free(RzBinSourceLineInfo *sli);
RZ_API const RzBinSourceLineSample *rz_bin_source_line_info_get_first_at(const RzBinSourceLineInfo *sli, ut64 addr);
RZ_API const RzBinSourceLineSample *rz_bin_source_line_info_get_next(const RzBinSourceLineInfo *sli, RZ_NONNULL const RzBinSourceLineSample *cur);

typedef struct rz_bin_plugin_t {
char *name;
char *desc;
Expand Down Expand Up @@ -1035,10 +937,6 @@ RZ_API const char *rz_bin_get_meth_flag_string(ut64 flag, bool compact);

RZ_API RZ_BORROW RzBinSection *rz_bin_get_section_at(RzBinObject *o, ut64 off, int va);

/* 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, RzDebugInfoOption opt);

/* filter.c */
RZ_API void rz_bin_load_filter(RzBin *bin, ut64 rules);
RZ_API bool rz_bin_strpurge(RzBin *bin, const char *str, ut64 addr);
Expand Down
Loading

0 comments on commit 0e71efd

Please sign in to comment.