To protect your data, the CISO officer has suggested users to enable GitLab 2FA as soon as possible.

mod.rs 7.61 KB
Newer Older
1
2
use log;
use simple_logger;
3
use utils;
4
use ast::ir::*;
5
use vm::VM;
6
7
use compiler::backend::Word;
use compiler::backend::RegGroup;
qinsoon's avatar
qinsoon committed
8
use utils::Address;
9

10
use std::fmt;
11
12
13
use std::os::raw::c_char;
use std::os::raw::c_void;
use std::ffi::CString;
14
15
use std::ffi::CStr;
use std::sync::Arc;
16

qinsoon's avatar
qinsoon committed
17
18
19
pub extern crate gc as mm;
pub mod thread;
pub mod entrypoints;
qinsoon's avatar
qinsoon committed
20
21
22

#[cfg(target_arch = "x86_64")]
#[path = "exception_x64.rs"]
23
pub mod exception;
qinsoon's avatar
qinsoon committed
24

25
26
27
// consider using libloading crate instead of the raw c functions for dynalic libraries
// however i am not sure if libloading can load symbols from current process (not from an actual dylib)
// so here i use dlopen/dlsym from C
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#[link(name="dl")]
extern "C" {
    fn dlopen(filename: *const c_char, flags: isize) -> *const c_void;
    fn dlsym(handle: *const c_void, symbol: *const c_char) -> *const c_void;
}

pub fn resolve_symbol(symbol: String) -> Address {
    use std::ptr;
    
    let rtld_default = unsafe {dlopen(ptr::null(), 0)};
    let ret = unsafe {dlsym(rtld_default, CString::new(symbol.clone()).unwrap().as_ptr())};
    
    if ret == 0 as *const c_void {
        panic!("cannot find symbol {}", symbol);
    }
    
    Address::from_ptr(ret)
}

qinsoon's avatar
qinsoon committed
47
48
use rustc_serialize::{Encodable, Encoder, Decodable, Decoder};

qinsoon's avatar
qinsoon committed
49
#[derive(PartialEq, Eq, Hash, Clone, Debug)]
50
pub enum ValueLocation {
qinsoon's avatar
qinsoon committed
51
52
53
    Register(RegGroup, MuID),     // 0
    Constant(RegGroup, Word),     // 1    
    Relocatable(RegGroup, MuName),// 2
54
    
qinsoon's avatar
qinsoon committed
55
56
57
58
    Direct(RegGroup, Address),    // 3
    Indirect(RegGroup, Address),  // 4
}

59
60
61
62
63
64
65
66
67
68
69
70
impl fmt::Display for ValueLocation {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &ValueLocation::Register(_, id) => write!(f, "VL_Reg: {}", id),
            &ValueLocation::Constant(_, val) => write!(f, "VL_Const: {}", val),
            &ValueLocation::Relocatable(_, ref name) => write!(f, "VL_Reloc: {}", name),
            &ValueLocation::Direct(_, addr) => write!(f, "VL_Direct: 0x{:x}", addr),
            &ValueLocation::Indirect(_, addr) => write!(f, "VL_Indirect: 0x{:x}", addr)
        }
    }
}

qinsoon's avatar
qinsoon committed
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
impl Encodable for ValueLocation {
    fn encode<S: Encoder> (&self, s: &mut S) -> Result<(), S::Error> {
        s.emit_enum("ValueLocation", |s| {
            match self {
                &ValueLocation::Register(grp, id) => {
                    s.emit_enum_variant("Register", 0, 2, |s| {
                        try!(s.emit_enum_variant_arg(0, |s| grp.encode(s)));
                        try!(s.emit_enum_variant_arg(1, |s| id.encode(s)));
                        Ok(())
                    })
                }
                &ValueLocation::Constant(grp, val) => {
                    s.emit_enum_variant("Constant", 1, 2, |s| {
                        try!(s.emit_enum_variant_arg(0, |s| grp.encode(s)));
                        try!(s.emit_enum_variant_arg(1, |s| val.encode(s)));
                        Ok(())
                    })    
                }                
                &ValueLocation::Relocatable(grp, ref name) => {
                    s.emit_enum_variant("Relocatable", 2, 2, |s| {
                        try!(s.emit_enum_variant_arg(0, |s| grp.encode(s)));
                        try!(s.emit_enum_variant_arg(1, |s| name.encode(s)));
                        Ok(())
                    })
                }
                &ValueLocation::Direct(_, _)
                | &ValueLocation::Indirect(_, _) => {
                    panic!("trying to encode an address location (not persistent)")
                }
            }
        })
    }
}

