/* radare - Copyright 2008-2016 - LGPL -- pancake */ #include #include #include #include #include #include #include "fastcall.h" R_LIB_VERSION (r_syscall); extern RSyscallPort sysport_x86[]; extern RSyscallPort sysport_avr[]; R_API RSyscall* r_syscall_new() { RSyscall *rs = R_NEW0 (RSyscall); if (rs) { rs->sysport = sysport_x86; rs->cb_printf = (PrintfCallback)printf; rs->regs = fastcall_x86_32; } return rs; } R_API void r_syscall_free(RSyscall *s) { sdb_free (s->db); free(s->os); memset (s, 0, sizeof (RSyscall)); free (s); } /* return fastcall register argument 'idx' for a syscall with 'num' args */ R_API const char *r_syscall_reg(RSyscall *s, int idx, int num) { if (num<0 || num>=R_SYSCALL_ARGS || idx<0 || idx>=R_SYSCALL_ARGS) return NULL; return s->regs[num].arg[idx]; } R_API int r_syscall_setup(RSyscall *s, const char *arch, const char *os, int bits) { const char *file; if (!os || !*os) os = R_SYS_OS; if (!arch) arch = R_SYS_ARCH; free (s->os); s->os = strdup (os); if (!strcmp (os, "any")) { // ignored return true; } if (!strcmp (arch, "mips")) { s->regs = fastcall_mips; } else if (!strcmp (arch,"avr")) { s->sysport = sysport_avr; } else if (!strcmp (arch,"sh")) { s->regs = fastcall_sh; } else if (!strcmp (arch, "arm")) { s->regs = fastcall_arm; } else if (!strcmp (arch, "x86")) { s->sysport = sysport_x86; switch (bits) { case 8: s->regs = fastcall_x86_8; break; case 32: s->regs = fastcall_x86_32; break; case 64: s->regs = fastcall_x86_64; break; } } #define SYSCALLPATH R2_LIBDIR"/radare2/"R2_VERSION"/syscall" file = sdb_fmt (0, "%s/%s-%s-%d.sdb", SYSCALLPATH, os, arch, bits); if (!r_file_exists (file)) { //eprintf ("r_syscall_setup: Cannot find '%s'\n", file); return false; } //eprintf ("DBG098: syscall->db must be reindexed for k\n"); #if 0 // TODO: use sdb_reset (s->db); /// XXX: memoization doesnt seems to work because RSyscall is recreated instead of configured :( sdb_close (s->db); sdb_reset (s->db); sdb_open (s->db, file); #else sdb_close (s->db); sdb_free (s->db); s->db = sdb_new (0, file, 0); #endif if (s->fd) fclose (s->fd); s->fd = NULL; return true; } /// XXX wtf is this function for? R_API int r_syscall_setup_file(RSyscall *s, const char *path) { if (s->fd) fclose (s->fd); s->fd = r_sandbox_fopen (path, "r"); if (s->fd == NULL) return false; /* TODO: load info from file */ return true; } R_API RSyscallItem *r_syscall_item_new_from_string(const char *name, const char *s) { RSyscallItem *si; char *o; if (!name || !s) return NULL; si = R_NEW0 (RSyscallItem); if (!si) return NULL; o = strdup (s); r_str_split (o, ','); si->name = strdup (name); si->swi = r_num_get (NULL, r_str_word_get0 (o, 0)); si->num = r_num_get (NULL, r_str_word_get0 (o, 1)); si->args = r_num_get (NULL, r_str_word_get0 (o, 2)); si->sargs = strdup (r_str_word_get0 (o, 3)); free (o); return si; } R_API void r_syscall_item_free(RSyscallItem *si) { if (!si) return; free (si->name); free (si->sargs); free (si); } static int getswi(Sdb *p, int swi) { if (p && swi == -1) { swi = (int)sdb_array_get_num (p, "_", 0, NULL); if (!swi) swi = 0x80; // default hardcoded? } return swi; } R_API RSyscallItem *r_syscall_get(RSyscall *s, int num, int swi) { const char *ret, *ret2, *key; RSyscallItem *si; if (!s || !s->db) return NULL; swi = getswi (s->db, swi); key = sdb_fmt (0, "0x%02x.%d", swi, num); ret = sdb_const_get (s->db, key, 0); if (ret == NULL) return NULL; ret2 = sdb_const_get (s->db, ret, 0); if (ret2 == NULL) { return NULL; } si = r_syscall_item_new_from_string (ret, ret2); return si; } R_API int r_syscall_get_num(RSyscall *s, const char *str) { if (!s || !s->db) return -1; return (int)sdb_array_get_num (s->db, str, 1, NULL); } R_API const char *r_syscall_get_i(RSyscall *s, int num, int swi) { char foo[32]; if (!s || !s->db) return NULL; swi = getswi (s->db, swi); snprintf (foo, sizeof (foo), "0x%x.%d", swi, num); return sdb_const_get (s->db, foo, 0); } static int callback_list(void *u, const char *k, const char *v) { RList *list = (RList*)u; if (!strchr (k, '.')) { RSyscallItem *si = r_syscall_item_new_from_string (k, v); if (!si) return 0; if (!strchr (si->name, '.')) r_list_append (list, si); } return 1; // continue loop } R_API RList *r_syscall_list(RSyscall *s) { RList *list; if (!s || !s->db) return NULL; // show list of syscalls to stdout list = r_list_newf ((RListFree)r_syscall_item_free); sdb_foreach (s->db, callback_list, list); return list; } /* io */ R_API const char *r_syscall_get_io(RSyscall *s, int ioport) { int i; if (!s) return NULL; for (i=0; s->sysport[i].name; i++) { if (ioport == s->sysport[i].port) return s->sysport[i].name; } return NULL; }