Rizin
unix-like reverse engineering framework and cli tools
serialize_flag.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2020 Florian Märkl <info@florianmaerkl.de>
2 // SPDX-License-Identifier: LGPL-3.0-only
3 
4 #include <rz_util/rz_serialize.h>
5 #include <rz_flag.h>
6 
7 /*
8  * SDB Format:
9  *
10  * /
11  * base=<base>
12  * realnames=<realnames?"1":"0">
13  * /spaces
14  * see spaces.c
15  * /tags
16  * like RzFlag.tags
17  * /zones
18  * <zone name>={"from":<from>,"to":<to>}
19  * /flags
20  * <flag name>={"realname":<str>,"demangled":<bool>,"offset":<uint>,"size":<uint>,"space":<str>,"color":<str>,"comment":<str>,"alias":<str>}
21  *
22  */
23 
24 RZ_API void rz_serialize_flag_zones_save(RZ_NONNULL Sdb *db, RZ_NONNULL RzList /*<RzFlagZoneItem *>*/ *zones) {
25  RzListIter *it;
26  RzFlagZoneItem *item;
27  rz_list_foreach (zones, it, item) {
28  PJ *j = pj_new();
29  if (!j) {
30  return;
31  }
32  pj_o(j);
33  pj_kn(j, "from", item->from);
34  pj_kn(j, "to", item->to);
35  pj_end(j);
36  sdb_set(db, item->name, pj_string(j), 0);
37  pj_free(j);
38  }
39 }
40 
41 static bool zone_load_cb(void *user, const char *k, const char *v) {
42  RzList *list = user;
43  char *json_str = strdup(v);
44  if (!json_str) {
45  return true;
46  }
47  RzJson *json = rz_json_parse(json_str);
48  if (!json) {
49  free(json_str);
50  return true;
51  }
52  if (json->type != RZ_JSON_OBJECT) {
53  goto beach;
54  }
55  const RzJson *child;
57  if (!item) {
58  goto beach;
59  }
60  item->name = strdup(k);
61  if (!item->name) {
62  free(item);
63  goto beach;
64  }
65  for (child = json->children.first; child; child = child->next) {
66  if (child->type != RZ_JSON_INTEGER) {
67  continue;
68  }
69  if (strcmp(child->key, "from") == 0) {
70  item->from = child->num.u_value;
71  } else if (strcmp(child->key, "to") == 0) {
72  item->to = child->num.u_value;
73  }
74  }
75  rz_list_append(list, item);
76 beach:
77  rz_json_free(json);
78  free(json_str);
79  return true;
80 }
81 
83  rz_return_val_if_fail(zones, false);
84  rz_list_purge(zones);
85  bool r = sdb_foreach(db, zone_load_cb, zones);
86  if (!r) {
87  RZ_SERIALIZE_ERR(res, "failed to parse a flag zone json");
88  }
89  return r;
90 }
91 
92 static bool flag_save_cb(RzFlagItem *flag, void *user) {
93  Sdb *db = user;
94  PJ *j = pj_new();
95  if (!j) {
96  return false;
97  }
98  pj_o(j);
99  if (flag->realname) {
100  pj_ks(j, "realname", flag->realname);
101  }
102  pj_kb(j, "demangled", flag->demangled);
103  pj_kn(j, "offset", flag->offset);
104  pj_kn(j, "size", flag->size);
105  if (flag->space) {
106  pj_ks(j, "space", flag->space->name);
107  }
108  if (flag->color) {
109  pj_ks(j, "color", flag->color);
110  }
111  if (flag->comment) {
112  pj_ks(j, "comment", flag->comment);
113  }
114  if (flag->alias) {
115  pj_ks(j, "alias", flag->alias);
116  }
117  pj_end(j);
118  sdb_set(db, flag->name, pj_string(j), 0);
119  pj_free(j);
120  return true;
121 }
122 
124  rz_serialize_spaces_save(sdb_ns(db, "spaces", true), &flag->spaces);
125  char buf[32];
126  if (snprintf(buf, sizeof(buf), "%" PFMT64d, flag->base) < 0) {
127  return;
128  }
129  sdb_set(db, "base", buf, 0);
130  sdb_set(db, "realnames", flag->realnames ? "1" : "0", 0);
131  sdb_copy(flag->tags, sdb_ns(db, "tags", true));
132  rz_serialize_flag_zones_save(sdb_ns(db, "zones", true), flag->zones);
133  rz_flag_foreach(flag, flag_save_cb, sdb_ns(db, "flags", true));
134 }
135 
136 typedef enum {
146 
147 typedef struct {
150 } FlagLoadCtx;
151 
152 static bool flag_load_cb(void *user, const char *k, const char *v) {
153  FlagLoadCtx *ctx = user;
154 
155  char *json_str = strdup(v);
156  if (!json_str) {
157  return true;
158  }
159  RzJson *json = rz_json_parse(json_str);
160  if (!json || json->type != RZ_JSON_OBJECT) {
161  free(json_str);
162  return false;
163  }
164 
165  RzFlagItem proto = { 0 };
166  bool offset_set = false;
167  bool size_set = false;
168 
169  RZ_KEY_PARSER_JSON(ctx->parser, json, child, {
170  case FLAG_FIELD_REALNAME:
171  if (child->type != RZ_JSON_STRING) {
172  break;
173  }
174  proto.realname = (char *)child->str_value;
175  break;
177  if (child->type != RZ_JSON_BOOLEAN) {
178  break;
179  }
180  proto.demangled = child->num.u_value != 0;
181  break;
182  case FLAG_FIELD_OFFSET:
183  if (child->type != RZ_JSON_INTEGER) {
184  break;
185  }
186  proto.offset = child->num.u_value;
187  offset_set = true;
188  break;
189  case FLAG_FIELD_SIZE:
190  if (child->type != RZ_JSON_INTEGER) {
191  break;
192  }
193  proto.size = child->num.u_value;
194  size_set = true;
195  break;
196  case FLAG_FIELD_SPACE:
197  if (child->type != RZ_JSON_STRING) {
198  break;
199  }
200  proto.space = rz_flag_space_get(ctx->flag, child->str_value);
201  break;
202  case FLAG_FIELD_COLOR:
203  if (child->type != RZ_JSON_STRING) {
204  break;
205  }
206  proto.color = (char *)child->str_value;
207  break;
208  case FLAG_FIELD_COMMENT:
209  if (child->type != RZ_JSON_STRING) {
210  break;
211  }
212  proto.comment = (char *)child->str_value;
213  break;
214  case FLAG_FIELD_ALIAS:
215  if (child->type != RZ_JSON_STRING) {
216  break;
217  }
218  proto.alias = (char *)child->str_value;
219  break;
220  default:
221  break;
222  });
223 
224  bool res = true;
225  if (!offset_set || !size_set) {
226  res = false;
227  goto beach;
228  }
229 
230  RzFlagItem *item = rz_flag_set(ctx->flag, k, proto.offset - ctx->flag->base, proto.size);
231  if (proto.realname) {
232  rz_flag_item_set_realname(item, proto.realname);
233  }
234  item->demangled = proto.demangled;
235  item->space = proto.space;
236  if (proto.color) {
237  rz_flag_item_set_color(item, proto.color);
238  }
239  if (proto.comment) {
240  rz_flag_item_set_comment(item, proto.comment);
241  }
242  if (proto.alias) {
243  rz_flag_item_set_alias(item, proto.alias);
244  }
245 
246 beach:
247  rz_json_free(json);
248  free(json_str);
249  return res;
250 }
251 
252 static bool load_flags(RZ_NONNULL Sdb *flags_db, RZ_NONNULL RzFlag *flag) {
253  FlagLoadCtx ctx = { flag, rz_key_parser_new() };
254  if (!ctx.parser) {
255  return false;
256  }
257  rz_key_parser_add(ctx.parser, "realname", FLAG_FIELD_REALNAME);
258  rz_key_parser_add(ctx.parser, "demangled", FLAG_FIELD_DEMANGLED);
259  rz_key_parser_add(ctx.parser, "offset", FLAG_FIELD_OFFSET);
260  rz_key_parser_add(ctx.parser, "size", FLAG_FIELD_SIZE);
261  rz_key_parser_add(ctx.parser, "space", FLAG_FIELD_SPACE);
262  rz_key_parser_add(ctx.parser, "color", FLAG_FIELD_COLOR);
263  rz_key_parser_add(ctx.parser, "comment", FLAG_FIELD_COMMENT);
264  rz_key_parser_add(ctx.parser, "alias", FLAG_FIELD_ALIAS);
265  bool r = sdb_foreach(flags_db, flag_load_cb, &ctx);
266  rz_key_parser_free(ctx.parser);
267  return r;
268 }
269 
271  rz_flag_unset_all(flag);
272 
273  const char *str = sdb_const_get(db, "base", NULL);
274  if (!str) {
275  RZ_SERIALIZE_ERR(res, "flag base key is missing");
276  return false;
277  }
278  flag->base = strtoll(str, NULL, 0);
279 
280  str = sdb_const_get(db, "realnames", 0);
281  if (!str) {
282  RZ_SERIALIZE_ERR(res, "flag realnames key is missing");
283  return false;
284  }
285  flag->realnames = strtoul(str, NULL, 0) ? true : false;
286 
287  Sdb *spaces_db = sdb_ns(db, "spaces", false);
288  if (!spaces_db) {
289  RZ_SERIALIZE_ERR(res, "missing spaces namespace");
290  return false;
291  }
292  if (!rz_serialize_spaces_load(spaces_db, &flag->spaces, false, res)) {
293  return false;
294  }
295 
296  Sdb *tags_db = sdb_ns(db, "tags", false);
297  if (!tags_db) {
298  RZ_SERIALIZE_ERR(res, "missing tags namespace");
299  return false;
300  }
301  sdb_copy(tags_db, flag->tags);
302 
303  Sdb *zones_db = sdb_ns(db, "zones", false);
304  if (!zones_db) {
305  RZ_SERIALIZE_ERR(res, "missing zones namespace");
306  return false;
307  }
308  rz_flag_zone_reset(flag);
309  if (!rz_serialize_flag_zones_load(zones_db, flag->zones, res)) {
310  return false;
311  }
312 
313  Sdb *flags_db = sdb_ns(db, "flags", false);
314  if (!flags_db) {
315  RZ_SERIALIZE_ERR(res, "missing flags sub-namespace");
316  return false;
317  }
318  if (!load_flags(flags_db, flag)) {
319  RZ_SERIALIZE_ERR(res, "failed to parse a flag json");
320  return false;
321  }
322 
323  return true;
324 }
#define RZ_API
#define NULL
Definition: cris-opc.c:27
#define r
Definition: crypto_rc6.c:12
#define true
const char * k
Definition: dsignal.c:11
const char * v
Definition: dsignal.c:12
RZ_API const char * rz_flag_item_set_color(RzFlagItem *item, const char *color)
Definition: flag.c:578
RZ_API void rz_flag_item_set_comment(RzFlagItem *item, const char *comment)
Definition: flag.c:564
RZ_API void rz_flag_item_set_alias(RzFlagItem *item, const char *alias)
Definition: flag.c:557
RZ_API RzFlagItem * rz_flag_set(RzFlag *f, const char *name, ut64 off, ut32 size)
Definition: flag.c:521
RZ_API void rz_flag_unset_all(RzFlag *f)
Definition: flag.c:677
RZ_API void rz_flag_item_set_realname(RzFlagItem *item, const char *realname)
Definition: flag.c:571
RZ_API void rz_flag_foreach(RzFlag *f, RzFlagItemCb cb, void *user)
Definition: flag.c:800
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
voidpf void * buf
Definition: ioapi.h:138
snprintf
Definition: kernel.h:364
static void list(RzEgg *egg)
Definition: rz-gg.c:52
RZ_API RZ_BORROW RzListIter * rz_list_append(RZ_NONNULL RzList *list, void *data)
Appends at the end of the list a new element.
Definition: list.c:288
RZ_API void rz_list_purge(RZ_NONNULL RzList *list)
Empties the list without freeing the list pointer.
Definition: list.c:120
return strdup("=SP r13\n" "=LR r14\n" "=PC r15\n" "=A0 r0\n" "=A1 r1\n" "=A2 r2\n" "=A3 r3\n" "=ZF zf\n" "=SF nf\n" "=OF vf\n" "=CF cf\n" "=SN or0\n" "gpr lr .32 56 0\n" "gpr pc .32 60 0\n" "gpr cpsr .32 64 0 ____tfiae_________________qvczn\n" "gpr or0 .32 68 0\n" "gpr tf .1 64.5 0 thumb\n" "gpr ef .1 64.9 0 endian\n" "gpr jf .1 64.24 0 java\n" "gpr qf .1 64.27 0 sticky_overflow\n" "gpr vf .1 64.28 0 overflow\n" "gpr cf .1 64.29 0 carry\n" "gpr zf .1 64.30 0 zero\n" "gpr nf .1 64.31 0 negative\n" "gpr itc .4 64.10 0 if_then_count\n" "gpr gef .4 64.16 0 great_or_equal\n" "gpr r0 .32 0 0\n" "gpr r1 .32 4 0\n" "gpr r2 .32 8 0\n" "gpr r3 .32 12 0\n" "gpr r4 .32 16 0\n" "gpr r5 .32 20 0\n" "gpr r6 .32 24 0\n" "gpr r7 .32 28 0\n" "gpr r8 .32 32 0\n" "gpr r9 .32 36 0\n" "gpr r10 .32 40 0\n" "gpr r11 .32 44 0\n" "gpr r12 .32 48 0\n" "gpr r13 .32 52 0\n" "gpr r14 .32 56 0\n" "gpr r15 .32 60 0\n" "gpr r16 .32 64 0\n" "gpr r17 .32 68 0\n")
RZ_API Sdb * sdb_ns(Sdb *s, const char *name, int create)
Definition: ns.c:186
#define rz_return_val_if_fail(expr, val)
Definition: rz_assert.h:108
@ RZ_JSON_INTEGER
Definition: rz_json.h:33
@ RZ_JSON_OBJECT
Definition: rz_json.h:30
@ RZ_JSON_BOOLEAN
Definition: rz_json.h:35
@ RZ_JSON_STRING
Definition: rz_json.h:32
RZ_API RzJson * rz_json_parse(char *text)
Definition: json_parser.c:382
RZ_API void rz_json_free(RzJson *js)
Definition: json_parser.c:45
RZ_API PJ * pj_new(void)
Definition: pj.c:25
RZ_API PJ * pj_kb(PJ *j, const char *k, bool v)
Definition: pj.c:177
RZ_API PJ * pj_end(PJ *j)
Definition: pj.c:87
RZ_API const char * pj_string(PJ *pj)
Definition: pj.c:57
RZ_API void pj_free(PJ *j)
Definition: pj.c:34
RZ_API PJ * pj_o(PJ *j)
Definition: pj.c:75
RZ_API PJ * pj_ks(PJ *j, const char *k, const char *v)
Definition: pj.c:170
RZ_API PJ * pj_kn(PJ *j, const char *k, ut64 n)
Definition: pj.c:121
static void rz_key_parser_add(RzKeyParser *parser, const char *key, int val)
Definition: rz_serialize.h:56
HtPP RzKeyParser
Hashtable-based key parser to prevent strcmp chains.
Definition: rz_serialize.h:46
static RzKeyParser * rz_key_parser_new(void)
Definition: rz_serialize.h:48
#define RZ_SERIALIZE_ERR(res,...)
Push an error to the local RzSerializeResultInfo \res RzSerializeInfoResult *.
Definition: rz_serialize.h:33
#define RZ_KEY_PARSER_JSON(parser, json, child, body)
Iterate over all keys in a json object and call RZ_KEY_PARSER_SWITCH on each.
Definition: rz_serialize.h:82
static void rz_key_parser_free(RzKeyParser *parser)
Definition: rz_serialize.h:52
RZ_API bool rz_serialize_spaces_load(RZ_NONNULL Sdb *db, RZ_NONNULL RzSpaces *spaces, bool load_name, RZ_NULLABLE RzSerializeResultInfo *res)
RZ_API void rz_serialize_spaces_save(RZ_NONNULL Sdb *db, RZ_NONNULL RzSpaces *spaces)
#define PFMT64d
Definition: rz_types.h:394
#define RZ_NULLABLE
Definition: rz_types.h:65
#define RZ_NEW0(x)
Definition: rz_types.h:284
#define RZ_NONNULL
Definition: rz_types.h:64
RZ_API int sdb_set(Sdb *s, const char *key, const char *val, ut32 cas)
Definition: sdb.c:611
RZ_API const char * sdb_const_get(Sdb *s, const char *key, ut32 *cas)
Definition: sdb.c:279
RZ_API void sdb_copy(Sdb *src, Sdb *dst)
Definition: sdb.c:1084
RZ_API bool sdb_foreach(Sdb *s, SdbForeachCallback cb, void *user)
Definition: sdb.c:758
static bool zone_load_cb(void *user, const char *k, const char *v)
static bool flag_load_cb(void *user, const char *k, const char *v)
RZ_API bool rz_serialize_flag_zones_load(RZ_NONNULL Sdb *db, RZ_NONNULL RzList *zones, RZ_NULLABLE RzSerializeResultInfo *res)
FlagField
@ FLAG_FIELD_COMMENT
@ FLAG_FIELD_DEMANGLED
@ FLAG_FIELD_OFFSET
@ FLAG_FIELD_SIZE
@ FLAG_FIELD_ALIAS
@ FLAG_FIELD_REALNAME
@ FLAG_FIELD_COLOR
@ FLAG_FIELD_SPACE
RZ_API void rz_serialize_flag_save(RZ_NONNULL Sdb *db, RZ_NONNULL RzFlag *flag)
RZ_API bool rz_serialize_flag_load(RZ_NONNULL Sdb *db, RZ_NONNULL RzFlag *flag, RZ_NULLABLE RzSerializeResultInfo *res)
RZ_API void rz_serialize_flag_zones_save(RZ_NONNULL Sdb *db, RZ_NONNULL RzList *zones)
static bool load_flags(RZ_NONNULL Sdb *flags_db, RZ_NONNULL RzFlag *flag)
static bool flag_save_cb(RzFlagItem *flag, void *user)
RzKeyParser * parser
RzFlag * flag
Definition: rz_pj.h:12
RzSpace * space
Definition: rz_flag.h:40
char * color
Definition: rz_flag.h:41
char * alias
Definition: rz_flag.h:43
ut64 offset
Definition: rz_flag.h:38
char * comment
Definition: rz_flag.h:42
char * realname
Definition: rz_flag.h:36
char * name
Definition: rz_flag.h:35
bool demangled
Definition: rz_flag.h:37
struct rz_json_t::@304::@307 children
const char * key
Definition: rz_json.h:40
struct rz_json_t * next
Definition: rz_json.h:56
RzJsonType type
Definition: rz_json.h:39
struct rz_json_t::@304::@306 num
char * name
Definition: rz_spaces.h:29
Definition: sdb.h:63
if(dbg->bits==RZ_SYS_BITS_64)
Definition: windows-arm64.h:4
RZ_API bool rz_flag_zone_reset(RzFlag *f)
Definition: zones.c:51