Path: blob/main/contrib/llvm-project/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
39653 views
//===-- DynamicLoaderPOSIXDYLD.cpp ----------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78// Main header include9#include "DynamicLoaderPOSIXDYLD.h"1011#include "lldb/Breakpoint/BreakpointLocation.h"12#include "lldb/Core/Module.h"13#include "lldb/Core/ModuleSpec.h"14#include "lldb/Core/PluginManager.h"15#include "lldb/Core/Section.h"16#include "lldb/Symbol/Function.h"17#include "lldb/Symbol/ObjectFile.h"18#include "lldb/Target/MemoryRegionInfo.h"19#include "lldb/Target/Platform.h"20#include "lldb/Target/Target.h"21#include "lldb/Target/Thread.h"22#include "lldb/Target/ThreadPlanRunToAddress.h"23#include "lldb/Utility/LLDBLog.h"24#include "lldb/Utility/Log.h"25#include "lldb/Utility/ProcessInfo.h"2627#include <memory>28#include <optional>2930using namespace lldb;31using namespace lldb_private;3233LLDB_PLUGIN_DEFINE_ADV(DynamicLoaderPOSIXDYLD, DynamicLoaderPosixDYLD)3435void DynamicLoaderPOSIXDYLD::Initialize() {36PluginManager::RegisterPlugin(GetPluginNameStatic(),37GetPluginDescriptionStatic(), CreateInstance);38}3940void DynamicLoaderPOSIXDYLD::Terminate() {}4142llvm::StringRef DynamicLoaderPOSIXDYLD::GetPluginDescriptionStatic() {43return "Dynamic loader plug-in that watches for shared library "44"loads/unloads in POSIX processes.";45}4647DynamicLoader *DynamicLoaderPOSIXDYLD::CreateInstance(Process *process,48bool force) {49bool create = force;50if (!create) {51const llvm::Triple &triple_ref =52process->GetTarget().GetArchitecture().GetTriple();53if (triple_ref.getOS() == llvm::Triple::FreeBSD ||54triple_ref.getOS() == llvm::Triple::Linux ||55triple_ref.getOS() == llvm::Triple::NetBSD ||56triple_ref.getOS() == llvm::Triple::OpenBSD)57create = true;58}5960if (create)61return new DynamicLoaderPOSIXDYLD(process);62return nullptr;63}6465DynamicLoaderPOSIXDYLD::DynamicLoaderPOSIXDYLD(Process *process)66: DynamicLoader(process), m_rendezvous(process),67m_load_offset(LLDB_INVALID_ADDRESS), m_entry_point(LLDB_INVALID_ADDRESS),68m_auxv(), m_dyld_bid(LLDB_INVALID_BREAK_ID),69m_vdso_base(LLDB_INVALID_ADDRESS),70m_interpreter_base(LLDB_INVALID_ADDRESS), m_initial_modules_added(false) {71}7273DynamicLoaderPOSIXDYLD::~DynamicLoaderPOSIXDYLD() {74if (m_dyld_bid != LLDB_INVALID_BREAK_ID) {75m_process->GetTarget().RemoveBreakpointByID(m_dyld_bid);76m_dyld_bid = LLDB_INVALID_BREAK_ID;77}78}7980void DynamicLoaderPOSIXDYLD::DidAttach() {81Log *log = GetLog(LLDBLog::DynamicLoader);82LLDB_LOGF(log, "DynamicLoaderPOSIXDYLD::%s() pid %" PRIu64, __FUNCTION__,83m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID);84m_auxv = std::make_unique<AuxVector>(m_process->GetAuxvData());8586LLDB_LOGF(87log, "DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 " reloaded auxv data",88__FUNCTION__, m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID);8990ModuleSP executable_sp = GetTargetExecutable();91ResolveExecutableModule(executable_sp);92m_rendezvous.UpdateExecutablePath();9394// find the main process load offset95addr_t load_offset = ComputeLoadOffset();96LLDB_LOGF(log,97"DynamicLoaderPOSIXDYLD::%s pid %" PRIu6498" executable '%s', load_offset 0x%" PRIx64,99__FUNCTION__,100m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID,101executable_sp ? executable_sp->GetFileSpec().GetPath().c_str()102: "<null executable>",103load_offset);104105EvalSpecialModulesStatus();106107// if we dont have a load address we cant re-base108bool rebase_exec = load_offset != LLDB_INVALID_ADDRESS;109110// if we have a valid executable111if (executable_sp.get()) {112lldb_private::ObjectFile *obj = executable_sp->GetObjectFile();113if (obj) {114// don't rebase if the module already has a load address115Target &target = m_process->GetTarget();116Address addr = obj->GetImageInfoAddress(&target);117if (addr.GetLoadAddress(&target) != LLDB_INVALID_ADDRESS)118rebase_exec = false;119}120} else {121// no executable, nothing to re-base122rebase_exec = false;123}124125// if the target executable should be re-based126if (rebase_exec) {127ModuleList module_list;128129module_list.Append(executable_sp);130LLDB_LOGF(log,131"DynamicLoaderPOSIXDYLD::%s pid %" PRIu64132" added executable '%s' to module load list",133__FUNCTION__,134m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID,135executable_sp->GetFileSpec().GetPath().c_str());136137UpdateLoadedSections(executable_sp, LLDB_INVALID_ADDRESS, load_offset,138true);139140LoadAllCurrentModules();141142m_process->GetTarget().ModulesDidLoad(module_list);143if (log) {144LLDB_LOGF(log,145"DynamicLoaderPOSIXDYLD::%s told the target about the "146"modules that loaded:",147__FUNCTION__);148for (auto module_sp : module_list.Modules()) {149LLDB_LOGF(log, "-- [module] %s (pid %" PRIu64 ")",150module_sp ? module_sp->GetFileSpec().GetPath().c_str()151: "<null>",152m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID);153}154}155}156157if (executable_sp.get()) {158if (!SetRendezvousBreakpoint()) {159// If we cannot establish rendezvous breakpoint right now we'll try again160// at entry point.161ProbeEntry();162}163}164}165166void DynamicLoaderPOSIXDYLD::DidLaunch() {167Log *log = GetLog(LLDBLog::DynamicLoader);168LLDB_LOGF(log, "DynamicLoaderPOSIXDYLD::%s()", __FUNCTION__);169170ModuleSP executable;171addr_t load_offset;172173m_auxv = std::make_unique<AuxVector>(m_process->GetAuxvData());174175executable = GetTargetExecutable();176load_offset = ComputeLoadOffset();177EvalSpecialModulesStatus();178179if (executable.get() && load_offset != LLDB_INVALID_ADDRESS) {180ModuleList module_list;181module_list.Append(executable);182UpdateLoadedSections(executable, LLDB_INVALID_ADDRESS, load_offset, true);183184LLDB_LOGF(log, "DynamicLoaderPOSIXDYLD::%s about to call ProbeEntry()",185__FUNCTION__);186187if (!SetRendezvousBreakpoint()) {188// If we cannot establish rendezvous breakpoint right now we'll try again189// at entry point.190ProbeEntry();191}192193LoadVDSO();194m_process->GetTarget().ModulesDidLoad(module_list);195}196}197198Status DynamicLoaderPOSIXDYLD::CanLoadImage() { return Status(); }199200void DynamicLoaderPOSIXDYLD::UpdateLoadedSections(ModuleSP module,201addr_t link_map_addr,202addr_t base_addr,203bool base_addr_is_offset) {204m_loaded_modules[module] = link_map_addr;205UpdateLoadedSectionsCommon(module, base_addr, base_addr_is_offset);206}207208void DynamicLoaderPOSIXDYLD::UnloadSections(const ModuleSP module) {209m_loaded_modules.erase(module);210211UnloadSectionsCommon(module);212}213214void DynamicLoaderPOSIXDYLD::ProbeEntry() {215Log *log = GetLog(LLDBLog::DynamicLoader);216217// If we have a core file, we don't need any breakpoints.218if (IsCoreFile())219return;220221const addr_t entry = GetEntryPoint();222if (entry == LLDB_INVALID_ADDRESS) {223LLDB_LOGF(224log,225"DynamicLoaderPOSIXDYLD::%s pid %" PRIu64226" GetEntryPoint() returned no address, not setting entry breakpoint",227__FUNCTION__, m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID);228return;229}230231LLDB_LOGF(log,232"DynamicLoaderPOSIXDYLD::%s pid %" PRIu64233" GetEntryPoint() returned address 0x%" PRIx64234", setting entry breakpoint",235__FUNCTION__,236m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID, entry);237238if (m_process) {239Breakpoint *const entry_break =240m_process->GetTarget().CreateBreakpoint(entry, true, false).get();241entry_break->SetCallback(EntryBreakpointHit, this, true);242entry_break->SetBreakpointKind("shared-library-event");243244// Shoudn't hit this more than once.245entry_break->SetOneShot(true);246}247}248249// The runtime linker has run and initialized the rendezvous structure once the250// process has hit its entry point. When we hit the corresponding breakpoint251// we interrogate the rendezvous structure to get the load addresses of all252// dependent modules for the process. Similarly, we can discover the runtime253// linker function and setup a breakpoint to notify us of any dynamically254// loaded modules (via dlopen).255bool DynamicLoaderPOSIXDYLD::EntryBreakpointHit(256void *baton, StoppointCallbackContext *context, user_id_t break_id,257user_id_t break_loc_id) {258assert(baton && "null baton");259if (!baton)260return false;261262Log *log = GetLog(LLDBLog::DynamicLoader);263DynamicLoaderPOSIXDYLD *const dyld_instance =264static_cast<DynamicLoaderPOSIXDYLD *>(baton);265LLDB_LOGF(log, "DynamicLoaderPOSIXDYLD::%s called for pid %" PRIu64,266__FUNCTION__,267dyld_instance->m_process ? dyld_instance->m_process->GetID()268: LLDB_INVALID_PROCESS_ID);269270// Disable the breakpoint --- if a stop happens right after this, which we've271// seen on occasion, we don't want the breakpoint stepping thread-plan logic272// to show a breakpoint instruction at the disassembled entry point to the273// program. Disabling it prevents it. (One-shot is not enough - one-shot274// removal logic only happens after the breakpoint goes public, which wasn't275// happening in our scenario).276if (dyld_instance->m_process) {277BreakpointSP breakpoint_sp =278dyld_instance->m_process->GetTarget().GetBreakpointByID(break_id);279if (breakpoint_sp) {280LLDB_LOGF(log,281"DynamicLoaderPOSIXDYLD::%s pid %" PRIu64282" disabling breakpoint id %" PRIu64,283__FUNCTION__, dyld_instance->m_process->GetID(), break_id);284breakpoint_sp->SetEnabled(false);285} else {286LLDB_LOGF(log,287"DynamicLoaderPOSIXDYLD::%s pid %" PRIu64288" failed to find breakpoint for breakpoint id %" PRIu64,289__FUNCTION__, dyld_instance->m_process->GetID(), break_id);290}291} else {292LLDB_LOGF(log,293"DynamicLoaderPOSIXDYLD::%s breakpoint id %" PRIu64294" no Process instance! Cannot disable breakpoint",295__FUNCTION__, break_id);296}297298dyld_instance->LoadAllCurrentModules();299dyld_instance->SetRendezvousBreakpoint();300return false; // Continue running.301}302303bool DynamicLoaderPOSIXDYLD::SetRendezvousBreakpoint() {304Log *log = GetLog(LLDBLog::DynamicLoader);305306// If we have a core file, we don't need any breakpoints.307if (IsCoreFile())308return false;309310if (m_dyld_bid != LLDB_INVALID_BREAK_ID) {311LLDB_LOG(log,312"Rendezvous breakpoint breakpoint id {0} for pid {1}"313"is already set.",314m_dyld_bid,315m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID);316return true;317}318319addr_t break_addr;320Target &target = m_process->GetTarget();321BreakpointSP dyld_break;322if (m_rendezvous.IsValid() && m_rendezvous.GetBreakAddress() != 0) {323break_addr = m_rendezvous.GetBreakAddress();324LLDB_LOG(log, "Setting rendezvous break address for pid {0} at {1:x}",325m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID,326break_addr);327dyld_break = target.CreateBreakpoint(break_addr, true, false);328} else {329LLDB_LOG(log, "Rendezvous structure is not set up yet. "330"Trying to locate rendezvous breakpoint in the interpreter "331"by symbol name.");332// Function names from different dynamic loaders that are known to be333// used as rendezvous between the loader and debuggers.334static std::vector<std::string> DebugStateCandidates{335"_dl_debug_state", "rtld_db_dlactivity", "__dl_rtld_db_dlactivity",336"r_debug_state", "_r_debug_state", "_rtld_debug_state",337};338339ModuleSP interpreter = LoadInterpreterModule();340FileSpecList containingModules;341if (interpreter)342containingModules.Append(interpreter->GetFileSpec());343else344containingModules.Append(345m_process->GetTarget().GetExecutableModulePointer()->GetFileSpec());346347dyld_break = target.CreateBreakpoint(348&containingModules, /*containingSourceFiles=*/nullptr,349DebugStateCandidates, eFunctionNameTypeFull, eLanguageTypeC,350/*m_offset=*/0,351/*skip_prologue=*/eLazyBoolNo,352/*internal=*/true,353/*request_hardware=*/false);354}355356if (dyld_break->GetNumResolvedLocations() != 1) {357LLDB_LOG(358log,359"Rendezvous breakpoint has abnormal number of"360" resolved locations ({0}) in pid {1}. It's supposed to be exactly 1.",361dyld_break->GetNumResolvedLocations(),362m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID);363364target.RemoveBreakpointByID(dyld_break->GetID());365return false;366}367368BreakpointLocationSP location = dyld_break->GetLocationAtIndex(0);369LLDB_LOG(log,370"Successfully set rendezvous breakpoint at address {0:x} "371"for pid {1}",372location->GetLoadAddress(),373m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID);374375dyld_break->SetCallback(RendezvousBreakpointHit, this, true);376dyld_break->SetBreakpointKind("shared-library-event");377m_dyld_bid = dyld_break->GetID();378return true;379}380381bool DynamicLoaderPOSIXDYLD::RendezvousBreakpointHit(382void *baton, StoppointCallbackContext *context, user_id_t break_id,383user_id_t break_loc_id) {384assert(baton && "null baton");385if (!baton)386return false;387388Log *log = GetLog(LLDBLog::DynamicLoader);389DynamicLoaderPOSIXDYLD *const dyld_instance =390static_cast<DynamicLoaderPOSIXDYLD *>(baton);391LLDB_LOGF(log, "DynamicLoaderPOSIXDYLD::%s called for pid %" PRIu64,392__FUNCTION__,393dyld_instance->m_process ? dyld_instance->m_process->GetID()394: LLDB_INVALID_PROCESS_ID);395396dyld_instance->RefreshModules();397398// Return true to stop the target, false to just let the target run.399const bool stop_when_images_change = dyld_instance->GetStopWhenImagesChange();400LLDB_LOGF(log,401"DynamicLoaderPOSIXDYLD::%s pid %" PRIu64402" stop_when_images_change=%s",403__FUNCTION__,404dyld_instance->m_process ? dyld_instance->m_process->GetID()405: LLDB_INVALID_PROCESS_ID,406stop_when_images_change ? "true" : "false");407return stop_when_images_change;408}409410void DynamicLoaderPOSIXDYLD::RefreshModules() {411if (!m_rendezvous.Resolve())412return;413414// The rendezvous class doesn't enumerate the main module, so track that415// ourselves here.416ModuleSP executable = GetTargetExecutable();417m_loaded_modules[executable] = m_rendezvous.GetLinkMapAddress();418419DYLDRendezvous::iterator I;420DYLDRendezvous::iterator E;421422ModuleList &loaded_modules = m_process->GetTarget().GetImages();423424if (m_rendezvous.ModulesDidLoad() || !m_initial_modules_added) {425ModuleList new_modules;426427// If this is the first time rendezvous breakpoint fires, we need428// to take care of adding all the initial modules reported by429// the loader. This is necessary to list ld-linux.so on Linux,430// and all DT_NEEDED entries on *BSD.431if (m_initial_modules_added) {432I = m_rendezvous.loaded_begin();433E = m_rendezvous.loaded_end();434} else {435I = m_rendezvous.begin();436E = m_rendezvous.end();437m_initial_modules_added = true;438}439for (; I != E; ++I) {440// Don't load a duplicate copy of ld.so if we have already loaded it441// earlier in LoadInterpreterModule. If we instead loaded then unloaded it442// later, the section information for ld.so would be removed. That443// information is required for placing breakpoints on Arm/Thumb systems.444if ((m_interpreter_module.lock() != nullptr) &&445(I->base_addr == m_interpreter_base))446continue;447448ModuleSP module_sp =449LoadModuleAtAddress(I->file_spec, I->link_addr, I->base_addr, true);450if (!module_sp.get())451continue;452453if (module_sp->GetObjectFile()->GetBaseAddress().GetLoadAddress(454&m_process->GetTarget()) == m_interpreter_base) {455ModuleSP interpreter_sp = m_interpreter_module.lock();456if (m_interpreter_module.lock() == nullptr) {457m_interpreter_module = module_sp;458} else if (module_sp == interpreter_sp) {459// Module already loaded.460continue;461}462}463464loaded_modules.AppendIfNeeded(module_sp);465new_modules.Append(module_sp);466}467m_process->GetTarget().ModulesDidLoad(new_modules);468}469470if (m_rendezvous.ModulesDidUnload()) {471ModuleList old_modules;472473E = m_rendezvous.unloaded_end();474for (I = m_rendezvous.unloaded_begin(); I != E; ++I) {475ModuleSpec module_spec{I->file_spec};476ModuleSP module_sp = loaded_modules.FindFirstModule(module_spec);477478if (module_sp.get()) {479old_modules.Append(module_sp);480UnloadSections(module_sp);481}482}483loaded_modules.Remove(old_modules);484m_process->GetTarget().ModulesDidUnload(old_modules, false);485}486}487488ThreadPlanSP489DynamicLoaderPOSIXDYLD::GetStepThroughTrampolinePlan(Thread &thread,490bool stop) {491ThreadPlanSP thread_plan_sp;492493StackFrame *frame = thread.GetStackFrameAtIndex(0).get();494const SymbolContext &context = frame->GetSymbolContext(eSymbolContextSymbol);495Symbol *sym = context.symbol;496497if (sym == nullptr || !sym->IsTrampoline())498return thread_plan_sp;499500ConstString sym_name = sym->GetMangled().GetName(Mangled::ePreferMangled);501if (!sym_name)502return thread_plan_sp;503504SymbolContextList target_symbols;505Target &target = thread.GetProcess()->GetTarget();506const ModuleList &images = target.GetImages();507508llvm::StringRef target_name = sym_name.GetStringRef();509// On AArch64, the trampoline name has a prefix (__AArch64ADRPThunk_ or510// __AArch64AbsLongThunk_) added to the function name. If we detect a511// trampoline with the prefix, we need to remove the prefix to find the512// function symbol.513if (target_name.consume_front("__AArch64ADRPThunk_") ||514target_name.consume_front("__AArch64AbsLongThunk_")) {515// An empty target name can happen for trampolines generated for516// section-referencing relocations.517if (!target_name.empty()) {518sym_name = ConstString(target_name);519}520}521images.FindSymbolsWithNameAndType(sym_name, eSymbolTypeCode, target_symbols);522if (!target_symbols.GetSize())523return thread_plan_sp;524525typedef std::vector<lldb::addr_t> AddressVector;526AddressVector addrs;527for (const SymbolContext &context : target_symbols) {528AddressRange range;529context.GetAddressRange(eSymbolContextEverything, 0, false, range);530lldb::addr_t addr = range.GetBaseAddress().GetLoadAddress(&target);531if (addr != LLDB_INVALID_ADDRESS)532addrs.push_back(addr);533}534535if (addrs.size() > 0) {536AddressVector::iterator start = addrs.begin();537AddressVector::iterator end = addrs.end();538539llvm::sort(start, end);540addrs.erase(std::unique(start, end), end);541thread_plan_sp =542std::make_shared<ThreadPlanRunToAddress>(thread, addrs, stop);543}544545return thread_plan_sp;546}547548void DynamicLoaderPOSIXDYLD::LoadVDSO() {549if (m_vdso_base == LLDB_INVALID_ADDRESS)550return;551552FileSpec file("[vdso]");553554MemoryRegionInfo info;555Status status = m_process->GetMemoryRegionInfo(m_vdso_base, info);556if (status.Fail()) {557Log *log = GetLog(LLDBLog::DynamicLoader);558LLDB_LOG(log, "Failed to get vdso region info: {0}", status);559return;560}561562if (ModuleSP module_sp = m_process->ReadModuleFromMemory(563file, m_vdso_base, info.GetRange().GetByteSize())) {564UpdateLoadedSections(module_sp, LLDB_INVALID_ADDRESS, m_vdso_base, false);565m_process->GetTarget().GetImages().AppendIfNeeded(module_sp);566}567}568569ModuleSP DynamicLoaderPOSIXDYLD::LoadInterpreterModule() {570if (m_interpreter_base == LLDB_INVALID_ADDRESS)571return nullptr;572573MemoryRegionInfo info;574Target &target = m_process->GetTarget();575Status status = m_process->GetMemoryRegionInfo(m_interpreter_base, info);576if (status.Fail() || info.GetMapped() != MemoryRegionInfo::eYes ||577info.GetName().IsEmpty()) {578Log *log = GetLog(LLDBLog::DynamicLoader);579LLDB_LOG(log, "Failed to get interpreter region info: {0}", status);580return nullptr;581}582583FileSpec file(info.GetName().GetCString());584ModuleSpec module_spec(file, target.GetArchitecture());585586// Don't notify that module is added here because its loading section587// addresses are not updated yet. We manually notify it below.588if (ModuleSP module_sp =589target.GetOrCreateModule(module_spec, /*notify=*/false)) {590UpdateLoadedSections(module_sp, LLDB_INVALID_ADDRESS, m_interpreter_base,591false);592// Manually notify that dynamic linker is loaded after updating load section593// addersses so that breakpoints can be resolved.594ModuleList module_list;595module_list.Append(module_sp);596target.ModulesDidLoad(module_list);597m_interpreter_module = module_sp;598return module_sp;599}600return nullptr;601}602603ModuleSP DynamicLoaderPOSIXDYLD::LoadModuleAtAddress(const FileSpec &file,604addr_t link_map_addr,605addr_t base_addr,606bool base_addr_is_offset) {607if (ModuleSP module_sp = DynamicLoader::LoadModuleAtAddress(608file, link_map_addr, base_addr, base_addr_is_offset))609return module_sp;610611// This works around an dynamic linker "bug" on android <= 23, where the612// dynamic linker would report the application name613// (e.g. com.example.myapplication) instead of the main process binary614// (/system/bin/app_process(32)). The logic is not sound in general (it615// assumes base_addr is the real address, even though it actually is a load616// bias), but it happens to work on android because app_process has a file617// address of zero.618// This should be removed after we drop support for android-23.619if (m_process->GetTarget().GetArchitecture().GetTriple().isAndroid()) {620MemoryRegionInfo memory_info;621Status error = m_process->GetMemoryRegionInfo(base_addr, memory_info);622if (error.Success() && memory_info.GetMapped() &&623memory_info.GetRange().GetRangeBase() == base_addr &&624!(memory_info.GetName().IsEmpty())) {625if (ModuleSP module_sp = DynamicLoader::LoadModuleAtAddress(626FileSpec(memory_info.GetName().GetStringRef()), link_map_addr,627base_addr, base_addr_is_offset))628return module_sp;629}630}631632return nullptr;633}634635void DynamicLoaderPOSIXDYLD::LoadAllCurrentModules() {636DYLDRendezvous::iterator I;637DYLDRendezvous::iterator E;638ModuleList module_list;639Log *log = GetLog(LLDBLog::DynamicLoader);640641LoadVDSO();642643if (!m_rendezvous.Resolve()) {644LLDB_LOGF(log,645"DynamicLoaderPOSIXDYLD::%s unable to resolve POSIX DYLD "646"rendezvous address",647__FUNCTION__);648return;649}650651// The rendezvous class doesn't enumerate the main module, so track that652// ourselves here.653ModuleSP executable = GetTargetExecutable();654m_loaded_modules[executable] = m_rendezvous.GetLinkMapAddress();655656std::vector<FileSpec> module_names;657for (I = m_rendezvous.begin(), E = m_rendezvous.end(); I != E; ++I)658module_names.push_back(I->file_spec);659m_process->PrefetchModuleSpecs(660module_names, m_process->GetTarget().GetArchitecture().GetTriple());661662for (I = m_rendezvous.begin(), E = m_rendezvous.end(); I != E; ++I) {663ModuleSP module_sp =664LoadModuleAtAddress(I->file_spec, I->link_addr, I->base_addr, true);665if (module_sp.get()) {666LLDB_LOG(log, "LoadAllCurrentModules loading module: {0}",667I->file_spec.GetFilename());668module_list.Append(module_sp);669} else {670Log *log = GetLog(LLDBLog::DynamicLoader);671LLDB_LOGF(672log,673"DynamicLoaderPOSIXDYLD::%s failed loading module %s at 0x%" PRIx64,674__FUNCTION__, I->file_spec.GetPath().c_str(), I->base_addr);675}676}677678m_process->GetTarget().ModulesDidLoad(module_list);679m_initial_modules_added = true;680}681682addr_t DynamicLoaderPOSIXDYLD::ComputeLoadOffset() {683addr_t virt_entry;684685if (m_load_offset != LLDB_INVALID_ADDRESS)686return m_load_offset;687688if ((virt_entry = GetEntryPoint()) == LLDB_INVALID_ADDRESS)689return LLDB_INVALID_ADDRESS;690691ModuleSP module = m_process->GetTarget().GetExecutableModule();692if (!module)693return LLDB_INVALID_ADDRESS;694695ObjectFile *exe = module->GetObjectFile();696if (!exe)697return LLDB_INVALID_ADDRESS;698699Address file_entry = exe->GetEntryPointAddress();700701if (!file_entry.IsValid())702return LLDB_INVALID_ADDRESS;703704m_load_offset = virt_entry - file_entry.GetFileAddress();705return m_load_offset;706}707708void DynamicLoaderPOSIXDYLD::EvalSpecialModulesStatus() {709if (std::optional<uint64_t> vdso_base =710m_auxv->GetAuxValue(AuxVector::AUXV_AT_SYSINFO_EHDR))711m_vdso_base = *vdso_base;712713if (std::optional<uint64_t> interpreter_base =714m_auxv->GetAuxValue(AuxVector::AUXV_AT_BASE))715m_interpreter_base = *interpreter_base;716}717718addr_t DynamicLoaderPOSIXDYLD::GetEntryPoint() {719if (m_entry_point != LLDB_INVALID_ADDRESS)720return m_entry_point;721722if (m_auxv == nullptr)723return LLDB_INVALID_ADDRESS;724725std::optional<uint64_t> entry_point =726m_auxv->GetAuxValue(AuxVector::AUXV_AT_ENTRY);727if (!entry_point)728return LLDB_INVALID_ADDRESS;729730m_entry_point = static_cast<addr_t>(*entry_point);731732const ArchSpec &arch = m_process->GetTarget().GetArchitecture();733734// On ppc64, the entry point is actually a descriptor. Dereference it.735if (arch.GetMachine() == llvm::Triple::ppc64)736m_entry_point = ReadUnsignedIntWithSizeInBytes(m_entry_point, 8);737738return m_entry_point;739}740741lldb::addr_t742DynamicLoaderPOSIXDYLD::GetThreadLocalData(const lldb::ModuleSP module_sp,743const lldb::ThreadSP thread,744lldb::addr_t tls_file_addr) {745Log *log = GetLog(LLDBLog::DynamicLoader);746auto it = m_loaded_modules.find(module_sp);747if (it == m_loaded_modules.end()) {748LLDB_LOGF(749log, "GetThreadLocalData error: module(%s) not found in loaded modules",750module_sp->GetObjectName().AsCString());751return LLDB_INVALID_ADDRESS;752}753754addr_t link_map = it->second;755if (link_map == LLDB_INVALID_ADDRESS || link_map == 0) {756LLDB_LOGF(log,757"GetThreadLocalData error: invalid link map address=0x%" PRIx64,758link_map);759return LLDB_INVALID_ADDRESS;760}761762const DYLDRendezvous::ThreadInfo &metadata = m_rendezvous.GetThreadInfo();763if (!metadata.valid) {764LLDB_LOGF(log,765"GetThreadLocalData error: fail to read thread info metadata");766return LLDB_INVALID_ADDRESS;767}768769LLDB_LOGF(log,770"GetThreadLocalData info: link_map=0x%" PRIx64771", thread info metadata: "772"modid_offset=0x%" PRIx32 ", dtv_offset=0x%" PRIx32773", tls_offset=0x%" PRIx32 ", dtv_slot_size=%" PRIx32 "\n",774link_map, metadata.modid_offset, metadata.dtv_offset,775metadata.tls_offset, metadata.dtv_slot_size);776777// Get the thread pointer.778addr_t tp = thread->GetThreadPointer();779if (tp == LLDB_INVALID_ADDRESS) {780LLDB_LOGF(log, "GetThreadLocalData error: fail to read thread pointer");781return LLDB_INVALID_ADDRESS;782}783784// Find the module's modid.785int modid_size = 4; // FIXME(spucci): This isn't right for big-endian 64-bit786int64_t modid = ReadUnsignedIntWithSizeInBytes(787link_map + metadata.modid_offset, modid_size);788if (modid == -1) {789LLDB_LOGF(log, "GetThreadLocalData error: fail to read modid");790return LLDB_INVALID_ADDRESS;791}792793// Lookup the DTV structure for this thread.794addr_t dtv_ptr = tp + metadata.dtv_offset;795addr_t dtv = ReadPointer(dtv_ptr);796if (dtv == LLDB_INVALID_ADDRESS) {797LLDB_LOGF(log, "GetThreadLocalData error: fail to read dtv");798return LLDB_INVALID_ADDRESS;799}800801// Find the TLS block for this module.802addr_t dtv_slot = dtv + metadata.dtv_slot_size * modid;803addr_t tls_block = ReadPointer(dtv_slot + metadata.tls_offset);804805LLDB_LOGF(log,806"DynamicLoaderPOSIXDYLD::Performed TLS lookup: "807"module=%s, link_map=0x%" PRIx64 ", tp=0x%" PRIx64808", modid=%" PRId64 ", tls_block=0x%" PRIx64 "\n",809module_sp->GetObjectName().AsCString(""), link_map, tp,810(int64_t)modid, tls_block);811812if (tls_block == LLDB_INVALID_ADDRESS) {813LLDB_LOGF(log, "GetThreadLocalData error: fail to read tls_block");814return LLDB_INVALID_ADDRESS;815} else816return tls_block + tls_file_addr;817}818819void DynamicLoaderPOSIXDYLD::ResolveExecutableModule(820lldb::ModuleSP &module_sp) {821Log *log = GetLog(LLDBLog::DynamicLoader);822823if (m_process == nullptr)824return;825826auto &target = m_process->GetTarget();827const auto platform_sp = target.GetPlatform();828829ProcessInstanceInfo process_info;830if (!m_process->GetProcessInfo(process_info)) {831LLDB_LOGF(log,832"DynamicLoaderPOSIXDYLD::%s - failed to get process info for "833"pid %" PRIu64,834__FUNCTION__, m_process->GetID());835return;836}837838LLDB_LOGF(839log, "DynamicLoaderPOSIXDYLD::%s - got executable by pid %" PRIu64 ": %s",840__FUNCTION__, m_process->GetID(),841process_info.GetExecutableFile().GetPath().c_str());842843ModuleSpec module_spec(process_info.GetExecutableFile(),844process_info.GetArchitecture());845if (module_sp && module_sp->MatchesModuleSpec(module_spec))846return;847848const auto executable_search_paths(Target::GetDefaultExecutableSearchPaths());849auto error = platform_sp->ResolveExecutable(850module_spec, module_sp,851!executable_search_paths.IsEmpty() ? &executable_search_paths : nullptr);852if (error.Fail()) {853StreamString stream;854module_spec.Dump(stream);855856LLDB_LOGF(log,857"DynamicLoaderPOSIXDYLD::%s - failed to resolve executable "858"with module spec \"%s\": %s",859__FUNCTION__, stream.GetData(), error.AsCString());860return;861}862863target.SetExecutableModule(module_sp, eLoadDependentsNo);864}865866bool DynamicLoaderPOSIXDYLD::AlwaysRelyOnEHUnwindInfo(867lldb_private::SymbolContext &sym_ctx) {868ModuleSP module_sp;869if (sym_ctx.symbol)870module_sp = sym_ctx.symbol->GetAddressRef().GetModule();871if (!module_sp && sym_ctx.function)872module_sp =873sym_ctx.function->GetAddressRange().GetBaseAddress().GetModule();874if (!module_sp)875return false;876877return module_sp->GetFileSpec().GetPath() == "[vdso]";878}879880bool DynamicLoaderPOSIXDYLD::IsCoreFile() const {881return !m_process->IsLiveDebugSession();882}883884885