1 | //===-- ObjectFileMachO.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 | #ifndef LLDB_SOURCE_PLUGINS_OBJECTFILE_MACH_O_OBJECTFILEMACHO_H |
10 | #define LLDB_SOURCE_PLUGINS_OBJECTFILE_MACH_O_OBJECTFILEMACHO_H |
11 | |
12 | #include "lldb/Core/Address.h" |
13 | #include "lldb/Host/SafeMachO.h" |
14 | #include "lldb/Symbol/ObjectFile.h" |
15 | #include "lldb/Utility/FileSpec.h" |
16 | #include "lldb/Utility/FileSpecList.h" |
17 | #include "lldb/Utility/RangeMap.h" |
18 | #include "lldb/Utility/StreamString.h" |
19 | #include "lldb/Utility/UUID.h" |
20 | #include <optional> |
21 | |
22 | // This class needs to be hidden as eventually belongs in a plugin that |
23 | // will export the ObjectFile protocol |
24 | class ObjectFileMachO : public lldb_private::ObjectFile { |
25 | public: |
26 | ObjectFileMachO(const lldb::ModuleSP &module_sp, lldb::DataBufferSP data_sp, |
27 | lldb::offset_t data_offset, |
28 | const lldb_private::FileSpec *file, lldb::offset_t offset, |
29 | lldb::offset_t length); |
30 | |
31 | ObjectFileMachO(const lldb::ModuleSP &module_sp, |
32 | lldb::WritableDataBufferSP data_sp, |
33 | const lldb::ProcessSP &process_sp, lldb::addr_t ); |
34 | |
35 | ~ObjectFileMachO() override = default; |
36 | |
37 | // Static Functions |
38 | static void Initialize(); |
39 | |
40 | static void Terminate(); |
41 | |
42 | static llvm::StringRef GetPluginNameStatic() { return "mach-o" ; } |
43 | |
44 | static llvm::StringRef GetPluginDescriptionStatic() { |
45 | return "Mach-o object file reader (32 and 64 bit)" ; |
46 | } |
47 | |
48 | static lldb_private::ObjectFile * |
49 | CreateInstance(const lldb::ModuleSP &module_sp, lldb::DataBufferSP data_sp, |
50 | lldb::offset_t data_offset, const lldb_private::FileSpec *file, |
51 | lldb::offset_t file_offset, lldb::offset_t length); |
52 | |
53 | static lldb_private::ObjectFile *CreateMemoryInstance( |
54 | const lldb::ModuleSP &module_sp, lldb::WritableDataBufferSP data_sp, |
55 | const lldb::ProcessSP &process_sp, lldb::addr_t ); |
56 | |
57 | static size_t GetModuleSpecifications(const lldb_private::FileSpec &file, |
58 | lldb::DataBufferSP &data_sp, |
59 | lldb::offset_t data_offset, |
60 | lldb::offset_t file_offset, |
61 | lldb::offset_t length, |
62 | lldb_private::ModuleSpecList &specs); |
63 | |
64 | static bool SaveCore(const lldb::ProcessSP &process_sp, |
65 | const lldb_private::FileSpec &outfile, |
66 | lldb::SaveCoreStyle &core_style, |
67 | lldb_private::Status &error); |
68 | |
69 | static bool MagicBytesMatch(lldb::DataBufferSP data_sp, lldb::addr_t offset, |
70 | lldb::addr_t length); |
71 | |
72 | // LLVM RTTI support |
73 | static char ID; |
74 | bool isA(const void *ClassID) const override { |
75 | return ClassID == &ID || ObjectFile::isA(ClassID); |
76 | } |
77 | static bool classof(const ObjectFile *obj) { return obj->isA(ClassID: &ID); } |
78 | |
79 | // Member Functions |
80 | bool () override; |
81 | |
82 | bool SetLoadAddress(lldb_private::Target &target, lldb::addr_t value, |
83 | bool value_is_offset) override; |
84 | |
85 | lldb::ByteOrder GetByteOrder() const override; |
86 | |
87 | bool IsExecutable() const override; |
88 | |
89 | bool IsDynamicLoader() const; |
90 | |
91 | bool IsSharedCacheBinary() const; |
92 | |
93 | bool IsKext() const; |
94 | |
95 | uint32_t GetAddressByteSize() const override; |
96 | |
97 | lldb_private::AddressClass GetAddressClass(lldb::addr_t file_addr) override; |
98 | |
99 | void ParseSymtab(lldb_private::Symtab &symtab) override; |
100 | |
101 | bool IsStripped() override; |
102 | |
103 | void CreateSections(lldb_private::SectionList &unified_section_list) override; |
104 | |
105 | void Dump(lldb_private::Stream *s) override; |
106 | |
107 | lldb_private::ArchSpec GetArchitecture() override; |
108 | |
109 | lldb_private::UUID GetUUID() override; |
110 | |
111 | uint32_t GetDependentModules(lldb_private::FileSpecList &files) override; |
112 | |
113 | lldb_private::FileSpecList GetReExportedLibraries() override { |
114 | return m_reexported_dylibs; |
115 | } |
116 | |
117 | lldb_private::Address GetEntryPointAddress() override; |
118 | |
119 | lldb_private::Address GetBaseAddress() override; |
120 | |
121 | uint32_t GetNumThreadContexts() override; |
122 | |
123 | std::vector<std::tuple<lldb::offset_t, lldb::offset_t>> |
124 | FindLC_NOTEByName(std::string name); |
125 | |
126 | std::string GetIdentifierString() override; |
127 | |
128 | lldb_private::AddressableBits GetAddressableBits() override; |
129 | |
130 | bool GetCorefileMainBinaryInfo(lldb::addr_t &value, bool &value_is_offset, |
131 | lldb_private::UUID &uuid, |
132 | ObjectFile::BinaryType &type) override; |
133 | |
134 | bool (std::vector<lldb::tid_t> &tids) override; |
135 | |
136 | bool LoadCoreFileImages(lldb_private::Process &process) override; |
137 | |
138 | lldb::RegisterContextSP |
139 | GetThreadContextAtIndex(uint32_t idx, lldb_private::Thread &thread) override; |
140 | |
141 | ObjectFile::Type CalculateType() override; |
142 | |
143 | ObjectFile::Strata CalculateStrata() override; |
144 | |
145 | llvm::VersionTuple GetVersion() override; |
146 | |
147 | llvm::VersionTuple GetMinimumOSVersion() override; |
148 | |
149 | llvm::VersionTuple GetSDKVersion() override; |
150 | |
151 | bool GetIsDynamicLinkEditor() override; |
152 | |
153 | bool CanTrustAddressRanges() override; |
154 | |
155 | static bool (lldb_private::DataExtractor &data, |
156 | lldb::offset_t *data_offset_ptr, |
157 | llvm::MachO::mach_header &); |
158 | |
159 | bool AllowAssemblyEmulationUnwindPlans() override; |
160 | |
161 | lldb_private::Section *(); |
162 | |
163 | // PluginInterface protocol |
164 | llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); } |
165 | |
166 | protected: |
167 | static lldb_private::UUID |
168 | (const llvm::MachO::mach_header &, |
169 | const lldb_private::DataExtractor &data, |
170 | lldb::offset_t lc_offset); // Offset to the first load command |
171 | |
172 | static lldb_private::ArchSpec ( |
173 | lldb::ModuleSP module_sp, const llvm::MachO::mach_header &, |
174 | const lldb_private::DataExtractor &data, lldb::offset_t lc_offset); |
175 | |
176 | /// Enumerate all ArchSpecs supported by this Mach-O file. |
177 | /// |
178 | /// On macOS one Mach-O slice can contain multiple load commands: |
179 | /// One load command for being loaded into a macOS process and one |
180 | /// load command for being loaded into a macCatalyst process. In |
181 | /// contrast to ObjectContainerUniversalMachO, this is the same |
182 | /// binary that can be loaded into different contexts. |
183 | static void (const llvm::MachO::mach_header &, |
184 | const lldb_private::DataExtractor &data, |
185 | lldb::offset_t lc_offset, |
186 | lldb_private::ModuleSpec &base_spec, |
187 | lldb_private::ModuleSpecList &all_specs); |
188 | |
189 | /// Intended for same-host arm device debugging where lldb needs to |
190 | /// detect libraries in the shared cache and augment the nlist entries |
191 | /// with an on-disk dyld_shared_cache file. The process will record |
192 | /// the shared cache UUID so the on-disk cache can be matched or rejected |
193 | /// correctly. |
194 | void GetProcessSharedCacheUUID(lldb_private::Process *, |
195 | lldb::addr_t &base_addr, |
196 | lldb_private::UUID &uuid); |
197 | |
198 | /// Intended for same-host arm device debugging where lldb will read |
199 | /// shared cache libraries out of its own memory instead of the remote |
200 | /// process' memory as an optimization. If lldb's shared cache UUID |
201 | /// does not match the process' shared cache UUID, this optimization |
202 | /// should not be used. |
203 | void GetLLDBSharedCacheUUID(lldb::addr_t &base_addir, lldb_private::UUID &uuid); |
204 | |
205 | lldb::addr_t CalculateSectionLoadAddressForMemoryImage( |
206 | lldb::addr_t , |
207 | const lldb_private::Section *, |
208 | const lldb_private::Section *section); |
209 | |
210 | lldb_private::UUID |
211 | GetSharedCacheUUID(lldb_private::FileSpec dyld_shared_cache, |
212 | const lldb::ByteOrder byte_order, |
213 | const uint32_t addr_byte_size); |
214 | |
215 | size_t ParseSymtab(); |
216 | |
217 | typedef lldb_private::RangeVector<uint32_t, uint32_t, 8> EncryptedFileRanges; |
218 | EncryptedFileRanges GetEncryptedFileRanges(); |
219 | |
220 | struct SegmentParsingContext; |
221 | void ProcessDysymtabCommand(const llvm::MachO::load_command &load_cmd, |
222 | lldb::offset_t offset); |
223 | void ProcessSegmentCommand(const llvm::MachO::load_command &load_cmd, |
224 | lldb::offset_t offset, uint32_t cmd_idx, |
225 | SegmentParsingContext &context); |
226 | void SanitizeSegmentCommand(llvm::MachO::segment_command_64 &seg_cmd, |
227 | uint32_t cmd_idx); |
228 | |
229 | bool SectionIsLoadable(const lldb_private::Section *section); |
230 | |
231 | /// A corefile may include metadata about all of the binaries that were |
232 | /// present in the process when the corefile was taken. This is only |
233 | /// implemented for Mach-O files for now; we'll generalize it when we |
234 | /// have other systems that can include the same. |
235 | struct MachOCorefileImageEntry { |
236 | std::string filename; |
237 | lldb_private::UUID uuid; |
238 | lldb::addr_t load_address = LLDB_INVALID_ADDRESS; |
239 | lldb::addr_t slide = 0; |
240 | bool currently_executing = false; |
241 | std::vector<std::tuple<lldb_private::ConstString, lldb::addr_t>> |
242 | segment_load_addresses; |
243 | }; |
244 | |
245 | struct LCNoteEntry { |
246 | LCNoteEntry(uint32_t addr_byte_size, lldb::ByteOrder byte_order) |
247 | : payload(lldb_private::Stream::eBinary, addr_byte_size, byte_order) {} |
248 | |
249 | std::string name; |
250 | lldb::addr_t payload_file_offset = 0; |
251 | lldb_private::StreamString payload; |
252 | }; |
253 | |
254 | struct MachOCorefileAllImageInfos { |
255 | std::vector<MachOCorefileImageEntry> all_image_infos; |
256 | bool IsValid() { return all_image_infos.size() > 0; } |
257 | }; |
258 | |
259 | /// Get the list of binary images that were present in the process |
260 | /// when the corefile was produced. |
261 | /// \return |
262 | /// The MachOCorefileAllImageInfos object returned will have |
263 | /// IsValid() == false if the information is unavailable. |
264 | MachOCorefileAllImageInfos GetCorefileAllImageInfos(); |
265 | |
266 | llvm::MachO::mach_header ; |
267 | static lldb_private::ConstString GetSegmentNameTEXT(); |
268 | static lldb_private::ConstString GetSegmentNameDATA(); |
269 | static lldb_private::ConstString GetSegmentNameDATA_DIRTY(); |
270 | static lldb_private::ConstString GetSegmentNameDATA_CONST(); |
271 | static lldb_private::ConstString GetSegmentNameOBJC(); |
272 | static lldb_private::ConstString GetSegmentNameLINKEDIT(); |
273 | static lldb_private::ConstString GetSegmentNameDWARF(); |
274 | static lldb_private::ConstString GetSegmentNameLLVM_COV(); |
275 | static lldb_private::ConstString GetSectionNameEHFrame(); |
276 | |
277 | llvm::MachO::dysymtab_command m_dysymtab; |
278 | std::vector<llvm::MachO::section_64> m_mach_sections; |
279 | std::optional<llvm::VersionTuple> m_min_os_version; |
280 | std::optional<llvm::VersionTuple> m_sdk_versions; |
281 | typedef lldb_private::RangeVector<uint32_t, uint32_t> FileRangeArray; |
282 | lldb_private::Address m_entry_point_address; |
283 | FileRangeArray m_thread_context_offsets; |
284 | lldb::offset_t m_linkedit_original_offset = 0; |
285 | lldb::addr_t m_text_address = LLDB_INVALID_ADDRESS; |
286 | bool m_thread_context_offsets_valid; |
287 | lldb_private::FileSpecList m_reexported_dylibs; |
288 | bool m_allow_assembly_emulation_unwind_plans; |
289 | }; |
290 | |
291 | #endif // LLDB_SOURCE_PLUGINS_OBJECTFILE_MACH_O_OBJECTFILEMACHO_H |
292 | |