Rizin
unix-like reverse engineering framework and cli tools
serialize_core.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_core.h>
6 
7 /*
8  * SDB Format:
9  *
10  * /
11  * /config => see config.c
12  * /flags => see flag.c
13  * /analysis => see analysis.c
14  * /file => see below
15  * offset=<offset>
16  * blocksize=<blocksize>
17  */
18 
19 static void file_save(RZ_NONNULL Sdb *db, RZ_NONNULL RzCore *core, RZ_NULLABLE const char *prj_file);
20 static bool file_load(RZ_NONNULL Sdb *db, RZ_NONNULL RzCore *core, RZ_NULLABLE const char *prj_file,
22 
23 RZ_API void rz_serialize_core_save(RZ_NONNULL Sdb *db, RZ_NONNULL RzCore *core, RZ_NULLABLE const char *prj_file) {
24  file_save(sdb_ns(db, "file", true), core, prj_file);
25  rz_serialize_config_save(sdb_ns(db, "config", true), core->config);
26  rz_serialize_flag_save(sdb_ns(db, "flags", true), core->flags);
27  rz_serialize_analysis_save(sdb_ns(db, "analysis", true), core->analysis);
28  rz_serialize_debug_save(sdb_ns(db, "debug", true), core->dbg);
29 
30  char buf[0x20];
31  if (snprintf(buf, sizeof(buf), "0x%" PFMT64x, core->offset) < 0) {
32  return;
33  }
34  sdb_set(db, "offset", buf, 0);
35 
36  if (snprintf(buf, sizeof(buf), "0x%" PFMT32x, core->blocksize) < 0) {
37  return;
38  }
39  sdb_set(db, "blocksize", buf, 0);
40 }
41 
42 static const char *const config_exclude[] = {
43  "dir.home",
44  "dir.libs",
45  "dir.magic",
46  "dir.plugins",
47  "dir.prefix",
48  "dir.projects",
49  "dir.source",
50  "dir.tmp",
51  "dir.types",
52  "http.root",
53  "pdb.symstore",
54  "scr.color",
55  "scr.color.args",
56  "scr.color.bytes",
57  "scr.color.grep",
58  "scr.color.ops",
59  "scr.color.pipe",
60  "scr.interactive", // especially relevant for Cutter since it needs this to be false
61  "scr.prompt", // especially relevant for rzpipe, otherwise loading a project might break the pipe
62  "scr.rainbow",
63  "scr.utf8",
64  "scr.utf8.curvy",
65  "ghidra.sleighhome", // also important for Cutter
66  NULL
67 };
68 
69 RZ_API bool rz_serialize_core_load(RZ_NONNULL Sdb *db, RZ_NONNULL RzCore *core, bool load_bin_io,
70  RZ_NULLABLE const char *prj_file, RZ_NULLABLE RzSerializeResultInfo *res) {
71  Sdb *subdb;
72 
73 #define SUB(ns, call) RZ_SERIALIZE_SUB_DO(db, subdb, res, ns, call, return false;)
74 
75  if (load_bin_io) {
76  SUB("file", file_load(subdb, core, prj_file, res));
77  }
78  SUB("config", rz_serialize_config_load(subdb, core->config, config_exclude, res));
79  SUB("flags", rz_serialize_flag_load(subdb, core->flags, res));
80  SUB("analysis", rz_serialize_analysis_load(subdb, core->analysis, res));
81  SUB("debug", rz_serialize_debug_load(subdb, core->dbg, res));
82 
83  const char *str = sdb_get(db, "offset", 0);
84  if (!str || !*str) {
85  RZ_SERIALIZE_ERR(res, "missing offset in core");
86  return false;
87  }
88  core->offset = strtoull(str, NULL, 0);
89 
90  str = sdb_get(db, "blocksize", 0);
91  if (!str || !*str) {
92  RZ_SERIALIZE_ERR(res, "missing blocksize in core");
93  return false;
94  }
95  ut64 bs = strtoull(str, NULL, 0);
96  rz_core_block_size(core, (int)bs);
97 
98  // handled by config already:
99  // cfglog, cmdrepeat, cmdtimes
100 
101  return true;
102 }
103 
104 /* these file functions are a high-level serialization of RBin and RIO, i.e. for loading the project's underlying binary.
105  * It only supports a subset of possible RBin and RIO configurations:
106  * - Only a single binary, loaded as a regular file
107  * - No IO cache (if there is cache, it will be discarded on save)
108  * - No custom IO mappings, etc.
109  * Thus it will eventually be replaced by more in-depth serialization of RBin and RIO.
110  *
111  * tl;dr it's a quick and dirty thing that only saves the binary's filename.
112  *
113  * SDB Format:
114  * /file
115  * raw=<entered filename, as passed to rizin:str>
116  * absolute=<absolute filename:str>
117  * relative=<relative to the project file, if saving project to a file:str>
118  */
119 
120 static char *prj_dir_abs(const char *prj_file) {
121  char *prj_abs = rz_file_abspath(prj_file);
122  if (!prj_abs) {
123  return NULL;
124  }
125  char *r = rz_file_dirname(prj_abs);
126  free(prj_abs);
127  return r;
128 }
129 
130 // (absolute) local filepath => project-relative platform-agnostic path
131 static char *prj_relative_make(const char *prj_dir, const char *abs_file) {
132  char *rel = rz_file_relpath(prj_dir, abs_file);
133  if (!rel) {
134  return NULL;
135  }
136  // convert only the relative path to a common format because it is the only path that makes any sense
137  // when a project file is relocated to another machine. Absolute and raw are always specific to one environment.
138  char *rel_unix = rz_file_path_local_to_unix(rel);
139  free(rel);
140  return rel_unix;
141 }
142 
143 // project-relative platform-agnostic path => (absolute) local filepath
144 static char *prj_relative_restore(const char *prj_dir, const char *rel_file) {
145  char *rel_local = rz_file_path_unix_to_local(rel_file);
146  if (!rel_local) {
147  return NULL;
148  }
149  char *abs = rz_file_abspath_rel(prj_dir, rel_local);
150  free(rel_local);
151  return abs;
152 }
153 
154 static void file_save(RZ_NONNULL Sdb *db, RZ_NONNULL RzCore *core, RZ_NULLABLE const char *prj_file) {
155  rz_return_if_fail(db && core);
156 
157  if (!core->file) {
158  return;
159  }
160  RzIODesc *desc = rz_io_desc_get(core->io, core->file->fd);
161  if (!desc) {
162  return;
163  }
164  if (!desc->plugin || strcmp(desc->plugin->name, "default")) {
165  eprintf("Warning: The current file is not loaded as a regular file. "
166  "This is not supported in projects yet and it will be necessary to manually re-load to use the project.\n");
167  return;
168  }
169  const char *filename = desc->uri;
170  if (!filename) {
171  return;
172  }
173  sdb_set(db, "raw", filename, 0);
174  char *abs = rz_file_abspath(filename);
175  if (!abs) {
176  return;
177  }
178  sdb_set(db, "absolute", abs, 0);
179  if (prj_file) {
180  char *prj_dir = prj_dir_abs(prj_file);
181  if (!prj_dir) {
182  goto beach;
183  }
184  char *rel = prj_relative_make(prj_dir, abs);
185  if (rel) {
186  sdb_set(db, "relative", rel, 0);
187  free(rel);
188  }
189  free(prj_dir);
190  }
191 beach:
192  free(abs);
193  return;
194 }
195 
196 typedef enum {
201 
203  if (!rz_file_is_regular(file)) {
204  return FILE_DOES_NOT_EXIST;
205  }
206 
208  if (!fh) {
209  RZ_SERIALIZE_ERR(res, "failed re-open file \"%s\" referenced by project", file);
210  return FILE_LOAD_FAIL;
211  }
213 
214  return FILE_SUCCESS;
215 }
216 
217 static bool file_load(RZ_NONNULL Sdb *db, RZ_NONNULL RzCore *core, RZ_NULLABLE const char *prj_file,
219  rz_core_file_close_fd(core, -1);
220  rz_io_close_all(core->io);
221  rz_bin_file_delete_all(core->bin);
222 
224  const char *rel = sdb_const_get(db, "relative", 0);
225  if (rel && prj_file) {
226  char *prj_dir = prj_dir_abs(prj_file);
227  if (prj_dir) {
228  char *file = prj_relative_restore(prj_dir, rel);
229  if (file) {
230  r = try_load_file(core, file, res);
231  free(file);
232  }
233  free(prj_dir);
234  }
235  }
236  if (r != FILE_DOES_NOT_EXIST) {
237  return r == FILE_SUCCESS;
238  }
239 
240  const char *file = sdb_const_get(db, "absolute", 0);
241  if (file) {
242  r = try_load_file(core, file, res);
243  }
244  if (r != FILE_DOES_NOT_EXIST) {
245  return r == FILE_SUCCESS;
246  }
247 
248  file = sdb_const_get(db, "raw", 0);
249  if (file) {
250  r = try_load_file(core, file, res);
251  }
252  if (r != FILE_DOES_NOT_EXIST) {
253  return r == FILE_SUCCESS;
254  }
255 
256  RZ_SERIALIZE_ERR(res, "failed to re-locate file referenced by project");
257  return false;
258 }
#define PFMT32x
RZ_API ut64 rz_bin_file_delete_all(RzBin *bin)
Definition: bfile.c:199
const char * desc
Definition: bin_vsf.c:19
FILE * fh
Definition: cabinfo.c:52
RZ_API RZ_BORROW RzCoreFile * rz_core_file_open(RZ_NONNULL RzCore *r, RZ_NONNULL const char *file, int flags, ut64 loadaddr)
Tries to open the file as is, otherwise tries as is a compilation of files.
Definition: cfile.c:1182
RZ_API bool rz_core_file_close_fd(RzCore *core, int fd)
Definition: cfile.c:1510
RZ_API bool rz_core_bin_load(RZ_NONNULL RzCore *r, RZ_NULLABLE const char *filenameuri, ut64 baddr)
Definition: cfile.c:942
#define RZ_API
#define NULL
Definition: cris-opc.c:27
#define r
Definition: crypto_rc6.c:12
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
const char * filename
Definition: ioapi.h:137
voidpf void * buf
Definition: ioapi.h:138
snprintf
Definition: kernel.h:364
RZ_API bool rz_core_block_size(RzCore *core, ut32 bsize)
Definition: core.c:2842
RZ_API Sdb * sdb_ns(Sdb *s, const char *name, int create)
Definition: ns.c:186
#define eprintf(x, y...)
Definition: rlcc.c:7
#define rz_return_if_fail(expr)
Definition: rz_assert.h:100
RZ_API char * rz_file_relpath(const char *base, const char *path)
Definition: file.c:278
RZ_API bool rz_file_is_regular(const char *str)
Definition: file.c:159
RZ_API char * rz_file_path_local_to_unix(const char *path)
Definition: file.c:332
RZ_API char * rz_file_abspath(const char *file)
Definition: file.c:267
RZ_API char * rz_file_dirname(const char *path)
Definition: file.c:120
RZ_API char * rz_file_abspath_rel(const char *cwd, const char *file)
Definition: file.c:219
RZ_API char * rz_file_path_unix_to_local(const char *path)
Definition: file.c:343
RZ_API RzIODesc * rz_io_desc_get(RzIO *io, int fd)
Definition: io_desc.c:73
RZ_API int rz_io_close_all(RzIO *io)
Definition: io.c:258
#define RZ_SERIALIZE_ERR(res,...)
Push an error to the local RzSerializeResultInfo \res RzSerializeInfoResult *.
Definition: rz_serialize.h:33
#define RZ_NULLABLE
Definition: rz_types.h:65
#define RZ_NONNULL
Definition: rz_types.h:64
#define RZ_PERM_RX
Definition: rz_types.h:97
#define PFMT64x
Definition: rz_types.h:393
#define UT64_MAX
Definition: rz_types_base.h:86
RZ_API int sdb_set(Sdb *s, const char *key, const char *val, ut32 cas)
Definition: sdb.c:611
RZ_API char * sdb_get(Sdb *s, const char *key, ut32 *cas)
Definition: sdb.c:290
RZ_API const char * sdb_const_get(Sdb *s, const char *key, ut32 *cas)
Definition: sdb.c:279
RZ_API bool rz_serialize_analysis_load(RZ_NONNULL Sdb *db, RZ_NONNULL RzAnalysis *analysis, RZ_NULLABLE RzSerializeResultInfo *res)
RZ_API void rz_serialize_analysis_save(RZ_NONNULL Sdb *db, RZ_NONNULL RzAnalysis *analysis)
RZ_API void rz_serialize_config_save(RZ_NONNULL Sdb *db, RZ_NONNULL RzConfig *config)
RZ_API bool rz_serialize_config_load(RZ_NONNULL Sdb *db, RZ_NONNULL RzConfig *config, RZ_NULLABLE const char *const *exclude, RZ_NULLABLE RzSerializeResultInfo *res)
static void file_save(RZ_NONNULL Sdb *db, RZ_NONNULL RzCore *core, RZ_NULLABLE const char *prj_file)
static char * prj_dir_abs(const char *prj_file)
static char * prj_relative_make(const char *prj_dir, const char *abs_file)
static char * prj_relative_restore(const char *prj_dir, const char *rel_file)
RZ_API bool rz_serialize_core_load(RZ_NONNULL Sdb *db, RZ_NONNULL RzCore *core, bool load_bin_io, RZ_NULLABLE const char *prj_file, RZ_NULLABLE RzSerializeResultInfo *res)
RZ_API void rz_serialize_core_save(RZ_NONNULL Sdb *db, RZ_NONNULL RzCore *core, RZ_NULLABLE const char *prj_file)
static FileRet try_load_file(RZ_NONNULL RzCore *core, const char *file, RZ_NULLABLE RzSerializeResultInfo *res)
static bool file_load(RZ_NONNULL Sdb *db, RZ_NONNULL RzCore *core, RZ_NULLABLE const char *prj_file, RZ_NULLABLE RzSerializeResultInfo *res)
FileRet
@ FILE_SUCCESS
@ FILE_DOES_NOT_EXIST
@ FILE_LOAD_FAIL
static const char *const config_exclude[]
#define SUB(ns, call)
RZ_API void rz_serialize_debug_save(RZ_NONNULL Sdb *db, RZ_NONNULL RzDebug *dbg)
Serialize debug state (RzDebug) and save to a sdb.
RZ_API bool rz_serialize_debug_load(RZ_NONNULL Sdb *db, RZ_NONNULL RzDebug *dbg, RZ_NULLABLE RzSerializeResultInfo *res)
Load a serialized debug state to a RzDebug instance.
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)
Definition: gzappend.c:170
Definition: sdb.h:63
ut64(WINAPI *w32_GetEnabledXStateFeatures)()