DynamoRIO / DynamoRIO/dynamorio
ASSERT: cross-module tail call from native_exec module ends up interpreting back_from_native
- Dominant language
- C
- Stars
- 3.2k
- Forks
- 629
- Avg merge
- 2d 15h
- Merged PRs (30d)
- 31
Description
_From [rnk@google.com](https://code.google.com/u/rnk@google.com/) on February 14, 2013 13:17:24_
I see when using -native_exec_retakeover (not committed yet) on clang -cc1 in a std::vector<> dtor. We have this code:
0x1d25430 <_ZNSt6vectorISt4pairIPFvPvES1_ESaIS4_EED1Ev>: mov (%rdi),%rdi
0x1d25433 <_ZNSt6vectorISt4pairIPFvPvES1_ESaIS4_EED1Ev+3>: test %rdi,%rdi
0x1d25436 <_ZNSt6vectorISt4pairIPFvPvES1_ESaIS4_EED1Ev+6>: je 0x1d2543d <_ZNSt6vectorISt4pairIPFvPvES1_ESaIS4_EED1Ev+13>
0x1d25438 <_ZNSt6vectorISt4pairIPFvPvES1_ESaIS4_EED1Ev+8>: jmpq 0x6333c0 <_ZdlPv@plt>
The important thing is:
jmpq 0x6333c0
That does a tail call to operator delete. It hits our GOT interceptor, so we interpret it. We interpret the return, which tries to dispatch on back_from_native.
There are a couple of solutions:
- dispatch should know about back_from_native. This will also make it generally safe to over-interpret native modules, but might have a perf hit for apps that don't use native_exec.
- The PLT stub could check the TOS for back_from_native, and pre-emptively replace it with native_retval. This adds overhead to every PLT call.
I'm going to implement checking in dispatch and measure the performance impact. If it is negligible, then IMO it's the best.
We already have some special cases enumerated in is_stopping_point(). Maybe I can keep the number of compares down with a call to is_in_dynamo_dll(), which only does two compares.
_Original issue: http://code.google.com/p/dynamorio/issues/detail?id=1077_
Contributor guide
Assessment
This issue has not been assessed yet.