180814287SRaphael Isemann //===-- DynamicLoaderMacOSXDYLD.cpp ---------------------------------------===//
230fdc8d8SChris Lattner //
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
630fdc8d8SChris Lattner //
730fdc8d8SChris Lattner //===----------------------------------------------------------------------===//
830fdc8d8SChris Lattner 
96e30fd05SJonas Devlieghere #include "DynamicLoaderMacOSXDYLD.h"
106e30fd05SJonas Devlieghere #include "DynamicLoaderDarwin.h"
116e30fd05SJonas Devlieghere #include "DynamicLoaderMacOS.h"
126e30fd05SJonas Devlieghere #include "Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h"
136e30fd05SJonas Devlieghere #include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
1430fdc8d8SChris Lattner #include "lldb/Breakpoint/StoppointCallbackContext.h"
1557e1201eSJason Molenda #include "lldb/Core/Debugger.h"
1630fdc8d8SChris Lattner #include "lldb/Core/Module.h"
171f746071SGreg Clayton #include "lldb/Core/ModuleSpec.h"
1830fdc8d8SChris Lattner #include "lldb/Core/PluginManager.h"
191f746071SGreg Clayton #include "lldb/Core/Section.h"
201f746071SGreg Clayton #include "lldb/Symbol/Function.h"
2130fdc8d8SChris Lattner #include "lldb/Symbol/ObjectFile.h"
225fe4d141SJason Molenda #include "lldb/Target/ABI.h"
2330fdc8d8SChris Lattner #include "lldb/Target/RegisterContext.h"
24b9c1b51eSKate Stone #include "lldb/Target/StackFrame.h"
2530fdc8d8SChris Lattner #include "lldb/Target/Target.h"
2630fdc8d8SChris Lattner #include "lldb/Target/Thread.h"
2730fdc8d8SChris Lattner #include "lldb/Target/ThreadPlanRunToAddress.h"
28666cc0b2SZachary Turner #include "lldb/Utility/DataBuffer.h"
29666cc0b2SZachary Turner #include "lldb/Utility/DataBufferHeap.h"
30c34698a8SPavel Labath #include "lldb/Utility/LLDBLog.h"
316f9e6901SZachary Turner #include "lldb/Utility/Log.h"
32d821c997SPavel Labath #include "lldb/Utility/State.h"
3330fdc8d8SChris Lattner 
3430fdc8d8SChris Lattner //#define ENABLE_DEBUG_PRINTF // COMMENT THIS LINE OUT PRIOR TO CHECKIN
3530fdc8d8SChris Lattner #ifdef ENABLE_DEBUG_PRINTF
3676e47d48SRaphael Isemann #include <cstdio>
3730fdc8d8SChris Lattner #define DEBUG_PRINTF(fmt, ...) printf(fmt, ##__VA_ARGS__)
3830fdc8d8SChris Lattner #else
3930fdc8d8SChris Lattner #define DEBUG_PRINTF(fmt, ...)
4030fdc8d8SChris Lattner #endif
4130fdc8d8SChris Lattner 
42ffeb4b60SDaniel Malea #ifndef __APPLE__
43ffeb4b60SDaniel Malea #include "Utility/UuidCompatibility.h"
44b6fddcd7SPavel Labath #else
45b6fddcd7SPavel Labath #include <uuid/uuid.h>
46ffeb4b60SDaniel Malea #endif
47ffeb4b60SDaniel Malea 
4830fdc8d8SChris Lattner using namespace lldb;
4930fdc8d8SChris Lattner using namespace lldb_private;
5030fdc8d8SChris Lattner 
LLDB_PLUGIN_DEFINE(DynamicLoaderMacOSXDYLD)51bba9ba8dSJonas Devlieghere LLDB_PLUGIN_DEFINE(DynamicLoaderMacOSXDYLD)
52fbb4d1e4SJonas Devlieghere 
5305097246SAdrian Prantl // Create an instance of this class. This function is filled into the plugin
5405097246SAdrian Prantl // info class that gets handed out by the plugin factory and allows the lldb to
5505097246SAdrian Prantl // instantiate an instance of this class.
56b9c1b51eSKate Stone DynamicLoader *DynamicLoaderMacOSXDYLD::CreateInstance(Process *process,
57b9c1b51eSKate Stone                                                        bool force) {
5893d3c833SGreg Clayton   bool create = force;
59b9c1b51eSKate Stone   if (!create) {
6093d3c833SGreg Clayton     create = true;
61aa149cbdSGreg Clayton     Module *exe_module = process->GetTarget().GetExecutableModulePointer();
62b9c1b51eSKate Stone     if (exe_module) {
63df0b7d5cSGreg Clayton       ObjectFile *object_file = exe_module->GetObjectFile();
64b9c1b51eSKate Stone       if (object_file) {
6549bce8ecSSean Callanan         create = (object_file->GetStrata() == ObjectFile::eStrataUser);
66df0b7d5cSGreg Clayton       }
67df0b7d5cSGreg Clayton     }
68df0b7d5cSGreg Clayton 
69b9c1b51eSKate Stone     if (create) {
70b9c1b51eSKate Stone       const llvm::Triple &triple_ref =
71b9c1b51eSKate Stone           process->GetTarget().GetArchitecture().GetTriple();
72b9c1b51eSKate Stone       switch (triple_ref.getOS()) {
7370512317SGreg Clayton       case llvm::Triple::Darwin:
7470512317SGreg Clayton       case llvm::Triple::MacOSX:
7570512317SGreg Clayton       case llvm::Triple::IOS:
76a814f704SJason Molenda       case llvm::Triple::TvOS:
77a814f704SJason Molenda       case llvm::Triple::WatchOS:
7832762fd2SJason Molenda       // NEED_BRIDGEOS_TRIPLE case llvm::Triple::BridgeOS:
7970512317SGreg Clayton         create = triple_ref.getVendor() == llvm::Triple::Apple;
8070512317SGreg Clayton         break;
8170512317SGreg Clayton       default:
8270512317SGreg Clayton         create = false;
8370512317SGreg Clayton         break;
8470512317SGreg Clayton       }
85df0b7d5cSGreg Clayton     }
8693d3c833SGreg Clayton   }
8793d3c833SGreg Clayton 
88a6682a41SJonas Devlieghere   if (UseDYLDSPI(process)) {
899ab5dc24SJason Molenda     create = false;
909ab5dc24SJason Molenda   }
919ab5dc24SJason Molenda 
9293d3c833SGreg Clayton   if (create)
9330fdc8d8SChris Lattner     return new DynamicLoaderMacOSXDYLD(process);
94248a1305SKonrad Kleine   return nullptr;
9530fdc8d8SChris Lattner }
9630fdc8d8SChris Lattner 
9730fdc8d8SChris Lattner // Constructor
DynamicLoaderMacOSXDYLD(Process * process)98b9c1b51eSKate Stone DynamicLoaderMacOSXDYLD::DynamicLoaderMacOSXDYLD(Process *process)
99b9c1b51eSKate Stone     : DynamicLoaderDarwin(process),
10030fdc8d8SChris Lattner       m_dyld_all_image_infos_addr(LLDB_INVALID_ADDRESS),
101b9c1b51eSKate Stone       m_dyld_all_image_infos(), m_dyld_all_image_infos_stop_id(UINT32_MAX),
102b9c1b51eSKate Stone       m_break_id(LLDB_INVALID_BREAK_ID), m_mutex(),
103b9c1b51eSKate Stone       m_process_image_addr_is_all_images_infos(false) {}
10430fdc8d8SChris Lattner 
10530fdc8d8SChris Lattner // Destructor
~DynamicLoaderMacOSXDYLD()106b9c1b51eSKate Stone DynamicLoaderMacOSXDYLD::~DynamicLoaderMacOSXDYLD() {
1075fe4d141SJason Molenda   if (LLDB_BREAK_ID_IS_VALID(m_break_id))
1085fe4d141SJason Molenda     m_process->GetTarget().RemoveBreakpointByID(m_break_id);
10930fdc8d8SChris Lattner }
11030fdc8d8SChris Lattner 
ProcessDidExec()111b9c1b51eSKate Stone bool DynamicLoaderMacOSXDYLD::ProcessDidExec() {
1125fe4d141SJason Molenda   std::lock_guard<std::recursive_mutex> baseclass_guard(GetMutex());
11363a27afaSGreg Clayton   bool did_exec = false;
114b9c1b51eSKate Stone   if (m_process) {
11590ba8115SGreg Clayton     // If we are stopped after an exec, we will have only one thread...
116b9c1b51eSKate Stone     if (m_process->GetThreadList().GetSize() == 1) {
11790ba8115SGreg Clayton       // We know if a process has exec'ed if our "m_dyld_all_image_infos_addr"
11890ba8115SGreg Clayton       // value differs from the Process' image info address. When a process
11990ba8115SGreg Clayton       // execs itself it might cause a change if ASLR is enabled.
12090ba8115SGreg Clayton       const addr_t shlib_addr = m_process->GetImageInfoAddress();
121a6682a41SJonas Devlieghere       if (m_process_image_addr_is_all_images_infos &&
122b9c1b51eSKate Stone           shlib_addr != m_dyld_all_image_infos_addr) {
12305097246SAdrian Prantl         // The image info address from the process is the
12405097246SAdrian Prantl         // 'dyld_all_image_infos' address and it has changed.
12563a27afaSGreg Clayton         did_exec = true;
126a6682a41SJonas Devlieghere       } else if (!m_process_image_addr_is_all_images_infos &&
127b9c1b51eSKate Stone                  shlib_addr == m_dyld.address) {
12805097246SAdrian Prantl         // The image info address from the process is the mach_header address
12905097246SAdrian Prantl         // for dyld and it has changed.
13063a27afaSGreg Clayton         did_exec = true;
131b9c1b51eSKate Stone       } else {
13290ba8115SGreg Clayton         // ASLR might be disabled and dyld could have ended up in the same
13305097246SAdrian Prantl         // location. We should try and detect if we are stopped at
13405097246SAdrian Prantl         // '_dyld_start'
13590ba8115SGreg Clayton         ThreadSP thread_sp(m_process->GetThreadList().GetThreadAtIndex(0));
136b9c1b51eSKate Stone         if (thread_sp) {
137b57e4a1bSJason Molenda           lldb::StackFrameSP frame_sp(thread_sp->GetStackFrameAtIndex(0));
138b9c1b51eSKate Stone           if (frame_sp) {
139b9c1b51eSKate Stone             const Symbol *symbol =
140b9c1b51eSKate Stone                 frame_sp->GetSymbolContext(eSymbolContextSymbol).symbol;
141b9c1b51eSKate Stone             if (symbol) {
14205cfdb0eSRaphael Isemann               if (symbol->GetName() == "_dyld_start")
14363a27afaSGreg Clayton                 did_exec = true;
14490ba8115SGreg Clayton             }
14590ba8115SGreg Clayton           }
14690ba8115SGreg Clayton         }
14790ba8115SGreg Clayton       }
14863a27afaSGreg Clayton 
149b9c1b51eSKate Stone       if (did_exec) {
15063a27afaSGreg Clayton         m_libpthread_module_wp.reset();
15163a27afaSGreg Clayton         m_pthread_getspecific_addr.Clear();
15290ba8115SGreg Clayton       }
15363a27afaSGreg Clayton     }
15463a27afaSGreg Clayton   }
15563a27afaSGreg Clayton   return did_exec;
15690ba8115SGreg Clayton }
15790ba8115SGreg Clayton 
15830fdc8d8SChris Lattner // Clear out the state of this class.
DoClear()159b9c1b51eSKate Stone void DynamicLoaderMacOSXDYLD::DoClear() {
16016ff8604SSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(m_mutex);
16130fdc8d8SChris Lattner 
1627ac5c86bSJim Ingham   if (LLDB_BREAK_ID_IS_VALID(m_break_id))
1632995077dSJim Ingham     m_process->GetTarget().RemoveBreakpointByID(m_break_id);
16430fdc8d8SChris Lattner 
16530fdc8d8SChris Lattner   m_dyld_all_image_infos_addr = LLDB_INVALID_ADDRESS;
16630fdc8d8SChris Lattner   m_dyld_all_image_infos.Clear();
16730fdc8d8SChris Lattner   m_break_id = LLDB_INVALID_BREAK_ID;
16830fdc8d8SChris Lattner }
16930fdc8d8SChris Lattner 
17030fdc8d8SChris Lattner // Check if we have found DYLD yet
DidSetNotificationBreakpoint()171b9c1b51eSKate Stone bool DynamicLoaderMacOSXDYLD::DidSetNotificationBreakpoint() {
17230fdc8d8SChris Lattner   return LLDB_BREAK_ID_IS_VALID(m_break_id);
17330fdc8d8SChris Lattner }
17430fdc8d8SChris Lattner 
ClearNotificationBreakpoint()175b9c1b51eSKate Stone void DynamicLoaderMacOSXDYLD::ClearNotificationBreakpoint() {
176b9c1b51eSKate Stone   if (LLDB_BREAK_ID_IS_VALID(m_break_id)) {
1775fe4d141SJason Molenda     m_process->GetTarget().RemoveBreakpointByID(m_break_id);
1785fe4d141SJason Molenda   }
1795fe4d141SJason Molenda }
1805fe4d141SJason Molenda 
18105097246SAdrian Prantl // Try and figure out where dyld is by first asking the Process if it knows
18205097246SAdrian Prantl // (which currently calls down in the lldb::Process to get the DYLD info
18305097246SAdrian Prantl // (available on SnowLeopard only). If that fails, then check in the default
18405097246SAdrian Prantl // addresses.
DoInitialImageFetch()185b9c1b51eSKate Stone void DynamicLoaderMacOSXDYLD::DoInitialImageFetch() {
186b9c1b51eSKate Stone   if (m_dyld_all_image_infos_addr == LLDB_INVALID_ADDRESS) {
18705097246SAdrian Prantl     // Check the image info addr as it might point to the mach header for dyld,
18805097246SAdrian Prantl     // or it might point to the dyld_all_image_infos struct
189c859e2d5SGreg Clayton     const addr_t shlib_addr = m_process->GetImageInfoAddress();
190b9c1b51eSKate Stone     if (shlib_addr != LLDB_INVALID_ADDRESS) {
191b9c1b51eSKate Stone       ByteOrder byte_order =
192b9c1b51eSKate Stone           m_process->GetTarget().GetArchitecture().GetByteOrder();
193c3776bf2SGreg Clayton       uint8_t buf[4];
194c3776bf2SGreg Clayton       DataExtractor data(buf, sizeof(buf), byte_order, 4);
19597206d57SZachary Turner       Status error;
196b9c1b51eSKate Stone       if (m_process->ReadMemory(shlib_addr, buf, 4, error) == 4) {
197c7bece56SGreg Clayton         lldb::offset_t offset = 0;
198c3776bf2SGreg Clayton         uint32_t magic = data.GetU32(&offset);
199b9c1b51eSKate Stone         switch (magic) {
200510938e5SCharles Davis         case llvm::MachO::MH_MAGIC:
201510938e5SCharles Davis         case llvm::MachO::MH_MAGIC_64:
202510938e5SCharles Davis         case llvm::MachO::MH_CIGAM:
203510938e5SCharles Davis         case llvm::MachO::MH_CIGAM_64:
20490ba8115SGreg Clayton           m_process_image_addr_is_all_images_infos = false;
2055fe4d141SJason Molenda           ReadDYLDInfoFromMemoryAndSetNotificationCallback(shlib_addr);
2065fe4d141SJason Molenda           return;
207c3776bf2SGreg Clayton 
208c3776bf2SGreg Clayton         default:
209c3776bf2SGreg Clayton           break;
210c3776bf2SGreg Clayton         }
211c3776bf2SGreg Clayton       }
212c3776bf2SGreg Clayton       // Maybe it points to the all image infos?
213c3776bf2SGreg Clayton       m_dyld_all_image_infos_addr = shlib_addr;
21490ba8115SGreg Clayton       m_process_image_addr_is_all_images_infos = true;
215c3776bf2SGreg Clayton     }
21639f7ee86SGreg Clayton   }
21730fdc8d8SChris Lattner 
218b9c1b51eSKate Stone   if (m_dyld_all_image_infos_addr != LLDB_INVALID_ADDRESS) {
219b9c1b51eSKate Stone     if (ReadAllImageInfosStructure()) {
22030fdc8d8SChris Lattner       if (m_dyld_all_image_infos.dyldImageLoadAddress != LLDB_INVALID_ADDRESS)
221b9c1b51eSKate Stone         ReadDYLDInfoFromMemoryAndSetNotificationCallback(
222b9c1b51eSKate Stone             m_dyld_all_image_infos.dyldImageLoadAddress);
22330fdc8d8SChris Lattner       else
224b9c1b51eSKate Stone         ReadDYLDInfoFromMemoryAndSetNotificationCallback(
225b9c1b51eSKate Stone             m_dyld_all_image_infos_addr & 0xfffffffffff00000ull);
2265fe4d141SJason Molenda       return;
22730fdc8d8SChris Lattner     }
22830fdc8d8SChris Lattner   }
22930fdc8d8SChris Lattner 
23030fdc8d8SChris Lattner   // Check some default values
231aa149cbdSGreg Clayton   Module *executable = m_process->GetTarget().GetExecutableModulePointer();
23230fdc8d8SChris Lattner 
233b9c1b51eSKate Stone   if (executable) {
234dce502edSGreg Clayton     const ArchSpec &exe_arch = executable->GetArchitecture();
235b9c1b51eSKate Stone     if (exe_arch.GetAddressByteSize() == 8) {
2365fe4d141SJason Molenda       ReadDYLDInfoFromMemoryAndSetNotificationCallback(0x7fff5fc00000ull);
237b9c1b51eSKate Stone     } else if (exe_arch.GetMachine() == llvm::Triple::arm ||
238b9c1b51eSKate Stone                exe_arch.GetMachine() == llvm::Triple::thumb ||
2397dd7a360SJason Molenda                exe_arch.GetMachine() == llvm::Triple::aarch64 ||
2407dd7a360SJason Molenda                exe_arch.GetMachine() == llvm::Triple::aarch64_32) {
2415fe4d141SJason Molenda       ReadDYLDInfoFromMemoryAndSetNotificationCallback(0x2fe00000);
242b9c1b51eSKate Stone     } else {
2435fe4d141SJason Molenda       ReadDYLDInfoFromMemoryAndSetNotificationCallback(0x8fe00000);
24430fdc8d8SChris Lattner     }
245dce502edSGreg Clayton   }
24632e0a750SGreg Clayton }
24732e0a750SGreg Clayton 
24805097246SAdrian Prantl // Assume that dyld is in memory at ADDR and try to parse it's load commands
ReadDYLDInfoFromMemoryAndSetNotificationCallback(lldb::addr_t addr)249b9c1b51eSKate Stone bool DynamicLoaderMacOSXDYLD::ReadDYLDInfoFromMemoryAndSetNotificationCallback(
250b9c1b51eSKate Stone     lldb::addr_t addr) {
2515fe4d141SJason Molenda   std::lock_guard<std::recursive_mutex> baseclass_guard(GetMutex());
25230fdc8d8SChris Lattner   DataExtractor data; // Load command data
2539ab5dc24SJason Molenda   static ConstString g_dyld_all_image_infos("dyld_all_image_infos");
25489ed21a8SJason Molenda   static ConstString g_new_dyld_all_image_infos("dyld4::dyld_all_image_infos");
255b9c1b51eSKate Stone   if (ReadMachHeader(addr, &m_dyld.header, &data)) {
256b9c1b51eSKate Stone     if (m_dyld.header.filetype == llvm::MachO::MH_DYLINKER) {
25730fdc8d8SChris Lattner       m_dyld.address = addr;
25830fdc8d8SChris Lattner       ModuleSP dyld_module_sp;
259b9c1b51eSKate Stone       if (ParseLoadCommands(data, m_dyld, &m_dyld.file_spec)) {
260b9c1b51eSKate Stone         if (m_dyld.file_spec) {
2615fe4d141SJason Molenda           UpdateDYLDImageInfoFromNewImageInfo(m_dyld);
26230fdc8d8SChris Lattner         }
26330fdc8d8SChris Lattner       }
2645fe4d141SJason Molenda       dyld_module_sp = GetDYLDModule();
26530fdc8d8SChris Lattner 
26639f7ee86SGreg Clayton       Target &target = m_process->GetTarget();
26739f7ee86SGreg Clayton 
268b9c1b51eSKate Stone       if (m_dyld_all_image_infos_addr == LLDB_INVALID_ADDRESS &&
269b9c1b51eSKate Stone           dyld_module_sp.get()) {
270b9c1b51eSKate Stone         const Symbol *symbol = dyld_module_sp->FindFirstSymbolWithNameAndType(
271b9c1b51eSKate Stone             g_dyld_all_image_infos, eSymbolTypeData);
27289ed21a8SJason Molenda         if (!symbol) {
27389ed21a8SJason Molenda           symbol = dyld_module_sp->FindFirstSymbolWithNameAndType(
27489ed21a8SJason Molenda               g_new_dyld_all_image_infos, eSymbolTypeData);
27589ed21a8SJason Molenda         }
27630fdc8d8SChris Lattner         if (symbol)
277358cf1eaSGreg Clayton           m_dyld_all_image_infos_addr = symbol->GetLoadAddress(&target);
27830fdc8d8SChris Lattner       }
27930fdc8d8SChris Lattner 
28030fdc8d8SChris Lattner       // Update all image infos
281f72ce3a2SJim Ingham       InitializeFromAllImageInfos();
28230fdc8d8SChris Lattner 
28305097246SAdrian Prantl       // If we didn't have an executable before, but now we do, then the dyld
28405097246SAdrian Prantl       // module shared pointer might be unique and we may need to add it again
28505097246SAdrian Prantl       // (since Target::SetExecutableModule() will clear the images). So append
28605097246SAdrian Prantl       // the dyld module back to the list if it is
28730fdc8d8SChris Lattner       /// unique!
288b9c1b51eSKate Stone       if (dyld_module_sp) {
28939f7ee86SGreg Clayton         target.GetImages().AppendIfNeeded(dyld_module_sp);
29030fdc8d8SChris Lattner 
291b9c1b51eSKate Stone         // At this point we should have read in dyld's module, and so we should
292b9c1b51eSKate Stone         // set breakpoints in it:
2936200471aSJim Ingham         ModuleList modules;
2946200471aSJim Ingham         modules.Append(dyld_module_sp);
29539f7ee86SGreg Clayton         target.ModulesDidLoad(modules);
2965fe4d141SJason Molenda         SetDYLDModule(dyld_module_sp);
2976200471aSJim Ingham       }
2989ab5dc24SJason Molenda 
29930fdc8d8SChris Lattner       return true;
30030fdc8d8SChris Lattner     }
30130fdc8d8SChris Lattner   }
30230fdc8d8SChris Lattner   return false;
30330fdc8d8SChris Lattner }
30430fdc8d8SChris Lattner 
NeedToDoInitialImageFetch()305b9c1b51eSKate Stone bool DynamicLoaderMacOSXDYLD::NeedToDoInitialImageFetch() {
30630fdc8d8SChris Lattner   return m_dyld_all_image_infos_addr == LLDB_INVALID_ADDRESS;
30730fdc8d8SChris Lattner }
30830fdc8d8SChris Lattner 
30930fdc8d8SChris Lattner // Static callback function that gets called when our DYLD notification
31005097246SAdrian Prantl // breakpoint gets hit. We update all of our image infos and then let our super
31105097246SAdrian Prantl // class DynamicLoader class decide if we should stop or not (based on global
31205097246SAdrian Prantl // preference).
NotifyBreakpointHit(void * baton,StoppointCallbackContext * context,lldb::user_id_t break_id,lldb::user_id_t break_loc_id)313b9c1b51eSKate Stone bool DynamicLoaderMacOSXDYLD::NotifyBreakpointHit(
314b9c1b51eSKate Stone     void *baton, StoppointCallbackContext *context, lldb::user_id_t break_id,
315b9c1b51eSKate Stone     lldb::user_id_t break_loc_id) {
31630fdc8d8SChris Lattner   // Let the event know that the images have changed
317f72ce3a2SJim Ingham   // DYLD passes three arguments to the notification breakpoint.
31805097246SAdrian Prantl   // Arg1: enum dyld_image_mode mode - 0 = adding, 1 = removing Arg2: uint32_t
31905097246SAdrian Prantl   // infoCount        - Number of shared libraries added Arg3: dyld_image_info
32005097246SAdrian Prantl   // info[]    - Array of structs of the form:
321b9c1b51eSKate Stone   //                                     const struct mach_header
322b9c1b51eSKate Stone   //                                     *imageLoadAddress
323f72ce3a2SJim Ingham   //                                     const char               *imageFilePath
324f72ce3a2SJim Ingham   //                                     uintptr_t imageFileModDate (a time_t)
325f72ce3a2SJim Ingham 
32630fdc8d8SChris Lattner   DynamicLoaderMacOSXDYLD *dyld_instance = (DynamicLoaderMacOSXDYLD *)baton;
327f72ce3a2SJim Ingham 
328b9c1b51eSKate Stone   // First step is to see if we've already initialized the all image infos.  If
32905097246SAdrian Prantl   // we haven't then this function will do so and return true.  In the course
33005097246SAdrian Prantl   // of initializing the all_image_infos it will read the complete current
33105097246SAdrian Prantl   // state, so we don't need to figure out what has changed from the data
33205097246SAdrian Prantl   // passed in to us.
333f72ce3a2SJim Ingham 
3347ac5c86bSJim Ingham   ExecutionContext exe_ctx(context->exe_ctx_ref);
3357ac5c86bSJim Ingham   Process *process = exe_ctx.GetProcessPtr();
3367ac5c86bSJim Ingham 
337b9c1b51eSKate Stone   // This is a sanity check just in case this dyld_instance is an old dyld
338b9c1b51eSKate Stone   // plugin's breakpoint still lying around.
3397ac5c86bSJim Ingham   if (process != dyld_instance->m_process)
3407ac5c86bSJim Ingham     return false;
3417ac5c86bSJim Ingham 
342f72ce3a2SJim Ingham   if (dyld_instance->InitializeFromAllImageInfos())
343f72ce3a2SJim Ingham     return dyld_instance->GetStopWhenImagesChange();
344f72ce3a2SJim Ingham 
345f72ce3a2SJim Ingham   const lldb::ABISP &abi = process->GetABI();
346b9c1b51eSKate Stone   if (abi) {
347b9c1b51eSKate Stone     // Build up the value array to store the three arguments given above, then
348b9c1b51eSKate Stone     // get the values from the ABI:
349f72ce3a2SJim Ingham 
3506e3b0cc2SRaphael Isemann     TypeSystemClang *clang_ast_context =
351594308c7SRaphael Isemann         ScratchTypeSystemClang::GetForTarget(process->GetTarget());
3523031818aSAlex Langford     if (!clang_ast_context)
3533031818aSAlex Langford       return false;
3543031818aSAlex Langford 
355f72ce3a2SJim Ingham     ValueList argument_values;
356f72ce3a2SJim Ingham     Value input_value;
357f72ce3a2SJim Ingham 
358b9c1b51eSKate Stone     CompilerType clang_void_ptr_type =
359b9c1b51eSKate Stone         clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
360b9c1b51eSKate Stone     CompilerType clang_uint32_type =
361b9c1b51eSKate Stone         clang_ast_context->GetBuiltinTypeForEncodingAndBitSize(
362b9c1b51eSKate Stone             lldb::eEncodingUint, 32);
363057efa99SAdrian Prantl     input_value.SetValueType(Value::ValueType::Scalar);
36499558cc4SGreg Clayton     input_value.SetCompilerType(clang_uint32_type);
365b9c1b51eSKate Stone     //        input_value.SetContext (Value::eContextTypeClangType,
366b9c1b51eSKate Stone     //        clang_uint32_type);
367f72ce3a2SJim Ingham     argument_values.PushValue(input_value);
368f72ce3a2SJim Ingham     argument_values.PushValue(input_value);
36999558cc4SGreg Clayton     input_value.SetCompilerType(clang_void_ptr_type);
370b9c1b51eSKate Stone     //        input_value.SetContext (Value::eContextTypeClangType,
371b9c1b51eSKate Stone     //        clang_void_ptr_type);
372f72ce3a2SJim Ingham     argument_values.PushValue(input_value);
373f72ce3a2SJim Ingham 
374b9c1b51eSKate Stone     if (abi->GetArgumentValues(exe_ctx.GetThreadRef(), argument_values)) {
375b9c1b51eSKate Stone       uint32_t dyld_mode =
376b9c1b51eSKate Stone           argument_values.GetValueAtIndex(0)->GetScalar().UInt(-1);
377b9c1b51eSKate Stone       if (dyld_mode != static_cast<uint32_t>(-1)) {
378b9c1b51eSKate Stone         // Okay the mode was right, now get the number of elements, and the
379b9c1b51eSKate Stone         // array of new elements...
380b9c1b51eSKate Stone         uint32_t image_infos_count =
381b9c1b51eSKate Stone             argument_values.GetValueAtIndex(1)->GetScalar().UInt(-1);
382b9c1b51eSKate Stone         if (image_infos_count != static_cast<uint32_t>(-1)) {
383b9c1b51eSKate Stone           // Got the number added, now go through the array of added elements,
38405097246SAdrian Prantl           // putting out the mach header address, and adding the image. Note,
38505097246SAdrian Prantl           // I'm not putting in logging here, since the AddModules &
38605097246SAdrian Prantl           // RemoveModules functions do all the logging internally.
387f72ce3a2SJim Ingham 
388b9c1b51eSKate Stone           lldb::addr_t image_infos_addr =
389b9c1b51eSKate Stone               argument_values.GetValueAtIndex(2)->GetScalar().ULongLong();
390b9c1b51eSKate Stone           if (dyld_mode == 0) {
391f72ce3a2SJim Ingham             // This is add:
392b9c1b51eSKate Stone             dyld_instance->AddModulesUsingImageInfosAddress(image_infos_addr,
393b9c1b51eSKate Stone                                                             image_infos_count);
394b9c1b51eSKate Stone           } else {
395f72ce3a2SJim Ingham             // This is remove:
396b9c1b51eSKate Stone             dyld_instance->RemoveModulesUsingImageInfosAddress(
397b9c1b51eSKate Stone                 image_infos_addr, image_infos_count);
398f72ce3a2SJim Ingham           }
399f72ce3a2SJim Ingham         }
400f72ce3a2SJim Ingham       }
401f72ce3a2SJim Ingham     }
402b9c1b51eSKate Stone   } else {
4032fc38b2bSJonas Devlieghere     Target &target = process->GetTarget();
4042fc38b2bSJonas Devlieghere     Debugger::ReportWarning(
4052fc38b2bSJonas Devlieghere         "no ABI plugin located for triple " +
4062fc38b2bSJonas Devlieghere             target.GetArchitecture().GetTriple().getTriple() +
4072fc38b2bSJonas Devlieghere             ": shared libraries will not be registered",
4082fc38b2bSJonas Devlieghere         target.GetDebugger().GetID());
40957e1201eSJason Molenda   }
410f72ce3a2SJim Ingham 
41130fdc8d8SChris Lattner   // Return true to stop the target, false to just let the target run
41230fdc8d8SChris Lattner   return dyld_instance->GetStopWhenImagesChange();
41330fdc8d8SChris Lattner }
41430fdc8d8SChris Lattner 
ReadAllImageInfosStructure()415b9c1b51eSKate Stone bool DynamicLoaderMacOSXDYLD::ReadAllImageInfosStructure() {
41616ff8604SSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(m_mutex);
4173af9ea56SGreg Clayton 
4183af9ea56SGreg Clayton   // the all image infos is already valid for this process stop ID
4193af9ea56SGreg Clayton   if (m_process->GetStopID() == m_dyld_all_image_infos_stop_id)
4203af9ea56SGreg Clayton     return true;
4213af9ea56SGreg Clayton 
42230fdc8d8SChris Lattner   m_dyld_all_image_infos.Clear();
423b9c1b51eSKate Stone   if (m_dyld_all_image_infos_addr != LLDB_INVALID_ADDRESS) {
424b9c1b51eSKate Stone     ByteOrder byte_order =
425b9c1b51eSKate Stone         m_process->GetTarget().GetArchitecture().GetByteOrder();
42649034417SJason Molenda     uint32_t addr_size =
42749034417SJason Molenda         m_process->GetTarget().GetArchitecture().GetAddressByteSize();
4283af9ea56SGreg Clayton 
42930fdc8d8SChris Lattner     uint8_t buf[256];
4303af9ea56SGreg Clayton     DataExtractor data(buf, sizeof(buf), byte_order, addr_size);
431c7bece56SGreg Clayton     lldb::offset_t offset = 0;
4323af9ea56SGreg Clayton 
4339ec89fdeSJason Molenda     const size_t count_v2 = sizeof(uint32_t) + // version
4349ec89fdeSJason Molenda                             sizeof(uint32_t) + // infoArrayCount
4359ec89fdeSJason Molenda                             addr_size +        // infoArray
4369ec89fdeSJason Molenda                             addr_size +        // notification
437b9c1b51eSKate Stone                             addr_size + // processDetachedFromSharedRegion +
438b9c1b51eSKate Stone                                         // libSystemInitialized + pad
43930fdc8d8SChris Lattner                             addr_size;  // dyldImageLoadAddress
440b9c1b51eSKate Stone     const size_t count_v11 = count_v2 + addr_size +  // jitInfo
4419ec89fdeSJason Molenda                              addr_size +             // dyldVersion
4429ec89fdeSJason Molenda                              addr_size +             // errorMessage
4439ec89fdeSJason Molenda                              addr_size +             // terminationFlags
4449ec89fdeSJason Molenda                              addr_size +             // coreSymbolicationShmPage
4459ec89fdeSJason Molenda                              addr_size +             // systemOrderFlag
4469ec89fdeSJason Molenda                              addr_size +             // uuidArrayCount
4479ec89fdeSJason Molenda                              addr_size +             // uuidArray
4489ec89fdeSJason Molenda                              addr_size +             // dyldAllImageInfosAddress
4499ec89fdeSJason Molenda                              addr_size +             // initialImageCount
4509ec89fdeSJason Molenda                              addr_size +             // errorKind
4519ec89fdeSJason Molenda                              addr_size +             // errorClientOfDylibPath
4529ec89fdeSJason Molenda                              addr_size +             // errorTargetDylibPath
4539ec89fdeSJason Molenda                              addr_size;              // errorSymbol
454b9c1b51eSKate Stone     const size_t count_v13 = count_v11 + addr_size + // sharedCacheSlide
45553756c4aSJason Molenda                              sizeof(uuid_t);         // sharedCacheUUID
4568a67bf72SBruce Mitchener     UNUSED_IF_ASSERT_DISABLED(count_v13);
45753756c4aSJason Molenda     assert(sizeof(buf) >= count_v13);
4589ec89fdeSJason Molenda 
45997206d57SZachary Turner     Status error;
460b9c1b51eSKate Stone     if (m_process->ReadMemory(m_dyld_all_image_infos_addr, buf, 4, error) ==
461b9c1b51eSKate Stone         4) {
4629ec89fdeSJason Molenda       m_dyld_all_image_infos.version = data.GetU32(&offset);
46305097246SAdrian Prantl       // If anything in the high byte is set, we probably got the byte order
46405097246SAdrian Prantl       // incorrect (the process might not have it set correctly yet due to
46505097246SAdrian Prantl       // attaching to a program without a specified file).
466b9c1b51eSKate Stone       if (m_dyld_all_image_infos.version & 0xff000000) {
46705097246SAdrian Prantl         // We have guessed the wrong byte order. Swap it and try reading the
46805097246SAdrian Prantl         // version again.
4693af9ea56SGreg Clayton         if (byte_order == eByteOrderLittle)
4703af9ea56SGreg Clayton           byte_order = eByteOrderBig;
4713af9ea56SGreg Clayton         else
4723af9ea56SGreg Clayton           byte_order = eByteOrderLittle;
4733af9ea56SGreg Clayton 
4743af9ea56SGreg Clayton         data.SetByteOrder(byte_order);
4753af9ea56SGreg Clayton         offset = 0;
4763af9ea56SGreg Clayton         m_dyld_all_image_infos.version = data.GetU32(&offset);
4773af9ea56SGreg Clayton       }
478b9c1b51eSKate Stone     } else {
4799ec89fdeSJason Molenda       return false;
4809ec89fdeSJason Molenda     }
4819ec89fdeSJason Molenda 
482b9c1b51eSKate Stone     const size_t count =
483b9c1b51eSKate Stone         (m_dyld_all_image_infos.version >= 11) ? count_v11 : count_v2;
4849ec89fdeSJason Molenda 
485b9c1b51eSKate Stone     const size_t bytes_read =
486b9c1b51eSKate Stone         m_process->ReadMemory(m_dyld_all_image_infos_addr, buf, count, error);
487b9c1b51eSKate Stone     if (bytes_read == count) {
4883af9ea56SGreg Clayton       offset = 0;
48930fdc8d8SChris Lattner       m_dyld_all_image_infos.version = data.GetU32(&offset);
49030fdc8d8SChris Lattner       m_dyld_all_image_infos.dylib_info_count = data.GetU32(&offset);
4910863f675SPavel Labath       m_dyld_all_image_infos.dylib_info_addr = data.GetAddress(&offset);
4920863f675SPavel Labath       m_dyld_all_image_infos.notification = data.GetAddress(&offset);
493b9c1b51eSKate Stone       m_dyld_all_image_infos.processDetachedFromSharedRegion =
494b9c1b51eSKate Stone           data.GetU8(&offset);
49530fdc8d8SChris Lattner       m_dyld_all_image_infos.libSystemInitialized = data.GetU8(&offset);
49630fdc8d8SChris Lattner       // Adjust for padding.
49730fdc8d8SChris Lattner       offset += addr_size - 2;
4980863f675SPavel Labath       m_dyld_all_image_infos.dyldImageLoadAddress = data.GetAddress(&offset);
499b9c1b51eSKate Stone       if (m_dyld_all_image_infos.version >= 11) {
5009ec89fdeSJason Molenda         offset += addr_size * 8;
5010863f675SPavel Labath         uint64_t dyld_all_image_infos_addr = data.GetAddress(&offset);
5029ec89fdeSJason Molenda 
503b9c1b51eSKate Stone         // When we started, we were given the actual address of the
50405097246SAdrian Prantl         // all_image_infos struct (probably via TASK_DYLD_INFO) in memory -
50505097246SAdrian Prantl         // this address is stored in m_dyld_all_image_infos_addr and is the
50605097246SAdrian Prantl         // most accurate address we have.
5079ec89fdeSJason Molenda 
508b9c1b51eSKate Stone         // We read the dyld_all_image_infos struct from memory; it contains its
50905097246SAdrian Prantl         // own address. If the address in the struct does not match the actual
51005097246SAdrian Prantl         // address, the dyld we're looking at has been loaded at a different
51105097246SAdrian Prantl         // location (slid) from where it intended to load.  The addresses in
51205097246SAdrian Prantl         // the dyld_all_image_infos struct are the original, non-slid
51305097246SAdrian Prantl         // addresses, and need to be adjusted.  Most importantly the address of
51405097246SAdrian Prantl         // dyld and the notification address need to be adjusted.
5159ec89fdeSJason Molenda 
516b9c1b51eSKate Stone         if (dyld_all_image_infos_addr != m_dyld_all_image_infos_addr) {
517b9c1b51eSKate Stone           uint64_t image_infos_offset =
518b9c1b51eSKate Stone               dyld_all_image_infos_addr -
519b9c1b51eSKate Stone               m_dyld_all_image_infos.dyldImageLoadAddress;
520b9c1b51eSKate Stone           uint64_t notification_offset =
521b9c1b51eSKate Stone               m_dyld_all_image_infos.notification -
522b9c1b51eSKate Stone               m_dyld_all_image_infos.dyldImageLoadAddress;
523b9c1b51eSKate Stone           m_dyld_all_image_infos.dyldImageLoadAddress =
524b9c1b51eSKate Stone               m_dyld_all_image_infos_addr - image_infos_offset;
525b9c1b51eSKate Stone           m_dyld_all_image_infos.notification =
526b9c1b51eSKate Stone               m_dyld_all_image_infos.dyldImageLoadAddress + notification_offset;
5279ec89fdeSJason Molenda         }
52830fdc8d8SChris Lattner       }
5293af9ea56SGreg Clayton       m_dyld_all_image_infos_stop_id = m_process->GetStopID();
53030fdc8d8SChris Lattner       return true;
53130fdc8d8SChris Lattner     }
53230fdc8d8SChris Lattner   }
53330fdc8d8SChris Lattner   return false;
53430fdc8d8SChris Lattner }
53530fdc8d8SChris Lattner 
AddModulesUsingImageInfosAddress(lldb::addr_t image_infos_addr,uint32_t image_infos_count)536b9c1b51eSKate Stone bool DynamicLoaderMacOSXDYLD::AddModulesUsingImageInfosAddress(
537b9c1b51eSKate Stone     lldb::addr_t image_infos_addr, uint32_t image_infos_count) {
5385fe4d141SJason Molenda   ImageInfo::collection image_infos;
539a007a6d8SPavel Labath   Log *log = GetLog(LLDBLog::DynamicLoader);
54063e5fb76SJonas Devlieghere   LLDB_LOGF(log, "Adding %d modules.\n", image_infos_count);
541f72ce3a2SJim Ingham 
54216ff8604SSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(m_mutex);
5435fe4d141SJason Molenda   std::lock_guard<std::recursive_mutex> baseclass_guard(GetMutex());
5443af9ea56SGreg Clayton   if (m_process->GetStopID() == m_dyld_image_infos_stop_id)
545f72ce3a2SJim Ingham     return true;
5463af9ea56SGreg Clayton 
547b9c1b51eSKate Stone   StructuredData::ObjectSP image_infos_json_sp =
548b9c1b51eSKate Stone       m_process->GetLoadedDynamicLibrariesInfos(image_infos_addr,
549b9c1b51eSKate Stone                                                 image_infos_count);
550b9c1b51eSKate Stone   if (image_infos_json_sp.get() && image_infos_json_sp->GetAsDictionary() &&
551b9c1b51eSKate Stone       image_infos_json_sp->GetAsDictionary()->HasKey("images") &&
552b9c1b51eSKate Stone       image_infos_json_sp->GetAsDictionary()
553b9c1b51eSKate Stone           ->GetValueForKey("images")
554b9c1b51eSKate Stone           ->GetAsArray() &&
555b9c1b51eSKate Stone       image_infos_json_sp->GetAsDictionary()
556b9c1b51eSKate Stone               ->GetValueForKey("images")
557b9c1b51eSKate Stone               ->GetAsArray()
558b9c1b51eSKate Stone               ->GetSize() == image_infos_count) {
55920ee21bdSJason Molenda     bool return_value = false;
560b9c1b51eSKate Stone     if (JSONImageInformationIntoImageInfo(image_infos_json_sp, image_infos)) {
5619ab5dc24SJason Molenda       UpdateSpecialBinariesFromNewImageInfos(image_infos);
56220ee21bdSJason Molenda       return_value = AddModulesUsingImageInfos(image_infos);
56320ee21bdSJason Molenda     }
56420ee21bdSJason Molenda     m_dyld_image_infos_stop_id = m_process->GetStopID();
56520ee21bdSJason Molenda     return return_value;
56620ee21bdSJason Molenda   }
56720ee21bdSJason Molenda 
568f72ce3a2SJim Ingham   if (!ReadImageInfos(image_infos_addr, image_infos_count, image_infos))
569f72ce3a2SJim Ingham     return false;
57030fdc8d8SChris Lattner 
571f72ce3a2SJim Ingham   UpdateImageInfosHeaderAndLoadCommands(image_infos, image_infos_count, false);
572f72ce3a2SJim Ingham   bool return_value = AddModulesUsingImageInfos(image_infos);
5733af9ea56SGreg Clayton   m_dyld_image_infos_stop_id = m_process->GetStopID();
574f72ce3a2SJim Ingham   return return_value;
57530fdc8d8SChris Lattner }
57630fdc8d8SChris Lattner 
RemoveModulesUsingImageInfosAddress(lldb::addr_t image_infos_addr,uint32_t image_infos_count)577b9c1b51eSKate Stone bool DynamicLoaderMacOSXDYLD::RemoveModulesUsingImageInfosAddress(
578b9c1b51eSKate Stone     lldb::addr_t image_infos_addr, uint32_t image_infos_count) {
5795fe4d141SJason Molenda   ImageInfo::collection image_infos;
580a007a6d8SPavel Labath   Log *log = GetLog(LLDBLog::DynamicLoader);
581f72ce3a2SJim Ingham 
58216ff8604SSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(m_mutex);
5835fe4d141SJason Molenda   std::lock_guard<std::recursive_mutex> baseclass_guard(GetMutex());
584f72ce3a2SJim Ingham   if (m_process->GetStopID() == m_dyld_image_infos_stop_id)
585f72ce3a2SJim Ingham     return true;
586f72ce3a2SJim Ingham 
587b9c1b51eSKate Stone   // First read in the image_infos for the removed modules, and their headers &
588b9c1b51eSKate Stone   // load commands.
589b9c1b51eSKate Stone   if (!ReadImageInfos(image_infos_addr, image_infos_count, image_infos)) {
590f72ce3a2SJim Ingham     if (log)
591f72ce3a2SJim Ingham       log->PutCString("Failed reading image infos array.");
592f72ce3a2SJim Ingham     return false;
593f72ce3a2SJim Ingham   }
594f72ce3a2SJim Ingham 
59563e5fb76SJonas Devlieghere   LLDB_LOGF(log, "Removing %d modules.", image_infos_count);
596f72ce3a2SJim Ingham 
597f72ce3a2SJim Ingham   ModuleList unloaded_module_list;
598b9c1b51eSKate Stone   for (uint32_t idx = 0; idx < image_infos.size(); ++idx) {
599b9c1b51eSKate Stone     if (log) {
60063e5fb76SJonas Devlieghere       LLDB_LOGF(log, "Removing module at address=0x%16.16" PRIx64 ".",
601b9c1b51eSKate Stone                 image_infos[idx].address);
6025160ce5cSGreg Clayton       image_infos[idx].PutToLog(log);
603f72ce3a2SJim Ingham     }
604f72ce3a2SJim Ingham 
60505097246SAdrian Prantl     // Remove this image_infos from the m_all_image_infos.  We do the
60605097246SAdrian Prantl     // comparison by address rather than by file spec because we can have many
60705097246SAdrian Prantl     // modules with the same "file spec" in the case that they are modules
60805097246SAdrian Prantl     // loaded from memory.
609f72ce3a2SJim Ingham     //
61005097246SAdrian Prantl     // Also copy over the uuid from the old entry to the removed entry so we
61105097246SAdrian Prantl     // can use it to lookup the module in the module list.
612f72ce3a2SJim Ingham 
613*98186defSSlava Gurevich     bool found = false;
614*98186defSSlava Gurevich 
615*98186defSSlava Gurevich     for (ImageInfo::collection::iterator pos = m_dyld_image_infos.begin();
616*98186defSSlava Gurevich          pos != m_dyld_image_infos.end(); pos++) {
617b9c1b51eSKate Stone       if (image_infos[idx].address == (*pos).address) {
618f72ce3a2SJim Ingham         image_infos[idx].uuid = (*pos).uuid;
619f72ce3a2SJim Ingham 
620b9c1b51eSKate Stone         // Add the module from this image_info to the "unloaded_module_list".
62105097246SAdrian Prantl         // We'll remove them all at one go later on.
622f72ce3a2SJim Ingham 
623b9c1b51eSKate Stone         ModuleSP unload_image_module_sp(
624248a1305SKonrad Kleine             FindTargetModuleForImageInfo(image_infos[idx], false, nullptr));
625b9c1b51eSKate Stone         if (unload_image_module_sp.get()) {
62604f5672cSJim Ingham           // When we unload, be sure to use the image info from the old list,
62704f5672cSJim Ingham           // since that has sections correctly filled in.
6285fe4d141SJason Molenda           UnloadModuleSections(unload_image_module_sp.get(), *pos);
629f72ce3a2SJim Ingham           unloaded_module_list.AppendIfNeeded(unload_image_module_sp);
630b9c1b51eSKate Stone         } else {
631b9c1b51eSKate Stone           if (log) {
63263e5fb76SJonas Devlieghere             LLDB_LOGF(log, "Could not find module for unloading info entry:");
6335160ce5cSGreg Clayton             image_infos[idx].PutToLog(log);
634f72ce3a2SJim Ingham           }
635f72ce3a2SJim Ingham         }
636f72ce3a2SJim Ingham 
637f72ce3a2SJim Ingham         // Then remove it from the m_dyld_image_infos:
638f72ce3a2SJim Ingham 
639f72ce3a2SJim Ingham         m_dyld_image_infos.erase(pos);
640*98186defSSlava Gurevich         found = true;
641f72ce3a2SJim Ingham         break;
642f72ce3a2SJim Ingham       }
643f72ce3a2SJim Ingham     }
644f72ce3a2SJim Ingham 
645*98186defSSlava Gurevich     if (!found) {
646b9c1b51eSKate Stone       if (log) {
64763e5fb76SJonas Devlieghere         LLDB_LOGF(log, "Could not find image_info entry for unloading image:");
6485160ce5cSGreg Clayton         image_infos[idx].PutToLog(log);
649f72ce3a2SJim Ingham       }
650f72ce3a2SJim Ingham     }
651f72ce3a2SJim Ingham   }
652b9c1b51eSKate Stone   if (unloaded_module_list.GetSize() > 0) {
653b9c1b51eSKate Stone     if (log) {
654f72ce3a2SJim Ingham       log->PutCString("Unloaded:");
655b9c1b51eSKate Stone       unloaded_module_list.LogUUIDAndPaths(
656b9c1b51eSKate Stone           log, "DynamicLoaderMacOSXDYLD::ModulesDidUnload");
657f72ce3a2SJim Ingham     }
6581759848bSEnrico Granata     m_process->GetTarget().GetImages().Remove(unloaded_module_list);
659f72ce3a2SJim Ingham   }
660f72ce3a2SJim Ingham   m_dyld_image_infos_stop_id = m_process->GetStopID();
661f72ce3a2SJim Ingham   return true;
662f72ce3a2SJim Ingham }
663f72ce3a2SJim Ingham 
ReadImageInfos(lldb::addr_t image_infos_addr,uint32_t image_infos_count,ImageInfo::collection & image_infos)664b9c1b51eSKate Stone bool DynamicLoaderMacOSXDYLD::ReadImageInfos(
665b9c1b51eSKate Stone     lldb::addr_t image_infos_addr, uint32_t image_infos_count,
666b9c1b51eSKate Stone     ImageInfo::collection &image_infos) {
6675fe4d141SJason Molenda   std::lock_guard<std::recursive_mutex> baseclass_guard(GetMutex());
6685fe4d141SJason Molenda   const ByteOrder endian = GetByteOrderFromMagic(m_dyld.header.magic);
669f72ce3a2SJim Ingham   const uint32_t addr_size = m_dyld.GetAddressByteSize();
670f72ce3a2SJim Ingham 
671f72ce3a2SJim Ingham   image_infos.resize(image_infos_count);
672f72ce3a2SJim Ingham   const size_t count = image_infos.size() * 3 * addr_size;
673f72ce3a2SJim Ingham   DataBufferHeap info_data(count, 0);
67497206d57SZachary Turner   Status error;
675b9c1b51eSKate Stone   const size_t bytes_read = m_process->ReadMemory(
676b9c1b51eSKate Stone       image_infos_addr, info_data.GetBytes(), info_data.GetByteSize(), error);
677b9c1b51eSKate Stone   if (bytes_read == count) {
678c7bece56SGreg Clayton     lldb::offset_t info_data_offset = 0;
679b9c1b51eSKate Stone     DataExtractor info_data_ref(info_data.GetBytes(), info_data.GetByteSize(),
680b9c1b51eSKate Stone                                 endian, addr_size);
681b9c1b51eSKate Stone     for (size_t i = 0;
682b9c1b51eSKate Stone          i < image_infos.size() && info_data_ref.ValidOffset(info_data_offset);
683b9c1b51eSKate Stone          i++) {
6840863f675SPavel Labath       image_infos[i].address = info_data_ref.GetAddress(&info_data_offset);
6850863f675SPavel Labath       lldb::addr_t path_addr = info_data_ref.GetAddress(&info_data_offset);
6860863f675SPavel Labath       image_infos[i].mod_date = info_data_ref.GetAddress(&info_data_offset);
687f72ce3a2SJim Ingham 
688f72ce3a2SJim Ingham       char raw_path[PATH_MAX];
689b9c1b51eSKate Stone       m_process->ReadCStringFromMemory(path_addr, raw_path, sizeof(raw_path),
690b9c1b51eSKate Stone                                        error);
691f72ce3a2SJim Ingham       // don't resolve the path
692b9c1b51eSKate Stone       if (error.Success()) {
6938f3be7a3SJonas Devlieghere         image_infos[i].file_spec.SetFile(raw_path, FileSpec::Style::native);
694f72ce3a2SJim Ingham       }
695e91b7957SGreg Clayton     }
696f72ce3a2SJim Ingham     return true;
697b9c1b51eSKate Stone   } else {
698f72ce3a2SJim Ingham     return false;
699f72ce3a2SJim Ingham   }
700f72ce3a2SJim Ingham }
701f72ce3a2SJim Ingham 
70205097246SAdrian Prantl // If we have found where the "_dyld_all_image_infos" lives in memory, read the
70305097246SAdrian Prantl // current info from it, and then update all image load addresses (or lack
70405097246SAdrian Prantl // thereof).  Only do this if this is the first time we're reading the dyld
70505097246SAdrian Prantl // infos.  Return true if we actually read anything, and false otherwise.
InitializeFromAllImageInfos()706b9c1b51eSKate Stone bool DynamicLoaderMacOSXDYLD::InitializeFromAllImageInfos() {
707a007a6d8SPavel Labath   Log *log = GetLog(LLDBLog::DynamicLoader);
708f72ce3a2SJim Ingham 
70916ff8604SSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(m_mutex);
7105fe4d141SJason Molenda   std::lock_guard<std::recursive_mutex> baseclass_guard(GetMutex());
711b9c1b51eSKate Stone   if (m_process->GetStopID() == m_dyld_image_infos_stop_id ||
712b9c1b51eSKate Stone       m_dyld_image_infos.size() != 0)
713f72ce3a2SJim Ingham     return false;
714f72ce3a2SJim Ingham 
715b9c1b51eSKate Stone   if (ReadAllImageInfosStructure()) {
716a17ec9d8SGreg Clayton     // Nothing to load or unload?
717a17ec9d8SGreg Clayton     if (m_dyld_all_image_infos.dylib_info_count == 0)
718a17ec9d8SGreg Clayton       return true;
719a17ec9d8SGreg Clayton 
720b9c1b51eSKate Stone     if (m_dyld_all_image_infos.dylib_info_addr == 0) {
721b9c1b51eSKate Stone       // DYLD is updating the images now.  So we should say we have no images,
722b9c1b51eSKate Stone       // and then we'll
723f72ce3a2SJim Ingham       // figure it out when we hit the added breakpoint.
724f72ce3a2SJim Ingham       return false;
725b9c1b51eSKate Stone     } else {
726b9c1b51eSKate Stone       if (!AddModulesUsingImageInfosAddress(
727b9c1b51eSKate Stone               m_dyld_all_image_infos.dylib_info_addr,
728b9c1b51eSKate Stone               m_dyld_all_image_infos.dylib_info_count)) {
729a85e6b6cSDaniel Malea         DEBUG_PRINTF("%s", "unable to read all data for all_dylib_infos.");
730f72ce3a2SJim Ingham         m_dyld_image_infos.clear();
731f72ce3a2SJim Ingham       }
732f72ce3a2SJim Ingham     }
733b53cb271SJim Ingham 
734b9c1b51eSKate Stone     // Now we have one more bit of business.  If there is a library left in the
73505097246SAdrian Prantl     // images for our target that doesn't have a load address, then it must be
73605097246SAdrian Prantl     // something that we were expecting to load (for instance we read a load
73705097246SAdrian Prantl     // command for it) but it didn't in fact load - probably because
73805097246SAdrian Prantl     // DYLD_*_PATH pointed to an equivalent version.  We don't want it to stay
73905097246SAdrian Prantl     // in the target's module list or it will confuse us, so unload it here.
740a17ec9d8SGreg Clayton     Target &target = m_process->GetTarget();
741b53cb271SJim Ingham     ModuleList not_loaded_modules;
742f2e05855SJonas Devlieghere     for (ModuleSP module_sp : target.GetImages().Modules()) {
743b9c1b51eSKate Stone       if (!module_sp->IsLoadedInTarget(&target)) {
744b9c1b51eSKate Stone         if (log) {
745b53cb271SJim Ingham           StreamString s;
746c4c464f8SRaphael Isemann           module_sp->GetDescription(s.AsRawOstream());
74763e5fb76SJonas Devlieghere           LLDB_LOGF(log, "Unloading pre-run module: %s.", s.GetData());
748b53cb271SJim Ingham         }
749b53cb271SJim Ingham         not_loaded_modules.Append(module_sp);
750b53cb271SJim Ingham       }
751b53cb271SJim Ingham     }
752b53cb271SJim Ingham 
753b9c1b51eSKate Stone     if (not_loaded_modules.GetSize() != 0) {
7541759848bSEnrico Granata       target.GetImages().Remove(not_loaded_modules);
755b53cb271SJim Ingham     }
756b53cb271SJim Ingham 
757f72ce3a2SJim Ingham     return true;
758b9c1b51eSKate Stone   } else
759f72ce3a2SJim Ingham     return false;
76030fdc8d8SChris Lattner }
76130fdc8d8SChris Lattner 
76205097246SAdrian Prantl // Read a mach_header at ADDR into HEADER, and also fill in the load command
76305097246SAdrian Prantl // data into LOAD_COMMAND_DATA if it is non-NULL.
76430fdc8d8SChris Lattner //
76530fdc8d8SChris Lattner // Returns true if we succeed, false if we fail for any reason.
ReadMachHeader(lldb::addr_t addr,llvm::MachO::mach_header * header,DataExtractor * load_command_data)766b9c1b51eSKate Stone bool DynamicLoaderMacOSXDYLD::ReadMachHeader(lldb::addr_t addr,
767b9c1b51eSKate Stone                                              llvm::MachO::mach_header *header,
768b9c1b51eSKate Stone                                              DataExtractor *load_command_data) {
76932e0a750SGreg Clayton   DataBufferHeap header_bytes(sizeof(llvm::MachO::mach_header), 0);
77097206d57SZachary Turner   Status error;
771b9c1b51eSKate Stone   size_t bytes_read = m_process->ReadMemory(addr, header_bytes.GetBytes(),
772b9c1b51eSKate Stone                                             header_bytes.GetByteSize(), error);
773b9c1b51eSKate Stone   if (bytes_read == sizeof(llvm::MachO::mach_header)) {
774c7bece56SGreg Clayton     lldb::offset_t offset = 0;
775ed49aed3SGreg Clayton     ::memset(header, 0, sizeof(llvm::MachO::mach_header));
77630fdc8d8SChris Lattner 
777b9c1b51eSKate Stone     // Get the magic byte unswapped so we can figure out what we are dealing
778b9c1b51eSKate Stone     // with
779b9c1b51eSKate Stone     DataExtractor data(header_bytes.GetBytes(), header_bytes.GetByteSize(),
780b9c1b51eSKate Stone                        endian::InlHostByteOrder(), 4);
78130fdc8d8SChris Lattner     header->magic = data.GetU32(&offset);
78230fdc8d8SChris Lattner     lldb::addr_t load_cmd_addr = addr;
783b9c1b51eSKate Stone     data.SetByteOrder(
784b9c1b51eSKate Stone         DynamicLoaderMacOSXDYLD::GetByteOrderFromMagic(header->magic));
785b9c1b51eSKate Stone     switch (header->magic) {
786510938e5SCharles Davis     case llvm::MachO::MH_MAGIC:
787510938e5SCharles Davis     case llvm::MachO::MH_CIGAM:
78830fdc8d8SChris Lattner       data.SetAddressByteSize(4);
78932e0a750SGreg Clayton       load_cmd_addr += sizeof(llvm::MachO::mach_header);
79030fdc8d8SChris Lattner       break;
79130fdc8d8SChris Lattner 
792510938e5SCharles Davis     case llvm::MachO::MH_MAGIC_64:
793510938e5SCharles Davis     case llvm::MachO::MH_CIGAM_64:
79430fdc8d8SChris Lattner       data.SetAddressByteSize(8);
79532e0a750SGreg Clayton       load_cmd_addr += sizeof(llvm::MachO::mach_header_64);
79630fdc8d8SChris Lattner       break;
79730fdc8d8SChris Lattner 
79830fdc8d8SChris Lattner     default:
79930fdc8d8SChris Lattner       return false;
80030fdc8d8SChris Lattner     }
80130fdc8d8SChris Lattner 
80230fdc8d8SChris Lattner     // Read the rest of dyld's mach header
803b9c1b51eSKate Stone     if (data.GetU32(&offset, &header->cputype,
804b9c1b51eSKate Stone                     (sizeof(llvm::MachO::mach_header) / sizeof(uint32_t)) -
805b9c1b51eSKate Stone                         1)) {
806248a1305SKonrad Kleine       if (load_command_data == nullptr)
807b9c1b51eSKate Stone         return true; // We were able to read the mach_header and weren't asked
808b9c1b51eSKate Stone                      // to read the load command bytes
80930fdc8d8SChris Lattner 
810fc54427eSJonas Devlieghere       WritableDataBufferSP load_cmd_data_sp(
811fc54427eSJonas Devlieghere           new DataBufferHeap(header->sizeofcmds, 0));
81230fdc8d8SChris Lattner 
813b9c1b51eSKate Stone       size_t load_cmd_bytes_read =
814b9c1b51eSKate Stone           m_process->ReadMemory(load_cmd_addr, load_cmd_data_sp->GetBytes(),
815b9c1b51eSKate Stone                                 load_cmd_data_sp->GetByteSize(), error);
81630fdc8d8SChris Lattner 
817b9c1b51eSKate Stone       if (load_cmd_bytes_read == header->sizeofcmds) {
81805097246SAdrian Prantl         // Set the load command data and also set the correct endian swap
81905097246SAdrian Prantl         // settings and the correct address size
82030fdc8d8SChris Lattner         load_command_data->SetData(load_cmd_data_sp, 0, header->sizeofcmds);
82130fdc8d8SChris Lattner         load_command_data->SetByteOrder(data.GetByteOrder());
82230fdc8d8SChris Lattner         load_command_data->SetAddressByteSize(data.GetAddressByteSize());
823b9c1b51eSKate Stone         return true; // We successfully read the mach_header and the load
824b9c1b51eSKate Stone                      // command data
82530fdc8d8SChris Lattner       }
82630fdc8d8SChris Lattner 
82730fdc8d8SChris Lattner       return false; // We weren't able to read the load command data
82830fdc8d8SChris Lattner     }
82930fdc8d8SChris Lattner   }
83030fdc8d8SChris Lattner   return false; // We failed the read the mach_header
83130fdc8d8SChris Lattner }
83230fdc8d8SChris Lattner 
83330fdc8d8SChris Lattner // Parse the load commands for an image
ParseLoadCommands(const DataExtractor & data,ImageInfo & dylib_info,FileSpec * lc_id_dylinker)834b9c1b51eSKate Stone uint32_t DynamicLoaderMacOSXDYLD::ParseLoadCommands(const DataExtractor &data,
835b9c1b51eSKate Stone                                                     ImageInfo &dylib_info,
836b9c1b51eSKate Stone                                                     FileSpec *lc_id_dylinker) {
837c7bece56SGreg Clayton   lldb::offset_t offset = 0;
83830fdc8d8SChris Lattner   uint32_t cmd_idx;
83930fdc8d8SChris Lattner   Segment segment;
84030fdc8d8SChris Lattner   dylib_info.Clear(true);
84130fdc8d8SChris Lattner 
842b9c1b51eSKate Stone   for (cmd_idx = 0; cmd_idx < dylib_info.header.ncmds; cmd_idx++) {
84305097246SAdrian Prantl     // Clear out any load command specific data from DYLIB_INFO since we are
84405097246SAdrian Prantl     // about to read it.
84530fdc8d8SChris Lattner 
846b9c1b51eSKate Stone     if (data.ValidOffsetForDataOfSize(offset,
847b9c1b51eSKate Stone                                       sizeof(llvm::MachO::load_command))) {
84832e0a750SGreg Clayton       llvm::MachO::load_command load_cmd;
849c7bece56SGreg Clayton       lldb::offset_t load_cmd_offset = offset;
85030fdc8d8SChris Lattner       load_cmd.cmd = data.GetU32(&offset);
85130fdc8d8SChris Lattner       load_cmd.cmdsize = data.GetU32(&offset);
852b9c1b51eSKate Stone       switch (load_cmd.cmd) {
853b9c1b51eSKate Stone       case llvm::MachO::LC_SEGMENT: {
854b9c1b51eSKate Stone         segment.name.SetTrimmedCStringWithLength(
855b9c1b51eSKate Stone             (const char *)data.GetData(&offset, 16), 16);
85605097246SAdrian Prantl         // We are putting 4 uint32_t values 4 uint64_t values so we have to use
85705097246SAdrian Prantl         // multiple 32 bit gets below.
858cdbf8667SGreg Clayton         segment.vmaddr = data.GetU32(&offset);
859cdbf8667SGreg Clayton         segment.vmsize = data.GetU32(&offset);
860cdbf8667SGreg Clayton         segment.fileoff = data.GetU32(&offset);
861cdbf8667SGreg Clayton         segment.filesize = data.GetU32(&offset);
862cdbf8667SGreg Clayton         // Extract maxprot, initprot, nsects and flags all at once
863cdbf8667SGreg Clayton         data.GetU32(&offset, &segment.maxprot, 4);
86430fdc8d8SChris Lattner         dylib_info.segments.push_back(segment);
865b9c1b51eSKate Stone       } break;
86630fdc8d8SChris Lattner 
867b9c1b51eSKate Stone       case llvm::MachO::LC_SEGMENT_64: {
868b9c1b51eSKate Stone         segment.name.SetTrimmedCStringWithLength(
869b9c1b51eSKate Stone             (const char *)data.GetData(&offset, 16), 16);
870cdbf8667SGreg Clayton         // Extract vmaddr, vmsize, fileoff, and filesize all at once
871cdbf8667SGreg Clayton         data.GetU64(&offset, &segment.vmaddr, 4);
872cdbf8667SGreg Clayton         // Extract maxprot, initprot, nsects and flags all at once
873cdbf8667SGreg Clayton         data.GetU32(&offset, &segment.maxprot, 4);
87430fdc8d8SChris Lattner         dylib_info.segments.push_back(segment);
875b9c1b51eSKate Stone       } break;
87630fdc8d8SChris Lattner 
877510938e5SCharles Davis       case llvm::MachO::LC_ID_DYLINKER:
878b9c1b51eSKate Stone         if (lc_id_dylinker) {
879b9c1b51eSKate Stone           const lldb::offset_t name_offset =
880b9c1b51eSKate Stone               load_cmd_offset + data.GetU32(&offset);
88130fdc8d8SChris Lattner           const char *path = data.PeekCStr(name_offset);
8828f3be7a3SJonas Devlieghere           lc_id_dylinker->SetFile(path, FileSpec::Style::native);
8838f3be7a3SJonas Devlieghere           FileSystem::Instance().Resolve(*lc_id_dylinker);
88430fdc8d8SChris Lattner         }
88530fdc8d8SChris Lattner         break;
88630fdc8d8SChris Lattner 
887510938e5SCharles Davis       case llvm::MachO::LC_UUID:
8882f93fd1fSPavel Labath         dylib_info.uuid = UUID::fromOptionalData(data.GetData(&offset, 16), 16);
88930fdc8d8SChris Lattner         break;
89030fdc8d8SChris Lattner 
89130fdc8d8SChris Lattner       default:
89230fdc8d8SChris Lattner         break;
89330fdc8d8SChris Lattner       }
89430fdc8d8SChris Lattner       // Set offset to be the beginning of the next load command.
89530fdc8d8SChris Lattner       offset = load_cmd_offset + load_cmd.cmdsize;
89630fdc8d8SChris Lattner     }
89730fdc8d8SChris Lattner   }
898cdbf8667SGreg Clayton 
89905097246SAdrian Prantl   // All sections listed in the dyld image info structure will all either be
90005097246SAdrian Prantl   // fixed up already, or they will all be off by a single slide amount that is
90105097246SAdrian Prantl   // determined by finding the first segment that is at file offset zero which
90205097246SAdrian Prantl   // also has bytes (a file size that is greater than zero) in the object file.
903cdbf8667SGreg Clayton 
904cdbf8667SGreg Clayton   // Determine the slide amount (if any)
905cdbf8667SGreg Clayton   const size_t num_sections = dylib_info.segments.size();
906b9c1b51eSKate Stone   for (size_t i = 0; i < num_sections; ++i) {
90705097246SAdrian Prantl     // Iterate through the object file sections to find the first section that
90805097246SAdrian Prantl     // starts of file offset zero and that has bytes in the file...
909b9c1b51eSKate Stone     if ((dylib_info.segments[i].fileoff == 0 &&
910b9c1b51eSKate Stone          dylib_info.segments[i].filesize > 0) ||
91105cfdb0eSRaphael Isemann         (dylib_info.segments[i].name == "__TEXT")) {
912cdbf8667SGreg Clayton       dylib_info.slide = dylib_info.address - dylib_info.segments[i].vmaddr;
91305097246SAdrian Prantl       // We have found the slide amount, so we can exit this for loop.
914cdbf8667SGreg Clayton       break;
915cdbf8667SGreg Clayton     }
916cdbf8667SGreg Clayton   }
91730fdc8d8SChris Lattner   return cmd_idx;
91830fdc8d8SChris Lattner }
91930fdc8d8SChris Lattner 
92030fdc8d8SChris Lattner // Read the mach_header and load commands for each image that the
92130fdc8d8SChris Lattner // _dyld_all_image_infos structure points to and cache the results.
922f72ce3a2SJim Ingham 
UpdateImageInfosHeaderAndLoadCommands(ImageInfo::collection & image_infos,uint32_t infos_count,bool update_executable)923b9c1b51eSKate Stone void DynamicLoaderMacOSXDYLD::UpdateImageInfosHeaderAndLoadCommands(
924b9c1b51eSKate Stone     ImageInfo::collection &image_infos, uint32_t infos_count,
925b9c1b51eSKate Stone     bool update_executable) {
92630fdc8d8SChris Lattner   uint32_t exe_idx = UINT32_MAX;
92730fdc8d8SChris Lattner   // Read any UUID values that we can get
928b9c1b51eSKate Stone   for (uint32_t i = 0; i < infos_count; i++) {
929b9c1b51eSKate Stone     if (!image_infos[i].UUIDValid()) {
93030fdc8d8SChris Lattner       DataExtractor data; // Load command data
931b9c1b51eSKate Stone       if (!ReadMachHeader(image_infos[i].address, &image_infos[i].header,
932b9c1b51eSKate Stone                           &data))
93330fdc8d8SChris Lattner         continue;
93430fdc8d8SChris Lattner 
935248a1305SKonrad Kleine       ParseLoadCommands(data, image_infos[i], nullptr);
93630fdc8d8SChris Lattner 
937510938e5SCharles Davis       if (image_infos[i].header.filetype == llvm::MachO::MH_EXECUTE)
93830fdc8d8SChris Lattner         exe_idx = i;
93930fdc8d8SChris Lattner     }
94030fdc8d8SChris Lattner   }
94130fdc8d8SChris Lattner 
94239f7ee86SGreg Clayton   Target &target = m_process->GetTarget();
94339f7ee86SGreg Clayton 
944b9c1b51eSKate Stone   if (exe_idx < image_infos.size()) {
945a17ec9d8SGreg Clayton     const bool can_create = true;
946248a1305SKonrad Kleine     ModuleSP exe_module_sp(FindTargetModuleForImageInfo(image_infos[exe_idx],
947248a1305SKonrad Kleine                                                         can_create, nullptr));
94830fdc8d8SChris Lattner 
949b9c1b51eSKate Stone     if (exe_module_sp) {
95039f7ee86SGreg Clayton       UpdateImageLoadAddress(exe_module_sp.get(), image_infos[exe_idx]);
95139f7ee86SGreg Clayton 
952b9c1b51eSKate Stone       if (exe_module_sp.get() != target.GetExecutableModulePointer()) {
95332e0a750SGreg Clayton         // Don't load dependent images since we are in dyld where we will know
954fd814c5aSGreg Clayton         // and find out about all images that are loaded. Also when setting the
955fd814c5aSGreg Clayton         // executable module, it will clear the targets module list, and if we
95605097246SAdrian Prantl         // have an in memory dyld module, it will get removed from the list so
95705097246SAdrian Prantl         // we will need to add it back after setting the executable module, so
95805097246SAdrian Prantl         // we first try and see if we already have a weak pointer to the dyld
95905097246SAdrian Prantl         // module, make it into a shared pointer, then add the executable, then
96005097246SAdrian Prantl         // re-add it back to make sure it is always in the list.
9615fe4d141SJason Molenda         ModuleSP dyld_module_sp(GetDYLDModule());
962fd814c5aSGreg Clayton 
96332e0a750SGreg Clayton         m_process->GetTarget().SetExecutableModule(exe_module_sp,
964f9a07e9fSJonas Devlieghere                                                    eLoadDependentsNo);
965fd814c5aSGreg Clayton 
966b9c1b51eSKate Stone         if (dyld_module_sp) {
967b9c1b51eSKate Stone           if (target.GetImages().AppendIfNeeded(dyld_module_sp)) {
9685fe4d141SJason Molenda             std::lock_guard<std::recursive_mutex> baseclass_guard(GetMutex());
9695fe4d141SJason Molenda 
97003d1730aSJim Ingham             // Also add it to the section list.
97103d1730aSJim Ingham             UpdateImageLoadAddress(dyld_module_sp.get(), m_dyld);
97203d1730aSJim Ingham           }
97303d1730aSJim Ingham         }
97430fdc8d8SChris Lattner       }
97530fdc8d8SChris Lattner     }
97630fdc8d8SChris Lattner   }
97730fdc8d8SChris Lattner }
97830fdc8d8SChris Lattner 
97905097246SAdrian Prantl // Dump the _dyld_all_image_infos members and all current image infos that we
98005097246SAdrian Prantl // have parsed to the file handle provided.
PutToLog(Log * log) const981b9c1b51eSKate Stone void DynamicLoaderMacOSXDYLD::PutToLog(Log *log) const {
982248a1305SKonrad Kleine   if (log == nullptr)
98330fdc8d8SChris Lattner     return;
98430fdc8d8SChris Lattner 
98516ff8604SSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(m_mutex);
9865fe4d141SJason Molenda   std::lock_guard<std::recursive_mutex> baseclass_guard(GetMutex());
98763e5fb76SJonas Devlieghere   LLDB_LOGF(log,
988b9c1b51eSKate Stone             "dyld_all_image_infos = { version=%d, count=%d, addr=0x%8.8" PRIx64
989b9c1b51eSKate Stone             ", notify=0x%8.8" PRIx64 " }",
99063e5fb76SJonas Devlieghere             m_dyld_all_image_infos.version,
99163e5fb76SJonas Devlieghere             m_dyld_all_image_infos.dylib_info_count,
99230fdc8d8SChris Lattner             (uint64_t)m_dyld_all_image_infos.dylib_info_addr,
99330fdc8d8SChris Lattner             (uint64_t)m_dyld_all_image_infos.notification);
99430fdc8d8SChris Lattner   size_t i;
99530fdc8d8SChris Lattner   const size_t count = m_dyld_image_infos.size();
996b9c1b51eSKate Stone   if (count > 0) {
9976ba50850SGreg Clayton     log->PutCString("Loaded:");
99830fdc8d8SChris Lattner     for (i = 0; i < count; i++)
99930fdc8d8SChris Lattner       m_dyld_image_infos[i].PutToLog(log);
100030fdc8d8SChris Lattner   }
100130fdc8d8SChris Lattner }
100230fdc8d8SChris Lattner 
SetNotificationBreakpoint()1003b9c1b51eSKate Stone bool DynamicLoaderMacOSXDYLD::SetNotificationBreakpoint() {
1004b9c1b51eSKate Stone   DEBUG_PRINTF("DynamicLoaderMacOSXDYLD::%s() process state = %s\n",
1005b9c1b51eSKate Stone                __FUNCTION__, StateAsCString(m_process->GetState()));
1006b9c1b51eSKate Stone   if (m_break_id == LLDB_INVALID_BREAK_ID) {
1007b9c1b51eSKate Stone     if (m_dyld_all_image_infos.notification != LLDB_INVALID_ADDRESS) {
100830fdc8d8SChris Lattner       Address so_addr;
100905097246SAdrian Prantl       // Set the notification breakpoint and install a breakpoint callback
101005097246SAdrian Prantl       // function that will get called each time the breakpoint gets hit. We
101105097246SAdrian Prantl       // will use this to track when shared libraries get loaded/unloaded.
1012b9c1b51eSKate Stone       bool resolved = m_process->GetTarget().ResolveLoadAddress(
1013b9c1b51eSKate Stone           m_dyld_all_image_infos.notification, so_addr);
1014b9c1b51eSKate Stone       if (!resolved) {
10159ab5dc24SJason Molenda         ModuleSP dyld_module_sp = GetDYLDModule();
1016b9c1b51eSKate Stone         if (dyld_module_sp) {
10175fe4d141SJason Molenda           std::lock_guard<std::recursive_mutex> baseclass_guard(GetMutex());
10185fe4d141SJason Molenda 
10193d5bb326SGreg Clayton           UpdateImageLoadAddress(dyld_module_sp.get(), m_dyld);
1020b9c1b51eSKate Stone           resolved = m_process->GetTarget().ResolveLoadAddress(
1021b9c1b51eSKate Stone               m_dyld_all_image_infos.notification, so_addr);
10223d5bb326SGreg Clayton         }
10233d5bb326SGreg Clayton       }
102430fdc8d8SChris Lattner 
1025b9c1b51eSKate Stone       if (resolved) {
1026b9c1b51eSKate Stone         Breakpoint *dyld_break =
1027b9c1b51eSKate Stone             m_process->GetTarget().CreateBreakpoint(so_addr, true, false).get();
1028b9c1b51eSKate Stone         dyld_break->SetCallback(DynamicLoaderMacOSXDYLD::NotifyBreakpointHit,
1029b9c1b51eSKate Stone                                 this, true);
10302995077dSJim Ingham         dyld_break->SetBreakpointKind("shared-library-event");
103130fdc8d8SChris Lattner         m_break_id = dyld_break->GetID();
103230fdc8d8SChris Lattner       }
103330fdc8d8SChris Lattner     }
103430fdc8d8SChris Lattner   }
103530fdc8d8SChris Lattner   return m_break_id != LLDB_INVALID_BREAK_ID;
103630fdc8d8SChris Lattner }
103730fdc8d8SChris Lattner 
CanLoadImage()103897206d57SZachary Turner Status DynamicLoaderMacOSXDYLD::CanLoadImage() {
103997206d57SZachary Turner   Status error;
104005097246SAdrian Prantl   // In order for us to tell if we can load a shared library we verify that the
104105097246SAdrian Prantl   // dylib_info_addr isn't zero (which means no shared libraries have been set
104205097246SAdrian Prantl   // yet, or dyld is currently mucking with the shared library list).
1043b9c1b51eSKate Stone   if (ReadAllImageInfosStructure()) {
1044b9c1b51eSKate Stone     // TODO: also check the _dyld_global_lock_held variable in
1045b9c1b51eSKate Stone     // libSystem.B.dylib?
10468f343b09SGreg Clayton     // TODO: check the malloc lock?
10478f343b09SGreg Clayton     // TODO: check the objective C lock?
10488f343b09SGreg Clayton     if (m_dyld_all_image_infos.dylib_info_addr != 0)
10498f343b09SGreg Clayton       return error; // Success
10508f343b09SGreg Clayton   }
10518f343b09SGreg Clayton 
10528f343b09SGreg Clayton   error.SetErrorString("unsafe to load or unload shared libraries");
10538f343b09SGreg Clayton   return error;
10548f343b09SGreg Clayton }
10558f343b09SGreg Clayton 
GetSharedCacheInformation(lldb::addr_t & base_address,UUID & uuid,LazyBool & using_shared_cache,LazyBool & private_shared_cache)1056b9c1b51eSKate Stone bool DynamicLoaderMacOSXDYLD::GetSharedCacheInformation(
1057b9c1b51eSKate Stone     lldb::addr_t &base_address, UUID &uuid, LazyBool &using_shared_cache,
1058b9c1b51eSKate Stone     LazyBool &private_shared_cache) {
105913becd4fSJason Molenda   base_address = LLDB_INVALID_ADDRESS;
106013becd4fSJason Molenda   uuid.Clear();
106113becd4fSJason Molenda   using_shared_cache = eLazyBoolCalculate;
106213becd4fSJason Molenda   private_shared_cache = eLazyBoolCalculate;
106313becd4fSJason Molenda 
1064b9c1b51eSKate Stone   if (m_process) {
106513becd4fSJason Molenda     addr_t all_image_infos = m_process->GetImageInfoAddress();
106613becd4fSJason Molenda 
1067b9c1b51eSKate Stone     // The address returned by GetImageInfoAddress may be the address of dyld
106805097246SAdrian Prantl     // (don't want) or it may be the address of the dyld_all_image_infos
106905097246SAdrian Prantl     // structure (want). The first four bytes will be either the version field
107005097246SAdrian Prantl     // (all_image_infos) or a Mach-O file magic constant. Version 13 and higher
107105097246SAdrian Prantl     // of dyld_all_image_infos is required to get the sharedCacheUUID field.
107213becd4fSJason Molenda 
107397206d57SZachary Turner     Status err;
1074b9c1b51eSKate Stone     uint32_t version_or_magic =
1075b9c1b51eSKate Stone         m_process->ReadUnsignedIntegerFromMemory(all_image_infos, 4, -1, err);
1076b9c1b51eSKate Stone     if (version_or_magic != static_cast<uint32_t>(-1) &&
1077b9c1b51eSKate Stone         version_or_magic != llvm::MachO::MH_MAGIC &&
1078b9c1b51eSKate Stone         version_or_magic != llvm::MachO::MH_CIGAM &&
1079b9c1b51eSKate Stone         version_or_magic != llvm::MachO::MH_MAGIC_64 &&
1080b9c1b51eSKate Stone         version_or_magic != llvm::MachO::MH_CIGAM_64 &&
1081b9c1b51eSKate Stone         version_or_magic >= 13) {
108213becd4fSJason Molenda       addr_t sharedCacheUUID_address = LLDB_INVALID_ADDRESS;
108313becd4fSJason Molenda       int wordsize = m_process->GetAddressByteSize();
1084b9c1b51eSKate Stone       if (wordsize == 8) {
1085b9c1b51eSKate Stone         sharedCacheUUID_address =
1086b9c1b51eSKate Stone             all_image_infos + 160; // sharedCacheUUID <mach-o/dyld_images.h>
108713becd4fSJason Molenda       }
1088b9c1b51eSKate Stone       if (wordsize == 4) {
1089b9c1b51eSKate Stone         sharedCacheUUID_address =
1090b9c1b51eSKate Stone             all_image_infos + 84; // sharedCacheUUID <mach-o/dyld_images.h>
109113becd4fSJason Molenda       }
1092b9c1b51eSKate Stone       if (sharedCacheUUID_address != LLDB_INVALID_ADDRESS) {
109313becd4fSJason Molenda         uuid_t shared_cache_uuid;
1094b9c1b51eSKate Stone         if (m_process->ReadMemory(sharedCacheUUID_address, shared_cache_uuid,
1095b9c1b51eSKate Stone                                   sizeof(uuid_t), err) == sizeof(uuid_t)) {
10962f93fd1fSPavel Labath           uuid = UUID::fromOptionalData(shared_cache_uuid, 16);
1097b9c1b51eSKate Stone           if (uuid.IsValid()) {
109813becd4fSJason Molenda             using_shared_cache = eLazyBoolYes;
109913becd4fSJason Molenda           }
110013becd4fSJason Molenda         }
110113becd4fSJason Molenda 
1102b9c1b51eSKate Stone         if (version_or_magic >= 15) {
1103b9c1b51eSKate Stone           // The sharedCacheBaseAddress field is the next one in the
1104b9c1b51eSKate Stone           // dyld_all_image_infos struct.
110513becd4fSJason Molenda           addr_t sharedCacheBaseAddr_address = sharedCacheUUID_address + 16;
110697206d57SZachary Turner           Status error;
1107b9c1b51eSKate Stone           base_address = m_process->ReadUnsignedIntegerFromMemory(
1108b9c1b51eSKate Stone               sharedCacheBaseAddr_address, wordsize, LLDB_INVALID_ADDRESS,
1109b9c1b51eSKate Stone               error);
111013becd4fSJason Molenda           if (error.Fail())
111113becd4fSJason Molenda             base_address = LLDB_INVALID_ADDRESS;
111213becd4fSJason Molenda         }
111313becd4fSJason Molenda 
111413becd4fSJason Molenda         return true;
111513becd4fSJason Molenda       }
111613becd4fSJason Molenda 
111713becd4fSJason Molenda       //
111813becd4fSJason Molenda       // add
1119b9c1b51eSKate Stone       // NB: sharedCacheBaseAddress is the next field in dyld_all_image_infos
1120b9c1b51eSKate Stone       // after
1121b9c1b51eSKate Stone       // sharedCacheUUID -- that is, 16 bytes after it, if we wanted to fetch
1122b9c1b51eSKate Stone       // it.
112313becd4fSJason Molenda     }
112413becd4fSJason Molenda   }
112513becd4fSJason Molenda   return false;
112613becd4fSJason Molenda }
112713becd4fSJason Molenda 
IsFullyInitialized()1128bbb41915SJonas Devlieghere bool DynamicLoaderMacOSXDYLD::IsFullyInitialized() {
1129bbb41915SJonas Devlieghere   if (ReadAllImageInfosStructure())
1130bbb41915SJonas Devlieghere     return m_dyld_all_image_infos.libSystemInitialized;
1131bbb41915SJonas Devlieghere   return false;
1132bbb41915SJonas Devlieghere }
1133bbb41915SJonas Devlieghere 
Initialize()1134b9c1b51eSKate Stone void DynamicLoaderMacOSXDYLD::Initialize() {
113530fdc8d8SChris Lattner   PluginManager::RegisterPlugin(GetPluginNameStatic(),
1136b9c1b51eSKate Stone                                 GetPluginDescriptionStatic(), CreateInstance);
11376e30fd05SJonas Devlieghere   DynamicLoaderMacOS::Initialize();
113830fdc8d8SChris Lattner }
113930fdc8d8SChris Lattner 
Terminate()1140b9c1b51eSKate Stone void DynamicLoaderMacOSXDYLD::Terminate() {
11416e30fd05SJonas Devlieghere   DynamicLoaderMacOS::Terminate();
114230fdc8d8SChris Lattner   PluginManager::UnregisterPlugin(CreateInstance);
114330fdc8d8SChris Lattner }
114430fdc8d8SChris Lattner 
GetPluginDescriptionStatic()11456fa1b4ffSPavel Labath llvm::StringRef DynamicLoaderMacOSXDYLD::GetPluginDescriptionStatic() {
1146b9c1b51eSKate Stone   return "Dynamic loader plug-in that watches for shared library loads/unloads "
1147b9c1b51eSKate Stone          "in MacOSX user processes.";
114830fdc8d8SChris Lattner }
114930fdc8d8SChris Lattner 
AddrByteSize()1150b9c1b51eSKate Stone uint32_t DynamicLoaderMacOSXDYLD::AddrByteSize() {
11515fe4d141SJason Molenda   std::lock_guard<std::recursive_mutex> baseclass_guard(GetMutex());
11525fe4d141SJason Molenda 
1153b9c1b51eSKate Stone   switch (m_dyld.header.magic) {
1154510938e5SCharles Davis   case llvm::MachO::MH_MAGIC:
1155510938e5SCharles Davis   case llvm::MachO::MH_CIGAM:
11561f746071SGreg Clayton     return 4;
11571f746071SGreg Clayton 
1158510938e5SCharles Davis   case llvm::MachO::MH_MAGIC_64:
1159510938e5SCharles Davis   case llvm::MachO::MH_CIGAM_64:
11601f746071SGreg Clayton     return 8;
11611f746071SGreg Clayton 
11621f746071SGreg Clayton   default:
11631f746071SGreg Clayton     break;
11641f746071SGreg Clayton   }
11651f746071SGreg Clayton   return 0;
11661f746071SGreg Clayton }
11671f746071SGreg Clayton 
GetByteOrderFromMagic(uint32_t magic)1168b9c1b51eSKate Stone lldb::ByteOrder DynamicLoaderMacOSXDYLD::GetByteOrderFromMagic(uint32_t magic) {
1169b9c1b51eSKate Stone   switch (magic) {
1170510938e5SCharles Davis   case llvm::MachO::MH_MAGIC:
1171510938e5SCharles Davis   case llvm::MachO::MH_MAGIC_64:
11729ccb970fSBruce Mitchener     return endian::InlHostByteOrder();
11731f746071SGreg Clayton 
1174510938e5SCharles Davis   case llvm::MachO::MH_CIGAM:
1175510938e5SCharles Davis   case llvm::MachO::MH_CIGAM_64:
11769ccb970fSBruce Mitchener     if (endian::InlHostByteOrder() == lldb::eByteOrderBig)
11771f746071SGreg Clayton       return lldb::eByteOrderLittle;
11781f746071SGreg Clayton     else
11791f746071SGreg Clayton       return lldb::eByteOrderBig;
11801f746071SGreg Clayton 
11811f746071SGreg Clayton   default:
11821f746071SGreg Clayton     break;
11831f746071SGreg Clayton   }
11841f746071SGreg Clayton   return lldb::eByteOrderInvalid;
11851f746071SGreg Clayton }
1186