1061da546Spatrick //===-- DynamicLoaderDarwinKernel.h -----------------------------*- C++ -*-===// 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 9dda28197Spatrick #ifndef LLDB_SOURCE_PLUGINS_DYNAMICLOADER_DARWIN_KERNEL_DYNAMICLOADERDARWINKERNEL_H 10dda28197Spatrick #define LLDB_SOURCE_PLUGINS_DYNAMICLOADER_DARWIN_KERNEL_DYNAMICLOADERDARWINKERNEL_H 11061da546Spatrick 12061da546Spatrick #include <mutex> 13061da546Spatrick #include <string> 14061da546Spatrick #include <vector> 15061da546Spatrick 16061da546Spatrick 17061da546Spatrick #include "lldb/Host/SafeMachO.h" 18061da546Spatrick 19061da546Spatrick #include "lldb/Target/DynamicLoader.h" 20061da546Spatrick #include "lldb/Target/Process.h" 21061da546Spatrick #include "lldb/Utility/FileSpec.h" 22061da546Spatrick #include "lldb/Utility/UUID.h" 23061da546Spatrick 24061da546Spatrick class DynamicLoaderDarwinKernel : public lldb_private::DynamicLoader { 25061da546Spatrick public: 26061da546Spatrick DynamicLoaderDarwinKernel(lldb_private::Process *process, 27061da546Spatrick lldb::addr_t kernel_addr); 28061da546Spatrick 29061da546Spatrick ~DynamicLoaderDarwinKernel() override; 30061da546Spatrick 31061da546Spatrick // Static Functions 32061da546Spatrick static void Initialize(); 33061da546Spatrick 34061da546Spatrick static void Terminate(); 35061da546Spatrick GetPluginNameStatic()36*f6aab3d8Srobert static llvm::StringRef GetPluginNameStatic() { return "darwin-kernel"; } 37061da546Spatrick 38*f6aab3d8Srobert static llvm::StringRef GetPluginDescriptionStatic(); 39061da546Spatrick 40061da546Spatrick static lldb_private::DynamicLoader * 41061da546Spatrick CreateInstance(lldb_private::Process *process, bool force); 42061da546Spatrick 43061da546Spatrick static void DebuggerInitialize(lldb_private::Debugger &debugger); 44061da546Spatrick 45061da546Spatrick static lldb::addr_t SearchForDarwinKernel(lldb_private::Process *process); 46061da546Spatrick 47061da546Spatrick /// Called after attaching a process. 48061da546Spatrick /// 49061da546Spatrick /// Allow DynamicLoader plug-ins to execute some code after 50061da546Spatrick /// attaching to a process. 51061da546Spatrick void DidAttach() override; 52061da546Spatrick 53061da546Spatrick void DidLaunch() override; 54061da546Spatrick 55061da546Spatrick lldb::ThreadPlanSP GetStepThroughTrampolinePlan(lldb_private::Thread &thread, 56061da546Spatrick bool stop_others) override; 57061da546Spatrick 58061da546Spatrick lldb_private::Status CanLoadImage() override; 59061da546Spatrick 60061da546Spatrick // PluginInterface protocol GetPluginName()61*f6aab3d8Srobert llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); } 62061da546Spatrick 63061da546Spatrick protected: 64061da546Spatrick void PrivateInitialize(lldb_private::Process *process); 65061da546Spatrick 66061da546Spatrick void PrivateProcessStateChanged(lldb_private::Process *process, 67061da546Spatrick lldb::StateType state); 68061da546Spatrick 69061da546Spatrick void UpdateIfNeeded(); 70061da546Spatrick 71061da546Spatrick void LoadKernelModuleIfNeeded(); 72061da546Spatrick 73061da546Spatrick void Clear(bool clear_process); 74061da546Spatrick 75061da546Spatrick void PutToLog(lldb_private::Log *log) const; 76061da546Spatrick 77061da546Spatrick static bool 78061da546Spatrick BreakpointHitCallback(void *baton, 79061da546Spatrick lldb_private::StoppointCallbackContext *context, 80061da546Spatrick lldb::user_id_t break_id, lldb::user_id_t break_loc_id); 81061da546Spatrick 82061da546Spatrick bool BreakpointHit(lldb_private::StoppointCallbackContext *context, 83061da546Spatrick lldb::user_id_t break_id, lldb::user_id_t break_loc_id); GetAddrByteSize()84061da546Spatrick uint32_t GetAddrByteSize() { return m_kernel.GetAddressByteSize(); } 85061da546Spatrick 86061da546Spatrick static lldb::ByteOrder GetByteOrderFromMagic(uint32_t magic); 87061da546Spatrick 88061da546Spatrick enum { 89061da546Spatrick KERNEL_MODULE_MAX_NAME = 64u, 90061da546Spatrick // Versions less than 2 didn't have an entry size, 91061da546Spatrick // they had a 64 bit name, 16 byte UUID, 8 byte addr, 92061da546Spatrick // 8 byte size, 8 byte version, 4 byte load tag, and 93061da546Spatrick // 4 byte flags 94061da546Spatrick KERNEL_MODULE_ENTRY_SIZE_VERSION_1 = 64u + 16u + 8u + 8u + 8u + 4u + 4u 95061da546Spatrick }; 96061da546Spatrick 97061da546Spatrick // class KextImageInfo represents a single kext or kernel binary image. 98061da546Spatrick // The class was designed to hold the information from the 99061da546Spatrick // OSKextLoadedKextSummary 100061da546Spatrick // structure (in libkern/libkern/OSKextLibPrivate.h from xnu). The kernel 101061da546Spatrick // maintains 102061da546Spatrick // a list of loded kexts in memory (the OSKextLoadedKextSummaryHeader 103061da546Spatrick // structure, 104061da546Spatrick // which points to an array of OSKextLoadedKextSummary's). 105061da546Spatrick // 106061da546Spatrick // A KextImageInfos may have - 107061da546Spatrick // 108061da546Spatrick // 1. The load address, name, UUID, and size of a kext/kernel binary in memory 109061da546Spatrick // (read straight out of the kernel's list-of-kexts loaded) 110061da546Spatrick // 2. A ModuleSP based on a MemoryModule read out of the kernel's memory 111061da546Spatrick // (very unlikely to have any symbolic information) 112061da546Spatrick // 3. A ModuleSP for an on-disk copy of the kext binary, possibly with debug 113061da546Spatrick // info 114061da546Spatrick // or a dSYM 115061da546Spatrick // 116061da546Spatrick // For performance reasons, the developer may prefer that lldb not load the 117061da546Spatrick // kexts out 118061da546Spatrick // of memory at the start of a kernel session. But we should build up / 119061da546Spatrick // maintain a 120061da546Spatrick // list of kexts that the kernel has told us about so we can relocate a kext 121061da546Spatrick // module 122061da546Spatrick // later if the user explicitly adds it to the target. 123061da546Spatrick 124061da546Spatrick class KextImageInfo { 125061da546Spatrick public: KextImageInfo()126be691f3bSpatrick KextImageInfo() : m_name(), m_module_sp(), m_memory_module_sp(), m_uuid() {} 127061da546Spatrick Clear()128061da546Spatrick void Clear() { 129061da546Spatrick m_load_address = LLDB_INVALID_ADDRESS; 130061da546Spatrick m_size = 0; 131061da546Spatrick m_name.clear(); 132061da546Spatrick m_uuid.Clear(); 133061da546Spatrick m_module_sp.reset(); 134061da546Spatrick m_memory_module_sp.reset(); 135061da546Spatrick m_load_process_stop_id = UINT32_MAX; 136061da546Spatrick } 137061da546Spatrick 138061da546Spatrick bool LoadImageAtFileAddress(lldb_private::Process *process); 139061da546Spatrick 140061da546Spatrick bool LoadImageUsingMemoryModule(lldb_private::Process *process); 141061da546Spatrick IsLoaded()142061da546Spatrick bool IsLoaded() { return m_load_process_stop_id != UINT32_MAX; } 143061da546Spatrick 144061da546Spatrick void SetLoadAddress( 145061da546Spatrick lldb::addr_t load_addr); // Address of the Mach-O header for this binary 146061da546Spatrick 147061da546Spatrick lldb::addr_t 148061da546Spatrick GetLoadAddress() const; // Address of the Mach-O header for this binary 149061da546Spatrick 150061da546Spatrick lldb_private::UUID GetUUID() const; 151061da546Spatrick 152061da546Spatrick void SetUUID(const lldb_private::UUID &uuid); 153061da546Spatrick 154061da546Spatrick void SetName(const char *); 155061da546Spatrick 156061da546Spatrick std::string GetName() const; 157061da546Spatrick 158061da546Spatrick void SetModule(lldb::ModuleSP module); 159061da546Spatrick 160061da546Spatrick lldb::ModuleSP GetModule(); 161061da546Spatrick 162061da546Spatrick // try to fill in m_memory_module_sp from memory based on the m_load_address 163061da546Spatrick bool ReadMemoryModule(lldb_private::Process *process); 164061da546Spatrick 165061da546Spatrick bool IsKernel() 166061da546Spatrick const; // true if this is the mach_kernel; false if this is a kext 167061da546Spatrick 168061da546Spatrick void SetIsKernel(bool is_kernel); 169061da546Spatrick 170061da546Spatrick uint64_t GetSize() const; 171061da546Spatrick 172061da546Spatrick void SetSize(uint64_t size); 173061da546Spatrick 174061da546Spatrick uint32_t 175061da546Spatrick GetProcessStopId() const; // the stop-id when this binary was first noticed 176061da546Spatrick 177061da546Spatrick void SetProcessStopId(uint32_t stop_id); 178061da546Spatrick 179061da546Spatrick bool operator==(const KextImageInfo &rhs); 180061da546Spatrick 181061da546Spatrick uint32_t GetAddressByteSize(); // as determined by Mach-O header 182061da546Spatrick 183061da546Spatrick lldb::ByteOrder GetByteOrder(); // as determined by Mach-O header 184061da546Spatrick 185061da546Spatrick lldb_private::ArchSpec 186061da546Spatrick GetArchitecture() const; // as determined by Mach-O header 187061da546Spatrick 188061da546Spatrick void PutToLog(lldb_private::Log *log) const; 189061da546Spatrick 190061da546Spatrick typedef std::vector<KextImageInfo> collection; 191061da546Spatrick typedef collection::iterator iterator; 192061da546Spatrick typedef collection::const_iterator const_iterator; 193061da546Spatrick 194061da546Spatrick private: 195061da546Spatrick std::string m_name; 196061da546Spatrick lldb::ModuleSP m_module_sp; 197061da546Spatrick lldb::ModuleSP m_memory_module_sp; 198be691f3bSpatrick uint32_t m_load_process_stop_id = 199be691f3bSpatrick UINT32_MAX; // the stop-id when this module was added 200061da546Spatrick // to the Target 201061da546Spatrick lldb_private::UUID 202061da546Spatrick m_uuid; // UUID for this dylib if it has one, else all zeros 203be691f3bSpatrick lldb::addr_t m_load_address = LLDB_INVALID_ADDRESS; 204be691f3bSpatrick uint64_t m_size = 0; 205be691f3bSpatrick bool m_kernel_image = 206be691f3bSpatrick false; // true if this is the kernel, false if this is a kext 207061da546Spatrick }; 208061da546Spatrick 209061da546Spatrick struct OSKextLoadedKextSummaryHeader { 210be691f3bSpatrick uint32_t version = 0; 211be691f3bSpatrick uint32_t entry_size = 0; 212be691f3bSpatrick uint32_t entry_count = 0; 213be691f3bSpatrick lldb::addr_t image_infos_addr = LLDB_INVALID_ADDRESS; 214061da546Spatrick 215be691f3bSpatrick OSKextLoadedKextSummaryHeader() = default; 216061da546Spatrick GetSizeOSKextLoadedKextSummaryHeader217061da546Spatrick uint32_t GetSize() { 218061da546Spatrick switch (version) { 219061da546Spatrick case 0: 220061da546Spatrick return 0; // Can't know the size without a valid version 221061da546Spatrick case 1: 222061da546Spatrick return 8; // Version 1 only had a version + entry_count 223061da546Spatrick default: 224061da546Spatrick break; 225061da546Spatrick } 226061da546Spatrick // Version 2 and above has version, entry_size, entry_count, and reserved 227061da546Spatrick return 16; 228061da546Spatrick } 229061da546Spatrick ClearOSKextLoadedKextSummaryHeader230061da546Spatrick void Clear() { 231061da546Spatrick version = 0; 232061da546Spatrick entry_size = 0; 233061da546Spatrick entry_count = 0; 234061da546Spatrick image_infos_addr = LLDB_INVALID_ADDRESS; 235061da546Spatrick } 236061da546Spatrick IsValidOSKextLoadedKextSummaryHeader237061da546Spatrick bool IsValid() const { return version >= 1 && version <= 2; } 238061da546Spatrick }; 239061da546Spatrick 240061da546Spatrick void RegisterNotificationCallbacks(); 241061da546Spatrick 242061da546Spatrick void UnregisterNotificationCallbacks(); 243061da546Spatrick 244061da546Spatrick void SetNotificationBreakpointIfNeeded(); 245061da546Spatrick 246061da546Spatrick bool ReadAllKextSummaries(); 247061da546Spatrick 248061da546Spatrick bool ReadKextSummaryHeader(); 249061da546Spatrick 250061da546Spatrick bool ParseKextSummaries(const lldb_private::Address &kext_summary_addr, 251061da546Spatrick uint32_t count); 252061da546Spatrick 253061da546Spatrick void 254061da546Spatrick UpdateImageInfosHeaderAndLoadCommands(KextImageInfo::collection &image_infos, 255061da546Spatrick uint32_t infos_count, 256061da546Spatrick bool update_executable); 257061da546Spatrick 258061da546Spatrick uint32_t ReadKextSummaries(const lldb_private::Address &kext_summary_addr, 259061da546Spatrick uint32_t image_infos_count, 260061da546Spatrick KextImageInfo::collection &image_infos); 261061da546Spatrick 262061da546Spatrick static lldb::addr_t 263061da546Spatrick SearchForKernelAtSameLoadAddr(lldb_private::Process *process); 264061da546Spatrick 265061da546Spatrick static lldb::addr_t 266061da546Spatrick SearchForKernelWithDebugHints(lldb_private::Process *process); 267061da546Spatrick 268061da546Spatrick static lldb::addr_t SearchForKernelNearPC(lldb_private::Process *process); 269061da546Spatrick 270061da546Spatrick static lldb::addr_t 271061da546Spatrick SearchForKernelViaExhaustiveSearch(lldb_private::Process *process); 272061da546Spatrick 273061da546Spatrick static bool 274061da546Spatrick ReadMachHeader(lldb::addr_t addr, lldb_private::Process *process, llvm::MachO::mach_header &mh, 275061da546Spatrick bool *read_error = nullptr); 276061da546Spatrick 277061da546Spatrick static lldb_private::UUID 278061da546Spatrick CheckForKernelImageAtAddress(lldb::addr_t addr, 279061da546Spatrick lldb_private::Process *process, 280061da546Spatrick bool *read_error = nullptr); 281061da546Spatrick 282061da546Spatrick lldb::addr_t m_kernel_load_address; 283061da546Spatrick KextImageInfo m_kernel; // Info about the current kernel image being used 284061da546Spatrick 285061da546Spatrick lldb_private::Address m_kext_summary_header_ptr_addr; 286061da546Spatrick lldb_private::Address m_kext_summary_header_addr; 287061da546Spatrick OSKextLoadedKextSummaryHeader m_kext_summary_header; 288061da546Spatrick KextImageInfo::collection m_known_kexts; 289061da546Spatrick mutable std::recursive_mutex m_mutex; 290061da546Spatrick lldb::user_id_t m_break_id; 291061da546Spatrick 292061da546Spatrick private: 293dda28197Spatrick DynamicLoaderDarwinKernel(const DynamicLoaderDarwinKernel &) = delete; 294dda28197Spatrick const DynamicLoaderDarwinKernel & 295dda28197Spatrick operator=(const DynamicLoaderDarwinKernel &) = delete; 296061da546Spatrick }; 297061da546Spatrick 298dda28197Spatrick #endif // LLDB_SOURCE_PLUGINS_DYNAMICLOADER_DARWIN_KERNEL_DYNAMICLOADERDARWINKERNEL_H 299