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,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

View File

@@ -0,0 +1,256 @@
//===-- DYLDRendezvous.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_Rendezvous_H_
#define liblldb_Rendezvous_H_
// C Includes
// C++ Includes
#include <list>
#include <string>
// Other libraries and framework includes
#include "lldb/Utility/FileSpec.h"
#include "lldb/lldb-defines.h"
#include "lldb/lldb-types.h"
#include "lldb/Core/LoadedModuleInfoList.h"
using lldb_private::LoadedModuleInfoList;
namespace lldb_private {
class Process;
}
/// @class DYLDRendezvous
/// @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 DYLDRendezvous {
// 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(0), brk(0), 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
};
DYLDRendezvous(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; }
/// @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; }
/// 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, 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.
lldb_private::FileSpec file_spec; ///< File spec of shared object.
SOEntry() { clear(); }
bool operator==(const SOEntry &entry) {
return file_spec == entry.file_spec;
}
void clear() {
link_addr = 0;
base_addr = 0;
path_addr = 0;
dyn_addr = 0;
next = 0;
prev = 0;
file_spec.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 file spec
lldb_private::FileSpec m_exe_file_spec;
/// 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 currently loaded SO modules
LoadedModuleInfoList m_loaded_modules;
/// 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 fromRemote = false);
bool FillSOEntryFromModuleInfo(
LoadedModuleInfoList::LoadedModuleInfo const &modInfo, SOEntry &entry);
bool SaveSOEntriesFromRemote(LoadedModuleInfoList &module_list);
bool AddSOEntriesFromRemote(LoadedModuleInfoList &module_list);
bool RemoveSOEntriesFromRemote(LoadedModuleInfoList &module_list);
bool AddSOEntries();
bool RemoveSOEntries();
void UpdateBaseAddrIfNecessary(SOEntry &entry, std::string const &file_path);
bool SOEntryIsMainExecutable(const SOEntry &entry);
/// 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

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,164 @@
//===-- DynamicLoaderPOSIXDYLD.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_DynamicLoaderPOSIXDYLD_h_
#define liblldb_DynamicLoaderPOSIXDYLD_h_
// C Includes
// C++ Includes
#include <map>
#include <memory>
// Other libraries and framework includes
// Project includes
#include "DYLDRendezvous.h"
#include "lldb/Breakpoint/StoppointCallbackContext.h"
#include "lldb/Core/ModuleList.h"
#include "lldb/Target/DynamicLoader.h"
class AuxVector;
class DynamicLoaderPOSIXDYLD : public lldb_private::DynamicLoader {
public:
DynamicLoaderPOSIXDYLD(lldb_private::Process *process);
~DynamicLoaderPOSIXDYLD() 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.
DYLDRendezvous 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;
/// Auxiliary vector of the inferior process.
std::unique_ptr<AuxVector> m_auxv;
/// Rendezvous breakpoint.
lldb::break_id_t m_dyld_bid;
/// Contains AT_SYSINFO_EHDR, which means a vDSO has been
/// mapped to the address space
lldb::addr_t m_vdso_base;
/// 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.
virtual void 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;
/// Resolves the entry point for the current inferior process and sets a
/// breakpoint at that address.
void ProbeEntry();
/// 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.
virtual void LoadAllCurrentModules();
void LoadVDSO(lldb_private::ModuleList &modules);
/// 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();
/// Evaluate if Aux vectors contain vDSO information
/// in case they do, read and assign the address to m_vdso_base
void EvalVdsoStatus();
/// Loads Module from inferior process.
void ResolveExecutableModule(lldb::ModuleSP &module_sp);
bool AlwaysRelyOnEHUnwindInfo(lldb_private::SymbolContext &sym_ctx) override;
private:
DISALLOW_COPY_AND_ASSIGN(DynamicLoaderPOSIXDYLD);
};
#endif // liblldb_DynamicLoaderPOSIXDYLD_h_