Skip to content

Commit

Permalink
Add file percentage in visual mode (V/Vv)
Browse files Browse the repository at this point in the history
  • Loading branch information
PeiweiHu committed May 17, 2024
1 parent a6d4a6b commit e99dbd9
Show file tree
Hide file tree
Showing 4 changed files with 154 additions and 2 deletions.
2 changes: 2 additions & 0 deletions librz/core/core_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,8 @@ typedef struct rz_core_visual_t {
int current5format;
/* Panels */
RzPanelsRoot *panels_root;
/* file percentage */
float percentage;
} RzCoreVisual;

RZ_IPI RZ_OWN RzCoreVisual *rz_core_visual_new();
Expand Down
125 changes: 125 additions & 0 deletions librz/core/tui/visual.c
Original file line number Diff line number Diff line change
Expand Up @@ -3503,6 +3503,113 @@ RZ_IPI void rz_core_visual_scrollbar_bottom(RzCore *core) {
rz_cons_flush();
}

static bool is_in_symbol_range(ut64 sym_addr, ut64 sym_size, ut64 addr) {
if (addr == sym_addr && sym_size == 0) {
return true;
}
if (sym_size == 0) {
return false;
}
return RZ_BETWEEN(sym_addr, addr, sym_addr + sym_size - 1);
}

/**
* \brief The percentage of the mapped memory region returned for the given address.
*
* \param core RzCore
* \param addr The given address
* \return percentage of mapped memory region, or -1 if not in mapped memory or error happens
*/
static float get_percentage_of_mapped_region(RzCore *core, ut64 addr) {
rz_return_val_if_fail(core, -1);

float percentage = -1;
RzBinObject *bin_obj = rz_bin_cur_object(core->bin);
RzPVector *sections = rz_bin_object_get_sections(bin_obj);
if (!sections) {
return -1;
}

RzBinSection *section;
void **iter;
rz_pvector_foreach (sections, iter) {
section = *iter;
if (is_in_symbol_range(section->vaddr, section->vsize, addr)) {
// calculate the percentage
percentage = (addr - section->vaddr) / (float)section->vsize;
break;
}
}

rz_pvector_free(sections);
return percentage;
}

/**
* \brief Get the address of the data of the row at the bottom of the screen
* for calculating file percentage
*
* \param core RzCore
* \return captured address
*/
static RZ_OWN char *screen_bottom_address(RzCore *core) {
rz_return_val_if_fail(core, NULL);

char *rtn = NULL;
// get the line at the bottom of the screen
if (!core->cons->lastline) {
return NULL;
}
char *output = strdup(core->cons->lastline);
size_t line_count = 0, *line_index = rz_str_split_lines(output, &line_count);
int rows;
rz_cons_get_size(&rows);
if (!line_index || rows > line_count) {
goto exit1;
}
char *lastline = output + line_index[rows - 1];

// capture the address from the line at the bottom
char *regex_str = ((RzCoreVisual *)core->visual)->printidx == RZ_CORE_VISUAL_MODE_CD ? "[0-9abcdefABCDEF]+" : "0x[0-9ABCDEFabcdef]+";
RzRegex *re = rz_regex_new(regex_str, RZ_REGEX_EXTENDED, 0);
RzPVector *matches = rz_regex_match_all_not_grouped(re, lastline, RZ_REGEX_ZERO_TERMINATED, 0, RZ_REGEX_DEFAULT);
if (!matches || rz_pvector_empty(matches)) {
goto exit;
}

RzRegexMatch *match = rz_pvector_at(matches, 0);
rtn = rz_str_ndup(lastline + match->start, match->len);

// filter address in command, xref like ; CALL XREF from entry.fini0 @ 0x6b67
char *comment_signs[] = { "@", ";" };
char *addr_pos = strstr(lastline, rtn);
for (ut32 i = 0; i < sizeof(comment_signs) / sizeof(comment_signs[0]); i++) {
const char *sign_pos = rz_str_strchr(lastline, comment_signs[i]);
if (sign_pos) {
if (addr_pos && addr_pos > sign_pos) {
rtn = NULL;
}
}
}

// in case the address doesn't have 0x prefix (RZ_CORE_VISUAL_MODE_CD)
if (rtn && !rz_str_startswith_icase(rtn, "0x")) {
ut32 addr_len = strlen(rtn), prefix_len = strlen("0x");
rtn = realloc(rtn, prefix_len + addr_len + 1);
memmove(rtn + 2, rtn, addr_len);
rtn[0] = '0';
rtn[1] = 'x';
}

exit:
rz_pvector_free(matches);
rz_regex_free(re);
exit1:
free(line_index);
free(output);
return rtn;
}

