Description
I am trying to build a shared WebAssembly library (in the sense of https://github.com/WebAssembly/tool-conventions/blob/master/DynamicLinking.md) from Rust.
The following looks promising:
#![no_main]
#![feature(link_args)]
#![allow(unused_attributes)]
#![link_args = "--import-memory"]
#![link_args = "--shared"]
// no_std just to make the output smaller and easier to understand
#![no_std]
#![feature(lang_items)]
#[lang = "eh_personality"] extern fn eh_personality() {}
use core::panic::PanicInfo;
#[panic_handler]
fn panic(_info: &PanicInfo) -> ! { loop {} }
#[link(wasm_import_module = "import")]
extern { pub fn foo(ptr : *const u8); }
#[export_name = "start"]
pub unsafe fn start() {
foo("Hi".as_ptr());
}
If I compile this (using --target wasm32-unknown-unknown
), I get the following code:
(module
(type $0 (func (param i32)))
(type $1 (func))
(type $2 (func (param i32 i32) (result i32)))
(import "env" "memory" (memory $0 0))
(import "env" "__indirect_function_table" (table 0 anyfunc))
(import "env" "__stack_pointer" (global $gimport$2 i32))
(import "env" "__memory_base" (global $gimport$3 i32))
(import "env" "__table_base" (global $gimport$4 i32))
(import "import" "foo" (func $foo (param i32)))
(global $global$0 i32 (i32.const 0))
(data (get_global $gimport$3) "\01gdb_load_rust_pretty_printers.py\00Hi")
(export "__rustc_debug_gdb_scripts_section__" (global $global$0))
(export "start" (func $start))
(func $__wasm_call_ctors (; 1 ;) (type $1)
)
(func $_ZN4core3str21_$LT$impl$u20$str$GT$6as_ptr17hd1ab9e60453863b8E (; 2 ;) (type $2) (param $var$0 i32) (param $var$1 i32) (result i32)
(local $var$2 i32)
(local $var$3 i32)
(local $var$4 i32)
(local $var$5 i32)
(set_local $var$2
(get_global $gimport$2)
)
(set_local $var$3
(i32.const 16)
)
(set_local $var$4
(i32.sub
(get_local $var$2)
(get_local $var$3)
)
)
(i32.store offset=8
(get_local $var$4)
(get_local $var$0)
)
(i32.store offset=12
(get_local $var$4)
(get_local $var$1)
)
(set_local $var$5
(i32.load offset=8
(get_local $var$4)
)
)
(return
(get_local $var$5)
)
)
(func $start (; 3 ;) (type $1)
(local $var$0 i32)
(local $var$1 i32)
(local $var$2 i32)
(local $var$3 i32)
(set_local $var$0
(i32.const 34)
)
(set_local $var$1
(get_local $var$0)
)
(set_local $var$2
(i32.const 2)
)
(set_local $var$3
(call $_ZN4core3str21_$LT$impl$u20$str$GT$6as_ptr17hd1ab9e60453863b8E
(get_local $var$1)
(get_local $var$2)
)
)
(call $foo
(get_local $var$3)
)
(return)
)
;; custom section "dylink", size 5
;; custom section ".debug_info", size 1748
;; custom section ".debug_macinfo", size 2
;; custom section ".debug_pubtypes", size 959
;; custom section ".debug_ranges", size 32
;; custom section ".debug_abbrev", size 401
;; custom section ".debug_line", size 280
;; custom section ".debug_str", size 1569
;; custom section ".debug_pubnames", size 235
;; custom section "producers", size 79
)
It is very promising that this module imports __stack_pointer
and __memory_base
, and that it puts the static data ("\01gdb_load_rust_pretty_printers.py\00Hi"
) at a position that is determined by the imported __memory_base
.
But when the code actually references the Hi
string, in function start
, it simply uses an absolute pointer, without shifting it by __memory_base
:
(set_local $var$0
(i32.const 34)
)
so this does not seem to be working yet.
Is there a flag I am using wrong? Or is this just not yet supported?
$ rustc --version
rustc 1.35.0-nightly (3750348da 2019-04-08)