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/Module.h" 14 #include "lldb/Core/PluginManager.h" 15 #include "lldb/Target/ExecutionContext.h" 16 #include "lldb/Target/Process.h" 17 #include "lldb/Target/RegisterContext.h" 18 #include "lldb/Target/Target.h" 19 #include "lldb/Target/ThreadPlanStepInstruction.h" 20 #include "lldb/Utility/Log.h" 21 22 #include "llvm/ADT/Triple.h" 23 24 using namespace lldb; 25 using namespace lldb_private; 26 27 DynamicLoaderWindowsDYLD::DynamicLoaderWindowsDYLD(Process *process) 28 : DynamicLoader(process) {} 29 30 DynamicLoaderWindowsDYLD::~DynamicLoaderWindowsDYLD() {} 31 32 void DynamicLoaderWindowsDYLD::Initialize() { 33 PluginManager::RegisterPlugin(GetPluginNameStatic(), 34 GetPluginDescriptionStatic(), CreateInstance); 35 } 36 37 void DynamicLoaderWindowsDYLD::Terminate() {} 38 39 ConstString DynamicLoaderWindowsDYLD::GetPluginNameStatic() { 40 static ConstString g_plugin_name("windows-dyld"); 41 return g_plugin_name; 42 } 43 44 const char *DynamicLoaderWindowsDYLD::GetPluginDescriptionStatic() { 45 return "Dynamic loader plug-in that watches for shared library " 46 "loads/unloads in Windows processes."; 47 } 48 49 DynamicLoader *DynamicLoaderWindowsDYLD::CreateInstance(Process *process, 50 bool force) { 51 bool should_create = force; 52 if (!should_create) { 53 const llvm::Triple &triple_ref = 54 process->GetTarget().GetArchitecture().GetTriple(); 55 if (triple_ref.getOS() == llvm::Triple::Win32) 56 should_create = true; 57 } 58 59 if (should_create) 60 return new DynamicLoaderWindowsDYLD(process); 61 62 return nullptr; 63 } 64 65 void DynamicLoaderWindowsDYLD::DidAttach() { 66 Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); 67 if (log) 68 log->Printf("DynamicLoaderWindowsDYLD::%s()", __FUNCTION__); 69 70 ModuleSP executable = GetTargetExecutable(); 71 72 if (!executable.get()) 73 return; 74 75 // Try to fetch the load address of the file from the process, since there 76 // could be randomization of the load address. 77 78 // It might happen that the remote has a different dir for the file, so we 79 // only send the basename of the executable in the query. I think this is safe 80 // because I doubt that two executables with the same basenames are loaded in 81 // memory... 82 FileSpec file_spec( 83 executable->GetPlatformFileSpec().GetFilename().GetCString()); 84 bool is_loaded; 85 addr_t base_addr = 0; 86 lldb::addr_t load_addr; 87 Status error = m_process->GetFileLoadAddress(file_spec, is_loaded, load_addr); 88 if (error.Success() && is_loaded) { 89 base_addr = load_addr; 90 UpdateLoadedSections(executable, LLDB_INVALID_ADDRESS, base_addr, false); 91 } 92 93 ModuleList module_list; 94 module_list.Append(executable); 95 m_process->GetTarget().ModulesDidLoad(module_list); 96 m_process->LoadModules(); 97 } 98 99 void DynamicLoaderWindowsDYLD::DidLaunch() {} 100 101 Status DynamicLoaderWindowsDYLD::CanLoadImage() { return Status(); } 102 103 ConstString DynamicLoaderWindowsDYLD::GetPluginName() { 104 return GetPluginNameStatic(); 105 } 106 107 uint32_t DynamicLoaderWindowsDYLD::GetPluginVersion() { return 1; } 108 109 ThreadPlanSP 110 DynamicLoaderWindowsDYLD::GetStepThroughTrampolinePlan(Thread &thread, 111 bool stop) { 112 auto arch = m_process->GetTarget().GetArchitecture(); 113 if (arch.GetMachine() != llvm::Triple::x86) { 114 return ThreadPlanSP(); 115 } 116 117 uint64_t pc = thread.GetRegisterContext()->GetPC(); 118 // Max size of an instruction in x86 is 15 bytes. 119 AddressRange range(pc, 2 * 15); 120 121 ExecutionContext exe_ctx(m_process->GetTarget()); 122 DisassemblerSP disassembler_sp = Disassembler::DisassembleRange( 123 arch, nullptr, nullptr, exe_ctx, range, true); 124 if (!disassembler_sp) { 125 return ThreadPlanSP(); 126 } 127 128 InstructionList *insn_list = &disassembler_sp->GetInstructionList(); 129 if (insn_list == nullptr) { 130 return ThreadPlanSP(); 131 } 132 133 // First instruction in a x86 Windows trampoline is going to be an indirect 134 // jump through the IAT and the next one will be a nop (usually there for 135 // alignment purposes). e.g.: 136 // 0x70ff4cfc <+956>: jmpl *0x7100c2a8 137 // 0x70ff4d02 <+962>: nop 138 139 auto first_insn = insn_list->GetInstructionAtIndex(0); 140 auto second_insn = insn_list->GetInstructionAtIndex(1); 141 142 if (first_insn == nullptr || second_insn == nullptr || 143 strcmp(first_insn->GetMnemonic(&exe_ctx), "jmpl") != 0 || 144 strcmp(second_insn->GetMnemonic(&exe_ctx), "nop") != 0) { 145 return ThreadPlanSP(); 146 } 147 148 assert(first_insn->DoesBranch() && !second_insn->DoesBranch()); 149 150 return ThreadPlanSP(new ThreadPlanStepInstruction( 151 thread, false, false, eVoteNoOpinion, eVoteNoOpinion)); 152 } 153