1 //===-- JITLoaderGDB.cpp --------------------------------------------------===// 2 // 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 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "JITLoaderGDB.h" 10 #ifdef LLDB_ENABLE_ALL 11 #include "Plugins/ObjectFile/Mach-O/ObjectFileMachO.h" 12 #endif // LLDB_ENABLE_ALL 13 #include "lldb/Breakpoint/Breakpoint.h" 14 #include "lldb/Core/Module.h" 15 #include "lldb/Core/ModuleSpec.h" 16 #include "lldb/Core/PluginManager.h" 17 #include "lldb/Core/Section.h" 18 #include "lldb/Interpreter/OptionValueProperties.h" 19 #include "lldb/Symbol/ObjectFile.h" 20 #include "lldb/Symbol/Symbol.h" 21 #include "lldb/Symbol/SymbolContext.h" 22 #include "lldb/Symbol/SymbolVendor.h" 23 #include "lldb/Target/Process.h" 24 #include "lldb/Target/SectionLoadList.h" 25 #include "lldb/Target/Target.h" 26 #include "lldb/Utility/DataBufferHeap.h" 27 #include "lldb/Utility/LLDBAssert.h" 28 #include "lldb/Utility/LLDBLog.h" 29 #include "lldb/Utility/Log.h" 30 #include "lldb/Utility/StreamString.h" 31 #include "llvm/Support/MathExtras.h" 32 33 #include <memory> 34 35 using namespace lldb; 36 using namespace lldb_private; 37 38 LLDB_PLUGIN_DEFINE(JITLoaderGDB) 39 40 namespace { 41 // Debug Interface Structures 42 enum jit_actions_t { JIT_NOACTION = 0, JIT_REGISTER_FN, JIT_UNREGISTER_FN }; 43 44 template <typename ptr_t> struct jit_code_entry { 45 ptr_t next_entry; // pointer 46 ptr_t prev_entry; // pointer 47 ptr_t symfile_addr; // pointer 48 uint64_t symfile_size; 49 }; 50 51 template <typename ptr_t> struct jit_descriptor { 52 uint32_t version; 53 uint32_t action_flag; // Values are jit_action_t 54 ptr_t relevant_entry; // pointer 55 ptr_t first_entry; // pointer 56 }; 57 58 enum EnableJITLoaderGDB { 59 eEnableJITLoaderGDBDefault, 60 eEnableJITLoaderGDBOn, 61 eEnableJITLoaderGDBOff, 62 }; 63 64 static constexpr OptionEnumValueElement g_enable_jit_loader_gdb_enumerators[] = 65 { 66 { 67 eEnableJITLoaderGDBDefault, 68 "default", 69 "Enable JIT compilation interface for all platforms except macOS", 70 }, 71 { 72 eEnableJITLoaderGDBOn, 73 "on", 74 "Enable JIT compilation interface", 75 }, 76 { 77 eEnableJITLoaderGDBOff, 78 "off", 79 "Disable JIT compilation interface", 80 }, 81 }; 82 83 #define LLDB_PROPERTIES_jitloadergdb 84 #include "JITLoaderGDBProperties.inc" 85 86 enum { 87 #define LLDB_PROPERTIES_jitloadergdb 88 #include "JITLoaderGDBPropertiesEnum.inc" 89 ePropertyEnableJITBreakpoint 90 }; 91 92 class PluginProperties : public Properties { 93 public: 94 static llvm::StringRef GetSettingName() { 95 return JITLoaderGDB::GetPluginNameStatic(); 96 } 97 98 PluginProperties() { 99 m_collection_sp = std::make_shared<OptionValueProperties>(GetSettingName()); 100 m_collection_sp->Initialize(g_jitloadergdb_properties); 101 } 102 103 EnableJITLoaderGDB GetEnable() const { 104 return GetPropertyAtIndexAs<EnableJITLoaderGDB>( 105 ePropertyEnable, 106 static_cast<EnableJITLoaderGDB>( 107 g_jitloadergdb_properties[ePropertyEnable].default_uint_value)); 108 } 109 }; 110 } // namespace 111 112 static PluginProperties &GetGlobalPluginProperties() { 113 static PluginProperties g_settings; 114 return g_settings; 115 } 116 117 template <typename ptr_t> 118 static bool ReadJITEntry(const addr_t from_addr, Process *process, 119 jit_code_entry<ptr_t> *entry) { 120 lldbassert(from_addr % sizeof(ptr_t) == 0); 121 122 ArchSpec::Core core = process->GetTarget().GetArchitecture().GetCore(); 123 bool i386_target = ArchSpec::kCore_x86_32_first <= core && 124 core <= ArchSpec::kCore_x86_32_last; 125 uint8_t uint64_align_bytes = i386_target ? 4 : 8; 126 const size_t data_byte_size = 127 llvm::alignTo(sizeof(ptr_t) * 3, uint64_align_bytes) + sizeof(uint64_t); 128 129 Status error; 130 DataBufferHeap data(data_byte_size, 0); 131 size_t bytes_read = process->ReadMemory(from_addr, data.GetBytes(), 132 data.GetByteSize(), error); 133 if (bytes_read != data_byte_size || !error.Success()) 134 return false; 135 136 DataExtractor extractor(data.GetBytes(), data.GetByteSize(), 137 process->GetByteOrder(), sizeof(ptr_t)); 138 lldb::offset_t offset = 0; 139 entry->next_entry = extractor.GetAddress(&offset); 140 entry->prev_entry = extractor.GetAddress(&offset); 141 entry->symfile_addr = extractor.GetAddress(&offset); 142 offset = llvm::alignTo(offset, uint64_align_bytes); 143 entry->symfile_size = extractor.GetU64(&offset); 144 145 return true; 146 } 147 148 JITLoaderGDB::JITLoaderGDB(lldb_private::Process *process) 149 : JITLoader(process), m_jit_objects(), 150 m_jit_break_id(LLDB_INVALID_BREAK_ID), 151 m_jit_descriptor_addr(LLDB_INVALID_ADDRESS) {} 152 153 JITLoaderGDB::~JITLoaderGDB() { 154 if (LLDB_BREAK_ID_IS_VALID(m_jit_break_id)) 155 m_process->GetTarget().RemoveBreakpointByID(m_jit_break_id); 156 } 157 158 void JITLoaderGDB::DebuggerInitialize(Debugger &debugger) { 159 if (!PluginManager::GetSettingForJITLoaderPlugin( 160 debugger, PluginProperties::GetSettingName())) { 161 const bool is_global_setting = true; 162 PluginManager::CreateSettingForJITLoaderPlugin( 163 debugger, GetGlobalPluginProperties().GetValueProperties(), 164 "Properties for the JIT LoaderGDB plug-in.", is_global_setting); 165 } 166 } 167 168 void JITLoaderGDB::DidAttach() { 169 Target &target = m_process->GetTarget(); 170 ModuleList &module_list = target.GetImages(); 171 SetJITBreakpoint(module_list); 172 } 173 174 void JITLoaderGDB::DidLaunch() { 175 Target &target = m_process->GetTarget(); 176 ModuleList &module_list = target.GetImages(); 177 SetJITBreakpoint(module_list); 178 } 179 180 void JITLoaderGDB::ModulesDidLoad(ModuleList &module_list) { 181 if (!DidSetJITBreakpoint() && m_process->IsAlive()) 182 SetJITBreakpoint(module_list); 183 } 184 185 // Setup the JIT Breakpoint 186 void JITLoaderGDB::SetJITBreakpoint(lldb_private::ModuleList &module_list) { 187 if (DidSetJITBreakpoint()) 188 return; 189 190 Log *log = GetLog(LLDBLog::JITLoader); 191 LLDB_LOGF(log, "JITLoaderGDB::%s looking for JIT register hook", 192 __FUNCTION__); 193 194 addr_t jit_addr = GetSymbolAddress( 195 module_list, ConstString("__jit_debug_register_code"), eSymbolTypeCode); 196 if (jit_addr == LLDB_INVALID_ADDRESS) 197 return; 198 199 m_jit_descriptor_addr = GetSymbolAddress( 200 module_list, ConstString("__jit_debug_descriptor"), eSymbolTypeData); 201 if (m_jit_descriptor_addr == LLDB_INVALID_ADDRESS) { 202 LLDB_LOGF(log, "JITLoaderGDB::%s failed to find JIT descriptor address", 203 __FUNCTION__); 204 return; 205 } 206 207 LLDB_LOGF(log, "JITLoaderGDB::%s setting JIT breakpoint", __FUNCTION__); 208 209 Breakpoint *bp = 210 m_process->GetTarget().CreateBreakpoint(jit_addr, true, false).get(); 211 bp->SetCallback(JITDebugBreakpointHit, this, true); 212 bp->SetBreakpointKind("jit-debug-register"); 213 m_jit_break_id = bp->GetID(); 214 215 ReadJITDescriptor(true); 216 } 217 218 bool JITLoaderGDB::JITDebugBreakpointHit(void *baton, 219 StoppointCallbackContext *context, 220 user_id_t break_id, 221 user_id_t break_loc_id) { 222 Log *log = GetLog(LLDBLog::JITLoader); 223 LLDB_LOGF(log, "JITLoaderGDB::%s hit JIT breakpoint", __FUNCTION__); 224 JITLoaderGDB *instance = static_cast<JITLoaderGDB *>(baton); 225 return instance->ReadJITDescriptor(false); 226 } 227 228 static void updateSectionLoadAddress(const SectionList §ion_list, 229 Target &target, uint64_t symbolfile_addr, 230 uint64_t symbolfile_size, 231 uint64_t &vmaddrheuristic, 232 uint64_t &min_addr, uint64_t &max_addr) { 233 const uint32_t num_sections = section_list.GetSize(); 234 for (uint32_t i = 0; i < num_sections; ++i) { 235 SectionSP section_sp(section_list.GetSectionAtIndex(i)); 236 if (section_sp) { 237 if (section_sp->IsFake()) { 238 uint64_t lower = (uint64_t)-1; 239 uint64_t upper = 0; 240 updateSectionLoadAddress(section_sp->GetChildren(), target, 241 symbolfile_addr, symbolfile_size, 242 vmaddrheuristic, lower, upper); 243 if (lower < min_addr) 244 min_addr = lower; 245 if (upper > max_addr) 246 max_addr = upper; 247 const lldb::addr_t slide_amount = lower - section_sp->GetFileAddress(); 248 section_sp->Slide(slide_amount, false); 249 section_sp->GetChildren().Slide(-slide_amount, false); 250 section_sp->SetByteSize(upper - lower); 251 } else { 252 vmaddrheuristic += 2 << section_sp->GetLog2Align(); 253 uint64_t lower; 254 if (section_sp->GetFileAddress() > vmaddrheuristic) 255 lower = section_sp->GetFileAddress(); 256 else { 257 lower = symbolfile_addr + section_sp->GetFileOffset(); 258 section_sp->SetFileAddress(symbolfile_addr + 259 section_sp->GetFileOffset()); 260 } 261 target.SetSectionLoadAddress(section_sp, lower, true); 262 uint64_t upper = lower + section_sp->GetByteSize(); 263 if (lower < min_addr) 264 min_addr = lower; 265 if (upper > max_addr) 266 max_addr = upper; 267 // This is an upper bound, but a good enough heuristic 268 vmaddrheuristic += section_sp->GetByteSize(); 269 } 270 } 271 } 272 } 273 274 bool JITLoaderGDB::ReadJITDescriptor(bool all_entries) { 275 if (m_process->GetTarget().GetArchitecture().GetAddressByteSize() == 8) 276 return ReadJITDescriptorImpl<uint64_t>(all_entries); 277 else 278 return ReadJITDescriptorImpl<uint32_t>(all_entries); 279 } 280 281 template <typename ptr_t> 282 bool JITLoaderGDB::ReadJITDescriptorImpl(bool all_entries) { 283 if (m_jit_descriptor_addr == LLDB_INVALID_ADDRESS) 284 return false; 285 286 Log *log = GetLog(LLDBLog::JITLoader); 287 Target &target = m_process->GetTarget(); 288 ModuleList &module_list = target.GetImages(); 289 290 jit_descriptor<ptr_t> jit_desc; 291 const size_t jit_desc_size = sizeof(jit_desc); 292 Status error; 293 size_t bytes_read = m_process->ReadMemory(m_jit_descriptor_addr, &jit_desc, 294 jit_desc_size, error); 295 if (bytes_read != jit_desc_size || !error.Success()) { 296 LLDB_LOGF(log, "JITLoaderGDB::%s failed to read JIT descriptor", 297 __FUNCTION__); 298 return false; 299 } 300 301 jit_actions_t jit_action = (jit_actions_t)jit_desc.action_flag; 302 addr_t jit_relevant_entry = (addr_t)jit_desc.relevant_entry; 303 if (all_entries) { 304 jit_action = JIT_REGISTER_FN; 305 jit_relevant_entry = (addr_t)jit_desc.first_entry; 306 } 307 308 while (jit_relevant_entry != 0) { 309 jit_code_entry<ptr_t> jit_entry; 310 if (!ReadJITEntry(jit_relevant_entry, m_process, &jit_entry)) { 311 LLDB_LOGF(log, "JITLoaderGDB::%s failed to read JIT entry at 0x%" PRIx64, 312 __FUNCTION__, jit_relevant_entry); 313 return false; 314 } 315 316 const addr_t &symbolfile_addr = (addr_t)jit_entry.symfile_addr; 317 const size_t &symbolfile_size = (size_t)jit_entry.symfile_size; 318 ModuleSP module_sp; 319 320 if (jit_action == JIT_REGISTER_FN) { 321 LLDB_LOGF(log, 322 "JITLoaderGDB::%s registering JIT entry at 0x%" PRIx64 323 " (%" PRIu64 " bytes)", 324 __FUNCTION__, symbolfile_addr, (uint64_t)symbolfile_size); 325 326 char jit_name[64]; 327 snprintf(jit_name, 64, "JIT(0x%" PRIx64 ")", symbolfile_addr); 328 module_sp = m_process->ReadModuleFromMemory( 329 FileSpec(jit_name), symbolfile_addr, symbolfile_size); 330 331 if (module_sp && module_sp->GetObjectFile()) { 332 // Object formats (like ELF) have no representation for a JIT type. 333 // We will get it wrong, if we deduce it from the header. 334 module_sp->GetObjectFile()->SetType(ObjectFile::eTypeJIT); 335 336 // load the symbol table right away 337 module_sp->GetObjectFile()->GetSymtab(); 338 339 m_jit_objects.insert(std::make_pair(symbolfile_addr, module_sp)); 340 #ifdef LLDB_ENABLE_ALL 341 if (auto image_object_file = 342 llvm::dyn_cast<ObjectFileMachO>(module_sp->GetObjectFile())) { 343 const SectionList *section_list = image_object_file->GetSectionList(); 344 if (section_list) { 345 uint64_t vmaddrheuristic = 0; 346 uint64_t lower = (uint64_t)-1; 347 uint64_t upper = 0; 348 updateSectionLoadAddress(*section_list, target, symbolfile_addr, 349 symbolfile_size, vmaddrheuristic, lower, 350 upper); 351 } 352 } else 353 #endif // LLDB_ENABLE_ALL 354 { 355 bool changed = false; 356 module_sp->SetLoadAddress(target, 0, true, changed); 357 } 358 359 module_list.AppendIfNeeded(module_sp); 360 361 ModuleList module_list; 362 module_list.Append(module_sp); 363 target.ModulesDidLoad(module_list); 364 } else { 365 LLDB_LOGF(log, 366 "JITLoaderGDB::%s failed to load module for " 367 "JIT entry at 0x%" PRIx64, 368 __FUNCTION__, symbolfile_addr); 369 } 370 } else if (jit_action == JIT_UNREGISTER_FN) { 371 LLDB_LOGF(log, "JITLoaderGDB::%s unregistering JIT entry at 0x%" PRIx64, 372 __FUNCTION__, symbolfile_addr); 373 374 JITObjectMap::iterator it = m_jit_objects.find(symbolfile_addr); 375 if (it != m_jit_objects.end()) { 376 module_sp = it->second; 377 ObjectFile *image_object_file = module_sp->GetObjectFile(); 378 if (image_object_file) { 379 const SectionList *section_list = image_object_file->GetSectionList(); 380 if (section_list) { 381 const uint32_t num_sections = section_list->GetSize(); 382 for (uint32_t i = 0; i < num_sections; ++i) { 383 SectionSP section_sp(section_list->GetSectionAtIndex(i)); 384 if (section_sp) { 385 target.GetSectionLoadList().SetSectionUnloaded(section_sp); 386 } 387 } 388 } 389 } 390 module_list.Remove(module_sp); 391 m_jit_objects.erase(it); 392 } 393 } else if (jit_action == JIT_NOACTION) { 394 // Nothing to do 395 } else { 396 assert(false && "Unknown jit action"); 397 } 398 399 if (all_entries) 400 jit_relevant_entry = (addr_t)jit_entry.next_entry; 401 else 402 jit_relevant_entry = 0; 403 } 404 405 return false; // Continue Running. 406 } 407 408 // PluginInterface protocol 409 JITLoaderSP JITLoaderGDB::CreateInstance(Process *process, bool force) { 410 JITLoaderSP jit_loader_sp; 411 bool enable; 412 switch (GetGlobalPluginProperties().GetEnable()) { 413 case EnableJITLoaderGDB::eEnableJITLoaderGDBOn: 414 enable = true; 415 break; 416 case EnableJITLoaderGDB::eEnableJITLoaderGDBOff: 417 enable = false; 418 break; 419 case EnableJITLoaderGDB::eEnableJITLoaderGDBDefault: 420 ArchSpec arch(process->GetTarget().GetArchitecture()); 421 enable = arch.GetTriple().getVendor() != llvm::Triple::Apple; 422 break; 423 } 424 if (enable) 425 jit_loader_sp = std::make_shared<JITLoaderGDB>(process); 426 return jit_loader_sp; 427 } 428 429 llvm::StringRef JITLoaderGDB::GetPluginDescriptionStatic() { 430 return "JIT loader plug-in that watches for JIT events using the GDB " 431 "interface."; 432 } 433 434 void JITLoaderGDB::Initialize() { 435 PluginManager::RegisterPlugin(GetPluginNameStatic(), 436 GetPluginDescriptionStatic(), CreateInstance, 437 DebuggerInitialize); 438 } 439 440 void JITLoaderGDB::Terminate() { 441 PluginManager::UnregisterPlugin(CreateInstance); 442 } 443 444 bool JITLoaderGDB::DidSetJITBreakpoint() const { 445 return LLDB_BREAK_ID_IS_VALID(m_jit_break_id); 446 } 447 448 addr_t JITLoaderGDB::GetSymbolAddress(ModuleList &module_list, 449 ConstString name, 450 SymbolType symbol_type) const { 451 SymbolContextList target_symbols; 452 Target &target = m_process->GetTarget(); 453 454 module_list.FindSymbolsWithNameAndType(name, symbol_type, target_symbols); 455 if (target_symbols.IsEmpty()) 456 return LLDB_INVALID_ADDRESS; 457 458 SymbolContext sym_ctx; 459 target_symbols.GetContextAtIndex(0, sym_ctx); 460 461 const Address jit_descriptor_addr = sym_ctx.symbol->GetAddress(); 462 if (!jit_descriptor_addr.IsValid()) 463 return LLDB_INVALID_ADDRESS; 464 465 const addr_t jit_addr = jit_descriptor_addr.GetLoadAddress(&target); 466 return jit_addr; 467 } 468