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