Imported Upstream version 6.10.0.49

Former-commit-id: 1d6753294b2993e1fbf92de9366bb9544db4189b
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2020-01-16 16:38:04 +00:00
parent d94e79959b
commit 468663ddbb
48518 changed files with 2789335 additions and 61176 deletions

View File

@@ -0,0 +1,9 @@
add_subdirectory(MacOSX-DYLD)
add_subdirectory(POSIX-DYLD)
add_subdirectory(Static)
add_subdirectory(Hexagon-DYLD)
add_subdirectory(Windows-DYLD)
if (CMAKE_SYSTEM_NAME MATCHES "Darwin")
add_subdirectory(Darwin-Kernel)
endif()

View File

@@ -0,0 +1,13 @@
add_lldb_library(lldbPluginDynamicLoaderDarwinKernel PLUGIN
DynamicLoaderDarwinKernel.cpp
LINK_LIBS
lldbBreakpoint
lldbCore
lldbHost
lldbInterpreter
lldbSymbol
lldbTarget
lldbUtility
lldbPluginPlatformMacOSX
)

View File

@@ -0,0 +1,305 @@
//===-- 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_

View File

@@ -0,0 +1,10 @@
add_lldb_library(lldbPluginDynamicLoaderHexagonDYLD PLUGIN
HexagonDYLDRendezvous.cpp
DynamicLoaderHexagonDYLD.cpp
LINK_LIBS
lldbBreakpoint
lldbCore
lldbSymbol
lldbTarget
)

View File

@@ -0,0 +1,147 @@
//===-- DynamicLoaderHexagonDYLD.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_DynamicLoaderHexagonDYLD_h_
#define liblldb_DynamicLoaderHexagonDYLD_h_
// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
#include "lldb/Breakpoint/StoppointCallbackContext.h"
#include "lldb/Target/DynamicLoader.h"
#include "HexagonDYLDRendezvous.h"
class DynamicLoaderHexagonDYLD : public lldb_private::DynamicLoader {
public:
DynamicLoaderHexagonDYLD(lldb_private::Process *process);
~DynamicLoaderHexagonDYLD() override;
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);
//------------------------------------------------------------------
// DynamicLoader protocol
//------------------------------------------------------------------
void DidAttach() override;
void DidLaunch() override;
lldb::ThreadPlanSP GetStepThroughTrampolinePlan(lldb_private::Thread &thread,
bool stop_others) override;
lldb_private::Status CanLoadImage() override;
lldb::addr_t GetThreadLocalData(const lldb::ModuleSP module,
const lldb::ThreadSP thread,
lldb::addr_t tls_file_addr) override;
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
lldb_private::ConstString GetPluginName() override;
uint32_t GetPluginVersion() override;
protected:
/// Runtime linker rendezvous structure.
HexagonDYLDRendezvous m_rendezvous;
/// Virtual load address of the inferior process.
lldb::addr_t m_load_offset;
/// Virtual entry address of the inferior process.
lldb::addr_t m_entry_point;
/// Rendezvous breakpoint.
lldb::break_id_t m_dyld_bid;
/// Loaded module list. (link map for each module)
std::map<lldb::ModuleWP, lldb::addr_t, std::owner_less<lldb::ModuleWP>>
m_loaded_modules;
/// Enables a breakpoint on a function called by the runtime
/// linker each time a module is loaded or unloaded.
bool SetRendezvousBreakpoint();
/// Callback routine which updates the current list of loaded modules based
/// on the information supplied by the runtime linker.
static bool RendezvousBreakpointHit(
void *baton, lldb_private::StoppointCallbackContext *context,
lldb::user_id_t break_id, lldb::user_id_t break_loc_id);
/// Helper method for RendezvousBreakpointHit. Updates LLDB's current set
/// of loaded modules.
void RefreshModules();
/// Updates the load address of every allocatable section in @p module.
///
/// @param module The module to traverse.
///
/// @param link_map_addr The virtual address of the link map for the @p
/// module.
///
/// @param base_addr The virtual base address @p module is loaded at.
void UpdateLoadedSections(lldb::ModuleSP module, lldb::addr_t link_map_addr,
lldb::addr_t base_addr,
bool base_addr_is_offset) override;
/// Removes the loaded sections from the target in @p module.
///
/// @param module The module to traverse.
void UnloadSections(const lldb::ModuleSP module) override;
/// Callback routine invoked when we hit the breakpoint on process entry.
///
/// This routine is responsible for resolving the load addresses of all
/// dependent modules required by the inferior and setting up the rendezvous
/// breakpoint.
static bool
EntryBreakpointHit(void *baton,
lldb_private::StoppointCallbackContext *context,
lldb::user_id_t break_id, lldb::user_id_t break_loc_id);
/// Helper for the entry breakpoint callback. Resolves the load addresses
/// of all dependent modules.
void LoadAllCurrentModules();
/// Computes a value for m_load_offset returning the computed address on
/// success and LLDB_INVALID_ADDRESS on failure.
lldb::addr_t ComputeLoadOffset();
/// Computes a value for m_entry_point returning the computed address on
/// success and LLDB_INVALID_ADDRESS on failure.
lldb::addr_t GetEntryPoint();
/// Checks to see if the target module has changed, updates the target
/// accordingly and returns the target executable module.
lldb::ModuleSP GetTargetExecutable();
/// return the address of the Rendezvous breakpoint
lldb::addr_t FindRendezvousBreakpointAddress();
private:
const lldb_private::SectionList *
GetSectionListFromModule(const lldb::ModuleSP module) const;
DISALLOW_COPY_AND_ASSIGN(DynamicLoaderHexagonDYLD);
};
#endif // liblldb_DynamicLoaderHexagonDYLD_h_

View File

