wasm-micro-runtime
wasm-micro-runtime copied to clipboard
Disassembler misinterprets instructions
While working on the disassembly view for the VS Code extension (#1801 #1818), I faced some issues when disassembling. This is how to reproduce using a simple c program:
#include <stdio.h>
void myfunc(int iteration) { printf("iteration %d end\n", iteration); }
int main() {
printf("Hello World\n");
for (size_t i = 0; i < 5; i++) {
myfunc(i);
}
return 0;
}
That's what I get when disassembling:
$ wasm-micro-runtime/core/deps/llvm/build-lldb/bin/lldb
Platform: remote-linux
Connected: no
Process 1 stopped
* thread #1, name = 'nobody', stop reason = trace
frame #0: 0x4000000000001069 test.wasm
-> 0x4000000000001069: block
0x400000000000106b: i32.const 0
0x400000000000106d: i32.load 3680
0x4000000000001074: br_if 0 ; 0: down to label0
(lldb) b main
Breakpoint 1: where = test.wasm`main + 41 at test.c:7:3, address = 0x400000000000112f
(lldb) c
Process 1 resuming
Process 1 stopped
* thread #1, name = 'nobody', stop reason = breakpoint 1.1
frame #0: 0x400000000000112f test.wasm`main at test.c:7:3
4
5 int main() {
6
-> 7 printf("Hello World\n");
8
9 for (size_t i = 0; i < 5; i++) {
10 myfunc(i);
(lldb) dis
test.wasm`main:
0x4000000000001106 <+0>: nop
What's causing the problem is the local[0..20] type=i32 instruction at the beginning of the stack frame, that fails to be decoded, hence stopping the decoding of the whole stack frame:
$ wasm-objdump -d test.wasm
test.wasm: file format wasm 0x1
[...]
001106 func[48] <__original_main>:
001107: 15 7f | local[0..20] type=i32
001109: 23 80 80 80 80 00 | global.get 0 <__stack_pointer>
00110f: 21 00 | local.set 0
001111: 41 10 | i32.const 16
001113: 21 01 | local.set 1
001115: 20 00 | local.get 0
Another related crash (it happens only with the commented line):
#include <stdio.h>
int sum(int a, int b) { return a + b; }
int main() {
// printf("Hello world!\n");
int a = 1;
int b = 2;
int c = sum(a, b);
printf("sum: %d", c);
return 0;
}
$ wasm-micro-runtime/core/deps/llvm/build-lldb/bin/lldb
Platform: remote-linux
Connected: no
Process 1 stopped
* thread #1, name = 'nobody', stop reason = trace
frame #0: 0x4000000000001066 test.wasm
-> 0x4000000000001066: block
0x4000000000001068: i32.const 0
0x400000000000106a: i32.load 3664
0x4000000000001071: br_if 0 ; 0: down to label0
(lldb) b main
Breakpoint 1: where = test.wasm`main + 41 at test.c:8:7, address = 0x400000000000110e
(lldb) c
Process 1 resuming
Process 1 stopped
* thread #1, name = 'nobody', stop reason = breakpoint 1.1
frame #0: 0x400000000000110e test.wasm`main at test.c:8:7
5 int main() {
6 // printf("Hello world!\n");
7
-> 8 int a = 1;
9 int b = 2;
10 int c = sum(a, b);
11 printf("sum: %d", c);
(lldb) dis
Assertion failed: (length < sizeof(m_data.inst.bytes)), function SetOpcodeBytes, file Opcode.h, line 188.
PLEASE submit a bug report to https://bugs.llvm.org/ and include the crash backtrace.
Stack dump:
0. Program arguments: wasm-micro-runtime/core/deps/llvm/build-lldb/bin/lldb
Stack dump without symbol names (ensure you have llvm-symbolizer in your PATH or set the environment var `LLVM_SYMBOLIZER_PATH` to point to it):
0 lldb 0x00000001008ddb00 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) + 72
1 lldb 0x00000001008de05c PrintStackTraceSignalHandler(void*) + 28
2 lldb 0x00000001008dbd40 llvm::sys::RunSignalHandlers() + 136
3 lldb 0x00000001008e0b6c SignalHandler(int) + 252
4 libsystem_platform.dylib 0x00000001abcab4a4 _sigtramp + 56
5 libsystem_pthread.dylib 0x00000001abc93ee0 pthread_kill + 288
6 libsystem_c.dylib 0x00000001abbce340 abort + 168
7 libsystem_c.dylib 0x00000001abbcd754 err + 0
8 liblldb.13.0.1.dylib 0x0000000120db10dc lldb_private::Opcode::SetOpcodeBytes(void const*, unsigned long) + 128
9 liblldb.13.0.1.dylib 0x0000000120db04f0 InstructionLLVMC::Decode(lldb_private::Disassembler const&, lldb_private::DataExtractor const&, unsigned long long) + 1060
10 liblldb.13.0.1.dylib 0x0000000120dae148 DisassemblerLLVMC::DecodeInstructions(lldb_private::Address const&, lldb_private::DataExtractor const&, unsigned long long, unsigned long, bool, bool) + 388
11 liblldb.13.0.1.dylib 0x0000000120591da0 lldb_private::Disassembler::ParseInstructions(lldb_private::Target&, lldb_private::Address, lldb_private::Disassembler::Limit, lldb_private::Stream*, bool) + 768
12 liblldb.13.0.1.dylib 0x000000012059208c lldb_private::Disassembler::Disassemble(lldb_private::Debugger&, lldb_private::ArchSpec const&, char const*, char const*, lldb_private::ExecutionContext const&, lldb_private::Address const&, lldb_private::Disassembler::Limit, bool, unsigned int, unsigned int, lldb_private::Stream&) + 288
13 liblldb.13.0.1.dylib 0x000000012265b600 lldb_private::CommandObjectDisassemble::DoExecute(lldb_private::Args&, lldb_private::CommandReturnObject&) + 1400
14 liblldb.13.0.1.dylib 0x00000001208d336c lldb_private::CommandObjectParsed::Execute(char const*, lldb_private::CommandReturnObject&) + 600
15 liblldb.13.0.1.dylib 0x000000012089c068 lldb_private::CommandInterpreter::HandleCommand(char const*, lldb_private::LazyBool, lldb_private::CommandReturnObject&) + 2388
16 liblldb.13.0.1.dylib 0x00000001208a0b94 lldb_private::CommandInterpreter::IOHandlerInputComplete(lldb_private::IOHandler&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&) + 400
17 liblldb.13.0.1.dylib 0x00000001205e0cfc lldb_private::IOHandlerEditline::Run() + 368
18 liblldb.13.0.1.dylib 0x0000000120576720 lldb_private::Debugger::RunIOHandlers() + 84
19 liblldb.13.0.1.dylib 0x00000001208a22f4 lldb_private::CommandInterpreter::RunCommandInterpreter(lldb_private::CommandInterpreterRunOptions&) + 204
20 liblldb.13.0.1.dylib 0x000000011ff8ccd0 lldb::SBDebugger::RunCommandInterpreter(bool, bool) + 456
21 lldb 0x000000010075104c Driver::MainLoop() + 2900
22 lldb 0x0000000100751aec main + 1148
23 dyld 0x0000000100f2908c start + 520
make: *** [lldb] Abort trap: 6