1 //===-- JITLoaderGDB.cpp --------------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "JITLoaderGDB.h"
10 #include "Plugins/ObjectFile/Mach-O/ObjectFileMachO.h"
11 #include "lldb/Breakpoint/Breakpoint.h"
12 #include "lldb/Core/Module.h"
13 #include "lldb/Core/ModuleSpec.h"
14 #include "lldb/Core/PluginManager.h"
15 #include "lldb/Core/Section.h"
16 #include "lldb/Interpreter/OptionValueProperties.h"
17 #include "lldb/Symbol/ObjectFile.h"
18 #include "lldb/Symbol/Symbol.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 #include "lldb/Utility/DataBufferHeap.h"
25 #include "lldb/Utility/LLDBAssert.h"
26 #include "lldb/Utility/LLDBLog.h"
27 #include "lldb/Utility/Log.h"
28 #include "lldb/Utility/StreamString.h"
29 #include "llvm/Support/MathExtras.h"
34 using namespace lldb_private
;
36 LLDB_PLUGIN_DEFINE(JITLoaderGDB
)
38 // Debug Interface Structures
39 enum jit_actions_t
{ JIT_NOACTION
= 0, JIT_REGISTER_FN
, JIT_UNREGISTER_FN
};
41 template <typename ptr_t
> struct jit_code_entry
{
42 ptr_t next_entry
; // pointer
43 ptr_t prev_entry
; // pointer
44 ptr_t symfile_addr
; // pointer
45 uint64_t symfile_size
;
48 template <typename ptr_t
> struct jit_descriptor
{
50 uint32_t action_flag
; // Values are jit_action_t
51 ptr_t relevant_entry
; // pointer
52 ptr_t first_entry
; // pointer
56 enum EnableJITLoaderGDB
{
57 eEnableJITLoaderGDBDefault
,
58 eEnableJITLoaderGDBOn
,
59 eEnableJITLoaderGDBOff
,
62 static constexpr OptionEnumValueElement g_enable_jit_loader_gdb_enumerators
[] =
65 eEnableJITLoaderGDBDefault
,
67 "Enable JIT compilation interface for all platforms except macOS",
70 eEnableJITLoaderGDBOn
,
72 "Enable JIT compilation interface",
75 eEnableJITLoaderGDBOff
,
77 "Disable JIT compilation interface",
81 #define LLDB_PROPERTIES_jitloadergdb
82 #include "JITLoaderGDBProperties.inc"
85 #define LLDB_PROPERTIES_jitloadergdb
86 #include "JITLoaderGDBPropertiesEnum.inc"
87 ePropertyEnableJITBreakpoint
90 class PluginProperties
: public Properties
{
92 static llvm::StringRef
GetSettingName() {
93 return JITLoaderGDB::GetPluginNameStatic();
97 m_collection_sp
= std::make_shared
<OptionValueProperties
>(GetSettingName());
98 m_collection_sp
->Initialize(g_jitloadergdb_properties
);
101 EnableJITLoaderGDB
GetEnable() const {
102 return GetPropertyAtIndexAs
<EnableJITLoaderGDB
>(
104 static_cast<EnableJITLoaderGDB
>(
105 g_jitloadergdb_properties
[ePropertyEnable
].default_uint_value
));
110 static PluginProperties
&GetGlobalPluginProperties() {
111 static PluginProperties g_settings
;
115 template <typename ptr_t
>
116 static bool ReadJITEntry(const addr_t from_addr
, Process
*process
,
117 jit_code_entry
<ptr_t
> *entry
) {
118 lldbassert(from_addr
% sizeof(ptr_t
) == 0);
120 ArchSpec::Core core
= process
->GetTarget().GetArchitecture().GetCore();
121 bool i386_target
= ArchSpec::kCore_x86_32_first
<= core
&&
122 core
<= ArchSpec::kCore_x86_32_last
;
123 uint8_t uint64_align_bytes
= i386_target
? 4 : 8;
124 const size_t data_byte_size
=
125 llvm::alignTo(sizeof(ptr_t
) * 3, uint64_align_bytes
) + sizeof(uint64_t);
128 DataBufferHeap
data(data_byte_size
, 0);
129 size_t bytes_read
= process
->ReadMemory(from_addr
, data
.GetBytes(),
130 data
.GetByteSize(), error
);
131 if (bytes_read
!= data_byte_size
|| !error
.Success())
134 DataExtractor
extractor(data
.GetBytes(), data
.GetByteSize(),
135 process
->GetByteOrder(), sizeof(ptr_t
));
136 lldb::offset_t offset
= 0;
137 entry
->next_entry
= extractor
.GetAddress(&offset
);
138 entry
->prev_entry
= extractor
.GetAddress(&offset
);
139 entry
->symfile_addr
= extractor
.GetAddress(&offset
);
140 offset
= llvm::alignTo(offset
, uint64_align_bytes
);
141 entry
->symfile_size
= extractor
.GetU64(&offset
);
146 JITLoaderGDB::JITLoaderGDB(lldb_private::Process
*process
)
147 : JITLoader(process
), m_jit_objects(),
148 m_jit_break_id(LLDB_INVALID_BREAK_ID
),
149 m_jit_descriptor_addr(LLDB_INVALID_ADDRESS
) {}
151 JITLoaderGDB::~JITLoaderGDB() {
152 if (LLDB_BREAK_ID_IS_VALID(m_jit_break_id
))
153 m_process
->GetTarget().RemoveBreakpointByID(m_jit_break_id
);
156 void JITLoaderGDB::DebuggerInitialize(Debugger
&debugger
) {
157 if (!PluginManager::GetSettingForJITLoaderPlugin(
158 debugger
, PluginProperties::GetSettingName())) {
159 const bool is_global_setting
= true;
160 PluginManager::CreateSettingForJITLoaderPlugin(
161 debugger
, GetGlobalPluginProperties().GetValueProperties(),
162 "Properties for the JIT LoaderGDB plug-in.", is_global_setting
);
166 void JITLoaderGDB::DidAttach() {
167 Target
&target
= m_process
->GetTarget();
168 ModuleList
&module_list
= target
.GetImages();
169 SetJITBreakpoint(module_list
);
172 void JITLoaderGDB::DidLaunch() {
173 Target
&target
= m_process
->GetTarget();
174 ModuleList
&module_list
= target
.GetImages();
175 SetJITBreakpoint(module_list
);
178 void JITLoaderGDB::ModulesDidLoad(ModuleList
&module_list
) {
179 if (!DidSetJITBreakpoint() && m_process
->IsAlive())
180 SetJITBreakpoint(module_list
);
183 // Setup the JIT Breakpoint
184 void JITLoaderGDB::SetJITBreakpoint(lldb_private::ModuleList
&module_list
) {
185 if (DidSetJITBreakpoint())
188 Log
*log
= GetLog(LLDBLog::JITLoader
);
189 LLDB_LOGF(log
, "JITLoaderGDB::%s looking for JIT register hook",
192 addr_t jit_addr
= GetSymbolAddress(
193 module_list
, ConstString("__jit_debug_register_code"), eSymbolTypeCode
);
194 if (jit_addr
== LLDB_INVALID_ADDRESS
)
197 m_jit_descriptor_addr
= GetSymbolAddress(
198 module_list
, ConstString("__jit_debug_descriptor"), eSymbolTypeData
);
199 if (m_jit_descriptor_addr
== LLDB_INVALID_ADDRESS
) {
200 LLDB_LOGF(log
, "JITLoaderGDB::%s failed to find JIT descriptor address",
205 LLDB_LOGF(log
, "JITLoaderGDB::%s setting JIT breakpoint", __FUNCTION__
);
208 m_process
->GetTarget().CreateBreakpoint(jit_addr
, true, false).get();
209 bp
->SetCallback(JITDebugBreakpointHit
, this, true);
210 bp
->SetBreakpointKind("jit-debug-register");
211 m_jit_break_id
= bp
->GetID();
213 ReadJITDescriptor(true);
216 bool JITLoaderGDB::JITDebugBreakpointHit(void *baton
,
217 StoppointCallbackContext
*context
,
219 user_id_t break_loc_id
) {
220 Log
*log
= GetLog(LLDBLog::JITLoader
);
221 LLDB_LOGF(log
, "JITLoaderGDB::%s hit JIT breakpoint", __FUNCTION__
);
222 JITLoaderGDB
*instance
= static_cast<JITLoaderGDB
*>(baton
);
223 return instance
->ReadJITDescriptor(false);
226 static void updateSectionLoadAddress(const SectionList
§ion_list
,
227 Target
&target
, uint64_t symbolfile_addr
,
228 uint64_t symbolfile_size
,
229 uint64_t &vmaddrheuristic
,
230 uint64_t &min_addr
, uint64_t &max_addr
) {
231 const uint32_t num_sections
= section_list
.GetSize();
232 for (uint32_t i
= 0; i
< num_sections
; ++i
) {
233 SectionSP
section_sp(section_list
.GetSectionAtIndex(i
));
235 if (section_sp
->IsFake()) {
236 uint64_t lower
= (uint64_t)-1;
238 updateSectionLoadAddress(section_sp
->GetChildren(), target
,
239 symbolfile_addr
, symbolfile_size
,
240 vmaddrheuristic
, lower
, upper
);
241 if (lower
< min_addr
)
243 if (upper
> max_addr
)
245 const lldb::addr_t slide_amount
= lower
- section_sp
->GetFileAddress();
246 section_sp
->Slide(slide_amount
, false);
247 section_sp
->GetChildren().Slide(-slide_amount
, false);
248 section_sp
->SetByteSize(upper
- lower
);
250 vmaddrheuristic
+= 2 << section_sp
->GetLog2Align();
252 if (section_sp
->GetFileAddress() > vmaddrheuristic
)
253 lower
= section_sp
->GetFileAddress();
255 lower
= symbolfile_addr
+ section_sp
->GetFileOffset();
256 section_sp
->SetFileAddress(symbolfile_addr
+
257 section_sp
->GetFileOffset());
259 target
.SetSectionLoadAddress(section_sp
, lower
, true);
260 uint64_t upper
= lower
+ section_sp
->GetByteSize();
261 if (lower
< min_addr
)
263 if (upper
> max_addr
)
265 // This is an upper bound, but a good enough heuristic
266 vmaddrheuristic
+= section_sp
->GetByteSize();
272 bool JITLoaderGDB::ReadJITDescriptor(bool all_entries
) {
273 if (m_process
->GetTarget().GetArchitecture().GetAddressByteSize() == 8)
274 return ReadJITDescriptorImpl
<uint64_t>(all_entries
);
276 return ReadJITDescriptorImpl
<uint32_t>(all_entries
);
279 template <typename ptr_t
>
280 bool JITLoaderGDB::ReadJITDescriptorImpl(bool all_entries
) {
281 if (m_jit_descriptor_addr
== LLDB_INVALID_ADDRESS
)
284 Log
*log
= GetLog(LLDBLog::JITLoader
);
285 Target
&target
= m_process
->GetTarget();
286 ModuleList
&module_list
= target
.GetImages();
288 jit_descriptor
<ptr_t
> jit_desc
;
289 const size_t jit_desc_size
= sizeof(jit_desc
);
291 size_t bytes_read
= m_process
->ReadMemory(m_jit_descriptor_addr
, &jit_desc
,
292 jit_desc_size
, error
);
293 if (bytes_read
!= jit_desc_size
|| !error
.Success()) {
294 LLDB_LOGF(log
, "JITLoaderGDB::%s failed to read JIT descriptor",
299 jit_actions_t jit_action
= (jit_actions_t
)jit_desc
.action_flag
;
300 addr_t jit_relevant_entry
= (addr_t
)jit_desc
.relevant_entry
;
302 jit_action
= JIT_REGISTER_FN
;
303 jit_relevant_entry
= (addr_t
)jit_desc
.first_entry
;
306 while (jit_relevant_entry
!= 0) {
307 jit_code_entry
<ptr_t
> jit_entry
;
308 if (!ReadJITEntry(jit_relevant_entry
, m_process
, &jit_entry
)) {
309 LLDB_LOGF(log
, "JITLoaderGDB::%s failed to read JIT entry at 0x%" PRIx64
,
310 __FUNCTION__
, jit_relevant_entry
);
314 const addr_t
&symbolfile_addr
= (addr_t
)jit_entry
.symfile_addr
;
315 const size_t &symbolfile_size
= (size_t)jit_entry
.symfile_size
;
318 if (jit_action
== JIT_REGISTER_FN
) {
320 "JITLoaderGDB::%s registering JIT entry at 0x%" PRIx64
321 " (%" PRIu64
" bytes)",
322 __FUNCTION__
, symbolfile_addr
, (uint64_t)symbolfile_size
);
325 snprintf(jit_name
, 64, "JIT(0x%" PRIx64
")", symbolfile_addr
);
326 module_sp
= m_process
->ReadModuleFromMemory(
327 FileSpec(jit_name
), symbolfile_addr
, symbolfile_size
);
329 if (module_sp
&& module_sp
->GetObjectFile()) {
330 // Object formats (like ELF) have no representation for a JIT type.
331 // We will get it wrong, if we deduce it from the header.
332 module_sp
->GetObjectFile()->SetType(ObjectFile::eTypeJIT
);
334 // load the symbol table right away
335 module_sp
->GetObjectFile()->GetSymtab();
337 m_jit_objects
.insert(std::make_pair(symbolfile_addr
, module_sp
));
338 if (auto image_object_file
=
339 llvm::dyn_cast
<ObjectFileMachO
>(module_sp
->GetObjectFile())) {
340 const SectionList
*section_list
= image_object_file
->GetSectionList();
342 uint64_t vmaddrheuristic
= 0;
343 uint64_t lower
= (uint64_t)-1;
345 updateSectionLoadAddress(*section_list
, target
, symbolfile_addr
,
346 symbolfile_size
, vmaddrheuristic
, lower
,
350 bool changed
= false;
351 module_sp
->SetLoadAddress(target
, 0, true, changed
);
354 module_list
.AppendIfNeeded(module_sp
);
356 ModuleList module_list
;
357 module_list
.Append(module_sp
);
358 target
.ModulesDidLoad(module_list
);
361 "JITLoaderGDB::%s failed to load module for "
362 "JIT entry at 0x%" PRIx64
,
363 __FUNCTION__
, symbolfile_addr
);
365 } else if (jit_action
== JIT_UNREGISTER_FN
) {
366 LLDB_LOGF(log
, "JITLoaderGDB::%s unregistering JIT entry at 0x%" PRIx64
,
367 __FUNCTION__
, symbolfile_addr
);
369 JITObjectMap::iterator it
= m_jit_objects
.find(symbolfile_addr
);
370 if (it
!= m_jit_objects
.end()) {
371 module_sp
= it
->second
;
372 ObjectFile
*image_object_file
= module_sp
->GetObjectFile();
373 if (image_object_file
) {
374 const SectionList
*section_list
= image_object_file
->GetSectionList();
376 const uint32_t num_sections
= section_list
->GetSize();
377 for (uint32_t i
= 0; i
< num_sections
; ++i
) {
378 SectionSP
section_sp(section_list
->GetSectionAtIndex(i
));
380 target
.GetSectionLoadList().SetSectionUnloaded(section_sp
);
385 module_list
.Remove(module_sp
);
386 m_jit_objects
.erase(it
);
388 } else if (jit_action
== JIT_NOACTION
) {
391 assert(false && "Unknown jit action");
395 jit_relevant_entry
= (addr_t
)jit_entry
.next_entry
;
397 jit_relevant_entry
= 0;
400 return false; // Continue Running.
403 // PluginInterface protocol
404 JITLoaderSP
JITLoaderGDB::CreateInstance(Process
*process
, bool force
) {
405 JITLoaderSP jit_loader_sp
;
407 switch (GetGlobalPluginProperties().GetEnable()) {
408 case EnableJITLoaderGDB::eEnableJITLoaderGDBOn
:
411 case EnableJITLoaderGDB::eEnableJITLoaderGDBOff
:
414 case EnableJITLoaderGDB::eEnableJITLoaderGDBDefault
:
415 ArchSpec
arch(process
->GetTarget().GetArchitecture());
416 enable
= arch
.GetTriple().getVendor() != llvm::Triple::Apple
;
420 jit_loader_sp
= std::make_shared
<JITLoaderGDB
>(process
);
421 return jit_loader_sp
;
424 llvm::StringRef
JITLoaderGDB::GetPluginDescriptionStatic() {
425 return "JIT loader plug-in that watches for JIT events using the GDB "
429 void JITLoaderGDB::Initialize() {
430 PluginManager::RegisterPlugin(GetPluginNameStatic(),
431 GetPluginDescriptionStatic(), CreateInstance
,
435 void JITLoaderGDB::Terminate() {
436 PluginManager::UnregisterPlugin(CreateInstance
);
439 bool JITLoaderGDB::DidSetJITBreakpoint() const {
440 return LLDB_BREAK_ID_IS_VALID(m_jit_break_id
);
443 addr_t
JITLoaderGDB::GetSymbolAddress(ModuleList
&module_list
,
445 SymbolType symbol_type
) const {
446 SymbolContextList target_symbols
;
447 Target
&target
= m_process
->GetTarget();
449 module_list
.FindSymbolsWithNameAndType(name
, symbol_type
, target_symbols
);
450 if (target_symbols
.IsEmpty())
451 return LLDB_INVALID_ADDRESS
;
453 SymbolContext sym_ctx
;
454 target_symbols
.GetContextAtIndex(0, sym_ctx
);
456 const Address jit_descriptor_addr
= sym_ctx
.symbol
->GetAddress();
457 if (!jit_descriptor_addr
.IsValid())
458 return LLDB_INVALID_ADDRESS
;
460 const addr_t jit_addr
= jit_descriptor_addr
.GetLoadAddress(&target
);