@@ -0,0 +1,368 @@
//===-- HexagonDYLDRendezvous.cpp -------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "lldb/Core/Module.h"
#include "lldb/Symbol/Symbol.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/Status.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
#include "HexagonDYLDRendezvous.h"
using namespace lldb;
using namespace lldb_private;
/// Locates the address of the rendezvous structure. Returns the address on
/// success and LLDB_INVALID_ADDRESS on failure.
static addr_t ResolveRendezvousAddress(Process *process) {
addr_t info_location;
addr_t info_addr;
Status error;
info_location = process->GetImageInfoAddress();
if (info_location == LLDB_INVALID_ADDRESS)
return LLDB_INVALID_ADDRESS;
info_addr = process->ReadPointerFromMemory(info_location, error);
if (error.Fail())
return LLDB_INVALID_ADDRESS;
if (info_addr == 0)
return LLDB_INVALID_ADDRESS;
return info_addr;
}
HexagonDYLDRendezvous::HexagonDYLDRendezvous(Process *process)
: m_process(process), m_rendezvous_addr(LLDB_INVALID_ADDRESS), m_current(),
m_previous(), m_soentries(), m_added_soentries(), m_removed_soentries() {
m_thread_info.valid = false;
// Cache a copy of the executable path
if (m_process) {
Module *exe_mod = m_process->GetTarget().GetExecutableModulePointer();
if (exe_mod)
exe_mod->GetFileSpec().GetPath(m_exe_path, PATH_MAX);
}
}
bool HexagonDYLDRendezvous::Resolve() {
const size_t word_size = 4;
Rendezvous info;
size_t address_size;
size_t padding;
addr_t info_addr;
addr_t cursor;
address_size = m_process->GetAddressByteSize();
padding = address_size - word_size;
if (m_rendezvous_addr == LLDB_INVALID_ADDRESS)
cursor = info_addr = ResolveRendezvousAddress(m_process);
else
cursor = info_addr = m_rendezvous_addr;
if (cursor == LLDB_INVALID_ADDRESS)
return false;
if (!(cursor = ReadWord(cursor, &info.version, word_size)))
return false;
if (!(cursor = ReadPointer(cursor + padding, &info.map_addr)))
return false;
if (!(cursor = ReadPointer(cursor, &info.brk)))
return false;
if (!(cursor = ReadWord(cursor, &info.state, word_size)))
return false;
if (!(cursor = ReadPointer(cursor + padding, &info.ldbase)))
return false;
// The rendezvous was successfully read. Update our internal state.
m_rendezvous_addr = info_addr;
m_previous = m_current;
m_current = info;
return UpdateSOEntries();
}
void HexagonDYLDRendezvous::SetRendezvousAddress(lldb::addr_t addr) {
m_rendezvous_addr = addr;
}
bool HexagonDYLDRendezvous::IsValid() {
return m_rendezvous_addr != LLDB_INVALID_ADDRESS;
}
bool HexagonDYLDRendezvous::UpdateSOEntries() {
SOEntry entry;
if (m_current.map_addr == 0)
return false;
// When the previous and current states are consistent this is the first
// time we have been asked to update. Just take a snapshot of the currently
// loaded modules.
if (m_previous.state == eConsistent && m_current.state == eConsistent)
return TakeSnapshot(m_soentries);
// If we are about to add or remove a shared object clear out the current
// state and take a snapshot of the currently loaded images.
if (m_current.state == eAdd || m_current.state == eDelete) {
// this is a fudge so that we can clear the assert below.
m_previous.state = eConsistent;
// We hit this assert on the 2nd run of this function after running the calc
// example
assert(m_previous.state == eConsistent);
m_soentries.clear();
m_added_soentries.clear();
m_removed_soentries.clear();
return TakeSnapshot(m_soentries);
}
assert(m_current.state == eConsistent);
// Otherwise check the previous state to determine what to expect and update
// accordingly.
if (m_previous.state == eAdd)
return UpdateSOEntriesForAddition();
else if (m_previous.state == eDelete)
return UpdateSOEntriesForDeletion();
return false;
}
bool HexagonDYLDRendezvous::UpdateSOEntriesForAddition() {
SOEntry entry;
iterator pos;
assert(m_previous.state == eAdd);
if (m_current.map_addr == 0)
return false;
for (addr_t cursor = m_current.map_addr; cursor != 0; cursor = entry.next) {
if (!ReadSOEntryFromMemory(cursor, entry))
return false;
// Only add shared libraries and not the executable.
// On Linux this is indicated by an empty path in the entry.
// On FreeBSD it is the name of the executable.
if (entry.path.empty() || ::strcmp(entry.path.c_str(), m_exe_path) == 0)
continue;
pos = std::find(m_soentries.begin(), m_soentries.end(), entry);
if (pos == m_soentries.end()) {
m_soentries.push_back(entry);
m_added_soentries.push_back(entry);
}
}
return true;
}
bool HexagonDYLDRendezvous::UpdateSOEntriesForDeletion() {
SOEntryList entry_list;
iterator pos;
assert(m_previous.state == eDelete);
if (!TakeSnapshot(entry_list))
return false;
for (iterator I = begin(); I != end(); ++I) {
pos = std::find(entry_list.begin(), entry_list.end(), *I);
if (pos == entry_list.end())
m_removed_soentries.push_back(*I);
}
m_soentries = entry_list;
return true;
}
bool HexagonDYLDRendezvous::TakeSnapshot(SOEntryList &entry_list) {
SOEntry entry;
if (m_current.map_addr == 0)
return false;
for (addr_t cursor = m_current.map_addr; cursor != 0; cursor = entry.next) {
if (!ReadSOEntryFromMemory(cursor, entry))
return false;
// Only add shared libraries and not the executable.
// On Linux this is indicated by an empty path in the entry.
// On FreeBSD it is the name of the executable.
if (entry.path.empty() || ::strcmp(entry.path.c_str(), m_exe_path) == 0)
continue;
entry_list.push_back(entry);
}
return true;
}
addr_t HexagonDYLDRendezvous::ReadWord(addr_t addr, uint64_t *dst,
size_t size) {
Status error;
*dst = m_process->ReadUnsignedIntegerFromMemory(addr, size, 0, error);
if (error.Fail())
return 0;
return addr + size;
}
addr_t HexagonDYLDRendezvous::ReadPointer(addr_t addr, addr_t *dst) {
Status error;
*dst = m_process->ReadPointerFromMemory(addr, error);
if (error.Fail())
return 0;
return addr + m_process->GetAddressByteSize();
}
std::string HexagonDYLDRendezvous::ReadStringFromMemory(addr_t addr) {
std::string str;
Status error;
size_t size;
char c;
if (addr == LLDB_INVALID_ADDRESS)
return std::string();
for (;;) {
size = m_process->DoReadMemory(addr, &c, 1, error);
if (size != 1 || error.Fail())
return std::string();
if (c == 0)
break;
else {
str.push_back(c);
addr++;
}
}
return str;
}
bool HexagonDYLDRendezvous::ReadSOEntryFromMemory(lldb::addr_t addr,
SOEntry &entry) {
entry.clear();
entry.link_addr = addr;
if (!(addr = ReadPointer(addr, &entry.base_addr)))
return false;
if (!(addr = ReadPointer(addr, &entry.path_addr)))
return false;
if (!(addr = ReadPointer(addr, &entry.dyn_addr)))
return false;
if (!(addr = ReadPointer(addr, &entry.next)))
return false;
if (!(addr = ReadPointer(addr, &entry.prev)))
return false;
entry.path = ReadStringFromMemory(entry.path_addr);
return true;
}
bool HexagonDYLDRendezvous::FindMetadata(const char *name, PThreadField field,
uint32_t &value) {
Target &target = m_process->GetTarget();
SymbolContextList list;
if (!target.GetImages().FindSymbolsWithNameAndType(ConstString(name),
eSymbolTypeAny, list))
return false;
Address address = list[0].symbol->GetAddress();
addr_t addr = address.GetLoadAddress(&target);
if (addr == LLDB_INVALID_ADDRESS)
return false;
Status error;
value = (uint32_t)m_process->ReadUnsignedIntegerFromMemory(
addr + field * sizeof(uint32_t), sizeof(uint32_t), 0, error);
if (error.Fail())
return false;
if (field == eSize)
value /= 8; // convert bits to bytes
return true;
}
const HexagonDYLDRendezvous::ThreadInfo &
HexagonDYLDRendezvous::GetThreadInfo() {
if (!m_thread_info.valid) {
bool ok = true;
ok &= FindMetadata("_thread_db_pthread_dtvp", eOffset,
m_thread_info.dtv_offset);
ok &=
FindMetadata("_thread_db_dtv_dtv", eSize, m_thread_info.dtv_slot_size);
ok &= FindMetadata("_thread_db_link_map_l_tls_modid", eOffset,
m_thread_info.modid_offset);
ok &= FindMetadata("_thread_db_dtv_t_pointer_val", eOffset,
m_thread_info.tls_offset);
if (ok)
m_thread_info.valid = true;
}
return m_thread_info;
}
void HexagonDYLDRendezvous::DumpToLog(Log *log) const {
int state = GetState();
if (!log)
return;
log->PutCString("HexagonDYLDRendezvous:");
log->Printf(" Address: %" PRIx64, GetRendezvousAddress());
log->Printf(" Version: %" PRIu64, GetVersion());
log->Printf(" Link : %" PRIx64, GetLinkMapAddress());
log->Printf(" Break : %" PRIx64, GetBreakAddress());
log->Printf(" LDBase : %" PRIx64, GetLDBase());
log->Printf(" State : %s",
(state == eConsistent)
? "consistent"
: (state == eAdd) ? "add" : (state == eDelete) ? "delete"
: "unknown");
iterator I = begin();
iterator E = end();
if (I != E)
log->PutCString("HexagonDYLDRendezvous SOEntries:");
for (int i = 1; I != E; ++I, ++i) {
log->Printf("\n SOEntry [%d] %s", i, I->path.c_str());
log->Printf(" Base : %" PRIx64, I->base_addr);
log->Printf(" Path : %" PRIx64, I->path_addr);
log->Printf(" Dyn : %" PRIx64, I->dyn_addr);
log->Printf(" Next : %" PRIx64, I->next);
log->Printf(" Prev : %" PRIx64, I->prev);
}
}

