1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
use raw::*;
use context::Context;
use function::CompiledFunction;
use util::from_ptr;
use libc::{c_uint, c_char};
use std::ffi::{self, CString};
use std::{fmt, str};
use std::marker::PhantomData;
use std::{mem, ptr};
use std::iter::Iterator;
use std::error::Error;
pub struct Needed<'a> {
_reader: jit_readelf_t,
index: c_uint,
length: c_uint,
marker: PhantomData<&'a ()>
}
impl<'a> Needed<'a> {
#[inline(always)]
fn new(read:&'a ReadElf) -> Needed<'a> {
unsafe {
Needed {
_reader: read.into(),
index: 0,
length: jit_readelf_num_needed(read.into()),
marker: PhantomData
}
}
}
}
impl<'a> Iterator for Needed<'a> {
type Item = &'a str;
fn next(&mut self) -> Option<&'a str> {
let index = self.index;
self.index += 1;
unsafe {
if index < self.length {
let c_name = jit_readelf_get_needed(self._reader, index);
Some(str::from_utf8(ffi::CStr::from_ptr(c_name).to_bytes()).unwrap())
} else {
None
}
}
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
((self.length - self.index) as usize, None)
}
}
pub struct ReadElf {
_reader: jit_readelf_t
}
native_ref!(ReadElf, _reader: jit_readelf_t);
#[repr(i32)]
#[derive(Clone, Copy)]
pub enum ReadElfErrorCode {
CannotOpen,
NotElf,
WrongArch,
BadFormat,
Memory
}
impl fmt::Debug for ReadElfErrorCode {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
write!(fmt, "{}", self.description())
}
}
impl fmt::Display for ReadElfErrorCode {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
write!(fmt, "{}", self.description())
}
}
impl Error for ReadElfErrorCode {
fn description(&self) -> &'static str {
match *self {
ReadElfErrorCode::CannotOpen => "Could not open the file",
ReadElfErrorCode::NotElf => "Not an ELF-format binary",
ReadElfErrorCode::WrongArch => "Wrong architecture for local system",
ReadElfErrorCode::BadFormat => "ELF file, but badly formatted",
ReadElfErrorCode::Memory => "Insufficient memory to load the file"
}
}
}
#[derive(Clone, Copy)]
pub struct ReadElfError<'a> {
filename: &'a str,
error: ReadElfErrorCode
}
impl<'a> fmt::Display for ReadElfError<'a> {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
write!(fmt, "'{}': {}", self.filename, self.error.description())
}
}
impl ReadElf {
pub fn new(filename:&str) -> Result<ReadElf, ReadElfError> {
unsafe {
let mut this = ptr::null_mut();
let c_name = CString::new(filename.as_bytes()).unwrap();
let code = jit_readelf_open(&mut this, mem::transmute(c_name.as_bytes().as_ptr()), 0);
if code == 0 {
Ok(from_ptr(this))
} else {
Err(ReadElfError {
filename: filename,
error: mem::transmute(code)
})
}
}
}
#[inline]
pub fn get_name(&self) -> &str {
unsafe {
let c_name = jit_readelf_get_name(self.into());
str::from_utf8(ffi::CStr::from_ptr(c_name).to_bytes()).unwrap()
}
}
#[inline]
pub fn add_to_context(&self, ctx:&Context) {
unsafe {
jit_readelf_add_to_context(self.into(), ctx.into())
}
}
#[inline]
pub unsafe fn get_symbol<T>(&self, symbol:&str) -> &mut T {
let c_sym = CString::new(symbol.as_bytes()).unwrap();
mem::transmute(jit_readelf_get_symbol(self.into(), c_sym.as_bytes().as_ptr() as *const c_char))
}
#[inline]
pub fn needed(&self) -> Needed {
Needed::new(self)
}
}
impl Drop for ReadElf {
#[inline]
fn drop(&mut self) {
unsafe {
jit_readelf_close(self.into())
}
}
}
pub struct WriteElf {
_writer: jit_writeelf_t
}
native_ref!(WriteElf, _writer: jit_writeelf_t);
impl WriteElf {
#[inline]
pub fn new(lib_name:&str) -> WriteElf {
unsafe {
let c_lib = CString::new(lib_name.as_bytes()).unwrap();
from_ptr(jit_writeelf_create(c_lib.as_bytes().as_ptr() as *const c_char))
}
}
#[inline]
pub fn write(&self, filename:&str) -> bool {
unsafe {
let c_filename = CString::new(filename.as_bytes()).unwrap();
jit_writeelf_write(self.into(), c_filename.as_bytes().as_ptr() as *const c_char) != 0
}
}
#[inline]
pub fn add_function(&self, func:&CompiledFunction, name:&str) -> bool {
unsafe {
let c_name = CString::new(name.as_bytes()).unwrap();
jit_writeelf_add_function(self.into(), func.into(), c_name.as_bytes().as_ptr() as *const c_char) != 0
}
}
#[inline]
pub fn add_needed(&self, lib_name:&str) -> bool {
unsafe {
let c_lib = CString::new(lib_name.as_bytes()).unwrap();
jit_writeelf_add_needed(self.into(), c_lib.as_bytes().as_ptr() as *const c_char) != 0
}
}
}
impl Drop for WriteElf {
#[inline]
fn drop(&mut self) {
unsafe {
jit_writeelf_destroy(self.into())
}
}
}