1//===-- DynamicLoaderMacOSXDYLD.h -------------------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9// This is the DynamicLoader plugin for Darwin (macOS / iPhoneOS / tvOS /
10// watchOS / BridgeOS)
11// platforms earlier than 2016, where lldb would read the "dyld_all_image_infos"
12// dyld internal structure to understand where things were loaded and the
13// solib loaded/unloaded notification function we put a breakpoint on gives us
14// an array of (load address, mod time, file path) tuples.
15//
16// As of late 2016, the new DynamicLoaderMacOS plugin should be used, which uses
17// dyld SPI functions to get the same information without reading internal dyld
18// data structures.
19
20#ifndef LLDB_SOURCE_PLUGINS_DYNAMICLOADER_MACOSX_DYLD_DYNAMICLOADERMACOSXDYLD_H
21#define LLDB_SOURCE_PLUGINS_DYNAMICLOADER_MACOSX_DYLD_DYNAMICLOADERMACOSXDYLD_H
22
23#include <mutex>
24#include <vector>
25
26#include "lldb/Host/SafeMachO.h"
27#include "lldb/Target/DynamicLoader.h"
28#include "lldb/Target/Process.h"
29#include "lldb/Utility/FileSpec.h"
30#include "lldb/Utility/StructuredData.h"
31#include "lldb/Utility/UUID.h"
32
33#include "DynamicLoaderDarwin.h"
34
35class DynamicLoaderMacOSXDYLD : public lldb_private::DynamicLoaderDarwin {
36public:
37 DynamicLoaderMacOSXDYLD(lldb_private::Process *process);
38
39 ~DynamicLoaderMacOSXDYLD() override;
40
41 // Static Functions
42 static void Initialize();
43
44 static void Terminate();
45
46 static llvm::StringRef GetPluginNameStatic() { return "macosx-dyld"; }
47
48 static llvm::StringRef GetPluginDescriptionStatic();
49
50 static lldb_private::DynamicLoader *
51 CreateInstance(lldb_private::Process *process, bool force);
52
53 /// Called after attaching a process.
54 ///
55 /// Allow DynamicLoader plug-ins to execute some code after
56 /// attaching to a process.
57 bool ProcessDidExec() override;
58
59 lldb_private::Status CanLoadImage() override;
60
61 bool GetSharedCacheInformation(
62 lldb::addr_t &base_address, lldb_private::UUID &uuid,
63 lldb_private::LazyBool &using_shared_cache,
64 lldb_private::LazyBool &private_shared_cache) override;
65
66 // PluginInterface protocol
67 llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); }
68
69 bool IsFullyInitialized() override;
70
71protected:
72 void PutToLog(lldb_private::Log *log) const;
73
74 void DoInitialImageFetch() override;
75
76 bool NeedToDoInitialImageFetch() override;
77
78 bool DidSetNotificationBreakpoint() override;
79
80 void DoClear() override;
81
82 bool ReadDYLDInfoFromMemoryAndSetNotificationCallback(lldb::addr_t addr);
83
84 static bool
85 NotifyBreakpointHit(void *baton,
86 lldb_private::StoppointCallbackContext *context,
87 lldb::user_id_t break_id, lldb::user_id_t break_loc_id);
88
89 uint32_t AddrByteSize();
90
91 bool ReadMachHeader(lldb::addr_t addr, llvm::MachO::mach_header *header,
92 lldb_private::DataExtractor *load_command_data);
93
94 uint32_t ParseLoadCommands(const lldb_private::DataExtractor &data,
95 ImageInfo &dylib_info,
96 lldb_private::FileSpec *lc_id_dylinker);
97
98 struct DYLDAllImageInfos {
99 uint32_t version = 0;
100 uint32_t dylib_info_count = 0; // Version >= 1
101 lldb::addr_t dylib_info_addr = LLDB_INVALID_ADDRESS; // Version >= 1
102 lldb::addr_t notification = LLDB_INVALID_ADDRESS; // Version >= 1
103 bool processDetachedFromSharedRegion = false; // Version >= 1
104 bool libSystemInitialized = false; // Version >= 2
105 lldb::addr_t dyldImageLoadAddress = LLDB_INVALID_ADDRESS; // Version >= 2
106
107 DYLDAllImageInfos() = default;
108
109 void Clear() {
110 version = 0;
111 dylib_info_count = 0;
112 dylib_info_addr = LLDB_INVALID_ADDRESS;
113 notification = LLDB_INVALID_ADDRESS;
114 processDetachedFromSharedRegion = false;
115 libSystemInitialized = false;
116 dyldImageLoadAddress = LLDB_INVALID_ADDRESS;
117 }
118
119 bool IsValid() const { return version >= 1 && version <= 6; }
120 };
121
122 static lldb::ByteOrder GetByteOrderFromMagic(uint32_t magic);
123
124 bool SetNotificationBreakpoint() override;
125
126 void ClearNotificationBreakpoint() override;
127
128 // There is a little tricky bit where you might initially attach while dyld is
129 // updating
130 // the all_image_infos, and you can't read the infos, so you have to continue
131 // and pick it
132 // up when you hit the update breakpoint. At that point, you need to run this
133 // initialize
134 // function, but when you do it that way you DON'T need to do the extra work
135 // you would at
136 // the breakpoint.
137 // So this function will only do actual work if the image infos haven't been
138 // read yet.
139 // If it does do any work, then it will return true, and false otherwise.
140 // That way you can
141 // call it in the breakpoint action, and if it returns true you're done.
142 bool InitializeFromAllImageInfos();
143
144 bool ReadAllImageInfosStructure();
145
146 bool AddModulesUsingImageInfosAddress(lldb::addr_t image_infos_addr,
147 uint32_t image_infos_count);
148
149 bool RemoveModulesUsingImageInfosAddress(lldb::addr_t image_infos_addr,
150 uint32_t image_infos_count);
151
152 void UpdateImageInfosHeaderAndLoadCommands(ImageInfo::collection &image_infos,
153 uint32_t infos_count,
154 bool update_executable);
155
156 bool ReadImageInfos(lldb::addr_t image_infos_addr, uint32_t image_infos_count,
157 ImageInfo::collection &image_infos);
158
159 lldb::addr_t m_dyld_all_image_infos_addr;
160 DYLDAllImageInfos m_dyld_all_image_infos;
161 uint32_t m_dyld_all_image_infos_stop_id;
162 lldb::user_id_t m_break_id;
163 mutable std::recursive_mutex m_mutex;
164 bool m_process_image_addr_is_all_images_infos;
165
166private:
167 DynamicLoaderMacOSXDYLD(const DynamicLoaderMacOSXDYLD &) = delete;
168 const DynamicLoaderMacOSXDYLD &
169 operator=(const DynamicLoaderMacOSXDYLD &) = delete;
170};
171
172#endif // LLDB_SOURCE_PLUGINS_DYNAMICLOADER_MACOSX_DYLD_DYNAMICLOADERMACOSXDYLD_H
173

source code of lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h