View File

@@ -0,0 +1,247 @@
//===-- HexagonDYLDRendezvous.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_HexagonDYLDRendezvous_H_
#define liblldb_HexagonDYLDRendezvous_H_
// C Includes
// C++ Includes
#include <list>
#include <string>
// Other libraries and framework includes
#include "lldb/lldb-defines.h"
#include "lldb/lldb-types.h"
namespace lldb_private {
class Process;
}
/// @class HexagonDYLDRendezvous
/// @brief Interface to the runtime linker.
///
/// A structure is present in a processes memory space which is updated by the
/// runtime liker each time a module is loaded or unloaded. This class provides
/// an interface to this structure and maintains a consistent snapshot of the
/// currently loaded modules.
class HexagonDYLDRendezvous {
// This structure is used to hold the contents of the debug rendezvous
// information (struct r_debug) as found in the inferiors memory. Note that
// the layout of this struct is not binary compatible, it is simply large
// enough to hold the information on both 32 and 64 bit platforms.
struct Rendezvous {
uint64_t version;
lldb::addr_t map_addr;
lldb::addr_t brk;
uint64_t state;
lldb::addr_t ldbase;
Rendezvous()
: version(0), map_addr(LLDB_INVALID_ADDRESS), brk(LLDB_INVALID_ADDRESS),
state(0), ldbase(0) {}
};
public:
// Various metadata supplied by the inferior's threading library to describe
// the per-thread state.
struct ThreadInfo {
bool valid; // whether we read valid metadata
uint32_t dtv_offset; // offset of DTV pointer within pthread
uint32_t dtv_slot_size; // size of one DTV slot
uint32_t modid_offset; // offset of module ID within link_map
uint32_t tls_offset; // offset of TLS pointer within DTV slot
};
HexagonDYLDRendezvous(lldb_private::Process *process);
/// Update the internal snapshot of runtime linker rendezvous and recompute
/// the currently loaded modules.
///
/// This method should be called once one start up, then once each time the
/// runtime linker enters the function given by GetBreakAddress().
///
/// @returns true on success and false on failure.
///
/// @see GetBreakAddress().
bool Resolve();
/// @returns true if this rendezvous has been located in the inferiors
/// address space and false otherwise.
bool IsValid();
/// @returns the address of the rendezvous structure in the inferiors
/// address space.
lldb::addr_t GetRendezvousAddress() const { return m_rendezvous_addr; }
/// Provide the dyld structure address
void SetRendezvousAddress(lldb::addr_t);
/// @returns the version of the rendezvous protocol being used.
uint64_t GetVersion() const { return m_current.version; }
/// @returns address in the inferiors address space containing the linked
/// list of shared object descriptors.
lldb::addr_t GetLinkMapAddress() const { return m_current.map_addr; }
/// A breakpoint should be set at this address and Resolve called on each
/// hit.
///
/// @returns the address of a function called by the runtime linker each
/// time a module is loaded/unloaded, or about to be loaded/unloaded.
///
/// @see Resolve()
lldb::addr_t GetBreakAddress() const { return m_current.brk; }
/// In hexagon it is possible that we can know the dyld breakpoint without
/// having to find it from the rendezvous structure
///
void SetBreakAddress(lldb::addr_t addr) { m_current.brk = addr; }
/// Returns the current state of the rendezvous structure.
uint64_t GetState() const { return m_current.state; }
/// @returns the base address of the runtime linker in the inferiors address
/// space.
lldb::addr_t GetLDBase() const { return m_current.ldbase; }
/// @returns the thread layout metadata from the inferiors thread library.
const ThreadInfo &GetThreadInfo();
/// @returns true if modules have been loaded into the inferior since the
/// last call to Resolve().
bool ModulesDidLoad() const { return !m_added_soentries.empty(); }
/// @returns true if modules have been unloaded from the inferior since the
/// last call to Resolve().
bool ModulesDidUnload() const { return !m_removed_soentries.empty(); }
void DumpToLog(lldb_private::Log *log) const;
/// @brief Constants describing the state of the rendezvous.
///
/// @see GetState().
enum RendezvousState {
eConsistent = 0,
eAdd,
eDelete,
};
/// @brief Structure representing the shared objects currently loaded into
/// the inferior process.
///
/// This object is a rough analogue to the struct link_map object which
/// actually lives in the inferiors memory.
struct SOEntry {
lldb::addr_t link_addr; ///< Address of this link_map.
lldb::addr_t base_addr; ///< Base address of the loaded object.
lldb::addr_t path_addr; ///< String naming the shared object.
lldb::addr_t dyn_addr; ///< Dynamic section of shared object.
lldb::addr_t next; ///< Address of next so_entry.
lldb::addr_t prev; ///< Address of previous so_entry.
std::string path; ///< File name of shared object.
SOEntry() { clear(); }
bool operator==(const SOEntry &entry) { return this->path == entry.path; }
void clear() {
link_addr = 0;
base_addr = 0;
path_addr = 0;
dyn_addr = 0;
next = 0;
prev = 0;
path.clear();
}
};
protected:
typedef std::list<SOEntry> SOEntryList;
public:
typedef SOEntryList::const_iterator iterator;
/// Iterators over all currently loaded modules.
iterator begin() const { return m_soentries.begin(); }
iterator end() const { return m_soentries.end(); }
/// Iterators over all modules loaded into the inferior since the last call
/// to Resolve().
iterator loaded_begin() const { return m_added_soentries.begin(); }
iterator loaded_end() const { return m_added_soentries.end(); }
/// Iterators over all modules unloaded from the inferior since the last
/// call to Resolve().
iterator unloaded_begin() const { return m_removed_soentries.begin(); }
iterator unloaded_end() const { return m_removed_soentries.end(); }
protected:
lldb_private::Process *m_process;
// Cached copy of executable pathname
char m_exe_path[PATH_MAX];
/// Location of the r_debug structure in the inferiors address space.
lldb::addr_t m_rendezvous_addr;
/// Current and previous snapshots of the rendezvous structure.
Rendezvous m_current;
Rendezvous m_previous;
/// List of SOEntry objects corresponding to the current link map state.
SOEntryList m_soentries;
/// List of SOEntry's added to the link map since the last call to Resolve().
SOEntryList m_added_soentries;
/// List of SOEntry's removed from the link map since the last call to
/// Resolve().
SOEntryList m_removed_soentries;
/// Threading metadata read from the inferior.
ThreadInfo m_thread_info;
/// Reads an unsigned integer of @p size bytes from the inferior's address
/// space starting at @p addr.
///
/// @returns addr + size if the read was successful and false otherwise.
lldb::addr_t ReadWord(lldb::addr_t addr, uint64_t *dst, size_t size);
/// Reads an address from the inferior's address space starting at @p addr.
///
/// @returns addr + target address size if the read was successful and
/// 0 otherwise.
lldb::addr_t ReadPointer(lldb::addr_t addr, lldb::addr_t *dst);
/// Reads a null-terminated C string from the memory location starting at @p
/// addr.
std::string ReadStringFromMemory(lldb::addr_t addr);
/// Reads an SOEntry starting at @p addr.
bool ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry);
/// Updates the current set of SOEntries, the set of added entries, and the
/// set of removed entries.
bool UpdateSOEntries();
bool UpdateSOEntriesForAddition();
bool UpdateSOEntriesForDeletion();
/// Reads the current list of shared objects according to the link map
/// supplied by the runtime linker.
bool TakeSnapshot(SOEntryList &entry_list);
enum PThreadField { eSize, eNElem, eOffset };
bool FindMetadata(const char *name, PThreadField field, uint32_t &value);
};
#endif // liblldb_HexagonDYLDRendezvous_H_

