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