mirror of
https://github.com/intel/llvm.git
synced 2026-01-17 06:40:01 +08:00
Implement trampoline step-through for Windows-x86.
Summary: This is required to be able to step through calls to external functions that are not properly marked with __declspec(dllimport). When a call like this is emitted, the linker will inject a trampoline to produce an indirect call through the IAT. Reviewers: zturner, jingham Reviewed By: jingham Subscribers: sas, jingham, lldb-commits Differential Revision: https://reviews.llvm.org/D22231 llvm-svn: 314045
This commit is contained in:
@@ -11,8 +11,11 @@
|
||||
#include "DynamicLoaderWindowsDYLD.h"
|
||||
|
||||
#include "lldb/Core/PluginManager.h"
|
||||
#include "lldb/Target/ExecutionContext.h"
|
||||
#include "lldb/Target/Process.h"
|
||||
#include "lldb/Target/RegisterContext.h"
|
||||
#include "lldb/Target/Target.h"
|
||||
#include "lldb/Target/ThreadPlanStepInstruction.h"
|
||||
|
||||
#include "llvm/ADT/Triple.h"
|
||||
|
||||
@@ -72,5 +75,44 @@ uint32_t DynamicLoaderWindowsDYLD::GetPluginVersion() { return 1; }
|
||||
ThreadPlanSP
|
||||
DynamicLoaderWindowsDYLD::GetStepThroughTrampolinePlan(Thread &thread,
|
||||
bool stop) {
|
||||
return ThreadPlanSP();
|
||||
auto arch = m_process->GetTarget().GetArchitecture();
|
||||
if (arch.GetMachine() != llvm::Triple::x86) {
|
||||
return ThreadPlanSP();
|
||||
}
|
||||
|
||||
uint64_t pc = thread.GetRegisterContext()->GetPC();
|
||||
// Max size of an instruction in x86 is 15 bytes.
|
||||
AddressRange range(pc, 2 * 15);
|
||||
|
||||
ExecutionContext exe_ctx(m_process->GetTarget());
|
||||
DisassemblerSP disassembler_sp = Disassembler::DisassembleRange(
|
||||
arch, nullptr, nullptr, exe_ctx, range, true);
|
||||
if (!disassembler_sp) {
|
||||
return ThreadPlanSP();
|
||||
}
|
||||
|
||||
InstructionList *insn_list = &disassembler_sp->GetInstructionList();
|
||||
if (insn_list == nullptr) {
|
||||
return ThreadPlanSP();
|
||||
}
|
||||
|
||||
// First instruction in a x86 Windows trampoline is going to be an indirect
|
||||
// jump through the IAT and the next one will be a nop (usually there for
|
||||
// alignment purposes). e.g.:
|
||||
// 0x70ff4cfc <+956>: jmpl *0x7100c2a8
|
||||
// 0x70ff4d02 <+962>: nop
|
||||
|
||||
auto first_insn = insn_list->GetInstructionAtIndex(0);
|
||||
auto second_insn = insn_list->GetInstructionAtIndex(1);
|
||||
|
||||
if (first_insn == nullptr || second_insn == nullptr ||
|
||||
strcmp(first_insn->GetMnemonic(&exe_ctx), "jmpl") != 0 ||
|
||||
strcmp(second_insn->GetMnemonic(&exe_ctx), "nop") != 0) {
|
||||
return ThreadPlanSP();
|
||||
}
|
||||
|
||||
assert(first_insn->DoesBranch() && !second_insn->DoesBranch());
|
||||
|
||||
return ThreadPlanSP(new ThreadPlanStepInstruction(
|
||||
thread, false, false, eVoteNoOpinion, eVoteNoOpinion));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user