summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSam Clegg <sbc@chromium.org>2020-05-18 12:15:41 -0400
committerGitHub <noreply@github.com>2020-05-18 09:15:41 -0700
commitb3275eb89f086b3a2b0effbafa3b38b4f6ce4ef6 (patch)
treefc016cc4cafd1961381139bf7af20c72859d5fec
parentc451ca33ce6609d8fac0529a84c8396c80fdbfa1 (diff)
downloadbinaryen-b3275eb89f086b3a2b0effbafa3b38b4f6ce4ef6.tar.gz
binaryen-b3275eb89f086b3a2b0effbafa3b38b4f6ce4ef6.tar.bz2
binaryen-b3275eb89f086b3a2b0effbafa3b38b4f6ce4ef6.zip
Add additional test for --check-stack-overflow (#2857)
This test verifies that functions in the llvm input source that do stack pointer manipulation get correctly handled by `wasm-emscripten-finalize --check-stack-overflow` (StackLimitEnforcer)
-rwxr-xr-xscripts/test/generate_lld_tests.py3
-rw-r--r--scripts/test/lld.py64
-rw-r--r--test/lld/basic_safe_stack.s38
-rw-r--r--test/lld/basic_safe_stack.wat41
-rw-r--r--test/lld/basic_safe_stack.wat.out116
5 files changed, 230 insertions, 32 deletions
diff --git a/scripts/test/generate_lld_tests.py b/scripts/test/generate_lld_tests.py
index 25a72f885..8338ffbd9 100755
--- a/scripts/test/generate_lld_tests.py
+++ b/scripts/test/generate_lld_tests.py
@@ -34,7 +34,7 @@ def generate_wat_files(llvm_bin, emscripten_root):
print('\n[ building wat files from C sources... ]\n')
lld_path = os.path.join(shared.options.binaryen_test, 'lld')
- for src_file, ext in files_with_extensions(lld_path, ['.c', '.cpp']):
+ for src_file, ext in files_with_extensions(lld_path, ['.c', '.cpp', '.s']):
print('..', src_file)
obj_file = src_file.replace(ext, '.o')
@@ -69,6 +69,7 @@ def generate_wat_files(llvm_bin, emscripten_root):
'--export', '__wasm_call_ctors',
'--export', '__data_end',
'--global-base=568',
+ '--no-gc-sections',
]
# We had a regression where this test only worked if debug names
# were included.
diff --git a/scripts/test/lld.py b/scripts/test/lld.py
index 19528ebc6..1407ea4b7 100644
--- a/scripts/test/lld.py
+++ b/scripts/test/lld.py
@@ -30,41 +30,43 @@ def args_for_finalize(filename):
return ret
+def run_test(input_path):
+ print('..', input_path)
+ is_passive = '.passive.' in input_path
+ mem_file = input_path + '.mem'
+ extension_arg_map = {
+ '.out': [],
+ }
+ if not is_passive:
+ extension_arg_map.update({
+ '.mem.out': ['--separate-data-segments', mem_file],
+ })
+ for ext, args in extension_arg_map.items():
+ expected_file = input_path + ext
+ if ext != '.out' and not os.path.exists(expected_file):
+ continue
+
+ cmd = shared.WASM_EMSCRIPTEN_FINALIZE + [input_path, '-S'] + args
+ cmd += args_for_finalize(os.path.basename(input_path))
+ actual = support.run_command(cmd)
+
+ if not os.path.exists(expected_file):
+ print(actual)
+ shared.fail_with_error('output ' + expected_file +
+ ' does not exist')
+ shared.fail_if_not_identical_to_file(actual, expected_file)
+ if ext == '.mem.out':
+ with open(mem_file) as mf:
+ mem = mf.read()
+ shared.fail_if_not_identical_to_file(mem, input_path + '.mem.mem')
+ os.remove(mem_file)
+
+
def test_wasm_emscripten_finalize():
print('\n[ checking wasm-emscripten-finalize testcases... ]\n')
for input_path in shared.get_tests(shared.get_test_dir('lld'), ['.wat', '.wasm']):
- print('..', input_path)
- is_passive = '.passive.' in input_path
- mem_file = input_path + '.mem'
- extension_arg_map = {
- '.out': [],
- }
- if not is_passive:
- extension_arg_map.update({
- '.mem.out': ['--separate-data-segments', mem_file],
- })
- for ext, ext_args in extension_arg_map.items():
- expected_file = input_path + ext
- if ext != '.out' and not os.path.exists(expected_file):
- continue
-
- cmd = shared.WASM_EMSCRIPTEN_FINALIZE + [input_path, '-S'] + \
- ext_args
- cmd += args_for_finalize(os.path.basename(input_path))
- actual = support.run_command(cmd)
-
- if not os.path.exists(expected_file):
- print(actual)
- shared.fail_with_error('output ' + expected_file +
- ' does not exist')
- shared.fail_if_not_identical_to_file(actual, expected_file)
- if ext == '.mem.out':
- with open(mem_file) as mf:
- mem = mf.read()
- shared.fail_if_not_identical_to_file(mem, input_path +
- '.mem.mem')
- os.remove(mem_file)
+ run_test(input_path)
def update_lld_tests():
diff --git a/test/lld/basic_safe_stack.s b/test/lld/basic_safe_stack.s
new file mode 100644
index 000000000..74614e798
--- /dev/null
+++ b/test/lld/basic_safe_stack.s
@@ -0,0 +1,38 @@
+# Test that wasm-binaryen-finalize --check-stack-overflow correctly
+# inserts stack chekc handlers.
+
+.globl stackRestore
+.globl stackAlloc
+
+.globaltype __stack_pointer, i32
+
+stackRestore:
+ .functype stackRestore(i32) -> ()
+ local.get 0
+ global.set __stack_pointer
+ end_function
+
+stackAlloc:
+ .functype stackAlloc(i32) -> (i32)
+ .local i32, i32
+ global.get __stack_pointer
+ # Get arg 0 -> number of bytes to allocate
+ local.get 0
+ # Stack grows down. Subtract arg0 from __stack_pointer
+ i32.sub
+ # Align result by anding with ~15
+ i32.const 0xfffffff0
+ i32.and
+ local.tee 1
+ global.set __stack_pointer
+ local.get 1
+ end_function
+
+.globl main
+main:
+ .functype main () -> ()
+ end_function
+
+.export_name stackAlloc, stackAlloc
+.export_name stackSave, stackSave
+.export_name stackRestore, stackRestore
diff --git a/test/lld/basic_safe_stack.wat b/test/lld/basic_safe_stack.wat
new file mode 100644
index 000000000..27f172913
--- /dev/null
+++ b/test/lld/basic_safe_stack.wat
@@ -0,0 +1,41 @@
+(module
+ (type $none_=>_none (func))
+ (type $i32_=>_none (func (param i32)))
+ (type $i32_=>_i32 (func (param i32) (result i32)))
+ (memory $0 2)
+ (table $0 1 1 funcref)
+ (global $global$0 (mut i32) (i32.const 66112))
+ (global $global$1 i32 (i32.const 568))
+ (export "memory" (memory $0))
+ (export "__wasm_call_ctors" (func $__wasm_call_ctors))
+ (export "stackRestore" (func $stackRestore))
+ (export "stackAlloc" (func $stackAlloc))
+ (export "main" (func $main))
+ (export "__data_end" (global $global$1))
+ (func $__wasm_call_ctors
+ )
+ (func $stackRestore (param $0 i32)
+ (global.set $global$0
+ (local.get $0)
+ )
+ )
+ (func $stackAlloc (param $0 i32) (result i32)
+ (local $1 i32)
+ (local $2 i32)
+ (global.set $global$0
+ (local.tee $1
+ (i32.and
+ (i32.sub
+ (global.get $global$0)
+ (local.get $0)
+ )
+ (i32.const -16)
+ )
+ )
+ )
+ (local.get $1)
+ )
+ (func $main
+ )
+)
+
diff --git a/test/lld/basic_safe_stack.wat.out b/test/lld/basic_safe_stack.wat.out
new file mode 100644
index 000000000..037d729df
--- /dev/null
+++ b/test/lld/basic_safe_stack.wat.out
@@ -0,0 +1,116 @@
+(module
+ (type $none_=>_none (func))
+ (type $i32_=>_none (func (param i32)))
+ (type $i32_=>_i32 (func (param i32) (result i32)))
+ (type $none_=>_i32 (func (result i32)))
+ (import "env" "__handle_stack_overflow" (func $__handle_stack_overflow))
+ (memory $0 2)
+ (table $0 1 1 funcref)
+ (global $global$0 (mut i32) (i32.const 66112))
+ (global $global$1 i32 (i32.const 568))
+ (global $__stack_limit (mut i32) (i32.const 0))
+ (export "memory" (memory $0))
+ (export "__wasm_call_ctors" (func $__wasm_call_ctors))
+ (export "stackRestore" (func $stackRestore))
+ (export "stackAlloc" (func $stackAlloc))
+ (export "main" (func $main))
+ (export "__data_end" (global $global$1))
+ (export "__set_stack_limit" (func $__set_stack_limit))
+ (export "stackSave" (func $stackSave))
+ (export "__growWasmMemory" (func $__growWasmMemory))
+ (func $__wasm_call_ctors
+ (nop)
+ )
+ (func $stackRestore (param $0 i32)
+ (local $1 i32)
+ (if
+ (i32.lt_u
+ (local.tee $1
+ (local.get $0)
+ )
+ (global.get $__stack_limit)
+ )
+ (call $__handle_stack_overflow)
+ )
+ (global.set $global$0
+ (local.get $1)
+ )
+ )
+ (func $stackAlloc (param $0 i32) (result i32)
+ (local $1 i32)
+ (local $2 i32)
+ (local $3 i32)
+ (block
+ (if
+ (i32.lt_u
+ (local.tee $3
+ (local.tee $1
+ (i32.and
+ (i32.sub
+ (global.get $global$0)
+ (local.get $0)
+ )
+ (i32.const -16)
+ )
+ )
+ )
+ (global.get $__stack_limit)
+ )
+ (call $__handle_stack_overflow)
+ )
+ (global.set $global$0
+ (local.get $3)
+ )
+ )
+ (local.get $1)
+ )
+ (func $main
+ (nop)
+ )
+ (func $__set_stack_limit (param $0 i32)
+ (global.set $__stack_limit
+ (local.get $0)
+ )
+ )
+ (func $stackSave (result i32)
+ (global.get $global$0)
+ )
+ (func $__growWasmMemory (param $newSize i32) (result i32)
+ (memory.grow
+ (local.get $newSize)
+ )
+ )
+)
+(;
+--BEGIN METADATA --
+{
+ "staticBump": 0,
+ "tableSize": 1,
+ "initializers": [
+ "__wasm_call_ctors"
+ ],
+ "declares": [
+ "__handle_stack_overflow"
+ ],
+ "externs": [
+ ],
+ "exports": [
+ "__wasm_call_ctors",
+ "stackRestore",
+ "stackAlloc",
+ "main",
+ "__set_stack_limit",
+ "stackSave",
+ "__growWasmMemory"
+ ],
+ "namedGlobals": {
+ "__data_end" : "568"
+ },
+ "invokeFuncs": [
+ ],
+ "features": [
+ ],
+ "mainReadsParams": 1
+}
+-- END METADATA --
+;)