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