View File

@@ -0,0 +1,16 @@
add_lldb_library(lldbPluginDynamicLoaderMacOSXDYLD PLUGIN
DynamicLoaderMacOSXDYLD.cpp
DynamicLoaderMacOS.cpp
DynamicLoaderDarwin.cpp
LINK_LIBS
lldbBreakpoint
lldbCore
lldbExpression
lldbHost
lldbSymbol
lldbTarget
lldbUtility
LINK_COMPONENTS
Support
)

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,245 @@
//===-- DynamicLoaderDarwin.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_DynamicLoaderDarwin_h_
#define liblldb_DynamicLoaderDarwin_h_
// C Includes
// C++ Includes
#include <map>
#include <mutex>
#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/SafeMachO.h"
#include "lldb/Utility/StructuredData.h"
#include "lldb/Utility/UUID.h"
#include "llvm/ADT/Triple.h"
namespace lldb_private {
class DynamicLoaderDarwin : public lldb_private::DynamicLoader {
public:
DynamicLoaderDarwin(lldb_private::Process *process);
virtual ~DynamicLoaderDarwin() override;
//------------------------------------------------------------------
/// 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;
size_t FindEquivalentSymbols(
lldb_private::Symbol *original_symbol,
lldb_private::ModuleList &module_list,
lldb_private::SymbolContextList &equivalent_symbols) override;
lldb::addr_t GetThreadLocalData(const lldb::ModuleSP module,
const lldb::ThreadSP thread,
lldb::addr_t tls_file_addr) override;
bool AlwaysRelyOnEHUnwindInfo(lldb_private::SymbolContext &sym_ctx) override;
virtual void DoInitialImageFetch() = 0;
virtual bool NeedToDoInitialImageFetch() = 0;
protected:
void PrivateInitialize(lldb_private::Process *process);
void PrivateProcessStateChanged(lldb_private::Process *process,
lldb::StateType state);
void Clear(bool clear_process);
// Clear method for classes derived from this one
virtual void DoClear() = 0;
void SetDYLDModule(lldb::ModuleSP &dyld_module_sp);
lldb::ModuleSP GetDYLDModule();
class Segment {
public:
Segment()
: name(), vmaddr(LLDB_INVALID_ADDRESS), vmsize(0), fileoff(0),
filesize(0), maxprot(0), initprot(0), nsects(0), flags(0) {}
lldb_private::ConstString name;
lldb::addr_t vmaddr;
lldb::addr_t vmsize;
lldb::addr_t fileoff;
lldb::addr_t filesize;
uint32_t maxprot;
uint32_t initprot;
uint32_t nsects;
uint32_t flags;
bool operator==(const Segment &rhs) const {
return name == rhs.name && vmaddr == rhs.vmaddr && vmsize == rhs.vmsize;
}
void PutToLog(lldb_private::Log *log, lldb::addr_t slide) const;
};
struct ImageInfo {
lldb::addr_t address; // Address of mach header for this dylib
lldb::addr_t slide; // The amount to slide all segments by if there is a
// global slide.
lldb::addr_t mod_date; // Modification date for this dylib
lldb_private::FileSpec file_spec; // Resolved path for this dylib
lldb_private::UUID
uuid; // UUID for this dylib if it has one, else all zeros
llvm::MachO::mach_header header; // The mach header for this image
std::vector<Segment> segments; // All segment vmaddr and vmsize pairs for
// this executable (from memory of inferior)
uint32_t load_stop_id; // The process stop ID that the sections for this
// image were loaded
llvm::Triple::OSType os_type; // LC_VERSION_MIN_... load command os type
std::string min_version_os_sdk; // LC_VERSION_MIN_... sdk value
ImageInfo()
: address(LLDB_INVALID_ADDRESS), slide(0), mod_date(0), file_spec(),
uuid(), header(), segments(), load_stop_id(0),
os_type(llvm::Triple::OSType::UnknownOS), min_version_os_sdk() {}
void Clear(bool load_cmd_data_only) {
if (!load_cmd_data_only) {
address = LLDB_INVALID_ADDRESS;
slide = 0;
mod_date = 0;
file_spec.Clear();
::memset(&header, 0, sizeof(header));
}
uuid.Clear();
segments.clear();
load_stop_id = 0;
os_type = llvm::Triple::OSType::UnknownOS;
min_version_os_sdk.clear();
}
bool operator==(const ImageInfo &rhs) const {
return address == rhs.address && slide == rhs.slide &&
mod_date == rhs.mod_date && file_spec == rhs.file_spec &&
uuid == rhs.uuid &&
memcmp(&header, &rhs.header, sizeof(header)) == 0 &&
segments == rhs.segments && os_type == rhs.os_type;
}
bool UUIDValid() const { return uuid.IsValid(); }
uint32_t GetAddressByteSize() {
if (header.cputype) {
if (header.cputype & llvm::MachO::CPU_ARCH_ABI64)
return 8;
else
return 4;
}
return 0;
}
lldb_private::ArchSpec GetArchitecture() const {
return lldb_private::ArchSpec(lldb_private::eArchTypeMachO,
header.cputype, header.cpusubtype);
}
const Segment *FindSegment(const lldb_private::ConstString &name) const;
void PutToLog(lldb_private::Log *log) const;
typedef std::vector<ImageInfo> collection;
typedef collection::iterator iterator;
typedef collection::const_iterator const_iterator;
};
bool UpdateImageLoadAddress(lldb_private::Module *module, ImageInfo &info);
bool UnloadModuleSections(lldb_private::Module *module, ImageInfo &info);
lldb::ModuleSP FindTargetModuleForImageInfo(ImageInfo &image_info,
bool can_create,
bool *did_create_ptr);
void UnloadImages(const std::vector<lldb::addr_t> &solib_addresses);
void UnloadAllImages();
virtual bool SetNotificationBreakpoint() = 0;
virtual void ClearNotificationBreakpoint() = 0;
virtual bool DidSetNotificationBreakpoint() = 0;
typedef std::map<uint64_t, lldb::addr_t> PthreadKeyToTLSMap;
typedef std::map<lldb::user_id_t, PthreadKeyToTLSMap> ThreadIDToTLSMap;
std::recursive_mutex &GetMutex() const { return m_mutex; }
lldb::ModuleSP GetPThreadLibraryModule();
lldb_private::Address GetPthreadSetSpecificAddress();
bool JSONImageInformationIntoImageInfo(
lldb_private::StructuredData::ObjectSP image_details,
ImageInfo::collection &image_infos);
// If image_infos contains / may contain dyld or executable image, call this
// method
// to keep our internal record keeping of the special binaries up-to-date.
void
UpdateSpecialBinariesFromNewImageInfos(ImageInfo::collection &image_infos);
// if image_info is a dyld binary, call this method
void UpdateDYLDImageInfoFromNewImageInfo(ImageInfo &image_info);
// If image_infos contains / may contain executable image, call this method
// to keep our internal record keeping of the special dyld binary up-to-date.
void AddExecutableModuleIfInImageInfos(ImageInfo::collection &image_infos);
bool AddModulesUsingImageInfos(ImageInfo::collection &image_infos);
// Whether we should use the new dyld SPI to get shared library information,
// or read
// it directly out of the dyld_all_image_infos. Whether we use the (newer)
// DynamicLoaderMacOS
// plugin or the (older) DynamicLoaderMacOSX plugin.
static bool UseDYLDSPI(lldb_private::Process *process);
lldb::ModuleWP m_dyld_module_wp; // the dyld whose file type (mac, ios, etc)
// matches the process
lldb::ModuleWP m_libpthread_module_wp;
lldb_private::Address m_pthread_getspecific_addr;
ThreadIDToTLSMap m_tid_to_tls_map;
ImageInfo::collection
m_dyld_image_infos; // Current shared libraries information
uint32_t m_dyld_image_infos_stop_id; // The process stop ID that
// "m_dyld_image_infos" is valid for
ImageInfo m_dyld;
mutable std::recursive_mutex m_mutex;
private:
DISALLOW_COPY_AND_ASSIGN(DynamicLoaderDarwin);
};
} // namespace lldb_private
#endif // liblldb_DynamicLoaderDarwin_h_

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,117 @@
//===-- DynamicLoaderMacOS.h -------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// This is the DynamicLoader plugin for Darwin (macOS / iPhoneOS / tvOS /
// watchOS)
// platforms late 2016 and newer, where lldb will call dyld SPI functions to get
// information about shared libraries, information about the shared cache, and
// the _dyld_debugger_notification function we put a breakpoint on give us an
// array of load addresses for solibs loaded and unloaded. The SPI will tell us
// about both dyld and the executable, in addition to all of the usual solibs.
#ifndef liblldb_DynamicLoaderMacOS_h_
#define liblldb_DynamicLoaderMacOS_h_
// C Includes
// C++ Includes
#include <mutex>
#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/SafeMachO.h"
#include "lldb/Utility/StructuredData.h"
#include "lldb/Utility/UUID.h"
#include "DynamicLoaderDarwin.h"
class DynamicLoaderMacOS : public lldb_private::DynamicLoaderDarwin {
public:
DynamicLoaderMacOS(lldb_private::Process *process);
virtual ~DynamicLoaderMacOS() 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);
//------------------------------------------------------------------
/// Called after attaching a process.
///
/// Allow DynamicLoader plug-ins to execute some code after
/// attaching to a process.
//------------------------------------------------------------------
bool ProcessDidExec() override;
lldb_private::Status CanLoadImage() override;
bool GetSharedCacheInformation(
lldb::addr_t &base_address, lldb_private::UUID &uuid,
lldb_private::LazyBool &using_shared_cache,
lldb_private::LazyBool &private_shared_cache) override;
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
lldb_private::ConstString GetPluginName() override;
uint32_t GetPluginVersion() override;
protected:
void PutToLog(lldb_private::Log *log) const;
void DoInitialImageFetch() override;
bool NeedToDoInitialImageFetch() override;
bool DidSetNotificationBreakpoint() override;
void AddBinaries(const std::vector<lldb::addr_t> &load_addresses);
void DoClear() override;
static bool
NotifyBreakpointHit(void *baton,
lldb_private::StoppointCallbackContext *context,
lldb::user_id_t break_id, lldb::user_id_t break_loc_id);
bool SetNotificationBreakpoint() override;
void ClearNotificationBreakpoint() override;
void UpdateImageInfosHeaderAndLoadCommands(ImageInfo::collection &image_infos,
uint32_t infos_count,
bool update_executable);
lldb::addr_t
GetDyldLockVariableAddressFromModule(lldb_private::Module *module);
uint32_t m_image_infos_stop_id; // The Stop ID the last time we
// loaded/unloaded images
lldb::user_id_t m_break_id;
mutable std::recursive_mutex m_mutex;
private:
DISALLOW_COPY_AND_ASSIGN(DynamicLoaderMacOS);
};
#endif // liblldb_DynamicLoaderMacOS_h_

