JITLoaderGDB.cpp revision 360784
1//===-- JITLoaderGDB.cpp ----------------------------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "JITLoaderGDB.h"
10#ifdef LLDB_ENABLE_ALL
11#include "Plugins/ObjectFile/Mach-O/ObjectFileMachO.h"
12#endif
13#include "lldb/Breakpoint/Breakpoint.h"
14#include "lldb/Core/Module.h"
15#include "lldb/Core/ModuleSpec.h"
16#include "lldb/Core/PluginManager.h"
17#include "lldb/Core/Section.h"
18#include "lldb/Interpreter/OptionValueProperties.h"
19#include "lldb/Symbol/ObjectFile.h"
20#include "lldb/Symbol/Symbol.h"
21#include "lldb/Symbol/SymbolContext.h"
22#include "lldb/Symbol/SymbolVendor.h"
23#include "lldb/Target/Process.h"
24#include "lldb/Target/SectionLoadList.h"
25#include "lldb/Target/Target.h"
26#include "lldb/Utility/DataBufferHeap.h"
27#include "lldb/Utility/LLDBAssert.h"
28#include "lldb/Utility/Log.h"
29#include "lldb/Utility/StreamString.h"
30#include "llvm/Support/MathExtras.h"
31
32#include <memory>
33
34using namespace lldb;
35using namespace lldb_private;
36
37// Debug Interface Structures
38enum jit_actions_t { JIT_NOACTION = 0, JIT_REGISTER_FN, JIT_UNREGISTER_FN };
39
40template <typename ptr_t> struct jit_code_entry {
41  ptr_t next_entry;   // pointer
42  ptr_t prev_entry;   // pointer
43  ptr_t symfile_addr; // pointer
44  uint64_t symfile_size;
45};
46
47template <typename ptr_t> struct jit_descriptor {
48  uint32_t version;
49  uint32_t action_flag; // Values are jit_action_t
50  ptr_t relevant_entry; // pointer
51  ptr_t first_entry;    // pointer
52};
53
54namespace {
55
56enum EnableJITLoaderGDB {
57  eEnableJITLoaderGDBDefault,
58  eEnableJITLoaderGDBOn,
59  eEnableJITLoaderGDBOff,
60};
61
62static constexpr OptionEnumValueElement g_enable_jit_loader_gdb_enumerators[] =
63    {
64        {
65            eEnableJITLoaderGDBDefault,
66            "default",
67            "Enable JIT compilation interface for all platforms except macOS",
68        },
69        {
70            eEnableJITLoaderGDBOn,
71            "on",
72            "Enable JIT compilation interface",
73        },
74        {
75            eEnableJITLoaderGDBOff,
76            "off",
77            "Disable JIT compilation interface",
78        },
79};
80
81#define LLDB_PROPERTIES_jitloadergdb
82#include "JITLoaderGDBProperties.inc"
83
84enum {
85#define LLDB_PROPERTIES_jitloadergdb
86#include "JITLoaderGDBPropertiesEnum.inc"
87  ePropertyEnableJITBreakpoint
88};
89
90class PluginProperties : public Properties {
91public:
92  static ConstString GetSettingName() {
93    return JITLoaderGDB::GetPluginNameStatic();
94  }
95
96  PluginProperties() {
97    m_collection_sp = std::make_shared<OptionValueProperties>(GetSettingName());
98    m_collection_sp->Initialize(g_jitloadergdb_properties);
99  }
100
101  EnableJITLoaderGDB GetEnable() const {
102    return (EnableJITLoaderGDB)m_collection_sp->GetPropertyAtIndexAsEnumeration(
103        nullptr, ePropertyEnable,
104        g_jitloadergdb_properties[ePropertyEnable].default_uint_value);
105  }
106};
107
108typedef std::shared_ptr<PluginProperties> JITLoaderGDBPropertiesSP;
109
110static const JITLoaderGDBPropertiesSP &GetGlobalPluginProperties() {
111  static const auto g_settings_sp(std::make_shared<PluginProperties>());
112  return g_settings_sp;
113}
114
115template <typename ptr_t>
116bool ReadJITEntry(const addr_t from_addr, Process *process,
117                  jit_code_entry<ptr_t> *entry) {
118  lldbassert(from_addr % sizeof(ptr_t) == 0);
119
120  ArchSpec::Core core = process->GetTarget().GetArchitecture().GetCore();
121  bool i386_target = ArchSpec::kCore_x86_32_first <= core &&
122                     core <= ArchSpec::kCore_x86_32_last;
123  uint8_t uint64_align_bytes = i386_target ? 4 : 8;
124  const size_t data_byte_size =
125      llvm::alignTo(sizeof(ptr_t) * 3, uint64_align_bytes) + sizeof(uint64_t);
126
127  Status error;
128  DataBufferHeap data(data_byte_size, 0);
129  size_t bytes_read = process->ReadMemory(from_addr, data.GetBytes(),
130                                          data.GetByteSize(), error);
131  if (bytes_read != data_byte_size || !error.Success())
132    return false;
133
134  DataExtractor extractor(data.GetBytes(), data.GetByteSize(),
135                          process->GetByteOrder(), sizeof(ptr_t));
136  lldb::offset_t offset = 0;
137  entry->next_entry = extractor.GetPointer(&offset);
138  entry->prev_entry = extractor.GetPointer(&offset);
139  entry->symfile_addr = extractor.GetPointer(&offset);
140  offset = llvm::alignTo(offset, uint64_align_bytes);
141  entry->symfile_size = extractor.GetU64(&offset);
142
143  return true;
144}
145
146} // anonymous namespace end
147
148JITLoaderGDB::JITLoaderGDB(lldb_private::Process *process)
149    : JITLoader(process), m_jit_objects(),
150      m_jit_break_id(LLDB_INVALID_BREAK_ID),
151      m_jit_descriptor_addr(LLDB_INVALID_ADDRESS) {}
152
153JITLoaderGDB::~JITLoaderGDB() {
154  if (LLDB_BREAK_ID_IS_VALID(m_jit_break_id))
155    m_process->GetTarget().RemoveBreakpointByID(m_jit_break_id);
156}
157
158void JITLoaderGDB::DebuggerInitialize(Debugger &debugger) {
159  if (!PluginManager::GetSettingForJITLoaderPlugin(
160          debugger, PluginProperties::GetSettingName())) {
161    const bool is_global_setting = true;
162    PluginManager::CreateSettingForJITLoaderPlugin(
163        debugger, GetGlobalPluginProperties()->GetValueProperties(),
164        ConstString("Properties for the JIT LoaderGDB plug-in."),
165        is_global_setting);
166  }
167}
168
169void JITLoaderGDB::DidAttach() {
170  Target &target = m_process->GetTarget();
171  ModuleList &module_list = target.GetImages();
172  SetJITBreakpoint(module_list);
173}
174
175void JITLoaderGDB::DidLaunch() {
176  Target &target = m_process->GetTarget();
177  ModuleList &module_list = target.GetImages();
178  SetJITBreakpoint(module_list);
179}
180
181void JITLoaderGDB::ModulesDidLoad(ModuleList &module_list) {
182  if (!DidSetJITBreakpoint() && m_process->IsAlive())
183    SetJITBreakpoint(module_list);
184}
185
186// Setup the JIT Breakpoint
187void JITLoaderGDB::SetJITBreakpoint(lldb_private::ModuleList &module_list) {
188  if (DidSetJITBreakpoint())
189    return;
190
191  Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_JIT_LOADER));
192  LLDB_LOGF(log, "JITLoaderGDB::%s looking for JIT register hook",
193            __FUNCTION__);
194
195  addr_t jit_addr = GetSymbolAddress(
196      module_list, ConstString("__jit_debug_register_code"), eSymbolTypeAny);
197  if (jit_addr == LLDB_INVALID_ADDRESS)
198    return;
199
200  m_jit_descriptor_addr = GetSymbolAddress(
201      module_list, ConstString("__jit_debug_descriptor"), eSymbolTypeData);
202  if (m_jit_descriptor_addr == LLDB_INVALID_ADDRESS) {
203    LLDB_LOGF(log, "JITLoaderGDB::%s failed to find JIT descriptor address",
204              __FUNCTION__);
205    return;
206  }
207
208  LLDB_LOGF(log, "JITLoaderGDB::%s setting JIT breakpoint", __FUNCTION__);
209
210  Breakpoint *bp =
211      m_process->GetTarget().CreateBreakpoint(jit_addr, true, false).get();
212  bp->SetCallback(JITDebugBreakpointHit, this, true);
213  bp->SetBreakpointKind("jit-debug-register");
214  m_jit_break_id = bp->GetID();
215
216  ReadJITDescriptor(true);
217}
218
219bool JITLoaderGDB::JITDebugBreakpointHit(void *baton,
220                                         StoppointCallbackContext *context,
221                                         user_id_t break_id,
222                                         user_id_t break_loc_id) {
223  Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_JIT_LOADER));
224  LLDB_LOGF(log, "JITLoaderGDB::%s hit JIT breakpoint", __FUNCTION__);
225  JITLoaderGDB *instance = static_cast<JITLoaderGDB *>(baton);
226  return instance->ReadJITDescriptor(false);
227}
228
229static void updateSectionLoadAddress(const SectionList &section_list,
230                                     Target &target, uint64_t symbolfile_addr,
231                                     uint64_t symbolfile_size,
232                                     uint64_t &vmaddrheuristic,
233                                     uint64_t &min_addr, uint64_t &max_addr) {
234  const uint32_t num_sections = section_list.GetSize();
235  for (uint32_t i = 0; i < num_sections; ++i) {
236    SectionSP section_sp(section_list.GetSectionAtIndex(i));
237    if (section_sp) {
238      if (section_sp->IsFake()) {
239        uint64_t lower = (uint64_t)-1;
240        uint64_t upper = 0;
241        updateSectionLoadAddress(section_sp->GetChildren(), target,
242                                 symbolfile_addr, symbolfile_size,
243                                 vmaddrheuristic, lower, upper);
244        if (lower < min_addr)
245          min_addr = lower;
246        if (upper > max_addr)
247          max_addr = upper;
248        const lldb::addr_t slide_amount = lower - section_sp->GetFileAddress();
249        section_sp->Slide(slide_amount, false);
250        section_sp->GetChildren().Slide(-slide_amount, false);
251        section_sp->SetByteSize(upper - lower);
252      } else {
253        vmaddrheuristic += 2 << section_sp->GetLog2Align();
254        uint64_t lower;
255        if (section_sp->GetFileAddress() > vmaddrheuristic)
256          lower = section_sp->GetFileAddress();
257        else {
258          lower = symbolfile_addr + section_sp->GetFileOffset();
259          section_sp->SetFileAddress(symbolfile_addr +
260                                     section_sp->GetFileOffset());
261        }
262        target.SetSectionLoadAddress(section_sp, lower, true);
263        uint64_t upper = lower + section_sp->GetByteSize();
264        if (lower < min_addr)
265          min_addr = lower;
266        if (upper > max_addr)
267          max_addr = upper;
268        // This is an upper bound, but a good enough heuristic
269        vmaddrheuristic += section_sp->GetByteSize();
270      }
271    }
272  }
273}
274
275bool JITLoaderGDB::ReadJITDescriptor(bool all_entries) {
276  if (m_process->GetTarget().GetArchitecture().GetAddressByteSize() == 8)
277    return ReadJITDescriptorImpl<uint64_t>(all_entries);
278  else
279    return ReadJITDescriptorImpl<uint32_t>(all_entries);
280}
281
282template <typename ptr_t>
283bool JITLoaderGDB::ReadJITDescriptorImpl(bool all_entries) {
284  if (m_jit_descriptor_addr == LLDB_INVALID_ADDRESS)
285    return false;
286
287  Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_JIT_LOADER));
288  Target &target = m_process->GetTarget();
289  ModuleList &module_list = target.GetImages();
290
291  jit_descriptor<ptr_t> jit_desc;
292  const size_t jit_desc_size = sizeof(jit_desc);
293  Status error;
294  size_t bytes_read = m_process->DoReadMemory(m_jit_descriptor_addr, &jit_desc,
295                                              jit_desc_size, error);
296  if (bytes_read != jit_desc_size || !error.Success()) {
297    LLDB_LOGF(log, "JITLoaderGDB::%s failed to read JIT descriptor",
298              __FUNCTION__);
299    return false;
300  }
301
302  jit_actions_t jit_action = (jit_actions_t)jit_desc.action_flag;
303  addr_t jit_relevant_entry = (addr_t)jit_desc.relevant_entry;
304  if (all_entries) {
305    jit_action = JIT_REGISTER_FN;
306    jit_relevant_entry = (addr_t)jit_desc.first_entry;
307  }
308
309  while (jit_relevant_entry != 0) {
310    jit_code_entry<ptr_t> jit_entry;
311    if (!ReadJITEntry(jit_relevant_entry, m_process, &jit_entry)) {
312      LLDB_LOGF(log, "JITLoaderGDB::%s failed to read JIT entry at 0x%" PRIx64,
313                __FUNCTION__, jit_relevant_entry);
314      return false;
315    }
316
317    const addr_t &symbolfile_addr = (addr_t)jit_entry.symfile_addr;
318    const size_t &symbolfile_size = (size_t)jit_entry.symfile_size;
319    ModuleSP module_sp;
320
321    if (jit_action == JIT_REGISTER_FN) {
322      LLDB_LOGF(log,
323                "JITLoaderGDB::%s registering JIT entry at 0x%" PRIx64
324                " (%" PRIu64 " bytes)",
325                __FUNCTION__, symbolfile_addr, (uint64_t)symbolfile_size);
326
327      char jit_name[64];
328      snprintf(jit_name, 64, "JIT(0x%" PRIx64 ")", symbolfile_addr);
329      module_sp = m_process->ReadModuleFromMemory(
330          FileSpec(jit_name), symbolfile_addr, symbolfile_size);
331
332      if (module_sp && module_sp->GetObjectFile()) {
333        // Object formats (like ELF) have no representation for a JIT type.
334        // We will get it wrong, if we deduce it from the header.
335        module_sp->GetObjectFile()->SetType(ObjectFile::eTypeJIT);
336
337        // load the symbol table right away
338        module_sp->GetObjectFile()->GetSymtab();
339
340        m_jit_objects.insert(std::make_pair(symbolfile_addr, module_sp));
341#ifdef LLDB_ENABLE_ALL
342        if (auto image_object_file =
343                llvm::dyn_cast<ObjectFileMachO>(module_sp->GetObjectFile())) {
344          const SectionList *section_list = image_object_file->GetSectionList();
345          if (section_list) {
346            uint64_t vmaddrheuristic = 0;
347            uint64_t lower = (uint64_t)-1;
348            uint64_t upper = 0;
349            updateSectionLoadAddress(*section_list, target, symbolfile_addr,
350                                     symbolfile_size, vmaddrheuristic, lower,
351                                     upper);
352          }
353        } else
354#endif
355        {
356          bool changed = false;
357          module_sp->SetLoadAddress(target, 0, true, changed);
358        }
359
360        module_list.AppendIfNeeded(module_sp);
361
362        ModuleList module_list;
363        module_list.Append(module_sp);
364        target.ModulesDidLoad(module_list);
365      } else {
366        LLDB_LOGF(log,
367                  "JITLoaderGDB::%s failed to load module for "
368                  "JIT entry at 0x%" PRIx64,
369                  __FUNCTION__, symbolfile_addr);
370      }
371    } else if (jit_action == JIT_UNREGISTER_FN) {
372      LLDB_LOGF(log, "JITLoaderGDB::%s unregistering JIT entry at 0x%" PRIx64,
373                __FUNCTION__, symbolfile_addr);
374
375      JITObjectMap::iterator it = m_jit_objects.find(symbolfile_addr);
376      if (it != m_jit_objects.end()) {
377        module_sp = it->second;
378        ObjectFile *image_object_file = module_sp->GetObjectFile();
379        if (image_object_file) {
380          const SectionList *section_list = image_object_file->GetSectionList();
381          if (section_list) {
382            const uint32_t num_sections = section_list->GetSize();
383            for (uint32_t i = 0; i < num_sections; ++i) {
384              SectionSP section_sp(section_list->GetSectionAtIndex(i));
385              if (section_sp) {
386                target.GetSectionLoadList().SetSectionUnloaded(section_sp);
387              }
388            }
389          }
390        }
391        module_list.Remove(module_sp);
392        m_jit_objects.erase(it);
393      }
394    } else if (jit_action == JIT_NOACTION) {
395      // Nothing to do
396    } else {
397      assert(false && "Unknown jit action");
398    }
399
400    if (all_entries)
401      jit_relevant_entry = (addr_t)jit_entry.next_entry;
402    else
403      jit_relevant_entry = 0;
404  }
405
406  return false; // Continue Running.
407}
408
409// PluginInterface protocol
410lldb_private::ConstString JITLoaderGDB::GetPluginNameStatic() {
411  static ConstString g_name("gdb");
412  return g_name;
413}
414
415JITLoaderSP JITLoaderGDB::CreateInstance(Process *process, bool force) {
416  JITLoaderSP jit_loader_sp;
417  bool enable;
418  switch (GetGlobalPluginProperties()->GetEnable()) {
419    case EnableJITLoaderGDB::eEnableJITLoaderGDBOn:
420      enable = true;
421      break;
422    case EnableJITLoaderGDB::eEnableJITLoaderGDBOff:
423      enable = false;
424      break;
425    case EnableJITLoaderGDB::eEnableJITLoaderGDBDefault:
426      ArchSpec arch(process->GetTarget().GetArchitecture());
427      enable = arch.GetTriple().getVendor() != llvm::Triple::Apple;
428      break;
429  }
430  if (enable)
431    jit_loader_sp = std::make_shared<JITLoaderGDB>(process);
432  return jit_loader_sp;
433}
434
435const char *JITLoaderGDB::GetPluginDescriptionStatic() {
436  return "JIT loader plug-in that watches for JIT events using the GDB "
437         "interface.";
438}
439
440lldb_private::ConstString JITLoaderGDB::GetPluginName() {
441  return GetPluginNameStatic();
442}
443
444uint32_t JITLoaderGDB::GetPluginVersion() { return 1; }
445
446void JITLoaderGDB::Initialize() {
447  PluginManager::RegisterPlugin(GetPluginNameStatic(),
448                                GetPluginDescriptionStatic(), CreateInstance,
449                                DebuggerInitialize);
450}
451
452void JITLoaderGDB::Terminate() {
453  PluginManager::UnregisterPlugin(CreateInstance);
454}
455
456bool JITLoaderGDB::DidSetJITBreakpoint() const {
457  return LLDB_BREAK_ID_IS_VALID(m_jit_break_id);
458}
459
460addr_t JITLoaderGDB::GetSymbolAddress(ModuleList &module_list,
461                                      ConstString name,
462                                      SymbolType symbol_type) const {
463  SymbolContextList target_symbols;
464  Target &target = m_process->GetTarget();
465
466  module_list.FindSymbolsWithNameAndType(name, symbol_type, target_symbols);
467  if (target_symbols.IsEmpty())
468    return LLDB_INVALID_ADDRESS;
469
470  SymbolContext sym_ctx;
471  target_symbols.GetContextAtIndex(0, sym_ctx);
472
473  const Address jit_descriptor_addr = sym_ctx.symbol->GetAddress();
474  if (!jit_descriptor_addr.IsValid())
475    return LLDB_INVALID_ADDRESS;
476
477  const addr_t jit_addr = jit_descriptor_addr.GetLoadAddress(&target);
478  return jit_addr;
479}
480