forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			306 lines
		
	
	
		
			9.6 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			306 lines
		
	
	
		
			9.6 KiB
		
	
	
	
		
			C++
		
	
	
	
| //===-- DynamicLoaderDarwinKernel.h -----------------------------*- C++ -*-===//
 | |
| //
 | |
| //                     The LLVM Compiler Infrastructure
 | |
| //
 | |
| // This file is distributed under the University of Illinois Open Source
 | |
| // License. See LICENSE.TXT for details.
 | |
| //
 | |
| //===----------------------------------------------------------------------===//
 | |
| 
 | |
| #ifndef liblldb_DynamicLoaderDarwinKernel_h_
 | |
| #define liblldb_DynamicLoaderDarwinKernel_h_
 | |
| 
 | |
| // C Includes
 | |
| // C++ Includes
 | |
| #include <mutex>
 | |
| #include <string>
 | |
| #include <vector>
 | |
| 
 | |
| // Other libraries and framework includes
 | |
| // Project includes
 | |
| #include "lldb/Target/DynamicLoader.h"
 | |
| #include "lldb/Target/Process.h"
 | |
| #include "lldb/Utility/FileSpec.h"
 | |
| #include "lldb/Utility/UUID.h"
 | |
| 
 | |
| class DynamicLoaderDarwinKernel : public lldb_private::DynamicLoader {
 | |
| public:
 | |
|   DynamicLoaderDarwinKernel(lldb_private::Process *process,
 | |
|                             lldb::addr_t kernel_addr);
 | |
| 
 | |
|   ~DynamicLoaderDarwinKernel() override;
 | |
| 
 | |
|   //------------------------------------------------------------------
 | |
|   // Static Functions
 | |
|   //------------------------------------------------------------------
 | |
|   static void Initialize();
 | |
| 
 | |
|   static void Terminate();
 | |
| 
 | |
|   static lldb_private::ConstString GetPluginNameStatic();
 | |
| 
 | |
|   static const char *GetPluginDescriptionStatic();
 | |
| 
 | |
|   static lldb_private::DynamicLoader *
 | |
|   CreateInstance(lldb_private::Process *process, bool force);
 | |
| 
 | |
|   static void DebuggerInitialize(lldb_private::Debugger &debugger);
 | |
| 
 | |
|   static lldb::addr_t SearchForDarwinKernel(lldb_private::Process *process);
 | |
| 
 | |
|   //------------------------------------------------------------------
 | |
|   /// Called after attaching a process.
 | |
|   ///
 | |
|   /// Allow DynamicLoader plug-ins to execute some code after
 | |
|   /// attaching to a process.
 | |
|   //------------------------------------------------------------------
 | |
|   void DidAttach() override;
 | |
| 
 | |
|   void DidLaunch() override;
 | |
| 
 | |
|   lldb::ThreadPlanSP GetStepThroughTrampolinePlan(lldb_private::Thread &thread,
 | |
|                                                   bool stop_others) override;
 | |
| 
 | |
|   lldb_private::Status CanLoadImage() override;
 | |
| 
 | |
|   //------------------------------------------------------------------
 | |
|   // PluginInterface protocol
 | |
|   //------------------------------------------------------------------
 | |
|   lldb_private::ConstString GetPluginName() override;
 | |
| 
 | |
|   uint32_t GetPluginVersion() override;
 | |
| 
 | |
| protected:
 | |
|   void PrivateInitialize(lldb_private::Process *process);
 | |
| 
 | |
|   void PrivateProcessStateChanged(lldb_private::Process *process,
 | |
|                                   lldb::StateType state);
 | |
| 
 | |
|   void UpdateIfNeeded();
 | |
| 
 | |
|   void LoadKernelModuleIfNeeded();
 | |
| 
 | |
|   void Clear(bool clear_process);
 | |
| 
 | |
|   void PutToLog(lldb_private::Log *log) const;
 | |
| 
 | |
|   static bool
 | |
|   BreakpointHitCallback(void *baton,
 | |
|                         lldb_private::StoppointCallbackContext *context,
 | |
|                         lldb::user_id_t break_id, lldb::user_id_t break_loc_id);
 | |
| 
 | |
|   bool BreakpointHit(lldb_private::StoppointCallbackContext *context,
 | |
|                      lldb::user_id_t break_id, lldb::user_id_t break_loc_id);
 | |
|   uint32_t GetAddrByteSize() { return m_kernel.GetAddressByteSize(); }
 | |
| 
 | |
|   static lldb::ByteOrder GetByteOrderFromMagic(uint32_t magic);
 | |
| 
 | |
|   enum {
 | |
|     KERNEL_MODULE_MAX_NAME = 64u,
 | |
|     // Versions less than 2 didn't have an entry size,
 | |
|     // they had a 64 bit name, 16 byte UUID, 8 byte addr,
 | |
|     // 8 byte size, 8 byte version, 4 byte load tag, and
 | |
|     // 4 byte flags
 | |
|     KERNEL_MODULE_ENTRY_SIZE_VERSION_1 = 64u + 16u + 8u + 8u + 8u + 4u + 4u
 | |
|   };
 | |
| 
 | |
|   // class KextImageInfo represents a single kext or kernel binary image.
 | |
|   // The class was designed to hold the information from the
 | |
|   // OSKextLoadedKextSummary
 | |
|   // structure (in libkern/libkern/OSKextLibPrivate.h from xnu).  The kernel
 | |
|   // maintains
 | |
|   // a list of loded kexts in memory (the OSKextLoadedKextSummaryHeader
 | |
|   // structure,
 | |
|   // which points to an array of OSKextLoadedKextSummary's).
 | |
|   //
 | |
|   // A KextImageInfos may have -
 | |
|   //
 | |
|   // 1. The load address, name, UUID, and size of a kext/kernel binary in memory
 | |
|   //    (read straight out of the kernel's list-of-kexts loaded)
 | |
|   // 2. A ModuleSP based on a MemoryModule read out of the kernel's memory
 | |
|   //    (very unlikely to have any symbolic information)
 | |
|   // 3. A ModuleSP for an on-disk copy of the kext binary, possibly with debug
 | |
|   // info
 | |
|   //    or a dSYM
 | |
|   //
 | |
|   // For performance reasons, the developer may prefer that lldb not load the
 | |
|   // kexts out
 | |
|   // of memory at the start of a kernel session.  But we should build up /
 | |
|   // maintain a
 | |
|   // list of kexts that the kernel has told us about so we can relocate a kext
 | |
|   // module
 | |
|   // later if the user explicitly adds it to the target.
 | |
| 
 | |
|   class KextImageInfo {
 | |
|   public:
 | |
|     KextImageInfo()
 | |
|         : m_name(), m_module_sp(), m_memory_module_sp(),
 | |
|           m_load_process_stop_id(UINT32_MAX), m_uuid(),
 | |
|           m_load_address(LLDB_INVALID_ADDRESS), m_size(0),
 | |
|           m_kernel_image(false) {}
 | |
| 
 | |
|     void Clear() {
 | |
|       m_load_address = LLDB_INVALID_ADDRESS;
 | |
|       m_size = 0;
 | |
|       m_name.clear();
 | |
|       m_uuid.Clear();
 | |
|       m_module_sp.reset();
 | |
|       m_memory_module_sp.reset();
 | |
|       m_load_process_stop_id = UINT32_MAX;
 | |
|     }
 | |
| 
 | |
|     bool LoadImageAtFileAddress(lldb_private::Process *process);
 | |
| 
 | |
|     bool LoadImageUsingMemoryModule(lldb_private::Process *process);
 | |
| 
 | |
|     bool IsLoaded() { return m_load_process_stop_id != UINT32_MAX; }
 | |
| 
 | |
|     void SetLoadAddress(
 | |
|         lldb::addr_t load_addr); // Address of the Mach-O header for this binary
 | |
| 
 | |
|     lldb::addr_t
 | |
|     GetLoadAddress() const; // Address of the Mach-O header for this binary
 | |
| 
 | |
|     lldb_private::UUID GetUUID() const;
 | |
| 
 | |
|     void SetUUID(const lldb_private::UUID &uuid);
 | |
| 
 | |
|     void SetName(const char *);
 | |
| 
 | |
|     std::string GetName() const;
 | |
| 
 | |
|     void SetModule(lldb::ModuleSP module);
 | |
| 
 | |
|     lldb::ModuleSP GetModule();
 | |
| 
 | |
|     // try to fill in m_memory_module_sp from memory based on the m_load_address
 | |
|     bool ReadMemoryModule(lldb_private::Process *process);
 | |
| 
 | |
|     bool IsKernel()
 | |
|         const; // true if this is the mach_kernel; false if this is a kext
 | |
| 
 | |
|     void SetIsKernel(bool is_kernel);
 | |
| 
 | |
|     uint64_t GetSize() const;
 | |
| 
 | |
|     void SetSize(uint64_t size);
 | |
| 
 | |
|     uint32_t
 | |
|     GetProcessStopId() const; // the stop-id when this binary was first noticed
 | |
| 
 | |
|     void SetProcessStopId(uint32_t stop_id);
 | |
| 
 | |
|     bool operator==(const KextImageInfo &rhs);
 | |
| 
 | |
|     uint32_t GetAddressByteSize(); // as determined by Mach-O header
 | |
| 
 | |
|     lldb::ByteOrder GetByteOrder(); // as determined by Mach-O header
 | |
| 
 | |
|     lldb_private::ArchSpec
 | |
|     GetArchitecture() const; // as determined by Mach-O header
 | |
| 
 | |
|     void PutToLog(lldb_private::Log *log) const;
 | |
| 
 | |
|     typedef std::vector<KextImageInfo> collection;
 | |
|     typedef collection::iterator iterator;
 | |
|     typedef collection::const_iterator const_iterator;
 | |
| 
 | |
|   private:
 | |
|     std::string m_name;
 | |
|     lldb::ModuleSP m_module_sp;
 | |
|     lldb::ModuleSP m_memory_module_sp;
 | |
|     uint32_t m_load_process_stop_id; // the stop-id when this module was added
 | |
|                                      // to the Target
 | |
|     lldb_private::UUID
 | |
|         m_uuid; // UUID for this dylib if it has one, else all zeros
 | |
|     lldb::addr_t m_load_address;
 | |
|     uint64_t m_size;
 | |
|     bool m_kernel_image; // true if this is the kernel, false if this is a kext
 | |
|   };
 | |
| 
 | |
|   struct OSKextLoadedKextSummaryHeader {
 | |
|     uint32_t version;
 | |
|     uint32_t entry_size;
 | |
|     uint32_t entry_count;
 | |
|     lldb::addr_t image_infos_addr;
 | |
| 
 | |
|     OSKextLoadedKextSummaryHeader()
 | |
|         : version(0), entry_size(0), entry_count(0),
 | |
|           image_infos_addr(LLDB_INVALID_ADDRESS) {}
 | |
| 
 | |
|     uint32_t GetSize() {
 | |
|       switch (version) {
 | |
|       case 0:
 | |
|         return 0; // Can't know the size without a valid version
 | |
|       case 1:
 | |
|         return 8; // Version 1 only had a version + entry_count
 | |
|       default:
 | |
|         break;
 | |
|       }
 | |
|       // Version 2 and above has version, entry_size, entry_count, and reserved
 | |
|       return 16;
 | |
|     }
 | |
| 
 | |
|     void Clear() {
 | |
|       version = 0;
 | |
|       entry_size = 0;
 | |
|       entry_count = 0;
 | |
|       image_infos_addr = LLDB_INVALID_ADDRESS;
 | |
|     }
 | |
| 
 | |
|     bool IsValid() const { return version >= 1 || version <= 2; }
 | |
|   };
 | |
| 
 | |
|   void RegisterNotificationCallbacks();
 | |
| 
 | |
|   void UnregisterNotificationCallbacks();
 | |
| 
 | |
|   void SetNotificationBreakpointIfNeeded();
 | |
| 
 | |
|   bool ReadAllKextSummaries();
 | |
| 
 | |
|   bool ReadKextSummaryHeader();
 | |
| 
 | |
|   bool ParseKextSummaries(const lldb_private::Address &kext_summary_addr,
 | |
|                           uint32_t count);
 | |
| 
 | |
|   void
 | |
|   UpdateImageInfosHeaderAndLoadCommands(KextImageInfo::collection &image_infos,
 | |
|                                         uint32_t infos_count,
 | |
|                                         bool update_executable);
 | |
| 
 | |
|   uint32_t ReadKextSummaries(const lldb_private::Address &kext_summary_addr,
 | |
|                              uint32_t image_infos_count,
 | |
|                              KextImageInfo::collection &image_infos);
 | |
| 
 | |
|   static lldb::addr_t
 | |
|   SearchForKernelAtSameLoadAddr(lldb_private::Process *process);
 | |
| 
 | |
|   static lldb::addr_t
 | |
|   SearchForKernelWithDebugHints(lldb_private::Process *process);
 | |
| 
 | |
|   static lldb::addr_t SearchForKernelNearPC(lldb_private::Process *process);
 | |
| 
 | |
|   static lldb::addr_t
 | |
|   SearchForKernelViaExhaustiveSearch(lldb_private::Process *process);
 | |
| 
 | |
|   static lldb_private::UUID
 | |
|   CheckForKernelImageAtAddress(lldb::addr_t addr,
 | |
|                                lldb_private::Process *process);
 | |
| 
 | |
|   lldb::addr_t m_kernel_load_address;
 | |
|   KextImageInfo m_kernel; // Info about the current kernel image being used
 | |
| 
 | |
|   lldb_private::Address m_kext_summary_header_ptr_addr;
 | |
|   lldb_private::Address m_kext_summary_header_addr;
 | |
|   OSKextLoadedKextSummaryHeader m_kext_summary_header;
 | |
|   KextImageInfo::collection m_known_kexts;
 | |
|   mutable std::recursive_mutex m_mutex;
 | |
|   lldb::user_id_t m_break_id;
 | |
| 
 | |
| private:
 | |
|   DISALLOW_COPY_AND_ASSIGN(DynamicLoaderDarwinKernel);
 | |
| };
 | |
| 
 | |
| #endif // liblldb_DynamicLoaderDarwinKernel_h_
 |