1dda28197Spatrick //===-- PlatformDarwinKernel.cpp ------------------------------------------===//
2061da546Spatrick //
3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information.
5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6061da546Spatrick //
7061da546Spatrick //===----------------------------------------------------------------------===//
8061da546Spatrick
9061da546Spatrick #include "PlatformDarwinKernel.h"
10061da546Spatrick
11061da546Spatrick #if defined(__APPLE__) // This Plugin uses the Mac-specific
12061da546Spatrick // source/Host/macosx/cfcpp utilities
13061da546Spatrick
14061da546Spatrick #include "lldb/Breakpoint/BreakpointLocation.h"
15*f6aab3d8Srobert #include "lldb/Core/Debugger.h"
16061da546Spatrick #include "lldb/Core/Module.h"
17061da546Spatrick #include "lldb/Core/ModuleList.h"
18061da546Spatrick #include "lldb/Core/ModuleSpec.h"
19061da546Spatrick #include "lldb/Core/PluginManager.h"
20061da546Spatrick #include "lldb/Host/Host.h"
21dda28197Spatrick #include "lldb/Host/HostInfo.h"
22061da546Spatrick #include "lldb/Interpreter/OptionValueFileSpecList.h"
23061da546Spatrick #include "lldb/Interpreter/OptionValueProperties.h"
24061da546Spatrick #include "lldb/Interpreter/Property.h"
25061da546Spatrick #include "lldb/Symbol/ObjectFile.h"
26061da546Spatrick #include "lldb/Target/Platform.h"
27061da546Spatrick #include "lldb/Target/Process.h"
28061da546Spatrick #include "lldb/Target/Target.h"
29061da546Spatrick #include "lldb/Utility/ArchSpec.h"
30*f6aab3d8Srobert #include "lldb/Utility/DataBufferHeap.h"
31061da546Spatrick #include "lldb/Utility/FileSpec.h"
32*f6aab3d8Srobert #include "lldb/Utility/LLDBLog.h"
33061da546Spatrick #include "lldb/Utility/Log.h"
34061da546Spatrick #include "lldb/Utility/Status.h"
35061da546Spatrick #include "lldb/Utility/StreamString.h"
36061da546Spatrick
37061da546Spatrick #include "llvm/Support/FileSystem.h"
38061da546Spatrick
39061da546Spatrick #include <CoreFoundation/CoreFoundation.h>
40061da546Spatrick
41061da546Spatrick #include <memory>
42061da546Spatrick
43061da546Spatrick #include "Host/macosx/cfcpp/CFCBundle.h"
44*f6aab3d8Srobert #include "Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.h"
45*f6aab3d8Srobert #include "Plugins/ObjectContainer/Mach-O-Fileset/ObjectContainerMachOFileset.h"
46061da546Spatrick
47061da546Spatrick using namespace lldb;
48061da546Spatrick using namespace lldb_private;
49061da546Spatrick
50061da546Spatrick // Static Variables
51061da546Spatrick static uint32_t g_initialize_count = 0;
52061da546Spatrick
53061da546Spatrick // Static Functions
Initialize()54061da546Spatrick void PlatformDarwinKernel::Initialize() {
55061da546Spatrick PlatformDarwin::Initialize();
56061da546Spatrick
57061da546Spatrick if (g_initialize_count++ == 0) {
58061da546Spatrick PluginManager::RegisterPlugin(PlatformDarwinKernel::GetPluginNameStatic(),
59061da546Spatrick PlatformDarwinKernel::GetDescriptionStatic(),
60061da546Spatrick PlatformDarwinKernel::CreateInstance,
61061da546Spatrick PlatformDarwinKernel::DebuggerInitialize);
62061da546Spatrick }
63061da546Spatrick }
64061da546Spatrick
Terminate()65061da546Spatrick void PlatformDarwinKernel::Terminate() {
66061da546Spatrick if (g_initialize_count > 0) {
67061da546Spatrick if (--g_initialize_count == 0) {
68061da546Spatrick PluginManager::UnregisterPlugin(PlatformDarwinKernel::CreateInstance);
69061da546Spatrick }
70061da546Spatrick }
71061da546Spatrick
72061da546Spatrick PlatformDarwin::Terminate();
73061da546Spatrick }
74061da546Spatrick
CreateInstance(bool force,const ArchSpec * arch)75061da546Spatrick PlatformSP PlatformDarwinKernel::CreateInstance(bool force,
76061da546Spatrick const ArchSpec *arch) {
77*f6aab3d8Srobert Log *log = GetLog(LLDBLog::Platform);
78061da546Spatrick if (log) {
79061da546Spatrick const char *arch_name;
80061da546Spatrick if (arch && arch->GetArchitectureName())
81061da546Spatrick arch_name = arch->GetArchitectureName();
82061da546Spatrick else
83061da546Spatrick arch_name = "<null>";
84061da546Spatrick
85061da546Spatrick const char *triple_cstr =
86061da546Spatrick arch ? arch->GetTriple().getTriple().c_str() : "<null>";
87061da546Spatrick
88061da546Spatrick LLDB_LOGF(log, "PlatformDarwinKernel::%s(force=%s, arch={%s,%s})",
89061da546Spatrick __FUNCTION__, force ? "true" : "false", arch_name, triple_cstr);
90061da546Spatrick }
91061da546Spatrick
92061da546Spatrick // This is a special plugin that we don't want to activate just based on an
93061da546Spatrick // ArchSpec for normal userland debugging. It is only useful in kernel debug
94061da546Spatrick // sessions and the DynamicLoaderDarwinPlugin (or a user doing 'platform
95061da546Spatrick // select') will force the creation of this Platform plugin.
96061da546Spatrick if (!force) {
97061da546Spatrick LLDB_LOGF(log,
98061da546Spatrick "PlatformDarwinKernel::%s() aborting creation of platform "
99061da546Spatrick "because force == false",
100061da546Spatrick __FUNCTION__);
101061da546Spatrick return PlatformSP();
102061da546Spatrick }
103061da546Spatrick
104061da546Spatrick bool create = force;
105061da546Spatrick LazyBool is_ios_debug_session = eLazyBoolCalculate;
106061da546Spatrick
107061da546Spatrick if (!create && arch && arch->IsValid()) {
108061da546Spatrick const llvm::Triple &triple = arch->GetTriple();
109061da546Spatrick switch (triple.getVendor()) {
110061da546Spatrick case llvm::Triple::Apple:
111061da546Spatrick create = true;
112061da546Spatrick break;
113061da546Spatrick
114061da546Spatrick // Only accept "unknown" for vendor if the host is Apple and it "unknown"
115061da546Spatrick // wasn't specified (it was just returned because it was NOT specified)
116061da546Spatrick case llvm::Triple::UnknownVendor:
117061da546Spatrick create = !arch->TripleVendorWasSpecified();
118061da546Spatrick break;
119061da546Spatrick default:
120061da546Spatrick break;
121061da546Spatrick }
122061da546Spatrick
123061da546Spatrick if (create) {
124061da546Spatrick switch (triple.getOS()) {
125061da546Spatrick case llvm::Triple::Darwin:
126061da546Spatrick case llvm::Triple::MacOSX:
127061da546Spatrick case llvm::Triple::IOS:
128061da546Spatrick case llvm::Triple::WatchOS:
129061da546Spatrick case llvm::Triple::TvOS:
130061da546Spatrick // NEED_BRIDGEOS_TRIPLE case llvm::Triple::BridgeOS:
131061da546Spatrick break;
132061da546Spatrick // Only accept "vendor" for vendor if the host is Apple and it "unknown"
133061da546Spatrick // wasn't specified (it was just returned because it was NOT specified)
134061da546Spatrick case llvm::Triple::UnknownOS:
135061da546Spatrick create = !arch->TripleOSWasSpecified();
136061da546Spatrick break;
137061da546Spatrick default:
138061da546Spatrick create = false;
139061da546Spatrick break;
140061da546Spatrick }
141061da546Spatrick }
142061da546Spatrick }
143061da546Spatrick if (arch && arch->IsValid()) {
144061da546Spatrick switch (arch->GetMachine()) {
145061da546Spatrick case llvm::Triple::x86:
146061da546Spatrick case llvm::Triple::x86_64:
147061da546Spatrick case llvm::Triple::ppc:
148061da546Spatrick case llvm::Triple::ppc64:
149061da546Spatrick is_ios_debug_session = eLazyBoolNo;
150061da546Spatrick break;
151061da546Spatrick case llvm::Triple::arm:
152061da546Spatrick case llvm::Triple::aarch64:
153061da546Spatrick case llvm::Triple::thumb:
154061da546Spatrick is_ios_debug_session = eLazyBoolYes;
155061da546Spatrick break;
156061da546Spatrick default:
157061da546Spatrick is_ios_debug_session = eLazyBoolCalculate;
158061da546Spatrick break;
159061da546Spatrick }
160061da546Spatrick }
161061da546Spatrick if (create) {
162061da546Spatrick LLDB_LOGF(log, "PlatformDarwinKernel::%s() creating platform",
163061da546Spatrick __FUNCTION__);
164061da546Spatrick
165061da546Spatrick return PlatformSP(new PlatformDarwinKernel(is_ios_debug_session));
166061da546Spatrick }
167061da546Spatrick
168061da546Spatrick LLDB_LOGF(log, "PlatformDarwinKernel::%s() aborting creation of platform",
169061da546Spatrick __FUNCTION__);
170061da546Spatrick
171061da546Spatrick return PlatformSP();
172061da546Spatrick }
173061da546Spatrick
GetDescriptionStatic()174*f6aab3d8Srobert llvm::StringRef PlatformDarwinKernel::GetDescriptionStatic() {
175061da546Spatrick return "Darwin Kernel platform plug-in.";
176061da546Spatrick }
177061da546Spatrick
178061da546Spatrick /// Code to handle the PlatformDarwinKernel settings
179061da546Spatrick
180061da546Spatrick #define LLDB_PROPERTIES_platformdarwinkernel
181061da546Spatrick #include "PlatformMacOSXProperties.inc"
182061da546Spatrick
183061da546Spatrick enum {
184061da546Spatrick #define LLDB_PROPERTIES_platformdarwinkernel
185061da546Spatrick #include "PlatformMacOSXPropertiesEnum.inc"
186061da546Spatrick };
187061da546Spatrick
188061da546Spatrick class PlatformDarwinKernelProperties : public Properties {
189061da546Spatrick public:
GetSettingName()190061da546Spatrick static ConstString &GetSettingName() {
191061da546Spatrick static ConstString g_setting_name("darwin-kernel");
192061da546Spatrick return g_setting_name;
193061da546Spatrick }
194061da546Spatrick
PlatformDarwinKernelProperties()195061da546Spatrick PlatformDarwinKernelProperties() : Properties() {
196061da546Spatrick m_collection_sp = std::make_shared<OptionValueProperties>(GetSettingName());
197061da546Spatrick m_collection_sp->Initialize(g_platformdarwinkernel_properties);
198061da546Spatrick }
199061da546Spatrick
200*f6aab3d8Srobert ~PlatformDarwinKernelProperties() override = default;
201061da546Spatrick
GetKextDirectories() const202061da546Spatrick FileSpecList GetKextDirectories() const {
203061da546Spatrick const uint32_t idx = ePropertyKextDirectories;
204061da546Spatrick const OptionValueFileSpecList *option_value =
205061da546Spatrick m_collection_sp->GetPropertyAtIndexAsOptionValueFileSpecList(
206061da546Spatrick NULL, false, idx);
207061da546Spatrick assert(option_value);
208061da546Spatrick return option_value->GetCurrentValue();
209061da546Spatrick }
210061da546Spatrick };
211061da546Spatrick
GetGlobalProperties()212*f6aab3d8Srobert static PlatformDarwinKernelProperties &GetGlobalProperties() {
213*f6aab3d8Srobert static PlatformDarwinKernelProperties g_settings;
214*f6aab3d8Srobert return g_settings;
215061da546Spatrick }
216061da546Spatrick
DebuggerInitialize(lldb_private::Debugger & debugger)217061da546Spatrick void PlatformDarwinKernel::DebuggerInitialize(
218061da546Spatrick lldb_private::Debugger &debugger) {
219061da546Spatrick if (!PluginManager::GetSettingForPlatformPlugin(
220061da546Spatrick debugger, PlatformDarwinKernelProperties::GetSettingName())) {
221061da546Spatrick const bool is_global_setting = true;
222061da546Spatrick PluginManager::CreateSettingForPlatformPlugin(
223*f6aab3d8Srobert debugger, GetGlobalProperties().GetValueProperties(),
224061da546Spatrick ConstString("Properties for the PlatformDarwinKernel plug-in."),
225061da546Spatrick is_global_setting);
226061da546Spatrick }
227061da546Spatrick }
228061da546Spatrick
229061da546Spatrick /// Default Constructor
PlatformDarwinKernel(lldb_private::LazyBool is_ios_debug_session)230061da546Spatrick PlatformDarwinKernel::PlatformDarwinKernel(
231061da546Spatrick lldb_private::LazyBool is_ios_debug_session)
232061da546Spatrick : PlatformDarwin(false), // This is a remote platform
233061da546Spatrick m_name_to_kext_path_map_with_dsyms(),
234061da546Spatrick m_name_to_kext_path_map_without_dsyms(), m_search_directories(),
235061da546Spatrick m_search_directories_no_recursing(), m_kernel_binaries_with_dsyms(),
236be691f3bSpatrick m_kernel_binaries_without_dsyms(), m_kernel_dsyms_no_binaries(),
237be691f3bSpatrick m_kernel_dsyms_yaas(), m_ios_debug_session(is_ios_debug_session)
238061da546Spatrick
239061da546Spatrick {
240061da546Spatrick CollectKextAndKernelDirectories();
241061da546Spatrick SearchForKextsAndKernelsRecursively();
242061da546Spatrick }
243061da546Spatrick
244061da546Spatrick /// Destructor.
245061da546Spatrick ///
246061da546Spatrick /// The destructor is virtual since this class is designed to be
247061da546Spatrick /// inherited from by the plug-in instance.
248be691f3bSpatrick PlatformDarwinKernel::~PlatformDarwinKernel() = default;
249061da546Spatrick
GetStatus(Stream & strm)250061da546Spatrick void PlatformDarwinKernel::GetStatus(Stream &strm) {
251061da546Spatrick Platform::GetStatus(strm);
252061da546Spatrick strm.Printf(" Debug session type: ");
253061da546Spatrick if (m_ios_debug_session == eLazyBoolYes)
254061da546Spatrick strm.Printf("iOS kernel debugging\n");
255061da546Spatrick else if (m_ios_debug_session == eLazyBoolNo)
256061da546Spatrick strm.Printf("Mac OS X kernel debugging\n");
257061da546Spatrick else
258061da546Spatrick strm.Printf("unknown kernel debugging\n");
259061da546Spatrick
260061da546Spatrick strm.Printf("Directories searched recursively:\n");
261061da546Spatrick const uint32_t num_kext_dirs = m_search_directories.size();
262061da546Spatrick for (uint32_t i = 0; i < num_kext_dirs; ++i) {
263061da546Spatrick strm.Printf("[%d] %s\n", i, m_search_directories[i].GetPath().c_str());
264061da546Spatrick }
265061da546Spatrick
266061da546Spatrick strm.Printf("Directories not searched recursively:\n");
267061da546Spatrick const uint32_t num_kext_dirs_no_recursion =
268061da546Spatrick m_search_directories_no_recursing.size();
269061da546Spatrick for (uint32_t i = 0; i < num_kext_dirs_no_recursion; i++) {
270061da546Spatrick strm.Printf("[%d] %s\n", i,
271061da546Spatrick m_search_directories_no_recursing[i].GetPath().c_str());
272061da546Spatrick }
273061da546Spatrick
274061da546Spatrick strm.Printf(" Number of kexts with dSYMs indexed: %d\n",
275061da546Spatrick (int)m_name_to_kext_path_map_with_dsyms.size());
276061da546Spatrick strm.Printf(" Number of kexts without dSYMs indexed: %d\n",
277061da546Spatrick (int)m_name_to_kext_path_map_without_dsyms.size());
278061da546Spatrick strm.Printf(" Number of Kernel binaries with dSYMs indexed: %d\n",
279061da546Spatrick (int)m_kernel_binaries_with_dsyms.size());
280061da546Spatrick strm.Printf(" Number of Kernel binaries without dSYMs indexed: %d\n",
281061da546Spatrick (int)m_kernel_binaries_without_dsyms.size());
282be691f3bSpatrick strm.Printf(" Number of Kernel dSYMs with no binaries indexed: %d\n",
283be691f3bSpatrick (int)m_kernel_dsyms_no_binaries.size());
284be691f3bSpatrick strm.Printf(" Number of Kernel dSYM.yaa's indexed: %d\n",
285be691f3bSpatrick (int)m_kernel_dsyms_yaas.size());
286061da546Spatrick
287*f6aab3d8Srobert Log *log = GetLog(LLDBLog::Platform);
288061da546Spatrick if (log) {
289061da546Spatrick LLDB_LOGF(log, "\nkexts with dSYMs");
290061da546Spatrick for (auto pos : m_name_to_kext_path_map_with_dsyms) {
291061da546Spatrick LLDB_LOGF(log, "%s", pos.second.GetPath().c_str());
292061da546Spatrick }
293061da546Spatrick LLDB_LOGF(log, "\nkexts without dSYMs");
294061da546Spatrick
295061da546Spatrick for (auto pos : m_name_to_kext_path_map_without_dsyms) {
296061da546Spatrick LLDB_LOGF(log, "%s", pos.second.GetPath().c_str());
297061da546Spatrick }
298be691f3bSpatrick LLDB_LOGF(log, "\nkernel binaries with dSYMS");
299061da546Spatrick for (auto fs : m_kernel_binaries_with_dsyms) {
300061da546Spatrick LLDB_LOGF(log, "%s", fs.GetPath().c_str());
301061da546Spatrick }
302be691f3bSpatrick LLDB_LOGF(log, "\nkernel binaries without dSYMS");
303061da546Spatrick for (auto fs : m_kernel_binaries_without_dsyms) {
304061da546Spatrick LLDB_LOGF(log, "%s", fs.GetPath().c_str());
305061da546Spatrick }
306be691f3bSpatrick LLDB_LOGF(log, "\nkernel dSYMS with no binaries");
307be691f3bSpatrick for (auto fs : m_kernel_dsyms_no_binaries) {
308be691f3bSpatrick LLDB_LOGF(log, "%s", fs.GetPath().c_str());
309be691f3bSpatrick }
310be691f3bSpatrick LLDB_LOGF(log, "\nkernels .dSYM.yaa's");
311be691f3bSpatrick for (auto fs : m_kernel_dsyms_yaas) {
312be691f3bSpatrick LLDB_LOGF(log, "%s", fs.GetPath().c_str());
313be691f3bSpatrick }
314061da546Spatrick LLDB_LOGF(log, "\n");
315061da546Spatrick }
316061da546Spatrick }
317061da546Spatrick
318061da546Spatrick // Populate the m_search_directories vector with directories we should search
319061da546Spatrick // for kernel & kext binaries.
320061da546Spatrick
CollectKextAndKernelDirectories()321061da546Spatrick void PlatformDarwinKernel::CollectKextAndKernelDirectories() {
322061da546Spatrick // Differentiate between "ios debug session" and "mac debug session" so we
323061da546Spatrick // don't index kext bundles that won't be used in this debug session. If
324061da546Spatrick // this is an ios kext debug session, looking in /System/Library/Extensions
325061da546Spatrick // is a waste of stat()s, for example.
326061da546Spatrick
327061da546Spatrick // DeveloperDirectory is something like
328061da546Spatrick // "/Applications/Xcode.app/Contents/Developer"
329dda28197Spatrick std::string developer_dir = HostInfo::GetXcodeDeveloperDirectory().GetPath();
330061da546Spatrick if (developer_dir.empty())
331061da546Spatrick developer_dir = "/Applications/Xcode.app/Contents/Developer";
332061da546Spatrick
333061da546Spatrick if (m_ios_debug_session != eLazyBoolNo) {
334061da546Spatrick AddSDKSubdirsToSearchPaths(developer_dir +
335061da546Spatrick "/Platforms/iPhoneOS.platform/Developer/SDKs");
336061da546Spatrick AddSDKSubdirsToSearchPaths(developer_dir +
337061da546Spatrick "/Platforms/AppleTVOS.platform/Developer/SDKs");
338061da546Spatrick AddSDKSubdirsToSearchPaths(developer_dir +
339061da546Spatrick "/Platforms/WatchOS.platform/Developer/SDKs");
340061da546Spatrick AddSDKSubdirsToSearchPaths(developer_dir +
341061da546Spatrick "/Platforms/BridgeOS.platform/Developer/SDKs");
342061da546Spatrick }
343061da546Spatrick if (m_ios_debug_session != eLazyBoolYes) {
344061da546Spatrick AddSDKSubdirsToSearchPaths(developer_dir +
345061da546Spatrick "/Platforms/MacOSX.platform/Developer/SDKs");
346061da546Spatrick }
347061da546Spatrick
348061da546Spatrick AddSDKSubdirsToSearchPaths("/Volumes/KernelDebugKit");
349061da546Spatrick AddSDKSubdirsToSearchPaths("/AppleInternal/Developer/KDKs");
350061da546Spatrick // The KDKs distributed from Apple installed on external developer systems
351061da546Spatrick // may be in directories like /Library/Developer/KDKs/KDK_10.10_14A298i.kdk
352061da546Spatrick AddSDKSubdirsToSearchPaths("/Library/Developer/KDKs");
353061da546Spatrick
354061da546Spatrick if (m_ios_debug_session != eLazyBoolNo) {
355061da546Spatrick }
356061da546Spatrick if (m_ios_debug_session != eLazyBoolYes) {
357061da546Spatrick AddRootSubdirsToSearchPaths(this, "/");
358061da546Spatrick }
359061da546Spatrick
360061da546Spatrick GetUserSpecifiedDirectoriesToSearch();
361061da546Spatrick
362061da546Spatrick // Add simple directory /Applications/Xcode.app/Contents/Developer/../Symbols
363061da546Spatrick FileSpec possible_dir(developer_dir + "/../Symbols");
364061da546Spatrick FileSystem::Instance().Resolve(possible_dir);
365061da546Spatrick if (FileSystem::Instance().IsDirectory(possible_dir))
366061da546Spatrick m_search_directories.push_back(possible_dir);
367061da546Spatrick
368061da546Spatrick // Add simple directory of the current working directory
369061da546Spatrick FileSpec cwd(".");
370061da546Spatrick FileSystem::Instance().Resolve(cwd);
371061da546Spatrick m_search_directories_no_recursing.push_back(cwd);
372061da546Spatrick }
373061da546Spatrick
GetUserSpecifiedDirectoriesToSearch()374061da546Spatrick void PlatformDarwinKernel::GetUserSpecifiedDirectoriesToSearch() {
375*f6aab3d8Srobert FileSpecList user_dirs(GetGlobalProperties().GetKextDirectories());
376061da546Spatrick std::vector<FileSpec> possible_sdk_dirs;
377061da546Spatrick
378061da546Spatrick const uint32_t user_dirs_count = user_dirs.GetSize();
379061da546Spatrick for (uint32_t i = 0; i < user_dirs_count; i++) {
380061da546Spatrick FileSpec dir = user_dirs.GetFileSpecAtIndex(i);
381061da546Spatrick FileSystem::Instance().Resolve(dir);
382061da546Spatrick if (FileSystem::Instance().IsDirectory(dir)) {
383061da546Spatrick m_search_directories.push_back(dir);
384061da546Spatrick }
385061da546Spatrick }
386061da546Spatrick }
387061da546Spatrick
AddRootSubdirsToSearchPaths(PlatformDarwinKernel * thisp,const std::string & dir)388061da546Spatrick void PlatformDarwinKernel::AddRootSubdirsToSearchPaths(
389061da546Spatrick PlatformDarwinKernel *thisp, const std::string &dir) {
390061da546Spatrick const char *subdirs[] = {
391061da546Spatrick "/System/Library/Extensions", "/Library/Extensions",
392061da546Spatrick "/System/Library/Kernels",
393061da546Spatrick "/System/Library/Extensions/KDK", // this one probably only exist in
394061da546Spatrick // /AppleInternal/Developer/KDKs/*.kdk/...
395061da546Spatrick nullptr};
396061da546Spatrick for (int i = 0; subdirs[i] != nullptr; i++) {
397061da546Spatrick FileSpec testdir(dir + subdirs[i]);
398061da546Spatrick FileSystem::Instance().Resolve(testdir);
399061da546Spatrick if (FileSystem::Instance().IsDirectory(testdir))
400061da546Spatrick thisp->m_search_directories.push_back(testdir);
401061da546Spatrick }
402061da546Spatrick
403061da546Spatrick // Look for kernel binaries in the top level directory, without any recursion
404061da546Spatrick thisp->m_search_directories_no_recursing.push_back(FileSpec(dir + "/"));
405061da546Spatrick }
406061da546Spatrick
407061da546Spatrick // Given a directory path dir, look for any subdirs named *.kdk and *.sdk
AddSDKSubdirsToSearchPaths(const std::string & dir)408061da546Spatrick void PlatformDarwinKernel::AddSDKSubdirsToSearchPaths(const std::string &dir) {
409061da546Spatrick // Look for *.kdk and *.sdk in dir
410061da546Spatrick const bool find_directories = true;
411061da546Spatrick const bool find_files = false;
412061da546Spatrick const bool find_other = false;
413061da546Spatrick FileSystem::Instance().EnumerateDirectory(
414061da546Spatrick dir.c_str(), find_directories, find_files, find_other,
415061da546Spatrick FindKDKandSDKDirectoriesInDirectory, this);
416061da546Spatrick }
417061da546Spatrick
418061da546Spatrick // Helper function to find *.sdk and *.kdk directories in a given directory.
419061da546Spatrick FileSystem::EnumerateDirectoryResult
FindKDKandSDKDirectoriesInDirectory(void * baton,llvm::sys::fs::file_type ft,llvm::StringRef path)420061da546Spatrick PlatformDarwinKernel::FindKDKandSDKDirectoriesInDirectory(
421061da546Spatrick void *baton, llvm::sys::fs::file_type ft, llvm::StringRef path) {
422061da546Spatrick static ConstString g_sdk_suffix = ConstString(".sdk");
423061da546Spatrick static ConstString g_kdk_suffix = ConstString(".kdk");
424061da546Spatrick
425061da546Spatrick PlatformDarwinKernel *thisp = (PlatformDarwinKernel *)baton;
426061da546Spatrick FileSpec file_spec(path);
427061da546Spatrick if (ft == llvm::sys::fs::file_type::directory_file &&
428061da546Spatrick (file_spec.GetFileNameExtension() == g_sdk_suffix ||
429061da546Spatrick file_spec.GetFileNameExtension() == g_kdk_suffix)) {
430061da546Spatrick AddRootSubdirsToSearchPaths(thisp, file_spec.GetPath());
431061da546Spatrick }
432061da546Spatrick return FileSystem::eEnumerateDirectoryResultNext;
433061da546Spatrick }
434061da546Spatrick
435061da546Spatrick // Recursively search trough m_search_directories looking for kext and kernel
436061da546Spatrick // binaries, adding files found to the appropriate lists.
SearchForKextsAndKernelsRecursively()437061da546Spatrick void PlatformDarwinKernel::SearchForKextsAndKernelsRecursively() {
438061da546Spatrick const uint32_t num_dirs = m_search_directories.size();
439061da546Spatrick for (uint32_t i = 0; i < num_dirs; i++) {
440061da546Spatrick const FileSpec &dir = m_search_directories[i];
441061da546Spatrick const bool find_directories = true;
442061da546Spatrick const bool find_files = true;
443061da546Spatrick const bool find_other = true; // I think eFileTypeSymbolicLink are "other"s.
444061da546Spatrick FileSystem::Instance().EnumerateDirectory(
445061da546Spatrick dir.GetPath().c_str(), find_directories, find_files, find_other,
446061da546Spatrick GetKernelsAndKextsInDirectoryWithRecursion, this);
447061da546Spatrick }
448061da546Spatrick const uint32_t num_dirs_no_recurse = m_search_directories_no_recursing.size();
449061da546Spatrick for (uint32_t i = 0; i < num_dirs_no_recurse; i++) {
450061da546Spatrick const FileSpec &dir = m_search_directories_no_recursing[i];
451061da546Spatrick const bool find_directories = true;
452061da546Spatrick const bool find_files = true;
453061da546Spatrick const bool find_other = true; // I think eFileTypeSymbolicLink are "other"s.
454061da546Spatrick FileSystem::Instance().EnumerateDirectory(
455061da546Spatrick dir.GetPath().c_str(), find_directories, find_files, find_other,
456061da546Spatrick GetKernelsAndKextsInDirectoryNoRecursion, this);
457061da546Spatrick }
458061da546Spatrick }
459061da546Spatrick
460061da546Spatrick // We're only doing a filename match here. We won't try opening the file to
461061da546Spatrick // see if it's really a kernel or not until we need to find a kernel of a given
462061da546Spatrick // UUID. There's no cheap way to find the UUID of a file (or if it's a Mach-O
463061da546Spatrick // binary at all) without creating a whole Module for the file and throwing it
464061da546Spatrick // away if it's not wanted.
465061da546Spatrick //
466061da546Spatrick // Recurse into any subdirectories found.
467061da546Spatrick
468061da546Spatrick FileSystem::EnumerateDirectoryResult
GetKernelsAndKextsInDirectoryWithRecursion(void * baton,llvm::sys::fs::file_type ft,llvm::StringRef path)469061da546Spatrick PlatformDarwinKernel::GetKernelsAndKextsInDirectoryWithRecursion(
470061da546Spatrick void *baton, llvm::sys::fs::file_type ft, llvm::StringRef path) {
471061da546Spatrick return GetKernelsAndKextsInDirectoryHelper(baton, ft, path, true);
472061da546Spatrick }
473061da546Spatrick
474061da546Spatrick FileSystem::EnumerateDirectoryResult
GetKernelsAndKextsInDirectoryNoRecursion(void * baton,llvm::sys::fs::file_type ft,llvm::StringRef path)475061da546Spatrick PlatformDarwinKernel::GetKernelsAndKextsInDirectoryNoRecursion(
476061da546Spatrick void *baton, llvm::sys::fs::file_type ft, llvm::StringRef path) {
477061da546Spatrick return GetKernelsAndKextsInDirectoryHelper(baton, ft, path, false);
478061da546Spatrick }
479061da546Spatrick
480061da546Spatrick FileSystem::EnumerateDirectoryResult
GetKernelsAndKextsInDirectoryHelper(void * baton,llvm::sys::fs::file_type ft,llvm::StringRef path,bool recurse)481061da546Spatrick PlatformDarwinKernel::GetKernelsAndKextsInDirectoryHelper(
482061da546Spatrick void *baton, llvm::sys::fs::file_type ft, llvm::StringRef path,
483061da546Spatrick bool recurse) {
484061da546Spatrick static ConstString g_kext_suffix = ConstString(".kext");
485061da546Spatrick static ConstString g_dsym_suffix = ConstString(".dSYM");
486061da546Spatrick static ConstString g_bundle_suffix = ConstString("Bundle");
487061da546Spatrick
488061da546Spatrick FileSpec file_spec(path);
489061da546Spatrick ConstString file_spec_extension = file_spec.GetFileNameExtension();
490061da546Spatrick
491*f6aab3d8Srobert Log *log = GetLog(LLDBLog::Platform);
492061da546Spatrick
493*f6aab3d8Srobert LLDB_LOGV(log, "PlatformDarwinKernel examining '{0}'", file_spec);
494061da546Spatrick
495061da546Spatrick PlatformDarwinKernel *thisp = (PlatformDarwinKernel *)baton;
496be691f3bSpatrick
497be691f3bSpatrick llvm::StringRef filename = file_spec.GetFilename().GetStringRef();
498be691f3bSpatrick bool is_kernel_filename =
499be691f3bSpatrick filename.startswith("kernel") || filename.startswith("mach");
500be691f3bSpatrick bool is_dsym_yaa = filename.endswith(".dSYM.yaa");
501be691f3bSpatrick
502061da546Spatrick if (ft == llvm::sys::fs::file_type::regular_file ||
503061da546Spatrick ft == llvm::sys::fs::file_type::symlink_file) {
504be691f3bSpatrick if (is_kernel_filename) {
505be691f3bSpatrick if (file_spec_extension != g_dsym_suffix && !is_dsym_yaa) {
506be691f3bSpatrick if (KernelHasdSYMSibling(file_spec)) {
507061da546Spatrick LLDB_LOGF(log,
508061da546Spatrick "PlatformDarwinKernel registering kernel binary '%s' with "
509061da546Spatrick "dSYM sibling",
510061da546Spatrick file_spec.GetPath().c_str());
511061da546Spatrick thisp->m_kernel_binaries_with_dsyms.push_back(file_spec);
512be691f3bSpatrick } else {
513061da546Spatrick LLDB_LOGF(
514be691f3bSpatrick log,
515be691f3bSpatrick "PlatformDarwinKernel registering kernel binary '%s', no dSYM",
516061da546Spatrick file_spec.GetPath().c_str());
517061da546Spatrick thisp->m_kernel_binaries_without_dsyms.push_back(file_spec);
518061da546Spatrick }
519be691f3bSpatrick }
520be691f3bSpatrick if (is_dsym_yaa) {
521be691f3bSpatrick LLDB_LOGF(log, "PlatformDarwinKernel registering kernel .dSYM.yaa '%s'",
522be691f3bSpatrick file_spec.GetPath().c_str());
523be691f3bSpatrick thisp->m_kernel_dsyms_yaas.push_back(file_spec);
524be691f3bSpatrick }
525061da546Spatrick return FileSystem::eEnumerateDirectoryResultNext;
526061da546Spatrick }
527be691f3bSpatrick } else {
528be691f3bSpatrick if (ft == llvm::sys::fs::file_type::directory_file) {
529be691f3bSpatrick if (file_spec_extension == g_kext_suffix) {
530061da546Spatrick AddKextToMap(thisp, file_spec);
531061da546Spatrick // Look to see if there is a PlugIns subdir with more kexts
532061da546Spatrick FileSpec contents_plugins(file_spec.GetPath() + "/Contents/PlugIns");
533061da546Spatrick std::string search_here_too;
534061da546Spatrick if (FileSystem::Instance().IsDirectory(contents_plugins)) {
535061da546Spatrick search_here_too = contents_plugins.GetPath();
536061da546Spatrick } else {
537061da546Spatrick FileSpec plugins(file_spec.GetPath() + "/PlugIns");
538061da546Spatrick if (FileSystem::Instance().IsDirectory(plugins)) {
539061da546Spatrick search_here_too = plugins.GetPath();
540061da546Spatrick }
541061da546Spatrick }
542061da546Spatrick
543061da546Spatrick if (!search_here_too.empty()) {
544061da546Spatrick const bool find_directories = true;
545061da546Spatrick const bool find_files = false;
546061da546Spatrick const bool find_other = false;
547061da546Spatrick FileSystem::Instance().EnumerateDirectory(
548061da546Spatrick search_here_too.c_str(), find_directories, find_files, find_other,
549061da546Spatrick recurse ? GetKernelsAndKextsInDirectoryWithRecursion
550061da546Spatrick : GetKernelsAndKextsInDirectoryNoRecursion,
551061da546Spatrick baton);
552061da546Spatrick }
553061da546Spatrick return FileSystem::eEnumerateDirectoryResultNext;
554061da546Spatrick }
555be691f3bSpatrick // Do we have a kernel dSYM with no kernel binary?
556be691f3bSpatrick if (is_kernel_filename && file_spec_extension == g_dsym_suffix) {
557be691f3bSpatrick if (KerneldSYMHasNoSiblingBinary(file_spec)) {
558be691f3bSpatrick LLDB_LOGF(log,
559be691f3bSpatrick "PlatformDarwinKernel registering kernel dSYM '%s' with "
560be691f3bSpatrick "no binary sibling",
561be691f3bSpatrick file_spec.GetPath().c_str());
562be691f3bSpatrick thisp->m_kernel_dsyms_no_binaries.push_back(file_spec);
563be691f3bSpatrick return FileSystem::eEnumerateDirectoryResultNext;
564be691f3bSpatrick }
565be691f3bSpatrick }
566be691f3bSpatrick }
567be691f3bSpatrick }
568be691f3bSpatrick
569061da546Spatrick // Don't recurse into dSYM/kext/bundle directories
570061da546Spatrick if (recurse && file_spec_extension != g_dsym_suffix &&
571061da546Spatrick file_spec_extension != g_kext_suffix &&
572061da546Spatrick file_spec_extension != g_bundle_suffix) {
573*f6aab3d8Srobert LLDB_LOGV(log, "PlatformDarwinKernel descending into directory '{0}'",
574*f6aab3d8Srobert file_spec);
575061da546Spatrick return FileSystem::eEnumerateDirectoryResultEnter;
576061da546Spatrick } else {
577061da546Spatrick return FileSystem::eEnumerateDirectoryResultNext;
578061da546Spatrick }
579061da546Spatrick }
580061da546Spatrick
AddKextToMap(PlatformDarwinKernel * thisp,const FileSpec & file_spec)581061da546Spatrick void PlatformDarwinKernel::AddKextToMap(PlatformDarwinKernel *thisp,
582061da546Spatrick const FileSpec &file_spec) {
583*f6aab3d8Srobert Log *log = GetLog(LLDBLog::Platform);
584061da546Spatrick CFCBundle bundle(file_spec.GetPath().c_str());
585061da546Spatrick CFStringRef bundle_id(bundle.GetIdentifier());
586061da546Spatrick if (bundle_id && CFGetTypeID(bundle_id) == CFStringGetTypeID()) {
587061da546Spatrick char bundle_id_buf[PATH_MAX];
588061da546Spatrick if (CFStringGetCString(bundle_id, bundle_id_buf, sizeof(bundle_id_buf),
589061da546Spatrick kCFStringEncodingUTF8)) {
590061da546Spatrick ConstString bundle_conststr(bundle_id_buf);
591061da546Spatrick if (KextHasdSYMSibling(file_spec))
592061da546Spatrick {
593061da546Spatrick LLDB_LOGF(log,
594061da546Spatrick "PlatformDarwinKernel registering kext binary '%s' with dSYM "
595061da546Spatrick "sibling",
596061da546Spatrick file_spec.GetPath().c_str());
597061da546Spatrick thisp->m_name_to_kext_path_map_with_dsyms.insert(
598061da546Spatrick std::pair<ConstString, FileSpec>(bundle_conststr, file_spec));
599061da546Spatrick }
600061da546Spatrick else
601061da546Spatrick {
602061da546Spatrick LLDB_LOGF(log,
603061da546Spatrick "PlatformDarwinKernel registering kext binary '%s', no dSYM",
604061da546Spatrick file_spec.GetPath().c_str());
605061da546Spatrick thisp->m_name_to_kext_path_map_without_dsyms.insert(
606061da546Spatrick std::pair<ConstString, FileSpec>(bundle_conststr, file_spec));
607061da546Spatrick }
608061da546Spatrick }
609061da546Spatrick }
610061da546Spatrick }
611061da546Spatrick
612061da546Spatrick // Given a FileSpec of /dir/dir/foo.kext
613061da546Spatrick // Return true if any of these exist:
614061da546Spatrick // /dir/dir/foo.kext.dSYM
615061da546Spatrick // /dir/dir/foo.kext/Contents/MacOS/foo.dSYM
616061da546Spatrick // /dir/dir/foo.kext/foo.dSYM
KextHasdSYMSibling(const FileSpec & kext_bundle_filepath)617061da546Spatrick bool PlatformDarwinKernel::KextHasdSYMSibling(
618061da546Spatrick const FileSpec &kext_bundle_filepath) {
619061da546Spatrick FileSpec dsym_fspec = kext_bundle_filepath;
620061da546Spatrick std::string filename = dsym_fspec.GetFilename().AsCString();
621061da546Spatrick filename += ".dSYM";
622*f6aab3d8Srobert dsym_fspec.SetFilename(filename);
623061da546Spatrick if (FileSystem::Instance().IsDirectory(dsym_fspec)) {
624061da546Spatrick return true;
625061da546Spatrick }
626061da546Spatrick // Should probably get the CFBundleExecutable here or call
627061da546Spatrick // CFBundleCopyExecutableURL
628061da546Spatrick
629061da546Spatrick // Look for a deep bundle foramt
630061da546Spatrick ConstString executable_name =
631061da546Spatrick kext_bundle_filepath.GetFileNameStrippingExtension();
632061da546Spatrick std::string deep_bundle_str =
633061da546Spatrick kext_bundle_filepath.GetPath() + "/Contents/MacOS/";
634061da546Spatrick deep_bundle_str += executable_name.AsCString();
635061da546Spatrick deep_bundle_str += ".dSYM";
636061da546Spatrick dsym_fspec.SetFile(deep_bundle_str, FileSpec::Style::native);
637061da546Spatrick FileSystem::Instance().Resolve(dsym_fspec);
638061da546Spatrick if (FileSystem::Instance().IsDirectory(dsym_fspec)) {
639061da546Spatrick return true;
640061da546Spatrick }
641061da546Spatrick
642061da546Spatrick // look for a shallow bundle format
643061da546Spatrick //
644061da546Spatrick std::string shallow_bundle_str = kext_bundle_filepath.GetPath() + "/";
645061da546Spatrick shallow_bundle_str += executable_name.AsCString();
646061da546Spatrick shallow_bundle_str += ".dSYM";
647061da546Spatrick dsym_fspec.SetFile(shallow_bundle_str, FileSpec::Style::native);
648061da546Spatrick FileSystem::Instance().Resolve(dsym_fspec);
649061da546Spatrick return FileSystem::Instance().IsDirectory(dsym_fspec);
650061da546Spatrick }
651061da546Spatrick
652061da546Spatrick // Given a FileSpec of /dir/dir/mach.development.t7004 Return true if a dSYM
653061da546Spatrick // exists next to it:
654061da546Spatrick // /dir/dir/mach.development.t7004.dSYM
KernelHasdSYMSibling(const FileSpec & kernel_binary)655061da546Spatrick bool PlatformDarwinKernel::KernelHasdSYMSibling(const FileSpec &kernel_binary) {
656061da546Spatrick FileSpec kernel_dsym = kernel_binary;
657061da546Spatrick std::string filename = kernel_binary.GetFilename().AsCString();
658061da546Spatrick filename += ".dSYM";
659*f6aab3d8Srobert kernel_dsym.SetFilename(filename);
660061da546Spatrick return FileSystem::Instance().IsDirectory(kernel_dsym);
661061da546Spatrick }
662061da546Spatrick
663be691f3bSpatrick // Given a FileSpec of /dir/dir/mach.development.t7004.dSYM
664be691f3bSpatrick // Return true if only the dSYM exists, no binary next to it.
665be691f3bSpatrick // /dir/dir/mach.development.t7004.dSYM
666be691f3bSpatrick // but no
667be691f3bSpatrick // /dir/dir/mach.development.t7004
KerneldSYMHasNoSiblingBinary(const FileSpec & kernel_dsym)668be691f3bSpatrick bool PlatformDarwinKernel::KerneldSYMHasNoSiblingBinary(
669be691f3bSpatrick const FileSpec &kernel_dsym) {
670be691f3bSpatrick static ConstString g_dsym_suffix = ConstString(".dSYM");
671be691f3bSpatrick std::string possible_path = kernel_dsym.GetPath();
672be691f3bSpatrick if (kernel_dsym.GetFileNameExtension() != g_dsym_suffix)
673be691f3bSpatrick return false;
674be691f3bSpatrick
675be691f3bSpatrick FileSpec binary_filespec = kernel_dsym;
676be691f3bSpatrick // Chop off the '.dSYM' extension on the filename
677*f6aab3d8Srobert binary_filespec.SetFilename(binary_filespec.GetFileNameStrippingExtension());
678be691f3bSpatrick
679be691f3bSpatrick // Is there a binary next to this this? Then return false.
680be691f3bSpatrick if (FileSystem::Instance().Exists(binary_filespec))
681be691f3bSpatrick return false;
682be691f3bSpatrick
683be691f3bSpatrick // If we have at least one binary in the DWARF subdir, then
684be691f3bSpatrick // this is a properly formed dSYM and it has no binary next
685be691f3bSpatrick // to it.
686be691f3bSpatrick if (GetDWARFBinaryInDSYMBundle(kernel_dsym).size() > 0)
687be691f3bSpatrick return true;
688be691f3bSpatrick
689be691f3bSpatrick return false;
690be691f3bSpatrick }
691be691f3bSpatrick
692be691f3bSpatrick // TODO: This method returns a vector of FileSpec's because a
693be691f3bSpatrick // dSYM bundle may contain multiple DWARF binaries, but it
694be691f3bSpatrick // only implements returning the base name binary for now;
695be691f3bSpatrick // it should iterate over every binary in the DWARF subdir
696be691f3bSpatrick // and return them all.
697be691f3bSpatrick std::vector<FileSpec>
GetDWARFBinaryInDSYMBundle(FileSpec dsym_bundle)698be691f3bSpatrick PlatformDarwinKernel::GetDWARFBinaryInDSYMBundle(FileSpec dsym_bundle) {
699be691f3bSpatrick std::vector<FileSpec> results;
700be691f3bSpatrick static ConstString g_dsym_suffix = ConstString(".dSYM");
701be691f3bSpatrick if (dsym_bundle.GetFileNameExtension() != g_dsym_suffix) {
702be691f3bSpatrick return results;
703be691f3bSpatrick }
704be691f3bSpatrick // Drop the '.dSYM' from the filename
705be691f3bSpatrick std::string filename =
706be691f3bSpatrick dsym_bundle.GetFileNameStrippingExtension().GetCString();
707be691f3bSpatrick std::string dirname = dsym_bundle.GetDirectory().GetCString();
708be691f3bSpatrick
709be691f3bSpatrick std::string binary_filepath = dsym_bundle.GetPath();
710be691f3bSpatrick binary_filepath += "/Contents/Resources/DWARF/";
711be691f3bSpatrick binary_filepath += filename;
712be691f3bSpatrick
713be691f3bSpatrick FileSpec binary_fspec(binary_filepath);
714be691f3bSpatrick if (FileSystem::Instance().Exists(binary_fspec))
715be691f3bSpatrick results.push_back(binary_fspec);
716be691f3bSpatrick return results;
717be691f3bSpatrick }
718be691f3bSpatrick
GetSharedModule(const ModuleSpec & module_spec,Process * process,ModuleSP & module_sp,const FileSpecList * module_search_paths_ptr,llvm::SmallVectorImpl<ModuleSP> * old_modules,bool * did_create_ptr)719061da546Spatrick Status PlatformDarwinKernel::GetSharedModule(
720061da546Spatrick const ModuleSpec &module_spec, Process *process, ModuleSP &module_sp,
721dda28197Spatrick const FileSpecList *module_search_paths_ptr,
722dda28197Spatrick llvm::SmallVectorImpl<ModuleSP> *old_modules, bool *did_create_ptr) {
723061da546Spatrick Status error;
724061da546Spatrick module_sp.reset();
725061da546Spatrick const FileSpec &platform_file = module_spec.GetFileSpec();
726061da546Spatrick
727061da546Spatrick // Treat the file's path as a kext bundle ID (e.g.
728061da546Spatrick // "com.apple.driver.AppleIRController") and search our kext index.
729061da546Spatrick std::string kext_bundle_id = platform_file.GetPath();
730061da546Spatrick
731*f6aab3d8Srobert if (module_spec.GetUUID().IsValid()) {
732*f6aab3d8Srobert // DynamicLoaderDarwinKernel uses the magic name mach_kernel,
733*f6aab3d8Srobert // UUID search can get here with no name - and it may be a kernel.
734*f6aab3d8Srobert if (kext_bundle_id == "mach_kernel" || kext_bundle_id.empty()) {
735*f6aab3d8Srobert error = GetSharedModuleKernel(module_spec, process, module_sp,
736be691f3bSpatrick module_search_paths_ptr, old_modules,
737be691f3bSpatrick did_create_ptr);
738*f6aab3d8Srobert if (error.Success() && module_sp) {
739*f6aab3d8Srobert return error;
740*f6aab3d8Srobert }
741be691f3bSpatrick } else {
742be691f3bSpatrick return GetSharedModuleKext(module_spec, process, module_sp,
743be691f3bSpatrick module_search_paths_ptr, old_modules,
744be691f3bSpatrick did_create_ptr);
745be691f3bSpatrick }
746*f6aab3d8Srobert }
747*f6aab3d8Srobert
748be691f3bSpatrick // Give the generic methods, including possibly calling into DebugSymbols
749be691f3bSpatrick // framework on macOS systems, a chance.
750be691f3bSpatrick return PlatformDarwin::GetSharedModule(module_spec, process, module_sp,
751be691f3bSpatrick module_search_paths_ptr, old_modules,
752be691f3bSpatrick did_create_ptr);
753be691f3bSpatrick }
754be691f3bSpatrick
GetSharedModuleKext(const ModuleSpec & module_spec,Process * process,ModuleSP & module_sp,const FileSpecList * module_search_paths_ptr,llvm::SmallVectorImpl<ModuleSP> * old_modules,bool * did_create_ptr)755be691f3bSpatrick Status PlatformDarwinKernel::GetSharedModuleKext(
756be691f3bSpatrick const ModuleSpec &module_spec, Process *process, ModuleSP &module_sp,
757be691f3bSpatrick const FileSpecList *module_search_paths_ptr,
758be691f3bSpatrick llvm::SmallVectorImpl<ModuleSP> *old_modules, bool *did_create_ptr) {
759be691f3bSpatrick Status error;
760be691f3bSpatrick module_sp.reset();
761be691f3bSpatrick const FileSpec &platform_file = module_spec.GetFileSpec();
762be691f3bSpatrick
763be691f3bSpatrick // Treat the file's path as a kext bundle ID (e.g.
764be691f3bSpatrick // "com.apple.driver.AppleIRController") and search our kext index.
765be691f3bSpatrick ConstString kext_bundle(platform_file.GetPath().c_str());
766061da546Spatrick // First look through the kext bundles that had a dsym next to them
767be691f3bSpatrick if (m_name_to_kext_path_map_with_dsyms.count(kext_bundle) > 0) {
768be691f3bSpatrick for (BundleIDToKextIterator it = m_name_to_kext_path_map_with_dsyms.begin();
769061da546Spatrick it != m_name_to_kext_path_map_with_dsyms.end(); ++it) {
770be691f3bSpatrick if (it->first == kext_bundle) {
771061da546Spatrick error = ExamineKextForMatchingUUID(it->second, module_spec.GetUUID(),
772061da546Spatrick module_spec.GetArchitecture(),
773061da546Spatrick module_sp);
774061da546Spatrick if (module_sp.get()) {
775061da546Spatrick return error;
776061da546Spatrick }
777061da546Spatrick }
778061da546Spatrick }
779061da546Spatrick }
780061da546Spatrick
781061da546Spatrick // Give the generic methods, including possibly calling into DebugSymbols
782061da546Spatrick // framework on macOS systems, a chance.
783061da546Spatrick error = PlatformDarwin::GetSharedModule(module_spec, process, module_sp,
784be691f3bSpatrick module_search_paths_ptr, old_modules,
785be691f3bSpatrick did_create_ptr);
786061da546Spatrick if (error.Success() && module_sp.get()) {
787061da546Spatrick return error;
788061da546Spatrick }
789061da546Spatrick
790061da546Spatrick return error;
791061da546Spatrick }
792061da546Spatrick
GetSharedModuleKernel(const ModuleSpec & module_spec,Process * process,ModuleSP & module_sp,const FileSpecList * module_search_paths_ptr,llvm::SmallVectorImpl<ModuleSP> * old_modules,bool * did_create_ptr)793be691f3bSpatrick Status PlatformDarwinKernel::GetSharedModuleKernel(
794be691f3bSpatrick const ModuleSpec &module_spec, Process *process, ModuleSP &module_sp,
795be691f3bSpatrick const FileSpecList *module_search_paths_ptr,
796be691f3bSpatrick llvm::SmallVectorImpl<ModuleSP> *old_modules, bool *did_create_ptr) {
797be691f3bSpatrick Status error;
798be691f3bSpatrick module_sp.reset();
799be691f3bSpatrick
800061da546Spatrick // First try all kernel binaries that have a dSYM next to them
801061da546Spatrick for (auto possible_kernel : m_kernel_binaries_with_dsyms) {
802061da546Spatrick if (FileSystem::Instance().Exists(possible_kernel)) {
803061da546Spatrick ModuleSpec kern_spec(possible_kernel);
804061da546Spatrick kern_spec.GetUUID() = module_spec.GetUUID();
805be691f3bSpatrick module_sp.reset(new Module(kern_spec));
806061da546Spatrick if (module_sp && module_sp->GetObjectFile() &&
807061da546Spatrick module_sp->MatchesModuleSpec(kern_spec)) {
808061da546Spatrick // module_sp is an actual kernel binary we want to add.
809061da546Spatrick if (process) {
810*f6aab3d8Srobert const bool notify = false;
811*f6aab3d8Srobert process->GetTarget().GetImages().AppendIfNeeded(module_sp, notify);
812061da546Spatrick error.Clear();
813061da546Spatrick return error;
814061da546Spatrick } else {
815be691f3bSpatrick error = ModuleList::GetSharedModule(kern_spec, module_sp, nullptr,
816be691f3bSpatrick nullptr, nullptr);
817be691f3bSpatrick if (module_sp && module_sp->GetObjectFile() &&
818be691f3bSpatrick module_sp->GetObjectFile()->GetType() !=
819be691f3bSpatrick ObjectFile::Type::eTypeCoreFile) {
820be691f3bSpatrick return error;
821be691f3bSpatrick }
822be691f3bSpatrick module_sp.reset();
823be691f3bSpatrick }
824be691f3bSpatrick }
825be691f3bSpatrick }
826be691f3bSpatrick }
827be691f3bSpatrick
828be691f3bSpatrick // Next try all dSYMs that have no kernel binary next to them (load
829be691f3bSpatrick // the kernel DWARF stub as the main binary)
830be691f3bSpatrick for (auto possible_kernel_dsym : m_kernel_dsyms_no_binaries) {
831be691f3bSpatrick std::vector<FileSpec> objfile_names =
832be691f3bSpatrick GetDWARFBinaryInDSYMBundle(possible_kernel_dsym);
833be691f3bSpatrick for (FileSpec objfile : objfile_names) {
834be691f3bSpatrick ModuleSpec kern_spec(objfile);
835be691f3bSpatrick kern_spec.GetUUID() = module_spec.GetUUID();
836be691f3bSpatrick kern_spec.GetSymbolFileSpec() = possible_kernel_dsym;
837be691f3bSpatrick
838be691f3bSpatrick module_sp.reset(new Module(kern_spec));
839be691f3bSpatrick if (module_sp && module_sp->GetObjectFile() &&
840be691f3bSpatrick module_sp->MatchesModuleSpec(kern_spec)) {
841be691f3bSpatrick // module_sp is an actual kernel binary we want to add.
842be691f3bSpatrick if (process) {
843*f6aab3d8Srobert const bool notify = false;
844*f6aab3d8Srobert process->GetTarget().GetImages().AppendIfNeeded(module_sp, notify);
845be691f3bSpatrick error.Clear();
846be691f3bSpatrick return error;
847be691f3bSpatrick } else {
848be691f3bSpatrick error = ModuleList::GetSharedModule(kern_spec, module_sp, nullptr,
849be691f3bSpatrick nullptr, nullptr);
850061da546Spatrick if (module_sp && module_sp->GetObjectFile() &&
851061da546Spatrick module_sp->GetObjectFile()->GetType() !=
852061da546Spatrick ObjectFile::Type::eTypeCoreFile) {
853061da546Spatrick return error;
854061da546Spatrick }
855061da546Spatrick module_sp.reset();
856061da546Spatrick }
857061da546Spatrick }
858061da546Spatrick }
859061da546Spatrick }
860061da546Spatrick
861061da546Spatrick // Give the generic methods, including possibly calling into DebugSymbols
862061da546Spatrick // framework on macOS systems, a chance.
863061da546Spatrick error = PlatformDarwin::GetSharedModule(module_spec, process, module_sp,
864be691f3bSpatrick module_search_paths_ptr, old_modules,
865be691f3bSpatrick did_create_ptr);
866061da546Spatrick if (error.Success() && module_sp.get()) {
867061da546Spatrick return error;
868061da546Spatrick }
869061da546Spatrick
870061da546Spatrick return error;
871061da546Spatrick }
872061da546Spatrick
873061da546Spatrick std::vector<lldb_private::FileSpec>
SearchForExecutablesRecursively(const std::string & dir)874061da546Spatrick PlatformDarwinKernel::SearchForExecutablesRecursively(const std::string &dir) {
875061da546Spatrick std::vector<FileSpec> executables;
876061da546Spatrick std::error_code EC;
877061da546Spatrick for (llvm::sys::fs::recursive_directory_iterator it(dir.c_str(), EC),
878061da546Spatrick end;
879061da546Spatrick it != end && !EC; it.increment(EC)) {
880061da546Spatrick auto status = it->status();
881061da546Spatrick if (!status)
882061da546Spatrick break;
883061da546Spatrick if (llvm::sys::fs::is_regular_file(*status) &&
884061da546Spatrick llvm::sys::fs::can_execute(it->path()))
885061da546Spatrick executables.emplace_back(it->path());
886061da546Spatrick }
887061da546Spatrick return executables;
888061da546Spatrick }
889061da546Spatrick
ExamineKextForMatchingUUID(const FileSpec & kext_bundle_path,const lldb_private::UUID & uuid,const ArchSpec & arch,ModuleSP & exe_module_sp)890061da546Spatrick Status PlatformDarwinKernel::ExamineKextForMatchingUUID(
891061da546Spatrick const FileSpec &kext_bundle_path, const lldb_private::UUID &uuid,
892061da546Spatrick const ArchSpec &arch, ModuleSP &exe_module_sp) {
893061da546Spatrick for (const auto &exe_file :
894061da546Spatrick SearchForExecutablesRecursively(kext_bundle_path.GetPath())) {
895061da546Spatrick if (FileSystem::Instance().Exists(exe_file)) {
896061da546Spatrick ModuleSpec exe_spec(exe_file);
897061da546Spatrick exe_spec.GetUUID() = uuid;
898061da546Spatrick if (!uuid.IsValid()) {
899061da546Spatrick exe_spec.GetArchitecture() = arch;
900061da546Spatrick }
901061da546Spatrick
902061da546Spatrick // First try to create a ModuleSP with the file / arch and see if the UUID
903061da546Spatrick // matches. If that fails (this exec file doesn't have the correct uuid),
904061da546Spatrick // don't call GetSharedModule (which may call in to the DebugSymbols
905061da546Spatrick // framework and therefore can be slow.)
906061da546Spatrick ModuleSP module_sp(new Module(exe_spec));
907061da546Spatrick if (module_sp && module_sp->GetObjectFile() &&
908061da546Spatrick module_sp->MatchesModuleSpec(exe_spec)) {
909061da546Spatrick Status error = ModuleList::GetSharedModule(exe_spec, exe_module_sp,
910061da546Spatrick NULL, NULL, NULL);
911061da546Spatrick if (exe_module_sp && exe_module_sp->GetObjectFile()) {
912061da546Spatrick return error;
913061da546Spatrick }
914061da546Spatrick }
915061da546Spatrick exe_module_sp.reset();
916061da546Spatrick }
917061da546Spatrick }
918061da546Spatrick
919061da546Spatrick return {};
920061da546Spatrick }
921061da546Spatrick
find_kernel_in_macho_fileset(Process * process,addr_t input_addr)922*f6aab3d8Srobert static addr_t find_kernel_in_macho_fileset(Process *process,
923*f6aab3d8Srobert addr_t input_addr) {
924*f6aab3d8Srobert Status error;
925*f6aab3d8Srobert WritableDataBufferSP header_data(new DataBufferHeap(512, 0));
926*f6aab3d8Srobert if (!process->ReadMemory(input_addr, header_data->GetBytes(),
927*f6aab3d8Srobert header_data->GetByteSize(), error) ||
928*f6aab3d8Srobert !error.Success())
929*f6aab3d8Srobert return LLDB_INVALID_ADDRESS;
930*f6aab3d8Srobert ModuleSP module_sp(new Module(ModuleSpec()));
931*f6aab3d8Srobert ObjectContainerSP container_sp(
932*f6aab3d8Srobert ObjectContainerMachOFileset::CreateMemoryInstance(
933*f6aab3d8Srobert module_sp, header_data, process->shared_from_this(), input_addr));
934*f6aab3d8Srobert if (!container_sp)
935*f6aab3d8Srobert return LLDB_INVALID_ADDRESS;
936*f6aab3d8Srobert
937*f6aab3d8Srobert ObjectContainerMachOFileset *fileset_container =
938*f6aab3d8Srobert static_cast<ObjectContainerMachOFileset *>(container_sp.get());
939*f6aab3d8Srobert ObjectContainerMachOFileset::Entry *entry =
940*f6aab3d8Srobert fileset_container->FindEntry("com.apple.kernel");
941*f6aab3d8Srobert if (entry)
942*f6aab3d8Srobert return entry->vmaddr;
943*f6aab3d8Srobert return LLDB_INVALID_ADDRESS;
944*f6aab3d8Srobert }
945*f6aab3d8Srobert
LoadPlatformBinaryAndSetup(Process * process,lldb::addr_t input_addr,bool notify)946*f6aab3d8Srobert bool PlatformDarwinKernel::LoadPlatformBinaryAndSetup(Process *process,
947*f6aab3d8Srobert lldb::addr_t input_addr,
948*f6aab3d8Srobert bool notify) {
949*f6aab3d8Srobert Log *log =
950*f6aab3d8Srobert GetLog(LLDBLog::Platform | LLDBLog::DynamicLoader | LLDBLog::Process);
951*f6aab3d8Srobert
952*f6aab3d8Srobert if (!process)
953*f6aab3d8Srobert return false;
954*f6aab3d8Srobert
955*f6aab3d8Srobert addr_t actual_address = find_kernel_in_macho_fileset(process, input_addr);
956*f6aab3d8Srobert
957*f6aab3d8Srobert LLDB_LOGF(log,
958*f6aab3d8Srobert "PlatformDarwinKernel::%s check address 0x%" PRIx64 " for "
959*f6aab3d8Srobert "a macho fileset, got back kernel address 0x%" PRIx64,
960*f6aab3d8Srobert __FUNCTION__, input_addr, actual_address);
961*f6aab3d8Srobert
962*f6aab3d8Srobert if (actual_address == LLDB_INVALID_ADDRESS)
963*f6aab3d8Srobert return false;
964*f6aab3d8Srobert
965*f6aab3d8Srobert // We have a xnu kernel binary, this is a kernel debug session.
966*f6aab3d8Srobert // Set the Target's Platform to be PlatformDarwinKernel, and the
967*f6aab3d8Srobert // Process' DynamicLoader to be DynamicLoaderDarwinKernel.
968*f6aab3d8Srobert
969*f6aab3d8Srobert PlatformSP platform_sp =
970*f6aab3d8Srobert process->GetTarget().GetDebugger().GetPlatformList().Create(
971*f6aab3d8Srobert PlatformDarwinKernel::GetPluginNameStatic());
972*f6aab3d8Srobert if (platform_sp)
973*f6aab3d8Srobert process->GetTarget().SetPlatform(platform_sp);
974*f6aab3d8Srobert
975*f6aab3d8Srobert DynamicLoaderUP dyld_up =
976*f6aab3d8Srobert std::make_unique<DynamicLoaderDarwinKernel>(process, actual_address);
977*f6aab3d8Srobert if (!dyld_up)
978*f6aab3d8Srobert return false;
979*f6aab3d8Srobert
980*f6aab3d8Srobert // Process owns it now
981*f6aab3d8Srobert process->SetDynamicLoader(std::move(dyld_up));
982*f6aab3d8Srobert
983*f6aab3d8Srobert return true;
984*f6aab3d8Srobert }
985*f6aab3d8Srobert
GetSupportedArchitectures(const ArchSpec & process_host_arch)986*f6aab3d8Srobert std::vector<ArchSpec> PlatformDarwinKernel::GetSupportedArchitectures(
987*f6aab3d8Srobert const ArchSpec &process_host_arch) {
988*f6aab3d8Srobert std::vector<ArchSpec> result;
989*f6aab3d8Srobert ARMGetSupportedArchitectures(result);
990*f6aab3d8Srobert x86GetSupportedArchitectures(result);
991*f6aab3d8Srobert return result;
992061da546Spatrick }
993061da546Spatrick
CalculateTrapHandlerSymbolNames()994061da546Spatrick void PlatformDarwinKernel::CalculateTrapHandlerSymbolNames() {
995061da546Spatrick m_trap_handlers.push_back(ConstString("trap_from_kernel"));
996061da546Spatrick m_trap_handlers.push_back(ConstString("hndl_machine_check"));
997061da546Spatrick m_trap_handlers.push_back(ConstString("hndl_double_fault"));
998061da546Spatrick m_trap_handlers.push_back(ConstString("hndl_allintrs"));
999061da546Spatrick m_trap_handlers.push_back(ConstString("hndl_alltraps"));
1000061da546Spatrick m_trap_handlers.push_back(ConstString("interrupt"));
1001061da546Spatrick m_trap_handlers.push_back(ConstString("fleh_prefabt"));
1002061da546Spatrick m_trap_handlers.push_back(ConstString("ExceptionVectorsBase"));
1003061da546Spatrick m_trap_handlers.push_back(ConstString("ExceptionVectorsTable"));
1004061da546Spatrick m_trap_handlers.push_back(ConstString("fleh_undef"));
1005061da546Spatrick m_trap_handlers.push_back(ConstString("fleh_dataabt"));
1006061da546Spatrick m_trap_handlers.push_back(ConstString("fleh_irq"));
1007061da546Spatrick m_trap_handlers.push_back(ConstString("fleh_decirq"));
1008061da546Spatrick m_trap_handlers.push_back(ConstString("fleh_fiq_generic"));
1009061da546Spatrick m_trap_handlers.push_back(ConstString("fleh_dec"));
1010061da546Spatrick }
1011061da546Spatrick
1012061da546Spatrick #endif // __APPLE__
1013