1dda28197Spatrick //===-- JITLoaderGDB.cpp --------------------------------------------------===//
2061da546Spatrick //
3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information.
5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6061da546Spatrick //
7061da546Spatrick //===----------------------------------------------------------------------===//
8061da546Spatrick
9061da546Spatrick #include "JITLoaderGDB.h"
10061da546Spatrick #include "Plugins/ObjectFile/Mach-O/ObjectFileMachO.h"
11061da546Spatrick #include "lldb/Breakpoint/Breakpoint.h"
12061da546Spatrick #include "lldb/Core/Module.h"
13061da546Spatrick #include "lldb/Core/ModuleSpec.h"
14061da546Spatrick #include "lldb/Core/PluginManager.h"
15061da546Spatrick #include "lldb/Core/Section.h"
16061da546Spatrick #include "lldb/Interpreter/OptionValueProperties.h"
17061da546Spatrick #include "lldb/Symbol/ObjectFile.h"
18061da546Spatrick #include "lldb/Symbol/Symbol.h"
19061da546Spatrick #include "lldb/Symbol/SymbolContext.h"
20061da546Spatrick #include "lldb/Symbol/SymbolVendor.h"
21061da546Spatrick #include "lldb/Target/Process.h"
22061da546Spatrick #include "lldb/Target/SectionLoadList.h"
23061da546Spatrick #include "lldb/Target/Target.h"
24061da546Spatrick #include "lldb/Utility/DataBufferHeap.h"
25061da546Spatrick #include "lldb/Utility/LLDBAssert.h"
26*f6aab3d8Srobert #include "lldb/Utility/LLDBLog.h"
27061da546Spatrick #include "lldb/Utility/Log.h"
28061da546Spatrick #include "lldb/Utility/StreamString.h"
29061da546Spatrick #include "llvm/Support/MathExtras.h"
30061da546Spatrick
31061da546Spatrick #include <memory>
32061da546Spatrick
33061da546Spatrick using namespace lldb;
34061da546Spatrick using namespace lldb_private;
35061da546Spatrick
36dda28197Spatrick LLDB_PLUGIN_DEFINE(JITLoaderGDB)
37dda28197Spatrick
38061da546Spatrick // Debug Interface Structures
39061da546Spatrick enum jit_actions_t { JIT_NOACTION = 0, JIT_REGISTER_FN, JIT_UNREGISTER_FN };
40061da546Spatrick
41061da546Spatrick template <typename ptr_t> struct jit_code_entry {
42061da546Spatrick ptr_t next_entry; // pointer
43061da546Spatrick ptr_t prev_entry; // pointer
44061da546Spatrick ptr_t symfile_addr; // pointer
45061da546Spatrick uint64_t symfile_size;
46061da546Spatrick };
47061da546Spatrick
48061da546Spatrick template <typename ptr_t> struct jit_descriptor {
49061da546Spatrick uint32_t version;
50061da546Spatrick uint32_t action_flag; // Values are jit_action_t
51061da546Spatrick ptr_t relevant_entry; // pointer
52061da546Spatrick ptr_t first_entry; // pointer
53061da546Spatrick };
54061da546Spatrick
55061da546Spatrick namespace {
56061da546Spatrick enum EnableJITLoaderGDB {
57061da546Spatrick eEnableJITLoaderGDBDefault,
58061da546Spatrick eEnableJITLoaderGDBOn,
59061da546Spatrick eEnableJITLoaderGDBOff,
60061da546Spatrick };
61061da546Spatrick
62061da546Spatrick static constexpr OptionEnumValueElement g_enable_jit_loader_gdb_enumerators[] =
63061da546Spatrick {
64061da546Spatrick {
65061da546Spatrick eEnableJITLoaderGDBDefault,
66061da546Spatrick "default",
67061da546Spatrick "Enable JIT compilation interface for all platforms except macOS",
68061da546Spatrick },
69061da546Spatrick {
70061da546Spatrick eEnableJITLoaderGDBOn,
71061da546Spatrick "on",
72061da546Spatrick "Enable JIT compilation interface",
73061da546Spatrick },
74061da546Spatrick {
75061da546Spatrick eEnableJITLoaderGDBOff,
76061da546Spatrick "off",
77061da546Spatrick "Disable JIT compilation interface",
78061da546Spatrick },
79061da546Spatrick };
80061da546Spatrick
81061da546Spatrick #define LLDB_PROPERTIES_jitloadergdb
82061da546Spatrick #include "JITLoaderGDBProperties.inc"
83061da546Spatrick
84061da546Spatrick enum {
85061da546Spatrick #define LLDB_PROPERTIES_jitloadergdb
86061da546Spatrick #include "JITLoaderGDBPropertiesEnum.inc"
87061da546Spatrick ePropertyEnableJITBreakpoint
88061da546Spatrick };
89061da546Spatrick
90061da546Spatrick class PluginProperties : public Properties {
91061da546Spatrick public:
GetSettingName()92061da546Spatrick static ConstString GetSettingName() {
93*f6aab3d8Srobert return ConstString(JITLoaderGDB::GetPluginNameStatic());
94061da546Spatrick }
95061da546Spatrick
PluginProperties()96061da546Spatrick PluginProperties() {
97061da546Spatrick m_collection_sp = std::make_shared<OptionValueProperties>(GetSettingName());
98061da546Spatrick m_collection_sp->Initialize(g_jitloadergdb_properties);
99061da546Spatrick }
100061da546Spatrick
GetEnable() const101061da546Spatrick EnableJITLoaderGDB GetEnable() const {
102061da546Spatrick return (EnableJITLoaderGDB)m_collection_sp->GetPropertyAtIndexAsEnumeration(
103061da546Spatrick nullptr, ePropertyEnable,
104061da546Spatrick g_jitloadergdb_properties[ePropertyEnable].default_uint_value);
105061da546Spatrick }
106061da546Spatrick };
107*f6aab3d8Srobert } // namespace
108061da546Spatrick
GetGlobalPluginProperties()109*f6aab3d8Srobert static PluginProperties &GetGlobalPluginProperties() {
110*f6aab3d8Srobert static PluginProperties g_settings;
111*f6aab3d8Srobert return g_settings;
112061da546Spatrick }
113061da546Spatrick
114061da546Spatrick template <typename ptr_t>
ReadJITEntry(const addr_t from_addr,Process * process,jit_code_entry<ptr_t> * entry)115*f6aab3d8Srobert static bool ReadJITEntry(const addr_t from_addr, Process *process,
116061da546Spatrick jit_code_entry<ptr_t> *entry) {
117061da546Spatrick lldbassert(from_addr % sizeof(ptr_t) == 0);
118061da546Spatrick
119061da546Spatrick ArchSpec::Core core = process->GetTarget().GetArchitecture().GetCore();
120061da546Spatrick bool i386_target = ArchSpec::kCore_x86_32_first <= core &&
121061da546Spatrick core <= ArchSpec::kCore_x86_32_last;
122061da546Spatrick uint8_t uint64_align_bytes = i386_target ? 4 : 8;
123061da546Spatrick const size_t data_byte_size =
124061da546Spatrick llvm::alignTo(sizeof(ptr_t) * 3, uint64_align_bytes) + sizeof(uint64_t);
125061da546Spatrick
126061da546Spatrick Status error;
127061da546Spatrick DataBufferHeap data(data_byte_size, 0);
128061da546Spatrick size_t bytes_read = process->ReadMemory(from_addr, data.GetBytes(),
129061da546Spatrick data.GetByteSize(), error);
130061da546Spatrick if (bytes_read != data_byte_size || !error.Success())
131061da546Spatrick return false;
132061da546Spatrick
133061da546Spatrick DataExtractor extractor(data.GetBytes(), data.GetByteSize(),
134061da546Spatrick process->GetByteOrder(), sizeof(ptr_t));
135061da546Spatrick lldb::offset_t offset = 0;
136dda28197Spatrick entry->next_entry = extractor.GetAddress(&offset);
137dda28197Spatrick entry->prev_entry = extractor.GetAddress(&offset);
138dda28197Spatrick entry->symfile_addr = extractor.GetAddress(&offset);
139061da546Spatrick offset = llvm::alignTo(offset, uint64_align_bytes);
140061da546Spatrick entry->symfile_size = extractor.GetU64(&offset);
141061da546Spatrick
142061da546Spatrick return true;
143061da546Spatrick }
144061da546Spatrick
JITLoaderGDB(lldb_private::Process * process)145061da546Spatrick JITLoaderGDB::JITLoaderGDB(lldb_private::Process *process)
146061da546Spatrick : JITLoader(process), m_jit_objects(),
147061da546Spatrick m_jit_break_id(LLDB_INVALID_BREAK_ID),
148061da546Spatrick m_jit_descriptor_addr(LLDB_INVALID_ADDRESS) {}
149061da546Spatrick
~JITLoaderGDB()150061da546Spatrick JITLoaderGDB::~JITLoaderGDB() {
151061da546Spatrick if (LLDB_BREAK_ID_IS_VALID(m_jit_break_id))
152061da546Spatrick m_process->GetTarget().RemoveBreakpointByID(m_jit_break_id);
153061da546Spatrick }
154061da546Spatrick
DebuggerInitialize(Debugger & debugger)155061da546Spatrick void JITLoaderGDB::DebuggerInitialize(Debugger &debugger) {
156061da546Spatrick if (!PluginManager::GetSettingForJITLoaderPlugin(
157061da546Spatrick debugger, PluginProperties::GetSettingName())) {
158061da546Spatrick const bool is_global_setting = true;
159061da546Spatrick PluginManager::CreateSettingForJITLoaderPlugin(
160*f6aab3d8Srobert debugger, GetGlobalPluginProperties().GetValueProperties(),
161061da546Spatrick ConstString("Properties for the JIT LoaderGDB plug-in."),
162061da546Spatrick is_global_setting);
163061da546Spatrick }
164061da546Spatrick }
165061da546Spatrick
DidAttach()166061da546Spatrick void JITLoaderGDB::DidAttach() {
167061da546Spatrick Target &target = m_process->GetTarget();
168061da546Spatrick ModuleList &module_list = target.GetImages();
169061da546Spatrick SetJITBreakpoint(module_list);
170061da546Spatrick }
171061da546Spatrick
DidLaunch()172061da546Spatrick void JITLoaderGDB::DidLaunch() {
173061da546Spatrick Target &target = m_process->GetTarget();
174061da546Spatrick ModuleList &module_list = target.GetImages();
175061da546Spatrick SetJITBreakpoint(module_list);
176061da546Spatrick }
177061da546Spatrick
ModulesDidLoad(ModuleList & module_list)178061da546Spatrick void JITLoaderGDB::ModulesDidLoad(ModuleList &module_list) {
179061da546Spatrick if (!DidSetJITBreakpoint() && m_process->IsAlive())
180061da546Spatrick SetJITBreakpoint(module_list);
181061da546Spatrick }
182061da546Spatrick
183061da546Spatrick // Setup the JIT Breakpoint
SetJITBreakpoint(lldb_private::ModuleList & module_list)184061da546Spatrick void JITLoaderGDB::SetJITBreakpoint(lldb_private::ModuleList &module_list) {
185061da546Spatrick if (DidSetJITBreakpoint())
186061da546Spatrick return;
187061da546Spatrick
188*f6aab3d8Srobert Log *log = GetLog(LLDBLog::JITLoader);
189061da546Spatrick LLDB_LOGF(log, "JITLoaderGDB::%s looking for JIT register hook",
190061da546Spatrick __FUNCTION__);
191061da546Spatrick
192061da546Spatrick addr_t jit_addr = GetSymbolAddress(
193*f6aab3d8Srobert module_list, ConstString("__jit_debug_register_code"), eSymbolTypeCode);
194061da546Spatrick if (jit_addr == LLDB_INVALID_ADDRESS)
195061da546Spatrick return;
196061da546Spatrick
197061da546Spatrick m_jit_descriptor_addr = GetSymbolAddress(
198061da546Spatrick module_list, ConstString("__jit_debug_descriptor"), eSymbolTypeData);
199061da546Spatrick if (m_jit_descriptor_addr == LLDB_INVALID_ADDRESS) {
200061da546Spatrick LLDB_LOGF(log, "JITLoaderGDB::%s failed to find JIT descriptor address",
201061da546Spatrick __FUNCTION__);
202061da546Spatrick return;
203061da546Spatrick }
204061da546Spatrick
205061da546Spatrick LLDB_LOGF(log, "JITLoaderGDB::%s setting JIT breakpoint", __FUNCTION__);
206061da546Spatrick
207061da546Spatrick Breakpoint *bp =
208061da546Spatrick m_process->GetTarget().CreateBreakpoint(jit_addr, true, false).get();
209061da546Spatrick bp->SetCallback(JITDebugBreakpointHit, this, true);
210061da546Spatrick bp->SetBreakpointKind("jit-debug-register");
211061da546Spatrick m_jit_break_id = bp->GetID();
212061da546Spatrick
213061da546Spatrick ReadJITDescriptor(true);
214061da546Spatrick }
215061da546Spatrick
JITDebugBreakpointHit(void * baton,StoppointCallbackContext * context,user_id_t break_id,user_id_t break_loc_id)216061da546Spatrick bool JITLoaderGDB::JITDebugBreakpointHit(void *baton,
217061da546Spatrick StoppointCallbackContext *context,
218061da546Spatrick user_id_t break_id,
219061da546Spatrick user_id_t break_loc_id) {
220*f6aab3d8Srobert Log *log = GetLog(LLDBLog::JITLoader);
221061da546Spatrick LLDB_LOGF(log, "JITLoaderGDB::%s hit JIT breakpoint", __FUNCTION__);
222061da546Spatrick JITLoaderGDB *instance = static_cast<JITLoaderGDB *>(baton);
223061da546Spatrick return instance->ReadJITDescriptor(false);
224061da546Spatrick }
225061da546Spatrick
updateSectionLoadAddress(const SectionList & section_list,Target & target,uint64_t symbolfile_addr,uint64_t symbolfile_size,uint64_t & vmaddrheuristic,uint64_t & min_addr,uint64_t & max_addr)226061da546Spatrick static void updateSectionLoadAddress(const SectionList §ion_list,
227061da546Spatrick Target &target, uint64_t symbolfile_addr,
228061da546Spatrick uint64_t symbolfile_size,
229061da546Spatrick uint64_t &vmaddrheuristic,
230061da546Spatrick uint64_t &min_addr, uint64_t &max_addr) {
231061da546Spatrick const uint32_t num_sections = section_list.GetSize();
232061da546Spatrick for (uint32_t i = 0; i < num_sections; ++i) {
233061da546Spatrick SectionSP section_sp(section_list.GetSectionAtIndex(i));
234061da546Spatrick if (section_sp) {
235061da546Spatrick if (section_sp->IsFake()) {
236061da546Spatrick uint64_t lower = (uint64_t)-1;
237061da546Spatrick uint64_t upper = 0;
238061da546Spatrick updateSectionLoadAddress(section_sp->GetChildren(), target,
239061da546Spatrick symbolfile_addr, symbolfile_size,
240061da546Spatrick vmaddrheuristic, lower, upper);
241061da546Spatrick if (lower < min_addr)
242061da546Spatrick min_addr = lower;
243061da546Spatrick if (upper > max_addr)
244061da546Spatrick max_addr = upper;
245061da546Spatrick const lldb::addr_t slide_amount = lower - section_sp->GetFileAddress();
246061da546Spatrick section_sp->Slide(slide_amount, false);
247061da546Spatrick section_sp->GetChildren().Slide(-slide_amount, false);
248061da546Spatrick section_sp->SetByteSize(upper - lower);
249061da546Spatrick } else {
250061da546Spatrick vmaddrheuristic += 2 << section_sp->GetLog2Align();
251061da546Spatrick uint64_t lower;
252061da546Spatrick if (section_sp->GetFileAddress() > vmaddrheuristic)
253061da546Spatrick lower = section_sp->GetFileAddress();
254061da546Spatrick else {
255061da546Spatrick lower = symbolfile_addr + section_sp->GetFileOffset();
256061da546Spatrick section_sp->SetFileAddress(symbolfile_addr +
257061da546Spatrick section_sp->GetFileOffset());
258061da546Spatrick }
259061da546Spatrick target.SetSectionLoadAddress(section_sp, lower, true);
260061da546Spatrick uint64_t upper = lower + section_sp->GetByteSize();
261061da546Spatrick if (lower < min_addr)
262061da546Spatrick min_addr = lower;
263061da546Spatrick if (upper > max_addr)
264061da546Spatrick max_addr = upper;
265061da546Spatrick // This is an upper bound, but a good enough heuristic
266061da546Spatrick vmaddrheuristic += section_sp->GetByteSize();
267061da546Spatrick }
268061da546Spatrick }
269061da546Spatrick }
270061da546Spatrick }
271061da546Spatrick
ReadJITDescriptor(bool all_entries)272061da546Spatrick bool JITLoaderGDB::ReadJITDescriptor(bool all_entries) {
273061da546Spatrick if (m_process->GetTarget().GetArchitecture().GetAddressByteSize() == 8)
274061da546Spatrick return ReadJITDescriptorImpl<uint64_t>(all_entries);
275061da546Spatrick else
276061da546Spatrick return ReadJITDescriptorImpl<uint32_t>(all_entries);
277061da546Spatrick }
278061da546Spatrick
279061da546Spatrick template <typename ptr_t>
ReadJITDescriptorImpl(bool all_entries)280061da546Spatrick bool JITLoaderGDB::ReadJITDescriptorImpl(bool all_entries) {
281061da546Spatrick if (m_jit_descriptor_addr == LLDB_INVALID_ADDRESS)
282061da546Spatrick return false;
283061da546Spatrick
284*f6aab3d8Srobert Log *log = GetLog(LLDBLog::JITLoader);
285061da546Spatrick Target &target = m_process->GetTarget();
286061da546Spatrick ModuleList &module_list = target.GetImages();
287061da546Spatrick
288061da546Spatrick jit_descriptor<ptr_t> jit_desc;
289061da546Spatrick const size_t jit_desc_size = sizeof(jit_desc);
290061da546Spatrick Status error;
291be691f3bSpatrick size_t bytes_read = m_process->ReadMemory(m_jit_descriptor_addr, &jit_desc,
292061da546Spatrick jit_desc_size, error);
293061da546Spatrick if (bytes_read != jit_desc_size || !error.Success()) {
294061da546Spatrick LLDB_LOGF(log, "JITLoaderGDB::%s failed to read JIT descriptor",
295061da546Spatrick __FUNCTION__);
296061da546Spatrick return false;
297061da546Spatrick }
298061da546Spatrick
299061da546Spatrick jit_actions_t jit_action = (jit_actions_t)jit_desc.action_flag;
300061da546Spatrick addr_t jit_relevant_entry = (addr_t)jit_desc.relevant_entry;
301061da546Spatrick if (all_entries) {
302061da546Spatrick jit_action = JIT_REGISTER_FN;
303061da546Spatrick jit_relevant_entry = (addr_t)jit_desc.first_entry;
304061da546Spatrick }
305061da546Spatrick
306061da546Spatrick while (jit_relevant_entry != 0) {
307061da546Spatrick jit_code_entry<ptr_t> jit_entry;
308061da546Spatrick if (!ReadJITEntry(jit_relevant_entry, m_process, &jit_entry)) {
309061da546Spatrick LLDB_LOGF(log, "JITLoaderGDB::%s failed to read JIT entry at 0x%" PRIx64,
310061da546Spatrick __FUNCTION__, jit_relevant_entry);
311061da546Spatrick return false;
312061da546Spatrick }
313061da546Spatrick
314061da546Spatrick const addr_t &symbolfile_addr = (addr_t)jit_entry.symfile_addr;
315061da546Spatrick const size_t &symbolfile_size = (size_t)jit_entry.symfile_size;
316061da546Spatrick ModuleSP module_sp;
317061da546Spatrick
318061da546Spatrick if (jit_action == JIT_REGISTER_FN) {
319061da546Spatrick LLDB_LOGF(log,
320061da546Spatrick "JITLoaderGDB::%s registering JIT entry at 0x%" PRIx64
321061da546Spatrick " (%" PRIu64 " bytes)",
322061da546Spatrick __FUNCTION__, symbolfile_addr, (uint64_t)symbolfile_size);
323061da546Spatrick
324061da546Spatrick char jit_name[64];
325061da546Spatrick snprintf(jit_name, 64, "JIT(0x%" PRIx64 ")", symbolfile_addr);
326061da546Spatrick module_sp = m_process->ReadModuleFromMemory(
327061da546Spatrick FileSpec(jit_name), symbolfile_addr, symbolfile_size);
328061da546Spatrick
329061da546Spatrick if (module_sp && module_sp->GetObjectFile()) {
330061da546Spatrick // Object formats (like ELF) have no representation for a JIT type.
331061da546Spatrick // We will get it wrong, if we deduce it from the header.
332061da546Spatrick module_sp->GetObjectFile()->SetType(ObjectFile::eTypeJIT);
333061da546Spatrick
334061da546Spatrick // load the symbol table right away
335061da546Spatrick module_sp->GetObjectFile()->GetSymtab();
336061da546Spatrick
337061da546Spatrick m_jit_objects.insert(std::make_pair(symbolfile_addr, module_sp));
338061da546Spatrick if (auto image_object_file =
339061da546Spatrick llvm::dyn_cast<ObjectFileMachO>(module_sp->GetObjectFile())) {
340061da546Spatrick const SectionList *section_list = image_object_file->GetSectionList();
341061da546Spatrick if (section_list) {
342061da546Spatrick uint64_t vmaddrheuristic = 0;
343061da546Spatrick uint64_t lower = (uint64_t)-1;
344061da546Spatrick uint64_t upper = 0;
345061da546Spatrick updateSectionLoadAddress(*section_list, target, symbolfile_addr,
346061da546Spatrick symbolfile_size, vmaddrheuristic, lower,
347061da546Spatrick upper);
348061da546Spatrick }
349061da546Spatrick } else {
350061da546Spatrick bool changed = false;
351061da546Spatrick module_sp->SetLoadAddress(target, 0, true, changed);
352061da546Spatrick }
353061da546Spatrick
354061da546Spatrick module_list.AppendIfNeeded(module_sp);
355061da546Spatrick
356061da546Spatrick ModuleList module_list;
357061da546Spatrick module_list.Append(module_sp);
358061da546Spatrick target.ModulesDidLoad(module_list);
359061da546Spatrick } else {
360061da546Spatrick LLDB_LOGF(log,
361061da546Spatrick "JITLoaderGDB::%s failed to load module for "
362061da546Spatrick "JIT entry at 0x%" PRIx64,
363061da546Spatrick __FUNCTION__, symbolfile_addr);
364061da546Spatrick }
365061da546Spatrick } else if (jit_action == JIT_UNREGISTER_FN) {
366061da546Spatrick LLDB_LOGF(log, "JITLoaderGDB::%s unregistering JIT entry at 0x%" PRIx64,
367061da546Spatrick __FUNCTION__, symbolfile_addr);
368061da546Spatrick
369061da546Spatrick JITObjectMap::iterator it = m_jit_objects.find(symbolfile_addr);
370061da546Spatrick if (it != m_jit_objects.end()) {
371061da546Spatrick module_sp = it->second;
372061da546Spatrick ObjectFile *image_object_file = module_sp->GetObjectFile();
373061da546Spatrick if (image_object_file) {
374061da546Spatrick const SectionList *section_list = image_object_file->GetSectionList();
375061da546Spatrick if (section_list) {
376061da546Spatrick const uint32_t num_sections = section_list->GetSize();
377061da546Spatrick for (uint32_t i = 0; i < num_sections; ++i) {
378061da546Spatrick SectionSP section_sp(section_list->GetSectionAtIndex(i));
379061da546Spatrick if (section_sp) {
380061da546Spatrick target.GetSectionLoadList().SetSectionUnloaded(section_sp);
381061da546Spatrick }
382061da546Spatrick }
383061da546Spatrick }
384061da546Spatrick }
385061da546Spatrick module_list.Remove(module_sp);
386061da546Spatrick m_jit_objects.erase(it);
387061da546Spatrick }
388061da546Spatrick } else if (jit_action == JIT_NOACTION) {
389061da546Spatrick // Nothing to do
390061da546Spatrick } else {
391061da546Spatrick assert(false && "Unknown jit action");
392061da546Spatrick }
393061da546Spatrick
394061da546Spatrick if (all_entries)
395061da546Spatrick jit_relevant_entry = (addr_t)jit_entry.next_entry;
396061da546Spatrick else
397061da546Spatrick jit_relevant_entry = 0;
398061da546Spatrick }
399061da546Spatrick
400061da546Spatrick return false; // Continue Running.
401061da546Spatrick }
402061da546Spatrick
403061da546Spatrick // PluginInterface protocol
CreateInstance(Process * process,bool force)404061da546Spatrick JITLoaderSP JITLoaderGDB::CreateInstance(Process *process, bool force) {
405061da546Spatrick JITLoaderSP jit_loader_sp;
406061da546Spatrick bool enable;
407*f6aab3d8Srobert switch (GetGlobalPluginProperties().GetEnable()) {
408061da546Spatrick case EnableJITLoaderGDB::eEnableJITLoaderGDBOn:
409061da546Spatrick enable = true;
410061da546Spatrick break;
411061da546Spatrick case EnableJITLoaderGDB::eEnableJITLoaderGDBOff:
412061da546Spatrick enable = false;
413061da546Spatrick break;
414061da546Spatrick case EnableJITLoaderGDB::eEnableJITLoaderGDBDefault:
415061da546Spatrick ArchSpec arch(process->GetTarget().GetArchitecture());
416061da546Spatrick enable = arch.GetTriple().getVendor() != llvm::Triple::Apple;
417061da546Spatrick break;
418061da546Spatrick }
419061da546Spatrick if (enable)
420061da546Spatrick jit_loader_sp = std::make_shared<JITLoaderGDB>(process);
421061da546Spatrick return jit_loader_sp;
422061da546Spatrick }
423061da546Spatrick
GetPluginDescriptionStatic()424*f6aab3d8Srobert llvm::StringRef JITLoaderGDB::GetPluginDescriptionStatic() {
425061da546Spatrick return "JIT loader plug-in that watches for JIT events using the GDB "
426061da546Spatrick "interface.";
427061da546Spatrick }
428061da546Spatrick
Initialize()429061da546Spatrick void JITLoaderGDB::Initialize() {
430061da546Spatrick PluginManager::RegisterPlugin(GetPluginNameStatic(),
431061da546Spatrick GetPluginDescriptionStatic(), CreateInstance,
432061da546Spatrick DebuggerInitialize);
433061da546Spatrick }
434061da546Spatrick
Terminate()435061da546Spatrick void JITLoaderGDB::Terminate() {
436061da546Spatrick PluginManager::UnregisterPlugin(CreateInstance);
437061da546Spatrick }
438061da546Spatrick
DidSetJITBreakpoint() const439061da546Spatrick bool JITLoaderGDB::DidSetJITBreakpoint() const {
440061da546Spatrick return LLDB_BREAK_ID_IS_VALID(m_jit_break_id);
441061da546Spatrick }
442061da546Spatrick
GetSymbolAddress(ModuleList & module_list,ConstString name,SymbolType symbol_type) const443061da546Spatrick addr_t JITLoaderGDB::GetSymbolAddress(ModuleList &module_list,
444061da546Spatrick ConstString name,
445061da546Spatrick SymbolType symbol_type) const {
446061da546Spatrick SymbolContextList target_symbols;
447061da546Spatrick Target &target = m_process->GetTarget();
448061da546Spatrick
449061da546Spatrick module_list.FindSymbolsWithNameAndType(name, symbol_type, target_symbols);
450061da546Spatrick if (target_symbols.IsEmpty())
451061da546Spatrick return LLDB_INVALID_ADDRESS;
452061da546Spatrick
453061da546Spatrick SymbolContext sym_ctx;
454061da546Spatrick target_symbols.GetContextAtIndex(0, sym_ctx);
455061da546Spatrick
456061da546Spatrick const Address jit_descriptor_addr = sym_ctx.symbol->GetAddress();
457061da546Spatrick if (!jit_descriptor_addr.IsValid())
458061da546Spatrick return LLDB_INVALID_ADDRESS;
459061da546Spatrick
460061da546Spatrick const addr_t jit_addr = jit_descriptor_addr.GetLoadAddress(&target);
461061da546Spatrick return jit_addr;
462061da546Spatrick }
463