Rizin
unix-like reverse engineering framework and cli tools
syscall.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2008-2020 pancake <pancake@nopcode.org>
2 // SPDX-License-Identifier: LGPL-3.0-only
3 
4 #include <rz_types.h>
5 #include <rz_util.h>
6 #include <rz_syscall.h>
7 #include <stdio.h>
8 #include <string.h>
9 
10 RZ_LIB_VERSION(rz_syscall);
11 
13  sc->refs++;
14  return sc;
15 }
16 
23  RzSysregItem *sysregitem = RZ_NEW0(RzSysregItem);
24  if (!sysregitem) {
25  return NULL;
26  }
27  sysregitem->comment = NULL;
28  sysregitem->type = NULL;
29  sysregitem->name = name ? strdup(name) : NULL;
30  return sysregitem;
31 }
32 
33 static void free_port_kv(HtUPKv *kv) {
34  rz_sysreg_item_free(kv->value);
35 }
36 
41  RzSysregsDB *sysregdb = RZ_NEW0(RzSysregsDB);
42  if (!sysregdb) {
43  return NULL;
44  }
45  sysregdb->port = ht_up_new(NULL, free_port_kv, NULL);
46  if (!sysregdb->port) {
47  free(sysregdb);
48  return NULL;
49  }
50  return sysregdb;
51 }
52 
57  if (!sysregdb) {
58  return;
59  }
60  ht_up_free(sysregdb->port);
61  free(sysregdb);
62 }
63 
69  if (rs) {
70  rs->srdb = rz_sysregs_db_new(); // sysregs database
71  rs->db = sdb_new0();
72  }
73  return rs;
74 }
75 
80  if (s) {
81  if (s->refs > 0) {
82  s->refs--;
83  return;
84  }
85  sdb_free(s->db);
86  free(s->os);
87  free(s->cpu);
88  free(s->arch);
89  rz_sysregs_db_free(s->srdb);
90  free(s);
91  }
92 }
93 
98  if (!s) {
99  return;
100  }
101  free(s->comment);
102  free(s->name);
103  free(s->type);
104  free(s);
105 }
106 
107 static bool load_sdb(Sdb **db, const char *name) {
108  rz_return_val_if_fail(db, false);
109  char *sdb_path = rz_path_system(RZ_SDB);
110  char *file_name = rz_str_newf("%s.sdb", name);
111  char *file = rz_file_path_join(sdb_path, file_name);
112  free(file_name);
113  free(sdb_path);
114  if (rz_file_exists(file)) {
115  if (*db) {
116  sdb_reset(*db);
117  sdb_open(*db, file);
118  } else {
119  *db = sdb_new(0, file, 0);
120  }
121  free(file);
122  return true;
123  }
124  free(file);
125  return false;
126 }
127 
128 static inline bool syscall_reload_needed(RzSyscall *s, const char *os, const char *arch, int bits) {
129  if (!s->os || strcmp(s->os, os)) {
130  return true;
131  }
132  if (!s->arch || strcmp(s->arch, arch)) {
133  return true;
134  }
135  return s->bits != bits;
136 }
137 
138 static inline bool sysregs_reload_needed(RzSyscall *s, const char *arch, int bits, const char *cpu) {
139  if (!s->arch || strcmp(s->arch, arch)) {
140  return true;
141  }
142  if (s->bits != bits) {
143  return true;
144  }
145  return !s->cpu || strcmp(s->cpu, cpu);
146 }
147 
148 static bool sdb_load_sysregs(RzSysregsDB *sysregdb, Sdb *sdb) {
149  rz_return_val_if_fail(sysregdb && sdb, false);
150  RzSysregItem *sysregitem;
151  SdbKv *kv;
152  SdbListIter *iter;
153  SdbList *l = sdb_foreach_list(sdb, false);
154  char *argument_key, *comment, *name;
155  ls_foreach (l, iter, kv) {
156  if (!strcmp(sdbkv_value(kv), "mmio") || !strcmp(sdbkv_value(kv), "reg")) {
157  name = sdbkv_key(kv);
158  sysregitem = rz_sysreg_item_new(name);
159  argument_key = rz_str_newf("%s.address", name);
160  if (!argument_key) {
161  rz_sysreg_item_free(sysregitem);
162  return false;
163  }
164  ut64 address = sdb_num_get(sdb, argument_key, NULL);
165  free(argument_key);
166  if (!address) {
167  rz_sysreg_item_free(sysregitem);
168  return false;
169  }
170 
171  argument_key = rz_str_newf("%s.comment", name);
172  comment = sdb_get(sdb, argument_key, NULL);
173  free(argument_key);
174  sysregitem->type = strdup(sdbkv_value(kv));
175  sysregitem->comment = comment;
176 
177  ht_up_insert(sysregdb->port, address, sysregitem);
178  }
179  }
180  ls_free(l);
181  return true;
182 }
183 
184 static bool sdb_load_by_path(RZ_NONNULL RzSysregsDB *sysregdb, const char *path) {
185  Sdb *db = sdb_new(0, path, 0);
186  bool result = sdb_load_sysregs(sysregdb, db);
187  sdb_close(db);
188  sdb_free(db);
189  return result;
190 }
191 
198 RZ_API bool rz_sysreg_load_sdb(RzSysregsDB *sysregdb, const char *path) {
199  if (!rz_file_exists(path) || !sysregdb) {
200  return false;
201  }
202  return sdb_load_by_path(sysregdb, path);
203 }
204 
213 RZ_API bool rz_sysreg_set_arch(RzSyscall *s, RZ_NONNULL const char *arch, RZ_NONNULL const char *regs_dir) {
214  rz_return_val_if_fail(s && regs_dir && arch, false);
215 
216  char buf[60];
217  char *path = rz_file_path_join(regs_dir, rz_strf(buf, "%s-%s-%d.sdb", arch, s->cpu, s->bits));
218  if (!path) {
219  return true;
220  }
221  rz_sysregs_db_free(s->srdb);
222  s->srdb = rz_sysregs_db_new();
223  if (!rz_sysreg_load_sdb(s->srdb, path)) {
224  free(path);
225  rz_sysregs_db_free(s->srdb);
226  s->srdb = rz_sysregs_db_new();
227  return false;
228  }
229  free(path);
230  return true;
231 }
232 
233 // TODO: should be renamed to rz_syscall_use();
234 RZ_API bool rz_syscall_setup(RzSyscall *s, const char *arch, int bits, const char *cpu, const char *os) {
235  bool syscall_changed, sysregs_changed;
236 
237  if (!os || !*os) {
238  os = RZ_SYS_OS;
239  }
240  if (!arch) {
241  arch = RZ_SYS_ARCH;
242  }
243  if (!cpu) {
244  cpu = arch;
245  }
246  syscall_changed = syscall_reload_needed(s, os, arch, bits);
247  sysregs_changed = sysregs_reload_needed(s, arch, bits, cpu);
248 
249  free(s->os);
250  s->os = strdup(os);
251 
252  free(s->cpu);
253  s->cpu = strdup(cpu);
254 
255  free(s->arch);
256  s->arch = strdup(arch);
257 
258  s->bits = bits;
259 
260  if (!strcmp(os, "any")) { // ignored
261  return true;
262  } else if (!strcmp(os, "darwin") || !strcmp(os, "osx") || !strcmp(os, "macos")) {
263  os = "darwin";
264  }
265 
266  if (syscall_changed) {
267  char *dbName = rz_str_newf(RZ_JOIN_2_PATHS("syscall", "%s-%s-%d"),
268  os, arch, bits);
269  if (dbName) {
270  if (!load_sdb(&s->db, dbName)) {
271  sdb_free(s->db);
272  s->db = NULL;
273  }
274  free(dbName);
275  }
276  }
277 
278  if (sysregs_changed) {
279  char *regs_dir = rz_path_system(RZ_SDB_REG);
280  rz_sysreg_set_arch(s, arch, regs_dir);
281  free(regs_dir);
282  }
283  if (s->fd) {
284  fclose(s->fd);
285  s->fd = NULL;
286  }
287  return true;
288 }
289 
291  RzSyscallItem *si;
292  char *o;
293  if (!name || !s) {
294  return NULL;
295  }
296  o = strdup(s);
297  int cols = rz_str_split(o, ',');
298  if (cols < 3) {
299  free(o);
300  return NULL;
301  }
302 
304  if (!si) {
305  free(o);
306  return NULL;
307  }
308  si->name = strdup(name);
309  si->swi = (int)rz_num_get(NULL, rz_str_word_get0(o, 0));
310  si->num = (int)rz_num_get(NULL, rz_str_word_get0(o, 1));
311  si->args = (int)rz_num_get(NULL, rz_str_word_get0(o, 2));
312  si->sargs = calloc(si->args + 1, sizeof(char));
313  if (!si->sargs) {
314  free(si);
315  free(o);
316  return NULL;
317  }
318  if (cols > 3) {
319  strncpy(si->sargs, rz_str_word_get0(o, 3), si->args);
320  }
321  free(o);
322  return si;
323 }
324 
326  if (!si) {
327  return;
328  }
329  free(si->name);
330  free(si->sargs);
331  free(si);
332 }
333 
334 static int getswi(RzSyscall *s, int swi) {
335  if (s && swi == -1) {
336  return rz_syscall_get_swi(s);
337  }
338  return swi;
339 }
340 
342  return (int)sdb_num_get(s->db, "_", NULL);
343 }
344 
347  if (!s->db) {
348  return NULL;
349  }
350  const char *ret, *ret2, *key;
351  swi = getswi(s, swi);
352  if (swi < 16) {
353  key = sdb_fmt("%d.%d", swi, num);
354  } else {
355  key = sdb_fmt("0x%02x.%d", swi, num);
356  }
357  ret = sdb_const_get(s->db, key, 0);
358  if (!ret) {
359  key = sdb_fmt("0x%02x.0x%02x", swi, num); // Workaround until Syscall SDB is fixed
360  ret = sdb_const_get(s->db, key, 0);
361  if (!ret) {
362  key = sdb_fmt("0x%02x.%d", num, swi); // Workaround until Syscall SDB is fixed
363  ret = sdb_const_get(s->db, key, 0);
364  if (!ret) {
365  return NULL;
366  }
367  }
368  }
369  ret2 = sdb_const_get(s->db, ret, 0);
370  if (!ret2) {
371  return NULL;
372  }
373  return rz_syscall_item_new_from_string(ret, ret2);
374 }
375 
377  rz_return_val_if_fail(s && str, -1);
378  if (!s->db) {
379  return -1;
380  }
381  int sn = (int)sdb_array_get_num(s->db, str, 1, NULL);
382  if (sn == 0) {
383  return (int)sdb_array_get_num(s->db, str, 0, NULL);
384  }
385  return sn;
386 }
387 
388 RZ_API const char *rz_syscall_get_i(RzSyscall *s, int num, int swi) {
390  if (!s->db) {
391  return NULL;
392  }
393  char foo[32];
394  swi = getswi(s, swi);
395  snprintf(foo, sizeof(foo), "0x%x.%d", swi, num);
396  return sdb_const_get(s->db, foo, 0);
397 }
398 
399 static bool callback_list(void *u, const char *k, const char *v) {
400  RzList *list = (RzList *)u;
401  if (!strchr(k, '.')) {
403  if (!si) {
404  return true;
405  }
406  if (!strchr(si->name, '.')) {
408  } else {
410  }
411  }
412  return true; // continue loop
413 }
414 
417  if (!s->db) {
418  return NULL;
419  }
422  return list;
423 }
424 
433 RZ_API const char *rz_sysreg_get(RzSyscall *s, const char *type, ut64 port) {
435  if (!s->srdb) {
436  return NULL;
437  }
438  RzSysregItem *item = ht_up_find(s->srdb->port, port, NULL);
439  if (item && !strcmp(item->type, type)) {
440  return item->comment;
441  }
442  return NULL;
443 }
si
#define rs()
static ut32 cpu[32]
Definition: analysis_or1k.c:21
RZ_API ut64 sdb_array_get_num(Sdb *s, const char *key, int idx, ut32 *cas)
Definition: array.c:63
int bits(struct state *s, int need)
Definition: blast.c:72
#define RZ_API
#define NULL
Definition: cris-opc.c:27
cs_arch arch
Definition: cstool.c:13
static static fork const void static count static fd const char const char static newpath const char static path const char path
Definition: sflib.h:35
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void static offset struct stat static buf void long static basep static whence static length const void static len key
Definition: sflib.h:118
const char * k
Definition: dsignal.c:11
const char * v
Definition: dsignal.c:12
static char sc[]
Definition: egg_cb.c:6
RZ_API char * sdb_fmt(const char *fmt,...)
Definition: fmt.c:26
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 RzMain foo[]
Definition: main.c:11
static void list(RzEgg *egg)
Definition: rz-gg.c:52
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_append(RZ_NONNULL RzList *list, void *data)
Appends at the end of the list a new element.
Definition: list.c:288
void * calloc(size_t number, size_t size)
Definition: malloc.c:102
static const char file_name
Definition: sflib.h:131
static static fork const void static count static fd const char const char static newpath char char char static envp time_t static t const char static mode static whence const char static dir time_t static t unsigned static seconds const char struct utimbuf static buf static inc static sig const char static mode static oldfd struct tms static buf static getgid static geteuid const char static filename static arg static mask struct ustat static ubuf static getppid static setsid static egid sigset_t static set struct timeval struct timezone static tz fd_set fd_set fd_set struct timeval static timeout const char char static bufsiz const char static swapflags void static offset const char static length static mode static who const char struct statfs static buf unsigned unsigned num
Definition: sflib.h:126
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 void ls_free(SdbList *list)
Definition: ls.c:191
#define ls_foreach(list, it, pos)
Definition: ls.h:31
int type
Definition: mipsasm.c:17
RZ_API ut64 sdb_num_get(Sdb *s, const char *key, ut32 *cas)
Definition: num.c:13
const char * name
Definition: op.c:541
static RzSocket * s
Definition: rtr.c:28
#define rz_return_val_if_fail(expr, val)
Definition: rz_assert.h:108
RZ_API bool rz_file_exists(const char *str)
Definition: file.c:192
RZ_API RZ_OWN char * rz_file_path_join(RZ_NONNULL const char *s1, RZ_NULLABLE const char *s2)
Concatenate two paths to create a new one with s1+s2 with the correct path separator.
Definition: file.c:1312
void(* RzListFree)(void *ptr)
Definition: rz_list.h:11
RZ_API ut64 rz_num_get(RzNum *num, const char *str)
Definition: unum.c:172
RZ_API RZ_OWN char * rz_path_system(RZ_NULLABLE const char *path)
Return the full system path of the given subpath path.
Definition: path.c:162
RZ_API char * rz_str_newf(const char *fmt,...) RZ_PRINTF_CHECK(1
RZ_API const char * rz_str_word_get0(const char *str, int idx)
Definition: str.c:598
RZ_API size_t rz_str_split(char *str, char ch)
Split string str in place by using ch as a delimiter.
Definition: str.c:406
#define rz_strf(buf,...)
Convenience macro for local temporary strings.
Definition: rz_str.h:59
#define RZ_NULLABLE
Definition: rz_types.h:65
#define RZ_OWN
Definition: rz_types.h:62
#define RZ_NEW0(x)
Definition: rz_types.h:284
#define RZ_JOIN_2_PATHS(p1, p2)
Definition: rz_types.h:224
#define RZ_NONNULL
Definition: rz_types.h:64
#define RZ_SYS_ARCH
Definition: rz_types.h:519
#define RZ_SYS_OS
Definition: rz_types.h:587
#define RZ_SDB
Definition: rz_userconf.h:74
#define RZ_SDB_REG
Definition: rz_userconf.h:85
RZ_API Sdb * sdb_new(const char *path, const char *name, int lock)
Definition: sdb.c:47
RZ_API void sdb_close(Sdb *s)
Definition: sdb.c:416
RZ_API Sdb * sdb_new0(void)
Definition: sdb.c:43
RZ_API char * sdb_get(Sdb *s, const char *key, ut32 *cas)
Definition: sdb.c:290
RZ_API bool sdb_free(Sdb *s)
Definition: sdb.c:206
RZ_API void sdb_reset(Sdb *s)
Definition: sdb.c:433
RZ_API const char * sdb_const_get(Sdb *s, const char *key, ut32 *cas)
Definition: sdb.c:279
RZ_API bool sdb_foreach(Sdb *s, SdbForeachCallback cb, void *user)
Definition: sdb.c:758
RZ_API int sdb_open(Sdb *s, const char *file)
Definition: sdb.c:383
RZ_API SdbList * sdb_foreach_list(Sdb *s, bool sorted)
Definition: sdb.c:630
static char * sdbkv_key(const SdbKv *kv)
Definition: sdbht.h:21
static char * sdbkv_value(const SdbKv *kv)
Definition: sdbht.h:25
static int
Definition: sfsocketcall.h:114
Definition: gzappend.c:170
Definition: ls.h:17
Definition: ls.h:22
Definition: z80asm.h:102
Definition: sdbht.h:14
Definition: sdb.h:63
RZ_API RzSyscall * rz_syscall_new(void)
Creates a new RzSyscall type.
Definition: syscall.c:67
RZ_API void rz_sysreg_item_free(RzSysregItem *s)
Frees an RzSysregItem type.
Definition: syscall.c:97
RZ_API RzSysregsDB * rz_sysregs_db_new()
Creates a new RzSysregDB type.
Definition: syscall.c:40
RZ_API bool rz_sysreg_load_sdb(RzSysregsDB *sysregdb, const char *path)
Loads the RzSysregDB from the path to the hashtable.
Definition: syscall.c:198
static bool callback_list(void *u, const char *k, const char *v)
Definition: syscall.c:399
static bool sdb_load_by_path(RZ_NONNULL RzSysregsDB *sysregdb, const char *path)
Definition: syscall.c:184
RZ_API RzSyscall * rz_syscall_ref(RzSyscall *sc)
Definition: syscall.c:12
RZ_LIB_VERSION(rz_syscall)
RZ_API void rz_syscall_free(RzSyscall *s)
Frees an RzSyscall type.
Definition: syscall.c:79
static bool sdb_load_sysregs(RzSysregsDB *sysregdb, Sdb *sdb)
Definition: syscall.c:148
RZ_API void rz_syscall_item_free(RzSyscallItem *si)
Definition: syscall.c:325
static int getswi(RzSyscall *s, int swi)
Definition: syscall.c:334
RZ_API RZ_OWN RzSysregItem * rz_sysreg_item_new(RZ_NULLABLE const char *name)
Creates a new RzSysregItem type.
Definition: syscall.c:22
RZ_API int rz_syscall_get_swi(RzSyscall *s)
Definition: syscall.c:341
static bool sysregs_reload_needed(RzSyscall *s, const char *arch, int bits, const char *cpu)
Definition: syscall.c:138
RZ_API bool rz_sysreg_set_arch(RzSyscall *s, RZ_NONNULL const char *arch, RZ_NONNULL const char *regs_dir)
Sets the architecture for sysregs during analysis and loads up the sysregs SDB database.
Definition: syscall.c:213
RZ_API int rz_syscall_get_num(RzSyscall *s, const char *str)
Definition: syscall.c:376
RZ_API RzSyscallItem * rz_syscall_item_new_from_string(const char *name, const char *s)
Definition: syscall.c:290
static bool load_sdb(Sdb **db, const char *name)
Definition: syscall.c:107
RZ_API RzSyscallItem * rz_syscall_get(RzSyscall *s, int num, int swi)
Definition: syscall.c:345
RZ_API const char * rz_sysreg_get(RzSyscall *s, const char *type, ut64 port)
Searches the sysregs SDB database inside librz/reg/d for the type (mmio/reg) and returns its value as...
Definition: syscall.c:433
static bool syscall_reload_needed(RzSyscall *s, const char *os, const char *arch, int bits)
Definition: syscall.c:128
RZ_API const char * rz_syscall_get_i(RzSyscall *s, int num, int swi)
Definition: syscall.c:388
RZ_API void rz_sysregs_db_free(RzSysregsDB *sysregdb)
Frees a RzSysregDB type.
Definition: syscall.c:56
RZ_API RzList * rz_syscall_list(RzSyscall *s)
Definition: syscall.c:415
RZ_API bool rz_syscall_setup(RzSyscall *s, const char *arch, int bits, const char *cpu, const char *os)
Definition: syscall.c:234
static void free_port_kv(HtUPKv *kv)
Definition: syscall.c:33
ut64(WINAPI *w32_GetEnabledXStateFeatures)()