|
| 1 | +//===-- DynamicLoaderWindows.cpp --------------------------------*- C++ -*-===// |
| 2 | +// |
| 3 | +// The LLVM Compiler Infrastructure |
| 4 | +// |
| 5 | +// This file is distributed under the University of Illinois Open Source |
| 6 | +// License. See LICENSE.TXT for details. |
| 7 | +// |
| 8 | +//===----------------------------------------------------------------------===// |
| 9 | + |
| 10 | +// C Includes |
| 11 | +// C++ Includes |
| 12 | +// Other libraries and framework includes |
| 13 | +#include "lldb/Core/PluginManager.h" |
| 14 | +#include "lldb/Core/Disassembler.h" |
| 15 | +#include "lldb/Core/Log.h" |
| 16 | +#include "lldb/Core/Module.h" |
| 17 | +#include "lldb/Core/ModuleSpec.h" |
| 18 | +#include "lldb/Core/Section.h" |
| 19 | +#include "lldb/Symbol/ObjectFile.h" |
| 20 | +#include "lldb/Target/Process.h" |
| 21 | +#include "lldb/Target/RegisterContext.h" |
| 22 | +#include "lldb/Target/SectionLoadList.h" |
| 23 | +#include "lldb/Target/Target.h" |
| 24 | +#include "lldb/Target/Thread.h" |
| 25 | +#include "lldb/Target/ThreadPlanRunToAddress.h" |
| 26 | + |
| 27 | +#include "DynamicLoaderWindows.h" |
| 28 | + |
| 29 | +using namespace lldb; |
| 30 | +using namespace lldb_private; |
| 31 | + |
| 32 | +void |
| 33 | +DynamicLoaderWindows::Initialize() |
| 34 | +{ |
| 35 | + PluginManager::RegisterPlugin(GetPluginNameStatic(), |
| 36 | + GetPluginDescriptionStatic(), |
| 37 | + CreateInstance); |
| 38 | +} |
| 39 | + |
| 40 | +void |
| 41 | +DynamicLoaderWindows::Terminate() |
| 42 | +{ |
| 43 | +} |
| 44 | + |
| 45 | +lldb_private::ConstString |
| 46 | +DynamicLoaderWindows::GetPluginName() |
| 47 | +{ |
| 48 | + return GetPluginNameStatic(); |
| 49 | +} |
| 50 | + |
| 51 | +lldb_private::ConstString |
| 52 | +DynamicLoaderWindows::GetPluginNameStatic() |
| 53 | +{ |
| 54 | + static ConstString g_name("windows-dyld"); |
| 55 | + return g_name; |
| 56 | +} |
| 57 | + |
| 58 | +const char * |
| 59 | +DynamicLoaderWindows::GetPluginDescriptionStatic() |
| 60 | +{ |
| 61 | + return "Dynamic loader plug-in that watches for shared library " |
| 62 | + "loads/unloads in Windows processes."; |
| 63 | +} |
| 64 | + |
| 65 | +void |
| 66 | +DynamicLoaderWindows::GetPluginCommandHelp(const char *command, Stream *strm) |
| 67 | +{ |
| 68 | +} |
| 69 | + |
| 70 | +uint32_t |
| 71 | +DynamicLoaderWindows::GetPluginVersion() |
| 72 | +{ |
| 73 | + return 1; |
| 74 | +} |
| 75 | + |
| 76 | +DynamicLoader * |
| 77 | +DynamicLoaderWindows::CreateInstance(Process *process, bool force) |
| 78 | +{ |
| 79 | + bool create = force; |
| 80 | + if (!create) |
| 81 | + { |
| 82 | + const llvm::Triple &triple_ref = process->GetTarget().GetArchitecture().GetTriple(); |
| 83 | + if (triple_ref.getOS() == llvm::Triple::Win32 || |
| 84 | + triple_ref.getOS() == llvm::Triple::MinGW32) |
| 85 | + create = true; |
| 86 | + } |
| 87 | + |
| 88 | + if (create) |
| 89 | + return new DynamicLoaderWindows (process); |
| 90 | + return NULL; |
| 91 | +} |
| 92 | + |
| 93 | +DynamicLoaderWindows::DynamicLoaderWindows(Process *process) |
| 94 | + : DynamicLoader(process), |
| 95 | + m_load_offset(LLDB_INVALID_ADDRESS), |
| 96 | + m_entry_point(LLDB_INVALID_ADDRESS) |
| 97 | +{ |
| 98 | +} |
| 99 | + |
| 100 | +DynamicLoaderWindows::~DynamicLoaderWindows() |
| 101 | +{ |
| 102 | +} |
| 103 | + |
| 104 | +void |
| 105 | +DynamicLoaderWindows::DidAttach() |
| 106 | +{ |
| 107 | +} |
| 108 | + |
| 109 | +void |
| 110 | +DynamicLoaderWindows::DidLaunch() |
| 111 | +{ |
| 112 | +} |
| 113 | + |
| 114 | +Error |
| 115 | +DynamicLoaderWindows::ExecutePluginCommand(Args &command, Stream *strm) |
| 116 | +{ |
| 117 | + return Error(); |
| 118 | +} |
| 119 | + |
| 120 | +Log * |
| 121 | +DynamicLoaderWindows::EnablePluginLogging(Stream *strm, Args &command) |
| 122 | +{ |
| 123 | + return NULL; |
| 124 | +} |
| 125 | + |
| 126 | +Error |
| 127 | +DynamicLoaderWindows::CanLoadImage() |
| 128 | +{ |
| 129 | + return Error(); |
| 130 | +} |
| 131 | + |
| 132 | +ThreadPlanSP |
| 133 | +DynamicLoaderWindows::GetStepThroughTrampolinePlan(Thread &thread, bool stop) |
| 134 | +{ |
| 135 | + ThreadPlanSP thread_plan_sp; |
| 136 | + |
| 137 | + RegisterContext *reg_ctx = thread.GetRegisterContext().get(); |
| 138 | + |
| 139 | + lldb::addr_t pc = reg_ctx->GetPC(); |
| 140 | + ProcessSP process_sp(thread.GetProcess()); |
| 141 | + Address pc_addr; |
| 142 | + bool addr_valid = false; |
| 143 | + uint8_t buffer[16] = { 0 }; // Must be big enough for any single instruction |
| 144 | + addr_valid = process_sp->GetTarget().GetSectionLoadList().ResolveLoadAddress(pc, pc_addr); |
| 145 | + |
| 146 | + // TODO: Cache it as in ThreadPlanAssemblyTracer::GetDisassembler () |
| 147 | + DisassemblerSP disassembler = Disassembler::FindPlugin(thread.GetProcess()->GetTarget().GetArchitecture(), NULL, NULL); |
| 148 | + if (disassembler) |
| 149 | + { |
| 150 | + Error err; |
| 151 | + process_sp->ReadMemory(pc, buffer, sizeof(buffer), err); |
| 152 | + |
| 153 | + if (err.Success()) |
| 154 | + { |
| 155 | + DataExtractor extractor(buffer, sizeof(buffer), |
| 156 | + process_sp->GetByteOrder(), |
| 157 | + process_sp->GetAddressByteSize()); |
| 158 | + |
| 159 | + bool data_from_file = false; |
| 160 | + if (addr_valid) |
| 161 | + disassembler->DecodeInstructions(pc_addr, extractor, 0, 1, false, data_from_file); |
| 162 | + else |
| 163 | + disassembler->DecodeInstructions(Address(pc), extractor, 0, 1, false, data_from_file); |
| 164 | + |
| 165 | + InstructionList &instruction_list = disassembler->GetInstructionList(); |
| 166 | + |
| 167 | + if (instruction_list.GetSize()) |
| 168 | + { |
| 169 | + const bool show_bytes = true; |
| 170 | + const bool show_address = true; |
| 171 | + Instruction *instruction = instruction_list.GetInstructionAtIndex(0).get(); |
| 172 | + |
| 173 | + ExecutionContext exe_ctx(thread.GetProcess()); |
| 174 | + const char* opcode = instruction->GetMnemonic(&exe_ctx); |
| 175 | + |
| 176 | + if (strcmp(opcode, "jmpl") == 0) |
| 177 | + { |
| 178 | + const char* operands_str = instruction->GetOperands(&exe_ctx); |
| 179 | + |
| 180 | + // Detect trampolines with pattern jmpl *0x400800 where 0x400800 contains the DLL function pointer |
| 181 | + // TODO1: Detect jmp address without string parsing (from MCInst) |
| 182 | + // TODO2: We should check import table for 0x400800 instead of fetching the pointer behind it (in PECOFF) |
| 183 | + unsigned long operand_ptr = strtoul(operands_str + 3, NULL, 16); |
| 184 | + Error error; |
| 185 | + unsigned long operand_value = process_sp->ReadPointerFromMemory(operand_ptr, error); |
| 186 | + |
| 187 | + Address sc_addr; |
| 188 | + if (process_sp->GetTarget().GetSectionLoadList().ResolveLoadAddress(operand_value, sc_addr)) |
| 189 | + { |
| 190 | + SymbolContext sc; |
| 191 | + thread.GetProcess()->GetTarget().GetImages().ResolveSymbolContextForAddress(sc_addr, eSymbolContextSymbol, sc); |
| 192 | + if (sc.symbol != NULL) |
| 193 | + { |
| 194 | + thread_plan_sp.reset(new ThreadPlanRunToAddress(thread, operand_value, false)); |
| 195 | + } |
| 196 | + } |
| 197 | + } |
| 198 | + } |
| 199 | + } |
| 200 | + } |
| 201 | + |
| 202 | + return thread_plan_sp; |
| 203 | +} |
0 commit comments