Rizin
unix-like reverse engineering framework and cli tools
project_migrate.c File Reference
#include <rz_project.h>
#include <rz_util/rz_pj.h>

Go to the source code of this file.

Classes

struct  V1V2TypesCtx
 
struct  V2V3TypesCtx
 

Functions

bool v1_v2_types_foreach_cb (void *user, const char *k, const char *v)
 
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_v2_v3 (RzProject *prj, RzSerializeResultInfo *res)
 
RZ_API bool rz_project_migrate_v3_v4 (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_v6_v7 (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. More...
 

Variables

static bool(*const migrations [])(RzProject *prj, RzSerializeResultInfo *res)
 

Detailed Description

About Project Migrations: The project format is versioned, which means that a project saved with a certain version will always follow the exact same format. The current version is defined as RZ_PROJECT_VERSION and is completely independent of Rizin release versions. Do not confuse them! When any change in Rizin happens that changes the project format, this version must be raised and a migration must be implemented, which converts a given project from the previous version to the current and will be executed when loading an old project with new Rizin. These migrations always bring a project from version x to version x+1 and they may be executed sequentially if multiple versions are skipped. For example loading a project with version 1 in Rizin with version 3 will execute (1->2), then (2->3) and finally load the project just like any regular project of version 3.

After introducing format changes in Rizin, do the following:

  • Raise RZ_PROJECT_VERSION by exactly 1.
  • Implement a function like bool rz_project_migrate_migrate_v1_v2(RzProject *prj, RzSerializeResultInfo *res) which edits prj in-place and converts it from the previous to the current version.
  • Append this function to the migrations array below.
  • Implement tests in test/unit/test_project_migrate.c that cover all changes (see the documentation there).

Definition in file project_migrate.c.

Function Documentation

◆ rz_project_migrate()

RZ_API bool rz_project_migrate ( RzProject prj,
unsigned long  version,
RzSerializeResultInfo res 
)

Migrate the given project to the current version in-place.

Definition at line 318 of file project_migrate.c.

318  {
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 }
RZ_API RZ_BORROW RzListIter * rz_list_push(RZ_NONNULL RzList *list, void *item)
Alias for rz_list_append.
Definition: list.c:60
static bool(*const migrations[])(RzProject *prj, RzSerializeResultInfo *res)
#define RZ_STATIC_ASSERT(x)
Definition: rz_assert.h:10
#define RZ_PROJECT_VERSION
Definition: rz_project.h:15
RZ_API char * rz_str_newf(const char *fmt,...) RZ_PRINTF_CHECK(1
#define RZ_ARRAY_SIZE(x)
Definition: rz_types.h:300

References migrations, RZ_ARRAY_SIZE, rz_list_push(), RZ_PROJECT_VERSION, RZ_STATIC_ASSERT, and rz_str_newf().

Referenced by rz_project_load().

◆ rz_project_migrate_v1_v2()

RZ_API bool rz_project_migrate_v1_v2 ( RzProject prj,
RzSerializeResultInfo res 
)

Definition at line 53 of file project_migrate.c.

53  {
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 }
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 void rz_list_free(RZ_NONNULL RzList *list)
Empties the list and frees the list pointer.
Definition: list.c:137
RZ_API Sdb * sdb_ns(Sdb *s, const char *name, int create)
Definition: ns.c:186
bool v1_v2_types_foreach_cb(void *user, const char *k, const char *v)
static RzSocket * s
Definition: rtr.c:28
#define RZ_SERIALIZE_SUB(db, subdb, res, ns, rip)
Get an sdb sub-namespace or fail.
Definition: rz_serialize.h:104
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
Definition: sdb.h:63

References free(), rz_list_free(), rz_list_newf(), RZ_SERIALIZE_SUB, s, sdb_foreach(), sdb_ns(), sdb_unset(), and v1_v2_types_foreach_cb().

◆ rz_project_migrate_v2_v3()

RZ_API bool rz_project_migrate_v2_v3 ( RzProject prj,
RzSerializeResultInfo res 
)

Definition at line 110 of file project_migrate.c.

110  {
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 }
bool v2_v3_types_foreach_cb(void *user, const char *k, const char *v)

References free(), rz_list_free(), rz_list_newf(), RZ_SERIALIZE_SUB, s, sdb_foreach(), sdb_ns(), sdb_unset(), and v2_v3_types_foreach_cb().

◆ rz_project_migrate_v3_v4()

RZ_API bool rz_project_migrate_v3_v4 ( RzProject prj,
RzSerializeResultInfo res 
)

Definition at line 166 of file project_migrate.c.

166  {
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 }

References free(), rz_list_free(), rz_list_newf(), RZ_SERIALIZE_SUB, s, sdb_foreach(), sdb_ns(), and sdb_unset().

◆ rz_project_migrate_v4_v5()

RZ_API bool rz_project_migrate_v4_v5 ( RzProject prj,
RzSerializeResultInfo res 
)

Definition at line 201 of file project_migrate.c.

201  {
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 }
int bits(struct state *s, int need)
Definition: blast.c:72
RZ_API ut64 sdb_num_get(Sdb *s, const char *key, ut32 *cas)
Definition: num.c:13
RZ_API int sdb_set(Sdb *s, const char *key, const char *val, ut32 cas)
Definition: sdb.c:611

References bits(), RZ_SERIALIZE_SUB, sdb_num_get(), and sdb_set().

◆ rz_project_migrate_v5_v6()

RZ_API bool rz_project_migrate_v5_v6 ( RzProject prj,
RzSerializeResultInfo res 
)

Definition at line 249 of file project_migrate.c.

249  {
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 }

References RZ_SERIALIZE_SUB, and sdb_ns().

◆ rz_project_migrate_v6_v7()

RZ_API bool rz_project_migrate_v6_v7 ( RzProject prj,
RzSerializeResultInfo res 
)

Definition at line 264 of file project_migrate.c.

264  {
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 }
#define NULL
Definition: cris-opc.c:27
RZ_API bool sdb_ns_unset(Sdb *s, const char *name, Sdb *r)
Definition: ns.c:136

References NULL, RZ_SERIALIZE_SUB, and sdb_ns_unset().

◆ rz_project_migrate_v7_v8()

RZ_API bool rz_project_migrate_v7_v8 ( RzProject prj,
RzSerializeResultInfo res 
)

Definition at line 280 of file project_migrate.c.

280  {
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 }

References NULL, RZ_SERIALIZE_SUB, sdb_ns_unset(), and sdb_unset().

◆ v1_v2_types_foreach_cb()

bool v1_v2_types_foreach_cb ( void *  user,
const char *  k,
const char *  v 
)

Definition at line 43 of file project_migrate.c.

43  {
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 }
const char * k
Definition: dsignal.c:11
const char * v
Definition: dsignal.c:12
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 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

References k, rz_list_push(), rz_str_endswith(), rz_str_startswith(), sdb_set(), strdup(), and v.

Referenced by rz_project_migrate_v1_v2().

◆ v2_v3_types_foreach_cb()

bool v2_v3_types_foreach_cb ( void *  user,
const char *  k,
const char *  v 
)

Definition at line 94 of file project_migrate.c.

94  {
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 }

References free(), k, rz_list_push(), rz_str_newf(), rz_str_startswith(), sdb_set(), strdup(), and v.

Referenced by rz_project_migrate_v2_v3().

Variable Documentation

◆ migrations

bool(*const migrations[])(RzProject *prj, RzSerializeResultInfo *res) ( RzProject prj,
RzSerializeResultInfo res 
)
static
Initial value:
= {
}
RZ_API bool rz_project_migrate_v2_v3(RzProject *prj, RzSerializeResultInfo *res)
RZ_API bool rz_project_migrate_v1_v2(RzProject *prj, RzSerializeResultInfo *res)
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)

Definition at line 307 of file project_migrate.c.

Referenced by rz_project_migrate().