@@ -4,18 +4,8 @@ use std::path::PathBuf;
4
4
fn main ( ) {
5
5
let out_dir = PathBuf :: from ( env:: var ( "OUT_DIR" ) . unwrap ( ) ) ;
6
6
7
- let mut function_names = Vec :: new ( ) ;
8
- function_names. push ( "replace_realloc_global_ptr" . to_owned ( ) ) ;
9
- function_names. push ( "replace_realloc_global_len" . to_owned ( ) ) ;
10
- function_names. push ( "replace_fds" . to_owned ( ) ) ;
11
-
12
- let mut global_names = Vec :: new ( ) ;
13
- global_names. push ( "internal_realloc_global_ptr" . to_owned ( ) ) ;
14
- global_names. push ( "internal_realloc_global_len" . to_owned ( ) ) ;
15
- global_names. push ( "internal_fds" . to_owned ( ) ) ;
16
-
17
- let wasm = build_raw_intrinsics ( & function_names, & global_names) ;
18
- let archive = build_archive ( & wasm, & function_names) ;
7
+ let wasm = build_raw_intrinsics ( ) ;
8
+ let archive = build_archive ( & wasm) ;
19
9
20
10
std:: fs:: write ( out_dir. join ( "libwasm-raw-intrinsics.a" ) , & archive) . unwrap ( ) ;
21
11
println ! ( "cargo:rustc-link-lib=static=wasm-raw-intrinsics" ) ;
@@ -31,83 +21,69 @@ fn main() {
31
21
/// ```rust
32
22
/// std::arch::global_asm!(
33
23
/// "
34
- /// .globaltype internal_realloc_global_ptr, i32
35
- /// internal_realloc_global_ptr:
36
- /// .globaltype internal_realloc_global_len, i32
37
- /// internal_realloc_global_len:
38
- /// .globaltype internal_fds, i32
39
- /// internal_fds:
24
+ /// .globaltype internal_global_ptr, i32
25
+ /// internal_global_ptr:
40
26
/// "
41
27
/// );
42
28
///
43
29
/// #[no_mangle]
44
- /// extern "C" fn replace_realloc_global_ptr(val: *mut u8 ) -> *mut u8 {
30
+ /// extern "C" fn get_global_ptr( ) -> *mut u8 {
45
31
/// unsafe {
46
32
/// let ret: *mut u8;
47
33
/// std::arch::asm!(
48
34
/// "
49
- /// global.get internal_realloc_global_ptr
50
- /// local.get {}
51
- /// global.set internal_realloc_global_ptr
35
+ /// global.get internal_global_ptr
52
36
/// ",
53
37
/// out(local) ret,
54
- /// in(local) val,
55
38
/// options(nostack, readonly)
56
39
/// );
57
40
/// ret
58
41
/// }
59
42
/// }
60
43
///
61
44
/// #[no_mangle]
62
- /// extern "C" fn replace_realloc_global_len (val: usize) -> usize {
45
+ /// extern "C" fn set_global_ptr (val: *mut u8) {
63
46
/// unsafe {
64
- /// let ret: usize;
65
47
/// std::arch::asm!(
66
48
/// "
67
- /// global.get internal_realloc_global_len
68
49
/// local.get {}
69
- /// global.set internal_realloc_global_len
50
+ /// global.set internal_global_ptr
70
51
/// ",
71
- /// out(local) ret,
72
52
/// in(local) val,
73
53
/// options(nostack, readonly)
74
54
/// );
75
- /// ret
76
55
/// }
77
56
/// }
78
57
/// ```
79
58
///
80
59
/// The main trickiness here is getting the `reloc.CODE` and `linking` sections
81
60
/// right.
82
- fn build_raw_intrinsics ( function_names : & [ String ] , global_names : & [ String ] ) -> Vec < u8 > {
61
+ fn build_raw_intrinsics ( ) -> Vec < u8 > {
83
62
use wasm_encoder:: Instruction :: * ;
84
63
use wasm_encoder:: * ;
85
64
86
65
let mut module = Module :: new ( ) ;
87
66
88
- // All our functions have the same type, i32 -> i32
89
67
let mut types = TypeSection :: new ( ) ;
90
- types. function ( [ ValType :: I32 ] , [ ValType :: I32 ] ) ;
68
+ types. function ( [ ] , [ ValType :: I32 ] ) ;
69
+ types. function ( [ ValType :: I32 ] , [ ] ) ;
91
70
module. section ( & types) ;
92
71
93
72
// Declare the functions, using the type we just added.
94
73
let mut funcs = FunctionSection :: new ( ) ;
95
- for _ in function_names {
96
- funcs. function ( 0 ) ;
97
- }
74
+ funcs. function ( 0 ) ;
75
+ funcs. function ( 1 ) ;
98
76
module. section ( & funcs) ;
99
77
100
78
// Declare the globals.
101
79
let mut globals = GlobalSection :: new ( ) ;
102
- for _ in global_names {
103
- globals. global (
104
- GlobalType {
105
- val_type : ValType :: I32 ,
106
- mutable : true ,
107
- } ,
108
- & ConstExpr :: i32_const ( 0 ) ,
109
- ) ;
110
- }
80
+ globals. global (
81
+ GlobalType {
82
+ val_type : ValType :: I32 ,
83
+ mutable : true ,
84
+ } ,
85
+ & ConstExpr :: i32_const ( 0 ) ,
86
+ ) ;
111
87
module. section ( & globals) ;
112
88
113
89
// Here the `code` section is defined. This is tricky because an offset is
@@ -117,43 +93,44 @@ fn build_raw_intrinsics(function_names: &[String], global_names: &[String]) -> V
117
93
//
118
94
// First the function body is created and then it's appended into a code
119
95
// section.
120
- let mut body = Vec :: new ( ) ;
121
- 0u32 . encode ( & mut body) ; // no locals
122
- let global_offset0 = body. len ( ) + 1 ;
123
- // global.get 0 ;; but with maximal encoding of the 0
124
- body. extend_from_slice ( & [ 0x23 , 0x80 , 0x80 , 0x80 , 0x80 , 0x00 ] ) ;
125
- LocalGet ( 0 ) . encode ( & mut body) ;
126
- let global_offset1 = body. len ( ) + 1 ;
127
- // global.set 0 ;; but with maximal encoding of the 0
128
- body. extend_from_slice ( & [ 0x24 , 0x81 , 0x80 , 0x80 , 0x80 , 0x00 ] ) ;
129
- End . encode ( & mut body) ;
130
-
131
- let mut body_offsets = Vec :: new ( ) ;
132
96
133
97
let mut code = Vec :: new ( ) ;
134
- function_names. len ( ) . encode ( & mut code) ;
135
- for _ in function_names {
98
+ 2u32 . encode ( & mut code) ;
99
+
100
+ // get_global_ptr
101
+ let global_offset0 = {
102
+ let mut body = Vec :: new ( ) ;
103
+ 0u32 . encode ( & mut body) ; // no locals
104
+ let global_offset = body. len ( ) + 1 ;
105
+ // global.get 0 ;; but with maximal encoding of the 0
106
+ body. extend_from_slice ( & [ 0x23 , 0x80 , 0x80 , 0x80 , 0x80 , 0x00 ] ) ;
107
+ End . encode ( & mut body) ;
136
108
body. len ( ) . encode ( & mut code) ; // length of the function
137
- body_offsets . push ( code. len ( ) ) ;
109
+ let offset = code. len ( ) + global_offset ;
138
110
code. extend_from_slice ( & body) ; // the function itself
139
- }
111
+ offset
112
+ } ;
113
+
114
+ // set_global_ptr
115
+ let global_offset1 = {
116
+ let mut body = Vec :: new ( ) ;
117
+ 0u32 . encode ( & mut body) ; // no locals
118
+ LocalGet ( 0 ) . encode ( & mut body) ;
119
+ let global_offset = body. len ( ) + 1 ;
120
+ // global.set 0 ;; but with maximal encoding of the 0
121
+ body. extend_from_slice ( & [ 0x24 , 0x80 , 0x80 , 0x80 , 0x80 , 0x00 ] ) ;
122
+ End . encode ( & mut body) ;
123
+ body. len ( ) . encode ( & mut code) ; // length of the function
124
+ let offset = code. len ( ) + global_offset;
125
+ code. extend_from_slice ( & body) ; // the function itself
126
+ offset
127
+ } ;
128
+
140
129
module. section ( & RawSection {
141
130
id : SectionId :: Code as u8 ,
142
131
data : & code,
143
132
} ) ;
144
133
145
- // Calculate the relocation offsets within the `code` section itself by
146
- // adding the start of where the body was placed to the offset within the
147
- // body.
148
- let global_offsets0 = body_offsets
149
- . iter ( )
150
- . map ( |x| x + global_offset0)
151
- . collect :: < Vec < _ > > ( ) ;
152
- let global_offsets1 = body_offsets
153
- . iter ( )
154
- . map ( |x| x + global_offset1)
155
- . collect :: < Vec < _ > > ( ) ;
156
-
157
134
// Here the linking section is constructed. There are two symbols described
158
135
// here, one for the function that we injected and one for the global
159
136
// that was injected. The injected global here is referenced in the
@@ -167,21 +144,22 @@ fn build_raw_intrinsics(function_names: &[String], global_names: &[String]) -> V
167
144
168
145
linking. push ( 0x08 ) ; // `WASM_SYMBOL_TABLE`
169
146
let mut subsection = Vec :: new ( ) ;
170
- 6u32 . encode ( & mut subsection) ; // 6 symbols (3 functions + 3 globals)
147
+ 3u32 . encode ( & mut subsection) ; // 3 symbols (2 functions + 1 global)
148
+
149
+ subsection. push ( 0x00 ) ; // SYMTAB_FUNCTION
150
+ 0x00 . encode ( & mut subsection) ; // flags
151
+ 0u32 . encode ( & mut subsection) ; // function index
152
+ "get_global_ptr" . encode ( & mut subsection) ; // symbol name
171
153
172
- for ( index, name) in function_names. iter ( ) . enumerate ( ) {
173
- subsection. push ( 0x00 ) ; // SYMTAB_FUNCTION
174
- 0x00 . encode ( & mut subsection) ; // flags
175
- index. encode ( & mut subsection) ; // function index
176
- name. encode ( & mut subsection) ; // symbol name
177
- }
154
+ subsection. push ( 0x00 ) ; // SYMTAB_FUNCTION
155
+ 0x00 . encode ( & mut subsection) ; // flags
156
+ 1u32 . encode ( & mut subsection) ; // function index
157
+ "set_global_ptr" . encode ( & mut subsection) ; // symbol name
178
158
179
- for ( index, name) in global_names. iter ( ) . enumerate ( ) {
180
- subsection. push ( 0x02 ) ; // SYMTAB_GLOBAL
181
- 0x02 . encode ( & mut subsection) ; // flags
182
- index. encode ( & mut subsection) ; // global index
183
- name. encode ( & mut subsection) ; // symbol name
184
- }
159
+ subsection. push ( 0x02 ) ; // SYMTAB_GLOBAL
160
+ 0x02 . encode ( & mut subsection) ; // flags
161
+ 0u32 . encode ( & mut subsection) ; // global index
162
+ "internal_global_ptr" . encode ( & mut subsection) ; // symbol name
185
163
186
164
subsection. encode ( & mut linking) ;
187
165
module. section ( & CustomSection {
@@ -195,15 +173,15 @@ fn build_raw_intrinsics(function_names: &[String], global_names: &[String]) -> V
195
173
{
196
174
let mut reloc = Vec :: new ( ) ;
197
175
3u32 . encode ( & mut reloc) ; // target section (code is the 4th section, 3 when 0-indexed)
198
- 6u32 . encode ( & mut reloc) ; // 6 relocations
199
- for index in 0 ..global_names . len ( ) {
200
- reloc. push ( 0x07 ) ; // R_WASM_GLOBAL_INDEX_LEB
201
- global_offsets0 [ index as usize ] . encode ( & mut reloc) ; // offset
202
- ( function_names . len ( ) + index ) . encode ( & mut reloc) ; // symbol index
203
- reloc . push ( 0x07 ) ; // R_WASM_GLOBAL_INDEX_LEB
204
- global_offsets1 [ index as usize ] . encode ( & mut reloc ) ; // offset
205
- ( function_names . len ( ) + index ) . encode ( & mut reloc) ; // symbol index
206
- }
176
+ 2u32 . encode ( & mut reloc) ; // 2 relocations
177
+
178
+ reloc. push ( 0x07 ) ; // R_WASM_GLOBAL_INDEX_LEB
179
+ global_offset0 . encode ( & mut reloc) ; // offset
180
+ 2u32 . encode ( & mut reloc) ; // symbol index
181
+
182
+ reloc . push ( 0x07 ) ; // R_WASM_GLOBAL_INDEX_LEB
183
+ global_offset1 . encode ( & mut reloc) ; // offset
184
+ 2u32 . encode ( & mut reloc ) ; // symbol index
207
185
208
186
module. section ( & CustomSection {
209
187
name : "reloc.CODE" ,
@@ -220,7 +198,7 @@ fn build_raw_intrinsics(function_names: &[String], global_names: &[String]) -> V
220
198
///
221
199
/// Like above this is still tricky, mainly around the production of the symbol
222
200
/// table.
223
- fn build_archive ( wasm : & [ u8 ] , function_names : & [ String ] ) -> Vec < u8 > {
201
+ fn build_archive ( wasm : & [ u8 ] ) -> Vec < u8 > {
224
202
use object:: { bytes_of, endian:: BigEndian , U32Bytes } ;
225
203
226
204
let mut archive = Vec :: new ( ) ;
@@ -238,17 +216,11 @@ fn build_archive(wasm: &[u8], function_names: &[String]) -> Vec<u8> {
238
216
// easier. Note though we don't know the offset of our `intrinsics.o` up
239
217
// front so it's left as 0 for now and filled in later.
240
218
let mut symbol_table = Vec :: new ( ) ;
241
- symbol_table. extend_from_slice ( bytes_of ( & U32Bytes :: new (
242
- BigEndian ,
243
- function_names. len ( ) . try_into ( ) . unwrap ( ) ,
244
- ) ) ) ;
245
- for _ in function_names {
246
- symbol_table. extend_from_slice ( bytes_of ( & U32Bytes :: new ( BigEndian , 0 ) ) ) ;
247
- }
248
- for name in function_names {
249
- symbol_table. extend_from_slice ( name. as_bytes ( ) ) ;
250
- symbol_table. push ( 0x00 ) ;
251
- }
219
+ symbol_table. extend_from_slice ( bytes_of ( & U32Bytes :: new ( BigEndian , 2 ) ) ) ;
220
+ symbol_table. extend_from_slice ( bytes_of ( & U32Bytes :: new ( BigEndian , 0 ) ) ) ;
221
+ symbol_table. extend_from_slice ( bytes_of ( & U32Bytes :: new ( BigEndian , 0 ) ) ) ;
222
+ symbol_table. extend_from_slice ( b"get_global_ptr\0 " ) ;
223
+ symbol_table. extend_from_slice ( b"set_global_ptr\0 " ) ;
252
224
253
225
archive. extend_from_slice ( bytes_of ( & object:: archive:: Header {
254
226
name : * b"/ " ,
@@ -277,6 +249,10 @@ fn build_archive(wasm: &[u8], function_names: &[String]) -> Vec<u8> {
277
249
BigEndian ,
278
250
member_offset. try_into ( ) . unwrap ( ) ,
279
251
) ) ) ;
252
+ archive[ symtab_offset + 8 ..] [ ..4 ] . copy_from_slice ( bytes_of ( & U32Bytes :: new (
253
+ BigEndian ,
254
+ member_offset. try_into ( ) . unwrap ( ) ,
255
+ ) ) ) ;
280
256
281
257
archive. extend_from_slice ( object:: bytes_of ( & object:: archive:: Header {
282
258
name : * b"intrinsics.o " ,
0 commit comments