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