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