View File

@@ -0,0 +1,186 @@
//===-- DynamicLoaderMacOSXDYLD.h -------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// This is the DynamicLoader plugin for Darwin (macOS / iPhoneOS / tvOS /
// watchOS)
// platforms earlier than 2016, where lldb would read the "dyld_all_image_infos"
// dyld internal structure to understand where things were loaded and the
// solib loaded/unloaded notification function we put a breakpoint on gives us
// an array of (load address, mod time, file path) tuples.
//
// As of late 2016, the new DynamicLoaderMacOS plugin should be used, which uses
// dyld SPI functions to get the same information without reading internal dyld
// data structures.
#ifndef liblldb_DynamicLoaderMacOSXDYLD_h_
#define liblldb_DynamicLoaderMacOSXDYLD_h_
// C Includes
// C++ Includes
#include <mutex>
#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/SafeMachO.h"
#include "lldb/Utility/StructuredData.h"
#include "lldb/Utility/UUID.h"
#include "DynamicLoaderDarwin.h"
class DynamicLoaderMacOSXDYLD : public lldb_private::DynamicLoaderDarwin {
public:
DynamicLoaderMacOSXDYLD(lldb_private::Process *process);
virtual ~DynamicLoaderMacOSXDYLD() 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);
//------------------------------------------------------------------
/// Called after attaching a process.
///
/// Allow DynamicLoader plug-ins to execute some code after
/// attaching to a process.
//------------------------------------------------------------------
bool ProcessDidExec() override;
lldb_private::Status CanLoadImage() override;
bool GetSharedCacheInformation(
lldb::addr_t &base_address, lldb_private::UUID &uuid,
lldb_private::LazyBool &using_shared_cache,
lldb_private::LazyBool &private_shared_cache) override;
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
lldb_private::ConstString GetPluginName() override;
uint32_t GetPluginVersion() override;
protected:
void PutToLog(lldb_private::Log *log) const;
void DoInitialImageFetch() override;
bool NeedToDoInitialImageFetch() override;
bool DidSetNotificationBreakpoint() override;
void DoClear() override;
bool ReadDYLDInfoFromMemoryAndSetNotificationCallback(lldb::addr_t addr);
static bool
NotifyBreakpointHit(void *baton,
lldb_private::StoppointCallbackContext *context,
lldb::user_id_t break_id, lldb::user_id_t break_loc_id);
uint32_t AddrByteSize();
bool ReadMachHeader(lldb::addr_t addr, llvm::MachO::mach_header *header,
lldb_private::DataExtractor *load_command_data);
uint32_t ParseLoadCommands(const lldb_private::DataExtractor &data,
ImageInfo &dylib_info,
lldb_private::FileSpec *lc_id_dylinker);
struct DYLDAllImageInfos {
uint32_t version;
uint32_t dylib_info_count; // Version >= 1
lldb::addr_t dylib_info_addr; // Version >= 1
lldb::addr_t notification; // Version >= 1
bool processDetachedFromSharedRegion; // Version >= 1
bool libSystemInitialized; // Version >= 2
lldb::addr_t dyldImageLoadAddress; // Version >= 2
DYLDAllImageInfos()
: version(0), dylib_info_count(0),
dylib_info_addr(LLDB_INVALID_ADDRESS),
notification(LLDB_INVALID_ADDRESS),
processDetachedFromSharedRegion(false), libSystemInitialized(false),
dyldImageLoadAddress(LLDB_INVALID_ADDRESS) {}
void Clear() {
version = 0;
dylib_info_count = 0;
dylib_info_addr = LLDB_INVALID_ADDRESS;
notification = LLDB_INVALID_ADDRESS;
processDetachedFromSharedRegion = false;
libSystemInitialized = false;
dyldImageLoadAddress = LLDB_INVALID_ADDRESS;
}
bool IsValid() const { return version >= 1 || version <= 6; }
};
static lldb::ByteOrder GetByteOrderFromMagic(uint32_t magic);
bool SetNotificationBreakpoint() override;
void ClearNotificationBreakpoint() override;
// There is a little tricky bit where you might initially attach while dyld is
// updating
// the all_image_infos, and you can't read the infos, so you have to continue
// and pick it
// up when you hit the update breakpoint. At that point, you need to run this
// initialize
// function, but when you do it that way you DON'T need to do the extra work
// you would at
// the breakpoint.
// So this function will only do actual work if the image infos haven't been
// read yet.
// If it does do any work, then it will return true, and false otherwise.
// That way you can
// call it in the breakpoint action, and if it returns true you're done.
bool InitializeFromAllImageInfos();
bool ReadAllImageInfosStructure();
bool AddModulesUsingImageInfosAddress(lldb::addr_t image_infos_addr,
uint32_t image_infos_count);
bool RemoveModulesUsingImageInfosAddress(lldb::addr_t image_infos_addr,
uint32_t image_infos_count);
void UpdateImageInfosHeaderAndLoadCommands(ImageInfo::collection &image_infos,
uint32_t infos_count,
bool update_executable);
bool ReadImageInfos(lldb::addr_t image_infos_addr, uint32_t image_infos_count,
ImageInfo::collection &image_infos);
lldb::addr_t m_dyld_all_image_infos_addr;
DYLDAllImageInfos m_dyld_all_image_infos;
uint32_t m_dyld_all_image_infos_stop_id;
lldb::user_id_t m_break_id;
mutable std::recursive_mutex m_mutex;
bool m_process_image_addr_is_all_images_infos;
private:
DISALLOW_COPY_AND_ASSIGN(DynamicLoaderMacOSXDYLD);
};
#endif // liblldb_DynamicLoaderMacOSXDYLD_h_

