Skip to content

Commit

Permalink
Dynamic loading support
Browse files Browse the repository at this point in the history
  • Loading branch information
xxuejie committed Nov 26, 2020
1 parent b88f9bd commit 0284643
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 0 deletions.
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ version = "0.1.0"
license = "MIT"
authors = ["Nervos Core Dev <[email protected]>"]
edition = "2018"
build = "build.rs"

[lib]
crate-type = ["lib", "staticlib", "cdylib"]
Expand All @@ -18,3 +19,6 @@ lazy_static = "1.4"
serde = "1.0"
serde_derive = "1.0"
serde_json = "1.0"

[build-dependencies]
cc = "1.0"
3 changes: 3 additions & 0 deletions build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
fn main() {
cc::Build::new().file("src/dlopen.c").compile("dlopen");
}
27 changes: 27 additions & 0 deletions src/dlopen.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#include <dlfcn.h>
#include <stdint.h>

#define ERROR_MEMORY_NOT_ENOUGH -23
#define ERROR_DYNAMIC_LOADING -24
#define RISCV_PGSIZE 4096
#define ROUNDUP(a, b) ((((a)-1) / (b) + 1) * (b))

int simulator_internal_dlopen2(const char* native_library_path,
const uint8_t* code, size_t length,
uint8_t* aligned_addr, size_t aligned_size,
void** handle, size_t* consumed_size) {
/* TODO: parse ELF and consume proper pages */
(void)code;
(void)aligned_addr;
size_t aligned_length = ROUNDUP(length, RISCV_PGSIZE);
if (aligned_size < aligned_length) {
return ERROR_MEMORY_NOT_ENOUGH;
}
*consumed_size = aligned_length;
*handle = dlopen(native_library_path, RTLD_NOW);
return -1;
}

void* ckb_dlsym(void* handle, const char* symbol) {
return dlsym(handle, symbol);
}
65 changes: 65 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ use constants::{
SOURCE_GROUP_OUTPUT, SOURCE_HEADER_DEP, SOURCE_INPUT, SOURCE_OUTPUT,
};
use serde_derive::{Deserialize, Serialize};
use std::collections::HashMap;
use std::ffi::CStr;
use std::os::raw::{c_char, c_int, c_void};

Expand All @@ -27,6 +28,7 @@ pub struct RunningSetup {
pub is_lock_script: bool,
pub is_output: bool,
pub script_index: u64,
pub native_binaries: HashMap<Vec<u8>, String>,
}

lazy_static! {
Expand Down Expand Up @@ -279,6 +281,69 @@ pub extern "C" fn ckb_load_cell_data(
CKB_SUCCESS
}

extern "C" {
fn simulator_internal_dlopen2(
native_library_path: *const u8,
code: *const u8,
length: u64,
aligned_addr: *mut u8,
aligned_size: u64,
handle: *mut *mut c_void,
consumed_size: *mut u64,
) -> c_int;
}

#[no_mangle]
pub extern "C" fn ckb_dlopen2(
dep_cell_hash: *const u8,
hash_type: u8,
aligned_addr: *mut u8,
aligned_size: u64,
handle: *mut *mut c_void,
consumed_size: *mut u64,
) -> c_int {
let dep_cell_hash = unsafe {
let ptr = dep_cell_hash.as_ref().expect("casting pointer");
std::slice::from_raw_parts(ptr, 32)
};
let mut buffer = vec![];
buffer.extend_from_slice(dep_cell_hash);
buffer.push(hash_type);
let filename = SETUP
.native_binaries
.get(&buffer)
.expect("cannot locate native binary!");
let cell_dep = TRANSACTION
.mock_info
.cell_deps
.iter()
.find(|cell_dep| {
if hash_type == 1 {
cell_dep
.output
.type_()
.to_opt()
.map(|t| t.calc_script_hash().as_slice() == dep_cell_hash)
.unwrap_or(false)
} else {
CellOutput::calc_data_hash(&cell_dep.data).as_slice() == dep_cell_hash
}
})
.expect("cannot locate cell dep");
let cell_data = cell_dep.data.as_ref();
unsafe {
simulator_internal_dlopen2(
filename.as_str().as_ptr(),
cell_data.as_ptr(),
cell_data.len() as u64,
aligned_addr,
aligned_size,
handle,
consumed_size,
)
}
}

fn fetch_cell(index: u64, source: u64) -> Result<(CellOutput, Bytes), c_int> {
match source {
SOURCE_INPUT => TRANSACTION
Expand Down

0 comments on commit 0284643

Please sign in to comment.