-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
590 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
target | ||
Cargo.lock |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
[package] | ||
name = "llvm_assemble" | ||
version = "0.1.0" | ||
authors = ["snf <[email protected]>"] | ||
build = "build.rs" | ||
|
||
[dependencies] | ||
libc = "*" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
//extern crate gcc; | ||
|
||
use std::process::Command; | ||
use std::env; | ||
use std::path::Path; | ||
|
||
fn llvm_config_get(llvm_config: &str, config: &str) -> String { | ||
let cmd = Command::new(llvm_config).arg(config).output().unwrap(); | ||
String::from_utf8(cmd.stdout).unwrap().trim().to_string() | ||
} | ||
|
||
fn main() { | ||
let out_dir = env::var("OUT_DIR").unwrap(); | ||
let llvm_config = { | ||
if let Ok(v) = env::var("LLVM_CONFIG") { | ||
v | ||
} else { | ||
"/home/asdf/local/bin/llvm-config".to_string() | ||
} | ||
}; | ||
|
||
macro_rules! get_flags { | ||
($arg:expr) => ( | ||
{ | ||
let llvm_flags = llvm_config_get(&llvm_config, $arg); | ||
let llvm_flags_args: Vec<String> = | ||
llvm_flags | ||
.split_whitespace() | ||
.map(|s| s.to_owned()) | ||
.collect(); | ||
llvm_flags_args | ||
} | ||
) | ||
} | ||
|
||
let llvm_cxxflags = get_flags!("--cxxflags"); | ||
let llvm_ldflags = get_flags!("--ldflags"); | ||
let llvm_libs = get_flags!("--libs"); | ||
let llvm_syslibs = get_flags!("--system-libs"); | ||
|
||
let out_obj = format!("{}/assemble.o", out_dir); | ||
let out_lib = format!("{}/libassemble.a", out_dir); | ||
|
||
Command::new("g++").args(&["src/c/assemble.cc", "-c", "-fPIC", "-o"]) | ||
.arg(&out_obj) | ||
.args(&llvm_cxxflags) | ||
.status().unwrap(); | ||
|
||
Command::new("ar").args(&["crus", &out_lib, &out_obj]) | ||
.current_dir(&Path::new(&out_dir)) | ||
.status().unwrap(); | ||
|
||
print!("cargo:rustc-flags="); | ||
for path in llvm_ldflags { | ||
print!("-L {} ", &path[2..]); | ||
} | ||
for lib in llvm_libs { | ||
print!("-l {} ", &lib[2..]); | ||
} | ||
for lib in llvm_syslibs { | ||
print!("-l {} ", &lib[2..]); | ||
} | ||
|
||
println!(""); | ||
println!("cargo:rustc-link-lib=dylib=stdc++"); | ||
println!("cargo:rustc-link-search=native={}", out_dir); | ||
println!("cargo:rustc-link-lib=static={}", "assemble"); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
#[allow(non_upper_case_globals)] | ||
#[allow(non_camel_case_types)] | ||
mod extern_def { | ||
/* automatically generated by rust-bindgen */ | ||
|
||
pub type ptrdiff_t = ::libc::c_long; | ||
pub type size_t = ::libc::c_ulong; | ||
pub type wchar_t = ::libc::c_int; | ||
pub type byte = ::libc::c_uchar; | ||
pub type Enum_Arch = ::libc::c_uint; | ||
pub const x86: ::libc::c_uint = 0; | ||
pub const x86_64: ::libc::c_uint = 1; | ||
pub const mips: ::libc::c_uint = 2; | ||
pub const arm: ::libc::c_uint = 3; | ||
pub const arm64: ::libc::c_uint = 4; | ||
pub const thumb: ::libc::c_uint = 5; | ||
pub const ppc32: ::libc::c_uint = 6; | ||
#[link(name = "assemble")] | ||
extern "C" { | ||
pub fn assemble(arch: Enum_Arch, instructions: *const ::libc::c_char, | ||
out: *mut byte, out_len: *mut size_t) -> ::libc::c_int; | ||
} | ||
} | ||
|
||
#[allow(non_camel_case_types)] | ||
pub enum Arch { | ||
X86, | ||
X86_64, | ||
Mips, | ||
Arm, | ||
Arm64, | ||
Thumb, | ||
PPC32 | ||
} | ||
|
||
impl Arch { | ||
pub fn to_c(self) -> u32 { | ||
match self { | ||
Arch::X86 => extern_def::x86, | ||
Arch::X86_64 => extern_def::x86_64, | ||
Arch::Mips => extern_def::mips, | ||
Arch::Arm => extern_def::arm, | ||
Arch::Arm64 => extern_def::arm64, | ||
Arch::Thumb => extern_def::thumb, | ||
Arch::PPC32 => extern_def::ppc32 | ||
} | ||
} | ||
} | ||
|
||
pub fn assemble(arch: Arch, input: &str) -> Option<Vec<u8>> { | ||
use std::ffi::CString; | ||
use std::slice; | ||
use libc; | ||
|
||
let e_arch = arch.to_c(); | ||
let ins = CString::new(input).unwrap(); | ||
|
||
unsafe { | ||
let mut out_len = 0x100; | ||
let out_arr: *mut u8 = libc::malloc(out_len) as (*mut u8); | ||
|
||
let res = extern_def::assemble(e_arch, ins.as_ptr(), out_arr, &mut out_len); | ||
if res == 0 { | ||
Some(slice::from_raw_parts(out_arr, out_len as usize).to_vec()) | ||
} else { | ||
None | ||
} | ||
} | ||
} | ||
|
||
#[test] | ||
fn test_assemble() { | ||
assert_eq!(assemble(Arch::X86, "int3").unwrap(), [0xcc]); | ||
} |
Oops, something went wrong.