View File

@@ -0,0 +1,142 @@
//===-- AuxVector.cpp -------------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "AuxVector.h"
#include "lldb/Target/Process.h"
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/DataExtractor.h"
#include "lldb/Utility/Log.h"
using namespace lldb;
using namespace lldb_private;
static bool GetMaxU64(DataExtractor &data, lldb::offset_t *offset_ptr,
uint64_t *value, unsigned int byte_size) {
lldb::offset_t saved_offset = *offset_ptr;
*value = data.GetMaxU64(offset_ptr, byte_size);
return *offset_ptr != saved_offset;
}
static bool ParseAuxvEntry(DataExtractor &data, AuxVector::Entry &entry,
lldb::offset_t *offset_ptr, unsigned int byte_size) {
if (!GetMaxU64(data, offset_ptr, &entry.type, byte_size))
return false;
if (!GetMaxU64(data, offset_ptr, &entry.value, byte_size))
return false;
return true;
}
DataBufferSP AuxVector::GetAuxvData() {
if (m_process)
return m_process->GetAuxvData();
else
return DataBufferSP();
}
void AuxVector::ParseAuxv(DataExtractor &data) {
const unsigned int byte_size = m_process->GetAddressByteSize();
lldb::offset_t offset = 0;
for (;;) {
Entry entry;
if (!ParseAuxvEntry(data, entry, &offset, byte_size))
break;
if (entry.type == AUXV_AT_NULL)
break;
if (entry.type == AUXV_AT_IGNORE)
continue;
m_auxv.push_back(entry);
}
}
AuxVector::AuxVector(Process *process) : m_process(process) {
DataExtractor data;
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER));
data.SetData(GetAuxvData());
data.SetByteOrder(m_process->GetByteOrder());
data.SetAddressByteSize(m_process->GetAddressByteSize());
ParseAuxv(data);
if (log)
DumpToLog(log);
}
AuxVector::iterator AuxVector::FindEntry(EntryType type) const {
for (iterator I = begin(); I != end(); ++I) {
if (I->type == static_cast<uint64_t>(type))
return I;
}
return end();
}
void AuxVector::DumpToLog(Log *log) const {
if (!log)
return;
log->PutCString("AuxVector: ");
for (iterator I = begin(); I != end(); ++I) {
log->Printf(" %s [%" PRIu64 "]: %" PRIx64, GetEntryName(*I), I->type,
I->value);
}
}
const char *AuxVector::GetEntryName(EntryType type) {
const char *name = "AT_???";
#define ENTRY_NAME(_type) \
_type: \
name = #_type + 5
switch (type) {
case ENTRY_NAME(AUXV_AT_NULL); break;
case ENTRY_NAME(AUXV_AT_IGNORE); break;
case ENTRY_NAME(AUXV_AT_EXECFD); break;
case ENTRY_NAME(AUXV_AT_PHDR); break;
case ENTRY_NAME(AUXV_AT_PHENT); break;
case ENTRY_NAME(AUXV_AT_PHNUM); break;
case ENTRY_NAME(AUXV_AT_PAGESZ); break;
case ENTRY_NAME(AUXV_AT_BASE); break;
case ENTRY_NAME(AUXV_AT_FLAGS); break;
case ENTRY_NAME(AUXV_AT_ENTRY); break;
case ENTRY_NAME(AUXV_AT_NOTELF); break;
case ENTRY_NAME(AUXV_AT_UID); break;
case ENTRY_NAME(AUXV_AT_EUID); break;
case ENTRY_NAME(AUXV_AT_GID); break;
case ENTRY_NAME(AUXV_AT_EGID); break;
case ENTRY_NAME(AUXV_AT_CLKTCK); break;
case ENTRY_NAME(AUXV_AT_PLATFORM); break;
case ENTRY_NAME(AUXV_AT_HWCAP); break;
case ENTRY_NAME(AUXV_AT_FPUCW); break;
case ENTRY_NAME(AUXV_AT_DCACHEBSIZE); break;
case ENTRY_NAME(AUXV_AT_ICACHEBSIZE); break;
case ENTRY_NAME(AUXV_AT_UCACHEBSIZE); break;
case ENTRY_NAME(AUXV_AT_IGNOREPPC); break;
case ENTRY_NAME(AUXV_AT_SECURE); break;
case ENTRY_NAME(AUXV_AT_BASE_PLATFORM); break;
case ENTRY_NAME(AUXV_AT_RANDOM); break;
case ENTRY_NAME(AUXV_AT_EXECFN); break;
case ENTRY_NAME(AUXV_AT_SYSINFO); break;
case ENTRY_NAME(AUXV_AT_SYSINFO_EHDR); break;
case ENTRY_NAME(AUXV_AT_L1I_CACHESHAPE); break;
case ENTRY_NAME(AUXV_AT_L1D_CACHESHAPE); break;
case ENTRY_NAME(AUXV_AT_L2_CACHESHAPE); break;
case ENTRY_NAME(AUXV_AT_L3_CACHESHAPE); break;
}
#undef ENTRY_NAME
return name;
}