static void visual_refresh(RzCore *core) {
static ut64 oseek = UT64_MAX;
const char *vi, *vcmd, *cmd_str;
Expand Down Expand Up @@ -3606,6 +3713,14 @@ static void visual_refresh(RzCore *core) {
}
#endif

// get the address in the line at the bottom of the screen to calculate the percentage
char *bottom_addr = screen_bottom_address(core);
if (bottom_addr) {
ut64 addr = rz_num_math(NULL, bottom_addr);
visual->percentage = get_percentage_of_mapped_region(core, addr);
free(bottom_addr);
}

/* this is why there's flickering */
if (core->print->vflush) {
rz_cons_visual_flush();
Expand All @@ -3624,6 +3739,15 @@ static void visual_refresh(RzCore *core) {
if (rz_config_get_i(core->config, "scr.scrollbar")) {
rz_core_visual_scrollbar(core);
}

int h, cols = rz_cons_get_size(&h);
if (visual->percentage >= 0) {
char *percentage_str = rz_str_newf("%.1f%%", visual->percentage * 100);
rz_cons_gotoxy(cols - strlen(percentage_str) - 1, h);
rz_cons_printf("%s", percentage_str);
rz_cons_flush();
free(percentage_str);
}
}

static void visual_refresh_oneshot(RzCore *core) {
Expand Down Expand Up @@ -3831,6 +3955,7 @@ RZ_IPI int rz_core_visual(RzCore *core, const char *input) {

rz_cons_enable_mouse(false);
if (visual->color) {

rz_cons_strcat(Color_RESET);
}
rz_config_set_i(core->config, "scr.color", visual->color);
Expand Down
27 changes: 26 additions & 1 deletion librz/core/tui/vmenus.c
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,7 @@ static ut64 var_variables_show(RzCore *core, int idx, int *vindex, int show, int

static int level = 0;
static st64 delta = 0;
static ut64 column_nlines = 0;
// output is used to store the result of printCmds
// and avoid duplicated analysis while j and k is pressed
static char *output = NULL;
Expand Down Expand Up @@ -289,7 +290,16 @@ static void rz_core_visual_analysis_refresh_column(RzCore *core, int colpos) {
free(cmdf);
}
if (output) {
// 'h - 2' because we have two new lines in rz_cons_printf
// count the lines of output for calculating percentage
column_nlines = 0;
char *s = output;
while (*s) {
if (*s == '\n') {
column_nlines++;
}
s++;
}
// crop and print output, 'h - 2' because we have two new lines in rz_cons_printf
char *out;
if (printMode == 1) {
out = rz_str_ansi_crop(output, 0, 0, w - colpos, h - 2);
Expand Down Expand Up @@ -453,6 +463,19 @@ static ut64 rz_core_visual_analysis_refresh(RzCore *core) {
rz_warn_if_reached();
break;
}

// print percentage at right corner
cols = rz_cons_get_size(&h);
float p = (float)(delta + h - 2) / (float)column_nlines;
if (p > 1) {
p = 1;
}
char *percentage = rz_str_newf("%.1f%%", p * 100);
// move to the right corner
rz_cons_gotoxy(cols - strlen(percentage) - 1, h);
rz_cons_printf("%s", percentage);
free(percentage);
rz_cons_show_cursor(false);
rz_cons_flush();
return addr;
}
Expand Down Expand Up @@ -708,11 +731,13 @@ RZ_IPI void rz_core_visual_analysis(RzCore *core, const char *input) {
}
break;
case ':': {
rz_cons_show_cursor(true);
ut64 orig = core->offset;
rz_core_seek(core, addr, false);
while (rz_core_visual_prompt(core))
;
rz_core_seek(core, orig, false);
rz_cons_show_cursor(false);
}
continue;
case '/':
Expand Down
2 changes: 1 addition & 1 deletion test/db/cmd/cmd_visual
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ EXPECT=<<EOF
0x00005b40 488d 3d21 c701 0048 8d35 1ac7 0100 4829 H.=!...H.5....H)
0x00005b50 fe48 c1fe 0348 89f0 48c1 e83f 4801 c648 .H...H..H..?H..H
0x00005b60 d1fe 7414 488b 053d c401 0048 85c0 7408 ..t.H..=...H..t.
0x00005b70 ffe0 660f 1f44 0000 c30f 1f80 0000 0000 ..f..D.......... [?25h
0x00005b70 ffe0 660f 1f44 0000 c30f 1f80 0000 0000 ..f..D.......... 9.2%[?25h
EOF
RUN

Expand Down

0 comments on commit e99dbd9

Please sign in to comment.