Use portable Format for Graph Metrics in Zignatures
This commit is contained in:
parent
c023766f50
commit
1907784363
5 changed files with 136 additions and 124 deletions
|
|
@ -220,7 +220,7 @@ RZ_API bool rz_sign_deserialize(RzAnalysis *a, RzSignItem *it, const char *k, co
|
|||
}
|
||||
|
||||
// Deserialize key: zign|space|name
|
||||
int n = rz_str_split(k2, '|');
|
||||
size_t n = rz_str_split(k2, '|');
|
||||
if (n != 3) {
|
||||
eprintf("Warning: Skipping signature with invalid key (%s)\n", k);
|
||||
success = false;
|
||||
|
|
@ -271,15 +271,29 @@ RZ_API bool rz_sign_deserialize(RzAnalysis *a, RzSignItem *it, const char *k, co
|
|||
DBL_VAL_FAIL(it->comment, RZ_SIGN_COMMENT);
|
||||
it->comment = strdup(token);
|
||||
break;
|
||||
case RZ_SIGN_GRAPH:
|
||||
case RZ_SIGN_GRAPH: {
|
||||
DBL_VAL_FAIL(it->graph, RZ_SIGN_GRAPH);
|
||||
if (strlen(token) == 2 * sizeof(RzSignGraph)) {
|
||||
it->graph = RZ_NEW0(RzSignGraph);
|
||||
if (it->graph) {
|
||||
rz_hex_str2bin(token, (ut8 *)it->graph);
|
||||
}
|
||||
char *s = strdup(token);
|
||||
if (!s) {
|
||||
break;
|
||||
}
|
||||
size_t gn = rz_str_split(s, ',');
|
||||
if (gn == 5) {
|
||||
it->graph = RZ_NEW0(RzSignGraph);
|
||||
const char *t = s;
|
||||
it->graph->cc = atoi(t);
|
||||
t = rz_str_word_get_next0(t);
|
||||
it->graph->nbbs = atoi(t);
|
||||
t = rz_str_word_get_next0(t);
|
||||
it->graph->edges = atoi(t);
|
||||
t = rz_str_word_get_next0(t);
|
||||
it->graph->ebbs = atoi(t);
|
||||
t = rz_str_word_get_next0(t);
|
||||
it->graph->bbsum = atoi(t);
|
||||
}
|
||||
free(s);
|
||||
break;
|
||||
}
|
||||
case RZ_SIGN_OFFSET:
|
||||
DBL_VAL_FAIL((it->addr != UT64_MAX), RZ_SIGN_OFFSET);
|
||||
it->addr = atoll(token);
|
||||
|
|
@ -389,125 +403,120 @@ static void serializeKeySpaceStr(RzAnalysis *a, const char *space, const char *n
|
|||
|
||||
static void serialize(RzAnalysis *a, RzSignItem *it, char *k, char *v) {
|
||||
RzListIter *iter = NULL;
|
||||
char *hexbytes = NULL, *hexmask = NULL, *hexgraph = NULL;
|
||||
char *hexbytes = NULL, *hexmask = NULL;
|
||||
char *refs = NULL, *xrefs = NULL, *ref = NULL, *var, *vars = NULL;
|
||||
char *type, *types = NULL;
|
||||
int i = 0, len = 0;
|
||||
RzSignBytes *bytes = it->bytes;
|
||||
RzSignGraph *graph = it->graph;
|
||||
RzSignHash *hash = it->hash;
|
||||
|
||||
if (k) {
|
||||
serializeKey(a, it->space, it->name, k);
|
||||
}
|
||||
if (v) {
|
||||
if (bytes) {
|
||||
len = bytes->size * 2 + 1;
|
||||
hexbytes = calloc(1, len);
|
||||
hexmask = calloc(1, len);
|
||||
if (!hexbytes || !hexmask) {
|
||||
free(hexbytes);
|
||||
free(hexmask);
|
||||
return;
|
||||
}
|
||||
if (!bytes->bytes) {
|
||||
bytes->bytes = malloc((bytes->size + 1) * 3);
|
||||
}
|
||||
rz_hex_bin2str(bytes->bytes, bytes->size, hexbytes);
|
||||
if (!bytes->mask) {
|
||||
bytes->mask = malloc((bytes->size + 1) * 3);
|
||||
}
|
||||
rz_hex_bin2str(bytes->mask, bytes->size, hexmask);
|
||||
}
|
||||
if (graph) {
|
||||
hexgraph = calloc(1, sizeof(RzSignGraph) * 2 + 1);
|
||||
if (hexgraph) {
|
||||
rz_hex_bin2str((ut8 *)graph, sizeof(RzSignGraph), hexgraph);
|
||||
}
|
||||
}
|
||||
i = 0;
|
||||
rz_list_foreach (it->refs, iter, ref) {
|
||||
if (i > 0) {
|
||||
refs = rz_str_appendch(refs, ',');
|
||||
}
|
||||
refs = rz_str_append(refs, ref);
|
||||
i++;
|
||||
}
|
||||
i = 0;
|
||||
rz_list_foreach (it->xrefs, iter, ref) {
|
||||
if (i > 0) {
|
||||
xrefs = rz_str_appendch(xrefs, ',');
|
||||
}
|
||||
xrefs = rz_str_append(xrefs, ref);
|
||||
i++;
|
||||
}
|
||||
i = 0;
|
||||
rz_list_foreach (it->vars, iter, var) {
|
||||
if (i > 0) {
|
||||
vars = rz_str_appendch(vars, ',');
|
||||
}
|
||||
vars = rz_str_append(vars, var);
|
||||
i++;
|
||||
}
|
||||
i = 0;
|
||||
rz_list_foreach (it->types, iter, type) {
|
||||
if (i > 0) {
|
||||
types = rz_str_appendch(types, ',');
|
||||
}
|
||||
types = rz_str_append(types, type);
|
||||
i++;
|
||||
}
|
||||
RzStrBuf *sb = rz_strbuf_new("");
|
||||
if (bytes) {
|
||||
// TODO: do not hardcoded s,b,m here, use RzSignType enum
|
||||
rz_strbuf_appendf(sb, "|s:%d|b:%s|m:%s", bytes->size, hexbytes, hexmask);
|
||||
}
|
||||
if (it->addr != UT64_MAX) {
|
||||
rz_strbuf_appendf(sb, "|%c:%" PFMT64d, RZ_SIGN_OFFSET, it->addr);
|
||||
}
|
||||
if (graph) {
|
||||
rz_strbuf_appendf(sb, "|%c:%s", RZ_SIGN_GRAPH, hexgraph);
|
||||
}
|
||||
if (refs) {
|
||||
rz_strbuf_appendf(sb, "|%c:%s", RZ_SIGN_REFS, refs);
|
||||
}
|
||||
if (xrefs) {
|
||||
rz_strbuf_appendf(sb, "|%c:%s", RZ_SIGN_XREFS, xrefs);
|
||||
}
|
||||
if (vars) {
|
||||
rz_strbuf_appendf(sb, "|%c:%s", RZ_SIGN_VARS, vars);
|
||||
}
|
||||
if (types) {
|
||||
rz_strbuf_appendf(sb, "|%c:%s", RZ_SIGN_TYPES, types);
|
||||
}
|
||||
if (it->comment) {
|
||||
// b64 encoded
|
||||
rz_strbuf_appendf(sb, "|%c:%s", RZ_SIGN_COMMENT, it->comment);
|
||||
}
|
||||
if (it->realname) {
|
||||
// b64 encoded
|
||||
rz_strbuf_appendf(sb, "|%c:%s", RZ_SIGN_NAME, it->realname);
|
||||
}
|
||||
if (hash && hash->bbhash) {
|
||||
rz_strbuf_appendf(sb, "|%c:%s", RZ_SIGN_BBHASH, hash->bbhash);
|
||||
}
|
||||
if (rz_strbuf_length(sb) >= RZ_SIGN_VAL_MAXSZ) {
|
||||
eprintf("Signature limit reached for 0x%08" PFMT64x " (%s)\n", it->addr, it->name);
|
||||
}
|
||||
char *res = rz_strbuf_drain(sb);
|
||||
if (res) {
|
||||
strncpy(v, res, RZ_SIGN_VAL_MAXSZ);
|
||||
free(res);
|
||||
}
|
||||
|
||||
free(hexbytes);
|
||||
free(hexmask);
|
||||
free(hexgraph);
|
||||
free(refs);
|
||||
free(vars);
|
||||
free(xrefs);
|
||||
free(types);
|
||||
if (!v) {
|
||||
return;
|
||||
}
|
||||
if (bytes) {
|
||||
len = bytes->size * 2 + 1;
|
||||
hexbytes = calloc(1, len);
|
||||
hexmask = calloc(1, len);
|
||||
if (!hexbytes || !hexmask) {
|
||||
free(hexbytes);
|
||||
free(hexmask);
|
||||
return;
|
||||
}
|
||||
if (!bytes->bytes) {
|
||||
bytes->bytes = malloc((bytes->size + 1) * 3);
|
||||
}
|
||||
rz_hex_bin2str(bytes->bytes, bytes->size, hexbytes);
|
||||
if (!bytes->mask) {
|
||||
bytes->mask = malloc((bytes->size + 1) * 3);
|
||||
}
|
||||
rz_hex_bin2str(bytes->mask, bytes->size, hexmask);
|
||||
}
|
||||
i = 0;
|
||||
rz_list_foreach (it->refs, iter, ref) {
|
||||
if (i > 0) {
|
||||
refs = rz_str_appendch(refs, ',');
|
||||
}
|
||||
refs = rz_str_append(refs, ref);
|
||||
i++;
|
||||
}
|
||||
i = 0;
|
||||
rz_list_foreach (it->xrefs, iter, ref) {
|
||||
if (i > 0) {
|
||||
xrefs = rz_str_appendch(xrefs, ',');
|
||||
}
|
||||
xrefs = rz_str_append(xrefs, ref);
|
||||
i++;
|
||||
}
|
||||
i = 0;
|
||||
rz_list_foreach (it->vars, iter, var) {
|
||||
if (i > 0) {
|
||||
vars = rz_str_appendch(vars, ',');
|
||||
}
|
||||
vars = rz_str_append(vars, var);
|
||||
i++;
|
||||
}
|
||||
i = 0;
|
||||
rz_list_foreach (it->types, iter, type) {
|
||||
if (i > 0) {
|
||||
types = rz_str_appendch(types, ',');
|
||||
}
|
||||
types = rz_str_append(types, type);
|
||||
i++;
|
||||
}
|
||||
RzStrBuf *sb = rz_strbuf_new("");
|
||||
if (bytes) {
|
||||
// TODO: do not hardcoded s,b,m here, use RzSignType enum
|
||||
rz_strbuf_appendf(sb, "|s:%d|b:%s|m:%s", bytes->size, hexbytes, hexmask);
|
||||
}
|
||||
if (it->addr != UT64_MAX) {
|
||||
rz_strbuf_appendf(sb, "|%c:%" PFMT64d, RZ_SIGN_OFFSET, it->addr);
|
||||
}
|
||||
if (it->graph) {
|
||||
rz_strbuf_appendf(sb, "|%c:%d,%d,%d,%d,%d", RZ_SIGN_GRAPH,
|
||||
it->graph->cc, it->graph->nbbs, it->graph->edges,
|
||||
it->graph->ebbs, it->graph->bbsum);
|
||||
}
|
||||
if (refs) {
|
||||
rz_strbuf_appendf(sb, "|%c:%s", RZ_SIGN_REFS, refs);
|
||||
}
|
||||
if (xrefs) {
|
||||
rz_strbuf_appendf(sb, "|%c:%s", RZ_SIGN_XREFS, xrefs);
|
||||
}
|
||||
if (vars) {
|
||||
rz_strbuf_appendf(sb, "|%c:%s", RZ_SIGN_VARS, vars);
|
||||
}
|
||||
if (types) {
|
||||
rz_strbuf_appendf(sb, "|%c:%s", RZ_SIGN_TYPES, types);
|
||||
}
|
||||
if (it->comment) {
|
||||
// b64 encoded
|
||||
rz_strbuf_appendf(sb, "|%c:%s", RZ_SIGN_COMMENT, it->comment);
|
||||
}
|
||||
if (it->realname) {
|
||||
// b64 encoded
|
||||
rz_strbuf_appendf(sb, "|%c:%s", RZ_SIGN_NAME, it->realname);
|
||||
}
|
||||
if (hash && hash->bbhash) {
|
||||
rz_strbuf_appendf(sb, "|%c:%s", RZ_SIGN_BBHASH, hash->bbhash);
|
||||
}
|
||||
if (rz_strbuf_length(sb) >= RZ_SIGN_VAL_MAXSZ) {
|
||||
eprintf("Signature limit reached for 0x%08" PFMT64x " (%s)\n", it->addr, it->name);
|
||||
}
|
||||
char *res = rz_strbuf_drain(sb);
|
||||
if (res) {
|
||||
strncpy(v, res, RZ_SIGN_VAL_MAXSZ);
|
||||
free(res);
|
||||
}
|
||||
|
||||
free(hexbytes);
|
||||
free(hexmask);
|
||||
free(refs);
|
||||
free(vars);
|
||||
free(xrefs);
|
||||
free(types);
|
||||
}
|
||||
|
||||
static RzList *deserialize_sign_space(RzAnalysis *a, RzSpace *space) {
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ RZ_API char *rz_str_sanitize_sdb_key(const char *s);
|
|||
RZ_API const char *rz_str_casestr(const char *a, const char *b);
|
||||
RZ_API const char *rz_str_firstbut(const char *s, char ch, const char *but);
|
||||
RZ_API const char *rz_str_lastbut(const char *s, char ch, const char *but);
|
||||
RZ_API int rz_str_split(char *str, char ch);
|
||||
RZ_API size_t rz_str_split(char *str, char ch);
|
||||
RZ_API RzList *rz_str_split_list(char *str, const char *c, int n);
|
||||
RZ_API RzList *rz_str_split_duplist(const char *str, const char *c, bool trim);
|
||||
RZ_API RzList *rz_str_split_duplist_n(const char *str, const char *c, int n, bool trim);
|
||||
|
|
@ -102,6 +102,9 @@ RZ_API int rz_str_char_count(const char *string, char ch);
|
|||
RZ_API char *rz_str_word_get0set(char *stra, int stralen, int idx, const char *newstr, int *newlen);
|
||||
RZ_API int rz_str_word_set0(char *str);
|
||||
RZ_API int rz_str_word_set0_stack(char *str);
|
||||
static inline const char *rz_str_word_get_next0(const char *str) {
|
||||
return str + strlen(str) + 1;
|
||||
}
|
||||
RZ_API const char *rz_str_word_get0(const char *str, int idx);
|
||||
RZ_API char *rz_str_word_get_first(const char *string);
|
||||
RZ_API void rz_str_trim(char *str);
|
||||
|
|
|
|||
|
|
@ -328,9 +328,9 @@ RZ_API int rz_str_delta(char *p, char a, char b) {
|
|||
* Replaces all instances of \p ch in \p str with a NULL byte and it returns
|
||||
* the number of split strings.
|
||||
*/
|
||||
RZ_API int rz_str_split(char *str, char ch) {
|
||||
RZ_API size_t rz_str_split(char *str, char ch) {
|
||||
rz_return_val_if_fail(str, 0);
|
||||
int i;
|
||||
size_t i;
|
||||
char *p;
|
||||
for (i = 1, p = str; *p; p++) {
|
||||
if (*p == ch) {
|
||||
|
|
@ -524,10 +524,10 @@ RZ_API const char *rz_str_word_get0(const char *str, int idx) {
|
|||
int i;
|
||||
const char *ptr = str;
|
||||
if (!ptr || idx < 0 /* prevent crashes with negative index */) {
|
||||
return (char *)nullstr;
|
||||
return nullstr;
|
||||
}
|
||||
for (i = 0; i != idx; i++) {
|
||||
ptr += strlen(ptr) + 1;
|
||||
ptr = rz_str_word_get_next0(ptr);
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1434,7 +1434,7 @@ Sdb *sign_ref_db() {
|
|||
sdb_set(spaces, "name", "zs", 0);
|
||||
Sdb *spaces_spaces = sdb_ns(spaces, "spaces", true);
|
||||
sdb_set(spaces_spaces, "koridai", "s", 0);
|
||||
sdb_set(db, "zign|*|sym.mahboi", "|s:4|b:deadbeef|m:c0ffee42|o:4919|g:7b0000000b0000000c0000000d0000002a000000|r:gwonam,link|x:king,ganon|v:r16,s42,b13|t:func.sym.mahboi.ret=char *,func.sym.mahboi.args=2,func.sym.mahboi.arg.0=\"int,arg0\",func.sym.mahboi.arg.1=\"uint32_t,die\"|c:This peace is what all true warriors strive for|n:sym.Mah.Boi|h:7bfa1358c427e26bc03c2384f41de7be6ebc01958a57e9a6deda5bdba9768851", 0);
|
||||
sdb_set(db, "zign|*|sym.mahboi", "|s:4|b:deadbeef|m:c0ffee42|o:4919|g:123,11,12,13,42|r:gwonam,link|x:king,ganon|v:r16,s42,b13|t:func.sym.mahboi.ret=char *,func.sym.mahboi.args=2,func.sym.mahboi.arg.0=\"int,arg0\",func.sym.mahboi.arg.1=\"uint32_t,die\"|c:This peace is what all true warriors strive for|n:sym.Mah.Boi|h:7bfa1358c427e26bc03c2384f41de7be6ebc01958a57e9a6deda5bdba9768851", 0);
|
||||
sdb_set(db, "zign|koridai|sym.boring", "|c:gee it sure is boring around here", 0);
|
||||
return db;
|
||||
}
|
||||
|
|
@ -1836,4 +1836,4 @@ int all_tests() {
|
|||
return tests_passed != tests_run;
|
||||
}
|
||||
|
||||
mu_main(all_tests)
|
||||
mu_main(all_tests)
|
||||
|
|
|
|||
|
|
@ -149,7 +149,7 @@ bool test_rz_str_case(void) {
|
|||
|
||||
bool test_rz_str_split(void) {
|
||||
char *hi = strdup("hello world");
|
||||
int r = rz_str_split(hi, ' ');
|
||||
size_t r = rz_str_split(hi, ' ');
|
||||
mu_assert_eq(r, 2, "split on space");
|
||||
char *hello = hi;
|
||||
char *world = hi + 6;
|
||||
|
|
|
|||
Loading…
Reference in a new issue