wasm-micro-runtime icon indicating copy to clipboard operation
wasm-micro-runtime copied to clipboard

Disassembler misinterprets instructions

Open eloparco opened this issue 3 years ago • 1 comments

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

eloparco avatar Dec 22 '22 10:12 eloparco

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

eloparco avatar Dec 22 '22 11:12 eloparco