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