View File

@@ -0,0 +1,111 @@
//===-- AuxVector.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_AuxVector_H_
#define liblldb_AuxVector_H_
// C Includes
// C++ Includes
#include <vector>
// Other libraries and framework includes
#include "lldb/lldb-forward.h"
namespace lldb_private {
class DataExtractor;
}
/// @class AuxVector
/// @brief Represents a processes auxiliary vector.
///
/// When a process is loaded on Linux a vector of values is placed onto the
/// stack communicating operating system specific information. On construction
/// this class locates and parses this information and provides a simple
/// read-only interface to the entries found.
class AuxVector {
public:
AuxVector(lldb_private::Process *process);
struct Entry {
uint64_t type;
uint64_t value;
Entry() : type(0), value(0) {}
};
/// Constants describing the type of entry.
/// On Linux, running "LD_SHOW_AUXV=1 ./executable" will spew AUX information.
/// Added AUXV prefix to avoid potential conflicts with system-defined macros
enum EntryType {
AUXV_AT_NULL = 0, ///< End of auxv.
AUXV_AT_IGNORE = 1, ///< Ignore entry.
AUXV_AT_EXECFD = 2, ///< File descriptor of program.
AUXV_AT_PHDR = 3, ///< Program headers.
AUXV_AT_PHENT = 4, ///< Size of program header.
AUXV_AT_PHNUM = 5, ///< Number of program headers.
AUXV_AT_PAGESZ = 6, ///< Page size.
AUXV_AT_BASE = 7, ///< Interpreter base address.
AUXV_AT_FLAGS = 8, ///< Flags.
AUXV_AT_ENTRY = 9, ///< Program entry point.
AUXV_AT_NOTELF = 10, ///< Set if program is not an ELF.
AUXV_AT_UID = 11, ///< UID.
AUXV_AT_EUID = 12, ///< Effective UID.
AUXV_AT_GID = 13, ///< GID.
AUXV_AT_EGID = 14, ///< Effective GID.
AUXV_AT_CLKTCK = 17, ///< Clock frequency (e.g. times(2)).
AUXV_AT_PLATFORM = 15, ///< String identifying platform.
AUXV_AT_HWCAP = 16, ///< Machine dependent hints about processor capabilities.
AUXV_AT_FPUCW = 18, ///< Used FPU control word.
AUXV_AT_DCACHEBSIZE = 19, ///< Data cache block size.
AUXV_AT_ICACHEBSIZE = 20, ///< Instruction cache block size.
AUXV_AT_UCACHEBSIZE = 21, ///< Unified cache block size.
AUXV_AT_IGNOREPPC = 22, ///< Entry should be ignored.
AUXV_AT_SECURE = 23, ///< Boolean, was exec setuid-like?
AUXV_AT_BASE_PLATFORM = 24, ///< String identifying real platforms.
AUXV_AT_RANDOM = 25, ///< Address of 16 random bytes.
AUXV_AT_EXECFN = 31, ///< Filename of executable.
AUXV_AT_SYSINFO = 32, ///< Pointer to the global system page used for system
///calls and other nice things.
AUXV_AT_SYSINFO_EHDR = 33,
AUXV_AT_L1I_CACHESHAPE = 34, ///< Shapes of the caches.
AUXV_AT_L1D_CACHESHAPE = 35,
AUXV_AT_L2_CACHESHAPE = 36,
AUXV_AT_L3_CACHESHAPE = 37,
};
private:
typedef std::vector<Entry> EntryVector;
public:
typedef EntryVector::const_iterator iterator;
iterator begin() const { return m_auxv.begin(); }
iterator end() const { return m_auxv.end(); }
iterator FindEntry(EntryType type) const;
static const char *GetEntryName(const Entry &entry) {
return GetEntryName(static_cast<EntryType>(entry.type));
}
static const char *GetEntryName(EntryType type);
void DumpToLog(lldb_private::Log *log) const;
private:
lldb_private::Process *m_process;
EntryVector m_auxv;
lldb::DataBufferSP GetAuxvData();
void ParseAuxv(lldb_private::DataExtractor &data);
};
#endif

View File

@@ -0,0 +1,15 @@
add_lldb_library(lldbPluginDynamicLoaderPosixDYLD PLUGIN
AuxVector.cpp
DYLDRendezvous.cpp
DynamicLoaderPOSIXDYLD.cpp
LINK_LIBS
lldbBreakpoint
lldbCore
lldbHost
lldbSymbol
lldbTarget
lldbPluginProcessElfCore
LINK_COMPONENTS
Support
)

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More