mirror of
https://github.com/radareorg/radare2.git
synced 2024-12-14 00:38:55 +00:00
116 lines
3.0 KiB
C
116 lines
3.0 KiB
C
/* radare - LGPL - Copyright 2016 pancake */
|
|
|
|
#include "r_lib.h"
|
|
#include "r_core.h"
|
|
#include "r_lang.h"
|
|
|
|
static int lang_rust_file(RLang *lang, const char *file) {
|
|
void *lib;
|
|
char *a, *cc, *p, name[512], buf[512];
|
|
const char *libpath, *libname;
|
|
|
|
if (strlen (file) > (sizeof(name)-10))
|
|
return false;
|
|
if (!strstr (file, ".rs"))
|
|
sprintf (name, "%s.rs", file);
|
|
else strcpy (name, file);
|
|
if (!r_file_exists (name)) {
|
|
eprintf ("file not found (%s)\n", name);
|
|
return false;
|
|
}
|
|
|
|
a = (char*)r_str_lchr (name, '/');
|
|
if (a) {
|
|
*a = 0;
|
|
libpath = name;
|
|
libname = a+1;
|
|
} else {
|
|
libpath = ".";
|
|
libname = name;
|
|
}
|
|
r_sys_setenv ("PKG_CONFIG_PATH", R2_LIBDIR"/pkgconfig");
|
|
p = strstr (name, ".rs"); if (p) *p=0;
|
|
cc = r_sys_getenv ("RUSTC");
|
|
if (cc && !*cc) {
|
|
R_FREE (cc);
|
|
}
|
|
if (!cc) {
|
|
cc = strdup ("rustc");
|
|
}
|
|
snprintf (buf, sizeof (buf), "%s --crate-type dylib %s -o %s/lib%s."R_LIB_EXT" -L native=/usr/local/lib/ -l r_core",
|
|
cc, file, libpath, libname);
|
|
free (cc);
|
|
if (r_sandbox_system (buf, 1) != 0)
|
|
return false;
|
|
|
|
snprintf (buf, sizeof (buf), "%s/lib%s."R_LIB_EXT, libpath, libname);
|
|
lib = r_lib_dl_open (buf);
|
|
if (lib!= NULL) {
|
|
void (*fcn)(RCore *);
|
|
fcn = r_lib_dl_sym (lib, "entry");
|
|
if (fcn) fcn (lang->user);
|
|
else eprintf ("Cannot find 'entry' symbol in library\n");
|
|
r_lib_dl_close (lib);
|
|
} else eprintf ("Cannot open library\n");
|
|
r_file_rm (buf); // remove lib
|
|
return 0;
|
|
}
|
|
|
|
static int lang_rust_init(void *user) {
|
|
// TODO: check if "valac" is found in path
|
|
return true;
|
|
}
|
|
|
|
static int lang_rust_run(RLang *lang, const char *code, int len) {
|
|
FILE *fd = fopen ("_tmp.rs", "w");
|
|
if (fd) {
|
|
const char *rust_header = \
|
|
"use std::ffi::CStr;\n" \
|
|
"extern {\n" \
|
|
" pub fn r_core_cmd_str(core: *const u8, s: *const u8) -> *const u8;\n" \
|
|
" pub fn free (ptr: *const u8);\n" \
|
|
"}\n" \
|
|
"\n" \
|
|
"pub struct R2;\n" \
|
|
"\n" \
|
|
"#[allow(dead_code)]\n" \
|
|
"impl R2 {\n" \
|
|
" fn cmdstr(&self, c: *const u8, str: &str) -> String {\n" \
|
|
" unsafe {\n" \
|
|
" let ptr = r_core_cmd_str(c, str.as_ptr()) as *const i8;\n" \
|
|
" let c_str = CStr::from_ptr(ptr).to_string_lossy().into_owned();\n" \
|
|
" free (ptr as *const u8);\n" \
|
|
" String::from (c_str)\n" \
|
|
" }\n" \
|
|
" }\n" \
|
|
"}\n" \
|
|
"\n" \
|
|
"#[no_mangle]\n" \
|
|
"#[allow(unused_variables)]\n" \
|
|
"#[allow(unused_unsafe)]\n" \
|
|
"pub extern fn entry(core: *const u8) {\n" \
|
|
" let r2 = R2;\n" \
|
|
" unsafe { /* because core is external */\n";
|
|
const char *rust_footer = \
|
|
" }\n" \
|
|
"}\n";
|
|
fputs (rust_header, fd);
|
|
fputs (code, fd);
|
|
fputs (rust_footer, fd);
|
|
fclose (fd);
|
|
lang_rust_file (lang, "_tmp.rs");
|
|
r_file_rm ("_tmp.rs");
|
|
} else eprintf ("Cannot open _tmp.rs\n");
|
|
return true;
|
|
}
|
|
|
|
static RLangPlugin r_lang_plugin_rust = {
|
|
.name = "rust",
|
|
.ext = "rs",
|
|
.license = "MIT",
|
|
.desc = "Rust language extension",
|
|
.run = lang_rust_run,
|
|
.init = (void*)lang_rust_init,
|
|
.run_file = (void*)lang_rust_file,
|
|
};
|