1 //===-- DynamicLoaderWindowsDYLD.cpp --------------------------------*- C++
2 //-*-===//
3 //
4 //                     The LLVM Compiler Infrastructure
5 //
6 // This file is distributed under the University of Illinois Open Source
7 // License. See LICENSE.TXT for details.
8 //
9 //===----------------------------------------------------------------------===//
10 
11 #include "DynamicLoaderWindowsDYLD.h"
12 
13 #include "lldb/Core/PluginManager.h"
14 #include "lldb/Target/ExecutionContext.h"
15 #include "lldb/Target/Process.h"
16 #include "lldb/Target/RegisterContext.h"
17 #include "lldb/Target/Target.h"
18 #include "lldb/Target/ThreadPlanStepInstruction.h"
19 
20 #include "llvm/ADT/Triple.h"
21 
22 using namespace lldb;
23 using namespace lldb_private;
24 
25 DynamicLoaderWindowsDYLD::DynamicLoaderWindowsDYLD(Process *process)
26     : DynamicLoader(process) {}
27 
28 DynamicLoaderWindowsDYLD::~DynamicLoaderWindowsDYLD() {}
29 
30 void DynamicLoaderWindowsDYLD::Initialize() {
31   PluginManager::RegisterPlugin(GetPluginNameStatic(),
32                                 GetPluginDescriptionStatic(), CreateInstance);
33 }
34 
35 void DynamicLoaderWindowsDYLD::Terminate() {}
36 
37 ConstString DynamicLoaderWindowsDYLD::GetPluginNameStatic() {
38   static ConstString g_plugin_name("windows-dyld");
39   return g_plugin_name;
40 }
41 
42 const char *DynamicLoaderWindowsDYLD::GetPluginDescriptionStatic() {
43   return "Dynamic loader plug-in that watches for shared library "
44          "loads/unloads in Windows processes.";
45 }
46 
47 DynamicLoader *DynamicLoaderWindowsDYLD::CreateInstance(Process *process,
48                                                         bool force) {
49   bool should_create = force;
50   if (!should_create) {
51     const llvm::Triple &triple_ref =
52         process->GetTarget().GetArchitecture().GetTriple();
53     if (triple_ref.getOS() == llvm::Triple::Win32)
54       should_create = true;
55   }
56 
57   if (should_create)
58     return new DynamicLoaderWindowsDYLD(process);
59 
60   return nullptr;
61 }
62 
63 void DynamicLoaderWindowsDYLD::DidAttach() {}
64 
65 void DynamicLoaderWindowsDYLD::DidLaunch() {}
66 
67 Status DynamicLoaderWindowsDYLD::CanLoadImage() { return Status(); }
68 
69 ConstString DynamicLoaderWindowsDYLD::GetPluginName() {
70   return GetPluginNameStatic();
71 }
72 
73 uint32_t DynamicLoaderWindowsDYLD::GetPluginVersion() { return 1; }
74 
75 ThreadPlanSP
76 DynamicLoaderWindowsDYLD::GetStepThroughTrampolinePlan(Thread &thread,
77                                                        bool stop) {
78   auto arch = m_process->GetTarget().GetArchitecture();
79   if (arch.GetMachine() != llvm::Triple::x86) {
80     return ThreadPlanSP();
81   }
82 
83   uint64_t pc = thread.GetRegisterContext()->GetPC();
84   // Max size of an instruction in x86 is 15 bytes.
85   AddressRange range(pc, 2 * 15);
86 
87   ExecutionContext exe_ctx(m_process->GetTarget());
88   DisassemblerSP disassembler_sp = Disassembler::DisassembleRange(
89       arch, nullptr, nullptr, exe_ctx, range, true);
90   if (!disassembler_sp) {
91     return ThreadPlanSP();
92   }
93 
94   InstructionList *insn_list = &disassembler_sp->GetInstructionList();
95   if (insn_list == nullptr) {
96     return ThreadPlanSP();
97   }
98 
99   // First instruction in a x86 Windows trampoline is going to be an indirect
100   // jump through the IAT and the next one will be a nop (usually there for
101   // alignment purposes). e.g.:
102   //     0x70ff4cfc <+956>: jmpl   *0x7100c2a8
103   //     0x70ff4d02 <+962>: nop
104 
105   auto first_insn = insn_list->GetInstructionAtIndex(0);
106   auto second_insn = insn_list->GetInstructionAtIndex(1);
107 
108   if (first_insn == nullptr || second_insn == nullptr ||
109       strcmp(first_insn->GetMnemonic(&exe_ctx), "jmpl") != 0 ||
110       strcmp(second_insn->GetMnemonic(&exe_ctx), "nop") != 0) {
111     return ThreadPlanSP();
112   }
113 
114   assert(first_insn->DoesBranch() && !second_insn->DoesBranch());
115 
116   return ThreadPlanSP(new ThreadPlanStepInstruction(
117       thread, false, false, eVoteNoOpinion, eVoteNoOpinion));
118 }
119