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