Update SDB and initial use of MHT for xrefs (disabled by default)

This commit is contained in:
pancake 2017-12-11 18:00:14 +01:00
parent 3570f6c669
commit ce77004507
15 changed files with 473 additions and 19 deletions

View File

@ -80,6 +80,8 @@ R_API RAnal *r_anal_new() {
anal->sdb_types = sdb_ns (anal->sdb, "types", 1);
anal->sdb_cc = sdb_ns (anal->sdb, "cc", 1);
anal->sdb_zigns = sdb_ns (anal->sdb, "zigns", 1);
anal->mht_refs = mht_new (32, mht_free);
anal->mht_xrefs = mht_new (32, mht_free);
anal->cb_printf = (PrintfCallback) printf;
(void)r_anal_pin_init (anal);
(void)r_anal_xrefs_init (anal);

View File

@ -163,7 +163,7 @@ static bool refExists(RList *refs, RAnalRef *ref) {
RAnalRef *r;
RListIter *iter;
r_list_foreach (refs, iter, r) {
if (r->at == ref->at && ref->addr == r->addr) {
if (r && r->at == ref->at && ref->addr == r->addr) {
r->type = ref->type;
return true;
}
@ -184,9 +184,11 @@ R_API int r_anal_fcn_xref_add(RAnal *a, RAnalFunction *fcn, ut64 at, ut64 addr,
return false;
}
// set global reference
// r_cons_printf ("C 0x%llx 0x%llx\n", at, addr);
r_anal_xrefs_set (a, type, at, addr);
// set per-function reference
#if FCN_OLD
// TOO OLD we shouldnt be storing this.. or we do?
ref->at = at; // from
ref->addr = addr; // to
ref->type = type;

View File

@ -47,11 +47,23 @@ R_API const char *r_anal_ref_to_string(RAnal *anal, int type) {
}
R_API int r_anal_ref_del(RAnal *anal, ut64 from, ut64 to) {
#if USE_MHT
// TODO Must delete from mht_refs too
mht *m = anal->mht_xrefs;
mhtkv *kv = mht_getr (m, from);
if (kv) {
mht *ht = kv->u;
if (ht) {
mht_del (ht, to);
}
}
#else
r_anal_xrefs_deln (anal, R_ANAL_REF_TYPE_NULL, from, to);
r_anal_xrefs_deln (anal, R_ANAL_REF_TYPE_CODE, from, to);
r_anal_xrefs_deln (anal, R_ANAL_REF_TYPE_CALL, from, to);
r_anal_xrefs_deln (anal, R_ANAL_REF_TYPE_DATA, from, to);
r_anal_xrefs_deln (anal, R_ANAL_REF_TYPE_STRING, from, to);
#endif
return true;
}

View File

@ -36,6 +36,84 @@ R_API bool r_anal_xrefs_save(RAnal *anal, const char *prjDir) {
return sdb_sync (anal->sdb_xrefs);
}
#if USE_MHT
static void mylistrefs(mht *m, ut64 addr, RList *list) {
int i, j;
for (i = 0; i < m->size; i++) {
mhtkv *kv = m->table[i];
if (!kv) continue;
while (kv->k != MHTNO) {
if (addr == UT64_MAX || addr == kv->k) {
RAnalRef *ref = r_anal_ref_new ();
if (ref) {
#if 0
eprintf ("%s 0x%08llx -> 0x%08llx (0x%llx)\n",
kv->u, kv->k, kv->v, addr);
#endif
ref->at = kv->k;
ref->addr = kv->v;
ref->type = kv->u ? *((char *)kv->u): 0;
r_list_append (list, ref);
}
}
kv++;
}
}
}
static void listrefs(mht *m, ut64 addr, RList *list) {
int i;
if (addr == UT64_MAX) {
for (i = 0; i < m->size; i++) {
mhtkv *kv = m->table[i];
if (kv) {
mht *ht = kv->u;
while (kv->k != MHTNO) {
mylistrefs (ht, UT64_MAX, list);
kv++;
}
}
}
} else {
mht *ht = mht_getu (m, addr);
if (!ht) {
return;
}
mylistrefs (ht, addr, list);
}
}
// [from=[from:to,],]
// 10->20
static void setref(mht *m, ut64 from, ut64 to, int type) {
mhtkv *kv = mht_getr (m, from);
mht *ht = NULL;
if (kv) {
ht = kv->u;
} else {
ht = R_NEW0 (mht);
if (ht) {
mht_init (ht, 9, mht_free);
mht_set (m, from, to, ht);
}
}
if (ht) {
mht_set (ht, from, to, r_anal_xrefs_type_tostring (type));
}
}
static void delref(mht *m, ut64 from, ut64 to, int type) {
mhtkv *kv = mht_getr (m, from);
if (kv) {
mht *ht = kv->u;
if (ht) {
mht_del (ht, to);
}
}
}
#endif
R_API int r_anal_xrefs_set (RAnal *anal, const RAnalRefType type, ut64 from, ut64 to) {
char key[33];
if (!anal || !DB) {
@ -45,13 +123,26 @@ R_API int r_anal_xrefs_set (RAnal *anal, const RAnalRefType type, ut64 from, ut6
return false;
}
// unknown refs should not be stored. seems wrong
#if 0
if (type == R_ANAL_REF_TYPE_NULL) {
return false;
}
#endif
#if USE_MHT
// setref (anal->mht_refs, from, to, type);
setref (anal->mht_xrefs, to, from, type);
// setref (anal->mht_xrefs, from, to, type);
// setref (anal->mht_refs, to, from, type);
// eprintf ("set %llx %llx %p\n", from , to, mht_getr(anal->mht_refs, from));
// mht_getu(m, from, checkType, "ref");
#else
XREFKEY (key, sizeof (key), "ref", type, from);
sdb_array_add_num (DB, key, to, 0);
XREFKEY (key, sizeof (key), "xref", type, to);
sdb_array_add_num (DB, key, from, 0);
#endif
return true;
}
@ -60,10 +151,15 @@ R_API int r_anal_xrefs_deln (RAnal *anal, const RAnalRefType type, ut64 from, ut
if (!anal || !DB) {
return false;
}
#if USE_MHT
delref (anal->mht_refs, from, to, type);
delref (anal->mht_xrefs, to, from, type);
#else
XREFKEY (key, sizeof (key), "ref", type, from);
sdb_array_remove_num (DB, key, to, 0);
XREFKEY (key, sizeof (key), "xref", type, to);
sdb_array_remove_num (DB, key, from, 0);
#endif
return true;
}
@ -120,11 +216,18 @@ R_API RList *r_anal_xrefs_get (RAnal *anal, ut64 to) {
if (!list) {
return NULL;
}
#if USE_MHT
listrefs (anal->mht_refs, to, list);
// XXX, one or the other?
listrefs (anal->mht_xrefs, to, list);
// listrefs (anal->mht_xrefs, to, list);
#else
r_anal_xrefs_from (anal, list, "xref", R_ANAL_REF_TYPE_NULL, to);
r_anal_xrefs_from (anal, list, "xref", R_ANAL_REF_TYPE_CODE, to);
r_anal_xrefs_from (anal, list, "xref", R_ANAL_REF_TYPE_CALL, to);
r_anal_xrefs_from (anal, list, "xref", R_ANAL_REF_TYPE_DATA, to);
r_anal_xrefs_from (anal, list, "xref", R_ANAL_REF_TYPE_STRING, to);
#endif
if (r_list_empty (list)) {
r_list_free (list);
list = NULL;
@ -137,11 +240,17 @@ R_API RList *r_anal_refs_get (RAnal *anal, ut64 from) {
if (!list) {
return NULL;
}
#if USE_MHT
listrefs (anal->mht_refs, from, list);
listrefs (anal->mht_xrefs, from, list);
// eprintf ("refs_get from %llx %d\n", from, r_list_length (list));
#else
r_anal_xrefs_from (anal, list, "ref", R_ANAL_REF_TYPE_NULL, from);
r_anal_xrefs_from (anal, list, "ref", R_ANAL_REF_TYPE_CODE, from);
r_anal_xrefs_from (anal, list, "ref", R_ANAL_REF_TYPE_CALL, from);
r_anal_xrefs_from (anal, list, "ref", R_ANAL_REF_TYPE_DATA, from);
r_anal_xrefs_from (anal, list, "ref", R_ANAL_REF_TYPE_STRING, from);
#endif
if (r_list_empty (list)) {
r_list_free (list);
list = NULL;
@ -155,15 +264,20 @@ R_API RList *r_anal_xrefs_get_from (RAnal *anal, ut64 to) {
return NULL;
}
list->free = NULL; // XXX
#if USE_MHT
listrefs (anal->mht_xrefs, to, list);
listrefs (anal->mht_refs, to, list);
#else
r_anal_xrefs_from (anal, list, "ref", R_ANAL_REF_TYPE_NULL, to);
r_anal_xrefs_from (anal, list, "ref", R_ANAL_REF_TYPE_CODE, to);
r_anal_xrefs_from (anal, list, "ref", R_ANAL_REF_TYPE_CALL, to);
r_anal_xrefs_from (anal, list, "ref", R_ANAL_REF_TYPE_DATA, to);
r_anal_xrefs_from (anal, list, "ref", R_ANAL_REF_TYPE_STRING, to);
if (r_list_length (list)<1) {
if (r_list_empty (list)) {
r_list_free (list);
list = NULL;
}
#endif
return list;
}
@ -289,6 +403,17 @@ static int xrefs_list_cb_plain(RAnal *anal, const char *k, const char *v) {
}
R_API void r_anal_xrefs_list(RAnal *anal, int rad) {
#if USE_MHT
RListIter *iter;
RAnalRef *ref;
RList *list = r_list_new();
listrefs (anal->mht_xrefs, UT64_MAX, list);
r_list_foreach (list, iter, ref) {
int type = ref->type? ref->type: ' ';
r_cons_printf ("%c 0x%08llx -> 0x%08llx\n", type, ref->at, ref->addr);
}
r_list_free (list);
#else
switch (rad) {
case 1:
case '*':
@ -318,6 +443,7 @@ R_API void r_anal_xrefs_list(RAnal *anal, int rad) {
sdb_foreach (DB, (SdbForeachCallback)xrefs_list_cb_plain, anal);
break;
}
#endif
}
R_API const char *r_anal_xrefs_type_tostring (char type) {
@ -342,8 +468,9 @@ typedef struct {
} CountState;
static int countcb(CountState *cs, const char *k, const char *v) {
if (!strncmp (k, "ref.", 4))
if (!strncmp (k, "ref.", 4)) {
cs->count ++;
}
return 1;
}

View File

@ -1077,7 +1077,6 @@ static void ds_show_refs(RDisasmState *ds) {
}
static void ds_show_xrefs(RDisasmState *ds) {
RList *xrefs;
RAnalRef *refi;
RListIter *iter;
RCore *core = ds->core;
@ -1089,7 +1088,7 @@ static void ds_show_xrefs(RDisasmState *ds) {
return;
}
/* show xrefs */
xrefs = r_anal_xref_get (core->anal, ds->at);
RList *xrefs = r_anal_xref_get (core->anal, ds->at);
if (!xrefs) {
return;
}
@ -1148,6 +1147,8 @@ static void ds_show_xrefs(RDisasmState *ds) {
refi->addr, name, COLOR_RESET (ds));
ds_newline (ds);
R_FREE (name);
} else {
eprintf ("Corrupted database?\n");
}
}
r_list_free (xrefs);

View File

@ -3,6 +3,8 @@
#ifndef R2_ANAL_H
#define R2_ANAL_H
#define USE_MHT 0
/* use sdb function storage */
#define FCN_SDB 1
/* use old refs and function storage */
@ -630,6 +632,10 @@ typedef struct r_anal_t {
Sdb *sdb_types;
Sdb *sdb_meta; // TODO: Future r_meta api
Sdb *sdb_zigns;
mht *mht_refs;
mht *mht_xrefs;
RSpaces meta_spaces;
RSpaces zign_spaces;
char *zign_path;

47
libr/include/sdb/mht.h Normal file
View File

@ -0,0 +1,47 @@
#define MHTSZ 32
#define MHTNO 0
typedef ut64 mhti;
typedef struct {
mhti k;
mhti v;
void *u;
#if 0
// unaligned
// on 32bits
void *pad;
// on 64bits
void *pad;
#endif
} mhtkv;
// 4 + 4 + 4 = 12 .. missing 4 more
// 8 + 8 + 4 = 20 .. missing 16, what about 32 ?
// 8 + 8 + 8 = 24 .. still not there, missing 8
// 4 + 4 + 8 = 16 .. lgtm
typedef void (*mht_freecb)(void *);
typedef struct {
void **table; //[MHTSZ];
mht_freecb f;
ut32 size;
} mht;
typedef mht SdbMini;
mht *mht_new(ut32 size, mht_freecb f);
void mht_free(mht*);
void mht_init(mht *m, ut32, mht_freecb f);
void mht_fini(mht *m);
mhti mht_hash(const char *s);
bool mht_set(mht *m, mhti k, mhti v, void *u);
mhtkv *mht_getr(mht *m, mhti k);
mhtkv *mht_getr(mht *m, mhti k);
mhti mht_get(mht *m, mhti k);
mhti mht_get(mht *m, mhti k);
void *mht_getu(mht *m, mhti k);
bool mht_add(mht *m, mhti k, mhti v, void *u);
bool mht_del(mht *m, mhti k);

View File

@ -12,6 +12,7 @@ extern "C" {
#include "types.h"
#include "sdbht.h"
#include "ls.h"
#include "mht.h"
#include "cdb.h"
#include "cdb_make.h"
#include "sdb_version.h"
@ -100,6 +101,7 @@ typedef struct sdb_t {
SdbKv tmpkv;
ut32 depth;
bool timestamped;
SdbMini mht;
} Sdb;
typedef struct sdb_ns_t {
@ -209,12 +211,13 @@ SDB_API int sdb_unlink(Sdb* s);
SDB_API int sdb_lock_wait(const char *s UNUSED);
/* expiration */
bool sdb_expire_set(Sdb* s, const char *key, ut64 expire, ut32 cas);
ut64 sdb_expire_get(Sdb* s, const char *key, ut32 *cas);
ut64 sdb_now(void);
ut64 sdb_unow(void);
ut32 sdb_hash(const char *key);
ut32 sdb_hash_len(const char *key, ut32 *len);
SDB_API bool sdb_expire_set(Sdb* s, const char *key, ut64 expire, ut32 cas);
SDB_API ut64 sdb_expire_get(Sdb* s, const char *key, ut32 *cas);
SDB_API ut64 sdb_now(void);
SDB_API ut64 sdb_unow(void);
SDB_API ut32 sdb_hash(const char *key);
SDB_API ut32 sdb_hash_len(const char *key, ut32 *len);
SDB_API ut8 sdb_hash_byte(const char *s);
/* json api */
SDB_API bool sdb_isjson(const char *k);

View File

@ -16,6 +16,7 @@ SDB_OBJS+=query.o
SDB_OBJS+=sdb.o
SDB_OBJS+=base64.o
SDB_OBJS+=disk.o
SDB_OBJS+=mht.o
SDB_OBJS+=array.o
SDB_OBJS+=fmt.o
SDB_OBJS+=match.o

View File

@ -3,6 +3,7 @@ include ../config.mk
CFLAGS+=-g
OBJ=cdb.o buffer.o cdb_make.o ls.o sdbht.o ht.o sdb.o num.o base64.o match.o
OBJ+=json.o ns.o lock.o util.o disk.o query.o array.o fmt.o journal.o
OBJ+=mht.o
SOBJ=$(subst .o,.o.o,${OBJ})

197
shlr/sdb/src/mht.c Normal file
View File

@ -0,0 +1,197 @@
/* sdb - MIT - Copyright 2017 - pancake */
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include "sdb.h"
mht *mht_new(ut32 size, mht_freecb f) {
mht *m = calloc(1, sizeof (mht));
mht_init (m, size, f);
return m;
}
void mht_init(mht *m, ut32 size, mht_freecb f) {
if (m) {
memset(m, 0, sizeof (mht));
if (size > 0) {
m->table = calloc (size, sizeof (mhtkv));
m->size = size;
}
m->f = f;
}
}
void mht_fini(mht *m) {
ut32 i;
if (m) {
if (m->f) {
for (i = 0; i < m->size; i++) {
mhtkv *kv = m->table[i];
if (kv) {
while (kv->k != MHTNO) {
m->f(kv->u);
kv++;
}
}
free (m->table[i]);
}
} else {
for (i = 0; i < m->size; i++) {
free (m->table[i]);
}
}
free (m->table);
mht_init(m, 0, NULL);
}
}
void mht_free(mht *m) {
mht_fini(m);
free (m);
}
mhti mht_hash(const char *s) {
return (mhti)sdb_hash(s);
}
bool mht_set(mht *m, mhti k, mhti v, void *u) {
if (!m || !m->size || k == MHTNO) {
return false;
}
const int bucket = k % m->size;
mhtkv *kv = m->table[bucket];
if (!kv) {
kv = calloc (sizeof(mhtkv), 2);
if (kv) {
m->table[bucket] = kv;
kv->k = MHTNO;
kv->v = MHTNO;
kv->u = NULL;
return mht_set(m, k, v, u);
}
return false;
}
mhtkv *tmp = kv;
while (kv->k != MHTNO) {
if (kv->k == k) {
kv->v = v;
kv->u = u;
return true;
}
kv++;
}
int cursz = (kv - tmp);
int curln = cursz / sizeof(mhtkv);
mhtkv *newkv = realloc(tmp, (curln + 2) * sizeof(mhtkv));
if (newkv) {
kv = m->table[bucket] = newkv;
kv += curln;
kv->k = k;
kv->v = v;
kv->u = u;
kv++;
kv->k = MHTNO;
kv->v = MHTNO;
kv->u = NULL;
return false;
}
return true;
}
mhtkv *mht_getr(mht *m, mhti k) {
int bucket = k % m->size;
mhtkv *kv = m->table[bucket];
if (kv) {
while (kv->k != MHTNO) {
if (kv->k == k) {
return kv;
}
kv++;
}
}
return NULL;
}
mhti mht_get(mht *m, mhti k) {
mhtkv *kv = mht_getr(m, k);
return kv? kv->v: MHTNO;
}
void *mht_getu(mht *m, mhti k) {
mhtkv *kv = mht_getr(m, k);
return kv? kv->u: NULL;
}
bool mht_add(mht *m, mhti k, mhti v, void *u) {
return mht_getr(m, k)
? mht_set(m, k, v, u)
: false;
}
bool mht_del(mht *m, mhti k) {
int bucket = k % m->size;
if (k == MHTNO) {
return false;
}
mhtkv *kv = m->table[bucket];
if (kv) {
while (kv->k != MHTNO) {
if (kv->k == k) {
if (m->f) {
m->f (kv->u);
}
mhtkv *n = kv + 1;
while (n->k != MHTNO) {
*kv++ = *n++;
}
kv->k = MHTNO;
return true;
}
kv++;
}
}
return false;
}
#if 0
static char *mht_str(mht *m, mhti k) {
// walk all buckets and print the data..... we need a printer for kv->u
char *res = malloc (1024);
int bucket = k % m->size;
mhti *kv = m->table[bucket];
char *p = res;
for (i = 0; i < 1024; i++) {
sprintf (p, "%s%lld", comma, kv->v);
p += strlen (p);
kv++;
}
return res;
}
static char *mht_str(mht *m) {
char *res = malloc (1024);
int bucket = k % m->size;
mhti *kv = m->table[bucket];
int i;
char *p = res;
for (i = 0; i < m->size; i++) {
sprintf (p, "%s%lld", comma, kv->v);
p += strlen (p);
kv++;
}
return res;
}
int main() {
mht m;
mht_init(&m, 32, free);
mht_set(&m, mht_hash("username"), 1024, NULL);
mht_set(&m, 32, 212, strdup("test"));
mht_del(&m, mht_hash("username"));
printf ("%d\n", (int)mht_get(&m, mht_hash("username")));
printf ("%s\n", mht_getu(&m, 32)); //mht_hash("username")));
mht_fini(&m);
return 0;
}
#endif

47
shlr/sdb/src/mht.h Normal file
View File

@ -0,0 +1,47 @@
#define MHTSZ 32
#define MHTNO 0
typedef ut64 mhti;
typedef struct {
mhti k;
mhti v;
void *u;
#if 0
// unaligned
// on 32bits
void *pad;
// on 64bits
void *pad;
#endif
} mhtkv;
// 4 + 4 + 4 = 12 .. missing 4 more
// 8 + 8 + 4 = 20 .. missing 16, what about 32 ?
// 8 + 8 + 8 = 24 .. still not there, missing 8
// 4 + 4 + 8 = 16 .. lgtm
typedef void (*mht_freecb)(void *);
typedef struct {
void **table; //[MHTSZ];
mht_freecb f;
ut32 size;
} mht;
typedef mht SdbMini;
mht *mht_new(ut32 size, mht_freecb f);
void mht_free(mht*);
void mht_init(mht *m, ut32, mht_freecb f);
void mht_fini(mht *m);
mhti mht_hash(const char *s);
bool mht_set(mht *m, mhti k, mhti v, void *u);
mhtkv *mht_getr(mht *m, mhti k);
mhtkv *mht_getr(mht *m, mhti k);
mhti mht_get(mht *m, mhti k);
mhti mht_get(mht *m, mhti k);
void *mht_getu(mht *m, mhti k);
bool mht_add(mht *m, mhti k, mhti v, void *u);
bool mht_del(mht *m, mhti k);

View File

@ -12,6 +12,7 @@ extern "C" {
#include "types.h"
#include "sdbht.h"
#include "ls.h"
#include "mht.h"
#include "cdb.h"
#include "cdb_make.h"
#include "sdb_version.h"
@ -100,6 +101,7 @@ typedef struct sdb_t {
SdbKv tmpkv;
ut32 depth;
bool timestamped;
SdbMini mht;
} Sdb;
typedef struct sdb_ns_t {
@ -209,12 +211,13 @@ SDB_API int sdb_unlink(Sdb* s);
SDB_API int sdb_lock_wait(const char *s UNUSED);
/* expiration */
bool sdb_expire_set(Sdb* s, const char *key, ut64 expire, ut32 cas);
ut64 sdb_expire_get(Sdb* s, const char *key, ut32 *cas);
ut64 sdb_now(void);
ut64 sdb_unow(void);
ut32 sdb_hash(const char *key);
ut32 sdb_hash_len(const char *key, ut32 *len);
SDB_API bool sdb_expire_set(Sdb* s, const char *key, ut64 expire, ut32 cas);
SDB_API ut64 sdb_expire_get(Sdb* s, const char *key, ut32 *cas);
SDB_API ut64 sdb_now(void);
SDB_API ut64 sdb_unow(void);
SDB_API ut32 sdb_hash(const char *key);
SDB_API ut32 sdb_hash_len(const char *key, ut32 *len);
SDB_API ut8 sdb_hash_byte(const char *s);
/* json api */
SDB_API bool sdb_isjson(const char *k);

View File

@ -26,10 +26,9 @@
#define SDB_IPI static
#endif
#if MINGW || __MINGW32__ || __MINGW64__
#define __MINGW__ 1
#else
#define __MINGW__ 0
#endif
#if __WIN32__ || __MINGW__ || __WINDOWS__ || _MSC_VER

View File

@ -65,6 +65,12 @@ SDB_API ut32 sdb_hash(const char *s) {
return sdb_hash_len (s, NULL);
}
SDB_API ut8 sdb_hash_byte(const char *s) {
const ut32 hash = sdb_hash_len (s, NULL);
const ut8 *h = (const ut8*)&hash;
return h[0] ^ h[1] ^ h[2] ^ h[3];
}
// assert (sizeof (s)>64)
// if s is null, the returned pointer must be freed!!
SDB_API char *sdb_itoa(ut64 n, char *s, int base) {