impl Decodable for ValueLocation {
    fn decode<D: Decoder>(d: &mut D) -> Result<ValueLocation, D::Error> {
        d.read_enum("ValueLocation", |d| {
            d.read_enum_variant(
                &vec!["Register", "Constant", "Relocatable"],
                |d, idx| {
                    match idx {
                        0 => {
                            // Register variant
                            let grp = try!(d.read_enum_variant_arg(0, |d| Decodable::decode(d)));
                            let id = try!(d.read_enum_variant_arg(1, |d| Decodable::decode(d)));
                            
                            Ok(ValueLocation::Register(grp, id))
                        }
                        1 => {
                            // Constant
                            let grp = try!(d.read_enum_variant_arg(0, |d| Decodable::decode(d)));
                            let val = try!(d.read_enum_variant_arg(1, |d| Decodable::decode(d)));
                            Ok(ValueLocation::Constant(grp, val))
                        }
                        2 => {
                            // Relocatable
                            let grp = try!(d.read_enum_variant_arg(0, |d| Decodable::decode(d)));
                            let name = try!(d.read_enum_variant_arg(1, |d| Decodable::decode(d)));
                            Ok(ValueLocation::Relocatable(grp, name))
                        }
                        _ => panic!("unexpected enum variant for ValueLocation: {}", idx)
                    }
                }
             ) 
        })
    }
137
138
139
140
141
142
143
}

impl ValueLocation {
    pub fn load_value(&self) -> (RegGroup, Word) {
        match self {
            &ValueLocation::Register(_, _)
            | &ValueLocation::Direct(_, _)
144
145
146
147
148
            | &ValueLocation::Indirect(_, _) => unimplemented!(),
            
            &ValueLocation::Constant(group, word) => {
                (group, word)
            }
149
150
151
            &ValueLocation::Relocatable(_, _) => panic!("expect a runtime value")
        }
    }
qinsoon's avatar
qinsoon committed
152
    
153
    #[allow(unused_variables)]
qinsoon's avatar
qinsoon committed
154
    pub fn from_constant(c: Constant) -> ValueLocation {
155
156
157
158
159
160
161
        match c {
            Constant::Int(int_val) => ValueLocation::Constant(RegGroup::GPR, utils::mem::u64_to_raw(int_val)),
            Constant::Float(f32_val) => ValueLocation::Constant(RegGroup::FPR, utils::mem::f32_to_raw(f32_val)),
            Constant::Double(f64_val) => ValueLocation::Constant(RegGroup::FPR, utils::mem::f64_to_raw(f64_val)),
            
            _ => unimplemented!()
        }
qinsoon's avatar
qinsoon committed
162
    }
qinsoon's avatar
qinsoon committed
163
164
165
166
167
168
169
170
171
172
    
    pub fn to_address(&self) -> Address {
        match self {
            &ValueLocation::Register(_, _)
            | &ValueLocation::Constant(_, _) => panic!("a register/constant cannot be turned into address"),
            &ValueLocation::Direct(_, addr) => addr, 
            &ValueLocation::Indirect(_, addr) => unsafe {addr.load::<Address>()},
            &ValueLocation::Relocatable(_, ref symbol) => resolve_symbol(symbol.clone())
        }
    }
173
174
}

175
176
pub const PRIMORDIAL_ENTRY : &'static str = "src/runtime/main.c";

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
#[no_mangle]
pub extern fn mu_trace_level_log() {
    simple_logger::init_with_level(log::LogLevel::Trace).ok();
}

#[no_mangle]
pub extern fn mu_main(serialized_vm : *const c_char) {      
    debug!("mu_main() started...");
    
    let str_vm = unsafe{CStr::from_ptr(serialized_vm)}.to_str().unwrap();
    
    let vm : Arc<VM> = Arc::new(VM::resume_vm(str_vm));
    
    let primordial = vm.primordial.read().unwrap();
    if primordial.is_none() {
        panic!("no primordial thread/stack/function. Client should provide an entry point");
    } else {
        let primordial = primordial.as_ref().unwrap();
        
        // create mu stack
        let stack = vm.new_stack(primordial.func_id);
        
        let args : Vec<ValueLocation> = primordial.args.iter().map(|arg| ValueLocation::from_constant(arg.clone())).collect();
        
        // FIXME: currently assumes no user defined thread local
        // will need to fix this after we can serialize heap object
203
        let thread = thread::MuThread::new_thread_normal(stack, unsafe{Address::zero()}, args, vm.clone());
204
205
206
        
        thread.join().unwrap();
    }
qinsoon's avatar
qinsoon committed
207
}