Summary: One of the conclusions of the discussion on D49740 was that SafeMachO is better off in the Host module (as that's the only place which should include mach/machine.h, which is what this header is working around). Also, Utility, which is the only module which cannot include Host, should not be doing anything with object file formats. This patch implements that move, and also removes any unneded includes of that file. I've verified that MacOS still compiles after this. Reviewers: jingham, zturner, teemperor Subscribers: fedor.sergeev, lldb-commits Differential Revision: https://reviews.llvm.org/D50383 llvm-svn: 342050
312 lines
9.7 KiB
C++
312 lines
9.7 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
|
|
|
|
#include "lldb/Host/SafeMachO.h"
|
|
|
|
// 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 bool
|
|
ReadMachHeader(lldb::addr_t addr, lldb_private::Process *process, llvm::MachO::mach_header &mh);
|
|
|
|
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_
|