blob: 905984d334105cbfb60557cb039c16246943ee0d [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
Greg Clayton48672af2014-06-24 22:22:43 +0000105 addr_t jit_addr = GetSymbolAddress(module_list,
106 ConstString("__jit_debug_register_code"),
107 eSymbolTypeAny);
Andrew MacPherson17220c12014-03-05 10:12:43 +0000108 if (jit_addr == LLDB_INVALID_ADDRESS)
109 return;
110
Greg Clayton48672af2014-06-24 22:22:43 +0000111 m_jit_descriptor_addr = GetSymbolAddress(module_list,
112 ConstString("__jit_debug_descriptor"),
113 eSymbolTypeData);
Andrew MacPhersoneb4d0602014-03-13 09:37:02 +0000114 if (m_jit_descriptor_addr == LLDB_INVALID_ADDRESS)
115 {
116 if (log)
117 log->Printf(
118 "JITLoaderGDB::%s failed to find JIT descriptor address",
119 __FUNCTION__);
120 return;
121 }
122
Andrew MacPherson17220c12014-03-05 10:12:43 +0000123 if (log)
124 log->Printf("JITLoaderGDB::%s setting JIT breakpoint",
125 __FUNCTION__);
126
127 Breakpoint *bp =
128 m_process->GetTarget().CreateBreakpoint(jit_addr, true, false).get();
129 bp->SetCallback(JITDebugBreakpointHit, this, true);
130 bp->SetBreakpointKind("jit-debug-register");
131 m_jit_break_id = bp->GetID();
132
133 ReadJITDescriptor(true);
134}
135
136bool
137JITLoaderGDB::JITDebugBreakpointHit(void *baton,
138 StoppointCallbackContext *context,
139 user_id_t break_id, user_id_t break_loc_id)
140{
141 Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_JIT_LOADER));
142 if (log)
143 log->Printf("JITLoaderGDB::%s hit JIT breakpoint",
144 __FUNCTION__);
145 JITLoaderGDB *instance = static_cast<JITLoaderGDB *>(baton);
146 return instance->ReadJITDescriptor(false);
147}
148
Greg Clayton48672af2014-06-24 22:22:43 +0000149static void updateSectionLoadAddress(const SectionList &section_list,
150 Target &target,
151 uint64_t symbolfile_addr,
152 uint64_t symbolfile_size,
153 uint64_t &vmaddrheuristic,
154 uint64_t &min_addr,
155 uint64_t &max_addr)
156{
157 const uint32_t num_sections = section_list.GetSize();
158 for (uint32_t i = 0; i<num_sections; ++i)
159 {
160 SectionSP section_sp(section_list.GetSectionAtIndex(i));
161 if (section_sp)
162 {
163 if(section_sp->IsFake()) {
164 uint64_t lower = (uint64_t)-1;
165 uint64_t upper = 0;
166 updateSectionLoadAddress(section_sp->GetChildren(), target, symbolfile_addr, symbolfile_size, vmaddrheuristic,
167 lower, upper);
168 if (lower < min_addr)
169 min_addr = lower;
170 if (upper > max_addr)
171 max_addr = upper;
172 const lldb::addr_t slide_amount = lower - section_sp->GetFileAddress();
173 section_sp->Slide(slide_amount, false);
174 section_sp->GetChildren().Slide(-slide_amount, false);
175 section_sp->SetByteSize (upper - lower);
176 } else {
177 vmaddrheuristic += 2<<section_sp->GetLog2Align();
178 uint64_t lower;
179 if (section_sp->GetFileAddress() > vmaddrheuristic)
180 lower = section_sp->GetFileAddress();
181 else {
182 lower = symbolfile_addr+section_sp->GetFileOffset();
183 section_sp->SetFileAddress(symbolfile_addr+section_sp->GetFileOffset());
184 }
185 target.SetSectionLoadAddress(section_sp, lower, true);
186 uint64_t upper = lower + section_sp->GetByteSize();
187 if (lower < min_addr)
188 min_addr = lower;
189 if (upper > max_addr)
190 max_addr = upper;
191 // This is an upper bound, but a good enough heuristic
192 vmaddrheuristic += section_sp->GetByteSize();
193 }
194 }
195 }
196}
197
Andrew MacPherson17220c12014-03-05 10:12:43 +0000198bool
199JITLoaderGDB::ReadJITDescriptor(bool all_entries)
200{
Andrew MacPhersoneb4d0602014-03-13 09:37:02 +0000201 if (m_jit_descriptor_addr == LLDB_INVALID_ADDRESS)
202 return false;
203
Andrew MacPherson17220c12014-03-05 10:12:43 +0000204 Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_JIT_LOADER));
205 Target &target = m_process->GetTarget();
Andrew MacPhersoneb4d0602014-03-13 09:37:02 +0000206 ModuleList &module_list = target.GetImages();
Andrew MacPherson17220c12014-03-05 10:12:43 +0000207
208 jit_descriptor jit_desc;
209 const size_t jit_desc_size = sizeof(jit_desc);
210 Error error;
Andrew MacPhersoneb4d0602014-03-13 09:37:02 +0000211 size_t bytes_read = m_process->DoReadMemory(
212 m_jit_descriptor_addr, &jit_desc, jit_desc_size, error);
Andrew MacPherson17220c12014-03-05 10:12:43 +0000213 if (bytes_read != jit_desc_size || !error.Success())
214 {
215 if (log)
216 log->Printf("JITLoaderGDB::%s failed to read JIT descriptor",
217 __FUNCTION__);
218 return false;
219 }
220
221 jit_actions_t jit_action = (jit_actions_t)jit_desc.action_flag;
222 addr_t jit_relevant_entry = (addr_t)jit_desc.relevant_entry;
223 if (all_entries)
224 {
225 jit_action = JIT_REGISTER_FN;
226 jit_relevant_entry = (addr_t)jit_desc.first_entry;
227 }
228
229 while (jit_relevant_entry != 0)
230 {
231 jit_code_entry jit_entry;
232 const size_t jit_entry_size = sizeof(jit_entry);
233 bytes_read = m_process->DoReadMemory(jit_relevant_entry, &jit_entry, jit_entry_size, error);
234 if (bytes_read != jit_entry_size || !error.Success())
235 {
236 if (log)
237 log->Printf(
238 "JITLoaderGDB::%s failed to read JIT entry at 0x%" PRIx64,
239 __FUNCTION__, jit_relevant_entry);
240 return false;
241 }
242
243 const addr_t &symbolfile_addr = (addr_t)jit_entry.symfile_addr;
244 const size_t &symbolfile_size = (size_t)jit_entry.symfile_size;
245 ModuleSP module_sp;
246
247 if (jit_action == JIT_REGISTER_FN)
248 {
249 if (log)
250 log->Printf(
251 "JITLoaderGDB::%s registering JIT entry at 0x%" PRIx64
252 " (%" PRIu64 " bytes)",
Jason Molendab509a412014-03-05 23:48:15 +0000253 __FUNCTION__, symbolfile_addr, (uint64_t) symbolfile_size);
Andrew MacPherson17220c12014-03-05 10:12:43 +0000254
255 char jit_name[64];
256 snprintf(jit_name, 64, "JIT(0x%" PRIx64 ")", symbolfile_addr);
257 module_sp = m_process->ReadModuleFromMemory(
258 FileSpec(jit_name, false), symbolfile_addr, symbolfile_size);
259
260 if (module_sp && module_sp->GetObjectFile())
261 {
262 bool changed;
Greg Clayton48672af2014-06-24 22:22:43 +0000263 m_jit_objects.insert(std::make_pair(symbolfile_addr, module_sp));
264 if (module_sp->GetObjectFile()->GetPluginName() == ConstString("mach-o"))
265 {
266 ObjectFile *image_object_file = module_sp->GetObjectFile();
267 if (image_object_file)
268 {
269 const SectionList *section_list = image_object_file->GetSectionList ();
270 if (section_list)
271 {
272 uint64_t vmaddrheuristic = 0;
273 uint64_t lower = (uint64_t)-1;
274 uint64_t upper = 0;
275 updateSectionLoadAddress(*section_list, target, symbolfile_addr, symbolfile_size,
276 vmaddrheuristic, lower, upper);
277 }
278 }
279 }
280 else
281 {
282 module_sp->SetLoadAddress(target, 0, true, changed);
283 }
Andrew MacPherson17220c12014-03-05 10:12:43 +0000284
285 // load the symbol table right away
286 module_sp->GetObjectFile()->GetSymtab();
287
Andrew MacPhersoneb4d0602014-03-13 09:37:02 +0000288 module_list.AppendIfNeeded(module_sp);
Andrew MacPherson17220c12014-03-05 10:12:43 +0000289
290 ModuleList module_list;
291 module_list.Append(module_sp);
292 target.ModulesDidLoad(module_list);
293 }
294 else
295 {
296 if (log)
297 log->Printf("JITLoaderGDB::%s failed to load module for "
298 "JIT entry at 0x%" PRIx64,
299 __FUNCTION__, symbolfile_addr);
300 }
301 }
302 else if (jit_action == JIT_UNREGISTER_FN)
303 {
304 if (log)
305 log->Printf(
306 "JITLoaderGDB::%s unregistering JIT entry at 0x%" PRIx64,
307 __FUNCTION__, symbolfile_addr);
308
309 JITObjectMap::iterator it = m_jit_objects.find(symbolfile_addr);
310 if (it != m_jit_objects.end())
311 {
312 module_sp = it->second;
313 ObjectFile *image_object_file = module_sp->GetObjectFile();
314 if (image_object_file)
315 {
316 const SectionList *section_list = image_object_file->GetSectionList ();
317 if (section_list)
318 {
319 const uint32_t num_sections = section_list->GetSize();
320 for (uint32_t i = 0; i<num_sections; ++i)
321 {
322 SectionSP section_sp(section_list->GetSectionAtIndex(i));
323 if (section_sp)
324 {
325 target.GetSectionLoadList().SetSectionUnloaded (section_sp);
326 }
327 }
328 }
329 }
Andrew MacPhersoneb4d0602014-03-13 09:37:02 +0000330 module_list.Remove(module_sp);
Andrew MacPherson17220c12014-03-05 10:12:43 +0000331 m_jit_objects.erase(it);
332 }
333 }
334 else if (jit_action == JIT_NOACTION)
335 {
336 // Nothing to do
337 }
338 else
339 {
340 assert(false && "Unknown jit action");
341 }
342
343 if (all_entries)
344 jit_relevant_entry = (addr_t)jit_entry.next_entry;
345 else
346 jit_relevant_entry = 0;
347 }
348
349 return false; // Continue Running.
350}
351
352//------------------------------------------------------------------
353// PluginInterface protocol
354//------------------------------------------------------------------
355lldb_private::ConstString
356JITLoaderGDB::GetPluginNameStatic()
357{
358 static ConstString g_name("gdb");
359 return g_name;
360}
361
362JITLoaderSP
363JITLoaderGDB::CreateInstance(Process *process, bool force)
364{
Greg Clayton521c2272014-04-07 20:13:57 +0000365 JITLoaderSP jit_loader_sp;
366 ArchSpec arch (process->GetTarget().GetArchitecture());
367 if (arch.GetTriple().getVendor() != llvm::Triple::Apple)
368 jit_loader_sp.reset(new JITLoaderGDB(process));
Andrew MacPherson17220c12014-03-05 10:12:43 +0000369 return jit_loader_sp;
370}
371
372const char *
373JITLoaderGDB::GetPluginDescriptionStatic()
374{
375 return "JIT loader plug-in that watches for JIT events using the GDB interface.";
376}
377
378lldb_private::ConstString
379JITLoaderGDB::GetPluginName()
380{
381 return GetPluginNameStatic();
382}
383
384uint32_t
385JITLoaderGDB::GetPluginVersion()
386{
387 return 1;
388}
389
390void
391JITLoaderGDB::Initialize()
392{
393 PluginManager::RegisterPlugin (GetPluginNameStatic(),
394 GetPluginDescriptionStatic(),
395 CreateInstance);
396}
397
398void
399JITLoaderGDB::Terminate()
400{
401 PluginManager::UnregisterPlugin (CreateInstance);
402}
403
404bool
405JITLoaderGDB::DidSetJITBreakpoint() const
406{
407 return LLDB_BREAK_ID_IS_VALID(m_jit_break_id);
408}
409
Andrew MacPherson17220c12014-03-05 10:12:43 +0000410addr_t
Andrew MacPhersoneb4d0602014-03-13 09:37:02 +0000411JITLoaderGDB::GetSymbolAddress(ModuleList &module_list, const ConstString &name,
412 SymbolType symbol_type) const
Andrew MacPherson17220c12014-03-05 10:12:43 +0000413{
414 SymbolContextList target_symbols;
415 Target &target = m_process->GetTarget();
Andrew MacPherson17220c12014-03-05 10:12:43 +0000416
Andrew MacPhersoneb4d0602014-03-13 09:37:02 +0000417 if (!module_list.FindSymbolsWithNameAndType(name, symbol_type,
418 target_symbols))
Andrew MacPherson17220c12014-03-05 10:12:43 +0000419 return LLDB_INVALID_ADDRESS;
420
421 SymbolContext sym_ctx;
422 target_symbols.GetContextAtIndex(0, sym_ctx);
423
424 const Address *jit_descriptor_addr = &sym_ctx.symbol->GetAddress();
425 if (!jit_descriptor_addr || !jit_descriptor_addr->IsValid())
426 return LLDB_INVALID_ADDRESS;
427
428 const addr_t jit_addr = jit_descriptor_addr->GetLoadAddress(&target);
429 return jit_addr;
430}