brintos

brintos / llvm-project-archived public Read only

0
0
Text · 9.5 KiB · 69dd8ca Raw
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