180814287SRaphael Isemann //===-- DynamicLoaderPOSIXDYLD.cpp ----------------------------------------===//
29ed5b49cSJohnny Chen //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
69ed5b49cSJohnny Chen //
79ed5b49cSJohnny Chen //===----------------------------------------------------------------------===//
89ed5b49cSJohnny Chen 
9c7f76104SPavel Labath // Main header include
10c7f76104SPavel Labath #include "DynamicLoaderPOSIXDYLD.h"
11c7f76104SPavel Labath 
12b9c1b51eSKate Stone #include "lldb/Breakpoint/BreakpointLocation.h"
131f746071SGreg Clayton #include "lldb/Core/Module.h"
141f746071SGreg Clayton #include "lldb/Core/ModuleSpec.h"
15b9c1b51eSKate Stone #include "lldb/Core/PluginManager.h"
161f746071SGreg Clayton #include "lldb/Core/Section.h"
17b9c1b51eSKate Stone #include "lldb/Symbol/Function.h"
181f746071SGreg Clayton #include "lldb/Symbol/ObjectFile.h"
19df1a0d11SPavel Labath #include "lldb/Target/MemoryRegionInfo.h"
20b9c1b51eSKate Stone #include "lldb/Target/Platform.h"
219ed5b49cSJohnny Chen #include "lldb/Target/Target.h"
229ed5b49cSJohnny Chen #include "lldb/Target/Thread.h"
239ed5b49cSJohnny Chen #include "lldb/Target/ThreadPlanRunToAddress.h"
24c34698a8SPavel Labath #include "lldb/Utility/LLDBLog.h"
256f9e6901SZachary Turner #include "lldb/Utility/Log.h"
26805e7106SZachary Turner #include "lldb/Utility/ProcessInfo.h"
279ed5b49cSJohnny Chen 
28796ac80bSJonas Devlieghere #include <memory>
299ed5b49cSJohnny Chen 
309ed5b49cSJohnny Chen using namespace lldb;
319ed5b49cSJohnny Chen using namespace lldb_private;
329ed5b49cSJohnny Chen 
LLDB_PLUGIN_DEFINE_ADV(DynamicLoaderPOSIXDYLD,DynamicLoaderPosixDYLD)33ccad1948SJonas Devlieghere LLDB_PLUGIN_DEFINE_ADV(DynamicLoaderPOSIXDYLD, DynamicLoaderPosixDYLD)
34fbb4d1e4SJonas Devlieghere 
35b9c1b51eSKate Stone void DynamicLoaderPOSIXDYLD::Initialize() {
369ed5b49cSJohnny Chen   PluginManager::RegisterPlugin(GetPluginNameStatic(),
37b9c1b51eSKate Stone                                 GetPluginDescriptionStatic(), CreateInstance);
389ed5b49cSJohnny Chen }
399ed5b49cSJohnny Chen 
Terminate()40b9c1b51eSKate Stone void DynamicLoaderPOSIXDYLD::Terminate() {}
419ed5b49cSJohnny Chen 
GetPluginDescriptionStatic()426fa1b4ffSPavel Labath llvm::StringRef DynamicLoaderPOSIXDYLD::GetPluginDescriptionStatic() {
439ed5b49cSJohnny Chen   return "Dynamic loader plug-in that watches for shared library "
449ed5b49cSJohnny Chen          "loads/unloads in POSIX processes.";
459ed5b49cSJohnny Chen }
469ed5b49cSJohnny Chen 
CreateInstance(Process * process,bool force)47b9c1b51eSKate Stone DynamicLoader *DynamicLoaderPOSIXDYLD::CreateInstance(Process *process,
48b9c1b51eSKate Stone                                                       bool force) {
499ed5b49cSJohnny Chen   bool create = force;
50b9c1b51eSKate Stone   if (!create) {
51b9c1b51eSKate Stone     const llvm::Triple &triple_ref =
52b9c1b51eSKate Stone         process->GetTarget().GetArchitecture().GetTriple();
53a1e3d086SKamil Rytarowski     if (triple_ref.getOS() == llvm::Triple::FreeBSD ||
54a1e3d086SKamil Rytarowski         triple_ref.getOS() == llvm::Triple::Linux ||
55a1e3d086SKamil Rytarowski         triple_ref.getOS() == llvm::Triple::NetBSD)
569ed5b49cSJohnny Chen       create = true;
579ed5b49cSJohnny Chen   }
589ed5b49cSJohnny Chen 
599ed5b49cSJohnny Chen   if (create)
609ed5b49cSJohnny Chen     return new DynamicLoaderPOSIXDYLD(process);
61248a1305SKonrad Kleine   return nullptr;
629ed5b49cSJohnny Chen }
639ed5b49cSJohnny Chen 
DynamicLoaderPOSIXDYLD(Process * process)649ed5b49cSJohnny Chen DynamicLoaderPOSIXDYLD::DynamicLoaderPOSIXDYLD(Process *process)
65b9c1b51eSKate Stone     : DynamicLoader(process), m_rendezvous(process),
66b9c1b51eSKate Stone       m_load_offset(LLDB_INVALID_ADDRESS), m_entry_point(LLDB_INVALID_ADDRESS),
67b9c1b51eSKate Stone       m_auxv(), m_dyld_bid(LLDB_INVALID_BREAK_ID),
68b7386d99SEugene Zemtsov       m_vdso_base(LLDB_INVALID_ADDRESS),
698666b905SMichał Górny       m_interpreter_base(LLDB_INVALID_ADDRESS), m_initial_modules_added(false) {
708666b905SMichał Górny }
719ed5b49cSJohnny Chen 
~DynamicLoaderPOSIXDYLD()72b9c1b51eSKate Stone DynamicLoaderPOSIXDYLD::~DynamicLoaderPOSIXDYLD() {
73b9c1b51eSKate Stone   if (m_dyld_bid != LLDB_INVALID_BREAK_ID) {
74c87e752bSMichael Sartain     m_process->GetTarget().RemoveBreakpointByID(m_dyld_bid);
75c87e752bSMichael Sartain     m_dyld_bid = LLDB_INVALID_BREAK_ID;
76c87e752bSMichael Sartain   }
779ed5b49cSJohnny Chen }
789ed5b49cSJohnny Chen 
DidAttach()79b9c1b51eSKate Stone void DynamicLoaderPOSIXDYLD::DidAttach() {
80a007a6d8SPavel Labath   Log *log = GetLog(LLDBLog::DynamicLoader);
8163e5fb76SJonas Devlieghere   LLDB_LOGF(log, "DynamicLoaderPOSIXDYLD::%s() pid %" PRIu64, __FUNCTION__,
82b9c1b51eSKate Stone             m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID);
83a8f3ae7cSJonas Devlieghere   m_auxv = std::make_unique<AuxVector>(m_process->GetAuxvData());
84c82f650aSTodd Fiala 
8563e5fb76SJonas Devlieghere   LLDB_LOGF(
8663e5fb76SJonas Devlieghere       log, "DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 " reloaded auxv data",
8763e5fb76SJonas Devlieghere       __FUNCTION__, m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID);
889ed5b49cSJohnny Chen 
890ddd41cdSOleksiy Vyalov   ModuleSP executable_sp = GetTargetExecutable();
906474721cSOleksiy Vyalov   ResolveExecutableModule(executable_sp);
91dbfdb139SMichał Górny   m_rendezvous.UpdateExecutablePath();
920ddd41cdSOleksiy Vyalov 
93c0c83851SAidan Dodds   // find the main process load offset
940ddd41cdSOleksiy Vyalov   addr_t load_offset = ComputeLoadOffset();
9563e5fb76SJonas Devlieghere   LLDB_LOGF(log,
9663e5fb76SJonas Devlieghere             "DynamicLoaderPOSIXDYLD::%s pid %" PRIu64
97b9c1b51eSKate Stone             " executable '%s', load_offset 0x%" PRIx64,
98b9c1b51eSKate Stone             __FUNCTION__,
99b9c1b51eSKate Stone             m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID,
100b9c1b51eSKate Stone             executable_sp ? executable_sp->GetFileSpec().GetPath().c_str()
101b9c1b51eSKate Stone                           : "<null executable>",
102b9c1b51eSKate Stone             load_offset);
1039ed5b49cSJohnny Chen 
104b7386d99SEugene Zemtsov   EvalSpecialModulesStatus();
105f546b411SRavitheja Addepally 
106c0c83851SAidan Dodds   // if we dont have a load address we cant re-base
107a6682a41SJonas Devlieghere   bool rebase_exec = load_offset != LLDB_INVALID_ADDRESS;
108c82f650aSTodd Fiala 
109c0c83851SAidan Dodds   // if we have a valid executable
110b9c1b51eSKate Stone   if (executable_sp.get()) {
111c0c83851SAidan Dodds     lldb_private::ObjectFile *obj = executable_sp->GetObjectFile();
112b9c1b51eSKate Stone     if (obj) {
113c0c83851SAidan Dodds       // don't rebase if the module already has a load address
114c0c83851SAidan Dodds       Target &target = m_process->GetTarget();
115c0c83851SAidan Dodds       Address addr = obj->GetImageInfoAddress(&target);
116c0c83851SAidan Dodds       if (addr.GetLoadAddress(&target) != LLDB_INVALID_ADDRESS)
117c0c83851SAidan Dodds         rebase_exec = false;
118c0c83851SAidan Dodds     }
119b9c1b51eSKate Stone   } else {
120c0c83851SAidan Dodds     // no executable, nothing to re-base
121c0c83851SAidan Dodds     rebase_exec = false;
122c0c83851SAidan Dodds   }
123c0c83851SAidan Dodds 
124c0c83851SAidan Dodds   // if the target executable should be re-based
125b9c1b51eSKate Stone   if (rebase_exec) {
1269ed5b49cSJohnny Chen     ModuleList module_list;
127c82f650aSTodd Fiala 
128c82f650aSTodd Fiala     module_list.Append(executable_sp);
12963e5fb76SJonas Devlieghere     LLDB_LOGF(log,
13063e5fb76SJonas Devlieghere               "DynamicLoaderPOSIXDYLD::%s pid %" PRIu64
131b9c1b51eSKate Stone               " added executable '%s' to module load list",
132c82f650aSTodd Fiala               __FUNCTION__,
133c82f650aSTodd Fiala               m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID,
134c82f650aSTodd Fiala               executable_sp->GetFileSpec().GetPath().c_str());
135c82f650aSTodd Fiala 
136b9c1b51eSKate Stone     UpdateLoadedSections(executable_sp, LLDB_INVALID_ADDRESS, load_offset,
137b9c1b51eSKate Stone                          true);
138bc5353a8STodd Fiala 
1399ed5b49cSJohnny Chen     LoadAllCurrentModules();
140bc5353a8STodd Fiala 
1419ed5b49cSJohnny Chen     m_process->GetTarget().ModulesDidLoad(module_list);
142b9c1b51eSKate Stone     if (log) {
14363e5fb76SJonas Devlieghere       LLDB_LOGF(log,
14463e5fb76SJonas Devlieghere                 "DynamicLoaderPOSIXDYLD::%s told the target about the "
145b9c1b51eSKate Stone                 "modules that loaded:",
146b9c1b51eSKate Stone                 __FUNCTION__);
147b9c1b51eSKate Stone       for (auto module_sp : module_list.Modules()) {
14863e5fb76SJonas Devlieghere         LLDB_LOGF(log, "-- [module] %s (pid %" PRIu64 ")",
149b9c1b51eSKate Stone                   module_sp ? module_sp->GetFileSpec().GetPath().c_str()
150b9c1b51eSKate Stone                             : "<null>",
151c82f650aSTodd Fiala                   m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID);
152c82f650aSTodd Fiala       }
153c82f650aSTodd Fiala     }
1549ed5b49cSJohnny Chen   }
1555659b36cSAntonio Afonso 
1565659b36cSAntonio Afonso   if (executable_sp.get()) {
1575659b36cSAntonio Afonso     if (!SetRendezvousBreakpoint()) {
1585659b36cSAntonio Afonso       // If we cannot establish rendezvous breakpoint right now we'll try again
1595659b36cSAntonio Afonso       // at entry point.
1605659b36cSAntonio Afonso       ProbeEntry();
1615659b36cSAntonio Afonso     }
1625659b36cSAntonio Afonso   }
1639ed5b49cSJohnny Chen }
1649ed5b49cSJohnny Chen 
DidLaunch()165b9c1b51eSKate Stone void DynamicLoaderPOSIXDYLD::DidLaunch() {
166a007a6d8SPavel Labath   Log *log = GetLog(LLDBLog::DynamicLoader);
16763e5fb76SJonas Devlieghere   LLDB_LOGF(log, "DynamicLoaderPOSIXDYLD::%s()", __FUNCTION__);
168952bccd2STodd Fiala 
1699ed5b49cSJohnny Chen   ModuleSP executable;
1709ed5b49cSJohnny Chen   addr_t load_offset;
1719ed5b49cSJohnny Chen 
172a8f3ae7cSJonas Devlieghere   m_auxv = std::make_unique<AuxVector>(m_process->GetAuxvData());
1739ed5b49cSJohnny Chen 
1743041286fSMatt Kopec   executable = GetTargetExecutable();
1759ed5b49cSJohnny Chen   load_offset = ComputeLoadOffset();
176b7386d99SEugene Zemtsov   EvalSpecialModulesStatus();
1779ed5b49cSJohnny Chen 
178b9c1b51eSKate Stone   if (executable.get() && load_offset != LLDB_INVALID_ADDRESS) {
1799ed5b49cSJohnny Chen     ModuleList module_list;
1809ed5b49cSJohnny Chen     module_list.Append(executable);
18142ecef3bSTamas Berghammer     UpdateLoadedSections(executable, LLDB_INVALID_ADDRESS, load_offset, true);
182952bccd2STodd Fiala 
18363e5fb76SJonas Devlieghere     LLDB_LOGF(log, "DynamicLoaderPOSIXDYLD::%s about to call ProbeEntry()",
184b9c1b51eSKate Stone               __FUNCTION__);
185952bccd2STodd Fiala 
186b7386d99SEugene Zemtsov     if (!SetRendezvousBreakpoint()) {
18705097246SAdrian Prantl       // If we cannot establish rendezvous breakpoint right now we'll try again
18805097246SAdrian Prantl       // at entry point.
189b7386d99SEugene Zemtsov       ProbeEntry();
190b7386d99SEugene Zemtsov     }
191b7386d99SEugene Zemtsov 
192b7386d99SEugene Zemtsov     LoadVDSO();
1939ed5b49cSJohnny Chen     m_process->GetTarget().ModulesDidLoad(module_list);
1949ed5b49cSJohnny Chen   }
1959ed5b49cSJohnny Chen }
1969ed5b49cSJohnny Chen 
CanLoadImage()19797206d57SZachary Turner Status DynamicLoaderPOSIXDYLD::CanLoadImage() { return Status(); }
1989ed5b49cSJohnny Chen 
UpdateLoadedSections(ModuleSP module,addr_t link_map_addr,addr_t base_addr,bool base_addr_is_offset)199b9c1b51eSKate Stone void DynamicLoaderPOSIXDYLD::UpdateLoadedSections(ModuleSP module,
20042ecef3bSTamas Berghammer                                                   addr_t link_map_addr,
20142ecef3bSTamas Berghammer                                                   addr_t base_addr,
202b9c1b51eSKate Stone                                                   bool base_addr_is_offset) {
2030a558357SRichard Mitton   m_loaded_modules[module] = link_map_addr;
20442ecef3bSTamas Berghammer   UpdateLoadedSectionsCommon(module, base_addr, base_addr_is_offset);
2059ed5b49cSJohnny Chen }
2069ed5b49cSJohnny Chen 
UnloadSections(const ModuleSP module)207b9c1b51eSKate Stone void DynamicLoaderPOSIXDYLD::UnloadSections(const ModuleSP module) {
2080a558357SRichard Mitton   m_loaded_modules.erase(module);
2090a558357SRichard Mitton 
2109e02dacdSSteve Pucci   UnloadSectionsCommon(module);
211d678d30bSMatt Kopec }
212d678d30bSMatt Kopec 
ProbeEntry()213b9c1b51eSKate Stone void DynamicLoaderPOSIXDYLD::ProbeEntry() {
214a007a6d8SPavel Labath   Log *log = GetLog(LLDBLog::DynamicLoader);
2159ed5b49cSJohnny Chen 
216c82f650aSTodd Fiala   const addr_t entry = GetEntryPoint();
217b9c1b51eSKate Stone   if (entry == LLDB_INVALID_ADDRESS) {
21863e5fb76SJonas Devlieghere     LLDB_LOGF(
21963e5fb76SJonas Devlieghere         log,
220b9c1b51eSKate Stone         "DynamicLoaderPOSIXDYLD::%s pid %" PRIu64
221b9c1b51eSKate Stone         " GetEntryPoint() returned no address, not setting entry breakpoint",
22263e5fb76SJonas Devlieghere         __FUNCTION__, m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID);
2239ed5b49cSJohnny Chen     return;
224c82f650aSTodd Fiala   }
2259ed5b49cSJohnny Chen 
22663e5fb76SJonas Devlieghere   LLDB_LOGF(log,
22763e5fb76SJonas Devlieghere             "DynamicLoaderPOSIXDYLD::%s pid %" PRIu64
228b9c1b51eSKate Stone             " GetEntryPoint() returned address 0x%" PRIx64
229b9c1b51eSKate Stone             ", setting entry breakpoint",
230b9c1b51eSKate Stone             __FUNCTION__,
23163e5fb76SJonas Devlieghere             m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID, entry);
232c82f650aSTodd Fiala 
233b9c1b51eSKate Stone   if (m_process) {
234b9c1b51eSKate Stone     Breakpoint *const entry_break =
235b9c1b51eSKate Stone         m_process->GetTarget().CreateBreakpoint(entry, true, false).get();
2369ed5b49cSJohnny Chen     entry_break->SetCallback(EntryBreakpointHit, this, true);
2372995077dSJim Ingham     entry_break->SetBreakpointKind("shared-library-event");
238952bccd2STodd Fiala 
239952bccd2STodd Fiala     // Shoudn't hit this more than once.
240952bccd2STodd Fiala     entry_break->SetOneShot(true);
2419ed5b49cSJohnny Chen   }
242823d8f62SJason Molenda }
2439ed5b49cSJohnny Chen 
2449ed5b49cSJohnny Chen // The runtime linker has run and initialized the rendezvous structure once the
24505097246SAdrian Prantl // process has hit its entry point.  When we hit the corresponding breakpoint
24605097246SAdrian Prantl // we interrogate the rendezvous structure to get the load addresses of all
2479ed5b49cSJohnny Chen // dependent modules for the process.  Similarly, we can discover the runtime
24805097246SAdrian Prantl // linker function and setup a breakpoint to notify us of any dynamically
24905097246SAdrian Prantl // loaded modules (via dlopen).
EntryBreakpointHit(void * baton,StoppointCallbackContext * context,user_id_t break_id,user_id_t break_loc_id)250b9c1b51eSKate Stone bool DynamicLoaderPOSIXDYLD::EntryBreakpointHit(
251b9c1b51eSKate Stone     void *baton, StoppointCallbackContext *context, user_id_t break_id,
252b9c1b51eSKate Stone     user_id_t break_loc_id) {
253c82f650aSTodd Fiala   assert(baton && "null baton");
254c82f650aSTodd Fiala   if (!baton)
255c82f650aSTodd Fiala     return false;
2569ed5b49cSJohnny Chen 
257a007a6d8SPavel Labath   Log *log = GetLog(LLDBLog::DynamicLoader);
258b9c1b51eSKate Stone   DynamicLoaderPOSIXDYLD *const dyld_instance =
259b9c1b51eSKate Stone       static_cast<DynamicLoaderPOSIXDYLD *>(baton);
26063e5fb76SJonas Devlieghere   LLDB_LOGF(log, "DynamicLoaderPOSIXDYLD::%s called for pid %" PRIu64,
261b9c1b51eSKate Stone             __FUNCTION__,
262b9c1b51eSKate Stone             dyld_instance->m_process ? dyld_instance->m_process->GetID()
263b9c1b51eSKate Stone                                      : LLDB_INVALID_PROCESS_ID);
264c82f650aSTodd Fiala 
265b9c1b51eSKate Stone   // Disable the breakpoint --- if a stop happens right after this, which we've
26605097246SAdrian Prantl   // seen on occasion, we don't want the breakpoint stepping thread-plan logic
26705097246SAdrian Prantl   // to show a breakpoint instruction at the disassembled entry point to the
26805097246SAdrian Prantl   // program.  Disabling it prevents it.  (One-shot is not enough - one-shot
26905097246SAdrian Prantl   // removal logic only happens after the breakpoint goes public, which wasn't
27005097246SAdrian Prantl   // happening in our scenario).
271b9c1b51eSKate Stone   if (dyld_instance->m_process) {
272b9c1b51eSKate Stone     BreakpointSP breakpoint_sp =
273b9c1b51eSKate Stone         dyld_instance->m_process->GetTarget().GetBreakpointByID(break_id);
274b9c1b51eSKate Stone     if (breakpoint_sp) {
27563e5fb76SJonas Devlieghere       LLDB_LOGF(log,
27663e5fb76SJonas Devlieghere                 "DynamicLoaderPOSIXDYLD::%s pid %" PRIu64
277b9c1b51eSKate Stone                 " disabling breakpoint id %" PRIu64,
278b9c1b51eSKate Stone                 __FUNCTION__, dyld_instance->m_process->GetID(), break_id);
279952bccd2STodd Fiala       breakpoint_sp->SetEnabled(false);
280b9c1b51eSKate Stone     } else {
28163e5fb76SJonas Devlieghere       LLDB_LOGF(log,
28263e5fb76SJonas Devlieghere                 "DynamicLoaderPOSIXDYLD::%s pid %" PRIu64
283b9c1b51eSKate Stone                 " failed to find breakpoint for breakpoint id %" PRIu64,
284b9c1b51eSKate Stone                 __FUNCTION__, dyld_instance->m_process->GetID(), break_id);
285952bccd2STodd Fiala     }
286b9c1b51eSKate Stone   } else {
28763e5fb76SJonas Devlieghere     LLDB_LOGF(log,
28863e5fb76SJonas Devlieghere               "DynamicLoaderPOSIXDYLD::%s breakpoint id %" PRIu64
289b9c1b51eSKate Stone               " no Process instance!  Cannot disable breakpoint",
290b9c1b51eSKate Stone               __FUNCTION__, break_id);
291952bccd2STodd Fiala   }
292952bccd2STodd Fiala 
2939ed5b49cSJohnny Chen   dyld_instance->LoadAllCurrentModules();
2949ed5b49cSJohnny Chen   dyld_instance->SetRendezvousBreakpoint();
2959ed5b49cSJohnny Chen   return false; // Continue running.
2969ed5b49cSJohnny Chen }
2979ed5b49cSJohnny Chen 
SetRendezvousBreakpoint()298b7386d99SEugene Zemtsov bool DynamicLoaderPOSIXDYLD::SetRendezvousBreakpoint() {
299a007a6d8SPavel Labath   Log *log = GetLog(LLDBLog::DynamicLoader);
300b7386d99SEugene Zemtsov   if (m_dyld_bid != LLDB_INVALID_BREAK_ID) {
301b7386d99SEugene Zemtsov     LLDB_LOG(log,
302b7386d99SEugene Zemtsov              "Rendezvous breakpoint breakpoint id {0} for pid {1}"
303b7386d99SEugene Zemtsov              "is already set.",
304b7386d99SEugene Zemtsov              m_dyld_bid,
305b7386d99SEugene Zemtsov              m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID);
306b7386d99SEugene Zemtsov     return true;
307b7386d99SEugene Zemtsov   }
308c82f650aSTodd Fiala 
309b7386d99SEugene Zemtsov   addr_t break_addr;
310c87e752bSMichael Sartain   Target &target = m_process->GetTarget();
311b7386d99SEugene Zemtsov   BreakpointSP dyld_break;
312879a47a5SGreg Clayton   if (m_rendezvous.IsValid() && m_rendezvous.GetBreakAddress() != 0) {
313b7386d99SEugene Zemtsov     break_addr = m_rendezvous.GetBreakAddress();
314b7386d99SEugene Zemtsov     LLDB_LOG(log, "Setting rendezvous break address for pid {0} at {1:x}",
315b9c1b51eSKate Stone              m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID,
316b9c1b51eSKate Stone              break_addr);
317b7386d99SEugene Zemtsov     dyld_break = target.CreateBreakpoint(break_addr, true, false);
318b7386d99SEugene Zemtsov   } else {
319b7386d99SEugene Zemtsov     LLDB_LOG(log, "Rendezvous structure is not set up yet. "
320b7386d99SEugene Zemtsov                   "Trying to locate rendezvous breakpoint in the interpreter "
321b7386d99SEugene Zemtsov                   "by symbol name.");
32203df9710SRumeet Dhindsa     // Function names from different dynamic loaders that are known to be
32303df9710SRumeet Dhindsa     // used as rendezvous between the loader and debuggers.
324b7386d99SEugene Zemtsov     static std::vector<std::string> DebugStateCandidates{
325b7386d99SEugene Zemtsov         "_dl_debug_state", "rtld_db_dlactivity", "__dl_rtld_db_dlactivity",
326b7386d99SEugene Zemtsov         "r_debug_state",   "_r_debug_state",     "_rtld_debug_state",
327b7386d99SEugene Zemtsov     };
328b7386d99SEugene Zemtsov 
32903df9710SRumeet Dhindsa     ModuleSP interpreter = LoadInterpreterModule();
33003df9710SRumeet Dhindsa     if (!interpreter) {
33103df9710SRumeet Dhindsa       FileSpecList containingModules;
33203df9710SRumeet Dhindsa       containingModules.Append(
33303df9710SRumeet Dhindsa           m_process->GetTarget().GetExecutableModulePointer()->GetFileSpec());
33403df9710SRumeet Dhindsa 
33503df9710SRumeet Dhindsa       dyld_break = target.CreateBreakpoint(
33603df9710SRumeet Dhindsa           &containingModules, /*containingSourceFiles=*/nullptr,
33703df9710SRumeet Dhindsa           DebugStateCandidates, eFunctionNameTypeFull, eLanguageTypeC,
338b12fd138SKazu Hirata           /*m_offset=*/0,
33903df9710SRumeet Dhindsa           /*skip_prologue=*/eLazyBoolNo,
34003df9710SRumeet Dhindsa           /*internal=*/true,
34103df9710SRumeet Dhindsa           /*request_hardware=*/false);
34203df9710SRumeet Dhindsa     } else {
343b7386d99SEugene Zemtsov       FileSpecList containingModules;
344b7386d99SEugene Zemtsov       containingModules.Append(interpreter->GetFileSpec());
345b7386d99SEugene Zemtsov       dyld_break = target.CreateBreakpoint(
34603df9710SRumeet Dhindsa           &containingModules, /*containingSourceFiles=*/nullptr,
347b7386d99SEugene Zemtsov           DebugStateCandidates, eFunctionNameTypeFull, eLanguageTypeC,
348b12fd138SKazu Hirata           /*m_offset=*/0,
34903df9710SRumeet Dhindsa           /*skip_prologue=*/eLazyBoolNo,
35003df9710SRumeet Dhindsa           /*internal=*/true,
35103df9710SRumeet Dhindsa           /*request_hardware=*/false);
35203df9710SRumeet Dhindsa     }
353b7386d99SEugene Zemtsov   }
354b7386d99SEugene Zemtsov 
355b7386d99SEugene Zemtsov   if (dyld_break->GetNumResolvedLocations() != 1) {
356b7386d99SEugene Zemtsov     LLDB_LOG(
357b7386d99SEugene Zemtsov         log,
358b7386d99SEugene Zemtsov         "Rendezvous breakpoint has abnormal number of"
359b7386d99SEugene Zemtsov         " resolved locations ({0}) in pid {1}. It's supposed to be exactly 1.",
360b7386d99SEugene Zemtsov         dyld_break->GetNumResolvedLocations(),
361b7386d99SEugene Zemtsov         m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID);
362b7386d99SEugene Zemtsov 
363b7386d99SEugene Zemtsov     target.RemoveBreakpointByID(dyld_break->GetID());
364b7386d99SEugene Zemtsov     return false;
365b7386d99SEugene Zemtsov   }
366b7386d99SEugene Zemtsov 
367b7386d99SEugene Zemtsov   BreakpointLocationSP location = dyld_break->GetLocationAtIndex(0);
368b7386d99SEugene Zemtsov   LLDB_LOG(log,
369b7386d99SEugene Zemtsov            "Successfully set rendezvous breakpoint at address {0:x} "
370b7386d99SEugene Zemtsov            "for pid {1}",
371b7386d99SEugene Zemtsov            location->GetLoadAddress(),
372b7386d99SEugene Zemtsov            m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID);
373b7386d99SEugene Zemtsov 
3749ed5b49cSJohnny Chen   dyld_break->SetCallback(RendezvousBreakpointHit, this, true);
3752995077dSJim Ingham   dyld_break->SetBreakpointKind("shared-library-event");
376c87e752bSMichael Sartain   m_dyld_bid = dyld_break->GetID();
377b7386d99SEugene Zemtsov   return true;
3789ed5b49cSJohnny Chen }
3799ed5b49cSJohnny Chen 
RendezvousBreakpointHit(void * baton,StoppointCallbackContext * context,user_id_t break_id,user_id_t break_loc_id)380b9c1b51eSKate Stone bool DynamicLoaderPOSIXDYLD::RendezvousBreakpointHit(
381b9c1b51eSKate Stone     void *baton, StoppointCallbackContext *context, user_id_t break_id,
382b9c1b51eSKate Stone     user_id_t break_loc_id) {
383c82f650aSTodd Fiala   assert(baton && "null baton");
384c82f650aSTodd Fiala   if (!baton)
385c82f650aSTodd Fiala     return false;
3869ed5b49cSJohnny Chen 
387a007a6d8SPavel Labath   Log *log = GetLog(LLDBLog::DynamicLoader);
388b9c1b51eSKate Stone   DynamicLoaderPOSIXDYLD *const dyld_instance =
389b9c1b51eSKate Stone       static_cast<DynamicLoaderPOSIXDYLD *>(baton);
39063e5fb76SJonas Devlieghere   LLDB_LOGF(log, "DynamicLoaderPOSIXDYLD::%s called for pid %" PRIu64,
391b9c1b51eSKate Stone             __FUNCTION__,
392b9c1b51eSKate Stone             dyld_instance->m_process ? dyld_instance->m_process->GetID()
393b9c1b51eSKate Stone                                      : LLDB_INVALID_PROCESS_ID);
394c82f650aSTodd Fiala 
3959ed5b49cSJohnny Chen   dyld_instance->RefreshModules();
3969ed5b49cSJohnny Chen 
3979ed5b49cSJohnny Chen   // Return true to stop the target, false to just let the target run.
398c82f650aSTodd Fiala   const bool stop_when_images_change = dyld_instance->GetStopWhenImagesChange();
39963e5fb76SJonas Devlieghere   LLDB_LOGF(log,
40063e5fb76SJonas Devlieghere             "DynamicLoaderPOSIXDYLD::%s pid %" PRIu64
401b9c1b51eSKate Stone             " stop_when_images_change=%s",
402b9c1b51eSKate Stone             __FUNCTION__,
403b9c1b51eSKate Stone             dyld_instance->m_process ? dyld_instance->m_process->GetID()
404b9c1b51eSKate Stone                                      : LLDB_INVALID_PROCESS_ID,
405b9c1b51eSKate Stone             stop_when_images_change ? "true" : "false");
406c82f650aSTodd Fiala   return stop_when_images_change;
4079ed5b49cSJohnny Chen }
4089ed5b49cSJohnny Chen 
RefreshModules()409b9c1b51eSKate Stone void DynamicLoaderPOSIXDYLD::RefreshModules() {
4109ed5b49cSJohnny Chen   if (!m_rendezvous.Resolve())
4119ed5b49cSJohnny Chen     return;
4129ed5b49cSJohnny Chen 
4139ed5b49cSJohnny Chen   DYLDRendezvous::iterator I;
4149ed5b49cSJohnny Chen   DYLDRendezvous::iterator E;
4159ed5b49cSJohnny Chen 
4169ed5b49cSJohnny Chen   ModuleList &loaded_modules = m_process->GetTarget().GetImages();
4179ed5b49cSJohnny Chen 
4188666b905SMichał Górny   if (m_rendezvous.ModulesDidLoad() || !m_initial_modules_added) {
4199ed5b49cSJohnny Chen     ModuleList new_modules;
4209ed5b49cSJohnny Chen 
4218666b905SMichał Górny     // If this is the first time rendezvous breakpoint fires, we need
4228666b905SMichał Górny     // to take care of adding all the initial modules reported by
4238666b905SMichał Górny     // the loader.  This is necessary to list ld-linux.so on Linux,
4248666b905SMichał Górny     // and all DT_NEEDED entries on *BSD.
4258666b905SMichał Górny     if (m_initial_modules_added) {
4268666b905SMichał Górny       I = m_rendezvous.loaded_begin();
4279ed5b49cSJohnny Chen       E = m_rendezvous.loaded_end();
4288666b905SMichał Górny     } else {
4298666b905SMichał Górny       I = m_rendezvous.begin();
4308666b905SMichał Górny       E = m_rendezvous.end();
4318666b905SMichał Górny       m_initial_modules_added = true;
4328666b905SMichał Górny     }
4338666b905SMichał Górny     for (; I != E; ++I) {
434b9c1b51eSKate Stone       ModuleSP module_sp =
435b9c1b51eSKate Stone           LoadModuleAtAddress(I->file_spec, I->link_addr, I->base_addr, true);
43655355829SPavel Labath       if (!module_sp.get())
43755355829SPavel Labath         continue;
43855355829SPavel Labath 
4398666b905SMichał Górny       if (module_sp->GetObjectFile()->GetBaseAddress().GetLoadAddress(
44055355829SPavel Labath               &m_process->GetTarget()) == m_interpreter_base) {
44155355829SPavel Labath         ModuleSP interpreter_sp = m_interpreter_module.lock();
442d5629b5dSEmre Kultursay         if (m_interpreter_module.lock() == nullptr) {
443d5629b5dSEmre Kultursay           m_interpreter_module = module_sp;
44455355829SPavel Labath         } else if (module_sp == interpreter_sp) {
44555355829SPavel Labath           // Module already loaded.
44655355829SPavel Labath           continue;
447d5629b5dSEmre Kultursay         } else {
448d5629b5dSEmre Kultursay           // If this is a duplicate instance of ld.so, unload it.  We may end
449d5629b5dSEmre Kultursay           // up with it if we load it via a different path than before
450d5629b5dSEmre Kultursay           // (symlink vs real path).
4518666b905SMichał Górny           // TODO: remove this once we either fix library matching or avoid
4528666b905SMichał Górny           // loading the interpreter when setting the rendezvous breakpoint.
4538666b905SMichał Górny           UnloadSections(module_sp);
4548666b905SMichał Górny           loaded_modules.Remove(module_sp);
4558666b905SMichał Górny           continue;
4568666b905SMichał Górny         }
457d5629b5dSEmre Kultursay       }
4588666b905SMichał Górny 
4591759848bSEnrico Granata       loaded_modules.AppendIfNeeded(module_sp);
460d678d30bSMatt Kopec       new_modules.Append(module_sp);
4619ed5b49cSJohnny Chen     }
462d678d30bSMatt Kopec     m_process->GetTarget().ModulesDidLoad(new_modules);
463d678d30bSMatt Kopec   }
4649ed5b49cSJohnny Chen 
465b9c1b51eSKate Stone   if (m_rendezvous.ModulesDidUnload()) {
4669ed5b49cSJohnny Chen     ModuleList old_modules;
4679ed5b49cSJohnny Chen 
4689ed5b49cSJohnny Chen     E = m_rendezvous.unloaded_end();
469b9c1b51eSKate Stone     for (I = m_rendezvous.unloaded_begin(); I != E; ++I) {
47055c1c349SChaoren Lin       ModuleSpec module_spec{I->file_spec};
47142ecef3bSTamas Berghammer       ModuleSP module_sp = loaded_modules.FindFirstModule(module_spec);
472d678d30bSMatt Kopec 
473b9c1b51eSKate Stone       if (module_sp.get()) {
4749ed5b49cSJohnny Chen         old_modules.Append(module_sp);
475d678d30bSMatt Kopec         UnloadSections(module_sp);
476d678d30bSMatt Kopec       }
4779ed5b49cSJohnny Chen     }
4781759848bSEnrico Granata     loaded_modules.Remove(old_modules);
479095eeaa0SGreg Clayton     m_process->GetTarget().ModulesDidUnload(old_modules, false);
4809ed5b49cSJohnny Chen   }
4819ed5b49cSJohnny Chen }
4829ed5b49cSJohnny Chen 
4839ed5b49cSJohnny Chen ThreadPlanSP
GetStepThroughTrampolinePlan(Thread & thread,bool stop)484b9c1b51eSKate Stone DynamicLoaderPOSIXDYLD::GetStepThroughTrampolinePlan(Thread &thread,
485b9c1b51eSKate Stone                                                      bool stop) {
4869ed5b49cSJohnny Chen   ThreadPlanSP thread_plan_sp;
4879ed5b49cSJohnny Chen 
488b57e4a1bSJason Molenda   StackFrame *frame = thread.GetStackFrameAtIndex(0).get();
4899ed5b49cSJohnny Chen   const SymbolContext &context = frame->GetSymbolContext(eSymbolContextSymbol);
4909ed5b49cSJohnny Chen   Symbol *sym = context.symbol;
4919ed5b49cSJohnny Chen 
492248a1305SKonrad Kleine   if (sym == nullptr || !sym->IsTrampoline())
4939ed5b49cSJohnny Chen     return thread_plan_sp;
4949ed5b49cSJohnny Chen 
495d8ad0188SMichael Daniels   ConstString sym_name = sym->GetMangled().GetName(Mangled::ePreferMangled);
4969ed5b49cSJohnny Chen   if (!sym_name)
4979ed5b49cSJohnny Chen     return thread_plan_sp;
4989ed5b49cSJohnny Chen 
4999ed5b49cSJohnny Chen   SymbolContextList target_symbols;
5000c90ef47SGreg Clayton   Target &target = thread.GetProcess()->GetTarget();
5011759848bSEnrico Granata   const ModuleList &images = target.GetImages();
5029ed5b49cSJohnny Chen 
5039ed5b49cSJohnny Chen   images.FindSymbolsWithNameAndType(sym_name, eSymbolTypeCode, target_symbols);
5049ed5b49cSJohnny Chen   size_t num_targets = target_symbols.GetSize();
5059ed5b49cSJohnny Chen   if (!num_targets)
5069ed5b49cSJohnny Chen     return thread_plan_sp;
5079ed5b49cSJohnny Chen 
5089ed5b49cSJohnny Chen   typedef std::vector<lldb::addr_t> AddressVector;
5099ed5b49cSJohnny Chen   AddressVector addrs;
510b9c1b51eSKate Stone   for (size_t i = 0; i < num_targets; ++i) {
5119ed5b49cSJohnny Chen     SymbolContext context;
5129ed5b49cSJohnny Chen     AddressRange range;
513b9c1b51eSKate Stone     if (target_symbols.GetContextAtIndex(i, context)) {
5149ed5b49cSJohnny Chen       context.GetAddressRange(eSymbolContextEverything, 0, false, range);
5159ed5b49cSJohnny Chen       lldb::addr_t addr = range.GetBaseAddress().GetLoadAddress(&target);
5169ed5b49cSJohnny Chen       if (addr != LLDB_INVALID_ADDRESS)
5179ed5b49cSJohnny Chen         addrs.push_back(addr);
5189ed5b49cSJohnny Chen     }
5199ed5b49cSJohnny Chen   }
5209ed5b49cSJohnny Chen 
521b9c1b51eSKate Stone   if (addrs.size() > 0) {
5229ed5b49cSJohnny Chen     AddressVector::iterator start = addrs.begin();
5239ed5b49cSJohnny Chen     AddressVector::iterator end = addrs.end();
5249ed5b49cSJohnny Chen 
5259bbba276SJonas Devlieghere     llvm::sort(start, end);
5269ed5b49cSJohnny Chen     addrs.erase(std::unique(start, end), end);
527796ac80bSJonas Devlieghere     thread_plan_sp =
528796ac80bSJonas Devlieghere         std::make_shared<ThreadPlanRunToAddress>(thread, addrs, stop);
5299ed5b49cSJohnny Chen   }
5309ed5b49cSJohnny Chen 
5319ed5b49cSJohnny Chen   return thread_plan_sp;
5329ed5b49cSJohnny Chen }
5339ed5b49cSJohnny Chen 
LoadVDSO()534b7386d99SEugene Zemtsov void DynamicLoaderPOSIXDYLD::LoadVDSO() {
535df1a0d11SPavel Labath   if (m_vdso_base == LLDB_INVALID_ADDRESS)
536df1a0d11SPavel Labath     return;
537df1a0d11SPavel Labath 
5388f3be7a3SJonas Devlieghere   FileSpec file("[vdso]");
539df1a0d11SPavel Labath 
540df1a0d11SPavel Labath   MemoryRegionInfo info;
541df1a0d11SPavel Labath   Status status = m_process->GetMemoryRegionInfo(m_vdso_base, info);
542df1a0d11SPavel Labath   if (status.Fail()) {
543a007a6d8SPavel Labath     Log *log = GetLog(LLDBLog::DynamicLoader);
544df1a0d11SPavel Labath     LLDB_LOG(log, "Failed to get vdso region info: {0}", status);
545df1a0d11SPavel Labath     return;
546df1a0d11SPavel Labath   }
547df1a0d11SPavel Labath 
548df1a0d11SPavel Labath   if (ModuleSP module_sp = m_process->ReadModuleFromMemory(
549df1a0d11SPavel Labath           file, m_vdso_base, info.GetRange().GetByteSize())) {
550df1a0d11SPavel Labath     UpdateLoadedSections(module_sp, LLDB_INVALID_ADDRESS, m_vdso_base, false);
551df1a0d11SPavel Labath     m_process->GetTarget().GetImages().AppendIfNeeded(module_sp);
552df1a0d11SPavel Labath   }
553df1a0d11SPavel Labath }
554df1a0d11SPavel Labath 
LoadInterpreterModule()555b7386d99SEugene Zemtsov ModuleSP DynamicLoaderPOSIXDYLD::LoadInterpreterModule() {
556b7386d99SEugene Zemtsov   if (m_interpreter_base == LLDB_INVALID_ADDRESS)
557b7386d99SEugene Zemtsov     return nullptr;
558b7386d99SEugene Zemtsov 
559b7386d99SEugene Zemtsov   MemoryRegionInfo info;
560b7386d99SEugene Zemtsov   Target &target = m_process->GetTarget();
561b7386d99SEugene Zemtsov   Status status = m_process->GetMemoryRegionInfo(m_interpreter_base, info);
562b7386d99SEugene Zemtsov   if (status.Fail() || info.GetMapped() != MemoryRegionInfo::eYes ||
563b7386d99SEugene Zemtsov       info.GetName().IsEmpty()) {
564a007a6d8SPavel Labath     Log *log = GetLog(LLDBLog::DynamicLoader);
565b7386d99SEugene Zemtsov     LLDB_LOG(log, "Failed to get interpreter region info: {0}", status);
566b7386d99SEugene Zemtsov     return nullptr;
567b7386d99SEugene Zemtsov   }
568b7386d99SEugene Zemtsov 
5698f3be7a3SJonas Devlieghere   FileSpec file(info.GetName().GetCString());
570b7386d99SEugene Zemtsov   ModuleSpec module_spec(file, target.GetArchitecture());
571b7386d99SEugene Zemtsov 
5721724a179SJason Molenda   if (ModuleSP module_sp = target.GetOrCreateModule(module_spec,
5731724a179SJason Molenda                                                     true /* notify */)) {
574b7386d99SEugene Zemtsov     UpdateLoadedSections(module_sp, LLDB_INVALID_ADDRESS, m_interpreter_base,
575b7386d99SEugene Zemtsov                          false);
5768666b905SMichał Górny     m_interpreter_module = module_sp;
577b7386d99SEugene Zemtsov     return module_sp;
578b7386d99SEugene Zemtsov   }
579b7386d99SEugene Zemtsov   return nullptr;
580b7386d99SEugene Zemtsov }
581b7386d99SEugene Zemtsov 
LoadModuleAtAddress(const FileSpec & file,addr_t link_map_addr,addr_t base_addr,bool base_addr_is_offset)582e67cee09SPavel Labath ModuleSP DynamicLoaderPOSIXDYLD::LoadModuleAtAddress(const FileSpec &file,
583e67cee09SPavel Labath                                                      addr_t link_map_addr,
584e67cee09SPavel Labath                                                      addr_t base_addr,
585e67cee09SPavel Labath                                                      bool base_addr_is_offset) {
586e67cee09SPavel Labath   if (ModuleSP module_sp = DynamicLoader::LoadModuleAtAddress(
587e67cee09SPavel Labath           file, link_map_addr, base_addr, base_addr_is_offset))
588e67cee09SPavel Labath     return module_sp;
589e67cee09SPavel Labath 
590e67cee09SPavel Labath   // This works around an dynamic linker "bug" on android <= 23, where the
591e67cee09SPavel Labath   // dynamic linker would report the application name
592e67cee09SPavel Labath   // (e.g. com.example.myapplication) instead of the main process binary
593e67cee09SPavel Labath   // (/system/bin/app_process(32)). The logic is not sound in general (it
594e67cee09SPavel Labath   // assumes base_addr is the real address, even though it actually is a load
595e67cee09SPavel Labath   // bias), but it happens to work on adroid because app_process has a file
596e67cee09SPavel Labath   // address of zero.
597e67cee09SPavel Labath   // This should be removed after we drop support for android-23.
598e67cee09SPavel Labath   if (m_process->GetTarget().GetArchitecture().GetTriple().isAndroid()) {
599e67cee09SPavel Labath     MemoryRegionInfo memory_info;
600e67cee09SPavel Labath     Status error = m_process->GetMemoryRegionInfo(base_addr, memory_info);
601e67cee09SPavel Labath     if (error.Success() && memory_info.GetMapped() &&
602e67cee09SPavel Labath         memory_info.GetRange().GetRangeBase() == base_addr &&
603e67cee09SPavel Labath         !(memory_info.GetName().IsEmpty())) {
604e67cee09SPavel Labath       if (ModuleSP module_sp = DynamicLoader::LoadModuleAtAddress(
605e67cee09SPavel Labath               FileSpec(memory_info.GetName().GetStringRef()), link_map_addr,
606e67cee09SPavel Labath               base_addr, base_addr_is_offset))
607e67cee09SPavel Labath         return module_sp;
608e67cee09SPavel Labath     }
609e67cee09SPavel Labath   }
610e67cee09SPavel Labath 
611e67cee09SPavel Labath   return nullptr;
612e67cee09SPavel Labath }
613e67cee09SPavel Labath 
LoadAllCurrentModules()614b9c1b51eSKate Stone void DynamicLoaderPOSIXDYLD::LoadAllCurrentModules() {
6159ed5b49cSJohnny Chen   DYLDRendezvous::iterator I;
6169ed5b49cSJohnny Chen   DYLDRendezvous::iterator E;
6179ed5b49cSJohnny Chen   ModuleList module_list;
618a007a6d8SPavel Labath   Log *log = GetLog(LLDBLog::DynamicLoader);
619b7386d99SEugene Zemtsov 
620b7386d99SEugene Zemtsov   LoadVDSO();
6219ed5b49cSJohnny Chen 
622b9c1b51eSKate Stone   if (!m_rendezvous.Resolve()) {
62363e5fb76SJonas Devlieghere     LLDB_LOGF(log,
62463e5fb76SJonas Devlieghere               "DynamicLoaderPOSIXDYLD::%s unable to resolve POSIX DYLD "
625b9c1b51eSKate Stone               "rendezvous address",
626d66b50c9SDeepak Panickal               __FUNCTION__);
6279ed5b49cSJohnny Chen     return;
6289715936dSEd Maste   }
6299ed5b49cSJohnny Chen 
63005097246SAdrian Prantl   // The rendezvous class doesn't enumerate the main module, so track that
63105097246SAdrian Prantl   // ourselves here.
6320a558357SRichard Mitton   ModuleSP executable = GetTargetExecutable();
6330a558357SRichard Mitton   m_loaded_modules[executable] = m_rendezvous.GetLinkMapAddress();
6342f1fbaebSPavel Labath 
6352f1fbaebSPavel Labath   std::vector<FileSpec> module_names;
6362f1fbaebSPavel Labath   for (I = m_rendezvous.begin(), E = m_rendezvous.end(); I != E; ++I)
6372f1fbaebSPavel Labath     module_names.push_back(I->file_spec);
6382f1fbaebSPavel Labath   m_process->PrefetchModuleSpecs(
6392f1fbaebSPavel Labath       module_names, m_process->GetTarget().GetArchitecture().GetTriple());
6402f1fbaebSPavel Labath 
641b9c1b51eSKate Stone   for (I = m_rendezvous.begin(), E = m_rendezvous.end(); I != E; ++I) {
642b9c1b51eSKate Stone     ModuleSP module_sp =
643b9c1b51eSKate Stone         LoadModuleAtAddress(I->file_spec, I->link_addr, I->base_addr, true);
644b9c1b51eSKate Stone     if (module_sp.get()) {
645b7386d99SEugene Zemtsov       LLDB_LOG(log, "LoadAllCurrentModules loading module: {0}",
646b7386d99SEugene Zemtsov                I->file_spec.GetFilename());
6479ed5b49cSJohnny Chen       module_list.Append(module_sp);
648b9c1b51eSKate Stone     } else {
649a007a6d8SPavel Labath       Log *log = GetLog(LLDBLog::DynamicLoader);
65063e5fb76SJonas Devlieghere       LLDB_LOGF(
65163e5fb76SJonas Devlieghere           log,
652b9c1b51eSKate Stone           "DynamicLoaderPOSIXDYLD::%s failed loading module %s at 0x%" PRIx64,
653*1b4b12a3SNico Weber           __FUNCTION__, I->file_spec.GetCString(), I->base_addr);
6549715936dSEd Maste     }
6559715936dSEd Maste   }
6569ed5b49cSJohnny Chen 
6579ed5b49cSJohnny Chen   m_process->GetTarget().ModulesDidLoad(module_list);
658d5629b5dSEmre Kultursay   m_initial_modules_added = true;
6599ed5b49cSJohnny Chen }
6609ed5b49cSJohnny Chen 
ComputeLoadOffset()661b9c1b51eSKate Stone addr_t DynamicLoaderPOSIXDYLD::ComputeLoadOffset() {
6629ed5b49cSJohnny Chen   addr_t virt_entry;
6639ed5b49cSJohnny Chen 
6649ed5b49cSJohnny Chen   if (m_load_offset != LLDB_INVALID_ADDRESS)
6659ed5b49cSJohnny Chen     return m_load_offset;
6669ed5b49cSJohnny Chen 
6679ed5b49cSJohnny Chen   if ((virt_entry = GetEntryPoint()) == LLDB_INVALID_ADDRESS)
6689ed5b49cSJohnny Chen     return LLDB_INVALID_ADDRESS;
6699ed5b49cSJohnny Chen 
6709ed5b49cSJohnny Chen   ModuleSP module = m_process->GetTarget().GetExecutableModule();
6710584d7fcSEd Maste   if (!module)
6720584d7fcSEd Maste     return LLDB_INVALID_ADDRESS;
6730584d7fcSEd Maste 
6749ed5b49cSJohnny Chen   ObjectFile *exe = module->GetObjectFile();
675926af0cdSOleksiy Vyalov   if (!exe)
676926af0cdSOleksiy Vyalov     return LLDB_INVALID_ADDRESS;
677926af0cdSOleksiy Vyalov 
6789ed5b49cSJohnny Chen   Address file_entry = exe->GetEntryPointAddress();
6799ed5b49cSJohnny Chen 
6809ed5b49cSJohnny Chen   if (!file_entry.IsValid())
6819ed5b49cSJohnny Chen     return LLDB_INVALID_ADDRESS;
6829ed5b49cSJohnny Chen 
6839ed5b49cSJohnny Chen   m_load_offset = virt_entry - file_entry.GetFileAddress();
6849ed5b49cSJohnny Chen   return m_load_offset;
6859ed5b49cSJohnny Chen }
6869ed5b49cSJohnny Chen 
EvalSpecialModulesStatus()687b7386d99SEugene Zemtsov void DynamicLoaderPOSIXDYLD::EvalSpecialModulesStatus() {
688943faef1SAntonio Afonso   if (llvm::Optional<uint64_t> vdso_base =
689943faef1SAntonio Afonso           m_auxv->GetAuxValue(AuxVector::AUXV_AT_SYSINFO_EHDR))
690943faef1SAntonio Afonso     m_vdso_base = *vdso_base;
691b7386d99SEugene Zemtsov 
692943faef1SAntonio Afonso   if (llvm::Optional<uint64_t> interpreter_base =
693943faef1SAntonio Afonso           m_auxv->GetAuxValue(AuxVector::AUXV_AT_BASE))
694943faef1SAntonio Afonso     m_interpreter_base = *interpreter_base;
695f546b411SRavitheja Addepally }
696f546b411SRavitheja Addepally 
GetEntryPoint()697b9c1b51eSKate Stone addr_t DynamicLoaderPOSIXDYLD::GetEntryPoint() {
6989ed5b49cSJohnny Chen   if (m_entry_point != LLDB_INVALID_ADDRESS)
6999ed5b49cSJohnny Chen     return m_entry_point;
7009ed5b49cSJohnny Chen 
701248a1305SKonrad Kleine   if (m_auxv == nullptr)
7029ed5b49cSJohnny Chen     return LLDB_INVALID_ADDRESS;
7039ed5b49cSJohnny Chen 
704943faef1SAntonio Afonso   llvm::Optional<uint64_t> entry_point =
705943faef1SAntonio Afonso       m_auxv->GetAuxValue(AuxVector::AUXV_AT_ENTRY);
706943faef1SAntonio Afonso   if (!entry_point)
7079ed5b49cSJohnny Chen     return LLDB_INVALID_ADDRESS;
7089ed5b49cSJohnny Chen 
709943faef1SAntonio Afonso   m_entry_point = static_cast<addr_t>(*entry_point);
7106256a0eaSJustin Hibbits 
7116256a0eaSJustin Hibbits   const ArchSpec &arch = m_process->GetTarget().GetArchitecture();
7126256a0eaSJustin Hibbits 
7136256a0eaSJustin Hibbits   // On ppc64, the entry point is actually a descriptor.  Dereference it.
7146256a0eaSJustin Hibbits   if (arch.GetMachine() == llvm::Triple::ppc64)
7156256a0eaSJustin Hibbits     m_entry_point = ReadUnsignedIntWithSizeInBytes(m_entry_point, 8);
7166256a0eaSJustin Hibbits 
7179ed5b49cSJohnny Chen   return m_entry_point;
7189ed5b49cSJohnny Chen }
719d678d30bSMatt Kopec 
7200a558357SRichard Mitton lldb::addr_t
GetThreadLocalData(const lldb::ModuleSP module_sp,const lldb::ThreadSP thread,lldb::addr_t tls_file_addr)721b9c1b51eSKate Stone DynamicLoaderPOSIXDYLD::GetThreadLocalData(const lldb::ModuleSP module_sp,
722b9c1b51eSKate Stone                                            const lldb::ThreadSP thread,
723b9c1b51eSKate Stone                                            lldb::addr_t tls_file_addr) {
724a8974690SGreg Clayton   auto it = m_loaded_modules.find(module_sp);
7250a558357SRichard Mitton   if (it == m_loaded_modules.end())
7260a558357SRichard Mitton     return LLDB_INVALID_ADDRESS;
7270a558357SRichard Mitton 
7280a558357SRichard Mitton   addr_t link_map = it->second;
7290a558357SRichard Mitton   if (link_map == LLDB_INVALID_ADDRESS)
7300a558357SRichard Mitton     return LLDB_INVALID_ADDRESS;
7310a558357SRichard Mitton 
7320a558357SRichard Mitton   const DYLDRendezvous::ThreadInfo &metadata = m_rendezvous.GetThreadInfo();
7330a558357SRichard Mitton   if (!metadata.valid)
7340a558357SRichard Mitton     return LLDB_INVALID_ADDRESS;
7350a558357SRichard Mitton 
7360a558357SRichard Mitton   // Get the thread pointer.
7370a558357SRichard Mitton   addr_t tp = thread->GetThreadPointer();
7380a558357SRichard Mitton   if (tp == LLDB_INVALID_ADDRESS)
7390a558357SRichard Mitton     return LLDB_INVALID_ADDRESS;
7400a558357SRichard Mitton 
7410a558357SRichard Mitton   // Find the module's modid.
7429e02dacdSSteve Pucci   int modid_size = 4; // FIXME(spucci): This isn't right for big-endian 64-bit
743b9c1b51eSKate Stone   int64_t modid = ReadUnsignedIntWithSizeInBytes(
744b9c1b51eSKate Stone       link_map + metadata.modid_offset, modid_size);
7450a558357SRichard Mitton   if (modid == -1)
7460a558357SRichard Mitton     return LLDB_INVALID_ADDRESS;
7470a558357SRichard Mitton 
748aaa0ba31SBruce Mitchener   // Lookup the DTV structure for this thread.
7490a558357SRichard Mitton   addr_t dtv_ptr = tp + metadata.dtv_offset;
7509e02dacdSSteve Pucci   addr_t dtv = ReadPointer(dtv_ptr);
7510a558357SRichard Mitton   if (dtv == LLDB_INVALID_ADDRESS)
7520a558357SRichard Mitton     return LLDB_INVALID_ADDRESS;
7530a558357SRichard Mitton 
7540a558357SRichard Mitton   // Find the TLS block for this module.
7550a558357SRichard Mitton   addr_t dtv_slot = dtv + metadata.dtv_slot_size * modid;
7569e02dacdSSteve Pucci   addr_t tls_block = ReadPointer(dtv_slot + metadata.tls_offset);
7570a558357SRichard Mitton 
758a007a6d8SPavel Labath   Log *log = GetLog(LLDBLog::DynamicLoader);
75963e5fb76SJonas Devlieghere   LLDB_LOGF(log,
76063e5fb76SJonas Devlieghere             "DynamicLoaderPOSIXDYLD::Performed TLS lookup: "
761b9c1b51eSKate Stone             "module=%s, link_map=0x%" PRIx64 ", tp=0x%" PRIx64
762b9c1b51eSKate Stone             ", modid=%" PRId64 ", tls_block=0x%" PRIx64 "\n",
763b9c1b51eSKate Stone             module_sp->GetObjectName().AsCString(""), link_map, tp,
764b9c1b51eSKate Stone             (int64_t)modid, tls_block);
7650a558357SRichard Mitton 
766c7bb34f6SGreg Clayton   if (tls_block == LLDB_INVALID_ADDRESS)
767c7bb34f6SGreg Clayton     return LLDB_INVALID_ADDRESS;
768c7bb34f6SGreg Clayton   else
7690ba05f18SGreg Clayton     return tls_block + tls_file_addr;
7700a558357SRichard Mitton }
7710ddd41cdSOleksiy Vyalov 
ResolveExecutableModule(lldb::ModuleSP & module_sp)772b9c1b51eSKate Stone void DynamicLoaderPOSIXDYLD::ResolveExecutableModule(
773b9c1b51eSKate Stone     lldb::ModuleSP &module_sp) {
774a007a6d8SPavel Labath   Log *log = GetLog(LLDBLog::DynamicLoader);
7756474721cSOleksiy Vyalov 
7760ddd41cdSOleksiy Vyalov   if (m_process == nullptr)
7776474721cSOleksiy Vyalov     return;
7780ddd41cdSOleksiy Vyalov 
7790ddd41cdSOleksiy Vyalov   auto &target = m_process->GetTarget();
7806474721cSOleksiy Vyalov   const auto platform_sp = target.GetPlatform();
7810ddd41cdSOleksiy Vyalov 
7826474721cSOleksiy Vyalov   ProcessInstanceInfo process_info;
783b9c1b51eSKate Stone   if (!m_process->GetProcessInfo(process_info)) {
78463e5fb76SJonas Devlieghere     LLDB_LOGF(log,
78563e5fb76SJonas Devlieghere               "DynamicLoaderPOSIXDYLD::%s - failed to get process info for "
786b9c1b51eSKate Stone               "pid %" PRIu64,
7876474721cSOleksiy Vyalov               __FUNCTION__, m_process->GetID());
7886474721cSOleksiy Vyalov     return;
7896474721cSOleksiy Vyalov   }
7906474721cSOleksiy Vyalov 
79163e5fb76SJonas Devlieghere   LLDB_LOGF(
79263e5fb76SJonas Devlieghere       log, "DynamicLoaderPOSIXDYLD::%s - got executable by pid %" PRIu64 ": %s",
793b9c1b51eSKate Stone       __FUNCTION__, m_process->GetID(),
794b9c1b51eSKate Stone       process_info.GetExecutableFile().GetPath().c_str());
7956474721cSOleksiy Vyalov 
796b9c1b51eSKate Stone   ModuleSpec module_spec(process_info.GetExecutableFile(),
797b9c1b51eSKate Stone                          process_info.GetArchitecture());
7986474721cSOleksiy Vyalov   if (module_sp && module_sp->MatchesModuleSpec(module_spec))
7996474721cSOleksiy Vyalov     return;
8006474721cSOleksiy Vyalov 
801a3f245ffSOleksiy Vyalov   const auto executable_search_paths(Target::GetDefaultExecutableSearchPaths());
802a3f245ffSOleksiy Vyalov   auto error = platform_sp->ResolveExecutable(
803b9c1b51eSKate Stone       module_spec, module_sp,
804b9c1b51eSKate Stone       !executable_search_paths.IsEmpty() ? &executable_search_paths : nullptr);
805b9c1b51eSKate Stone   if (error.Fail()) {
8066474721cSOleksiy Vyalov     StreamString stream;
8076474721cSOleksiy Vyalov     module_spec.Dump(stream);
8086474721cSOleksiy Vyalov 
80963e5fb76SJonas Devlieghere     LLDB_LOGF(log,
81063e5fb76SJonas Devlieghere               "DynamicLoaderPOSIXDYLD::%s - failed to resolve executable "
811b9c1b51eSKate Stone               "with module spec \"%s\": %s",
812c156427dSZachary Turner               __FUNCTION__, stream.GetData(), error.AsCString());
8136474721cSOleksiy Vyalov     return;
8146474721cSOleksiy Vyalov   }
8156474721cSOleksiy Vyalov 
816f9a07e9fSJonas Devlieghere   target.SetExecutableModule(module_sp, eLoadDependentsNo);
8170ddd41cdSOleksiy Vyalov }
818c7f76104SPavel Labath 
AlwaysRelyOnEHUnwindInfo(lldb_private::SymbolContext & sym_ctx)819b9c1b51eSKate Stone bool DynamicLoaderPOSIXDYLD::AlwaysRelyOnEHUnwindInfo(
820b9c1b51eSKate Stone     lldb_private::SymbolContext &sym_ctx) {
821c7f76104SPavel Labath   ModuleSP module_sp;
822c7f76104SPavel Labath   if (sym_ctx.symbol)
823c7f76104SPavel Labath     module_sp = sym_ctx.symbol->GetAddressRef().GetModule();
824c7f76104SPavel Labath   if (!module_sp && sym_ctx.function)
825b9c1b51eSKate Stone     module_sp =
826b9c1b51eSKate Stone         sym_ctx.function->GetAddressRange().GetBaseAddress().GetModule();
827c7f76104SPavel Labath   if (!module_sp)
828c7f76104SPavel Labath     return false;
829c7f76104SPavel Labath 
830c7f76104SPavel Labath   return module_sp->GetFileSpec().GetPath() == "[vdso]";
831c7f76104SPavel Labath }
832