blob: e6a6d0762ea99fc9b3333067663d24ea08654771 [file] [log] [blame]
Andrew MacPherson17220c12014-03-05 10:12:43 +00001//===-- 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
26using namespace lldb;
27using namespace lldb_private;
28
29//------------------------------------------------------------------
30// Debug Interface Structures
31//------------------------------------------------------------------
32typedef enum
33{
34 JIT_NOACTION = 0,
35 JIT_REGISTER_FN,
36 JIT_UNREGISTER_FN
37} jit_actions_t;
38
39struct 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
47struct 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
55JITLoaderGDB::JITLoaderGDB (lldb_private::Process *process) :
56 JITLoader(process),
57 m_jit_objects(),
Andrew MacPhersoneb4d0602014-03-13 09:37:02 +000058 m_jit_break_id(LLDB_INVALID_BREAK_ID),
59 m_jit_descriptor_addr(LLDB_INVALID_ADDRESS)
Andrew MacPherson17220c12014-03-05 10:12:43 +000060{
Andrew MacPherson17220c12014-03-05 10:12:43 +000061}
62
63JITLoaderGDB::~JITLoaderGDB ()
64{
65 if (LLDB_BREAK_ID_IS_VALID(m_jit_break_id))
66 m_process->GetTarget().RemoveBreakpointByID (m_jit_break_id);
Andrew MacPherson17220c12014-03-05 10:12:43 +000067}
68
69void JITLoaderGDB::DidAttach()
70{
Andrew MacPhersoneb4d0602014-03-13 09:37:02 +000071 Target &target = m_process->GetTarget();
72 ModuleList &module_list = target.GetImages();
73 SetJITBreakpoint(module_list);
Andrew MacPherson17220c12014-03-05 10:12:43 +000074}
75
76void JITLoaderGDB::DidLaunch()
77{
Andrew MacPhersoneb4d0602014-03-13 09:37:02 +000078 Target &target = m_process->GetTarget();
79 ModuleList &module_list = target.GetImages();
80 SetJITBreakpoint(module_list);
81}
82
83void
84JITLoaderGDB::ModulesDidLoad(ModuleList &module_list)
85{
86 if (!DidSetJITBreakpoint() && m_process->IsAlive())
87 SetJITBreakpoint(module_list);
Andrew MacPherson17220c12014-03-05 10:12:43 +000088}
89
90//------------------------------------------------------------------
91// Setup the JIT Breakpoint
92//------------------------------------------------------------------
93void
Andrew MacPhersoneb4d0602014-03-13 09:37:02 +000094JITLoaderGDB::SetJITBreakpoint(lldb_private::ModuleList &module_list)
Andrew MacPherson17220c12014-03-05 10:12:43 +000095{
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
Andrew MacPhersoneb4d0602014-03-13 09:37:02 +0000105 addr_t jit_addr = GetSymbolAddress(
106 module_list, ConstString("__jit_debug_register_code"), eSymbolTypeAny);
Andrew MacPherson17220c12014-03-05 10:12:43 +0000107 if (jit_addr == LLDB_INVALID_ADDRESS)
108 return;
109
Andrew MacPhersoneb4d0602014-03-13 09:37:02 +0000110 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
Andrew MacPherson17220c12014-03-05 10:12:43 +0000121 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
134bool
135JITLoaderGDB::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
147bool
148JITLoaderGDB::ReadJITDescriptor(bool all_entries)
149{
Andrew MacPhersoneb4d0602014-03-13 09:37:02 +0000150 if (m_jit_descriptor_addr == LLDB_INVALID_ADDRESS)
151 return false;
152
Andrew MacPherson17220c12014-03-05 10:12:43 +0000153 Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_JIT_LOADER));
154 Target &target = m_process->GetTarget();
Andrew MacPhersoneb4d0602014-03-13 09:37:02 +0000155 ModuleList &module_list = target.GetImages();
Andrew MacPherson17220c12014-03-05 10:12:43 +0000156
157 jit_descriptor jit_desc;
158 const size_t jit_desc_size = sizeof(jit_desc);
159 Error error;
Andrew MacPhersoneb4d0602014-03-13 09:37:02 +0000160 size_t bytes_read = m_process->DoReadMemory(
161 m_jit_descriptor_addr, &jit_desc, jit_desc_size, error);
Andrew MacPherson17220c12014-03-05 10:12:43 +0000162 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)",
Jason Molendab509a412014-03-05 23:48:15 +0000202 __FUNCTION__, symbolfile_addr, (uint64_t) symbolfile_size);
Andrew MacPherson17220c12014-03-05 10:12:43 +0000203
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
Andrew MacPhersoneb4d0602014-03-13 09:37:02 +0000220 module_list.AppendIfNeeded(module_sp);
Andrew MacPherson17220c12014-03-05 10:12:43 +0000221
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 }
Andrew MacPhersoneb4d0602014-03-13 09:37:02 +0000262 module_list.Remove(module_sp);
Andrew MacPherson17220c12014-03-05 10:12:43 +0000263 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//------------------------------------------------------------------
287lldb_private::ConstString
288JITLoaderGDB::GetPluginNameStatic()
289{
290 static ConstString g_name("gdb");
291 return g_name;
292}
293
294JITLoaderSP
295JITLoaderGDB::CreateInstance(Process *process, bool force)
296{
297 JITLoaderSP jit_loader_sp(new JITLoaderGDB(process));
298 return jit_loader_sp;
299}
300
301const char *
302JITLoaderGDB::GetPluginDescriptionStatic()
303{
304 return "JIT loader plug-in that watches for JIT events using the GDB interface.";
305}
306
307lldb_private::ConstString
308JITLoaderGDB::GetPluginName()
309{
310 return GetPluginNameStatic();
311}
312
313uint32_t
314JITLoaderGDB::GetPluginVersion()
315{
316 return 1;
317}
318
319void
320JITLoaderGDB::Initialize()
321{
322 PluginManager::RegisterPlugin (GetPluginNameStatic(),
323 GetPluginDescriptionStatic(),
324 CreateInstance);
325}
326
327void
328JITLoaderGDB::Terminate()
329{
330 PluginManager::UnregisterPlugin (CreateInstance);
331}
332
333bool
334JITLoaderGDB::DidSetJITBreakpoint() const
335{
336 return LLDB_BREAK_ID_IS_VALID(m_jit_break_id);
337}
338
Andrew MacPherson17220c12014-03-05 10:12:43 +0000339addr_t
Andrew MacPhersoneb4d0602014-03-13 09:37:02 +0000340JITLoaderGDB::GetSymbolAddress(ModuleList &module_list, const ConstString &name,
341 SymbolType symbol_type) const
Andrew MacPherson17220c12014-03-05 10:12:43 +0000342{
343 SymbolContextList target_symbols;
344 Target &target = m_process->GetTarget();
Andrew MacPherson17220c12014-03-05 10:12:43 +0000345
Andrew MacPhersoneb4d0602014-03-13 09:37:02 +0000346 if (!module_list.FindSymbolsWithNameAndType(name, symbol_type,
347 target_symbols))
Andrew MacPherson17220c12014-03-05 10:12:43 +0000348 return LLDB_INVALID_ADDRESS;
349
350 SymbolContext sym_ctx;
351 target_symbols.GetContextAtIndex(0, sym_ctx);
352
353 const Address *jit_descriptor_addr = &sym_ctx.symbol->GetAddress();
354 if (!jit_descriptor_addr || !jit_descriptor_addr->IsValid())
355 return LLDB_INVALID_ADDRESS;
356
357 const addr_t jit_addr = jit_descriptor_addr->GetLoadAddress(&target);
358 return jit_addr;
359}