301 lines · c
1//===-- DynamicLoaderDarwinKernel.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-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef LLDB_SOURCE_PLUGINS_DYNAMICLOADER_DARWIN_KERNEL_DYNAMICLOADERDARWINKERNEL_H10#define LLDB_SOURCE_PLUGINS_DYNAMICLOADER_DARWIN_KERNEL_DYNAMICLOADERDARWINKERNEL_H11 12#include <mutex>13#include <string>14#include <vector>15 16 17#include "lldb/Host/SafeMachO.h"18 19#include "lldb/Core/Progress.h"20#include "lldb/Target/DynamicLoader.h"21#include "lldb/Target/Process.h"22#include "lldb/Utility/FileSpec.h"23#include "lldb/Utility/UUID.h"24 25class DynamicLoaderDarwinKernel : public lldb_private::DynamicLoader {26public:27 DynamicLoaderDarwinKernel(lldb_private::Process *process,28 lldb::addr_t kernel_addr);29 30 ~DynamicLoaderDarwinKernel() override;31 32 // Static Functions33 static void Initialize();34 35 static void Terminate();36 37 static llvm::StringRef GetPluginNameStatic() { return "darwin-kernel"; }38 39 static llvm::StringRef GetPluginDescriptionStatic();40 41 static lldb_private::DynamicLoader *42 CreateInstance(lldb_private::Process *process, bool force);43 44 static void DebuggerInitialize(lldb_private::Debugger &debugger);45 46 static lldb::addr_t SearchForDarwinKernel(lldb_private::Process *process);47 48 /// Called after attaching a process.49 ///50 /// Allow DynamicLoader plug-ins to execute some code after51 /// attaching to a process.52 void DidAttach() override;53 54 void DidLaunch() override;55 56 lldb::ThreadPlanSP GetStepThroughTrampolinePlan(lldb_private::Thread &thread,57 bool stop_others) override;58 59 lldb_private::Status CanLoadImage() override;60 61 // PluginInterface protocol62 llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); }63 64protected:65 void PrivateInitialize(lldb_private::Process *process);66 67 void PrivateProcessStateChanged(lldb_private::Process *process,68 lldb::StateType state);69 70 void UpdateIfNeeded();71 72 void LoadKernelModuleIfNeeded();73 74 void Clear(bool clear_process);75 76 void PutToLog(lldb_private::Log *log) const;77 78 static bool79 BreakpointHitCallback(void *baton,80 lldb_private::StoppointCallbackContext *context,81 lldb::user_id_t break_id, lldb::user_id_t break_loc_id);82 83 bool BreakpointHit(lldb_private::StoppointCallbackContext *context,84 lldb::user_id_t break_id, lldb::user_id_t break_loc_id);85 uint32_t GetAddrByteSize() { return m_kernel.GetAddressByteSize(); }86 87 static lldb::ByteOrder GetByteOrderFromMagic(uint32_t magic);88 89 enum {90 KERNEL_MODULE_MAX_NAME = 64u,91 // Versions less than 2 didn't have an entry size,92 // they had a 64 bit name, 16 byte UUID, 8 byte addr,93 // 8 byte size, 8 byte version, 4 byte load tag, and94 // 4 byte flags95 KERNEL_MODULE_ENTRY_SIZE_VERSION_1 = 64u + 16u + 8u + 8u + 8u + 4u + 4u96 };97 98 // class KextImageInfo represents a single kext or kernel binary image.99 // The class was designed to hold the information from the100 // OSKextLoadedKextSummary101 // structure (in libkern/libkern/OSKextLibPrivate.h from xnu). The kernel102 // maintains103 // a list of loded kexts in memory (the OSKextLoadedKextSummaryHeader104 // structure,105 // which points to an array of OSKextLoadedKextSummary's).106 //107 // A KextImageInfos may have -108 //109 // 1. The load address, name, UUID, and size of a kext/kernel binary in memory110 // (read straight out of the kernel's list-of-kexts loaded)111 // 2. A ModuleSP based on a MemoryModule read out of the kernel's memory112 // (very unlikely to have any symbolic information)113 // 3. A ModuleSP for an on-disk copy of the kext binary, possibly with debug114 // info115 // or a dSYM116 //117 // For performance reasons, the developer may prefer that lldb not load the118 // kexts out119 // of memory at the start of a kernel session. But we should build up /120 // maintain a121 // list of kexts that the kernel has told us about so we can relocate a kext122 // module123 // later if the user explicitly adds it to the target.124 125 class KextImageInfo {126 public:127 KextImageInfo() : m_name(), m_module_sp(), m_memory_module_sp(), m_uuid() {}128 129 void Clear() {130 m_load_address = LLDB_INVALID_ADDRESS;131 m_size = 0;132 m_name.clear();133 m_uuid.Clear();134 m_module_sp.reset();135 m_memory_module_sp.reset();136 m_load_process_stop_id = UINT32_MAX;137 }138 139 bool LoadImageAtFileAddress(lldb_private::Process *process);140 141 bool LoadImageUsingMemoryModule(lldb_private::Process *process,142 lldb_private::Progress *progress = nullptr);143 144 bool IsLoaded() { return m_load_process_stop_id != UINT32_MAX; }145 146 void SetLoadAddress(147 lldb::addr_t load_addr); // Address of the Mach-O header for this binary148 149 lldb::addr_t150 GetLoadAddress() const; // Address of the Mach-O header for this binary151 152 lldb_private::UUID GetUUID() const;153 154 void SetUUID(const lldb_private::UUID &uuid);155 156 void SetName(const char *);157 158 std::string GetName() const;159 160 void SetModule(lldb::ModuleSP module);161 162 lldb::ModuleSP GetModule();163 164 // try to fill in m_memory_module_sp from memory based on the m_load_address165 bool ReadMemoryModule(lldb_private::Process *process);166 167 bool IsKernel()168 const; // true if this is the mach_kernel; false if this is a kext169 170 void SetIsKernel(bool is_kernel);171 172 uint64_t GetSize() const;173 174 void SetSize(uint64_t size);175 176 uint32_t177 GetProcessStopId() const; // the stop-id when this binary was first noticed178 179 void SetProcessStopId(uint32_t stop_id);180 181 bool operator==(const KextImageInfo &rhs) const;182 183 uint32_t GetAddressByteSize(); // as determined by Mach-O header184 185 lldb::ByteOrder GetByteOrder(); // as determined by Mach-O header186 187 lldb_private::ArchSpec188 GetArchitecture() const; // as determined by Mach-O header189 190 void PutToLog(lldb_private::Log *log) const;191 192 typedef std::vector<KextImageInfo> collection;193 typedef collection::iterator iterator;194 typedef collection::const_iterator const_iterator;195 196 private:197 std::string m_name;198 lldb::ModuleSP m_module_sp;199 lldb::ModuleSP m_memory_module_sp;200 uint32_t m_load_process_stop_id =201 UINT32_MAX; // the stop-id when this module was added202 // to the Target203 lldb_private::UUID204 m_uuid; // UUID for this dylib if it has one, else all zeros205 lldb::addr_t m_load_address = LLDB_INVALID_ADDRESS;206 uint64_t m_size = 0;207 bool m_kernel_image =208 false; // true if this is the kernel, false if this is a kext209 };210 211 struct OSKextLoadedKextSummaryHeader {212 uint32_t version = 0;213 uint32_t entry_size = 0;214 uint32_t entry_count = 0;215 lldb::addr_t image_infos_addr = LLDB_INVALID_ADDRESS;216 217 OSKextLoadedKextSummaryHeader() = default;218 219 uint32_t GetSize() {220 switch (version) {221 case 0:222 return 0; // Can't know the size without a valid version223 case 1:224 return 8; // Version 1 only had a version + entry_count225 default:226 break;227 }228 // Version 2 and above has version, entry_size, entry_count, and reserved229 return 16;230 }231 232 void Clear() {233 version = 0;234 entry_size = 0;235 entry_count = 0;236 image_infos_addr = LLDB_INVALID_ADDRESS;237 }238 239 bool IsValid() const { return version >= 1 && version <= 2; }240 };241 242 void RegisterNotificationCallbacks();243 244 void UnregisterNotificationCallbacks();245 246 void SetNotificationBreakpointIfNeeded();247 248 bool ReadAllKextSummaries();249 250 bool ReadKextSummaryHeader();251 252 bool ParseKextSummaries(const lldb_private::Address &kext_summary_addr,253 uint32_t count);254 255 void256 UpdateImageInfosHeaderAndLoadCommands(KextImageInfo::collection &image_infos,257 uint32_t infos_count,258 bool update_executable);259 260 uint32_t ReadKextSummaries(const lldb_private::Address &kext_summary_addr,261 uint32_t image_infos_count,262 KextImageInfo::collection &image_infos);263 264 static lldb::addr_t265 SearchForKernelAtSameLoadAddr(lldb_private::Process *process);266 267 static lldb::addr_t268 SearchForKernelWithDebugHints(lldb_private::Process *process);269 270 static lldb::addr_t SearchForKernelNearPC(lldb_private::Process *process);271 272 static lldb::addr_t273 SearchForKernelViaExhaustiveSearch(lldb_private::Process *process);274 275 static bool276 ReadMachHeader(lldb::addr_t addr, lldb_private::Process *process, llvm::MachO::mach_header &mh,277 bool *read_error = nullptr);278 279 static lldb_private::UUID280 CheckForKernelImageAtAddress(lldb::addr_t addr,281 lldb_private::Process *process,282 bool *read_error = nullptr);283 284 lldb::addr_t m_kernel_load_address;285 KextImageInfo m_kernel; // Info about the current kernel image being used286 287 lldb_private::Address m_kext_summary_header_ptr_addr;288 lldb_private::Address m_kext_summary_header_addr;289 OSKextLoadedKextSummaryHeader m_kext_summary_header;290 KextImageInfo::collection m_known_kexts;291 mutable std::recursive_mutex m_mutex;292 lldb::user_id_t m_break_id;293 294private:295 DynamicLoaderDarwinKernel(const DynamicLoaderDarwinKernel &) = delete;296 const DynamicLoaderDarwinKernel &297 operator=(const DynamicLoaderDarwinKernel &) = delete;298};299 300#endif // LLDB_SOURCE_PLUGINS_DYNAMICLOADER_DARWIN_KERNEL_DYNAMICLOADERDARWINKERNEL_H301