diff --git a/lldb/include/lldb/Host/common/NativeProcessProtocol.h b/lldb/include/lldb/Host/common/NativeProcessProtocol.h --- a/lldb/include/lldb/Host/common/NativeProcessProtocol.h +++ b/lldb/include/lldb/Host/common/NativeProcessProtocol.h @@ -133,6 +133,10 @@ return GetArchitecture().GetByteOrder(); } + uint32_t GetAddressByteSize() const { + return GetArchitecture().GetAddressByteSize(); + } + virtual llvm::ErrorOr> GetAuxvData() const = 0; diff --git a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.h b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.h deleted file mode 100644 --- a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.h +++ /dev/null @@ -1,108 +0,0 @@ -//===-- AuxVector.h ---------------------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_AuxVector_H_ -#define liblldb_AuxVector_H_ - -#include - -#include "lldb/lldb-forward.h" - -namespace lldb_private { -class DataExtractor; -} - -/// \class AuxVector -/// 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 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(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 diff --git a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/CMakeLists.txt b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/CMakeLists.txt --- a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/CMakeLists.txt +++ b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/CMakeLists.txt @@ -1,5 +1,4 @@ add_lldb_library(lldbPluginDynamicLoaderPosixDYLD PLUGIN - AuxVector.cpp DYLDRendezvous.cpp DynamicLoaderPOSIXDYLD.cpp @@ -10,6 +9,7 @@ lldbSymbol lldbTarget lldbPluginProcessElfCore + lldbPluginProcessUtility LINK_COMPONENTS Support ) diff --git a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h --- a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h +++ b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h @@ -13,6 +13,7 @@ #include #include "DYLDRendezvous.h" +#include "Plugins/Process/Utility/AuxVector.h" #include "lldb/Breakpoint/StoppointCallbackContext.h" #include "lldb/Core/ModuleList.h" #include "lldb/Target/DynamicLoader.h" diff --git a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp --- a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp +++ b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp @@ -9,8 +9,6 @@ // Main header include #include "DynamicLoaderPOSIXDYLD.h" -#include "AuxVector.h" - #include "lldb/Breakpoint/BreakpointLocation.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleSpec.h" @@ -90,8 +88,9 @@ if (log) log->Printf("DynamicLoaderPOSIXDYLD::%s() pid %" PRIu64, __FUNCTION__, m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID); - - m_auxv.reset(new AuxVector(m_process)); + DataExtractor auxv_data(m_process->GetAuxvData(), m_process->GetByteOrder(), + m_process->GetAddressByteSize()); + m_auxv = llvm::make_unique(auxv_data); if (log) log->Printf("DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 " reloaded auxv data", __FUNCTION__, @@ -179,7 +178,9 @@ ModuleSP executable; addr_t load_offset; - m_auxv.reset(new AuxVector(m_process)); + DataExtractor auxv_data(m_process->GetAuxvData(), m_process->GetByteOrder(), + m_process->GetAddressByteSize()); + m_auxv = llvm::make_unique(auxv_data); executable = GetTargetExecutable(); load_offset = ComputeLoadOffset(); @@ -625,13 +626,15 @@ } void DynamicLoaderPOSIXDYLD::EvalSpecialModulesStatus() { - auto I = m_auxv->FindEntry(AuxVector::AUXV_AT_SYSINFO_EHDR); - if (I != m_auxv->end() && I->value != 0) - m_vdso_base = I->value; - - I = m_auxv->FindEntry(AuxVector::AUXV_AT_BASE); - if (I != m_auxv->end() && I->value != 0) - m_interpreter_base = I->value; + llvm::Optional vdso_base = + m_auxv->GetAuxValue(AuxVector::AUXV_AT_SYSINFO_EHDR); + if (vdso_base) + m_vdso_base = *vdso_base; + + llvm::Optional interpreter_base = + m_auxv->GetAuxValue(AuxVector::AUXV_AT_BASE); + if (interpreter_base) + m_interpreter_base = *interpreter_base; } addr_t DynamicLoaderPOSIXDYLD::GetEntryPoint() { @@ -641,12 +644,13 @@ if (m_auxv == nullptr) return LLDB_INVALID_ADDRESS; - AuxVector::iterator I = m_auxv->FindEntry(AuxVector::AUXV_AT_ENTRY); + llvm::Optional entry_point = + m_auxv->GetAuxValue(AuxVector::AUXV_AT_ENTRY); - if (I == m_auxv->end()) + if (!entry_point) return LLDB_INVALID_ADDRESS; - m_entry_point = static_cast(I->value); + m_entry_point = static_cast(*entry_point); const ArchSpec &arch = m_process->GetTarget().GetArchitecture(); diff --git a/lldb/source/Plugins/Process/Linux/NativeProcessLinux.h b/lldb/source/Plugins/Process/Linux/NativeProcessLinux.h --- a/lldb/source/Plugins/Process/Linux/NativeProcessLinux.h +++ b/lldb/source/Plugins/Process/Linux/NativeProcessLinux.h @@ -12,6 +12,7 @@ #include #include +#include "Plugins/Process/Utility/AuxVector.h" #include "lldb/Host/Debug.h" #include "lldb/Host/HostThread.h" #include "lldb/Host/linux/Support.h" @@ -102,6 +103,8 @@ return getProcFile(GetID(), "auxv"); } + llvm::Optional GetAuxValue(enum AuxVector::EntryType type); + lldb::user_id_t StartTrace(const TraceOptions &config, Status &error) override; @@ -132,6 +135,7 @@ private: MainLoop::SignalHandleUP m_sigchld_handle; ArchSpec m_arch; + std::unique_ptr m_aux_vector; LazyBool m_supports_mem_region = eLazyBoolCalculate; std::vector> m_mem_region_cache; diff --git a/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp b/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp --- a/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp +++ b/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp @@ -2082,3 +2082,18 @@ return error; } + +llvm::Optional +NativeProcessLinux::GetAuxValue(enum AuxVector::EntryType type) { + if (m_aux_vector == nullptr) { + auto buffer_or_error = GetAuxvData(); + if (!buffer_or_error) + return llvm::None; + DataExtractor auxv_data(buffer_or_error.get()->getBufferStart(), + buffer_or_error.get()->getBufferSize(), + GetByteOrder(), GetAddressByteSize()); + m_aux_vector = llvm::make_unique(auxv_data); + } + + return m_aux_vector->GetAuxValue(type); +} diff --git a/lldb/source/Plugins/Process/Utility/AuxVector.h b/lldb/source/Plugins/Process/Utility/AuxVector.h new file mode 100644 --- /dev/null +++ b/lldb/source/Plugins/Process/Utility/AuxVector.h @@ -0,0 +1,73 @@ +//===-- AuxVector.h ---------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_AuxVector_H_ +#define liblldb_AuxVector_H_ + +#include "lldb/Utility/DataExtractor.h" +#include "lldb/Utility/Log.h" +#include + +class AuxVector { + +public: + AuxVector(lldb_private::DataExtractor &data); + + /// 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, + }; + + llvm::Optional GetAuxValue(enum EntryType entry_type) const; + void DumpToLog(lldb_private::Log *log) const; + const char *GetEntryName(EntryType type) const; + +private: + void ParseAuxv(lldb_private::DataExtractor &data); + + std::unordered_map m_auxv_entries; +}; + +#endif diff --git a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.cpp b/lldb/source/Plugins/Process/Utility/AuxVector.cpp rename from lldb/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.cpp rename to lldb/source/Plugins/Process/Utility/AuxVector.cpp --- a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.cpp +++ b/lldb/source/Plugins/Process/Utility/AuxVector.cpp @@ -7,98 +7,59 @@ //===----------------------------------------------------------------------===// #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; +AuxVector::AuxVector(lldb_private::DataExtractor &data) { ParseAuxv(data); } -static bool GetMaxU64(DataExtractor &data, lldb::offset_t *offset_ptr, - uint64_t *value, unsigned int byte_size) { +static bool ReadUInt(lldb_private::DataExtractor &data, + lldb::offset_t *offset_ptr, uint64_t *value) { lldb::offset_t saved_offset = *offset_ptr; - *value = data.GetMaxU64(offset_ptr, byte_size); + // We're not reading an address but an int that could be 32 or 64 bit + // depending on the address size, which is what GetAddress does. + *value = data.GetAddress(offset_ptr); 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(); +void AuxVector::ParseAuxv(lldb_private::DataExtractor &data) { lldb::offset_t offset = 0; - - for (;;) { - Entry entry; - - if (!ParseAuxvEntry(data, entry, &offset, byte_size)) + while (true) { + uint64_t type = 0; + uint64_t value = 0; + if (!ReadUInt(data, &offset, &type) || !ReadUInt(data, &offset, &value)) break; - - if (entry.type == AUXV_AT_NULL) + if (type == AUXV_AT_NULL) break; - - if (entry.type == AUXV_AT_IGNORE) + if (type == AUXV_AT_IGNORE) continue; - m_auxv.push_back(entry); + m_auxv_entries[type] = value; } } -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(type)) - return I; - } - - return end(); +llvm::Optional +AuxVector::GetAuxValue(enum EntryType entry_type) const { + auto it = m_auxv_entries.find(static_cast(entry_type)); + if (it != m_auxv_entries.end()) + return it->second; + return llvm::None; } -void AuxVector::DumpToLog(Log *log) const { +void AuxVector::DumpToLog(lldb_private::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); + for (auto entry : m_auxv_entries) { + log->Printf(" %s [%" PRIu64 "]: %" PRIx64, + GetEntryName(static_cast(entry.first)), entry.first, + entry.second); } } -const char *AuxVector::GetEntryName(EntryType type) { +const char *AuxVector::GetEntryName(EntryType type) const { const char *name = "AT_???"; -#define ENTRY_NAME(_type) \ - _type: \ +#define ENTRY_NAME(_type) \ + _type: \ name = &#_type[5] switch (type) { case ENTRY_NAME(AUXV_AT_NULL); break; diff --git a/lldb/source/Plugins/Process/Utility/CMakeLists.txt b/lldb/source/Plugins/Process/Utility/CMakeLists.txt --- a/lldb/source/Plugins/Process/Utility/CMakeLists.txt +++ b/lldb/source/Plugins/Process/Utility/CMakeLists.txt @@ -1,4 +1,5 @@ add_lldb_library(lldbPluginProcessUtility PLUGIN + AuxVector.cpp DynamicRegisterInfo.cpp FreeBSDSignals.cpp GDBRemoteSignals.cpp