29#include "llvm/Support/MathExtras.h"
40enum jit_actions_t { JIT_NOACTION = 0, JIT_REGISTER_FN, JIT_UNREGISTER_FN };
42template <
typename ptr_t>
struct jit_code_entry {
46 uint64_t symfile_size;
49template <
typename ptr_t>
struct jit_descriptor {
56enum EnableJITLoaderGDB {
57 eEnableJITLoaderGDBDefault,
58 eEnableJITLoaderGDBOn,
59 eEnableJITLoaderGDBOff,
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
92 static llvm::StringRef GetSettingName() {
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));
111 static PluginProperties g_settings;
115template <
typename ptr_t>
117 jit_code_entry<ptr_t> *entry) {
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);
131 if (bytes_read != data_byte_size || !
error.Success())
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);
158 debugger, PluginProperties::GetSettingName())) {
159 const bool is_global_setting =
true;
162 "Properties for the JIT LoaderGDB plug-in.", is_global_setting);
189 LLDB_LOGF(log,
"JITLoaderGDB::%s looking for JIT register hook",
200 LLDB_LOGF(log,
"JITLoaderGDB::%s failed to find JIT descriptor address",
205 LLDB_LOGF(log,
"JITLoaderGDB::%s setting JIT breakpoint", __FUNCTION__);
221 LLDB_LOGF(log,
"JITLoaderGDB::%s hit JIT breakpoint", __FUNCTION__);
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) {
235 if (section_sp->IsFake()) {
236 uint64_t lower = (uint64_t)-1;
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());
260 uint64_t upper = lower + section_sp->GetByteSize();
261 if (lower < min_addr)
263 if (upper > max_addr)
266 vmaddrheuristic += section_sp->GetByteSize();
274 return ReadJITDescriptorImpl<uint64_t>(all_entries);
276 return ReadJITDescriptorImpl<uint32_t>(all_entries);
279template <
typename ptr_t>
288 jit_descriptor<ptr_t> jit_desc;
289 const size_t jit_desc_size =
sizeof(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;
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);
327 FileSpec(jit_name), symbolfile_addr, symbolfile_size);
329 if (module_sp && module_sp->GetObjectFile()) {
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;
346 symbolfile_size, vmaddrheuristic, lower,
350 bool changed =
false;
351 module_sp->SetLoadAddress(target, 0,
true, changed);
357 module_list.
Append(module_sp);
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);
371 module_sp = it->second;
372 ObjectFile *image_object_file = module_sp->GetObjectFile();
373 if (image_object_file) {
376 const uint32_t num_sections = section_list->
GetSize();
377 for (uint32_t i = 0; i < num_sections; ++i) {
385 module_list.
Remove(module_sp);
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;
408 case EnableJITLoaderGDB::eEnableJITLoaderGDBOn:
411 case EnableJITLoaderGDB::eEnableJITLoaderGDBOff:
414 case EnableJITLoaderGDB::eEnableJITLoaderGDBDefault:
416 enable = arch.
GetTriple().getVendor() != llvm::Triple::Apple;
420 jit_loader_sp = std::make_shared<JITLoaderGDB>(process);
421 return jit_loader_sp;
425 return "JIT loader plug-in that watches for JIT events using the GDB "
457 if (!jit_descriptor_addr.
IsValid())
static llvm::raw_ostream & error(Stream &strm)
static PluginProperties & GetGlobalPluginProperties()
static void updateSectionLoadAddress(const SectionList §ion_list, Target &target, uint64_t symbolfile_addr, uint64_t symbolfile_size, uint64_t &vmaddrheuristic, uint64_t &min_addr, uint64_t &max_addr)
static bool ReadJITEntry(const addr_t from_addr, Process *process, jit_code_entry< ptr_t > *entry)
#define LLDB_LOGF(log,...)
#define LLDB_PLUGIN_DEFINE(PluginName)
JITObjectMap m_jit_objects
lldb::addr_t m_jit_descriptor_addr
JITLoaderGDB(lldb_private::Process *process)
lldb::addr_t GetSymbolAddress(lldb_private::ModuleList &module_list, lldb_private::ConstString name, lldb::SymbolType symbol_type) const
bool ReadJITDescriptor(bool all_entries)
static lldb::JITLoaderSP CreateInstance(lldb_private::Process *process, bool force)
bool ReadJITDescriptorImpl(bool all_entries)
static void DebuggerInitialize(lldb_private::Debugger &debugger)
static llvm::StringRef GetPluginNameStatic()
static llvm::StringRef GetPluginDescriptionStatic()
bool DidSetJITBreakpoint() const
static bool JITDebugBreakpointHit(void *baton, lldb_private::StoppointCallbackContext *context, lldb::user_id_t break_id, lldb::user_id_t break_loc_id)
lldb::user_id_t m_jit_break_id
void DidLaunch() override
Called after launching a process.
void ModulesDidLoad(lldb_private::ModuleList &module_list) override
Called after a new shared object has been loaded so that it can be probed for JIT entry point hooks.
void DidAttach() override
Called after attaching a process.
void SetJITBreakpoint(lldb_private::ModuleList &module_list)
A section + offset based address class.
lldb::addr_t GetLoadAddress(Target *target) const
Get the load address.
bool IsValid() const
Check if the object state is valid.
An architecture specification class.
uint32_t GetAddressByteSize() const
Returns the size in bytes of an address of the current architecture.
llvm::Triple & GetTriple()
Architecture triple accessor.
General Outline: A breakpoint has four main parts, a filter, a resolver, the list of breakpoint locat...
void SetBreakpointKind(const char *kind)
Set the "kind" description for a breakpoint.
void SetCallback(BreakpointHitCallback callback, void *baton, bool is_synchronous=false)
Set the callback action invoked when the breakpoint is hit.
A uniqued constant string class.
A subclass of DataBuffer that stores a data buffer on the heap.
lldb::offset_t GetByteSize() const override
Get the number of bytes in the data buffer.
A class to manage flag bits.
A plug-in interface definition class for JIT loaders.
A collection class for Module objects.
bool AppendIfNeeded(const lldb::ModuleSP &new_module, bool notify=true)
Append a module to the module list, if it is not already there.
void FindSymbolsWithNameAndType(ConstString name, lldb::SymbolType symbol_type, SymbolContextList &sc_list) const
bool Remove(const lldb::ModuleSP &module_sp, bool notify=true)
Remove a module from the module list.
void Append(const lldb::ModuleSP &module_sp, bool notify=true)
Append a module to the module list.
A plug-in interface definition class for object file parsers.
@ eTypeJIT
JIT code that has symbols, sections and possibly debug info.
virtual SectionList * GetSectionList(bool update_module_section_list=true)
Gets the section list for the currently selected architecture (and object for archives).
static bool CreateSettingForJITLoaderPlugin(Debugger &debugger, const lldb::OptionValuePropertiesSP &properties_sp, llvm::StringRef description, bool is_global_property)
static bool RegisterPlugin(llvm::StringRef name, llvm::StringRef description, ABICreateInstance create_callback)
static lldb::OptionValuePropertiesSP GetSettingForJITLoaderPlugin(Debugger &debugger, llvm::StringRef setting_name)
static bool UnregisterPlugin(ABICreateInstance create_callback)
A plug-in interface definition class for debugging a process.
virtual size_t ReadMemory(lldb::addr_t vm_addr, void *buf, size_t size, Status &error)
Read of memory from a process.
lldb::ByteOrder GetByteOrder() const
virtual bool IsAlive()
Check if a process is still alive.
lldb::ModuleSP ReadModuleFromMemory(const FileSpec &file_spec, lldb::addr_t header_addr, size_t size_to_read=512)
Target & GetTarget()
Get the target object pointer for this module.
lldb::SectionSP GetSectionAtIndex(size_t idx) const
bool SetSectionUnloaded(const lldb::SectionSP §ion_sp, lldb::addr_t load_addr)
General Outline: When we hit a breakpoint we need to package up whatever information is needed to eva...
lldb::break_id_t GetID() const
Defines a list of symbol context objects.
bool GetContextAtIndex(size_t idx, SymbolContext &sc) const
Get accessor for a symbol context at index idx.
Defines a symbol context baton that can be handed other debug core functions.
Symbol * symbol
The Symbol for a given query.
Address GetAddress() const
void ModulesDidLoad(ModuleList &module_list)
SectionLoadList & GetSectionLoadList()
bool RemoveBreakpointByID(lldb::break_id_t break_id)
lldb::BreakpointSP CreateBreakpoint(const FileSpecList *containingModules, const FileSpec &file, uint32_t line_no, uint32_t column, lldb::addr_t offset, LazyBool check_inlines, LazyBool skip_prologue, bool internal, bool request_hardware, LazyBool move_to_nearest_code)
const ModuleList & GetImages() const
Get accessor for the images for this process.
const ArchSpec & GetArchitecture() const
bool SetSectionLoadAddress(const lldb::SectionSP §ion, lldb::addr_t load_addr, bool warn_multiple=false)
uint8_t * GetBytes()
Get a pointer to the data.
#define LLDB_INVALID_BREAK_ID
#define LLDB_BREAK_ID_IS_VALID(bid)
#define LLDB_INVALID_ADDRESS
A class that represents a running process on the host machine.
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
std::shared_ptr< lldb_private::Section > SectionSP
std::shared_ptr< lldb_private::JITLoader > JITLoaderSP
std::shared_ptr< lldb_private::Module > ModuleSP