1 //===-- DYLDRendezvous.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 "lldb/Core/Module.h" 10 #include "lldb/Symbol/ObjectFile.h" 11 #include "lldb/Symbol/Symbol.h" 12 #include "lldb/Symbol/SymbolContext.h" 13 #include "lldb/Target/Platform.h" 14 #include "lldb/Target/Process.h" 15 #include "lldb/Target/Target.h" 16 #include "lldb/Utility/ArchSpec.h" 17 #include "lldb/Utility/LLDBLog.h" 18 #include "lldb/Utility/Log.h" 19 #include "lldb/Utility/Status.h" 20 21 #include "llvm/Support/Path.h" 22 23 #include "DYLDRendezvous.h" 24 25 using namespace lldb; 26 using namespace lldb_private; 27 28 DYLDRendezvous::DYLDRendezvous(Process *process) 29 : m_process(process), m_rendezvous_addr(LLDB_INVALID_ADDRESS), 30 m_executable_interpreter(false), m_current(), m_previous(), 31 m_loaded_modules(), m_soentries(), m_added_soentries(), 32 m_removed_soentries() { 33 m_thread_info.valid = false; 34 UpdateExecutablePath(); 35 } 36 37 addr_t DYLDRendezvous::ResolveRendezvousAddress() { 38 Log *log = GetLog(LLDBLog::DynamicLoader); 39 addr_t info_location; 40 addr_t info_addr; 41 Status error; 42 43 if (!m_process) { 44 LLDB_LOGF(log, "%s null process provided", __FUNCTION__); 45 return LLDB_INVALID_ADDRESS; 46 } 47 48 // Try to get it from our process. This might be a remote process and might 49 // grab it via some remote-specific mechanism. 50 info_location = m_process->GetImageInfoAddress(); 51 LLDB_LOGF(log, "%s info_location = 0x%" PRIx64, __FUNCTION__, info_location); 52 53 // If the process fails to return an address, fall back to seeing if the 54 // local object file can help us find it. 55 if (info_location == LLDB_INVALID_ADDRESS) { 56 Target *target = &m_process->GetTarget(); 57 if (target) { 58 ObjectFile *obj_file = target->GetExecutableModule()->GetObjectFile(); 59 Address addr = obj_file->GetImageInfoAddress(target); 60 61 if (addr.IsValid()) { 62 info_location = addr.GetLoadAddress(target); 63 LLDB_LOGF(log, 64 "%s resolved via direct object file approach to 0x%" PRIx64, 65 __FUNCTION__, info_location); 66 } else { 67 const Symbol *_r_debug = 68 target->GetExecutableModule()->FindFirstSymbolWithNameAndType( 69 ConstString("_r_debug")); 70 if (_r_debug) { 71 info_addr = _r_debug->GetAddress().GetLoadAddress(target); 72 if (info_addr != LLDB_INVALID_ADDRESS) { 73 LLDB_LOGF(log, 74 "%s resolved by finding symbol '_r_debug' whose value is " 75 "0x%" PRIx64, 76 __FUNCTION__, info_addr); 77 m_executable_interpreter = true; 78 return info_addr; 79 } 80 } 81 LLDB_LOGF(log, 82 "%s FAILED - direct object file approach did not yield a " 83 "valid address", 84 __FUNCTION__); 85 } 86 } 87 } 88 89 if (info_location == LLDB_INVALID_ADDRESS) { 90 LLDB_LOGF(log, "%s FAILED - invalid info address", __FUNCTION__); 91 return LLDB_INVALID_ADDRESS; 92 } 93 94 LLDB_LOGF(log, "%s reading pointer (%" PRIu32 " bytes) from 0x%" PRIx64, 95 __FUNCTION__, m_process->GetAddressByteSize(), info_location); 96 97 info_addr = m_process->ReadPointerFromMemory(info_location, error); 98 if (error.Fail()) { 99 LLDB_LOGF(log, "%s FAILED - could not read from the info location: %s", 100 __FUNCTION__, error.AsCString()); 101 return LLDB_INVALID_ADDRESS; 102 } 103 104 if (info_addr == 0) { 105 LLDB_LOGF(log, 106 "%s FAILED - the rendezvous address contained at 0x%" PRIx64 107 " returned a null value", 108 __FUNCTION__, info_location); 109 return LLDB_INVALID_ADDRESS; 110 } 111 112 return info_addr; 113 } 114 115 void DYLDRendezvous::UpdateExecutablePath() { 116 if (m_process) { 117 Log *log = GetLog(LLDBLog::DynamicLoader); 118 Module *exe_mod = m_process->GetTarget().GetExecutableModulePointer(); 119 if (exe_mod) { 120 m_exe_file_spec = exe_mod->GetPlatformFileSpec(); 121 LLDB_LOGF(log, "DYLDRendezvous::%s exe module executable path set: '%s'", 122 __FUNCTION__, m_exe_file_spec.GetCString()); 123 } else { 124 LLDB_LOGF(log, 125 "DYLDRendezvous::%s cannot cache exe module path: null " 126 "executable module pointer", 127 __FUNCTION__); 128 } 129 } 130 } 131 132 bool DYLDRendezvous::Resolve() { 133 Log *log = GetLog(LLDBLog::DynamicLoader); 134 135 const size_t word_size = 4; 136 Rendezvous info; 137 size_t address_size; 138 size_t padding; 139 addr_t info_addr; 140 addr_t cursor; 141 142 address_size = m_process->GetAddressByteSize(); 143 padding = address_size - word_size; 144 LLDB_LOGF(log, 145 "DYLDRendezvous::%s address size: %" PRIu64 ", padding %" PRIu64, 146 __FUNCTION__, uint64_t(address_size), uint64_t(padding)); 147 148 if (m_rendezvous_addr == LLDB_INVALID_ADDRESS) 149 cursor = info_addr = 150 ResolveRendezvousAddress(); 151 else 152 cursor = info_addr = m_rendezvous_addr; 153 LLDB_LOGF(log, "DYLDRendezvous::%s cursor = 0x%" PRIx64, __FUNCTION__, 154 cursor); 155 156 if (cursor == LLDB_INVALID_ADDRESS) 157 return false; 158 159 if (!(cursor = ReadWord(cursor, &info.version, word_size))) 160 return false; 161 162 if (!(cursor = ReadPointer(cursor + padding, &info.map_addr))) 163 return false; 164 165 if (!(cursor = ReadPointer(cursor, &info.brk))) 166 return false; 167 168 if (!(cursor = ReadWord(cursor, &info.state, word_size))) 169 return false; 170 171 if (!(cursor = ReadPointer(cursor + padding, &info.ldbase))) 172 return false; 173 174 // The rendezvous was successfully read. Update our internal state. 175 m_rendezvous_addr = info_addr; 176 m_previous = m_current; 177 m_current = info; 178 179 if (m_current.map_addr == 0) 180 return false; 181 182 if (UpdateSOEntriesFromRemote()) 183 return true; 184 185 return UpdateSOEntries(); 186 } 187 188 bool DYLDRendezvous::IsValid() { 189 return m_rendezvous_addr != LLDB_INVALID_ADDRESS; 190 } 191 192 DYLDRendezvous::RendezvousAction DYLDRendezvous::GetAction() const { 193 switch (m_current.state) { 194 195 case eConsistent: 196 switch (m_previous.state) { 197 // When the previous and current states are consistent this is the first 198 // time we have been asked to update. Just take a snapshot of the 199 // currently loaded modules. 200 case eConsistent: 201 return eTakeSnapshot; 202 // If we are about to add or remove a shared object clear out the current 203 // state and take a snapshot of the currently loaded images. 204 case eAdd: 205 return eAddModules; 206 case eDelete: 207 return eRemoveModules; 208 } 209 break; 210 211 case eAdd: 212 case eDelete: 213 // Some versions of the android dynamic linker might send two 214 // notifications with state == eAdd back to back. Ignore them until we 215 // get an eConsistent notification. 216 if (!(m_previous.state == eConsistent || 217 (m_previous.state == eAdd && m_current.state == eDelete))) 218 return eNoAction; 219 220 return eTakeSnapshot; 221 } 222 223 return eNoAction; 224 } 225 226 bool DYLDRendezvous::UpdateSOEntriesFromRemote() { 227 auto action = GetAction(); 228 229 if (action == eNoAction) 230 return false; 231 232 if (action == eTakeSnapshot) { 233 m_added_soentries.clear(); 234 m_removed_soentries.clear(); 235 // We already have the loaded list from the previous update so no need to 236 // find all the modules again. 237 if (!m_loaded_modules.m_list.empty()) 238 return true; 239 } 240 241 llvm::Expected<LoadedModuleInfoList> module_list = 242 m_process->GetLoadedModuleList(); 243 if (!module_list) { 244 llvm::consumeError(module_list.takeError()); 245 return false; 246 } 247 248 switch (action) { 249 case eTakeSnapshot: 250 m_soentries.clear(); 251 return SaveSOEntriesFromRemote(*module_list); 252 case eAddModules: 253 return AddSOEntriesFromRemote(*module_list); 254 case eRemoveModules: 255 return RemoveSOEntriesFromRemote(*module_list); 256 case eNoAction: 257 return false; 258 } 259 llvm_unreachable("Fully covered switch above!"); 260 } 261 262 bool DYLDRendezvous::UpdateSOEntries() { 263 switch (GetAction()) { 264 case eTakeSnapshot: 265 m_soentries.clear(); 266 m_added_soentries.clear(); 267 m_removed_soentries.clear(); 268 return TakeSnapshot(m_soentries); 269 case eAddModules: 270 return AddSOEntries(); 271 case eRemoveModules: 272 return RemoveSOEntries(); 273 case eNoAction: 274 return false; 275 } 276 llvm_unreachable("Fully covered switch above!"); 277 } 278 279 bool DYLDRendezvous::FillSOEntryFromModuleInfo( 280 LoadedModuleInfoList::LoadedModuleInfo const &modInfo, SOEntry &entry) { 281 addr_t link_map_addr; 282 addr_t base_addr; 283 addr_t dyn_addr; 284 std::string name; 285 286 if (!modInfo.get_link_map(link_map_addr) || !modInfo.get_base(base_addr) || 287 !modInfo.get_dynamic(dyn_addr) || !modInfo.get_name(name)) 288 return false; 289 290 entry.link_addr = link_map_addr; 291 entry.base_addr = base_addr; 292 entry.dyn_addr = dyn_addr; 293 294 entry.file_spec.SetFile(name, FileSpec::Style::native); 295 296 UpdateBaseAddrIfNecessary(entry, name); 297 298 // not needed if we're using ModuleInfos 299 entry.next = 0; 300 entry.prev = 0; 301 entry.path_addr = 0; 302 303 return true; 304 } 305 306 bool DYLDRendezvous::SaveSOEntriesFromRemote( 307 const LoadedModuleInfoList &module_list) { 308 for (auto const &modInfo : module_list.m_list) { 309 SOEntry entry; 310 if (!FillSOEntryFromModuleInfo(modInfo, entry)) 311 return false; 312 313 // Only add shared libraries and not the executable. 314 if (!SOEntryIsMainExecutable(entry)) { 315 UpdateFileSpecIfNecessary(entry); 316 m_soentries.push_back(entry); 317 } 318 } 319 320 m_loaded_modules = module_list; 321 return true; 322 } 323 324 bool DYLDRendezvous::AddSOEntriesFromRemote( 325 const LoadedModuleInfoList &module_list) { 326 for (auto const &modInfo : module_list.m_list) { 327 bool found = false; 328 for (auto const &existing : m_loaded_modules.m_list) { 329 if (modInfo == existing) { 330 found = true; 331 break; 332 } 333 } 334 335 if (found) 336 continue; 337 338 SOEntry entry; 339 if (!FillSOEntryFromModuleInfo(modInfo, entry)) 340 return false; 341 342 // Only add shared libraries and not the executable. 343 if (!SOEntryIsMainExecutable(entry)) { 344 UpdateFileSpecIfNecessary(entry); 345 m_soentries.push_back(entry); 346 m_added_soentries.push_back(entry); 347 } 348 } 349 350 m_loaded_modules = module_list; 351 return true; 352 } 353 354 bool DYLDRendezvous::RemoveSOEntriesFromRemote( 355 const LoadedModuleInfoList &module_list) { 356 for (auto const &existing : m_loaded_modules.m_list) { 357 bool found = false; 358 for (auto const &modInfo : module_list.m_list) { 359 if (modInfo == existing) { 360 found = true; 361 break; 362 } 363 } 364 365 if (found) 366 continue; 367 368 SOEntry entry; 369 if (!FillSOEntryFromModuleInfo(existing, entry)) 370 return false; 371 372 // Only add shared libraries and not the executable. 373 if (!SOEntryIsMainExecutable(entry)) { 374 auto pos = std::find(m_soentries.begin(), m_soentries.end(), entry); 375 if (pos == m_soentries.end()) 376 return false; 377 378 m_soentries.erase(pos); 379 m_removed_soentries.push_back(entry); 380 } 381 } 382 383 m_loaded_modules = module_list; 384 return true; 385 } 386 387 bool DYLDRendezvous::AddSOEntries() { 388 SOEntry entry; 389 iterator pos; 390 391 assert(m_previous.state == eAdd); 392 393 if (m_current.map_addr == 0) 394 return false; 395 396 for (addr_t cursor = m_current.map_addr; cursor != 0; cursor = entry.next) { 397 if (!ReadSOEntryFromMemory(cursor, entry)) 398 return false; 399 400 // Only add shared libraries and not the executable. 401 if (SOEntryIsMainExecutable(entry)) 402 continue; 403 404 UpdateFileSpecIfNecessary(entry); 405 406 pos = std::find(m_soentries.begin(), m_soentries.end(), entry); 407 if (pos == m_soentries.end()) { 408 m_soentries.push_back(entry); 409 m_added_soentries.push_back(entry); 410 } 411 } 412 413 return true; 414 } 415 416 bool DYLDRendezvous::RemoveSOEntries() { 417 SOEntryList entry_list; 418 iterator pos; 419 420 assert(m_previous.state == eDelete); 421 422 if (!TakeSnapshot(entry_list)) 423 return false; 424 425 for (iterator I = begin(); I != end(); ++I) { 426 pos = std::find(entry_list.begin(), entry_list.end(), *I); 427 if (pos == entry_list.end()) 428 m_removed_soentries.push_back(*I); 429 } 430 431 m_soentries = entry_list; 432 return true; 433 } 434 435 bool DYLDRendezvous::SOEntryIsMainExecutable(const SOEntry &entry) { 436 // On some systes the executable is indicated by an empty path in the entry. 437 // On others it is the full path to the executable. 438 439 auto triple = m_process->GetTarget().GetArchitecture().GetTriple(); 440 switch (triple.getOS()) { 441 case llvm::Triple::FreeBSD: 442 case llvm::Triple::NetBSD: 443 return entry.file_spec == m_exe_file_spec; 444 case llvm::Triple::Linux: 445 if (triple.isAndroid()) 446 return entry.file_spec == m_exe_file_spec; 447 // If we are debugging ld.so, then all SOEntries should be treated as 448 // libraries, including the "main" one (denoted by an empty string). 449 if (!entry.file_spec && m_executable_interpreter) 450 return false; 451 return !entry.file_spec; 452 default: 453 return false; 454 } 455 } 456 457 bool DYLDRendezvous::TakeSnapshot(SOEntryList &entry_list) { 458 SOEntry entry; 459 460 if (m_current.map_addr == 0) 461 return false; 462 463 // Clear previous entries since we are about to obtain an up to date list. 464 entry_list.clear(); 465 466 for (addr_t cursor = m_current.map_addr; cursor != 0; cursor = entry.next) { 467 if (!ReadSOEntryFromMemory(cursor, entry)) 468 return false; 469 470 // Only add shared libraries and not the executable. 471 if (SOEntryIsMainExecutable(entry)) 472 continue; 473 474 UpdateFileSpecIfNecessary(entry); 475 476 entry_list.push_back(entry); 477 } 478 479 return true; 480 } 481 482 addr_t DYLDRendezvous::ReadWord(addr_t addr, uint64_t *dst, size_t size) { 483 Status error; 484 485 *dst = m_process->ReadUnsignedIntegerFromMemory(addr, size, 0, error); 486 if (error.Fail()) 487 return 0; 488 489 return addr + size; 490 } 491 492 addr_t DYLDRendezvous::ReadPointer(addr_t addr, addr_t *dst) { 493 Status error; 494 495 *dst = m_process->ReadPointerFromMemory(addr, error); 496 if (error.Fail()) 497 return 0; 498 499 return addr + m_process->GetAddressByteSize(); 500 } 501 502 std::string DYLDRendezvous::ReadStringFromMemory(addr_t addr) { 503 std::string str; 504 Status error; 505 506 if (addr == LLDB_INVALID_ADDRESS) 507 return std::string(); 508 509 m_process->ReadCStringFromMemory(addr, str, error); 510 511 return str; 512 } 513 514 // Returns true if the load bias reported by the linker is incorrect for the 515 // given entry. This function is used to handle cases where we want to work 516 // around a bug in the system linker. 517 static bool isLoadBiasIncorrect(Target &target, const std::string &file_path) { 518 // On Android L (API 21, 22) the load address of the "/system/bin/linker" 519 // isn't filled in correctly. 520 unsigned os_major = target.GetPlatform()->GetOSVersion().getMajor(); 521 return target.GetArchitecture().GetTriple().isAndroid() && 522 (os_major == 21 || os_major == 22) && 523 (file_path == "/system/bin/linker" || 524 file_path == "/system/bin/linker64"); 525 } 526 527 void DYLDRendezvous::UpdateBaseAddrIfNecessary(SOEntry &entry, 528 std::string const &file_path) { 529 // If the load bias reported by the linker is incorrect then fetch the load 530 // address of the file from the proc file system. 531 if (isLoadBiasIncorrect(m_process->GetTarget(), file_path)) { 532 lldb::addr_t load_addr = LLDB_INVALID_ADDRESS; 533 bool is_loaded = false; 534 Status error = 535 m_process->GetFileLoadAddress(entry.file_spec, is_loaded, load_addr); 536 if (error.Success() && is_loaded) 537 entry.base_addr = load_addr; 538 } 539 } 540 541 void DYLDRendezvous::UpdateFileSpecIfNecessary(SOEntry &entry) { 542 // Updates filename if empty. It is useful while debugging ld.so, 543 // when the link map returns empty string for the main executable. 544 if (!entry.file_spec) { 545 MemoryRegionInfo region; 546 Status region_status = 547 m_process->GetMemoryRegionInfo(entry.dyn_addr, region); 548 if (!region.GetName().IsEmpty()) 549 entry.file_spec.SetFile(region.GetName().AsCString(), 550 FileSpec::Style::native); 551 } 552 } 553 554 bool DYLDRendezvous::ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry) { 555 entry.clear(); 556 557 entry.link_addr = addr; 558 559 if (!(addr = ReadPointer(addr, &entry.base_addr))) 560 return false; 561 562 // mips adds an extra load offset field to the link map struct on FreeBSD and 563 // NetBSD (need to validate other OSes). 564 // http://svnweb.freebsd.org/base/head/sys/sys/link_elf.h?revision=217153&view=markup#l57 565 const ArchSpec &arch = m_process->GetTarget().GetArchitecture(); 566 if ((arch.GetTriple().getOS() == llvm::Triple::FreeBSD || 567 arch.GetTriple().getOS() == llvm::Triple::NetBSD) && 568 arch.IsMIPS()) { 569 addr_t mips_l_offs; 570 if (!(addr = ReadPointer(addr, &mips_l_offs))) 571 return false; 572 if (mips_l_offs != 0 && mips_l_offs != entry.base_addr) 573 return false; 574 } 575 576 if (!(addr = ReadPointer(addr, &entry.path_addr))) 577 return false; 578 579 if (!(addr = ReadPointer(addr, &entry.dyn_addr))) 580 return false; 581 582 if (!(addr = ReadPointer(addr, &entry.next))) 583 return false; 584 585 if (!(addr = ReadPointer(addr, &entry.prev))) 586 return false; 587 588 std::string file_path = ReadStringFromMemory(entry.path_addr); 589 entry.file_spec.SetFile(file_path, FileSpec::Style::native); 590 591 UpdateBaseAddrIfNecessary(entry, file_path); 592 593 return true; 594 } 595 596 bool DYLDRendezvous::FindMetadata(const char *name, PThreadField field, 597 uint32_t &value) { 598 Target &target = m_process->GetTarget(); 599 600 SymbolContextList list; 601 target.GetImages().FindSymbolsWithNameAndType(ConstString(name), 602 eSymbolTypeAny, list); 603 if (list.IsEmpty()) 604 return false; 605 606 Address address = list[0].symbol->GetAddress(); 607 addr_t addr = address.GetLoadAddress(&target); 608 if (addr == LLDB_INVALID_ADDRESS) 609 return false; 610 611 Status error; 612 value = (uint32_t)m_process->ReadUnsignedIntegerFromMemory( 613 addr + field * sizeof(uint32_t), sizeof(uint32_t), 0, error); 614 if (error.Fail()) 615 return false; 616 617 if (field == eSize) 618 value /= 8; // convert bits to bytes 619 620 return true; 621 } 622 623 const DYLDRendezvous::ThreadInfo &DYLDRendezvous::GetThreadInfo() { 624 if (!m_thread_info.valid) { 625 bool ok = true; 626 627 ok &= FindMetadata("_thread_db_pthread_dtvp", eOffset, 628 m_thread_info.dtv_offset); 629 ok &= 630 FindMetadata("_thread_db_dtv_dtv", eSize, m_thread_info.dtv_slot_size); 631 ok &= FindMetadata("_thread_db_link_map_l_tls_modid", eOffset, 632 m_thread_info.modid_offset); 633 ok &= FindMetadata("_thread_db_dtv_t_pointer_val", eOffset, 634 m_thread_info.tls_offset); 635 636 if (ok) 637 m_thread_info.valid = true; 638 } 639 640 return m_thread_info; 641 } 642 643 void DYLDRendezvous::DumpToLog(Log *log) const { 644 int state = GetState(); 645 646 if (!log) 647 return; 648 649 log->PutCString("DYLDRendezvous:"); 650 LLDB_LOGF(log, " Address: %" PRIx64, GetRendezvousAddress()); 651 LLDB_LOGF(log, " Version: %" PRIu64, GetVersion()); 652 LLDB_LOGF(log, " Link : %" PRIx64, GetLinkMapAddress()); 653 LLDB_LOGF(log, " Break : %" PRIx64, GetBreakAddress()); 654 LLDB_LOGF(log, " LDBase : %" PRIx64, GetLDBase()); 655 LLDB_LOGF(log, " State : %s", 656 (state == eConsistent) 657 ? "consistent" 658 : (state == eAdd) ? "add" 659 : (state == eDelete) ? "delete" : "unknown"); 660 661 iterator I = begin(); 662 iterator E = end(); 663 664 if (I != E) 665 log->PutCString("DYLDRendezvous SOEntries:"); 666 667 for (int i = 1; I != E; ++I, ++i) { 668 LLDB_LOGF(log, "\n SOEntry [%d] %s", i, I->file_spec.GetCString()); 669 LLDB_LOGF(log, " Base : %" PRIx64, I->base_addr); 670 LLDB_LOGF(log, " Path : %" PRIx64, I->path_addr); 671 LLDB_LOGF(log, " Dyn : %" PRIx64, I->dyn_addr); 672 LLDB_LOGF(log, " Next : %" PRIx64, I->next); 673 LLDB_LOGF(log, " Prev : %" PRIx64, I->prev); 674 } 675 } 676