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