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