Rizin
unix-like reverse engineering framework and cli tools
project_migrate.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2021 Florian Märkl <info@florianmaerkl.de>
2 // SPDX-License-Identifier: LGPL-3.0-only
3 
4 #include <rz_project.h>
5 #include <rz_util/rz_pj.h>
6 
30 // --
31 // Migration 1 -> 2
32 //
33 // Changes from 788fdb3d8ef98f50d61cdee72e0b57c74c814022:
34 // Information which addresses are marked as noreturn was previosly saved in "/core/analysis/types" as records like:
35 // addr.1337.noreturn=true
36 // Now it is available in "/core/analysis/noreturn" while actual type-related info stays in "/core/analysis/types".
37 
38 typedef struct {
39  RzList /*<char *>*/ *moved_keys;
41 } V1V2TypesCtx;
42 
43 bool v1_v2_types_foreach_cb(void *user, const char *k, const char *v) {
44  if (!rz_str_startswith(k, "addr.") || !rz_str_endswith(k, ".noreturn")) {
45  return true;
46  }
47  V1V2TypesCtx *ctx = user;
48  sdb_set(ctx->noreturn_db, k, v, 0);
49  rz_list_push(ctx->moved_keys, strdup(k));
50  return true;
51 }
52 
54  Sdb *core_db;
55  RZ_SERIALIZE_SUB(prj, core_db, res, "core", return false;);
56  Sdb *analysis_db;
57  RZ_SERIALIZE_SUB(core_db, analysis_db, res, "analysis", return false;);
58  Sdb *types_db;
59  RZ_SERIALIZE_SUB(analysis_db, types_db, res, "types", return false;);
60  V1V2TypesCtx ctx = {
61  .moved_keys = rz_list_newf(free),
62  .noreturn_db = sdb_ns(analysis_db, "noreturn", true)
63  };
64  if (!ctx.moved_keys || !ctx.noreturn_db) {
65  return false;
66  }
68  RzListIter *it;
69  char *s;
70  rz_list_foreach (ctx.moved_keys, it, s) {
71  sdb_unset(types_db, s, 0);
72  }
73  rz_list_free(ctx.moved_keys);
74  return true;
75 }
76 
77 // --
78 // Migration 2 -> 3
79 //
80 // Changes from 788fdb3d8ef98f50d61cdee72e0b57c74c814022:
81 // Types database "analysis/types" was converted into two
82 // separate SDBs - types and callables
83 // Thus all "func.*" keys from "/core/analysis/types" should be moved to
84 // "/core/analysis/callables"
85 // Type links information is also separated now from
86 // "/core/analysis/types" to "/core/analysis/typelinks"
87 
88 typedef struct {
89  RzList /*<char *>*/ *moved_keys;
92 } V2V3TypesCtx;
93 
94 bool v2_v3_types_foreach_cb(void *user, const char *k, const char *v) {
95  V2V3TypesCtx *ctx = user;
96  if (rz_str_startswith(k, "func.") || !strcmp(v, "func")) {
97  sdb_set(ctx->callables_db, k, v, 0);
98  rz_list_push(ctx->moved_keys, strdup(k));
99  } else if (rz_str_startswith(k, "link.")) {
100  // Old addresses were stored as hexadecimal numbers without `0x` part
101  // New addresses have them
102  char *tl_key = rz_str_newf("0x%s", k + strlen("link."));
103  sdb_set(ctx->typelinks_db, tl_key, v, 0);
104  free(tl_key);
105  rz_list_push(ctx->moved_keys, strdup(k));
106  }
107  return true;
108 }
109 
111  Sdb *core_db;
112  RZ_SERIALIZE_SUB(prj, core_db, res, "core", return false;);
113  Sdb *analysis_db;
114  RZ_SERIALIZE_SUB(core_db, analysis_db, res, "analysis", return false;);
115  Sdb *types_db;
116  RZ_SERIALIZE_SUB(analysis_db, types_db, res, "types", return false;);
117  V2V3TypesCtx ctx = {
118  .moved_keys = rz_list_newf(free),
119  .callables_db = sdb_ns(analysis_db, "callables", true),
120  .typelinks_db = sdb_ns(analysis_db, "typelinks", true)
121  };
122  if (!ctx.moved_keys || !ctx.callables_db || !ctx.typelinks_db) {
123  return false;
124  }
126  RzListIter *it;
127  char *s;
128  rz_list_foreach (ctx.moved_keys, it, s) {
129  sdb_unset(types_db, s, 0);
130  }
131  rz_list_free(ctx.moved_keys);
132  return true;
133 }
134 
135 // --
136 // Migration 3 -> 4
137 //
138 // Changes from 8d54707ccf8b3492b999dfa42057da0847acb952:
139 // Added new global variables in "/core/analysis/vars"
140 
141 #if 0
142 typedef struct {
143  RzList /*<char *>*/ *moved_keys;
144  Sdb *global_vars_db;
145 } V3V4TypesCtx;
146 
147 bool v3_v4_types_foreach_cb(void *user, const char *k, const char *v) {
148  V3V4TypesCtx *ctx = user;
149  if (rz_str_startswith(k, "0x")) {
150  char name[32];
151  PJ *j = pj_new();
152  pj_o(j);
153  pj_ks(j, "name", rz_strf(name, "gvar_%s", k));
154  pj_ks(j, "type", v);
155  pj_ks(j, "addr", k);
156  // We don't have constraints for typelink here.
157  pj_end(j);
158  sdb_set(ctx->global_vars_db, k, pj_string(j), 0);
159  pj_free(j);
160  rz_list_push(ctx->moved_keys, strdup(k));
161  }
162  return true;
163 }
164 #endif
165 
167  Sdb *core_db;
168  RZ_SERIALIZE_SUB(prj, core_db, res, "core", return false;);
169  Sdb *analysis_db;
170  RZ_SERIALIZE_SUB(core_db, analysis_db, res, "analysis", return false;);
171  // Kill me in the future
172  sdb_ns(analysis_db, "vars", true);
173 #if 0
174  V3V4TypesCtx ctx = {
175  .moved_keys = rz_list_newf(free),
176  .global_vars_db = sdb_ns(analysis_db, "vars", true)
177  };
178 
179  if (!ctx.moved_keys || !ctx.global_vars_db) {
180  return false;
181  }
182  Sdb *typelinks_db = sdb_ns(analysis_db, "typelinks", true);
183  sdb_foreach(typelinks_db, v3_v4_types_foreach_cb, &ctx);
184  RzListIter *it;
185  char *s;
186  rz_list_foreach (ctx.moved_keys, it, s) {
187  sdb_unset(typelinks_db, s, 0);
188  }
189  rz_list_free(ctx.moved_keys);
190 #endif
191  return true;
192 }
193 
194 // --
195 // Migration 4 -> 5
196 //
197 // Changes from a523314fa7c8fde0c2c0d116e82aa77f62991d37
198 // Added new type called `unknown_t` in "/core/analysis/types"
199 // It is used for all unknown types during the project loading and saving
200 
202  Sdb *core_db;
203  RZ_SERIALIZE_SUB(prj, core_db, res, "core", return false;);
204  Sdb *analysis_db;
205  RZ_SERIALIZE_SUB(core_db, analysis_db, res, "analysis", return false;);
206  Sdb *config_db;
207  RZ_SERIALIZE_SUB(core_db, config_db, res, "config", return false;);
208  Sdb *types_db;
209  RZ_SERIALIZE_SUB(analysis_db, types_db, res, "types", return false;);
210  // Common keys:
211  // unknown_t=type
212  // type.unknown_t.typeclass=Integral
213  sdb_set(types_db, "unknown_t", "type", 0);
214  sdb_set(types_db, "type.unknown_t.typeclass", "Integral", 0);
215  // Now we read the bits value from "asm.bits=XX" in "/core/config"
216  int bits = sdb_num_get(config_db, "asm.bits", 0);
217  switch (bits) {
218  case 16:
219  // type.unknown_t=w
220  // type.unknown_t.size=16
221  sdb_set(types_db, "type.unknown_t", "w", 0);
222  sdb_set(types_db, "type.unknown_t.size", "16", 0);
223  break;
224  case 64:
225  // type.unknown_t=q
226  // type.unknown_t.size=64
227  sdb_set(types_db, "type.unknown_t", "q", 0);
228  sdb_set(types_db, "type.unknown_t.size", "64", 0);
229  break;
230  case 32:
231  default:
232  // type.unknown_t=d
233  // type.unknown_t.size=32
234  sdb_set(types_db, "type.unknown_t", "d", 0);
235  sdb_set(types_db, "type.unknown_t.size", "32", 0);
236  break;
237  }
238  return true;
239 }
240 
241 // --
242 // Migration 5 -> 6
243 //
244 // Changes from 2c48a91d1332daede8d0640ce407c3abcf0abfb4
245 // Added serialization functionality for debug (only for breakpoints as of now)
246 // Used to save and load current RzDebug instance (only breakpoints) using serialization
247 // New namespaces: /core/debug, /core/debug/breakpoints
248 
250  Sdb *core_db;
251  RZ_SERIALIZE_SUB(prj, core_db, res, "core", return false;);
252  Sdb *debug_db = sdb_ns(core_db, "debug", true);
253  sdb_ns(debug_db, "breakpoints", true);
254 
255  return true;
256 }
257 
258 // --
259 // Migration 6 -> 7
260 //
261 // Changes from <commit-hash>
262 // Removed esil pin feature. Namespace deleted: /core/analysis/pins
263 
265  Sdb *core_db;
266  RZ_SERIALIZE_SUB(prj, core_db, res, "core", return false;);
267  Sdb *analysis_db;
268  RZ_SERIALIZE_SUB(core_db, analysis_db, res, "analysis", return false;);
269  sdb_ns_unset(analysis_db, "pins", NULL);
270  return true;
271 }
272 
273 // --
274 // Migration 7 -> 8
275 //
276 // Changes from <commit-hash>
277 // Removed zignature feature. Namespace deleted: /core/analysis/zigns
278 // Also removed configs zign.* options.
279 
281  Sdb *core_db;
282  RZ_SERIALIZE_SUB(prj, core_db, res, "core", return false;);
283  Sdb *analysis_db;
284  RZ_SERIALIZE_SUB(core_db, analysis_db, res, "analysis", return false;);
285  sdb_ns_unset(analysis_db, "zigns", NULL);
286  Sdb *config_db;
287  RZ_SERIALIZE_SUB(core_db, config_db, res, "config", return false;);
288  sdb_unset(config_db, "zign.autoload", 0);
289  sdb_unset(config_db, "zign.diff.bthresh", 0);
290  sdb_unset(config_db, "zign.diff.gthresh", 0);
291  sdb_unset(config_db, "zign.match.bytes", 0);
292  sdb_unset(config_db, "zign.match.graph", 0);
293  sdb_unset(config_db, "zign.match.hash", 0);
294  sdb_unset(config_db, "zign.match.offset", 0);
295  sdb_unset(config_db, "zign.match.refs", 0);
296  sdb_unset(config_db, "zign.match.types", 0);
297  sdb_unset(config_db, "zign.maxsz", 0);
298  sdb_unset(config_db, "zign.mincc", 0);
299  sdb_unset(config_db, "zign.minsz", 0);
300  sdb_unset(config_db, "zign.prefix", 0);
301  sdb_unset(config_db, "zign.threshold", 0);
302  return true;
303 }
304 
305 // --
306 
307 static bool (*const migrations[])(RzProject *prj, RzSerializeResultInfo *res) = {
315 };
316 
320  while (version < RZ_PROJECT_VERSION) {
321  bool succ = migrations[version - 1](prj, res);
322  if (!succ) {
323  rz_list_push(res, rz_str_newf("project migration from version %lu to %lu failed.", version, version + 1));
324  return false;
325  }
326  rz_list_push(res, rz_str_newf("project migrated from version %lu to %lu.", version, version + 1));
327  version++;
328  }
329  return true;
330 }
int bits(struct state *s, int need)
Definition: blast.c:72
#define RZ_API
#define NULL
Definition: cris-opc.c:27
const char * k
Definition: dsignal.c:11
const char * v
Definition: dsignal.c:12
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
RZ_API RZ_OWN RzList * rz_list_newf(RzListFree f)
Returns a new initialized RzList pointer and sets the free method.
Definition: list.c:248
RZ_API RZ_BORROW RzListIter * rz_list_push(RZ_NONNULL RzList *list, void *item)
Alias for rz_list_append.
Definition: list.c:60
RZ_API void rz_list_free(RZ_NONNULL RzList *list)
Empties the list and frees the list pointer.
Definition: list.c:137
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
RZ_API bool sdb_ns_unset(Sdb *s, const char *name, Sdb *r)
Definition: ns.c:136
RZ_API ut64 sdb_num_get(Sdb *s, const char *key, ut32 *cas)
Definition: num.c:13
bool v1_v2_types_foreach_cb(void *user, const char *k, const char *v)
RZ_API bool rz_project_migrate_v2_v3(RzProject *prj, RzSerializeResultInfo *res)
RZ_API bool rz_project_migrate_v1_v2(RzProject *prj, RzSerializeResultInfo *res)
bool v2_v3_types_foreach_cb(void *user, const char *k, const char *v)
RZ_API bool rz_project_migrate_v3_v4(RzProject *prj, RzSerializeResultInfo *res)
RZ_API bool rz_project_migrate_v6_v7(RzProject *prj, RzSerializeResultInfo *res)
RZ_API bool rz_project_migrate_v4_v5(RzProject *prj, RzSerializeResultInfo *res)
RZ_API bool rz_project_migrate_v5_v6(RzProject *prj, RzSerializeResultInfo *res)
RZ_API bool rz_project_migrate_v7_v8(RzProject *prj, RzSerializeResultInfo *res)
RZ_API bool rz_project_migrate(RzProject *prj, unsigned long version, RzSerializeResultInfo *res)
Migrate the given project to the current version in-place.
static bool(*const migrations[])(RzProject *prj, RzSerializeResultInfo *res)
static RzSocket * s
Definition: rtr.c:28
#define RZ_STATIC_ASSERT(x)
Definition: rz_assert.h:10
RZ_API PJ * pj_new(void)
Definition: pj.c:25
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
#define RZ_PROJECT_VERSION
Definition: rz_project.h:15
#define RZ_SERIALIZE_SUB(db, subdb, res, ns, rip)
Get an sdb sub-namespace or fail.
Definition: rz_serialize.h:104
RZ_API char * rz_str_newf(const char *fmt,...) RZ_PRINTF_CHECK(1
RZ_API bool rz_str_startswith(RZ_NONNULL const char *str, RZ_NONNULL const char *needle)
Checks if a string starts with a specifc sequence of characters (case sensitive)
Definition: str.c:3286
RZ_API bool rz_str_endswith(RZ_NONNULL const char *str, RZ_NONNULL const char *needle)
Checks if a string ends with a specifc sequence of characters (case sensitive)
Definition: str.c:3329
#define rz_strf(buf,...)
Convenience macro for local temporary strings.
Definition: rz_str.h:59
#define RZ_ARRAY_SIZE(x)
Definition: rz_types.h:300
RZ_API int sdb_set(Sdb *s, const char *key, const char *val, ut32 cas)
Definition: sdb.c:611
RZ_API bool sdb_foreach(Sdb *s, SdbForeachCallback cb, void *user)
Definition: sdb.c:758
RZ_API int sdb_unset(Sdb *s, const char *key, ut32 cas)
Definition: sdb.c:294
RzList * moved_keys
deferred for deletion from the old sdb
RzList * moved_keys
deferred for deletion from the old sdb
Definition: z80asm.h:102
Definition: rz_pj.h:12
Definition: sdb.h:63
#define bool
Definition: sysdefs.h:146