dart-lang / sdk

The Dart SDK, including the VM, JS and Wasm compilers, analysis, core libraries, and more.
https://dart.dev
BSD 3-Clause "New" or "Revised" License
10.11k stars 1.57k forks source link

[vm/ffi] Using --disassemble with BSS relocation crashes disassembler #41705

Open dcharkes opened 4 years ago

dcharkes commented 4 years ago

Passing the --disassemble flag to Dart code using BSS relocations in AOT crashes the disassembler.

Currently, the only place where these are used are FFI callbacks, so I'm flagging this issue as FFI.

Hypothesis:

0x7f715ed3bf7c    cc                     int3
0x7f715ed3bf7d    cc                     int3
0x7f715ed3bf7e    cc                     int3
0x7f715ed3bf7f    cc                     int3
--- beginning of replacement
0x7f715ed3bf80    0000                   addb [rax],rax
0x7f715ed3bf82    0000                   addb [rax],rax
0x7f715ed3bf84    0000                   addb [rax],rax
0x7f715ed3bf86    0000                   addb [rax],rax
--- end of replacement
0x7f715ed3bf88    488d05f1ffffff         leaq rax,[rip-0xf]

gets replaced with an offset into the BSS section:

x7f9651b91644    cc                     int3
0x7f9651b91645    cc                     int3
0x7f9651b91646    cc                     int3
0x7f9651b91647    cc                     int3
--- replaced, and not valid instructions
0x7f9651b91648    c01916                 rcrb [rcx],22
0x7f9651b9164b    0000                   addb [rax],rax
0x7f9651b9164d    0000                   addb [rax],rax
0x7f9651b9164f    00488d                 addb [rax-0x73],rcx
--- the above instruction contains 1 byte from the replaced data and 2 bytes from a next instruction
--- Command "vm" (took 88ms):
DART_CONFIGURATION=DebugX64 out/DebugX64/dart_precompiled_runtime --print-flow-graph --print-flow-graph-filter=Ffi --disassemble --trace-runtime-calls --ignore-unrecognized-flags --packages=/usr/local/google/home/dacoharkes/dart-sdk/sdk/.packages /usr/local/google/home/dacoharkes/dart-sdk/sdk/out/DebugX64/generated_compilations/dartkp/tests_ffi_2_vmspecific_function_callbacks_test.dart_10/out.aotsnapshot

exit code:
-6

stderr:
../../runtime/vm/compiler/assembler/disassembler_x86.cc: 362: error: unreachable code
version=2.9.0-edge.3288a0c850d3bc71352d8064664b5f32724ae9c9 (be) (Wed Apr 29 11:32:55 2020 +0200) on "linux_x64"
pid=167006, thread=167009, isolate=vm-service(0x55b0c0619e00)
isolate_instructions=7faff0e47000, vm_instructions=7faff0e42000
  pc 0x000055b0bf0ba94c fp 0x00007faff097d150 dart::Profiler::DumpStackTrace(void*)+0x7c
  pc 0x000055b0bed99462 fp 0x00007faff097d230 dart::Assert::Fail(char const*, ...)+0x82
  pc 0x000055b0bf1666ba fp 0x00007faff097d270 dart::DisassemblerX64::InstructionDecode(unsigned long)+0xaca
  pc 0x000055b0bf166746 fp 0x00007faff097d2f0 dart::Disassembler::DecodeInstruction(char*, long, char*, long, int*, dart::Code const&, dart::Object**, unsigned long)+0x66
  pc 0x000055b0bf1619d2 fp 0x00007faff097e490 dart::Disassembler::Disassemble(unsigned long, unsigned long, dart::DisassemblyFormatter*, dart::Code const&, dart::Code::Comments const*)+0x162
  pc 0x000055b0bf0597c1 fp 0x00007faff097e4f0 out/DebugX64/dart_precompiled_runtime+0x90e7c1
  pc 0x000055b0bf161d79 fp 0x00007faff097e580 dart::Disassembler::DisassembleCodeHelper(char const*, dart::Code const&, bool)+0xa9
  pc 0x000055b0bf1625c1 fp 0x00007faff097e5e0 dart::Disassembler::DisassembleCode(dart::Function const&, dart::Code const&, bool)+0xa1
  pc 0x000055b0bef8b0e9 fp 0x00007faff097e630 out/DebugX64/dart_precompiled_runtime+0x8400e9
  pc 0x000055b0bef83bdc fp 0x00007faff097e6d0 dart::Deserializer::ReadProgramSnapshot(dart::ObjectStore*)+0x30c
  pc 0x000055b0bef843b0 fp 0x00007faff097e7e0 dart::FullSnapshotReader::ReadProgramSnapshot()+0x170
  pc 0x000055b0bef9f255 fp 0x00007faff097e8a0 dart::Dart::InitIsolateFromSnapshot(dart::Thread*, dart::Isolate*, unsigned char const*, unsigned char const*, unsigned char const*, long)+0x1d5
  pc 0x000055b0bef9f4fc fp 0x00007faff097ea10 dart::Dart::InitializeIsolate(unsigned char const*, unsigned char const*, unsigned char const*, long, dart::IsolateGroup*, void*)+0x1dc
  pc 0x000055b0bf3ea51d fp 0x00007faff097eab0 out/DebugX64/dart_precompiled_runtime+0xc9f51d
  pc 0x000055b0bf3ea8c8 fp 0x00007faff097eb80 Dart_CreateIsolateGroup+0x1f8
  pc 0x000055b0bed8045d fp 0x00007faff097ebe0 out/DebugX64/dart_precompiled_runtime+0x63545d
  pc 0x000055b0bf121da8 fp 0x00007faff097ec80 out/DebugX64/dart_precompiled_runtime+0x9d6da8
  pc 0x000055b0bf149e55 fp 0x00007faff097ecd0 dart::ThreadPool::Worker::Loop()+0xe5
  pc 0x000055b0bf149951 fp 0x00007faff097ed20 dart::ThreadPool::Worker::Main(unsigned long)+0x131
  pc 0x000055b0bf0b55e2 fp 0x00007faff097ee70 out/DebugX64/dart_precompiled_runtime+0x96a5e2
-- End of DumpStackTrace

--- Re-run this test:
python tools/test.py -c dartkp ffi_2/vmspecific_function_callbacks_test/10
[00:49 | 100% | +  194 | -    4]

cc @mkustermann

mkustermann commented 4 years ago

We can just fill the not-yet relocated offset with breakpoint instructions (i.e. int3 on intel).

dcharkes commented 4 years ago

No, this is after relocation, when reading the snapshot. Or do you mean that we detect the pattern and replace it temporarily with int3s when disassembling?

mkustermann commented 4 years ago

I see. It's the new technology which runs the disassembler at AOT runtime.

We could also change the pc-relative load from BSS to use instructions to build up the constant instead of loading the constant from the instruction stream & jumping over it.

We do this in other situations already, e.g. loads from the object pool.