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