diff options
author | mortimer <mortimer@cvs.openbsd.org> | 2019-11-09 16:45:49 +0000 |
---|---|---|
committer | mortimer <mortimer@cvs.openbsd.org> | 2019-11-09 16:45:49 +0000 |
commit | 6e03bb45be5d11fe00839093ae0c76a05df73f97 (patch) | |
tree | 38e689c5b36d446a72b9feb819ceb31b076b56e8 /gnu | |
parent | 9a7461dfc4b75ee86810e2cebc8d87ea1c039d9f (diff) |
Add lldb support for debugging running binaries on amd64.
Follows a similar model as NetBSD. Much help from patrick, kettenis and guenther.
lldb and lldb-server remain not installed by default.
ok patrick@
Diffstat (limited to 'gnu')
32 files changed, 3239 insertions, 905 deletions
diff --git a/gnu/llvm/tools/lldb/include/lldb/Utility/ArchSpec.h b/gnu/llvm/tools/lldb/include/lldb/Utility/ArchSpec.h index 50f69606e3d..d2d3812b93e 100644 --- a/gnu/llvm/tools/lldb/include/lldb/Utility/ArchSpec.h +++ b/gnu/llvm/tools/lldb/include/lldb/Utility/ArchSpec.h @@ -10,26 +10,27 @@ #ifndef LLDB_UTILITY_ARCHSPEC_H #define LLDB_UTILITY_ARCHSPEC_H +#include "lldb/Utility/CompletionRequest.h" #include "lldb/Utility/ConstString.h" #include "lldb/lldb-enumerations.h" #include "lldb/lldb-forward.h" #include "lldb/lldb-private-enumerations.h" -#include "llvm/ADT/StringRef.h" // for StringRef +#include "llvm/ADT/StringRef.h" #include "llvm/ADT/Triple.h" -#include <cstddef> // for size_t -#include <cstdint> // for uint32_t -#include <string> // for string +#include <cstddef> +#include <cstdint> +#include <string> namespace lldb_private { //---------------------------------------------------------------------- -/// @class ArchSpec ArchSpec.h "lldb/Utility/ArchSpec.h" -/// @brief An architecture specification class. +/// @class ArchSpec ArchSpec.h "lldb/Utility/ArchSpec.h" An architecture +/// specification class. /// /// A class designed to be created from a cpu type and subtype, a -/// string representation, or an llvm::Triple. Keeping all of the -/// conversions of strings to architecture enumeration values confined -/// to this class allows new architecture support to be added easily. +/// string representation, or an llvm::Triple. Keeping all of the conversions +/// of strings to architecture enumeration values confined to this class +/// allows new architecture support to be added easily. //---------------------------------------------------------------------- class ArchSpec { public: @@ -178,6 +179,7 @@ public: eCore_x86_64_x86_64, eCore_x86_64_x86_64h, // Haswell enabled x86_64 + eCore_x86_64_amd64, eCore_hexagon_generic, eCore_hexagon_hexagonv4, eCore_hexagon_hexagonv5, @@ -245,16 +247,15 @@ public: //------------------------------------------------------------------ /// Default constructor. /// - /// Default constructor that initializes the object with invalid - /// cpu type and subtype values. + /// Default constructor that initializes the object with invalid cpu type + /// and subtype values. //------------------------------------------------------------------ ArchSpec(); //------------------------------------------------------------------ /// Constructor over triple. /// - /// Constructs an ArchSpec with properties consistent with the given - /// Triple. + /// Constructs an ArchSpec with properties consistent with the given Triple. //------------------------------------------------------------------ explicit ArchSpec(const llvm::Triple &triple); explicit ArchSpec(const char *triple_cstr); @@ -262,8 +263,8 @@ public: //------------------------------------------------------------------ /// Constructor over architecture name. /// - /// Constructs an ArchSpec with properties consistent with the given - /// object type and architecture name. + /// Constructs an ArchSpec with properties consistent with the given object + /// type and architecture name. //------------------------------------------------------------------ explicit ArchSpec(ArchitectureType arch_type, uint32_t cpu_type, uint32_t cpu_subtype); @@ -284,16 +285,18 @@ public: //--------------------------------------------------------------------------- /// Returns true if the OS, vendor and environment fields of the triple are - /// unset. The triple is expected to be normalized (llvm::Triple::normalize). + /// unset. The triple is expected to be normalized + /// (llvm::Triple::normalize). //--------------------------------------------------------------------------- static bool ContainsOnlyArch(const llvm::Triple &normalized_triple); - static size_t AutoComplete(llvm::StringRef name, StringList &matches); + static void ListSupportedArchNames(StringList &list); + static size_t AutoComplete(CompletionRequest &request); //------------------------------------------------------------------ /// Returns a static string representing the current architecture. /// - /// @return A static string correcponding to the current + /// @return A static string corresponding to the current /// architecture. //------------------------------------------------------------------ const char *GetArchitectureName() const; @@ -306,8 +309,8 @@ public: bool IsMIPS() const; //------------------------------------------------------------------ - /// Returns a string representing current architecture as a target CPU - /// for tools like compiler, disassembler etc. + /// Returns a string representing current architecture as a target CPU for + /// tools like compiler, disassembler etc. /// /// @return A string representing target CPU for the current /// architecture. @@ -329,8 +332,7 @@ public: void Clear(); //------------------------------------------------------------------ - /// Returns the size in bytes of an address of the current - /// architecture. + /// Returns the size in bytes of an address of the current architecture. /// /// @return The byte size of an address of the current architecture. //------------------------------------------------------------------ @@ -356,9 +358,8 @@ public: //------------------------------------------------------------------ /// Set the distribution id of the architecture. /// - /// This will be something like "ubuntu", "fedora", etc. on Linux. - /// This should be the same value returned by - /// HostInfo::GetDistributionId (). + /// This will be something like "ubuntu", "fedora", etc. on Linux. This + /// should be the same value returned by HostInfo::GetDistributionId (). ///------------------------------------------------------------------ void SetDistributionId(const char *distribution_id); @@ -371,6 +372,7 @@ public: bool IsValid() const { return m_core >= eCore_arm_generic && m_core < kNumCores; } + explicit operator bool() const { return IsValid(); } bool TripleVendorWasSpecified() const { return !m_triple.getVendorName().empty(); @@ -395,13 +397,12 @@ public: //------------------------------------------------------------------ /// Merges fields from another ArchSpec into this ArchSpec. /// - /// This will use the supplied ArchSpec to fill in any fields of - /// the triple in this ArchSpec which were unspecified. This can - /// be used to refine a generic ArchSpec with a more specific one. - /// For example, if this ArchSpec's triple is something like - /// i386-unknown-unknown-unknown, and we have a triple which is - /// x64-pc-windows-msvc, then merging that triple into this one - /// will result in the triple i386-pc-windows-msvc. + /// This will use the supplied ArchSpec to fill in any fields of the triple + /// in this ArchSpec which were unspecified. This can be used to refine a + /// generic ArchSpec with a more specific one. For example, if this + /// ArchSpec's triple is something like i386-unknown-unknown-unknown, and we + /// have a triple which is x64-pc-windows-msvc, then merging that triple + /// into this one will result in the triple i386-pc-windows-msvc. /// //------------------------------------------------------------------ void MergeFrom(const ArchSpec &other); @@ -421,16 +422,16 @@ public: /// /// @return True if the object, and CPU were successfully set. /// - /// As a side effect, the vendor value is usually set to unknown. - /// The exections are + /// As a side effect, the vendor value is usually set to unknown. The + /// exceptions are /// aarch64-apple-ios /// arm-apple-ios /// thumb-apple-ios /// x86-apple- /// x86_64-apple- /// - /// As a side effect, the os value is usually set to unknown - /// The exceptions are + /// As a side effect, the os value is usually set to unknown The exceptions + /// are /// *-*-aix /// aarch64-apple-ios /// arm-apple-ios @@ -456,10 +457,10 @@ public: //------------------------------------------------------------------ /// Sets this ArchSpec's byte order. /// - /// In the common case there is no need to call this method as the - /// byte order can almost always be determined by the architecture. - /// However, many CPU's are bi-endian (ARM, Alpha, PowerPC, etc) - /// and the default/assumed byte order may be incorrect. + /// In the common case there is no need to call this method as the byte + /// order can almost always be determined by the architecture. However, many + /// CPU's are bi-endian (ARM, Alpha, PowerPC, etc) and the default/assumed + /// byte order may be incorrect. //------------------------------------------------------------------ void SetByteOrder(lldb::ByteOrder byte_order) { m_byte_order = byte_order; } @@ -476,28 +477,28 @@ public: //------------------------------------------------------------------ /// Architecture data byte width accessor /// - /// @return the size in 8-bit (host) bytes of a minimum addressable - /// unit from the Architecture's data bus + /// @return the size in 8-bit (host) bytes of a minimum addressable unit + /// from the Architecture's data bus //------------------------------------------------------------------ uint32_t GetDataByteSize() const; //------------------------------------------------------------------ /// Architecture code byte width accessor /// - /// @return the size in 8-bit (host) bytes of a minimum addressable - /// unit from the Architecture's code bus + /// @return the size in 8-bit (host) bytes of a minimum addressable unit + /// from the Architecture's code bus //------------------------------------------------------------------ uint32_t GetCodeByteSize() const; //------------------------------------------------------------------ - /// Architecture tripple accessor. + /// Architecture triple accessor. /// /// @return A triple describing this ArchSpec. //------------------------------------------------------------------ llvm::Triple &GetTriple() { return m_triple; } //------------------------------------------------------------------ - /// Architecture tripple accessor. + /// Architecture triple accessor. /// /// @return A triple describing this ArchSpec. //------------------------------------------------------------------ @@ -506,14 +507,14 @@ public: void DumpTriple(Stream &s) const; //------------------------------------------------------------------ - /// Architecture tripple setter. + /// Architecture triple setter. /// - /// Configures this ArchSpec according to the given triple. If the - /// triple has unknown components in all of the vendor, OS, and - /// the optional environment field (i.e. "i386-unknown-unknown") - /// then default values are taken from the host. Architecture and - /// environment components are used to further resolve the CPU type - /// and subtype, endian characteristics, etc. + /// Configures this ArchSpec according to the given triple. If the triple + /// has unknown components in all of the vendor, OS, and the optional + /// environment field (i.e. "i386-unknown-unknown") then default values are + /// taken from the host. Architecture and environment components are used + /// to further resolve the CPU type and subtype, endian characteristics, + /// etc. /// /// @return A triple describing this ArchSpec. //------------------------------------------------------------------ @@ -530,8 +531,8 @@ public: lldb::ByteOrder GetDefaultEndian() const; //------------------------------------------------------------------ - /// Returns true if 'char' is a signed type by defualt in the - /// architecture false otherwise + /// Returns true if 'char' is a signed type by default in the architecture + /// false otherwise /// /// @return True if 'char' is a signed type by default on the /// architecture and false otherwise. @@ -539,18 +540,18 @@ public: bool CharIsSignedByDefault() const; //------------------------------------------------------------------ - /// Compare an ArchSpec to another ArchSpec, requiring an exact cpu - /// type match between them. - /// e.g. armv7s is not an exact match with armv7 - this would return false + /// Compare an ArchSpec to another ArchSpec, requiring an exact cpu type + /// match between them. e.g. armv7s is not an exact match with armv7 - this + /// would return false /// /// @return true if the two ArchSpecs match. //------------------------------------------------------------------ bool IsExactMatch(const ArchSpec &rhs) const; //------------------------------------------------------------------ - /// Compare an ArchSpec to another ArchSpec, requiring a compatible - /// cpu type match between them. - /// e.g. armv7s is compatible with armv7 - this method would return true + /// Compare an ArchSpec to another ArchSpec, requiring a compatible cpu type + /// match between them. e.g. armv7s is compatible with armv7 - this method + /// would return true /// /// @return true if the two ArchSpecs are compatible //------------------------------------------------------------------ @@ -566,12 +567,12 @@ public: //------------------------------------------------------------------ /// Detect whether this architecture uses thumb code exclusively /// - /// Some embedded ARM chips (e.g. the ARM Cortex M0-7 line) can - /// only execute the Thumb instructions, never Arm. We should normally - /// pick up arm/thumbness from their the processor status bits (cpsr/xpsr) - /// or hints on each function - but when doing bare-boards low level - /// debugging (especially common with these embedded processors), we may - /// not have those things easily accessible. + /// Some embedded ARM chips (e.g. the ARM Cortex M0-7 line) can only execute + /// the Thumb instructions, never Arm. We should normally pick up + /// arm/thumbness from their the processor status bits (cpsr/xpsr) or hints + /// on each function - but when doing bare-boards low level debugging + /// (especially common with these embedded processors), we may not have + /// those things easily accessible. /// /// @return true if this is an arm ArchSpec which can only execute Thumb /// instructions @@ -592,31 +593,30 @@ protected: Core m_core = kCore_invalid; lldb::ByteOrder m_byte_order = lldb::eByteOrderInvalid; - // Additional arch flags which we cannot get from triple and core - // For MIPS these are application specific extensions like - // micromips, mips16 etc. + // Additional arch flags which we cannot get from triple and core For MIPS + // these are application specific extensions like micromips, mips16 etc. uint32_t m_flags = 0; ConstString m_distribution_id; - // Called when m_def or m_entry are changed. Fills in all remaining - // members with default values. + // Called when m_def or m_entry are changed. Fills in all remaining members + // with default values. void CoreUpdated(bool update_triple); }; //------------------------------------------------------------------ -/// @fn bool operator< (const ArchSpec& lhs, const ArchSpec& rhs) -/// @brief Less than operator. +/// @fn bool operator< (const ArchSpec& lhs, const ArchSpec& rhs) Less than +/// operator. /// -/// Tests two ArchSpec objects to see if \a lhs is less than \a -/// rhs. +/// Tests two ArchSpec objects to see if \a lhs is less than \a rhs. /// -/// @param[in] lhs The Left Hand Side ArchSpec object to compare. -/// @param[in] rhs The Left Hand Side ArchSpec object to compare. +/// @param[in] lhs The Left Hand Side ArchSpec object to compare. @param[in] +/// rhs The Left Hand Side ArchSpec object to compare. /// /// @return true if \a lhs is less than \a rhs //------------------------------------------------------------------ bool operator<(const ArchSpec &lhs, const ArchSpec &rhs); +bool operator==(const ArchSpec &lhs, const ArchSpec &rhs); bool ParseMachCPUDashSubtypeTriple(llvm::StringRef triple_str, ArchSpec &arch); diff --git a/gnu/llvm/tools/lldb/packages/Python/lldbsuite/test/api/multithreaded/common.h b/gnu/llvm/tools/lldb/packages/Python/lldbsuite/test/api/multithreaded/common.h index dad8bba07a3..bd40bdd421a 100644 --- a/gnu/llvm/tools/lldb/packages/Python/lldbsuite/test/api/multithreaded/common.h +++ b/gnu/llvm/tools/lldb/packages/Python/lldbsuite/test/api/multithreaded/common.h @@ -58,7 +58,7 @@ public: /// Allocates a char buffer with the current working directory inline char* get_working_dir() { -#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) +#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) return getwd(0); #else return get_current_dir_name(); diff --git a/gnu/llvm/tools/lldb/packages/Python/lldbsuite/test/tools/lldb-server/thread-name/main.cpp b/gnu/llvm/tools/lldb/packages/Python/lldbsuite/test/tools/lldb-server/thread-name/main.cpp index 0403031143b..c01b7f7007b 100644 --- a/gnu/llvm/tools/lldb/packages/Python/lldbsuite/test/tools/lldb-server/thread-name/main.cpp +++ b/gnu/llvm/tools/lldb/packages/Python/lldbsuite/test/tools/lldb-server/thread-name/main.cpp @@ -6,6 +6,8 @@ void set_thread_name(const char *name) { ::pthread_setname_np(name); #elif defined(__FreeBSD__) ::pthread_set_name_np(::pthread_self(), name); +#elif defined(__OpenBSD__) + ::pthread_set_name_np(::pthread_self(), name); #elif defined(__linux__) ::pthread_setname_np(::pthread_self(), name); #elif defined(__NetBSD__) diff --git a/gnu/llvm/tools/lldb/source/Core/FormatEntity.cpp b/gnu/llvm/tools/lldb/source/Core/FormatEntity.cpp index 6002efe9244..c8c2f4c849e 100644 --- a/gnu/llvm/tools/lldb/source/Core/FormatEntity.cpp +++ b/gnu/llvm/tools/lldb/source/Core/FormatEntity.cpp @@ -10,29 +10,28 @@ #include "lldb/Core/FormatEntity.h" #include "lldb/Core/Address.h" -#include "lldb/Core/AddressRange.h" // for AddressRange -#include "lldb/Core/ArchSpec.h" // for ArchSpec +#include "lldb/Core/AddressRange.h" #include "lldb/Core/Debugger.h" +#include "lldb/Core/DumpRegisterValue.h" #include "lldb/Core/Module.h" -#include "lldb/Core/RegisterValue.h" // for RegisterValue #include "lldb/Core/ValueObject.h" #include "lldb/Core/ValueObjectVariable.h" #include "lldb/DataFormatters/DataVisualization.h" -#include "lldb/DataFormatters/FormatClasses.h" // for TypeNameSpecifier... +#include "lldb/DataFormatters/FormatClasses.h" #include "lldb/DataFormatters/FormatManager.h" -#include "lldb/DataFormatters/TypeSummary.h" // for TypeSummaryImpl::... +#include "lldb/DataFormatters/TypeSummary.h" #include "lldb/Expression/ExpressionVariable.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Symbol/Block.h" #include "lldb/Symbol/CompileUnit.h" -#include "lldb/Symbol/CompilerType.h" // for CompilerType +#include "lldb/Symbol/CompilerType.h" #include "lldb/Symbol/Function.h" #include "lldb/Symbol/LineEntry.h" #include "lldb/Symbol/Symbol.h" -#include "lldb/Symbol/SymbolContext.h" // for SymbolContext +#include "lldb/Symbol/SymbolContext.h" #include "lldb/Symbol/VariableList.h" #include "lldb/Target/ExecutionContext.h" -#include "lldb/Target/ExecutionContextScope.h" // for ExecutionContextS... +#include "lldb/Target/ExecutionContextScope.h" #include "lldb/Target/Language.h" #include "lldb/Target/Process.h" #include "lldb/Target/RegisterContext.h" @@ -42,30 +41,32 @@ #include "lldb/Target/Target.h" #include "lldb/Target/Thread.h" #include "lldb/Utility/AnsiTerminal.h" -#include "lldb/Utility/ConstString.h" // for ConstString, oper... +#include "lldb/Utility/ArchSpec.h" +#include "lldb/Utility/ConstString.h" #include "lldb/Utility/FileSpec.h" -#include "lldb/Utility/Log.h" // for Log -#include "lldb/Utility/Logging.h" // for GetLogIfAllCatego... -#include "lldb/Utility/SharingPtr.h" // for SharingPtr +#include "lldb/Utility/Log.h" +#include "lldb/Utility/Logging.h" +#include "lldb/Utility/RegisterValue.h" +#include "lldb/Utility/SharingPtr.h" #include "lldb/Utility/Stream.h" #include "lldb/Utility/StreamString.h" -#include "lldb/Utility/StringList.h" // for StringList -#include "lldb/Utility/StructuredData.h" // for StructuredData::O... -#include "lldb/lldb-defines.h" // for LLDB_INVALID_ADDRESS -#include "lldb/lldb-forward.h" // for ValueObjectSP +#include "lldb/Utility/StringList.h" +#include "lldb/Utility/StructuredData.h" +#include "lldb/lldb-defines.h" +#include "lldb/lldb-forward.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringRef.h" -#include "llvm/ADT/Triple.h" // for Triple, Triple::O... -#include "llvm/Support/Compiler.h" // for LLVM_FALLTHROUGH - -#include <ctype.h> // for isxdigit -#include <inttypes.h> // for PRIu64, PRIx64 -#include <memory> // for shared_ptr, opera... -#include <stdio.h> // for sprintf -#include <stdlib.h> // for strtoul -#include <string.h> // for size_t, strchr -#include <type_traits> // for move -#include <utility> // for pair +#include "llvm/ADT/Triple.h" +#include "llvm/Support/Compiler.h" + +#include <ctype.h> +#include <inttypes.h> +#include <memory> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <type_traits> +#include <utility> namespace lldb_private { class ScriptInterpreter; @@ -127,6 +128,7 @@ static FormatEntity::Entry::Definition g_frame_child_entries[] = { ENTRY("flags", FrameRegisterFlags, UInt64), ENTRY("no-debug", FrameNoDebug, None), ENTRY_CHILDREN("reg", FrameRegisterByName, UInt64, g_string_entry), + ENTRY("is-artificial", FrameIsArtificial, UInt32), }; static FormatEntity::Entry::Definition g_function_child_entries[] = { @@ -145,6 +147,7 @@ static FormatEntity::Entry::Definition g_function_child_entries[] = { static FormatEntity::Entry::Definition g_line_child_entries[] = { ENTRY_CHILDREN("file", LineEntryFile, None, g_file_child_entries), ENTRY("number", LineEntryLineNumber, UInt32), + ENTRY("column", LineEntryColumn, UInt32), ENTRY("start-addr", LineEntryStartAddress, UInt64), ENTRY("end-addr", LineEntryEndAddress, UInt64), }; @@ -355,6 +358,7 @@ const char *FormatEntity::Entry::TypeToCString(Type t) { ENUM_TO_CSTR(FrameRegisterFP); ENUM_TO_CSTR(FrameRegisterFlags); ENUM_TO_CSTR(FrameRegisterByName); + ENUM_TO_CSTR(FrameIsArtificial); ENUM_TO_CSTR(ScriptFrame); ENUM_TO_CSTR(FunctionID); ENUM_TO_CSTR(FunctionDidChange); @@ -371,6 +375,7 @@ const char *FormatEntity::Entry::TypeToCString(Type t) { ENUM_TO_CSTR(FunctionIsOptimized); ENUM_TO_CSTR(LineEntryFile); ENUM_TO_CSTR(LineEntryLineNumber); + ENUM_TO_CSTR(LineEntryColumn); ENUM_TO_CSTR(LineEntryStartAddress); ENUM_TO_CSTR(LineEntryEndAddress); ENUM_TO_CSTR(CurrentPCArrow); @@ -467,10 +472,9 @@ static bool DumpAddressOffsetFromFunction(Stream &s, const SymbolContext *sc, if (sc->function) { func_addr = sc->function->GetAddressRange().GetBaseAddress(); if (sc->block && !concrete_only) { - // Check to make sure we aren't in an inline - // function. If we are, use the inline block - // range that contains "format_addr" since - // blocks can be discontiguous. + // Check to make sure we aren't in an inline function. If we are, use + // the inline block range that contains "format_addr" since blocks + // can be discontiguous. Block *inline_block = sc->block->GetContainingInlinedBlock(); AddressRange inline_range; if (inline_block && @@ -622,7 +626,7 @@ static bool DumpRegister(Stream &s, StackFrame *frame, RegisterKind reg_kind, if (reg_info) { RegisterValue reg_value; if (reg_ctx->ReadRegister(reg_info, reg_value)) { - reg_value.Dump(&s, reg_info, false, false, format); + DumpRegisterValue(reg_value, &s, reg_info, false, false, format); return true; } } @@ -822,8 +826,7 @@ static bool DumpValue(Stream &s, const SymbolContext *sc, if (do_deref_pointer && !is_array_range) { // I have not deref-ed yet, let's do it // this happens when we are not going through - // GetValueForVariableExpressionPath - // to get to the target ValueObject + // GetValueForVariableExpressionPath to get to the target ValueObject Status error; target = target->Dereference(error).get(); if (error.Fail()) { @@ -842,9 +845,9 @@ static bool DumpValue(Stream &s, const SymbolContext *sc, return false; } - // we do not want to use the summary for a bitfield of type T:n - // if we were originally dealing with just a T - that would get - // us into an endless recursion + // we do not want to use the summary for a bitfield of type T:n if we were + // originally dealing with just a T - that would get us into an endless + // recursion if (target->IsBitfield() && was_var_indexed) { // TODO: check for a (T:n)-specific summary - we should still obey that StreamString bitfield_name; @@ -905,8 +908,7 @@ static bool DumpValue(Stream &s, const SymbolContext *sc, } // if directly trying to print ${var}, and this is an aggregate, display a - // nice - // type @ location message + // nice type @ location message if (is_aggregate && was_plain_var) { s << target->GetTypeName() << " @ " << target->GetLocationAsCString(); return true; @@ -1021,7 +1023,7 @@ static bool DumpRegister(Stream &s, StackFrame *frame, const char *reg_name, if (reg_info) { RegisterValue reg_value; if (reg_ctx->ReadRegister(reg_info, reg_value)) { - reg_value.Dump(&s, reg_info, false, false, format); + DumpRegisterValue(reg_value, &s, reg_info, false, false, format); return true; } } @@ -1142,8 +1144,8 @@ bool FormatEntity::Format(const Entry &entry, Stream &s, if (!success) break; } - // Only if all items in a scope succeed, then do we - // print the output into the main stream + // Only if all items in a scope succeed, then do we print the output into + // the main stream if (success) s.Write(scope_stream.GetString().data(), scope_stream.GetString().size()); } @@ -1206,9 +1208,8 @@ bool FormatEntity::Format(const Entry &entry, Stream &s, // Watch for the special "tid" format... if (entry.printf_format == "tid") { // TODO(zturner): Rather than hardcoding this to be platform - // specific, it should be controlled by a - // setting and the default value of the setting can be different - // depending on the platform. + // specific, it should be controlled by a setting and the default + // value of the setting can be different depending on the platform. Target &target = thread->GetProcess()->GetTarget(); ArchSpec arch(target.GetArchitecture()); llvm::Triple::OSType ostype = arch.IsValid() @@ -1216,7 +1217,8 @@ bool FormatEntity::Format(const Entry &entry, Stream &s, : llvm::Triple::UnknownOS; if ((ostype == llvm::Triple::FreeBSD) || (ostype == llvm::Triple::Linux) || - (ostype == llvm::Triple::NetBSD)) { + (ostype == llvm::Triple::NetBSD) || + (ostype == llvm::Triple::OpenBSD)) { format = "%" PRIu64; } } else { @@ -1490,6 +1492,13 @@ bool FormatEntity::Format(const Entry &entry, Stream &s, } return false; + case Entry::Type::FrameIsArtificial: { + if (exe_ctx) + if (StackFrame *frame = exe_ctx->GetFramePtr()) + return frame->IsArtificial(); + return false; + } + case Entry::Type::ScriptFrame: if (exe_ctx) { StackFrame *frame = exe_ctx->GetFramePtr(); @@ -1817,6 +1826,16 @@ bool FormatEntity::Format(const Entry &entry, Stream &s, } return false; + case Entry::Type::LineEntryColumn: + if (sc && sc->line_entry.IsValid() && sc->line_entry.column) { + const char *format = "%" PRIu32; + if (!entry.printf_format.empty()) + format = entry.printf_format.c_str(); + s.Printf(format, sc->line_entry.column); + return true; + } + return false; + case Entry::Type::LineEntryStartAddress: case Entry::Type::LineEntryEndAddress: if (sc && sc->line_entry.range.GetBaseAddress().IsValid()) { @@ -1914,9 +1933,9 @@ static Status ParseEntry(const llvm::StringRef &format_str, error.SetErrorStringWithFormat("%s", error_strm.GetData()); } else if (sep_char == ':') { // Any value whose separator is a with a ':' means this value has a - // string argument - // that needs to be stored in the entry (like "${script.var:}"). - // In this case the string value is the empty string which is ok. + // string argument that needs to be stored in the entry (like + // "${script.var:}"). In this case the string value is the empty + // string which is ok. } else { error.SetErrorStringWithFormat("%s", "invalid entry definitions"); } @@ -1926,8 +1945,7 @@ static Status ParseEntry(const llvm::StringRef &format_str, error = ParseEntry(value, entry_def, entry); } else if (sep_char == ':') { // Any value whose separator is a with a ':' means this value has a - // string argument - // that needs to be stored in the entry (like + // string argument that needs to be stored in the entry (like // "${script.var:modulename.function}") entry.string = value.str(); } else { @@ -2065,17 +2083,17 @@ Status FormatEntity::ParseInternal(llvm::StringRef &format, Entry &parent_entry, case '0': // 1 to 3 octal chars { - // Make a string that can hold onto the initial zero char, - // up to 3 octal digits, and a terminating NULL. + // Make a string that can hold onto the initial zero char, up to 3 + // octal digits, and a terminating NULL. char oct_str[5] = {0, 0, 0, 0, 0}; int i; for (i = 0; (format[i] >= '0' && format[i] <= '7') && i < 4; ++i) oct_str[i] = format[i]; - // We don't want to consume the last octal character since - // the main for loop will do this for us, so we advance p by - // one less than i (even if i is zero) + // We don't want to consume the last octal character since the main + // for loop will do this for us, so we advance p by one less than i + // (even if i is zero) format = format.drop_front(i); unsigned long octal_value = ::strtoul(oct_str, nullptr, 8); if (octal_value <= UINT8_MAX) { @@ -2115,8 +2133,8 @@ Status FormatEntity::ParseInternal(llvm::StringRef &format, Entry &parent_entry, break; default: - // Just desensitize any other character by just printing what - // came after the '\' + // Just desensitize any other character by just printing what came + // after the '\' parent_entry.AppendChar(desens_char); break; } @@ -2142,10 +2160,9 @@ Status FormatEntity::ParseInternal(llvm::StringRef &format, Entry &parent_entry, if (!variable_format.empty()) { entry.printf_format = variable_format.str(); - // If the format contains a '%' we are going to assume this is - // a printf style format. So if you want to format your thread ID - // using "0x%llx" you can use: - // ${thread.id%0x%llx} + // If the format contains a '%' we are going to assume this is a + // printf style format. So if you want to format your thread ID + // using "0x%llx" you can use: ${thread.id%0x%llx} // // If there is no '%' in the format, then it is assumed to be a // LLDB format name, or one of the extended formats specified in @@ -2264,9 +2281,9 @@ Status FormatEntity::ParseInternal(llvm::StringRef &format, Entry &parent_entry, return error; } } - // Check if this entry just wants to insert a constant string - // value into the parent_entry, if so, insert the string with - // AppendText, else append the entry to the parent_entry. + // Check if this entry just wants to insert a constant string value + // into the parent_entry, if so, insert the string with AppendText, + // else append the entry to the parent_entry. if (entry.type == Entry::Type::InsertString) parent_entry.AppendText(entry.string.c_str()); else @@ -2350,12 +2367,11 @@ static void AddMatches(const FormatEntity::Entry::Definition *def, } } -size_t FormatEntity::AutoComplete(llvm::StringRef str, int match_start_point, - int max_return_elements, bool &word_complete, - StringList &matches) { - word_complete = false; - str = str.drop_front(match_start_point); - matches.Clear(); +size_t FormatEntity::AutoComplete(CompletionRequest &request) { + llvm::StringRef str = request.GetCursorArgumentPrefix().str(); + + request.SetWordComplete(false); + str = str.drop_front(request.GetMatchStartPoint()); const size_t dollar_pos = str.rfind('$'); if (dollar_pos == llvm::StringRef::npos) @@ -2365,7 +2381,7 @@ size_t FormatEntity::AutoComplete(llvm::StringRef str, int match_start_point, if (dollar_pos == str.size() - 1) { std::string match = str.str(); match.append("{"); - matches.AppendString(match); + request.AddCompletion(match); return 1; } @@ -2383,8 +2399,10 @@ size_t FormatEntity::AutoComplete(llvm::StringRef str, int match_start_point, llvm::StringRef partial_variable(str.substr(dollar_pos + 2)); if (partial_variable.empty()) { // Suggest all top level entites as we are just past "${" - AddMatches(&g_root, str, llvm::StringRef(), matches); - return matches.GetSize(); + StringList new_matches; + AddMatches(&g_root, str, llvm::StringRef(), new_matches); + request.AddCompletions(new_matches); + return request.GetNumberOfMatches(); } // We have a partially specified variable, find it @@ -2400,19 +2418,23 @@ size_t FormatEntity::AutoComplete(llvm::StringRef str, int match_start_point, // Exact match if (n > 0) { // "${thread.info" <TAB> - matches.AppendString(MakeMatch(str, ".")); + request.AddCompletion(MakeMatch(str, ".")); } else { // "${thread.id" <TAB> - matches.AppendString(MakeMatch(str, "}")); - word_complete = true; + request.AddCompletion(MakeMatch(str, "}")); + request.SetWordComplete(true); } } else if (remainder.equals(".")) { // "${thread." <TAB> - AddMatches(entry_def, str, llvm::StringRef(), matches); + StringList new_matches; + AddMatches(entry_def, str, llvm::StringRef(), new_matches); + request.AddCompletions(new_matches); } else { // We have a partial match // "${thre" <TAB> - AddMatches(entry_def, str, remainder, matches); + StringList new_matches; + AddMatches(entry_def, str, remainder, new_matches); + request.AddCompletions(new_matches); } - return matches.GetSize(); + return request.GetNumberOfMatches(); } diff --git a/gnu/llvm/tools/lldb/source/Host/common/SocketAddress.cpp b/gnu/llvm/tools/lldb/source/Host/common/SocketAddress.cpp index def3e0359f0..9612af9ad70 100644 --- a/gnu/llvm/tools/lldb/source/Host/common/SocketAddress.cpp +++ b/gnu/llvm/tools/lldb/source/Host/common/SocketAddress.cpp @@ -21,7 +21,6 @@ #include <stddef.h> #include <stdio.h> -// C Includes #if !defined(_WIN32) #include <arpa/inet.h> #endif @@ -29,9 +28,6 @@ #include <assert.h> #include <string.h> -// C++ Includes -// Other libraries and framework includes -// Project includes #include "lldb/Host/PosixApi.h" // WindowsXP needs an inet_ntop implementation @@ -128,7 +124,7 @@ static socklen_t GetFamilyLength(sa_family_t family) { } socklen_t SocketAddress::GetLength() const { -#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) +#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) return m_socket_addr.sa.sa_len; #else return GetFamilyLength(GetFamily()); @@ -143,7 +139,7 @@ sa_family_t SocketAddress::GetFamily() const { void SocketAddress::SetFamily(sa_family_t family) { m_socket_addr.sa.sa_family = family; -#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) +#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) m_socket_addr.sa.sa_len = GetFamilyLength(family); #endif } diff --git a/gnu/llvm/tools/lldb/source/Host/openbsd/Host.cpp b/gnu/llvm/tools/lldb/source/Host/openbsd/Host.cpp index 0535256b9aa..ee65e317685 100644 --- a/gnu/llvm/tools/lldb/source/Host/openbsd/Host.cpp +++ b/gnu/llvm/tools/lldb/source/Host/openbsd/Host.cpp @@ -7,7 +7,6 @@ // //===----------------------------------------------------------------------===// -// C Includes #include <sys/types.h> #include <sys/signal.h> @@ -19,15 +18,9 @@ #include <stdio.h> -// C++ Includes -// Other libraries and framework includes -// Project includes -#include "lldb/Core/Module.h" #include "lldb/Host/Host.h" #include "lldb/Host/HostInfo.h" -#include "lldb/Target/Platform.h" #include "lldb/Target/Process.h" -#include "lldb/Utility/CleanUp.h" #include "lldb/Utility/DataBufferHeap.h" #include "lldb/Utility/DataExtractor.h" #include "lldb/Utility/Endian.h" @@ -45,64 +38,78 @@ extern char **environ; using namespace lldb; using namespace lldb_private; -size_t Host::GetEnvironment(StringList &env) { +Environment Host::GetEnvironment() { + Environment env; char *v; char **var = environ; for (; var != NULL && *var != NULL; ++var) { v = strchr(*var, (int)'-'); if (v == NULL) continue; - env.AppendString(v); + env.insert(v); } - return env.GetSize(); + return env; } static bool GetOpenBSDProcessArgs(const ProcessInstanceInfoMatch *match_info_ptr, ProcessInstanceInfo &process_info) { - if (process_info.ProcessIDIsValid()) { - int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_ARGS, - (int)process_info.GetProcessID()}; - - char arg_data[8192]; - size_t arg_data_size = sizeof(arg_data); - if (::sysctl(mib, 4, arg_data, &arg_data_size, NULL, 0) == 0) { - DataExtractor data(arg_data, arg_data_size, endian::InlHostByteOrder(), - sizeof(void *)); - lldb::offset_t offset = 0; - const char *cstr; - - cstr = data.GetCStr(&offset); - if (cstr) { - process_info.GetExecutableFile().SetFile(cstr, false); - - if (!(match_info_ptr == NULL || - NameMatches( - process_info.GetExecutableFile().GetFilename().GetCString(), + if (!process_info.ProcessIDIsValid()) + return false; + + int pid = process_info.GetProcessID(); + + int mib[4] = {CTL_KERN, KERN_PROC_ARGS, pid, KERN_PROC_ARGV}; + size_t kern_proc_args_size = 0; + + // On OpenBSD, this will just fill ARG_MAX all the time + if (::sysctl(mib, 4, NULL, &kern_proc_args_size, NULL, 0) == -1) + return false; + + std::string arg_data(kern_proc_args_size, 0); + + if (::sysctl(mib, 4, (void *)arg_data.data(), &kern_proc_args_size, NULL, 0) == -1) + return false; + + arg_data.resize(kern_proc_args_size); + + // arg_data is a NULL terminated list of pointers, where the pointers + // point within arg_data to the location of the arg string + DataExtractor data(arg_data.data(), arg_data.length(), endian::InlHostByteOrder(), sizeof(void *)); + + lldb::offset_t offset = 0; + lldb::offset_t arg_offset = 0; + uint64_t arg_addr = 0; + const char *cstr; + + arg_addr = data.GetAddress(&offset); + arg_offset = arg_addr - (uint64_t)arg_data.data(); + cstr = data.GetCStr(&arg_offset); + + if (!cstr) + return false; + + process_info.GetExecutableFile().SetFile(cstr, FileSpec::Style::native); + + if (match_info_ptr != NULL && + !NameMatches(process_info.GetExecutableFile().GetFilename().GetCString(), match_info_ptr->GetNameMatchType(), - match_info_ptr->GetProcessInfo().GetName()))) - return false; - - Args &proc_args = process_info.GetArguments(); - while (1) { - const uint8_t *p = data.PeekData(offset, 1); - while ((p != NULL) && (*p == '\0') && offset < arg_data_size) { - ++offset; - p = data.PeekData(offset, 1); - } - if (p == NULL || offset >= arg_data_size) - return true; - - cstr = data.GetCStr(&offset); - if (cstr) - proc_args.AppendArgument(llvm::StringRef(cstr)); - else - return true; - } - } - } + match_info_ptr->GetProcessInfo().GetName())) + { + return false; } - return false; + + Args &proc_args = process_info.GetArguments(); + + while (1) { + arg_addr = data.GetAddress(&offset); + if (arg_addr == 0) + break; + arg_offset = arg_addr - (uint64_t)arg_data.data(); + cstr = data.GetCStr(&arg_offset); + proc_args.AppendArgument(cstr); + } + return true; } static bool GetOpenBSDProcessCPUType(ProcessInstanceInfo &process_info) { @@ -116,21 +123,21 @@ static bool GetOpenBSDProcessCPUType(ProcessInstanceInfo &process_info) { } static bool GetOpenBSDProcessUserAndGroup(ProcessInstanceInfo &process_info) { - struct kinfo_proc proc_kinfo; - size_t proc_kinfo_size; if (process_info.ProcessIDIsValid()) { - int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, - (int)process_info.GetProcessID()}; - proc_kinfo_size = sizeof(struct kinfo_proc); + struct kinfo_proc proc_kinfo = {}; + size_t proc_kinfo_size = sizeof(proc_kinfo); + int mib[6] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, + (int)process_info.GetProcessID(), + sizeof(proc_kinfo), 1}; - if (::sysctl(mib, 4, &proc_kinfo, &proc_kinfo_size, NULL, 0) == 0) { + if (::sysctl(mib, 6, &proc_kinfo, &proc_kinfo_size, NULL, 0) == 0) { if (proc_kinfo_size > 0) { process_info.SetParentProcessID(proc_kinfo.p_ppid); process_info.SetUserID(proc_kinfo.p_ruid); process_info.SetGroupID(proc_kinfo.p_rgid); process_info.SetEffectiveUserID(proc_kinfo.p_uid); - process_info.SetEffectiveGroupID(proc_kinfo.p_gid); + process_info.SetEffectiveGroupID(proc_kinfo.p_gid); return true; } } @@ -147,10 +154,10 @@ uint32_t Host::FindProcesses(const ProcessInstanceInfoMatch &match_info, ProcessInstanceInfoList &process_infos) { std::vector<struct kinfo_proc> kinfos; - int mib[3] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL}; + int mib[6] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0, sizeof(struct kinfo_proc), 0}; size_t pid_data_size = 0; - if (::sysctl(mib, 3, NULL, &pid_data_size, NULL, 0) != 0) + if (::sysctl(mib, 6, NULL, &pid_data_size, NULL, 0) != 0) return 0; // Add a few extra in case a few more show up @@ -158,9 +165,10 @@ uint32_t Host::FindProcesses(const ProcessInstanceInfoMatch &match_info, (pid_data_size / sizeof(struct kinfo_proc)) + 10; kinfos.resize(estimated_pid_count); + mib[5] = estimated_pid_count; pid_data_size = kinfos.size() * sizeof(struct kinfo_proc); - if (::sysctl(mib, 3, &kinfos[0], &pid_data_size, NULL, 0) != 0) + if (::sysctl(mib, 6, &kinfos[0], &pid_data_size, NULL, 0) != 0) return 0; const size_t actual_pid_count = (pid_data_size / sizeof(struct kinfo_proc)); diff --git a/gnu/llvm/tools/lldb/source/Host/posix/DomainSocket.cpp b/gnu/llvm/tools/lldb/source/Host/posix/DomainSocket.cpp index 3e3abadc2e5..af27e066413 100644 --- a/gnu/llvm/tools/lldb/source/Host/posix/DomainSocket.cpp +++ b/gnu/llvm/tools/lldb/source/Host/posix/DomainSocket.cpp @@ -50,7 +50,7 @@ bool SetSockAddr(llvm::StringRef name, const size_t name_offset, saddr_un_len = offsetof(struct sockaddr_un, sun_path) + name_offset + name.size(); -#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) +#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) saddr_un->sun_len = saddr_un_len; #endif diff --git a/gnu/llvm/tools/lldb/source/Host/posix/PipePosix.cpp b/gnu/llvm/tools/lldb/source/Host/posix/PipePosix.cpp index da99fd70242..6782440bb1b 100644 --- a/gnu/llvm/tools/lldb/source/Host/posix/PipePosix.cpp +++ b/gnu/llvm/tools/lldb/source/Host/posix/PipePosix.cpp @@ -39,7 +39,7 @@ enum PIPES { READ, WRITE }; // Constants 0 and 1 for READ and WRITE // pipe2 is supported by a limited set of platforms // TODO: Add more platforms that support pipe2. #if defined(__linux__) || (defined(__FreeBSD__) && __FreeBSD__ >= 10) || \ - defined(__NetBSD__) + defined(__NetBSD__) || defined(__OpenBSD__) #define PIPE2_SUPPORTED 1 #else #define PIPE2_SUPPORTED 0 @@ -61,12 +61,13 @@ bool SetCloexecFlag(int fd) { std::chrono::time_point<std::chrono::steady_clock> Now() { return std::chrono::steady_clock::now(); } -} +} // namespace PipePosix::PipePosix() : m_fds{PipePosix::kInvalidDescriptor, PipePosix::kInvalidDescriptor} {} -PipePosix::PipePosix(int read_fd, int write_fd) : m_fds{read_fd, write_fd} {} +PipePosix::PipePosix(lldb::pipe_t read, lldb::pipe_t write) + : m_fds{read, write} {} PipePosix::PipePosix(PipePosix &&pipe_posix) : PipeBase{std::move(pipe_posix)}, @@ -125,20 +126,16 @@ Status PipePosix::CreateNew(llvm::StringRef name, bool child_process_inherit) { Status PipePosix::CreateWithUniqueName(llvm::StringRef prefix, bool child_process_inherit, llvm::SmallVectorImpl<char> &name) { - llvm::SmallString<PATH_MAX> named_pipe_path; - llvm::SmallString<PATH_MAX> pipe_spec((prefix + ".%%%%%%").str()); - FileSpec tmpdir_file_spec; - tmpdir_file_spec.Clear(); - if (HostInfo::GetLLDBPath(ePathTypeLLDBTempSystemDir, tmpdir_file_spec)) { - tmpdir_file_spec.AppendPathComponent(pipe_spec.c_str()); - } else { + llvm::SmallString<128> named_pipe_path; + llvm::SmallString<128> pipe_spec((prefix + ".%%%%%%").str()); + FileSpec tmpdir_file_spec = HostInfo::GetProcessTempDir(); + if (!tmpdir_file_spec) tmpdir_file_spec.AppendPathComponent("/tmp"); - tmpdir_file_spec.AppendPathComponent(pipe_spec.c_str()); - } + tmpdir_file_spec.AppendPathComponent(pipe_spec); // It's possible that another process creates the target path after we've - // verified it's available but before we create it, in which case we - // should try again. + // verified it's available but before we create it, in which case we should + // try again. Status error; do { llvm::sys::fs::createUniqueFile(tmpdir_file_spec.GetPath(), diff --git a/gnu/llvm/tools/lldb/source/Initialization/CMakeLists.txt b/gnu/llvm/tools/lldb/source/Initialization/CMakeLists.txt index 7a100588e00..237e9761f02 100644 --- a/gnu/llvm/tools/lldb/source/Initialization/CMakeLists.txt +++ b/gnu/llvm/tools/lldb/source/Initialization/CMakeLists.txt @@ -1,8 +1,4 @@ -if ( CMAKE_SYSTEM_NAME MATCHES "Darwin" ) - list(APPEND EXTRA_PLUGINS lldbPluginObjectFileMachO) -endif() - -if ( CMAKE_SYSTEM_NAME MATCHES "Linux|Android|FreeBSD|NetBSD" ) +if ( CMAKE_SYSTEM_NAME MATCHES "Linux|Android|FreeBSD|NetBSD|OpenBSD" ) list(APPEND EXTRA_PLUGINS lldbPluginProcessPOSIX) endif() @@ -23,8 +19,6 @@ add_lldb_library(lldbInitialization lldbPluginInstructionMIPS64 lldbPluginObjectContainerBSDArchive lldbPluginObjectContainerMachOArchive - lldbPluginObjectFileELF - lldbPluginObjectFilePECOFF lldbPluginProcessGDBRemote ${EXTRA_PLUGINS} ${LLDB_SYSTEM_LIBS} diff --git a/gnu/llvm/tools/lldb/source/Initialization/SystemInitializerCommon.cpp b/gnu/llvm/tools/lldb/source/Initialization/SystemInitializerCommon.cpp index e76ba4122bb..767f54962c0 100644 --- a/gnu/llvm/tools/lldb/source/Initialization/SystemInitializerCommon.cpp +++ b/gnu/llvm/tools/lldb/source/Initialization/SystemInitializerCommon.cpp @@ -14,19 +14,15 @@ #include "Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.h" #include "Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h" #include "Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.h" -#include "Plugins/ObjectFile/ELF/ObjectFileELF.h" -#include "Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h" #include "Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h" +#include "lldb/Host/FileSystem.h" #include "lldb/Host/Host.h" #include "lldb/Host/HostInfo.h" #include "lldb/Utility/Log.h" +#include "lldb/Utility/Reproducer.h" #include "lldb/Utility/Timer.h" -#if defined(__APPLE__) -#include "Plugins/ObjectFile/Mach-O/ObjectFileMachO.h" -#endif - -#if defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__) +#if defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) #include "Plugins/Process/POSIX/ProcessPOSIXLog.h" #endif @@ -35,18 +31,19 @@ #include "lldb/Host/windows/windows.h" #endif -#include "llvm/Support/PrettyStackTrace.h" #include "llvm/Support/TargetSelect.h" #include <string> using namespace lldb_private; +using namespace lldb_private::repro; SystemInitializerCommon::SystemInitializerCommon() {} SystemInitializerCommon::~SystemInitializerCommon() {} -void SystemInitializerCommon::Initialize() { +llvm::Error +SystemInitializerCommon::Initialize(const InitializerOptions &options) { #if defined(_MSC_VER) const char *disable_crash_dialog_var = getenv("LLDB_DISABLE_CRASH_DIALOG"); if (disable_crash_dialog_var && @@ -69,8 +66,17 @@ void SystemInitializerCommon::Initialize() { } #endif - llvm::EnablePrettyStackTrace(); - InitializeLog(); + ReproducerMode mode = ReproducerMode::Off; + if (options.reproducer_capture) + mode = ReproducerMode::Capture; + if (options.reproducer_replay) + mode = ReproducerMode::Replay; + + if (auto e = Reproducer::Initialize(mode, FileSpec(options.reproducer_path))) + return e; + + FileSystem::Initialize(); + Log::Initialize(); HostInfo::Initialize(); static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); Timer scoped_timer(func_cat, LLVM_PRETTY_FUNCTION); @@ -79,8 +85,6 @@ void SystemInitializerCommon::Initialize() { // Initialize plug-ins ObjectContainerBSDArchive::Initialize(); - ObjectFileELF::Initialize(); - ObjectFilePECOFF::Initialize(); EmulateInstructionARM::Initialize(); EmulateInstructionMIPS::Initialize(); @@ -91,32 +95,26 @@ void SystemInitializerCommon::Initialize() { //---------------------------------------------------------------------- ObjectContainerUniversalMachO::Initialize(); -#if defined(__APPLE__) - ObjectFileMachO::Initialize(); -#endif -#if defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__) +#if defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) ProcessPOSIXLog::Initialize(); #endif #if defined(_MSC_VER) ProcessWindowsLog::Initialize(); #endif + + return llvm::Error::success(); } void SystemInitializerCommon::Terminate() { static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); Timer scoped_timer(func_cat, LLVM_PRETTY_FUNCTION); ObjectContainerBSDArchive::Terminate(); - ObjectFileELF::Terminate(); - ObjectFilePECOFF::Terminate(); EmulateInstructionARM::Terminate(); EmulateInstructionMIPS::Terminate(); EmulateInstructionMIPS64::Terminate(); ObjectContainerUniversalMachO::Terminate(); -#if defined(__APPLE__) - ObjectFileMachO::Terminate(); -#endif #if defined(_MSC_VER) ProcessWindowsLog::Terminate(); @@ -124,4 +122,6 @@ void SystemInitializerCommon::Terminate() { HostInfo::Terminate(); Log::DisableAllLogChannels(); + FileSystem::Terminate(); + Reproducer::Terminate(); } diff --git a/gnu/llvm/tools/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp b/gnu/llvm/tools/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp index c1986976b0f..9a09ebc31af 100644 --- a/gnu/llvm/tools/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp +++ b/gnu/llvm/tools/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp @@ -7,10 +7,6 @@ // //===----------------------------------------------------------------------===// -// C Includes -// C++ Includes -// Other libraries and framework includes -#include "lldb/Core/ArchSpec.h" #include "lldb/Core/Module.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Symbol/Symbol.h" @@ -18,6 +14,7 @@ #include "lldb/Target/Platform.h" #include "lldb/Target/Process.h" #include "lldb/Target/Target.h" +#include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/Log.h" #include "lldb/Utility/Status.h" @@ -48,8 +45,8 @@ static addr_t ResolveRendezvousAddress(Process *process) { if (log) log->Printf("%s info_location = 0x%" PRIx64, __FUNCTION__, info_location); - // If the process fails to return an address, fall back to seeing if the local - // object file can help us find it. + // If the process fails to return an address, fall back to seeing if the + // local object file can help us find it. if (info_location == LLDB_INVALID_ADDRESS) { Target *target = &process->GetTarget(); if (target) { @@ -193,8 +190,8 @@ bool DYLDRendezvous::UpdateSOEntries(bool fromRemote) { if (!fromRemote && 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 + // 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 fromRemote ? SaveSOEntriesFromRemote(module_list) @@ -203,9 +200,9 @@ bool DYLDRendezvous::UpdateSOEntries(bool fromRemote) { // 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) { - // Some versions of the android dynamic linker might send two - // notifications with state == eAdd back to back. Ignore them - // until we get an eConsistent notification. + // Some versions of the android dynamic linker might send two notifications + // with state == eAdd back to back. Ignore them until we get an eConsistent + // notification. if (!(m_previous.state == eConsistent || (m_previous.state == eAdd && m_current.state == eDelete))) return false; @@ -246,7 +243,7 @@ bool DYLDRendezvous::FillSOEntryFromModuleInfo( entry.base_addr = base_addr; entry.dyn_addr = dyn_addr; - entry.file_spec.SetFile(name, false); + entry.file_spec.SetFile(name, FileSpec::Style::native); UpdateBaseAddrIfNecessary(entry, name); @@ -386,6 +383,7 @@ bool DYLDRendezvous::SOEntryIsMainExecutable(const SOEntry &entry) { switch (triple.getOS()) { case llvm::Triple::FreeBSD: case llvm::Triple::NetBSD: + case llvm::Triple::OpenBSD: return entry.file_spec == m_exe_file_spec; case llvm::Triple::Linux: if (triple.isAndroid()) @@ -452,30 +450,22 @@ std::string DYLDRendezvous::ReadStringFromMemory(addr_t addr) { } // Returns true if the load bias reported by the linker is incorrect for the -// given entry. This -// function is used to handle cases where we want to work around a bug in the -// system linker. +// given entry. This function is used to handle cases where we want to work +// around a bug in the system linker. static bool isLoadBiasIncorrect(Target &target, const std::string &file_path) { // On Android L (API 21, 22) the load address of the "/system/bin/linker" - // isn't filled in - // correctly. - uint32_t os_major = 0, os_minor = 0, os_update = 0; - if (target.GetArchitecture().GetTriple().isAndroid() && - target.GetPlatform()->GetOSVersion(os_major, os_minor, os_update) && - (os_major == 21 || os_major == 22) && - (file_path == "/system/bin/linker" || - file_path == "/system/bin/linker64")) { - return true; - } - - return false; + // isn't filled in correctly. + unsigned os_major = target.GetPlatform()->GetOSVersion().getMajor(); + return target.GetArchitecture().GetTriple().isAndroid() && + (os_major == 21 || os_major == 22) && + (file_path == "/system/bin/linker" || + file_path == "/system/bin/linker64"); } void DYLDRendezvous::UpdateBaseAddrIfNecessary(SOEntry &entry, std::string const &file_path) { // If the load bias reported by the linker is incorrect then fetch the load - // address of the file - // from the proc file system. + // address of the file from the proc file system. if (isLoadBiasIncorrect(m_process->GetTarget(), file_path)) { lldb::addr_t load_addr = LLDB_INVALID_ADDRESS; bool is_loaded = false; @@ -494,8 +484,8 @@ bool DYLDRendezvous::ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry) { if (!(addr = ReadPointer(addr, &entry.base_addr))) return false; - // mips adds an extra load offset field to the link map struct on - // FreeBSD and NetBSD (need to validate other OSes). + // mips adds an extra load offset field to the link map struct on FreeBSD and + // NetBSD (need to validate other OSes). // http://svnweb.freebsd.org/base/head/sys/sys/link_elf.h?revision=217153&view=markup#l57 const ArchSpec &arch = m_process->GetTarget().GetArchitecture(); if ((arch.GetTriple().getOS() == llvm::Triple::FreeBSD || @@ -524,7 +514,7 @@ bool DYLDRendezvous::ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry) { return false; std::string file_path = ReadStringFromMemory(entry.path_addr); - entry.file_spec.SetFile(file_path, false); + entry.file_spec.SetFile(file_path, FileSpec::Style::native); UpdateBaseAddrIfNecessary(entry, file_path); diff --git a/gnu/llvm/tools/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp b/gnu/llvm/tools/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp index a7afeb6d68c..77e0c870c20 100644 --- a/gnu/llvm/tools/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp +++ b/gnu/llvm/tools/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp @@ -10,10 +10,8 @@ // Main header include #include "DynamicLoaderPOSIXDYLD.h" -// Project includes #include "AuxVector.h" -// Other libraries and framework includes #include "lldb/Breakpoint/BreakpointLocation.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleSpec.h" @@ -29,8 +27,6 @@ #include "lldb/Target/ThreadPlanRunToAddress.h" #include "lldb/Utility/Log.h" -// C++ Includes -// C Includes using namespace lldb; using namespace lldb_private; @@ -66,7 +62,8 @@ DynamicLoader *DynamicLoaderPOSIXDYLD::CreateInstance(Process *process, process->GetTarget().GetArchitecture().GetTriple(); if (triple_ref.getOS() == llvm::Triple::FreeBSD || triple_ref.getOS() == llvm::Triple::Linux || - triple_ref.getOS() == llvm::Triple::NetBSD) + triple_ref.getOS() == llvm::Triple::NetBSD || + triple_ref.getOS() == llvm::Triple::OpenBSD) create = true; } @@ -79,7 +76,8 @@ DynamicLoaderPOSIXDYLD::DynamicLoaderPOSIXDYLD(Process *process) : DynamicLoader(process), m_rendezvous(process), m_load_offset(LLDB_INVALID_ADDRESS), m_entry_point(LLDB_INVALID_ADDRESS), m_auxv(), m_dyld_bid(LLDB_INVALID_BREAK_ID), - m_vdso_base(LLDB_INVALID_ADDRESS) {} + m_vdso_base(LLDB_INVALID_ADDRESS), + m_interpreter_base(LLDB_INVALID_ADDRESS) {} DynamicLoaderPOSIXDYLD::~DynamicLoaderPOSIXDYLD() { if (m_dyld_bid != LLDB_INVALID_BREAK_ID) { @@ -117,10 +115,10 @@ void DynamicLoaderPOSIXDYLD::DidAttach() { : "<null executable>", load_offset); - EvalVdsoStatus(); + EvalSpecialModulesStatus(); // if we dont have a load address we cant re-base - bool rebase_exec = (load_offset == LLDB_INVALID_ADDRESS) ? false : true; + bool rebase_exec = load_offset != LLDB_INVALID_ADDRESS; // if we have a valid executable if (executable_sp.get()) { @@ -152,31 +150,10 @@ void DynamicLoaderPOSIXDYLD::DidAttach() { UpdateLoadedSections(executable_sp, LLDB_INVALID_ADDRESS, load_offset, true); - // When attaching to a target, there are two possible states: - // (1) We already crossed the entry point and therefore the rendezvous - // structure is ready to be used and we can load the list of modules - // and place the rendezvous breakpoint. - // (2) We didn't cross the entry point yet, so these structures are not - // ready; we should behave as if we just launched the target and - // call ProbeEntry(). This will place a breakpoint on the entry - // point which itself will be hit after the rendezvous structure is - // set up and will perform actions described in (1). - if (m_rendezvous.Resolve()) { - if (log) - log->Printf("DynamicLoaderPOSIXDYLD::%s() pid %" PRIu64 - " rendezvous could resolve: attach assuming dynamic loader " - "info is available now", - __FUNCTION__, - m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID); - LoadAllCurrentModules(); - SetRendezvousBreakpoint(); - } else { - if (log) - log->Printf("DynamicLoaderPOSIXDYLD::%s() pid %" PRIu64 - " rendezvous could not yet resolve: adding breakpoint to " - "catch future rendezvous setup", - __FUNCTION__, - m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID); + LoadAllCurrentModules(); + if (!SetRendezvousBreakpoint()) { + // If we cannot establish rendezvous breakpoint right now we'll try again + // at entry point. ProbeEntry(); } @@ -207,7 +184,7 @@ void DynamicLoaderPOSIXDYLD::DidLaunch() { executable = GetTargetExecutable(); load_offset = ComputeLoadOffset(); - EvalVdsoStatus(); + EvalSpecialModulesStatus(); if (executable.get() && load_offset != LLDB_INVALID_ADDRESS) { ModuleList module_list; @@ -217,8 +194,14 @@ void DynamicLoaderPOSIXDYLD::DidLaunch() { if (log) log->Printf("DynamicLoaderPOSIXDYLD::%s about to call ProbeEntry()", __FUNCTION__); - ProbeEntry(); + if (!SetRendezvousBreakpoint()) { + // If we cannot establish rendezvous breakpoint right now we'll try again + // at entry point. + ProbeEntry(); + } + + LoadVDSO(); m_process->GetTarget().ModulesDidLoad(module_list); } } @@ -273,11 +256,11 @@ void DynamicLoaderPOSIXDYLD::ProbeEntry() { } // The runtime linker has run and initialized the rendezvous structure once the -// process has hit its entry point. When we hit the corresponding breakpoint we -// interrogate the rendezvous structure to get the load addresses of all +// process has hit its entry point. When we hit the corresponding breakpoint +// we interrogate the rendezvous structure to get the load addresses of all // dependent modules for the process. Similarly, we can discover the runtime -// linker function and setup a breakpoint to notify us of any dynamically loaded -// modules (via dlopen). +// linker function and setup a breakpoint to notify us of any dynamically +// loaded modules (via dlopen). bool DynamicLoaderPOSIXDYLD::EntryBreakpointHit( void *baton, StoppointCallbackContext *context, user_id_t break_id, user_id_t break_loc_id) { @@ -295,13 +278,11 @@ bool DynamicLoaderPOSIXDYLD::EntryBreakpointHit( : LLDB_INVALID_PROCESS_ID); // Disable the breakpoint --- if a stop happens right after this, which we've - // seen on occasion, we don't - // want the breakpoint stepping thread-plan logic to show a breakpoint - // instruction at the disassembled - // entry point to the program. Disabling it prevents it. (One-shot is not - // enough - one-shot removal logic - // only happens after the breakpoint goes public, which wasn't happening in - // our scenario). + // seen on occasion, we don't want the breakpoint stepping thread-plan logic + // to show a breakpoint instruction at the disassembled entry point to the + // program. Disabling it prevents it. (One-shot is not enough - one-shot + // removal logic only happens after the breakpoint goes public, which wasn't + // happening in our scenario). if (dyld_instance->m_process) { BreakpointSP breakpoint_sp = dyld_instance->m_process->GetTarget().GetBreakpointByID(break_id); @@ -329,38 +310,77 @@ bool DynamicLoaderPOSIXDYLD::EntryBreakpointHit( return false; // Continue running. } -void DynamicLoaderPOSIXDYLD::SetRendezvousBreakpoint() { +bool DynamicLoaderPOSIXDYLD::SetRendezvousBreakpoint() { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); + if (m_dyld_bid != LLDB_INVALID_BREAK_ID) { + LLDB_LOG(log, + "Rendezvous breakpoint breakpoint id {0} for pid {1}" + "is already set.", + m_dyld_bid, + m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID); + return true; + } - addr_t break_addr = m_rendezvous.GetBreakAddress(); + addr_t break_addr; Target &target = m_process->GetTarget(); - - if (m_dyld_bid == LLDB_INVALID_BREAK_ID) { - if (log) - log->Printf("DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 - " setting rendezvous break address at 0x%" PRIx64, - __FUNCTION__, - m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID, - break_addr); - Breakpoint *dyld_break = - target.CreateBreakpoint(break_addr, true, false).get(); - dyld_break->SetCallback(RendezvousBreakpointHit, this, true); - dyld_break->SetBreakpointKind("shared-library-event"); - m_dyld_bid = dyld_break->GetID(); + BreakpointSP dyld_break; + if (m_rendezvous.IsValid()) { + break_addr = m_rendezvous.GetBreakAddress(); + LLDB_LOG(log, "Setting rendezvous break address for pid {0} at {1:x}", + m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID, + break_addr); + dyld_break = target.CreateBreakpoint(break_addr, true, false); } else { - if (log) - log->Printf("DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 - " reusing break id %" PRIu32 ", address at 0x%" PRIx64, - __FUNCTION__, - m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID, - m_dyld_bid, break_addr); + LLDB_LOG(log, "Rendezvous structure is not set up yet. " + "Trying to locate rendezvous breakpoint in the interpreter " + "by symbol name."); + ModuleSP interpreter = LoadInterpreterModule(); + if (!interpreter) { + LLDB_LOG(log, "Can't find interpreter, rendezvous breakpoint isn't set."); + return false; + } + + // Function names from different dynamic loaders that are known to be used + // as rendezvous between the loader and debuggers. + static std::vector<std::string> DebugStateCandidates{ + "_dl_debug_state", "rtld_db_dlactivity", "__dl_rtld_db_dlactivity", + "r_debug_state", "_r_debug_state", "_rtld_debug_state", + }; + + FileSpecList containingModules; + containingModules.Append(interpreter->GetFileSpec()); + dyld_break = target.CreateBreakpoint( + &containingModules, nullptr /* containingSourceFiles */, + DebugStateCandidates, eFunctionNameTypeFull, eLanguageTypeC, + 0, /* offset */ + eLazyBoolNo, /* skip_prologue */ + true, /* internal */ + false /* request_hardware */); + } + + if (dyld_break->GetNumResolvedLocations() != 1) { + LLDB_LOG( + log, + "Rendezvous breakpoint has abnormal number of" + " resolved locations ({0}) in pid {1}. It's supposed to be exactly 1.", + dyld_break->GetNumResolvedLocations(), + m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID); + + target.RemoveBreakpointByID(dyld_break->GetID()); + return false; } - // Make sure our breakpoint is at the right address. - assert(target.GetBreakpointByID(m_dyld_bid) - ->FindLocationByAddress(break_addr) - ->GetBreakpoint() - .GetID() == m_dyld_bid); + BreakpointLocationSP location = dyld_break->GetLocationAtIndex(0); + LLDB_LOG(log, + "Successfully set rendezvous breakpoint at address {0:x} " + "for pid {1}", + location->GetLoadAddress(), + m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID); + + dyld_break->SetCallback(RendezvousBreakpointHit, this, true); + dyld_break->SetBreakpointKind("shared-library-event"); + m_dyld_bid = dyld_break->GetID(); + return true; } bool DynamicLoaderPOSIXDYLD::RendezvousBreakpointHit( @@ -477,7 +497,7 @@ DynamicLoaderPOSIXDYLD::GetStepThroughTrampolinePlan(Thread &thread, AddressVector::iterator start = addrs.begin(); AddressVector::iterator end = addrs.end(); - std::sort(start, end); + llvm::sort(start, end); addrs.erase(std::unique(start, end), end); thread_plan_sp.reset(new ThreadPlanRunToAddress(thread, addrs, stop)); } @@ -485,11 +505,11 @@ DynamicLoaderPOSIXDYLD::GetStepThroughTrampolinePlan(Thread &thread, return thread_plan_sp; } -void DynamicLoaderPOSIXDYLD::LoadVDSO(ModuleList &modules) { +void DynamicLoaderPOSIXDYLD::LoadVDSO() { if (m_vdso_base == LLDB_INVALID_ADDRESS) return; - FileSpec file("[vdso]", false); + FileSpec file("[vdso]"); MemoryRegionInfo info; Status status = m_process->GetMemoryRegionInfo(m_vdso_base, info); @@ -506,13 +526,40 @@ void DynamicLoaderPOSIXDYLD::LoadVDSO(ModuleList &modules) { } } +ModuleSP DynamicLoaderPOSIXDYLD::LoadInterpreterModule() { + if (m_interpreter_base == LLDB_INVALID_ADDRESS) + return nullptr; + + MemoryRegionInfo info; + Target &target = m_process->GetTarget(); + Status status = m_process->GetMemoryRegionInfo(m_interpreter_base, info); + if (status.Fail() || info.GetMapped() != MemoryRegionInfo::eYes || + info.GetName().IsEmpty()) { + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); + LLDB_LOG(log, "Failed to get interpreter region info: {0}", status); + return nullptr; + } + + FileSpec file(info.GetName().GetCString()); + ModuleSpec module_spec(file, target.GetArchitecture()); + + if (ModuleSP module_sp = target.GetSharedModule(module_spec)) { + UpdateLoadedSections(module_sp, LLDB_INVALID_ADDRESS, m_interpreter_base, + false); + return module_sp; + } + return nullptr; +} + void DynamicLoaderPOSIXDYLD::LoadAllCurrentModules() { DYLDRendezvous::iterator I; DYLDRendezvous::iterator E; ModuleList module_list; + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); + + LoadVDSO(); if (!m_rendezvous.Resolve()) { - Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); if (log) log->Printf("DynamicLoaderPOSIXDYLD::%s unable to resolve POSIX DYLD " "rendezvous address", @@ -520,11 +567,10 @@ void DynamicLoaderPOSIXDYLD::LoadAllCurrentModules() { return; } - // The rendezvous class doesn't enumerate the main module, so track - // that ourselves here. + // The rendezvous class doesn't enumerate the main module, so track that + // ourselves here. ModuleSP executable = GetTargetExecutable(); m_loaded_modules[executable] = m_rendezvous.GetLinkMapAddress(); - LoadVDSO(module_list); std::vector<FileSpec> module_names; for (I = m_rendezvous.begin(), E = m_rendezvous.end(); I != E; ++I) @@ -536,6 +582,8 @@ void DynamicLoaderPOSIXDYLD::LoadAllCurrentModules() { ModuleSP module_sp = LoadModuleAtAddress(I->file_spec, I->link_addr, I->base_addr, true); if (module_sp.get()) { + LLDB_LOG(log, "LoadAllCurrentModules loading module: {0}", + I->file_spec.GetFilename()); module_list.Append(module_sp); } else { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); @@ -575,11 +623,14 @@ addr_t DynamicLoaderPOSIXDYLD::ComputeLoadOffset() { return m_load_offset; } -void DynamicLoaderPOSIXDYLD::EvalVdsoStatus() { - AuxVector::iterator I = m_auxv->FindEntry(AuxVector::AUXV_AT_SYSINFO_EHDR); - - if (I != m_auxv->end()) +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; } addr_t DynamicLoaderPOSIXDYLD::GetEntryPoint() { @@ -702,7 +753,7 @@ void DynamicLoaderPOSIXDYLD::ResolveExecutableModule( return; } - target.SetExecutableModule(module_sp, false); + target.SetExecutableModule(module_sp, eLoadDependentsNo); } bool DynamicLoaderPOSIXDYLD::AlwaysRelyOnEHUnwindInfo( diff --git a/gnu/llvm/tools/lldb/source/Plugins/Platform/OpenBSD/PlatformOpenBSD.cpp b/gnu/llvm/tools/lldb/source/Plugins/Platform/OpenBSD/PlatformOpenBSD.cpp index edb8ec951d3..b5f7226901c 100644 --- a/gnu/llvm/tools/lldb/source/Plugins/Platform/OpenBSD/PlatformOpenBSD.cpp +++ b/gnu/llvm/tools/lldb/source/Plugins/Platform/OpenBSD/PlatformOpenBSD.cpp @@ -10,28 +10,24 @@ #include "PlatformOpenBSD.h" #include "lldb/Host/Config.h" -// C Includes #include <stdio.h> #ifndef LLDB_DISABLE_POSIX #include <sys/utsname.h> #endif -// C++ Includes -// Other libraries and framework includes -// Project includes #include "lldb/Core/Debugger.h" #include "lldb/Core/PluginManager.h" -#include "lldb/Core/State.h" #include "lldb/Host/HostInfo.h" #include "lldb/Target/Process.h" #include "lldb/Target/Target.h" #include "lldb/Utility/FileSpec.h" #include "lldb/Utility/Log.h" +#include "lldb/Utility/State.h" #include "lldb/Utility/Status.h" #include "lldb/Utility/StreamString.h" -// Define these constants from OpenBSD mman.h for use when targeting -// remote openbsd systems even when host has different values. +// Define these constants from OpenBSD mman.h for use when targeting remote +// openbsd systems even when host has different values. #define MAP_PRIVATE 0x0002 #define MAP_ANON 0x1000 @@ -50,7 +46,7 @@ PlatformSP PlatformOpenBSD::CreateInstance(bool force, const ArchSpec *arch) { arch ? arch->GetTriple().getTriple() : "<null>"); bool create = force; - if (create == false && arch && arch->IsValid()) { + if (!create && arch && arch->IsValid()) { const llvm::Triple &triple = arch->GetTriple(); switch (triple.getOS()) { case llvm::Triple::OpenBSD: @@ -58,9 +54,8 @@ PlatformSP PlatformOpenBSD::CreateInstance(bool force, const ArchSpec *arch) { break; #if defined(__OpenBSD__) - // Only accept "unknown" for the OS if the host is BSD and - // it "unknown" wasn't specified (it was just returned because it - // was NOT specified) + // Only accept "unknown" for the OS if the host is BSD and it "unknown" + // wasn't specified (it was just returned because it was NOT specified) case llvm::Triple::OSType::UnknownOS: create = !arch->TripleOSWasSpecified(); break; @@ -98,7 +93,7 @@ ConstString PlatformOpenBSD::GetPluginName() { } void PlatformOpenBSD::Initialize() { - Platform::Initialize(); + PlatformPOSIX::Initialize(); if (g_initialize_count++ == 0) { #if defined(__OpenBSD__) @@ -133,7 +128,7 @@ PlatformOpenBSD::PlatformOpenBSD(bool is_host) PlatformOpenBSD::~PlatformOpenBSD() = default; bool PlatformOpenBSD::GetSupportedArchitectureAtIndex(uint32_t idx, - ArchSpec &arch) { + ArchSpec &arch) { if (IsHost()) { ArchSpec hostArch = HostInfo::GetArchitecture(HostInfo::eArchKindDefault); if (hostArch.GetTriple().isOSOpenBSD()) { @@ -167,13 +162,10 @@ bool PlatformOpenBSD::GetSupportedArchitectureAtIndex(uint32_t idx, return false; } // Leave the vendor as "llvm::Triple:UnknownVendor" and don't specify the - // vendor by - // calling triple.SetVendorName("unknown") so that it is a "unspecified - // unknown". - // This means when someone calls triple.GetVendorName() it will return an - // empty string - // which indicates that the vendor can be set when two architectures are - // merged + // vendor by calling triple.SetVendorName("unknown") so that it is a + // "unspecified unknown". This means when someone calls + // triple.GetVendorName() it will return an empty string which indicates + // that the vendor can be set when two architectures are merged // Now set the triple into "arch" and return true arch.SetTriple(triple); @@ -202,22 +194,145 @@ void PlatformOpenBSD::GetStatus(Stream &strm) { #endif } -// OpenBSD processes cannot yet be launched by spawning and attaching. bool PlatformOpenBSD::CanDebugProcess() { - return false; + if (IsHost()) { + return true; + } else { + // If we're connected, we can debug. + return IsConnected(); + } +} + +// For local debugging, OpenBSD will override the debug logic to use llgs-launch +// rather than lldb-launch, llgs-attach. This differs from current lldb- +// launch, debugserver-attach approach on MacOSX. +lldb::ProcessSP +PlatformOpenBSD::DebugProcess(ProcessLaunchInfo &launch_info, Debugger &debugger, + Target *target, // Can be NULL, if NULL create a new + // target, else use existing one + Status &error) { + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); + LLDB_LOG(log, "target {0}", target); + + // If we're a remote host, use standard behavior from parent class. + if (!IsHost()) + return PlatformPOSIX::DebugProcess(launch_info, debugger, target, error); + + // + // For local debugging, we'll insist on having ProcessGDBRemote create the + // process. + // + + ProcessSP process_sp; + + // Make sure we stop at the entry point + launch_info.GetFlags().Set(eLaunchFlagDebug); + + // We always launch the process we are going to debug in a separate process + // group, since then we can handle ^C interrupts ourselves w/o having to + // worry about the target getting them as well. + launch_info.SetLaunchInSeparateProcessGroup(true); + + // Ensure we have a target. + if (target == nullptr) { + LLDB_LOG(log, "creating new target"); + TargetSP new_target_sp; + error = debugger.GetTargetList().CreateTarget(debugger, "", "", eLoadDependentsNo, + nullptr, new_target_sp); + if (error.Fail()) { + LLDB_LOG(log, "failed to create new target: {0}", error); + return process_sp; + } + + target = new_target_sp.get(); + if (!target) { + error.SetErrorString("CreateTarget() returned nullptr"); + LLDB_LOG(log, "error: {0}", error); + return process_sp; + } + } + + // Mark target as currently selected target. + debugger.GetTargetList().SetSelectedTarget(target); + + // Now create the gdb-remote process. + LLDB_LOG(log, "having target create process with gdb-remote plugin"); + process_sp = target->CreateProcess( + launch_info.GetListener(), "gdb-remote", nullptr); + + if (!process_sp) { + error.SetErrorString("CreateProcess() failed for gdb-remote process"); + LLDB_LOG(log, "error: {0}", error); + return process_sp; + } + + LLDB_LOG(log, "successfully created process"); + // Adjust launch for a hijacker. + ListenerSP listener_sp; + if (!launch_info.GetHijackListener()) { + LLDB_LOG(log, "setting up hijacker"); + listener_sp = + Listener::MakeListener("lldb.PlatformOpenBSD.DebugProcess.hijack"); + launch_info.SetHijackListener(listener_sp); + process_sp->HijackProcessEvents(listener_sp); + } + + // Log file actions. + if (log) { + LLDB_LOG(log, "launching process with the following file actions:"); + StreamString stream; + size_t i = 0; + const FileAction *file_action; + while ((file_action = launch_info.GetFileActionAtIndex(i++)) != nullptr) { + file_action->Dump(stream); + LLDB_LOG(log, "{0}", stream.GetData()); + stream.Clear(); + } + } + + // Do the launch. + error = process_sp->Launch(launch_info); + if (error.Success()) { + // Handle the hijacking of process events. + if (listener_sp) { + const StateType state = process_sp->WaitForProcessToStop( + llvm::None, NULL, false, listener_sp); + + LLDB_LOG(log, "pid {0} state {0}", process_sp->GetID(), state); + } + + // Hook up process PTY if we have one (which we should for local debugging + // with llgs). + int pty_fd = launch_info.GetPTY().ReleaseMasterFileDescriptor(); + if (pty_fd != PseudoTerminal::invalid_fd) { + process_sp->SetSTDIOFileDescriptor(pty_fd); + LLDB_LOG(log, "hooked up STDIO pty to process"); + } else + LLDB_LOG(log, "not using process STDIO pty"); + } else { + LLDB_LOG(log, "process launch failed: {0}", error); + // FIXME figure out appropriate cleanup here. Do we delete the target? Do + // we delete the process? Does our caller do that? + } + + return process_sp; } void PlatformOpenBSD::CalculateTrapHandlerSymbolNames() { m_trap_handlers.push_back(ConstString("_sigtramp")); } -uint64_t PlatformOpenBSD::ConvertMmapFlagsToPlatform(const ArchSpec &arch, - unsigned flags) { +MmapArgList PlatformOpenBSD::GetMmapArgumentList(const ArchSpec &arch, + addr_t addr, addr_t length, + unsigned prot, unsigned flags, + addr_t fd, addr_t offset) { uint64_t flags_platform = 0; if (flags & eMmapFlagsPrivate) flags_platform |= MAP_PRIVATE; if (flags & eMmapFlagsAnon) flags_platform |= MAP_ANON; - return flags_platform; + + MmapArgList args({addr, length, prot, flags_platform, fd, offset}); + return args; } diff --git a/gnu/llvm/tools/lldb/source/Plugins/Platform/OpenBSD/PlatformOpenBSD.h b/gnu/llvm/tools/lldb/source/Plugins/Platform/OpenBSD/PlatformOpenBSD.h index 55f6451e236..32a1a991b62 100644 --- a/gnu/llvm/tools/lldb/source/Plugins/Platform/OpenBSD/PlatformOpenBSD.h +++ b/gnu/llvm/tools/lldb/source/Plugins/Platform/OpenBSD/PlatformOpenBSD.h @@ -51,10 +51,15 @@ public: bool CanDebugProcess() override; + lldb::ProcessSP DebugProcess(ProcessLaunchInfo &launch_info, Debugger &debugger, + Target *target, Status &error) override; + void CalculateTrapHandlerSymbolNames() override; - uint64_t ConvertMmapFlagsToPlatform(const ArchSpec &arch, - unsigned flags) override; + MmapArgList GetMmapArgumentList(const ArchSpec &arch, lldb::addr_t addr, + lldb::addr_t length, unsigned prot, + unsigned flags, lldb::addr_t fd, + lldb::addr_t offset) override; private: DISALLOW_COPY_AND_ASSIGN(PlatformOpenBSD); diff --git a/gnu/llvm/tools/lldb/source/Plugins/Process/CMakeLists.txt b/gnu/llvm/tools/lldb/source/Plugins/Process/CMakeLists.txt index 62abd75a43b..bc80f93a271 100644 --- a/gnu/llvm/tools/lldb/source/Plugins/Process/CMakeLists.txt +++ b/gnu/llvm/tools/lldb/source/Plugins/Process/CMakeLists.txt @@ -7,13 +7,16 @@ elseif (CMAKE_SYSTEM_NAME MATCHES "FreeBSD") elseif (CMAKE_SYSTEM_NAME MATCHES "NetBSD") add_subdirectory(NetBSD) add_subdirectory(POSIX) +elseif (CMAKE_SYSTEM_NAME MATCHES "OpenBSD") + add_subdirectory(OpenBSD) + add_subdirectory(POSIX) elseif (CMAKE_SYSTEM_NAME MATCHES "Windows") add_subdirectory(Windows/Common) elseif (CMAKE_SYSTEM_NAME MATCHES "Darwin") add_subdirectory(MacOSX-Kernel) - add_subdirectory(mach-core) endif() add_subdirectory(gdb-remote) add_subdirectory(Utility) add_subdirectory(elf-core) +add_subdirectory(mach-core) add_subdirectory(minidump) diff --git a/gnu/llvm/tools/lldb/source/Plugins/Process/OpenBSD/CMakeLists.txt b/gnu/llvm/tools/lldb/source/Plugins/Process/OpenBSD/CMakeLists.txt new file mode 100644 index 00000000000..4eb5697ab83 --- /dev/null +++ b/gnu/llvm/tools/lldb/source/Plugins/Process/OpenBSD/CMakeLists.txt @@ -0,0 +1,17 @@ +add_lldb_library(lldbPluginProcessOpenBSD PLUGIN + NativeProcessOpenBSD.cpp + NativeRegisterContextOpenBSD.cpp + NativeRegisterContextOpenBSD_x86_64.cpp + NativeThreadOpenBSD.cpp + + LINK_LIBS + lldbCore + lldbHost + lldbSymbol + lldbTarget + lldbUtility + lldbPluginProcessPOSIX + lldbPluginProcessUtility + LINK_COMPONENTS + Support + ) diff --git a/gnu/llvm/tools/lldb/source/Plugins/Process/OpenBSD/NativeProcessOpenBSD.cpp b/gnu/llvm/tools/lldb/source/Plugins/Process/OpenBSD/NativeProcessOpenBSD.cpp new file mode 100644 index 00000000000..eeb05cfa495 --- /dev/null +++ b/gnu/llvm/tools/lldb/source/Plugins/Process/OpenBSD/NativeProcessOpenBSD.cpp @@ -0,0 +1,576 @@ +//===-- NativeProcessOpenBSD.cpp ------------------------------- -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "NativeProcessOpenBSD.h" + +// C Includes +#include <errno.h> +#define _DYN_LOADER +#include <elf.h> +#include <util.h> + +// C++ Includes + +#include "Plugins/Process/POSIX/ProcessPOSIXLog.h" +#include "lldb/Host/HostProcess.h" +#include "lldb/Host/common/NativeRegisterContext.h" +#include "lldb/Host/posix/ProcessLauncherPosixFork.h" +#include "llvm/Support/Errno.h" +#include "lldb/Target/Process.h" +#include "lldb/Utility/State.h" + +// System includes - They have to be included after framework includes because +// they define some macros which collide with variable names in other modules +// clang-format off +#include <sys/types.h> +#include <sys/ptrace.h> +#include <sys/sysctl.h> +#include <sys/wait.h> +// clang-format on + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::process_openbsd; +using namespace llvm; + +// Simple helper function to ensure flags are enabled on the given file +// descriptor. +static Status EnsureFDFlags(int fd, int flags) { + Status error; + + int status = fcntl(fd, F_GETFL); + if (status == -1) { + error.SetErrorToErrno(); + return error; + } + + if (fcntl(fd, F_SETFL, status | flags) == -1) { + error.SetErrorToErrno(); + return error; + } + + return error; +} + +// ----------------------------------------------------------------------------- +// Public Static Methods +// ----------------------------------------------------------------------------- + +llvm::Expected<std::unique_ptr<NativeProcessProtocol>> +NativeProcessOpenBSD::Factory::Launch(ProcessLaunchInfo &launch_info, + NativeDelegate &native_delegate, + MainLoop &mainloop) const { + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); + + Status status; + ::pid_t pid = ProcessLauncherPosixFork() + .LaunchProcess(launch_info, status) + .GetProcessId(); + LLDB_LOG(log, "pid = {0:x}", pid); + if (status.Fail()) { + LLDB_LOG(log, "failed to launch process: {0}", status); + return status.ToError(); + } + + // Wait for the child process to trap on its call to execve. + int wstatus; + ::pid_t wpid = llvm::sys::RetryAfterSignal(-1, ::waitpid, pid, &wstatus, 0); + assert(wpid == pid); + (void)wpid; + if (!WIFSTOPPED(wstatus)) { + LLDB_LOG(log, "Could not sync with inferior process: wstatus={1}", + WaitStatus::Decode(wstatus)); + return llvm::make_error<StringError>("Could not sync with inferior process", + llvm::inconvertibleErrorCode()); + } + LLDB_LOG(log, "inferior started, now in stopped state"); + + ProcessInstanceInfo Info; + if (!Host::GetProcessInfo(pid, Info)) { + return llvm::make_error<StringError>("Cannot get process architecture", + llvm::inconvertibleErrorCode()); + } + + // Set the architecture to the exe architecture. + LLDB_LOG(log, "pid = {0:x}, detected architecture {1}", pid, + Info.GetArchitecture().GetArchitectureName()); + + std::unique_ptr<NativeProcessOpenBSD> process_up(new NativeProcessOpenBSD( + pid, launch_info.GetPTY().ReleaseMasterFileDescriptor(), native_delegate, + Info.GetArchitecture(), mainloop)); + + status = process_up->ReinitializeThreads(); + if (status.Fail()) + return status.ToError(); + + for (const auto &thread : process_up->m_threads) + static_cast<NativeThreadOpenBSD &>(*thread).SetStoppedBySignal(SIGSTOP); + process_up->SetState(StateType::eStateStopped, false); + + return std::move(process_up); +} + +llvm::Expected<std::unique_ptr<NativeProcessProtocol>> +NativeProcessOpenBSD::Factory::Attach( + lldb::pid_t pid, NativeProcessProtocol::NativeDelegate &native_delegate, + MainLoop &mainloop) const { + + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); + LLDB_LOG(log, "pid = {0:x}", pid); + + // Retrieve the architecture for the running process. + ProcessInstanceInfo Info; + if (!Host::GetProcessInfo(pid, Info)) { + return llvm::make_error<StringError>("Cannot get process architecture", + llvm::inconvertibleErrorCode()); + } + + std::unique_ptr<NativeProcessOpenBSD> process_up(new NativeProcessOpenBSD( + pid, -1, native_delegate, Info.GetArchitecture(), mainloop)); + + Status status = process_up->Attach(); + if (!status.Success()) + return status.ToError(); + + return std::move(process_up); +} + +// ----------------------------------------------------------------------------- +// Public Instance Methods +// ----------------------------------------------------------------------------- + +NativeProcessOpenBSD::NativeProcessOpenBSD(::pid_t pid, int terminal_fd, + NativeDelegate &delegate, + const ArchSpec &arch, + MainLoop &mainloop) + : NativeProcessProtocol(pid, terminal_fd, delegate), m_arch(arch) { + if (m_terminal_fd != -1) { + Status status = EnsureFDFlags(m_terminal_fd, O_NONBLOCK); + assert(status.Success()); + } + + Status status; + m_sigchld_handle = mainloop.RegisterSignal( + SIGCHLD, [this](MainLoopBase &) { SigchldHandler(); }, status); + assert(m_sigchld_handle && status.Success()); +} + +// Handles all waitpid events from the inferior process. +void NativeProcessOpenBSD::MonitorCallback(lldb::pid_t pid, int signal) { + switch (signal) { + case SIGTRAP: + return MonitorSIGTRAP(pid); + default: + return MonitorSignal(pid, signal); + } +} + +void NativeProcessOpenBSD::MonitorExited(lldb::pid_t pid, WaitStatus status) { + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); + + LLDB_LOG(log, "got exit signal({0}) , pid = {1}", status, pid); + + /* Stop Tracking All Threads attached to Process */ + m_threads.clear(); + + SetExitStatus(status, true); + + // Notify delegate that our process has exited. + SetState(StateType::eStateExited, true); +} + +void NativeProcessOpenBSD::MonitorSIGTRAP(lldb::pid_t pid) { + for (const auto &thread : m_threads) { + static_cast<NativeThreadOpenBSD &>(*thread).SetStoppedByBreakpoint(); + FixupBreakpointPCAsNeeded(static_cast<NativeThreadOpenBSD &>(*thread)); + } + SetState(StateType::eStateStopped, true); +} + + +void NativeProcessOpenBSD::MonitorSignal(lldb::pid_t pid, int signal) { + for (const auto &thread : m_threads) { + static_cast<NativeThreadOpenBSD &>(*thread).SetStoppedBySignal(signal); + } + SetState(StateType::eStateStopped, true); +} + +Status NativeProcessOpenBSD::PtraceWrapper(int req, lldb::pid_t pid, void *addr, + int data, int *result) { + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE)); + Status error; + int ret; + + errno = 0; + ret = ptrace(req, static_cast<::pid_t>(pid), (caddr_t)addr, data); + + if (ret == -1) + error.SetErrorToErrno(); + + if (result) + *result = ret; + + LLDB_LOG(log, "ptrace({0}, {1}, {2}, {3})={4:x}", req, pid, addr, data, ret); + + if (error.Fail()) + LLDB_LOG(log, "ptrace() failed: {0}", error); + + return error; +} + +Status NativeProcessOpenBSD::Resume(const ResumeActionList &resume_actions) { + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); + LLDB_LOG(log, "pid {0}", GetID()); + + const auto &thread = m_threads[0]; + const ResumeAction *const action = + resume_actions.GetActionForThread(thread->GetID(), true); + + if (action == nullptr) { + LLDB_LOG(log, "no action specified for pid {0} tid {1}", GetID(), + thread->GetID()); + return Status(); + } + + Status error; + + switch (action->state) { + case eStateRunning: { + // Run the thread, possibly feeding it the signal. + error = NativeProcessOpenBSD::PtraceWrapper(PT_CONTINUE, GetID(), (void *)1, + action->signal); + if (!error.Success()) + return error; + for (const auto &thread : m_threads) + static_cast<NativeThreadOpenBSD &>(*thread).SetRunning(); + SetState(eStateRunning, true); + break; + } + case eStateStepping: + // Run the thread, possibly feeding it the signal. + error = NativeProcessOpenBSD::PtraceWrapper(PT_STEP, GetID(), (void *)1, + action->signal); + if (!error.Success()) + return error; + for (const auto &thread : m_threads) + static_cast<NativeThreadOpenBSD &>(*thread).SetStepping(); + SetState(eStateStepping, true); + break; + + case eStateSuspended: + case eStateStopped: + llvm_unreachable("Unexpected state"); + + default: + return Status("NativeProcessOpenBSD::%s (): unexpected state %s specified " + "for pid %" PRIu64 ", tid %" PRIu64, + __FUNCTION__, StateAsCString(action->state), GetID(), + thread->GetID()); + } + + return Status(); +} + +Status NativeProcessOpenBSD::Halt() { + Status error; + + if (kill(GetID(), SIGSTOP) != 0) + error.SetErrorToErrno(); + + return error; +} + +Status NativeProcessOpenBSD::Detach() { + Status error; + + // Stop monitoring the inferior. + m_sigchld_handle.reset(); + + // Tell ptrace to detach from the process. + if (GetID() == LLDB_INVALID_PROCESS_ID) + return error; + + return PtraceWrapper(PT_DETACH, GetID()); +} + +Status NativeProcessOpenBSD::Signal(int signo) { + Status error; + + if (kill(GetID(), signo)) + error.SetErrorToErrno(); + + return error; +} + +Status NativeProcessOpenBSD::Kill() { + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); + LLDB_LOG(log, "pid {0}", GetID()); + + Status error; + + switch (m_state) { + case StateType::eStateInvalid: + case StateType::eStateExited: + case StateType::eStateCrashed: + case StateType::eStateDetached: + case StateType::eStateUnloaded: + // Nothing to do - the process is already dead. + LLDB_LOG(log, "ignored for PID {0} due to current state: {1}", GetID(), + StateAsCString(m_state)); + return error; + + case StateType::eStateConnected: + case StateType::eStateAttaching: + case StateType::eStateLaunching: + case StateType::eStateStopped: + case StateType::eStateRunning: + case StateType::eStateStepping: + case StateType::eStateSuspended: + // We can try to kill a process in these states. + break; + } + + if (kill(GetID(), SIGKILL) != 0) { + error.SetErrorToErrno(); + return error; + } + + return error; +} + +Status NativeProcessOpenBSD::GetMemoryRegionInfo(lldb::addr_t load_addr, + MemoryRegionInfo &range_info) { + return Status("Unimplemented"); +} + +Status NativeProcessOpenBSD::PopulateMemoryRegionCache() { + return Status("Unimplemented"); +} + +Status NativeProcessOpenBSD::AllocateMemory(size_t size, uint32_t permissions, + lldb::addr_t &addr) { + return Status("Unimplemented"); +} + +Status NativeProcessOpenBSD::DeallocateMemory(lldb::addr_t addr) { + return Status("Unimplemented"); +} + +lldb::addr_t NativeProcessOpenBSD::GetSharedLibraryInfoAddress() { + // punt on this for now + return LLDB_INVALID_ADDRESS; +} + +size_t NativeProcessOpenBSD::UpdateThreads() { return m_threads.size(); } + +Status NativeProcessOpenBSD::SetBreakpoint(lldb::addr_t addr, uint32_t size, + bool hardware) { + if (hardware) + return Status("NativeProcessOpenBSD does not support hardware breakpoints"); + else + return SetSoftwareBreakpoint(addr, size); +} + +Status NativeProcessOpenBSD::GetLoadedModuleFileSpec(const char *module_path, + FileSpec &file_spec) { + return Status("Unimplemented"); +} + +Status NativeProcessOpenBSD::GetFileLoadAddress(const llvm::StringRef &file_name, + lldb::addr_t &load_addr) { + load_addr = LLDB_INVALID_ADDRESS; + return Status(); +} + +void NativeProcessOpenBSD::SigchldHandler() { + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); + // Process all pending waitpid notifications. + int status; + ::pid_t wait_pid = + llvm::sys::RetryAfterSignal(-1, waitpid, GetID(), &status, WNOHANG); + + if (wait_pid == 0) + return; // We are done. + + if (wait_pid == -1) { + Status error(errno, eErrorTypePOSIX); + LLDB_LOG(log, "waitpid ({0}, &status, _) failed: {1}", GetID(), error); + } + + WaitStatus wait_status = WaitStatus::Decode(status); + bool exited = wait_status.type == WaitStatus::Exit || + (wait_status.type == WaitStatus::Signal && + wait_pid == static_cast<::pid_t>(GetID())); + + LLDB_LOG(log, + "waitpid ({0}, &status, _) => pid = {1}, status = {2}, exited = {3}", + GetID(), wait_pid, status, exited); + + if (exited) + MonitorExited(wait_pid, wait_status); + else { + assert(wait_status.type == WaitStatus::Stop); + MonitorCallback(wait_pid, wait_status.status); + } +} + +bool NativeProcessOpenBSD::HasThreadNoLock(lldb::tid_t thread_id) { + for (const auto &thread : m_threads) { + assert(thread && "thread list should not contain NULL threads"); + if (thread->GetID() == thread_id) { + // We have this thread. + return true; + } + } + + // We don't have this thread. + return false; +} + +NativeThreadOpenBSD &NativeProcessOpenBSD::AddThread(lldb::tid_t thread_id) { + + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD)); + LLDB_LOG(log, "pid {0} adding thread with tid {1}", GetID(), thread_id); + + assert(!HasThreadNoLock(thread_id) && + "attempted to add a thread by id that already exists"); + + // If this is the first thread, save it as the current thread + if (m_threads.empty()) + SetCurrentThreadID(thread_id); + + m_threads.push_back(llvm::make_unique<NativeThreadOpenBSD>(*this, thread_id)); + return static_cast<NativeThreadOpenBSD &>(*m_threads.back()); +} + +Status NativeProcessOpenBSD::Attach() { + // Attach to the requested process. + // An attach will cause the thread to stop with a SIGSTOP. + Status status = PtraceWrapper(PT_ATTACH, m_pid); + if (status.Fail()) + return status; + + int wstatus; + // At this point we should have a thread stopped if waitpid succeeds. + if ((wstatus = waitpid(m_pid, NULL, 0)) < 0) + return Status(errno, eErrorTypePOSIX); + + /* Initialize threads */ + status = ReinitializeThreads(); + if (status.Fail()) + return status; + + for (const auto &thread : m_threads) + static_cast<NativeThreadOpenBSD &>(*thread).SetStoppedBySignal(SIGSTOP); + + // Let our process instance know the thread has stopped. + SetState(StateType::eStateStopped); + return Status(); +} + +Status NativeProcessOpenBSD::ReadMemory(lldb::addr_t addr, void *buf, + size_t size, size_t &bytes_read) { + unsigned char *dst = static_cast<unsigned char *>(buf); + struct ptrace_io_desc io; + + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_MEMORY)); + LLDB_LOG(log, "addr = {0}, buf = {1}, size = {2}", addr, buf, size); + + bytes_read = 0; + io.piod_op = PIOD_READ_D; + io.piod_len = size; + + do { + io.piod_offs = (void *)(addr + bytes_read); + io.piod_addr = dst + bytes_read; + + Status error = NativeProcessOpenBSD::PtraceWrapper(PT_IO, GetID(), &io); + if (error.Fail()) + return error; + + bytes_read = io.piod_len; + io.piod_len = size - bytes_read; + } while (bytes_read < size); + + return Status(); +} + +Status NativeProcessOpenBSD::WriteMemory(lldb::addr_t addr, const void *buf, + size_t size, size_t &bytes_written) { + const unsigned char *src = static_cast<const unsigned char *>(buf); + Status error; + struct ptrace_io_desc io; + + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_MEMORY)); + LLDB_LOG(log, "addr = {0}, buf = {1}, size = {2}", addr, buf, size); + + bytes_written = 0; + io.piod_op = PIOD_WRITE_D; + io.piod_len = size; + + do { + io.piod_addr = const_cast<void *>(static_cast<const void *>(src + bytes_written)); + io.piod_offs = (void *)(addr + bytes_written); + + Status error = NativeProcessOpenBSD::PtraceWrapper(PT_IO, GetID(), &io); + if (error.Fail()) + return error; + + bytes_written = io.piod_len; + io.piod_len = size - bytes_written; + } while (bytes_written < size); + + return error; +} + +llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> +NativeProcessOpenBSD::GetAuxvData() const { + size_t auxv_size = 100 * sizeof(AuxInfo); + + ErrorOr<std::unique_ptr<WritableMemoryBuffer>> buf = + llvm::WritableMemoryBuffer::getNewMemBuffer(auxv_size); + + struct ptrace_io_desc io; + io.piod_op = PIOD_READ_AUXV; + io.piod_offs = 0; + io.piod_addr = static_cast<void *>(buf.get()->getBufferStart()); + io.piod_len = auxv_size; + + Status error = NativeProcessOpenBSD::PtraceWrapper(PT_IO, GetID(), &io); + + if (error.Fail()) + return std::error_code(error.GetError(), std::generic_category()); + + if (io.piod_len < 1) + return std::error_code(ECANCELED, std::generic_category()); + + return std::move(buf); +} + +Status NativeProcessOpenBSD::ReinitializeThreads() { + // Clear old threads + m_threads.clear(); + + // Initialize new thread + struct ptrace_thread_state info = {}; + Status error = PtraceWrapper(PT_GET_THREAD_FIRST, GetID(), &info, sizeof(info)); + if (error.Fail()) { + return error; + } + // Reinitialize from scratch threads and register them in process + while (info.pts_tid > 0) { + AddThread(info.pts_tid); + error = PtraceWrapper(PT_GET_THREAD_NEXT, GetID(), &info, sizeof(info)); + if (error.Fail() && errno != 0) { + return error; + } + } + + return error; +} diff --git a/gnu/llvm/tools/lldb/source/Plugins/Process/OpenBSD/NativeProcessOpenBSD.h b/gnu/llvm/tools/lldb/source/Plugins/Process/OpenBSD/NativeProcessOpenBSD.h new file mode 100644 index 00000000000..5aeb131e18e --- /dev/null +++ b/gnu/llvm/tools/lldb/source/Plugins/Process/OpenBSD/NativeProcessOpenBSD.h @@ -0,0 +1,123 @@ +//===-- NativeProcessOpenBSD.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_NativeProcessOpenBSD_H_ +#define liblldb_NativeProcessOpenBSD_H_ + +#include "lldb/Target/MemoryRegionInfo.h" +#include "lldb/Utility/ArchSpec.h" +#include "lldb/Utility/FileSpec.h" + +#include "NativeThreadOpenBSD.h" +#include "lldb/Host/common/NativeProcessProtocol.h" + +namespace lldb_private { +namespace process_openbsd { +/// @class NativeProcessOpenBSD +/// Manages communication with the inferior (debugee) process. +/// +/// Upon construction, this class prepares and launches an inferior process +/// for debugging. +/// +/// Changes in the inferior process state are broadcasted. +class NativeProcessOpenBSD : public NativeProcessProtocol { +public: + class Factory : public NativeProcessProtocol::Factory { + public: + llvm::Expected<std::unique_ptr<NativeProcessProtocol>> + Launch(ProcessLaunchInfo &launch_info, NativeDelegate &native_delegate, + MainLoop &mainloop) const override; + + llvm::Expected<std::unique_ptr<NativeProcessProtocol>> + Attach(lldb::pid_t pid, NativeDelegate &native_delegate, + MainLoop &mainloop) const override; + }; + + // --------------------------------------------------------------------- + // NativeProcessProtocol Interface + // --------------------------------------------------------------------- + Status Resume(const ResumeActionList &resume_actions) override; + + Status Halt() override; + + Status Detach() override; + + Status Signal(int signo) override; + + Status Kill() override; + + Status GetMemoryRegionInfo(lldb::addr_t load_addr, + MemoryRegionInfo &range_info) override; + + Status ReadMemory(lldb::addr_t addr, void *buf, size_t size, + size_t &bytes_read) override; + + Status WriteMemory(lldb::addr_t addr, const void *buf, size_t size, + size_t &bytes_written) override; + + Status AllocateMemory(size_t size, uint32_t permissions, + lldb::addr_t &addr) override; + + Status DeallocateMemory(lldb::addr_t addr) override; + + lldb::addr_t GetSharedLibraryInfoAddress() override; + + size_t UpdateThreads() override; + + const ArchSpec &GetArchitecture() const override { return m_arch; } + + Status SetBreakpoint(lldb::addr_t addr, uint32_t size, + bool hardware) override; + + Status GetLoadedModuleFileSpec(const char *module_path, + FileSpec &file_spec) override; + + Status GetFileLoadAddress(const llvm::StringRef &file_name, + lldb::addr_t &load_addr) override; + + llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> + GetAuxvData() const override; + + // --------------------------------------------------------------------- + // Interface used by NativeRegisterContext-derived classes. + // --------------------------------------------------------------------- + static Status PtraceWrapper(int req, lldb::pid_t pid, void *addr = nullptr, + int data = 0, int *result = nullptr); + +private: + MainLoop::SignalHandleUP m_sigchld_handle; + ArchSpec m_arch; + std::vector<std::pair<MemoryRegionInfo, FileSpec>> m_mem_region_cache; + + // --------------------------------------------------------------------- + // Private Instance Methods + // --------------------------------------------------------------------- + NativeProcessOpenBSD(::pid_t pid, int terminal_fd, NativeDelegate &delegate, + const ArchSpec &arch, MainLoop &mainloop); + + bool HasThreadNoLock(lldb::tid_t thread_id); + + NativeThreadOpenBSD &AddThread(lldb::tid_t thread_id); + + void MonitorCallback(lldb::pid_t pid, int signal); + void MonitorExited(lldb::pid_t pid, WaitStatus status); + void MonitorSIGTRAP(lldb::pid_t pid); + void MonitorSignal(lldb::pid_t pid, int signal); + + Status PopulateMemoryRegionCache(); + void SigchldHandler(); + + Status Attach(); + Status ReinitializeThreads(); +}; + +} // namespace process_openbsd +} // namespace lldb_private + +#endif // #ifndef liblldb_NativeProcessOpenBSD_H_ diff --git a/gnu/llvm/tools/lldb/source/Plugins/Process/OpenBSD/NativeRegisterContextOpenBSD.cpp b/gnu/llvm/tools/lldb/source/Plugins/Process/OpenBSD/NativeRegisterContextOpenBSD.cpp new file mode 100644 index 00000000000..fb70b028e3d --- /dev/null +++ b/gnu/llvm/tools/lldb/source/Plugins/Process/OpenBSD/NativeRegisterContextOpenBSD.cpp @@ -0,0 +1,86 @@ +//===-- NativeRegisterContextOpenBSD.cpp -------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "NativeRegisterContextOpenBSD.h" + +#include "lldb/Host/common/NativeProcessProtocol.h" + +using namespace lldb_private; +using namespace lldb_private::process_openbsd; + +// clang-format off +#include <sys/types.h> +#include <sys/ptrace.h> +// clang-format on + +NativeRegisterContextOpenBSD::NativeRegisterContextOpenBSD( + NativeThreadProtocol &native_thread, + RegisterInfoInterface *reg_info_interface_p) + : NativeRegisterContextRegisterInfo(native_thread, + reg_info_interface_p) {} + +Status NativeRegisterContextOpenBSD::ReadGPR() { + void *buf = GetGPRBuffer(); + if (!buf) + return Status("GPR buffer is NULL"); + + return DoReadGPR(buf); +} + +Status NativeRegisterContextOpenBSD::WriteGPR() { + void *buf = GetGPRBuffer(); + if (!buf) + return Status("GPR buffer is NULL"); + + return DoWriteGPR(buf); +} + +Status NativeRegisterContextOpenBSD::ReadFPR() { + void *buf = GetFPRBuffer(); + if (!buf) + return Status("FPR buffer is NULL"); + + return DoReadFPR(buf); +} + +Status NativeRegisterContextOpenBSD::WriteFPR() { + void *buf = GetFPRBuffer(); + if (!buf) + return Status("FPR buffer is NULL"); + + return DoWriteFPR(buf); +} + +Status NativeRegisterContextOpenBSD::DoReadGPR(void *buf) { + return NativeProcessOpenBSD::PtraceWrapper(PT_GETREGS, GetProcessPid(), buf, + m_thread.GetID()); +} + +Status NativeRegisterContextOpenBSD::DoWriteGPR(void *buf) { + return NativeProcessOpenBSD::PtraceWrapper(PT_SETREGS, GetProcessPid(), buf, + m_thread.GetID()); +} + +Status NativeRegisterContextOpenBSD::DoReadFPR(void *buf) { + return NativeProcessOpenBSD::PtraceWrapper(PT_GETFPREGS, GetProcessPid(), buf, + m_thread.GetID()); +} + +Status NativeRegisterContextOpenBSD::DoWriteFPR(void *buf) { + return NativeProcessOpenBSD::PtraceWrapper(PT_SETFPREGS, GetProcessPid(), buf, + m_thread.GetID()); +} + +NativeProcessOpenBSD &NativeRegisterContextOpenBSD::GetProcess() { + return static_cast<NativeProcessOpenBSD &>(m_thread.GetProcess()); +} + +::pid_t NativeRegisterContextOpenBSD::GetProcessPid() { + return GetProcess().GetID(); +} diff --git a/gnu/llvm/tools/lldb/source/Plugins/Process/OpenBSD/NativeRegisterContextOpenBSD.h b/gnu/llvm/tools/lldb/source/Plugins/Process/OpenBSD/NativeRegisterContextOpenBSD.h new file mode 100644 index 00000000000..013fe893fc1 --- /dev/null +++ b/gnu/llvm/tools/lldb/source/Plugins/Process/OpenBSD/NativeRegisterContextOpenBSD.h @@ -0,0 +1,63 @@ +//===-- NativeRegisterContextOpenBSD.h ---------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef lldb_NativeRegisterContextOpenBSD_h +#define lldb_NativeRegisterContextOpenBSD_h + +#include "lldb/Host/common/NativeThreadProtocol.h" + +#include "Plugins/Process/OpenBSD/NativeProcessOpenBSD.h" +#include "Plugins/Process/Utility/NativeRegisterContextRegisterInfo.h" + +namespace lldb_private { +namespace process_openbsd { + +class NativeRegisterContextOpenBSD : public NativeRegisterContextRegisterInfo { +public: + NativeRegisterContextOpenBSD(NativeThreadProtocol &native_thread, + RegisterInfoInterface *reg_info_interface_p); + + // This function is implemented in the NativeRegisterContextOpenBSD_* + // subclasses to create a new instance of the host specific + // NativeRegisterContextOpenBSD. The implementations can't collide as only one + // NativeRegisterContextOpenBSD_* variant should be compiled into the final + // executable. + static NativeRegisterContextOpenBSD * + CreateHostNativeRegisterContextOpenBSD(const ArchSpec &target_arch, + NativeThreadProtocol &native_thread); + +protected: + virtual Status ReadGPR(); + virtual Status WriteGPR(); + + virtual Status ReadFPR(); + virtual Status WriteFPR(); + + virtual void *GetGPRBuffer() { return nullptr; } + virtual size_t GetGPRSize() { + return GetRegisterInfoInterface().GetGPRSize(); + } + + virtual void *GetFPRBuffer() { return nullptr; } + virtual size_t GetFPRSize() { return 0; } + + virtual Status DoReadGPR(void *buf); + virtual Status DoWriteGPR(void *buf); + + virtual Status DoReadFPR(void *buf); + virtual Status DoWriteFPR(void *buf); + + virtual NativeProcessOpenBSD &GetProcess(); + virtual ::pid_t GetProcessPid(); +}; + +} // namespace process_openbsd +} // namespace lldb_private + +#endif // #ifndef lldb_NativeRegisterContextOpenBSD_h diff --git a/gnu/llvm/tools/lldb/source/Plugins/Process/OpenBSD/NativeRegisterContextOpenBSD_x86_64.cpp b/gnu/llvm/tools/lldb/source/Plugins/Process/OpenBSD/NativeRegisterContextOpenBSD_x86_64.cpp new file mode 100644 index 00000000000..c6102fd38e4 --- /dev/null +++ b/gnu/llvm/tools/lldb/source/Plugins/Process/OpenBSD/NativeRegisterContextOpenBSD_x86_64.cpp @@ -0,0 +1,861 @@ +//===-- NativeRegisterContextOpenBSD_x86_64.cpp ---------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#if defined(__x86_64__) + +#include <elf.h> +#include <err.h> +#include <stdint.h> +#include <stdlib.h> + +#include "NativeRegisterContextOpenBSD_x86_64.h" + +#include "lldb/Host/HostInfo.h" +#include "lldb/Utility/DataBufferHeap.h" +#include "lldb/Utility/Log.h" +#include "lldb/Utility/RegisterValue.h" +#include "lldb/Utility/Status.h" + +#include "Plugins/Process/Utility/RegisterContextOpenBSD_x86_64.h" + +// clang-format off +#include <sys/types.h> +#include <sys/sysctl.h> +#include <sys/time.h> +#include <machine/cpu.h> +// clang-format on + +using namespace lldb_private; +using namespace lldb_private::process_openbsd; + +// ---------------------------------------------------------------------------- +// Private namespace. +// ---------------------------------------------------------------------------- + +namespace { +// x86 64-bit general purpose registers. +static const uint32_t g_gpr_regnums_x86_64[] = { + lldb_rax_x86_64, lldb_rbx_x86_64, lldb_rcx_x86_64, lldb_rdx_x86_64, + lldb_rdi_x86_64, lldb_rsi_x86_64, lldb_rbp_x86_64, lldb_rsp_x86_64, + lldb_r8_x86_64, lldb_r9_x86_64, lldb_r10_x86_64, lldb_r11_x86_64, + lldb_r12_x86_64, lldb_r13_x86_64, lldb_r14_x86_64, lldb_r15_x86_64, + lldb_rip_x86_64, lldb_rflags_x86_64, lldb_cs_x86_64, lldb_fs_x86_64, + lldb_gs_x86_64, lldb_ss_x86_64, lldb_ds_x86_64, lldb_es_x86_64, + lldb_eax_x86_64, lldb_ebx_x86_64, lldb_ecx_x86_64, lldb_edx_x86_64, + lldb_edi_x86_64, lldb_esi_x86_64, lldb_ebp_x86_64, lldb_esp_x86_64, + lldb_r8d_x86_64, // Low 32 bits or r8 + lldb_r9d_x86_64, // Low 32 bits or r9 + lldb_r10d_x86_64, // Low 32 bits or r10 + lldb_r11d_x86_64, // Low 32 bits or r11 + lldb_r12d_x86_64, // Low 32 bits or r12 + lldb_r13d_x86_64, // Low 32 bits or r13 + lldb_r14d_x86_64, // Low 32 bits or r14 + lldb_r15d_x86_64, // Low 32 bits or r15 + lldb_ax_x86_64, lldb_bx_x86_64, lldb_cx_x86_64, lldb_dx_x86_64, + lldb_di_x86_64, lldb_si_x86_64, lldb_bp_x86_64, lldb_sp_x86_64, + lldb_r8w_x86_64, // Low 16 bits or r8 + lldb_r9w_x86_64, // Low 16 bits or r9 + lldb_r10w_x86_64, // Low 16 bits or r10 + lldb_r11w_x86_64, // Low 16 bits or r11 + lldb_r12w_x86_64, // Low 16 bits or r12 + lldb_r13w_x86_64, // Low 16 bits or r13 + lldb_r14w_x86_64, // Low 16 bits or r14 + lldb_r15w_x86_64, // Low 16 bits or r15 + lldb_ah_x86_64, lldb_bh_x86_64, lldb_ch_x86_64, lldb_dh_x86_64, + lldb_al_x86_64, lldb_bl_x86_64, lldb_cl_x86_64, lldb_dl_x86_64, + lldb_dil_x86_64, lldb_sil_x86_64, lldb_bpl_x86_64, lldb_spl_x86_64, + lldb_r8l_x86_64, // Low 8 bits or r8 + lldb_r9l_x86_64, // Low 8 bits or r9 + lldb_r10l_x86_64, // Low 8 bits or r10 + lldb_r11l_x86_64, // Low 8 bits or r11 + lldb_r12l_x86_64, // Low 8 bits or r12 + lldb_r13l_x86_64, // Low 8 bits or r13 + lldb_r14l_x86_64, // Low 8 bits or r14 + lldb_r15l_x86_64, // Low 8 bits or r15 + LLDB_INVALID_REGNUM // register sets need to end with this flag +}; +static_assert((sizeof(g_gpr_regnums_x86_64) / sizeof(g_gpr_regnums_x86_64[0])) - + 1 == + k_num_gpr_registers_x86_64, + "g_gpr_regnums_x86_64 has wrong number of register infos"); + +// Number of register sets provided by this context. +enum { k_num_extended_register_sets = 2, k_num_register_sets = 4 }; + +// Register sets for x86 64-bit. +static const RegisterSet g_reg_sets_x86_64[k_num_register_sets] = { + {"General Purpose Registers", "gpr", k_num_gpr_registers_x86_64, + g_gpr_regnums_x86_64}, +}; + +#define REG_CONTEXT_SIZE (GetRegisterInfoInterface().GetGPRSize()) + +} // namespace + +NativeRegisterContextOpenBSD * +NativeRegisterContextOpenBSD::CreateHostNativeRegisterContextOpenBSD( + const ArchSpec &target_arch, NativeThreadProtocol &native_thread) { + return new NativeRegisterContextOpenBSD_x86_64(target_arch, native_thread); +} + +// ---------------------------------------------------------------------------- +// NativeRegisterContextOpenBSD_x86_64 members. +// ---------------------------------------------------------------------------- + +static RegisterInfoInterface * +CreateRegisterInfoInterface(const ArchSpec &target_arch) { + assert((HostInfo::GetArchitecture().GetAddressByteSize() == 8) && + "Register setting path assumes this is a 64-bit host"); + // X86_64 hosts know how to work with 64-bit and 32-bit EXEs using the x86_64 + // register context. + return new RegisterContextOpenBSD_x86_64(target_arch); +} + +NativeRegisterContextOpenBSD_x86_64::NativeRegisterContextOpenBSD_x86_64( + const ArchSpec &target_arch, NativeThreadProtocol &native_thread) + : NativeRegisterContextOpenBSD(native_thread, + CreateRegisterInfoInterface(target_arch)), + m_gpr_x86_64(), m_fpr_x86_64() {} + +// CONSIDER after local and llgs debugging are merged, register set support can +// be moved into a base x86-64 class with IsRegisterSetAvailable made virtual. +uint32_t NativeRegisterContextOpenBSD_x86_64::GetRegisterSetCount() const { + uint32_t sets = 0; + for (uint32_t set_index = 0; set_index < k_num_register_sets; ++set_index) { + if (GetSetForNativeRegNum(set_index) != -1) + ++sets; + } + + return sets; +} + +const RegisterSet * +NativeRegisterContextOpenBSD_x86_64::GetRegisterSet(uint32_t set_index) const { + switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) { + case llvm::Triple::x86_64: + return &g_reg_sets_x86_64[set_index]; + default: + assert(false && "Unhandled target architecture."); + return nullptr; + } + + return nullptr; +} + +int NativeRegisterContextOpenBSD_x86_64::GetSetForNativeRegNum( + int reg_num) const { + if (reg_num <= k_last_gpr_x86_64) + return GPRegSet; + else if (reg_num <= k_last_fpr_x86_64) + return FPRegSet; + else if (reg_num <= k_last_avx_x86_64) + return -1; // AVX + else if (reg_num <= k_last_mpxr_x86_64) + return -1; // MPXR + else if (reg_num <= k_last_mpxc_x86_64) + return -1; // MPXC + else if (reg_num <= lldb_dr7_x86_64) + return -1; // DBR + else + return -1; +} + +int NativeRegisterContextOpenBSD_x86_64::ReadRegisterSet(uint32_t set) { + switch (set) { + case GPRegSet: + ReadGPR(); + return 0; + case FPRegSet: + ReadFPR(); + return 0; + default: + break; + } + return -1; +} +int NativeRegisterContextOpenBSD_x86_64::WriteRegisterSet(uint32_t set) { + switch (set) { + case GPRegSet: + WriteGPR(); + return 0; + case FPRegSet: + WriteFPR(); + return 0; + default: + break; + } + return -1; +} + +Status +NativeRegisterContextOpenBSD_x86_64::ReadRegister(const RegisterInfo *reg_info, + RegisterValue ®_value) { + Status error; + + if (!reg_info) { + error.SetErrorString("reg_info NULL"); + return error; + } + + const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; + if (reg == LLDB_INVALID_REGNUM) { + // This is likely an internal register for lldb use only and should not be + // directly queried. + error.SetErrorStringWithFormat("register \"%s\" is an internal-only lldb " + "register, cannot read directly", + reg_info->name); + return error; + } + + int set = GetSetForNativeRegNum(reg); + if (set == -1) { + // This is likely an internal register for lldb use only and should not be + // directly queried. + error.SetErrorStringWithFormat("register \"%s\" is in unrecognized set", + reg_info->name); + return error; + } + + if (ReadRegisterSet(set) != 0) { + // This is likely an internal register for lldb use only and should not be + // directly queried. + error.SetErrorStringWithFormat( + "reading register set for register \"%s\" failed", reg_info->name); + return error; + } + + switch (reg) { + case lldb_rax_x86_64: + reg_value = (uint64_t)m_gpr_x86_64.r_rax; + break; + case lldb_rbx_x86_64: + reg_value = (uint64_t)m_gpr_x86_64.r_rbx; + break; + case lldb_rcx_x86_64: + reg_value = (uint64_t)m_gpr_x86_64.r_rcx; + break; + case lldb_rdx_x86_64: + reg_value = (uint64_t)m_gpr_x86_64.r_rdx; + break; + case lldb_rdi_x86_64: + reg_value = (uint64_t)m_gpr_x86_64.r_rdi; + break; + case lldb_rsi_x86_64: + reg_value = (uint64_t)m_gpr_x86_64.r_rsi; + break; + case lldb_rbp_x86_64: + reg_value = (uint64_t)m_gpr_x86_64.r_rbp; + break; + case lldb_rsp_x86_64: + reg_value = (uint64_t)m_gpr_x86_64.r_rsp; + break; + case lldb_r8_x86_64: + reg_value = (uint64_t)m_gpr_x86_64.r_r8; + break; + case lldb_r9_x86_64: + reg_value = (uint64_t)m_gpr_x86_64.r_r9; + break; + case lldb_r10_x86_64: + reg_value = (uint64_t)m_gpr_x86_64.r_r10; + break; + case lldb_r11_x86_64: + reg_value = (uint64_t)m_gpr_x86_64.r_r11; + break; + case lldb_r12_x86_64: + reg_value = (uint64_t)m_gpr_x86_64.r_r12; + break; + case lldb_r13_x86_64: + reg_value = (uint64_t)m_gpr_x86_64.r_r13; + break; + case lldb_r14_x86_64: + reg_value = (uint64_t)m_gpr_x86_64.r_r14; + break; + case lldb_r15_x86_64: + reg_value = (uint64_t)m_gpr_x86_64.r_r15; + break; + case lldb_rip_x86_64: + reg_value = (uint64_t)m_gpr_x86_64.r_rip; + break; + case lldb_rflags_x86_64: + reg_value = (uint64_t)m_gpr_x86_64.r_rflags; + break; + case lldb_cs_x86_64: + reg_value = (uint64_t)m_gpr_x86_64.r_cs; + break; + case lldb_fs_x86_64: + reg_value = (uint64_t)m_gpr_x86_64.r_fs; + break; + case lldb_gs_x86_64: + reg_value = (uint64_t)m_gpr_x86_64.r_gs; + break; + case lldb_ss_x86_64: + reg_value = (uint64_t)m_gpr_x86_64.r_ss; + break; + case lldb_ds_x86_64: + reg_value = (uint64_t)m_gpr_x86_64.r_ds; + break; + case lldb_es_x86_64: + reg_value = (uint64_t)m_gpr_x86_64.r_es; + break; + case lldb_fctrl_x86_64: + reg_value = (uint16_t)m_fpr_x86_64.fxstate.fx_fcw; + break; + case lldb_fstat_x86_64: + reg_value = (uint16_t)m_fpr_x86_64.fxstate.fx_fsw; + break; + case lldb_ftag_x86_64: + reg_value = (uint8_t)m_fpr_x86_64.fxstate.fx_ftw; + break; + case lldb_fop_x86_64: + reg_value = (uint64_t)m_fpr_x86_64.fxstate.fx_fop; + break; + case lldb_fiseg_x86_64: + reg_value = (uint64_t)m_fpr_x86_64.fxstate.fx_rip; + break; + case lldb_fioff_x86_64: + reg_value = (uint32_t)m_fpr_x86_64.fxstate.fx_rip; + break; + case lldb_foseg_x86_64: + reg_value = (uint64_t)m_fpr_x86_64.fxstate.fx_rdp; + break; + case lldb_fooff_x86_64: + reg_value = (uint32_t)m_fpr_x86_64.fxstate.fx_rdp; + break; + case lldb_mxcsr_x86_64: + reg_value = (uint32_t)m_fpr_x86_64.fxstate.fx_mxcsr; + break; + case lldb_mxcsrmask_x86_64: + reg_value = (uint32_t)m_fpr_x86_64.fxstate.fx_mxcsr_mask; + break; + case lldb_st0_x86_64: + case lldb_st1_x86_64: + case lldb_st2_x86_64: + case lldb_st3_x86_64: + case lldb_st4_x86_64: + case lldb_st5_x86_64: + case lldb_st6_x86_64: + case lldb_st7_x86_64: + reg_value.SetBytes(&m_fpr_x86_64.fxstate.fx_st[reg - lldb_st0_x86_64], + reg_info->byte_size, endian::InlHostByteOrder()); + break; + case lldb_mm0_x86_64: + case lldb_mm1_x86_64: + case lldb_mm2_x86_64: + case lldb_mm3_x86_64: + case lldb_mm4_x86_64: + case lldb_mm5_x86_64: + case lldb_mm6_x86_64: + case lldb_mm7_x86_64: + reg_value.SetBytes(&m_fpr_x86_64.fxstate.fx_xmm[reg - lldb_mm0_x86_64], + reg_info->byte_size, endian::InlHostByteOrder()); + break; + case lldb_xmm0_x86_64: + case lldb_xmm1_x86_64: + case lldb_xmm2_x86_64: + case lldb_xmm3_x86_64: + case lldb_xmm4_x86_64: + case lldb_xmm5_x86_64: + case lldb_xmm6_x86_64: + case lldb_xmm7_x86_64: + case lldb_xmm8_x86_64: + case lldb_xmm9_x86_64: + case lldb_xmm10_x86_64: + case lldb_xmm11_x86_64: + case lldb_xmm12_x86_64: + case lldb_xmm13_x86_64: + case lldb_xmm14_x86_64: + case lldb_xmm15_x86_64: + reg_value.SetBytes(&m_fpr_x86_64.fxstate.fx_xmm[reg - lldb_xmm0_x86_64], + reg_info->byte_size, endian::InlHostByteOrder()); + break; + } + + return error; +} + +Status NativeRegisterContextOpenBSD_x86_64::WriteRegister( + const RegisterInfo *reg_info, const RegisterValue ®_value) { + + Status error; + + if (!reg_info) { + error.SetErrorString("reg_info NULL"); + return error; + } + + const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; + if (reg == LLDB_INVALID_REGNUM) { + // This is likely an internal register for lldb use only and should not be + // directly queried. + error.SetErrorStringWithFormat("register \"%s\" is an internal-only lldb " + "register, cannot read directly", + reg_info->name); + return error; + } + + int set = GetSetForNativeRegNum(reg); + if (set == -1) { + // This is likely an internal register for lldb use only and should not be + // directly queried. + error.SetErrorStringWithFormat("register \"%s\" is in unrecognized set", + reg_info->name); + return error; + } + + if (ReadRegisterSet(set) != 0) { + // This is likely an internal register for lldb use only and should not be + // directly queried. + error.SetErrorStringWithFormat( + "reading register set for register \"%s\" failed", reg_info->name); + return error; + } + + switch (reg) { + case lldb_rax_x86_64: + m_gpr_x86_64.r_rax = reg_value.GetAsUInt64(); + break; + case lldb_rbx_x86_64: + m_gpr_x86_64.r_rbx = reg_value.GetAsUInt64(); + break; + case lldb_rcx_x86_64: + m_gpr_x86_64.r_rcx = reg_value.GetAsUInt64(); + break; + case lldb_rdx_x86_64: + m_gpr_x86_64.r_rdx = reg_value.GetAsUInt64(); + break; + case lldb_rdi_x86_64: + m_gpr_x86_64.r_rdi = reg_value.GetAsUInt64(); + break; + case lldb_rsi_x86_64: + m_gpr_x86_64.r_rsi = reg_value.GetAsUInt64(); + break; + case lldb_rbp_x86_64: + m_gpr_x86_64.r_rbp = reg_value.GetAsUInt64(); + break; + case lldb_rsp_x86_64: + m_gpr_x86_64.r_rsp = reg_value.GetAsUInt64(); + break; + case lldb_r8_x86_64: + m_gpr_x86_64.r_r8 = reg_value.GetAsUInt64(); + break; + case lldb_r9_x86_64: + m_gpr_x86_64.r_r9 = reg_value.GetAsUInt64(); + break; + case lldb_r10_x86_64: + m_gpr_x86_64.r_r10 = reg_value.GetAsUInt64(); + break; + case lldb_r11_x86_64: + m_gpr_x86_64.r_r11 = reg_value.GetAsUInt64(); + break; + case lldb_r12_x86_64: + m_gpr_x86_64.r_r12 = reg_value.GetAsUInt64(); + break; + case lldb_r13_x86_64: + m_gpr_x86_64.r_r13 = reg_value.GetAsUInt64(); + break; + case lldb_r14_x86_64: + m_gpr_x86_64.r_r14 = reg_value.GetAsUInt64(); + break; + case lldb_r15_x86_64: + m_gpr_x86_64.r_r15 = reg_value.GetAsUInt64(); + break; + case lldb_rip_x86_64: + m_gpr_x86_64.r_rip = reg_value.GetAsUInt64(); + break; + case lldb_rflags_x86_64: + m_gpr_x86_64.r_rflags = reg_value.GetAsUInt64(); + break; + case lldb_cs_x86_64: + m_gpr_x86_64.r_cs = reg_value.GetAsUInt64(); + break; + case lldb_fs_x86_64: + m_gpr_x86_64.r_fs = reg_value.GetAsUInt64(); + break; + case lldb_gs_x86_64: + m_gpr_x86_64.r_gs = reg_value.GetAsUInt64(); + break; + case lldb_ss_x86_64: + m_gpr_x86_64.r_ss = reg_value.GetAsUInt64(); + break; + case lldb_ds_x86_64: + m_gpr_x86_64.r_ds = reg_value.GetAsUInt64(); + break; + case lldb_es_x86_64: + m_gpr_x86_64.r_es = reg_value.GetAsUInt64(); + break; + case lldb_fctrl_x86_64: + m_fpr_x86_64.fxstate.fx_fcw = reg_value.GetAsUInt16(); + break; + case lldb_fstat_x86_64: + m_fpr_x86_64.fxstate.fx_fsw = reg_value.GetAsUInt16(); + break; + case lldb_ftag_x86_64: + m_fpr_x86_64.fxstate.fx_ftw = reg_value.GetAsUInt8(); + break; + case lldb_fop_x86_64: + m_fpr_x86_64.fxstate.fx_fop = reg_value.GetAsUInt16(); + break; + case lldb_fiseg_x86_64: + m_fpr_x86_64.fxstate.fx_rip = reg_value.GetAsUInt64(); + break; + case lldb_fioff_x86_64: + m_fpr_x86_64.fxstate.fx_rip = reg_value.GetAsUInt32(); + break; + case lldb_foseg_x86_64: + m_fpr_x86_64.fxstate.fx_rdp = reg_value.GetAsUInt64(); + break; + case lldb_fooff_x86_64: + m_fpr_x86_64.fxstate.fx_rdp = reg_value.GetAsUInt32(); + break; + case lldb_mxcsr_x86_64: + m_fpr_x86_64.fxstate.fx_mxcsr = reg_value.GetAsUInt32(); + break; + case lldb_mxcsrmask_x86_64: + m_fpr_x86_64.fxstate.fx_mxcsr_mask = reg_value.GetAsUInt32(); + break; + case lldb_st0_x86_64: + case lldb_st1_x86_64: + case lldb_st2_x86_64: + case lldb_st3_x86_64: + case lldb_st4_x86_64: + case lldb_st5_x86_64: + case lldb_st6_x86_64: + case lldb_st7_x86_64: + ::memcpy(&m_fpr_x86_64.fxstate.fx_st[reg - lldb_st0_x86_64], + reg_value.GetBytes(), reg_value.GetByteSize()); + break; + case lldb_mm0_x86_64: + case lldb_mm1_x86_64: + case lldb_mm2_x86_64: + case lldb_mm3_x86_64: + case lldb_mm4_x86_64: + case lldb_mm5_x86_64: + case lldb_mm6_x86_64: + case lldb_mm7_x86_64: + ::memcpy(&m_fpr_x86_64.fxstate.fx_xmm[reg - lldb_mm0_x86_64], + reg_value.GetBytes(), reg_value.GetByteSize()); + break; + case lldb_xmm0_x86_64: + case lldb_xmm1_x86_64: + case lldb_xmm2_x86_64: + case lldb_xmm3_x86_64: + case lldb_xmm4_x86_64: + case lldb_xmm5_x86_64: + case lldb_xmm6_x86_64: + case lldb_xmm7_x86_64: + case lldb_xmm8_x86_64: + case lldb_xmm9_x86_64: + case lldb_xmm10_x86_64: + case lldb_xmm11_x86_64: + case lldb_xmm12_x86_64: + case lldb_xmm13_x86_64: + case lldb_xmm14_x86_64: + case lldb_xmm15_x86_64: + ::memcpy(&m_fpr_x86_64.fxstate.fx_xmm[reg - lldb_xmm0_x86_64], + reg_value.GetBytes(), reg_value.GetByteSize()); + break; + } + + if (WriteRegisterSet(set) != 0) + error.SetErrorStringWithFormat("failed to write register set"); + + return error; +} + +Status NativeRegisterContextOpenBSD_x86_64::ReadAllRegisterValues( + lldb::DataBufferSP &data_sp) { + Status error; + + data_sp.reset(new DataBufferHeap(REG_CONTEXT_SIZE, 0)); + if (!data_sp) { + error.SetErrorStringWithFormat( + "failed to allocate DataBufferHeap instance of size %zu", + REG_CONTEXT_SIZE); + return error; + } + + error = ReadGPR(); + if (error.Fail()) + return error; + + uint8_t *dst = data_sp->GetBytes(); + if (dst == nullptr) { + error.SetErrorStringWithFormat("DataBufferHeap instance of size %zu" + " returned a null pointer", + REG_CONTEXT_SIZE); + return error; + } + + ::memcpy(dst, &m_gpr_x86_64, GetRegisterInfoInterface().GetGPRSize()); + dst += GetRegisterInfoInterface().GetGPRSize(); + + RegisterValue value((uint64_t)-1); + const RegisterInfo *reg_info = + GetRegisterInfoInterface().GetDynamicRegisterInfo("orig_eax"); + if (reg_info == nullptr) + reg_info = GetRegisterInfoInterface().GetDynamicRegisterInfo("orig_rax"); + return error; +} + +Status NativeRegisterContextOpenBSD_x86_64::WriteAllRegisterValues( + const lldb::DataBufferSP &data_sp) { + Status error; + + if (!data_sp) { + error.SetErrorStringWithFormat( + "NativeRegisterContextOpenBSD_x86_64::%s invalid data_sp provided", + __FUNCTION__); + return error; + } + + if (data_sp->GetByteSize() != REG_CONTEXT_SIZE) { + error.SetErrorStringWithFormat( + "NativeRegisterContextOpenBSD_x86_64::%s data_sp contained mismatched " + "data size, expected %zu, actual %llu", + __FUNCTION__, REG_CONTEXT_SIZE, data_sp->GetByteSize()); + return error; + } + + uint8_t *src = data_sp->GetBytes(); + if (src == nullptr) { + error.SetErrorStringWithFormat("NativeRegisterContextOpenBSD_x86_64::%s " + "DataBuffer::GetBytes() returned a null " + "pointer", + __FUNCTION__); + return error; + } + ::memcpy(&m_gpr_x86_64, src, GetRegisterInfoInterface().GetGPRSize()); + + error = WriteGPR(); + if (error.Fail()) + return error; + src += GetRegisterInfoInterface().GetGPRSize(); + + return error; +} + +Status NativeRegisterContextOpenBSD_x86_64::IsWatchpointHit(uint32_t wp_index, + bool &is_hit) { + if (wp_index >= NumSupportedHardwareWatchpoints()) + return Status("Watchpoint index out of range"); + + RegisterValue reg_value; + const RegisterInfo *const reg_info = GetRegisterInfoAtIndex(lldb_dr6_x86_64); + Status error = ReadRegister(reg_info, reg_value); + if (error.Fail()) { + is_hit = false; + return error; + } + + uint64_t status_bits = reg_value.GetAsUInt64(); + + is_hit = status_bits & (1 << wp_index); + + return error; +} + +Status NativeRegisterContextOpenBSD_x86_64::GetWatchpointHitIndex( + uint32_t &wp_index, lldb::addr_t trap_addr) { + uint32_t num_hw_wps = NumSupportedHardwareWatchpoints(); + for (wp_index = 0; wp_index < num_hw_wps; ++wp_index) { + bool is_hit; + Status error = IsWatchpointHit(wp_index, is_hit); + if (error.Fail()) { + wp_index = LLDB_INVALID_INDEX32; + return error; + } else if (is_hit) { + return error; + } + } + wp_index = LLDB_INVALID_INDEX32; + return Status(); +} + +Status NativeRegisterContextOpenBSD_x86_64::IsWatchpointVacant(uint32_t wp_index, + bool &is_vacant) { + if (wp_index >= NumSupportedHardwareWatchpoints()) + return Status("Watchpoint index out of range"); + + RegisterValue reg_value; + const RegisterInfo *const reg_info = GetRegisterInfoAtIndex(lldb_dr7_x86_64); + Status error = ReadRegister(reg_info, reg_value); + if (error.Fail()) { + is_vacant = false; + return error; + } + + uint64_t control_bits = reg_value.GetAsUInt64(); + + is_vacant = !(control_bits & (1 << (2 * wp_index))); + + return error; +} + +Status NativeRegisterContextOpenBSD_x86_64::SetHardwareWatchpointWithIndex( + lldb::addr_t addr, size_t size, uint32_t watch_flags, uint32_t wp_index) { + + if (wp_index >= NumSupportedHardwareWatchpoints()) + return Status("Watchpoint index out of range"); + + // Read only watchpoints aren't supported on x86_64. Fall back to read/write + // waitchpoints instead. + // TODO: Add logic to detect when a write happens and ignore that watchpoint + // hit. + if (watch_flags == 0x2) + watch_flags = 0x3; + + if (watch_flags != 0x1 && watch_flags != 0x3) + return Status("Invalid read/write bits for watchpoint"); + + if (size != 1 && size != 2 && size != 4 && size != 8) + return Status("Invalid size for watchpoint"); + + bool is_vacant; + Status error = IsWatchpointVacant(wp_index, is_vacant); + if (error.Fail()) + return error; + if (!is_vacant) + return Status("Watchpoint index not vacant"); + + RegisterValue reg_value; + const RegisterInfo *const reg_info_dr7 = + GetRegisterInfoAtIndex(lldb_dr7_x86_64); + error = ReadRegister(reg_info_dr7, reg_value); + if (error.Fail()) + return error; + + // for watchpoints 0, 1, 2, or 3, respectively, set bits 1, 3, 5, or 7 + uint64_t enable_bit = 1 << (2 * wp_index); + + // set bits 16-17, 20-21, 24-25, or 28-29 + // with 0b01 for write, and 0b11 for read/write + uint64_t rw_bits = watch_flags << (16 + 4 * wp_index); + + // set bits 18-19, 22-23, 26-27, or 30-31 + // with 0b00, 0b01, 0b10, or 0b11 + // for 1, 2, 8 (if supported), or 4 bytes, respectively + uint64_t size_bits = (size == 8 ? 0x2 : size - 1) << (18 + 4 * wp_index); + + uint64_t bit_mask = (0x3 << (2 * wp_index)) | (0xF << (16 + 4 * wp_index)); + + uint64_t control_bits = reg_value.GetAsUInt64() & ~bit_mask; + + control_bits |= enable_bit | rw_bits | size_bits; + + const RegisterInfo *const reg_info_drN = + GetRegisterInfoAtIndex(lldb_dr0_x86_64 + wp_index); + error = WriteRegister(reg_info_drN, RegisterValue(addr)); + if (error.Fail()) + return error; + + error = WriteRegister(reg_info_dr7, RegisterValue(control_bits)); + if (error.Fail()) + return error; + + error.Clear(); + return error; +} + +bool NativeRegisterContextOpenBSD_x86_64::ClearHardwareWatchpoint( + uint32_t wp_index) { + if (wp_index >= NumSupportedHardwareWatchpoints()) + return false; + + RegisterValue reg_value; + + // for watchpoints 0, 1, 2, or 3, respectively, clear bits 0, 1, 2, or 3 of + // the debug status register (DR6) + const RegisterInfo *const reg_info_dr6 = + GetRegisterInfoAtIndex(lldb_dr6_x86_64); + Status error = ReadRegister(reg_info_dr6, reg_value); + if (error.Fail()) + return false; + uint64_t bit_mask = 1 << wp_index; + uint64_t status_bits = reg_value.GetAsUInt64() & ~bit_mask; + error = WriteRegister(reg_info_dr6, RegisterValue(status_bits)); + if (error.Fail()) + return false; + + // for watchpoints 0, 1, 2, or 3, respectively, clear bits {0-1,16-19}, + // {2-3,20-23}, {4-5,24-27}, or {6-7,28-31} of the debug control register + // (DR7) + const RegisterInfo *const reg_info_dr7 = + GetRegisterInfoAtIndex(lldb_dr7_x86_64); + error = ReadRegister(reg_info_dr7, reg_value); + if (error.Fail()) + return false; + bit_mask = (0x3 << (2 * wp_index)) | (0xF << (16 + 4 * wp_index)); + uint64_t control_bits = reg_value.GetAsUInt64() & ~bit_mask; + return WriteRegister(reg_info_dr7, RegisterValue(control_bits)).Success(); +} + +Status NativeRegisterContextOpenBSD_x86_64::ClearAllHardwareWatchpoints() { + RegisterValue reg_value; + + // clear bits {0-4} of the debug status register (DR6) + const RegisterInfo *const reg_info_dr6 = + GetRegisterInfoAtIndex(lldb_dr6_x86_64); + Status error = ReadRegister(reg_info_dr6, reg_value); + if (error.Fail()) + return error; + uint64_t bit_mask = 0xF; + uint64_t status_bits = reg_value.GetAsUInt64() & ~bit_mask; + error = WriteRegister(reg_info_dr6, RegisterValue(status_bits)); + if (error.Fail()) + return error; + + // clear bits {0-7,16-31} of the debug control register (DR7) + const RegisterInfo *const reg_info_dr7 = + GetRegisterInfoAtIndex(lldb_dr7_x86_64); + error = ReadRegister(reg_info_dr7, reg_value); + if (error.Fail()) + return error; + bit_mask = 0xFF | (0xFFFF << 16); + uint64_t control_bits = reg_value.GetAsUInt64() & ~bit_mask; + return WriteRegister(reg_info_dr7, RegisterValue(control_bits)); +} + +uint32_t NativeRegisterContextOpenBSD_x86_64::SetHardwareWatchpoint( + lldb::addr_t addr, size_t size, uint32_t watch_flags) { + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); + const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints(); + for (uint32_t wp_index = 0; wp_index < num_hw_watchpoints; ++wp_index) { + bool is_vacant; + Status error = IsWatchpointVacant(wp_index, is_vacant); + if (is_vacant) { + error = SetHardwareWatchpointWithIndex(addr, size, watch_flags, wp_index); + if (error.Success()) + return wp_index; + } + if (error.Fail() && log) { + log->Printf("NativeRegisterContextOpenBSD_x86_64::%s Error: %s", + __FUNCTION__, error.AsCString()); + } + } + return LLDB_INVALID_INDEX32; +} + +lldb::addr_t +NativeRegisterContextOpenBSD_x86_64::GetWatchpointAddress(uint32_t wp_index) { + if (wp_index >= NumSupportedHardwareWatchpoints()) + return LLDB_INVALID_ADDRESS; + RegisterValue reg_value; + const RegisterInfo *const reg_info_drN = + GetRegisterInfoAtIndex(lldb_dr0_x86_64 + wp_index); + if (ReadRegister(reg_info_drN, reg_value).Fail()) + return LLDB_INVALID_ADDRESS; + return reg_value.GetAsUInt64(); +} + +uint32_t NativeRegisterContextOpenBSD_x86_64::NumSupportedHardwareWatchpoints() { + // Available debug address registers: dr0, dr1, dr2, dr3 + return 4; +} + +#endif // defined(__x86_64__) diff --git a/gnu/llvm/tools/lldb/source/Plugins/Process/OpenBSD/NativeRegisterContextOpenBSD_x86_64.h b/gnu/llvm/tools/lldb/source/Plugins/Process/OpenBSD/NativeRegisterContextOpenBSD_x86_64.h new file mode 100644 index 00000000000..595a57ad0c3 --- /dev/null +++ b/gnu/llvm/tools/lldb/source/Plugins/Process/OpenBSD/NativeRegisterContextOpenBSD_x86_64.h @@ -0,0 +1,92 @@ +//===-- NativeRegisterContextOpenBSD_x86_64.h --------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#if defined(__x86_64__) + +#ifndef lldb_NativeRegisterContextOpenBSD_x86_64_h +#define lldb_NativeRegisterContextOpenBSD_x86_64_h + +// clang-format off +#include <sys/types.h> +#include <machine/reg.h> +// clang-format on + +#include "Plugins/Process/OpenBSD/NativeRegisterContextOpenBSD.h" +#include "Plugins/Process/Utility/RegisterContext_x86.h" +#include "Plugins/Process/Utility/lldb-x86-register-enums.h" + +namespace lldb_private { +namespace process_openbsd { + +class NativeProcessOpenBSD; + +class NativeRegisterContextOpenBSD_x86_64 : public NativeRegisterContextOpenBSD { +public: + NativeRegisterContextOpenBSD_x86_64(const ArchSpec &target_arch, + NativeThreadProtocol &native_thread); + uint32_t GetRegisterSetCount() const override; + + const RegisterSet *GetRegisterSet(uint32_t set_index) const override; + + Status ReadRegister(const RegisterInfo *reg_info, + RegisterValue ®_value) override; + + Status WriteRegister(const RegisterInfo *reg_info, + const RegisterValue ®_value) override; + + Status ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override; + + Status WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override; + + Status IsWatchpointHit(uint32_t wp_index, bool &is_hit) override; + + Status GetWatchpointHitIndex(uint32_t &wp_index, + lldb::addr_t trap_addr) override; + + Status IsWatchpointVacant(uint32_t wp_index, bool &is_vacant) override; + + bool ClearHardwareWatchpoint(uint32_t wp_index) override; + + Status ClearAllHardwareWatchpoints() override; + + Status SetHardwareWatchpointWithIndex(lldb::addr_t addr, size_t size, + uint32_t watch_flags, + uint32_t wp_index); + + uint32_t SetHardwareWatchpoint(lldb::addr_t addr, size_t size, + uint32_t watch_flags) override; + + lldb::addr_t GetWatchpointAddress(uint32_t wp_index) override; + + uint32_t NumSupportedHardwareWatchpoints() override; + +protected: + void *GetGPRBuffer() override { return &m_gpr_x86_64; } + void *GetFPRBuffer() override { return &m_fpr_x86_64; } + +private: + // Private member types. + enum { GPRegSet, FPRegSet }; + + // Private member variables. + struct reg m_gpr_x86_64; + struct fpreg m_fpr_x86_64; + + int GetSetForNativeRegNum(int reg_num) const; + + int ReadRegisterSet(uint32_t set); + int WriteRegisterSet(uint32_t set); +}; + +} // namespace process_openbsd +} // namespace lldb_private + +#endif // #ifndef lldb_NativeRegisterContextOpenBSD_x86_64_h + +#endif // defined(__x86_64__) diff --git a/gnu/llvm/tools/lldb/source/Plugins/Process/OpenBSD/NativeThreadOpenBSD.cpp b/gnu/llvm/tools/lldb/source/Plugins/Process/OpenBSD/NativeThreadOpenBSD.cpp new file mode 100644 index 00000000000..30a5ae0fff7 --- /dev/null +++ b/gnu/llvm/tools/lldb/source/Plugins/Process/OpenBSD/NativeThreadOpenBSD.cpp @@ -0,0 +1,206 @@ +//===-- NativeThreadOpenBSD.cpp -------------------------------- -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "NativeThreadOpenBSD.h" +#include "NativeRegisterContextOpenBSD.h" + +#include "NativeProcessOpenBSD.h" + +#include "Plugins/Process/POSIX/CrashReason.h" +#include "Plugins/Process/POSIX/ProcessPOSIXLog.h" +#include "lldb/Utility/LLDBAssert.h" +#include "lldb/Utility/RegisterValue.h" +#include "lldb/Utility/State.h" + +#include <sstream> + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::process_openbsd; + +NativeThreadOpenBSD::NativeThreadOpenBSD(NativeProcessOpenBSD &process, + lldb::tid_t tid) + : NativeThreadProtocol(process, tid), m_state(StateType::eStateInvalid), + m_stop_info(), m_reg_context_up( +NativeRegisterContextOpenBSD::CreateHostNativeRegisterContextOpenBSD(process.GetArchitecture(), *this) +), m_stop_description() {} + +void NativeThreadOpenBSD::SetStoppedBySignal(uint32_t signo, + const siginfo_t *info) { + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD)); + LLDB_LOG(log, "tid = {0} in called with signal {1}", GetID(), signo); + + SetStopped(); + + m_stop_info.reason = StopReason::eStopReasonSignal; + m_stop_info.details.signal.signo = signo; + + m_stop_description.clear(); + if (info) { + switch (signo) { + case SIGSEGV: + case SIGBUS: + case SIGFPE: + case SIGILL: + const auto reason = GetCrashReason(*info); + m_stop_description = GetCrashReasonString(reason, *info); + break; + } + } +} + +void NativeThreadOpenBSD::SetStoppedByBreakpoint() { + SetStopped(); + m_stop_info.reason = StopReason::eStopReasonBreakpoint; + m_stop_info.details.signal.signo = SIGTRAP; +} + +void NativeThreadOpenBSD::SetStoppedByTrace() { + SetStopped(); + m_stop_info.reason = StopReason::eStopReasonTrace; + m_stop_info.details.signal.signo = SIGTRAP; +} + +void NativeThreadOpenBSD::SetStoppedByExec() { + SetStopped(); + m_stop_info.reason = StopReason::eStopReasonExec; + m_stop_info.details.signal.signo = SIGTRAP; +} + +void NativeThreadOpenBSD::SetStoppedByWatchpoint(uint32_t wp_index) { + SetStopped(); + + lldbassert(wp_index != LLDB_INVALID_INDEX32 && "wp_index cannot be invalid"); + + std::ostringstream ostr; + ostr << GetRegisterContext().GetWatchpointAddress(wp_index) << " "; + ostr << wp_index; + + ostr << " " << GetRegisterContext().GetWatchpointHitAddress(wp_index); + + m_stop_description = ostr.str(); + + m_stop_info.reason = StopReason::eStopReasonWatchpoint; + m_stop_info.details.signal.signo = SIGTRAP; +} + +void NativeThreadOpenBSD::SetStopped() { + const StateType new_state = StateType::eStateStopped; + m_state = new_state; + m_stop_description.clear(); +} + +void NativeThreadOpenBSD::SetRunning() { + m_state = StateType::eStateRunning; + m_stop_info.reason = StopReason::eStopReasonNone; +} + +void NativeThreadOpenBSD::SetStepping() { + m_state = StateType::eStateStepping; + m_stop_info.reason = StopReason::eStopReasonNone; +} + +std::string NativeThreadOpenBSD::GetName() { return std::string(""); } + +lldb::StateType NativeThreadOpenBSD::GetState() { return m_state; } + +bool NativeThreadOpenBSD::GetStopReason(ThreadStopInfo &stop_info, + std::string &description) { + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD)); + + description.clear(); + + switch (m_state) { + case eStateStopped: + case eStateCrashed: + case eStateExited: + case eStateSuspended: + case eStateUnloaded: + stop_info = m_stop_info; + description = m_stop_description; + + return true; + + case eStateInvalid: + case eStateConnected: + case eStateAttaching: + case eStateLaunching: + case eStateRunning: + case eStateStepping: + case eStateDetached: + LLDB_LOG(log, "tid = {0} in state {1} cannot answer stop reason", GetID(), + StateAsCString(m_state)); + return false; + } + llvm_unreachable("unhandled StateType!"); +} + +NativeRegisterContext& NativeThreadOpenBSD::GetRegisterContext() { + assert(m_reg_context_up); +return *m_reg_context_up; +} + +Status NativeThreadOpenBSD::SetWatchpoint(lldb::addr_t addr, size_t size, + uint32_t watch_flags, bool hardware) { + if (!hardware) + return Status("not implemented"); + if (m_state == eStateLaunching) + return Status(); + Status error = RemoveWatchpoint(addr); + if (error.Fail()) + return error; + uint32_t wp_index = GetRegisterContext().SetHardwareWatchpoint(addr, size, watch_flags); + if (wp_index == LLDB_INVALID_INDEX32) + return Status("Setting hardware watchpoint failed."); + m_watchpoint_index_map.insert({addr, wp_index}); + return Status(); +} + +Status NativeThreadOpenBSD::RemoveWatchpoint(lldb::addr_t addr) { + auto wp = m_watchpoint_index_map.find(addr); + if (wp == m_watchpoint_index_map.end()) + return Status(); + uint32_t wp_index = wp->second; + m_watchpoint_index_map.erase(wp); + if (GetRegisterContext().ClearHardwareWatchpoint(wp_index)) + return Status(); + return Status("Clearing hardware watchpoint failed."); +} + +Status NativeThreadOpenBSD::SetHardwareBreakpoint(lldb::addr_t addr, + size_t size) { + if (m_state == eStateLaunching) + return Status(); + + Status error = RemoveHardwareBreakpoint(addr); + if (error.Fail()) + return error; + + uint32_t bp_index = GetRegisterContext().SetHardwareBreakpoint(addr, size); + + if (bp_index == LLDB_INVALID_INDEX32) + return Status("Setting hardware breakpoint failed."); + + m_hw_break_index_map.insert({addr, bp_index}); + return Status(); +} + +Status NativeThreadOpenBSD::RemoveHardwareBreakpoint(lldb::addr_t addr) { + auto bp = m_hw_break_index_map.find(addr); + if (bp == m_hw_break_index_map.end()) + return Status(); + + uint32_t bp_index = bp->second; + if (GetRegisterContext().ClearHardwareBreakpoint(bp_index)) { + m_hw_break_index_map.erase(bp); + return Status(); + } + + return Status("Clearing hardware breakpoint failed."); +} diff --git a/gnu/llvm/tools/lldb/source/Plugins/Process/OpenBSD/NativeThreadOpenBSD.h b/gnu/llvm/tools/lldb/source/Plugins/Process/OpenBSD/NativeThreadOpenBSD.h new file mode 100644 index 00000000000..62f6803ab95 --- /dev/null +++ b/gnu/llvm/tools/lldb/source/Plugins/Process/OpenBSD/NativeThreadOpenBSD.h @@ -0,0 +1,81 @@ +//===-- NativeThreadOpenBSD.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_NativeThreadOpenBSD_H_ +#define liblldb_NativeThreadOpenBSD_H_ + +#include "lldb/Host/common/NativeThreadProtocol.h" + +#include <csignal> +#include <map> +#include <string> + +namespace lldb_private { +namespace process_openbsd { + +class NativeProcessOpenBSD; + +class NativeThreadOpenBSD : public NativeThreadProtocol { + friend class NativeProcessOpenBSD; + +public: + NativeThreadOpenBSD(NativeProcessOpenBSD &process, lldb::tid_t tid); + + // --------------------------------------------------------------------- + // NativeThreadProtocol Interface + // --------------------------------------------------------------------- + std::string GetName() override; + + lldb::StateType GetState() override; + + bool GetStopReason(ThreadStopInfo &stop_info, + std::string &description) override; + + NativeRegisterContext& GetRegisterContext() override; + + Status SetWatchpoint(lldb::addr_t addr, size_t size, uint32_t watch_flags, + bool hardware) override; + + Status RemoveWatchpoint(lldb::addr_t addr) override; + + Status SetHardwareBreakpoint(lldb::addr_t addr, size_t size) override; + + Status RemoveHardwareBreakpoint(lldb::addr_t addr) override; + +private: + // --------------------------------------------------------------------- + // Interface for friend classes + // --------------------------------------------------------------------- + + void SetStoppedBySignal(uint32_t signo, const siginfo_t *info = nullptr); + void SetStoppedByBreakpoint(); + void SetStoppedByTrace(); + void SetStoppedByExec(); + void SetStoppedByWatchpoint(uint32_t wp_index); + void SetStopped(); + void SetRunning(); + void SetStepping(); + + // --------------------------------------------------------------------- + // Member Variables + // --------------------------------------------------------------------- + lldb::StateType m_state; + ThreadStopInfo m_stop_info; + std::unique_ptr<NativeRegisterContext> m_reg_context_up; + std::string m_stop_description; + using WatchpointIndexMap = std::map<lldb::addr_t, uint32_t>; + WatchpointIndexMap m_watchpoint_index_map; + WatchpointIndexMap m_hw_break_index_map; +}; + +typedef std::shared_ptr<NativeThreadOpenBSD> NativeThreadOpenBSDSP; +} // namespace process_openbsd +} // namespace lldb_private + +#endif // #ifndef liblldb_NativeThreadOpenBSD_H_ diff --git a/gnu/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp b/gnu/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp index f53db502be9..d22cf44baf8 100644 --- a/gnu/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp +++ b/gnu/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp @@ -11,24 +11,22 @@ #include <errno.h> -// C Includes #ifdef __APPLE__ #include <TargetConditionals.h> #endif -// C++ Includes #include <chrono> #include <cstring> -// Other libraries and framework includes #include "lldb/Core/ModuleSpec.h" #include "lldb/Host/Config.h" #include "lldb/Host/File.h" #include "lldb/Host/FileSystem.h" #include "lldb/Host/Host.h" #include "lldb/Host/HostInfo.h" -#include "lldb/Interpreter/Args.h" +#include "lldb/Host/SafeMachO.h" +#include "lldb/Interpreter/OptionArgParser.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Target/FileAction.h" #include "lldb/Target/Platform.h" @@ -40,9 +38,8 @@ #include "lldb/Utility/StreamString.h" #include "llvm/ADT/Triple.h" -// Project includes #include "ProcessGDBRemoteLog.h" -#include "Utility/StringExtractorGDBRemote.h" +#include "lldb/Utility/StringExtractorGDBRemote.h" #ifdef __ANDROID__ #include "lldb/Host/android/HostInfoAndroid.h" @@ -218,12 +215,15 @@ GDBRemoteCommunicationServerCommon::Handle_qHostInfo( if (sub != LLDB_INVALID_CPUTYPE) response.Printf("cpusubtype:%u;", sub); - if (cpu == ArchSpec::kCore_arm_any) { + if (cpu == llvm::MachO::CPU_TYPE_ARM + || cpu == llvm::MachO::CPU_TYPE_ARM64) { // Indicate the OS type. #if defined(TARGET_OS_TV) && TARGET_OS_TV == 1 response.PutCString("ostype:tvos;"); #elif defined(TARGET_OS_WATCH) && TARGET_OS_WATCH == 1 response.PutCString("ostype:watchos;"); +#elif defined(TARGET_OS_BRIDGE) && TARGET_OS_BRIDGE == 1 + response.PutCString("ostype:bridgeos;"); #else response.PutCString("ostype:ios;"); #endif @@ -265,19 +265,10 @@ GDBRemoteCommunicationServerCommon::Handle_qHostInfo( break; } - uint32_t major = UINT32_MAX; - uint32_t minor = UINT32_MAX; - uint32_t update = UINT32_MAX; - if (HostInfo::GetOSVersion(major, minor, update)) { - if (major != UINT32_MAX) { - response.Printf("os_version:%u", major); - if (minor != UINT32_MAX) { - response.Printf(".%u", minor); - if (update != UINT32_MAX) - response.Printf(".%u", update); - } - response.PutChar(';'); - } + llvm::VersionTuple version = HostInfo::GetOSVersion(); + if (!version.empty()) { + response.Format("os_version:{0}", version.getAsString()); + response.PutChar(';'); } std::string s; @@ -295,9 +286,9 @@ GDBRemoteCommunicationServerCommon::Handle_qHostInfo( #if defined(__APPLE__) #if defined(__arm__) || defined(__arm64__) || defined(__aarch64__) - // For iOS devices, we are connected through a USB Mux so we never pretend - // to actually have a hostname as far as the remote lldb that is connecting - // to this lldb-platform is concerned + // For iOS devices, we are connected through a USB Mux so we never pretend to + // actually have a hostname as far as the remote lldb that is connecting to + // this lldb-platform is concerned response.PutCString("hostname:"); response.PutCStringAsRawHex8("127.0.0.1"); response.PutChar(';'); @@ -357,7 +348,8 @@ GDBRemoteCommunicationServerCommon::Handle_qfProcessInfo( StringExtractor extractor(value); std::string file; extractor.GetHexByteString(file); - match_info.GetProcessInfo().GetExecutableFile().SetFile(file, false); + match_info.GetProcessInfo().GetExecutableFile().SetFile( + file, FileSpec::Style::native); } else if (key.equals("name_match")) { NameMatch name_match = llvm::StringSwitch<NameMatch>(value) .Case("equals", NameMatch::Equals) @@ -401,10 +393,10 @@ GDBRemoteCommunicationServerCommon::Handle_qfProcessInfo( match_info.GetProcessInfo().SetEffectiveGroupID(gid); } else if (key.equals("all_users")) { match_info.SetMatchAllUsers( - Args::StringToBoolean(value, false, &success)); + OptionArgParser::ToBoolean(value, false, &success)); } else if (key.equals("triple")) { - match_info.GetProcessInfo().GetArchitecture().SetTriple( - value.str().c_str(), NULL); + match_info.GetProcessInfo().GetArchitecture() = + HostInfo::GetAugmentedArchSpec(value); } else { success = false; } @@ -415,8 +407,8 @@ GDBRemoteCommunicationServerCommon::Handle_qfProcessInfo( } if (Host::FindProcesses(match_info, m_proc_infos)) { - // We found something, return the first item by calling the get - // subsequent process info packet handler... + // We found something, return the first item by calling the get subsequent + // process info packet handler... return Handle_qsProcessInfo(packet); } return SendErrorResponse(3); @@ -524,7 +516,8 @@ GDBRemoteCommunicationServerCommon::Handle_vFile_Open( if (packet.GetChar() == ',') { mode_t mode = packet.GetHexMaxU32(false, 0600); Status error; - const FileSpec path_spec{path, true}; + FileSpec path_spec(path); + FileSystem::Instance().Resolve(path_spec); int fd = ::open(path_spec.GetCString(), flags, mode); const int save_errno = fd == -1 ? errno : 0; StreamString response; @@ -663,12 +656,14 @@ GDBRemoteCommunicationServerCommon::Handle_vFile_Mode( std::string path; packet.GetHexByteString(path); if (!path.empty()) { - Status error; - const uint32_t mode = File::GetPermissions(FileSpec{path, true}, error); + FileSpec file_spec(path); + FileSystem::Instance().Resolve(file_spec); + std::error_code ec; + const uint32_t mode = FileSystem::Instance().GetPermissions(file_spec, ec); StreamString response; response.Printf("F%u", mode); - if (mode == 0 || error.Fail()) - response.Printf(",%i", (int)error.GetError()); + if (mode == 0 || ec) + response.Printf(",%i", (int)Status(ec).GetError()); return SendPacketNoLock(response.GetString()); } return SendErrorResponse(23); @@ -702,7 +697,11 @@ GDBRemoteCommunicationServerCommon::Handle_vFile_symlink( packet.GetHexByteStringTerminatedBy(dst, ','); packet.GetChar(); // Skip ',' char packet.GetHexByteString(src); - Status error = FileSystem::Symlink(FileSpec{src, true}, FileSpec{dst, false}); + + FileSpec src_spec(src); + FileSystem::Instance().Resolve(src_spec); + Status error = FileSystem::Instance().Symlink(src_spec, FileSpec(dst)); + StreamString response; response.Printf("F%u,%u", error.GetError(), error.GetError()); return SendPacketNoLock(response.GetString()); @@ -731,14 +730,15 @@ GDBRemoteCommunicationServerCommon::Handle_qPlatform_shell( if (packet.GetChar() == ',') { // FIXME: add timeout to qPlatform_shell packet // uint32_t timeout = packet.GetHexMaxU32(false, 32); - uint32_t timeout = 10; if (packet.GetChar() == ',') packet.GetHexByteString(working_dir); int status, signo; std::string output; + FileSpec working_spec(working_dir); + FileSystem::Instance().Resolve(working_spec); Status err = - Host::RunShellCommand(path.c_str(), FileSpec{working_dir, true}, - &status, &signo, &output, timeout); + Host::RunShellCommand(path.c_str(), working_spec, &status, &signo, + &output, std::chrono::seconds(10)); StreamGDBRemote response; if (err.Fail()) { response.PutCString("F,"); @@ -838,7 +838,7 @@ GDBRemoteCommunicationServerCommon::Handle_qSupported( response.PutCString(";QThreadSuffixSupported+"); response.PutCString(";QListThreadsInStopReply+"); response.PutCString(";qEcho+"); -#if defined(__linux__) || defined(__NetBSD__) +#if defined(__linux__) || defined(__NetBSD__) || defined(__OpenBSD__) response.PutCString(";QPassSignals+"); response.PutCString(";qXfer:auxv:read+"); #endif @@ -889,7 +889,7 @@ GDBRemoteCommunicationServerCommon::Handle_QSetSTDIN( packet.GetHexByteString(path); const bool read = true; const bool write = false; - if (file_action.Open(STDIN_FILENO, FileSpec{path, false}, read, write)) { + if (file_action.Open(STDIN_FILENO, FileSpec(path), read, write)) { m_process_launch_info.AppendFileAction(file_action); return SendOKResponse(); } @@ -905,7 +905,7 @@ GDBRemoteCommunicationServerCommon::Handle_QSetSTDOUT( packet.GetHexByteString(path); const bool read = false; const bool write = true; - if (file_action.Open(STDOUT_FILENO, FileSpec{path, false}, read, write)) { + if (file_action.Open(STDOUT_FILENO, FileSpec(path), read, write)) { m_process_launch_info.AppendFileAction(file_action); return SendOKResponse(); } @@ -921,7 +921,7 @@ GDBRemoteCommunicationServerCommon::Handle_QSetSTDERR( packet.GetHexByteString(path); const bool read = false; const bool write = true; - if (file_action.Open(STDERR_FILENO, FileSpec{path, false}, read, write)) { + if (file_action.Open(STDERR_FILENO, FileSpec(path), read, write)) { m_process_launch_info.AppendFileAction(file_action); return SendOKResponse(); } @@ -945,8 +945,7 @@ GDBRemoteCommunicationServerCommon::Handle_QEnvironment( packet.SetFilePos(::strlen("QEnvironment:")); const uint32_t bytes_left = packet.GetBytesLeft(); if (bytes_left > 0) { - m_process_launch_info.GetEnvironmentEntries().AppendArgument( - llvm::StringRef::withNullAsEmpty(packet.Peek())); + m_process_launch_info.GetEnvironment().insert(packet.Peek()); return SendOKResponse(); } return SendErrorResponse(12); @@ -960,7 +959,7 @@ GDBRemoteCommunicationServerCommon::Handle_QEnvironmentHexEncoded( if (bytes_left > 0) { std::string str; packet.GetHexByteString(str); - m_process_launch_info.GetEnvironmentEntries().AppendArgument(str); + m_process_launch_info.GetEnvironment().insert(str); return SendOKResponse(); } return SendErrorResponse(12); @@ -973,8 +972,7 @@ GDBRemoteCommunicationServerCommon::Handle_QLaunchArch( const uint32_t bytes_left = packet.GetBytesLeft(); if (bytes_left > 0) { const char *arch_triple = packet.Peek(); - ArchSpec arch_spec(arch_triple, NULL); - m_process_launch_info.SetArchitecture(arch_spec); + m_process_launch_info.SetArchitecture(HostInfo::GetAugmentedArchSpec(arch_triple)); return SendOKResponse(); } return SendErrorResponse(13); @@ -982,11 +980,11 @@ GDBRemoteCommunicationServerCommon::Handle_QLaunchArch( GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerCommon::Handle_A(StringExtractorGDBRemote &packet) { - // The 'A' packet is the most over designed packet ever here with - // redundant argument indexes, redundant argument lengths and needed hex - // encoded argument string values. Really all that is needed is a comma - // separated hex encoded argument value list, but we will stay true to the - // documented version of the 'A' packet here... + // The 'A' packet is the most over designed packet ever here with redundant + // argument indexes, redundant argument lengths and needed hex encoded + // argument string values. Really all that is needed is a comma separated hex + // encoded argument value list, but we will stay true to the documented + // version of the 'A' packet here... Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); int actual_arg_index = 0; @@ -994,8 +992,8 @@ GDBRemoteCommunicationServerCommon::Handle_A(StringExtractorGDBRemote &packet) { packet.SetFilePos(1); // Skip the 'A' bool success = true; while (success && packet.GetBytesLeft() > 0) { - // Decode the decimal argument string length. This length is the - // number of hex nibbles in the argument string value. + // Decode the decimal argument string length. This length is the number of + // hex nibbles in the argument string value. const uint32_t arg_len = packet.GetU32(UINT32_MAX); if (arg_len == UINT32_MAX) success = false; @@ -1004,8 +1002,8 @@ GDBRemoteCommunicationServerCommon::Handle_A(StringExtractorGDBRemote &packet) { if (packet.GetChar() != ',') success = false; else { - // Decode the argument index. We ignore this really because - // who would really send down the arguments in a random order??? + // Decode the argument index. We ignore this really because who would + // really send down the arguments in a random order??? const uint32_t arg_idx = packet.GetU32(UINT32_MAX); if (arg_idx == UINT32_MAX) success = false; @@ -1014,9 +1012,9 @@ GDBRemoteCommunicationServerCommon::Handle_A(StringExtractorGDBRemote &packet) { if (packet.GetChar() != ',') success = false; else { - // Decode the argument string value from hex bytes - // back into a UTF8 string and make sure the length - // matches the one supplied in the packet + // Decode the argument string value from hex bytes back into a UTF8 + // string and make sure the length matches the one supplied in the + // packet std::string arg; if (packet.GetHexByteStringFixedLength(arg, arg_len) != (arg_len / 2)) @@ -1030,7 +1028,8 @@ GDBRemoteCommunicationServerCommon::Handle_A(StringExtractorGDBRemote &packet) { if (success) { if (arg_idx == 0) - m_process_launch_info.GetExecutableFile().SetFile(arg, false); + m_process_launch_info.GetExecutableFile().SetFile( + arg, FileSpec::Style::native); m_process_launch_info.GetArguments().AppendArgument(arg); if (log) log->Printf("LLGSPacketHandler::%s added arg %d: \"%s\"", @@ -1255,8 +1254,8 @@ void GDBRemoteCommunicationServerCommon:: // Nothing. break; } - // In case of MIPS64, pointer size is depend on ELF ABI - // For N32 the pointer size is 4 and for N64 it is 8 + // In case of MIPS64, pointer size is depend on ELF ABI For N32 the pointer + // size is 4 and for N64 it is 8 std::string abi = proc_arch.GetTargetABI(); if (!abi.empty()) response.Printf("elf_abi:%s;", abi.c_str()); @@ -1269,7 +1268,9 @@ FileSpec GDBRemoteCommunicationServerCommon::FindModuleFile( #ifdef __ANDROID__ return HostInfoAndroid::ResolveLibraryPath(module_path, arch); #else - return FileSpec(module_path, true); + FileSpec file_spec(module_path); + FileSystem::Instance().Resolve(file_spec); + return file_spec; #endif } @@ -1278,7 +1279,9 @@ GDBRemoteCommunicationServerCommon::GetModuleInfo(llvm::StringRef module_path, llvm::StringRef triple) { ArchSpec arch(triple); - const FileSpec req_module_path_spec(module_path, true); + FileSpec req_module_path_spec(module_path); + FileSystem::Instance().Resolve(req_module_path_spec); + const FileSpec module_path_spec = FindModuleFile(req_module_path_spec.GetPath(), arch); const ModuleSpec module_spec(module_path_spec, arch); diff --git a/gnu/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp b/gnu/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp index 9294359dbef..96f6a8f0f8f 100644 --- a/gnu/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp +++ b/gnu/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp @@ -14,15 +14,10 @@ #include "GDBRemoteCommunicationServerLLGS.h" #include "lldb/Utility/StreamGDBRemote.h" -// C Includes -// C++ Includes #include <chrono> #include <cstring> #include <thread> -// Other libraries and framework includes -#include "lldb/Core/RegisterValue.h" -#include "lldb/Core/State.h" #include "lldb/Host/ConnectionFileDescriptor.h" #include "lldb/Host/Debug.h" #include "lldb/Host/File.h" @@ -33,23 +28,24 @@ #include "lldb/Host/common/NativeProcessProtocol.h" #include "lldb/Host/common/NativeRegisterContext.h" #include "lldb/Host/common/NativeThreadProtocol.h" -#include "lldb/Interpreter/Args.h" #include "lldb/Target/FileAction.h" #include "lldb/Target/MemoryRegionInfo.h" +#include "lldb/Utility/Args.h" #include "lldb/Utility/DataBuffer.h" #include "lldb/Utility/Endian.h" #include "lldb/Utility/JSON.h" #include "lldb/Utility/LLDBAssert.h" #include "lldb/Utility/Log.h" +#include "lldb/Utility/RegisterValue.h" +#include "lldb/Utility/State.h" #include "lldb/Utility/StreamString.h" #include "lldb/Utility/UriParser.h" #include "llvm/ADT/Triple.h" #include "llvm/Support/ScopedPrinter.h" -// Project includes #include "ProcessGDBRemote.h" #include "ProcessGDBRemoteLog.h" -#include "Utility/StringExtractorGDBRemote.h" +#include "lldb/Utility/StringExtractorGDBRemote.h" using namespace lldb; using namespace lldb_private; @@ -204,21 +200,8 @@ void GDBRemoteCommunicationServerLLGS::RegisterPacketHandlers() { }); } -Status -GDBRemoteCommunicationServerLLGS::SetLaunchArguments(const char *const args[], - int argc) { - if ((argc < 1) || !args || !args[0] || !args[0][0]) - return Status("%s: no process command line specified to launch", - __FUNCTION__); - - m_process_launch_info.SetArguments(const_cast<const char **>(args), true); - return Status(); -} - -Status -GDBRemoteCommunicationServerLLGS::SetLaunchFlags(unsigned int launch_flags) { - m_process_launch_info.GetFlags().Set(launch_flags); - return Status(); +void GDBRemoteCommunicationServerLLGS::SetLaunchInfo(const ProcessLaunchInfo &info) { + m_process_launch_info = info; } Status GDBRemoteCommunicationServerLLGS::LaunchProcess() { @@ -235,8 +218,10 @@ Status GDBRemoteCommunicationServerLLGS::LaunchProcess() { m_process_launch_info.SetLaunchInSeparateProcessGroup(true); m_process_launch_info.GetFlags().Set(eLaunchFlagDebug); - const bool default_to_use_pty = true; - m_process_launch_info.FinalizeFileActions(nullptr, default_to_use_pty); + if (should_forward_stdio) { + if (llvm::Error Err = m_process_launch_info.SetUpPtyRedirection()) + return Status(std::move(Err)); + } { std::lock_guard<std::recursive_mutex> guard(m_debugged_process_mutex); @@ -244,26 +229,20 @@ Status GDBRemoteCommunicationServerLLGS::LaunchProcess() { "process but one already exists"); auto process_or = m_process_factory.Launch(m_process_launch_info, *this, m_mainloop); - if (!process_or) { - Status status(process_or.takeError()); - llvm::errs() << llvm::formatv( - "failed to launch executable `{0}`: {1}", - m_process_launch_info.GetArguments().GetArgumentAtIndex(0), status); - return status; - } + if (!process_or) + return Status(process_or.takeError()); m_debugged_process_up = std::move(*process_or); } - // Handle mirroring of inferior stdout/stderr over the gdb-remote protocol - // as needed. - // llgs local-process debugging may specify PTY paths, which will make these - // file actions non-null - // process launch -i/e/o will also make these file actions non-null - // nullptr means that the traffic is expected to flow over gdb-remote protocol + // Handle mirroring of inferior stdout/stderr over the gdb-remote protocol as + // needed. llgs local-process debugging may specify PTY paths, which will + // make these file actions non-null process launch -i/e/o will also make + // these file actions non-null nullptr means that the traffic is expected to + // flow over gdb-remote protocol if (should_forward_stdio) { // nullptr means it's not redirected to file or pty (in case of LLGS local) - // at least one of stdio will be transferred pty<->gdb-remote - // we need to give the pty master handle to this object to read and/or write + // at least one of stdio will be transferred pty<->gdb-remote we need to + // give the pty master handle to this object to read and/or write LLDB_LOG(log, "pid = {0}: setting up stdout/stderr redirection via $O " "gdb-remote commands", @@ -309,7 +288,7 @@ Status GDBRemoteCommunicationServerLLGS::AttachToProcess(lldb::pid_t pid) { // else. if (m_debugged_process_up && m_debugged_process_up->GetID() != LLDB_INVALID_PROCESS_ID) - return Status("cannot attach to a process %" PRIu64 + return Status("cannot attach to process %" PRIu64 " when another process with pid %" PRIu64 " is being debugged.", pid, m_debugged_process_up->GetID()); @@ -396,12 +375,12 @@ static void AppendHexValue(StreamString &response, const uint8_t *buf, } static void WriteRegisterValueInHexFixedWidth( - StreamString &response, NativeRegisterContextSP ®_ctx_sp, + StreamString &response, NativeRegisterContext ®_ctx, const RegisterInfo ®_info, const RegisterValue *reg_value_p, lldb::ByteOrder byte_order) { RegisterValue reg_value; if (!reg_value_p) { - Status error = reg_ctx_sp->ReadRegister(®_info, reg_value); + Status error = reg_ctx.ReadRegister(®_info, reg_value); if (error.Success()) reg_value_p = ®_value; // else log. @@ -423,15 +402,13 @@ static void WriteRegisterValueInHexFixedWidth( static JSONObject::SP GetRegistersAsJSON(NativeThreadProtocol &thread) { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD)); - NativeRegisterContextSP reg_ctx_sp = thread.GetRegisterContext(); - if (!reg_ctx_sp) - return nullptr; + NativeRegisterContext& reg_ctx = thread.GetRegisterContext(); JSONObject::SP register_object_sp = std::make_shared<JSONObject>(); #ifdef LLDB_JTHREADSINFO_FULL_REGISTER_SET - // Expedite all registers in the first register set (i.e. should be GPRs) that - // are not contained in other registers. + // Expedite all registers in the first register set (i.e. should be GPRs) + // that are not contained in other registers. const RegisterSet *reg_set_p = reg_ctx_sp->GetRegisterSet(0); if (!reg_set_p) return nullptr; @@ -440,22 +417,21 @@ static JSONObject::SP GetRegistersAsJSON(NativeThreadProtocol &thread) { uint32_t reg_num = *reg_num_p; #else // Expedite only a couple of registers until we figure out why sending - // registers is - // expensive. + // registers is expensive. static const uint32_t k_expedited_registers[] = { LLDB_REGNUM_GENERIC_PC, LLDB_REGNUM_GENERIC_SP, LLDB_REGNUM_GENERIC_FP, LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM}; for (const uint32_t *generic_reg_p = k_expedited_registers; *generic_reg_p != LLDB_INVALID_REGNUM; ++generic_reg_p) { - uint32_t reg_num = reg_ctx_sp->ConvertRegisterKindToRegisterNumber( + uint32_t reg_num = reg_ctx.ConvertRegisterKindToRegisterNumber( eRegisterKindGeneric, *generic_reg_p); if (reg_num == LLDB_INVALID_REGNUM) continue; // Target does not support the given register. #endif const RegisterInfo *const reg_info_p = - reg_ctx_sp->GetRegisterInfoAtIndex(reg_num); + reg_ctx.GetRegisterInfoAtIndex(reg_num); if (reg_info_p == nullptr) { if (log) log->Printf( @@ -469,7 +445,7 @@ static JSONObject::SP GetRegistersAsJSON(NativeThreadProtocol &thread) { // registers. RegisterValue reg_value; - Status error = reg_ctx_sp->ReadRegister(reg_info_p, reg_value); + Status error = reg_ctx.ReadRegister(reg_info_p, reg_value); if (error.Fail()) { if (log) log->Printf("%s failed to read register '%s' index %" PRIu32 ": %s", @@ -480,7 +456,7 @@ static JSONObject::SP GetRegistersAsJSON(NativeThreadProtocol &thread) { } StreamString stream; - WriteRegisterValueInHexFixedWidth(stream, reg_ctx_sp, *reg_info_p, + WriteRegisterValueInHexFixedWidth(stream, reg_ctx, *reg_info_p, ®_value, lldb::eByteOrderBig); register_object_sp->SetObject( @@ -523,16 +499,16 @@ static JSONArray::SP GetJSONThreadsInfo(NativeProcessProtocol &process, // Ensure we can get info on the given thread. uint32_t thread_idx = 0; - for (NativeThreadProtocolSP thread_sp; - (thread_sp = process.GetThreadAtIndex(thread_idx)) != nullptr; + for (NativeThreadProtocol *thread; + (thread = process.GetThreadAtIndex(thread_idx)) != nullptr; ++thread_idx) { - lldb::tid_t tid = thread_sp->GetID(); + lldb::tid_t tid = thread->GetID(); // Grab the reason this thread stopped. struct ThreadStopInfo tid_stop_info; std::string description; - if (!thread_sp->GetStopReason(tid_stop_info, description)) + if (!thread->GetStopReason(tid_stop_info, description)) return nullptr; const int signum = tid_stop_info.details.signal.signo; @@ -548,7 +524,7 @@ static JSONArray::SP GetJSONThreadsInfo(NativeProcessProtocol &process, threads_array_sp->AppendObject(thread_obj_sp); if (!abridged) { - if (JSONObject::SP registers_sp = GetRegistersAsJSON(*thread_sp)) + if (JSONObject::SP registers_sp = GetRegistersAsJSON(*thread)) thread_obj_sp->SetObject("registers", registers_sp); } @@ -556,7 +532,7 @@ static JSONArray::SP GetJSONThreadsInfo(NativeProcessProtocol &process, if (signum != 0) thread_obj_sp->SetObject("signal", std::make_shared<JSONNumber>(signum)); - const std::string thread_name = thread_sp->GetName(); + const std::string thread_name = thread->GetName(); if (!thread_name.empty()) thread_obj_sp->SetObject("name", std::make_shared<JSONString>(thread_name)); @@ -604,19 +580,18 @@ GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread( m_debugged_process_up->GetID(), tid); // Ensure we can get info on the given thread. - NativeThreadProtocolSP thread_sp(m_debugged_process_up->GetThreadByID(tid)); - if (!thread_sp) + NativeThreadProtocol *thread = m_debugged_process_up->GetThreadByID(tid); + if (!thread) return SendErrorResponse(51); // Grab the reason this thread stopped. struct ThreadStopInfo tid_stop_info; std::string description; - if (!thread_sp->GetStopReason(tid_stop_info, description)) + if (!thread->GetStopReason(tid_stop_info, description)) return SendErrorResponse(52); // FIXME implement register handling for exec'd inferiors. - // if (tid_stop_info.reason == eStopReasonExec) - // { + // if (tid_stop_info.reason == eStopReasonExec) { // const bool force = true; // InitializeRegisters(force); // } @@ -638,7 +613,7 @@ GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread( response.Printf("thread:%" PRIx64 ";", tid); // Include the thread name if there is one. - const std::string thread_name = thread_sp->GetName(); + const std::string thread_name = thread->GetName(); if (!thread_name.empty()) { size_t thread_name_len = thread_name.length(); @@ -653,36 +628,33 @@ GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread( response.PutChar(';'); } - // If a 'QListThreadsInStopReply' was sent to enable this feature, we - // will send all thread IDs back in the "threads" key whose value is - // a list of hex thread IDs separated by commas: + // If a 'QListThreadsInStopReply' was sent to enable this feature, we will + // send all thread IDs back in the "threads" key whose value is a list of hex + // thread IDs separated by commas: // "threads:10a,10b,10c;" - // This will save the debugger from having to send a pair of qfThreadInfo - // and qsThreadInfo packets, but it also might take a lot of room in the - // stop reply packet, so it must be enabled only on systems where there - // are no limits on packet lengths. + // This will save the debugger from having to send a pair of qfThreadInfo and + // qsThreadInfo packets, but it also might take a lot of room in the stop + // reply packet, so it must be enabled only on systems where there are no + // limits on packet lengths. if (m_list_threads_in_stop_reply) { response.PutCString("threads:"); uint32_t thread_index = 0; - NativeThreadProtocolSP listed_thread_sp; - for (listed_thread_sp = - m_debugged_process_up->GetThreadAtIndex(thread_index); - listed_thread_sp; ++thread_index, - listed_thread_sp = m_debugged_process_up->GetThreadAtIndex( - thread_index)) { + NativeThreadProtocol *listed_thread; + for (listed_thread = m_debugged_process_up->GetThreadAtIndex(thread_index); + listed_thread; ++thread_index, + listed_thread = m_debugged_process_up->GetThreadAtIndex(thread_index)) { if (thread_index > 0) response.PutChar(','); - response.Printf("%" PRIx64, listed_thread_sp->GetID()); + response.Printf("%" PRIx64, listed_thread->GetID()); } response.PutChar(';'); - // Include JSON info that describes the stop reason for any threads - // that actually have stop reasons. We use the new "jstopinfo" key - // whose values is hex ascii JSON that contains the thread IDs - // thread stop info only for threads that have stop reasons. Only send - // this if we have more than one thread otherwise this packet has all - // the info it needs. + // Include JSON info that describes the stop reason for any threads that + // actually have stop reasons. We use the new "jstopinfo" key whose values + // is hex ascii JSON that contains the thread IDs thread stop info only for + // threads that have stop reasons. Only send this if we have more than one + // thread otherwise this packet has all the info it needs. if (thread_index > 0) { const bool threads_with_valid_stop_info_only = true; JSONArray::SP threads_info_sp = GetJSONThreadsInfo( @@ -701,20 +673,18 @@ GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread( uint32_t i = 0; response.PutCString("thread-pcs"); char delimiter = ':'; - for (NativeThreadProtocolSP thread_sp; - (thread_sp = m_debugged_process_up->GetThreadAtIndex(i)) != nullptr; + for (NativeThreadProtocol *thread; + (thread = m_debugged_process_up->GetThreadAtIndex(i)) != nullptr; ++i) { - NativeRegisterContextSP reg_ctx_sp = thread_sp->GetRegisterContext(); - if (!reg_ctx_sp) - continue; + NativeRegisterContext& reg_ctx = thread->GetRegisterContext(); - uint32_t reg_to_read = reg_ctx_sp->ConvertRegisterKindToRegisterNumber( + uint32_t reg_to_read = reg_ctx.ConvertRegisterKindToRegisterNumber( eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); const RegisterInfo *const reg_info_p = - reg_ctx_sp->GetRegisterInfoAtIndex(reg_to_read); + reg_ctx.GetRegisterInfoAtIndex(reg_to_read); RegisterValue reg_value; - Status error = reg_ctx_sp->ReadRegister(reg_info_p, reg_value); + Status error = reg_ctx.ReadRegister(reg_info_p, reg_value); if (error.Fail()) { if (log) log->Printf("%s failed to read register '%s' index %" PRIu32 ": %s", @@ -727,7 +697,7 @@ GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread( response.PutChar(delimiter); delimiter = ','; - WriteRegisterValueInHexFixedWidth(response, reg_ctx_sp, *reg_info_p, + WriteRegisterValueInHexFixedWidth(response, reg_ctx, *reg_info_p, ®_value, endian::InlHostByteOrder()); } @@ -739,49 +709,48 @@ GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread( // // Grab the register context. - NativeRegisterContextSP reg_ctx_sp = thread_sp->GetRegisterContext(); - if (reg_ctx_sp) { - // Expedite all registers in the first register set (i.e. should be GPRs) - // that are not contained in other registers. - const RegisterSet *reg_set_p; - if (reg_ctx_sp->GetRegisterSetCount() > 0 && - ((reg_set_p = reg_ctx_sp->GetRegisterSet(0)) != nullptr)) { - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s expediting registers " - "from set '%s' (registers set count: %zu)", - __FUNCTION__, - reg_set_p->name ? reg_set_p->name : "<unnamed-set>", - reg_set_p->num_registers); - - for (const uint32_t *reg_num_p = reg_set_p->registers; - *reg_num_p != LLDB_INVALID_REGNUM; ++reg_num_p) { - const RegisterInfo *const reg_info_p = - reg_ctx_sp->GetRegisterInfoAtIndex(*reg_num_p); - if (reg_info_p == nullptr) { + NativeRegisterContext& reg_ctx = thread->GetRegisterContext(); + // Expedite all registers in the first register set (i.e. should be GPRs) + // that are not contained in other registers. + const RegisterSet *reg_set_p; + if (reg_ctx.GetRegisterSetCount() > 0 && + ((reg_set_p = reg_ctx.GetRegisterSet(0)) != nullptr)) { + if (log) + log->Printf("GDBRemoteCommunicationServerLLGS::%s expediting registers " + "from set '%s' (registers set count: %zu)", + __FUNCTION__, + reg_set_p->name ? reg_set_p->name : "<unnamed-set>", + reg_set_p->num_registers); + + for (const uint32_t *reg_num_p = reg_set_p->registers; + *reg_num_p != LLDB_INVALID_REGNUM; ++reg_num_p) { + const RegisterInfo *const reg_info_p = + reg_ctx.GetRegisterInfoAtIndex(*reg_num_p); + if (reg_info_p == nullptr) { + if (log) + log->Printf("GDBRemoteCommunicationServerLLGS::%s failed to get " + "register info for register set '%s', register index " + "%" PRIu32, + __FUNCTION__, + reg_set_p->name ? reg_set_p->name : "<unnamed-set>", + *reg_num_p); + } else if (reg_info_p->value_regs == nullptr) { + // Only expediate registers that are not contained in other registers. + RegisterValue reg_value; + Status error = reg_ctx.ReadRegister(reg_info_p, reg_value); + if (error.Success()) { + response.Printf("%.02x:", *reg_num_p); + WriteRegisterValueInHexFixedWidth(response, reg_ctx, *reg_info_p, + ®_value, lldb::eByteOrderBig); + response.PutChar(';'); + } else { if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s failed to get " - "register info for register set '%s', register index " - "%" PRIu32, + log->Printf("GDBRemoteCommunicationServerLLGS::%s failed to read " + "register '%s' index %" PRIu32 ": %s", __FUNCTION__, - reg_set_p->name ? reg_set_p->name : "<unnamed-set>", - *reg_num_p); - } else if (reg_info_p->value_regs == nullptr) { - // Only expediate registers that are not contained in other registers. - RegisterValue reg_value; - Status error = reg_ctx_sp->ReadRegister(reg_info_p, reg_value); - if (error.Success()) { - response.Printf("%.02x:", *reg_num_p); - WriteRegisterValueInHexFixedWidth(response, reg_ctx_sp, *reg_info_p, - ®_value, lldb::eByteOrderBig); - response.PutChar(';'); - } else { - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s failed to read " - "register '%s' index %" PRIu32 ": %s", - __FUNCTION__, reg_info_p->name ? reg_info_p->name - : "<unnamed-register>", - *reg_num_p, error.AsCString()); - } + reg_info_p->name ? reg_info_p->name + : "<unnamed-register>", + *reg_num_p, error.AsCString()); } } } @@ -831,12 +800,13 @@ void GDBRemoteCommunicationServerLLGS::HandleInferiorState_Exited( __FUNCTION__, process->GetID()); } - // Close the pipe to the inferior terminal i/o if we launched it - // and set one up. + // Close the pipe to the inferior terminal i/o if we launched it and set one + // up. MaybeCloseInferiorTerminalConnection(); // We are ready to exit the debug monitor. m_exit_now = true; + m_mainloop.RequestTermination(); } void GDBRemoteCommunicationServerLLGS::HandleInferiorState_Stopped( @@ -847,8 +817,7 @@ void GDBRemoteCommunicationServerLLGS::HandleInferiorState_Stopped( if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s called", __FUNCTION__); - // Send the stop reason unless this is the stop after the - // launch or attach. + // Send the stop reason unless this is the stop after the launch or attach. switch (m_inferior_prev_state) { case eStateLaunching: case eStateAttaching: @@ -883,13 +852,11 @@ void GDBRemoteCommunicationServerLLGS::ProcessStateChanged( break; case StateType::eStateStopped: - // Make sure we get all of the pending stdout/stderr from the inferior - // and send it to the lldb host before we send the state change - // notification + // Make sure we get all of the pending stdout/stderr from the inferior and + // send it to the lldb host before we send the state change notification SendProcessOutput(); // Then stop the forwarding, so that any late output (see llvm.org/pr25652) - // does not - // interfere with our protocol. + // does not interfere with our protocol. StopSTDIOForwarding(); HandleInferiorState_Stopped(process); break; @@ -1311,17 +1278,17 @@ GDBRemoteCommunicationServerLLGS::Handle_qC(StringExtractorGDBRemote &packet) { (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) return SendErrorResponse(68); - // Make sure we set the current thread so g and p packets return - // the data the gdb will expect. + // Make sure we set the current thread so g and p packets return the data the + // gdb will expect. lldb::tid_t tid = m_debugged_process_up->GetCurrentThreadID(); SetCurrentThreadID(tid); - NativeThreadProtocolSP thread_sp = m_debugged_process_up->GetCurrentThread(); - if (!thread_sp) + NativeThreadProtocol *thread = m_debugged_process_up->GetCurrentThread(); + if (!thread) return SendErrorResponse(69); StreamString response; - response.Printf("QC%" PRIx64, thread_sp->GetID()); + response.Printf("QC%" PRIx64, thread->GetID()); return SendPacketNoLock(response.GetString()); } @@ -1364,7 +1331,7 @@ GDBRemoteCommunicationServerLLGS::Handle_QSetWorkingDir( packet.SetFilePos(::strlen("QSetWorkingDir:")); std::string path; packet.GetHexByteString(path); - m_process_launch_info.SetWorkingDirectory(FileSpec{path, true}); + m_process_launch_info.SetWorkingDirectory(FileSpec(path)); return SendOKResponse(); } @@ -1421,10 +1388,9 @@ GDBRemoteCommunicationServerLLGS::Handle_C(StringExtractorGDBRemote &packet) { Status error; // We have two branches: what to do if a continue thread is specified (in - // which case we target - // sending the signal to that thread), or when we don't have a continue thread - // set (in which - // case we send a signal to the process). + // which case we target sending the signal to that thread), or when we don't + // have a continue thread set (in which case we send a signal to the + // process). // TODO discuss with Greg Clayton, make sure this makes sense. @@ -1663,8 +1629,8 @@ GDBRemoteCommunicationServerLLGS::SendStopReasonForState( case eStateStopped: case eStateCrashed: { lldb::tid_t tid = m_debugged_process_up->GetCurrentThreadID(); - // Make sure we set the current thread so g and p packets return - // the data the gdb will expect. + // Make sure we set the current thread so g and p packets return the data + // the gdb will expect. SetCurrentThreadID(tid); return SendStopReplyPacketForThread(tid); } @@ -1692,14 +1658,12 @@ GDBRemoteCommunicationServerLLGS::Handle_qRegisterInfo( return SendErrorResponse(68); // Ensure we have a thread. - NativeThreadProtocolSP thread_sp(m_debugged_process_up->GetThreadAtIndex(0)); - if (!thread_sp) + NativeThreadProtocol *thread = m_debugged_process_up->GetThreadAtIndex(0); + if (!thread) return SendErrorResponse(69); // Get the register context for the first thread. - NativeRegisterContextSP reg_context_sp(thread_sp->GetRegisterContext()); - if (!reg_context_sp) - return SendErrorResponse(69); + NativeRegisterContext ®_context = thread->GetRegisterContext(); // Parse out the register number from the request. packet.SetFilePos(strlen("qRegisterInfo")); @@ -1710,11 +1674,10 @@ GDBRemoteCommunicationServerLLGS::Handle_qRegisterInfo( // Return the end of registers response if we've iterated one past the end of // the register set. - if (reg_index >= reg_context_sp->GetUserRegisterCount()) + if (reg_index >= reg_context.GetUserRegisterCount()) return SendErrorResponse(69); - const RegisterInfo *reg_info = - reg_context_sp->GetRegisterInfoAtIndex(reg_index); + const RegisterInfo *reg_info = reg_context.GetRegisterInfoAtIndex(reg_index); if (!reg_info) return SendErrorResponse(69); @@ -1796,7 +1759,7 @@ GDBRemoteCommunicationServerLLGS::Handle_qRegisterInfo( }; const char *const register_set_name = - reg_context_sp->GetRegisterSetNameForRegisterAtIndex(reg_index); + reg_context.GetRegisterSetNameForRegisterAtIndex(reg_index); if (register_set_name) { response.PutCString("set:"); response.PutCString(register_set_name); @@ -1908,18 +1871,17 @@ GDBRemoteCommunicationServerLLGS::Handle_qfThreadInfo( response.PutChar('m'); LLDB_LOG(log, "starting thread iteration"); - NativeThreadProtocolSP thread_sp; + NativeThreadProtocol *thread; uint32_t thread_index; for (thread_index = 0, - thread_sp = m_debugged_process_up->GetThreadAtIndex(thread_index); - thread_sp; ++thread_index, - thread_sp = m_debugged_process_up->GetThreadAtIndex(thread_index)) { - LLDB_LOG(log, "iterated thread {0}({1}, tid={2})", thread_index, - thread_sp ? "is not null" : "null", - thread_sp ? thread_sp->GetID() : LLDB_INVALID_THREAD_ID); + thread = m_debugged_process_up->GetThreadAtIndex(thread_index); + thread; ++thread_index, + thread = m_debugged_process_up->GetThreadAtIndex(thread_index)) { + LLDB_LOG(log, "iterated thread {0}(tid={2})", thread_index, + thread->GetID()); if (thread_index > 0) response.PutChar(','); - response.Printf("%" PRIx64, thread_sp->GetID()); + response.Printf("%" PRIx64, thread->GetID()); } LLDB_LOG(log, "finished thread iteration"); @@ -1951,38 +1913,27 @@ GDBRemoteCommunicationServerLLGS::Handle_p(StringExtractorGDBRemote &packet) { } // Get the thread to use. - NativeThreadProtocolSP thread_sp = GetThreadFromSuffix(packet); - if (!thread_sp) { - if (log) - log->Printf( - "GDBRemoteCommunicationServerLLGS::%s failed, no thread available", - __FUNCTION__); + NativeThreadProtocol *thread = GetThreadFromSuffix(packet); + if (!thread) { + LLDB_LOG(log, "failed, no thread available"); return SendErrorResponse(0x15); } // Get the thread's register context. - NativeRegisterContextSP reg_context_sp(thread_sp->GetRegisterContext()); - if (!reg_context_sp) { - LLDB_LOG( - log, - "pid {0} tid {1} failed, no register context available for the thread", - m_debugged_process_up->GetID(), thread_sp->GetID()); - return SendErrorResponse(0x15); - } + NativeRegisterContext ®_context = thread->GetRegisterContext(); // Return the end of registers response if we've iterated one past the end of // the register set. - if (reg_index >= reg_context_sp->GetUserRegisterCount()) { + if (reg_index >= reg_context.GetUserRegisterCount()) { if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, requested " "register %" PRIu32 " beyond register count %" PRIu32, __FUNCTION__, reg_index, - reg_context_sp->GetUserRegisterCount()); + reg_context.GetUserRegisterCount()); return SendErrorResponse(0x15); } - const RegisterInfo *reg_info = - reg_context_sp->GetRegisterInfoAtIndex(reg_index); + const RegisterInfo *reg_info = reg_context.GetRegisterInfoAtIndex(reg_index); if (!reg_info) { if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, requested " @@ -1996,7 +1947,7 @@ GDBRemoteCommunicationServerLLGS::Handle_p(StringExtractorGDBRemote &packet) { // Retrieve the value RegisterValue reg_value; - Status error = reg_context_sp->ReadRegister(reg_info, reg_value); + Status error = reg_context.ReadRegister(reg_info, reg_value); if (error.Fail()) { if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, read of " @@ -2047,24 +1998,13 @@ GDBRemoteCommunicationServerLLGS::Handle_P(StringExtractorGDBRemote &packet) { return SendIllFormedResponse( packet, "P packet missing '=' char after register number"); - // Get process architecture. - ArchSpec process_arch; - if (!m_debugged_process_up || - !m_debugged_process_up->GetArchitecture(process_arch)) { - if (log) - log->Printf("GDBRemoteCommunicationServerLLGS::%s failed to retrieve " - "inferior architecture", - __FUNCTION__); - return SendErrorResponse(0x49); - } - // Parse out the value. uint8_t reg_bytes[32]; // big enough to support up to 256 bit ymmN register size_t reg_size = packet.GetHexBytesAvail(reg_bytes); // Get the thread to use. - NativeThreadProtocolSP thread_sp = GetThreadFromSuffix(packet); - if (!thread_sp) { + NativeThreadProtocol *thread = GetThreadFromSuffix(packet); + if (!thread) { if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, no thread " "available (thread index 0)", @@ -2073,18 +2013,8 @@ GDBRemoteCommunicationServerLLGS::Handle_P(StringExtractorGDBRemote &packet) { } // Get the thread's register context. - NativeRegisterContextSP reg_context_sp(thread_sp->GetRegisterContext()); - if (!reg_context_sp) { - if (log) - log->Printf( - "GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 " tid %" PRIu64 - " failed, no register context available for the thread", - __FUNCTION__, m_debugged_process_up->GetID(), thread_sp->GetID()); - return SendErrorResponse(0x15); - } - - const RegisterInfo *reg_info = - reg_context_sp->GetRegisterInfoAtIndex(reg_index); + NativeRegisterContext ®_context = thread->GetRegisterContext(); + const RegisterInfo *reg_info = reg_context.GetRegisterInfoAtIndex(reg_index); if (!reg_info) { if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, requested " @@ -2095,18 +2025,16 @@ GDBRemoteCommunicationServerLLGS::Handle_P(StringExtractorGDBRemote &packet) { // Return the end of registers response if we've iterated one past the end of // the register set. - if (reg_index >= reg_context_sp->GetUserRegisterCount()) { + if (reg_index >= reg_context.GetUserRegisterCount()) { if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, requested " "register %" PRIu32 " beyond register count %" PRIu32, - __FUNCTION__, reg_index, - reg_context_sp->GetUserRegisterCount()); + __FUNCTION__, reg_index, reg_context.GetUserRegisterCount()); return SendErrorResponse(0x47); } - // The dwarf expression are evaluate on host site - // which may cause register size to change - // Hence the reg_size may not be same as reg_info->bytes_size + // The dwarf expression are evaluate on host site which may cause register + // size to change Hence the reg_size may not be same as reg_info->bytes_size if ((reg_size != reg_info->byte_size) && !(reg_info->dynamic_size_dwarf_expr_bytes)) { return SendIllFormedResponse(packet, "P packet register size is incorrect"); @@ -2115,8 +2043,10 @@ GDBRemoteCommunicationServerLLGS::Handle_P(StringExtractorGDBRemote &packet) { // Build the reginfos response. StreamGDBRemote response; - RegisterValue reg_value(reg_bytes, reg_size, process_arch.GetByteOrder()); - Status error = reg_context_sp->WriteRegister(reg_info, reg_value); + RegisterValue reg_value( + reg_bytes, reg_size, + m_debugged_process_up->GetArchitecture().GetByteOrder()); + Status error = reg_context.WriteRegister(reg_info, reg_value); if (error.Fail()) { if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, write of " @@ -2177,8 +2107,8 @@ GDBRemoteCommunicationServerLLGS::Handle_H(StringExtractorGDBRemote &packet) { // Ensure we have the given thread when not specifying -1 (all threads) or 0 // (any thread). if (tid != LLDB_INVALID_THREAD_ID && tid != 0) { - NativeThreadProtocolSP thread_sp(m_debugged_process_up->GetThreadByID(tid)); - if (!thread_sp) { + NativeThreadProtocol *thread = m_debugged_process_up->GetThreadByID(tid); + if (!thread) { if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, tid %" PRIu64 " not found", @@ -2435,10 +2365,9 @@ GDBRemoteCommunicationServerLLGS::Handle_qMemoryRegionInfoSupported( Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); // Currently only the NativeProcessProtocol knows if it can handle a - // qMemoryRegionInfoSupported - // request, but we're not guaranteed to be attached to a process. For now - // we'll assume the - // client only asks this when a process is being debugged. + // qMemoryRegionInfoSupported request, but we're not guaranteed to be + // attached to a process. For now we'll assume the client only asks this + // when a process is being debugged. // Ensure we have a process running; otherwise, we can't figure this out // since we won't have a NativeProcessProtocol. @@ -2729,8 +2658,7 @@ GDBRemoteCommunicationServerLLGS::Handle_s(StringExtractorGDBRemote &packet) { } // We first try to use a continue thread id. If any one or any all set, use - // the current thread. - // Bail out if we don't have a thread id. + // the current thread. Bail out if we don't have a thread id. lldb::tid_t tid = GetContinueThreadID(); if (tid == 0 || tid == LLDB_INVALID_THREAD_ID) tid = GetCurrentThreadID(); @@ -2739,8 +2667,8 @@ GDBRemoteCommunicationServerLLGS::Handle_s(StringExtractorGDBRemote &packet) { // Double check that we have such a thread. // TODO investigate: on MacOSX we might need to do an UpdateThreads () here. - NativeThreadProtocolSP thread_sp = m_debugged_process_up->GetThreadByID(tid); - if (!thread_sp || thread_sp->GetID() != tid) + NativeThreadProtocol *thread = m_debugged_process_up->GetThreadByID(tid); + if (!thread) return SendErrorResponse(0x33); // Create the step action for the given thread. @@ -2770,7 +2698,7 @@ GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerLLGS::Handle_qXfer_auxv_read( StringExtractorGDBRemote &packet) { // *BSD impls should be able to do this too. -#if defined(__linux__) || defined(__NetBSD__) +#if defined(__linux__) || defined(__NetBSD__) || defined(__OpenBSD__) Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); // Parse out the offset. @@ -2865,8 +2793,8 @@ GDBRemoteCommunicationServerLLGS::Handle_QSaveRegisterState( packet.SetFilePos(strlen("QSaveRegisterState")); // Get the thread to use. - NativeThreadProtocolSP thread_sp = GetThreadFromSuffix(packet); - if (!thread_sp) { + NativeThreadProtocol *thread = GetThreadFromSuffix(packet); + if (!thread) { if (m_thread_suffix_supported) return SendIllFormedResponse( packet, "No thread specified in QSaveRegisterState packet"); @@ -2876,18 +2804,11 @@ GDBRemoteCommunicationServerLLGS::Handle_QSaveRegisterState( } // Grab the register context for the thread. - NativeRegisterContextSP reg_context_sp(thread_sp->GetRegisterContext()); - if (!reg_context_sp) { - LLDB_LOG( - log, - "pid {0} tid {1} failed, no register context available for the thread", - m_debugged_process_up->GetID(), thread_sp->GetID()); - return SendErrorResponse(0x15); - } + NativeRegisterContext& reg_context = thread->GetRegisterContext(); // Save registers to a buffer. DataBufferSP register_data_sp; - Status error = reg_context_sp->ReadAllRegisterValues(register_data_sp); + Status error = reg_context.ReadAllRegisterValues(register_data_sp); if (error.Fail()) { LLDB_LOG(log, "pid {0} failed to save all register values: {1}", m_debugged_process_up->GetID(), error); @@ -2930,8 +2851,8 @@ GDBRemoteCommunicationServerLLGS::Handle_QRestoreRegisterState( } // Get the thread to use. - NativeThreadProtocolSP thread_sp = GetThreadFromSuffix(packet); - if (!thread_sp) { + NativeThreadProtocol *thread = GetThreadFromSuffix(packet); + if (!thread) { if (m_thread_suffix_supported) return SendIllFormedResponse( packet, "No thread specified in QRestoreRegisterState packet"); @@ -2941,14 +2862,7 @@ GDBRemoteCommunicationServerLLGS::Handle_QRestoreRegisterState( } // Grab the register context for the thread. - NativeRegisterContextSP reg_context_sp(thread_sp->GetRegisterContext()); - if (!reg_context_sp) { - LLDB_LOG( - log, - "pid {0} tid {1} failed, no register context available for the thread", - m_debugged_process_up->GetID(), thread_sp->GetID()); - return SendErrorResponse(0x15); - } + NativeRegisterContext ®_context = thread->GetRegisterContext(); // Retrieve register state buffer, then remove from the list. DataBufferSP register_data_sp; @@ -2969,7 +2883,7 @@ GDBRemoteCommunicationServerLLGS::Handle_QRestoreRegisterState( m_saved_registers_map.erase(it); } - Status error = reg_context_sp->WriteAllRegisterValues(register_data_sp); + Status error = reg_context.WriteAllRegisterValues(register_data_sp); if (error.Fail()) { LLDB_LOG(log, "pid {0} failed to restore all register values: {1}", m_debugged_process_up->GetID(), error); @@ -3008,7 +2922,7 @@ GDBRemoteCommunicationServerLLGS::Handle_vAttach( log->Printf("GDBRemoteCommunicationServerLLGS::%s failed to attach to " "pid %" PRIu64 ": %s\n", __FUNCTION__, pid, error.AsCString()); - return SendErrorResponse(0x01); + return SendErrorResponse(error); } // Notify we attached by sending a stop packet. @@ -3166,8 +3080,8 @@ GDBRemoteCommunicationServerLLGS::Handle_QPassSignals( std::vector<int> signals; packet.SetFilePos(strlen("QPassSignals:")); - // Read sequence of hex signal numbers divided by a semicolon and - // optionally spaces. + // Read sequence of hex signal numbers divided by a semicolon and optionally + // spaces. while (packet.GetBytesLeft() > 0) { int signal = packet.GetS32(-1, 16); if (signal < 0) @@ -3219,22 +3133,19 @@ void GDBRemoteCommunicationServerLLGS::MaybeCloseInferiorTerminalConnection() { } } -NativeThreadProtocolSP GDBRemoteCommunicationServerLLGS::GetThreadFromSuffix( +NativeThreadProtocol *GDBRemoteCommunicationServerLLGS::GetThreadFromSuffix( StringExtractorGDBRemote &packet) { - NativeThreadProtocolSP thread_sp; - // We have no thread if we don't have a process. if (!m_debugged_process_up || m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID) - return thread_sp; + return nullptr; // If the client hasn't asked for thread suffix support, there will not be a - // thread suffix. - // Use the current thread in that case. + // thread suffix. Use the current thread in that case. if (!m_thread_suffix_supported) { const lldb::tid_t current_tid = GetCurrentThreadID(); if (current_tid == LLDB_INVALID_THREAD_ID) - return thread_sp; + return nullptr; else if (current_tid == 0) { // Pick a thread. return m_debugged_process_up->GetThreadAtIndex(0); @@ -3251,11 +3162,11 @@ NativeThreadProtocolSP GDBRemoteCommunicationServerLLGS::GetThreadFromSuffix( "error: expected ';' prior to start of thread suffix: packet " "contents = '%s'", __FUNCTION__, packet.GetStringRef().c_str()); - return thread_sp; + return nullptr; } if (!packet.GetBytesLeft()) - return thread_sp; + return nullptr; // Parse out thread: portion. if (strncmp(packet.Peek(), "thread:", strlen("thread:")) != 0) { @@ -3264,21 +3175,21 @@ NativeThreadProtocolSP GDBRemoteCommunicationServerLLGS::GetThreadFromSuffix( "error: expected 'thread:' but not found, packet contents = " "'%s'", __FUNCTION__, packet.GetStringRef().c_str()); - return thread_sp; + return nullptr; } packet.SetFilePos(packet.GetFilePos() + strlen("thread:")); const lldb::tid_t tid = packet.GetHexMaxU64(false, 0); if (tid != 0) return m_debugged_process_up->GetThreadByID(tid); - return thread_sp; + return nullptr; } lldb::tid_t GDBRemoteCommunicationServerLLGS::GetCurrentThreadID() const { if (m_current_tid == 0 || m_current_tid == LLDB_INVALID_THREAD_ID) { - // Use whatever the debug process says is the current thread id - // since the protocol either didn't specify or specified we want - // any/all threads marked as the current thread. + // Use whatever the debug process says is the current thread id since the + // protocol either didn't specify or specified we want any/all threads + // marked as the current thread. if (!m_debugged_process_up) return LLDB_INVALID_THREAD_ID; return m_debugged_process_up->GetCurrentThreadID(); @@ -3307,7 +3218,7 @@ GDBRemoteCommunicationServerLLGS::FindModuleFile(const std::string &module_path, if (m_debugged_process_up ->GetLoadedModuleFileSpec(module_path.c_str(), file_spec) .Success()) { - if (file_spec.Exists()) + if (FileSystem::Instance().Exists(file_spec)) return file_spec; } } diff --git a/gnu/llvm/tools/lldb/source/Utility/ArchSpec.cpp b/gnu/llvm/tools/lldb/source/Utility/ArchSpec.cpp index a10fe78260b..01accfee83e 100644 --- a/gnu/llvm/tools/lldb/source/Utility/ArchSpec.cpp +++ b/gnu/llvm/tools/lldb/source/Utility/ArchSpec.cpp @@ -9,16 +9,17 @@ #include "lldb/Utility/ArchSpec.h" +#include "lldb/Utility/Log.h" #include "lldb/Utility/NameMatches.h" -#include "lldb/Utility/Stream.h" // for Stream +#include "lldb/Utility/Stream.h" #include "lldb/Utility/StringList.h" -#include "lldb/lldb-defines.h" // for LLDB_INVALID_C... +#include "lldb/lldb-defines.h" #include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/Twine.h" // for Twine +#include "llvm/ADT/Twine.h" #include "llvm/BinaryFormat/COFF.h" #include "llvm/BinaryFormat/ELF.h" -#include "llvm/BinaryFormat/MachO.h" // for CPUType::CPU_T... -#include "llvm/Support/Compiler.h" // for LLVM_FALLTHROUGH +#include "llvm/BinaryFormat/MachO.h" +#include "llvm/Support/Compiler.h" #include "llvm/Support/Host.h" using namespace lldb; @@ -203,6 +204,8 @@ static const CoreDefinition g_core_definitions[] = { ArchSpec::eCore_x86_64_x86_64, "x86_64"}, {eByteOrderLittle, 8, 1, 15, llvm::Triple::x86_64, ArchSpec::eCore_x86_64_x86_64h, "x86_64h"}, + {eByteOrderLittle, 8, 1, 15, llvm::Triple::x86_64, + ArchSpec::eCore_x86_64_amd64, "amd64"}, {eByteOrderLittle, 4, 4, 4, llvm::Triple::hexagon, ArchSpec::eCore_hexagon_generic, "hexagon"}, {eByteOrderLittle, 4, 4, 4, llvm::Triple::hexagon, @@ -223,8 +226,8 @@ static const CoreDefinition g_core_definitions[] = { "kalimba5"}}; // Ensure that we have an entry in the g_core_definitions for each core. If you -// comment out an entry above, -// you will need to comment out the corresponding ArchSpec::Core enumeration. +// comment out an entry above, you will need to comment out the corresponding +// ArchSpec::Core enumeration. static_assert(sizeof(g_core_definitions) / sizeof(CoreDefinition) == ArchSpec::kNumCores, "make sure we have one core definition for each core"); @@ -244,17 +247,24 @@ struct ArchDefinition { const char *name; }; -size_t ArchSpec::AutoComplete(llvm::StringRef name, StringList &matches) { - if (!name.empty()) { +void ArchSpec::ListSupportedArchNames(StringList &list) { + for (uint32_t i = 0; i < llvm::array_lengthof(g_core_definitions); ++i) + list.AppendString(g_core_definitions[i].name); +} + +size_t ArchSpec::AutoComplete(CompletionRequest &request) { + if (!request.GetCursorArgumentPrefix().empty()) { for (uint32_t i = 0; i < llvm::array_lengthof(g_core_definitions); ++i) { - if (NameMatches(g_core_definitions[i].name, NameMatch::StartsWith, name)) - matches.AppendString(g_core_definitions[i].name); + if (NameMatches(g_core_definitions[i].name, NameMatch::StartsWith, + request.GetCursorArgumentPrefix())) + request.AddCompletion(g_core_definitions[i].name); } } else { - for (uint32_t i = 0; i < llvm::array_lengthof(g_core_definitions); ++i) - matches.AppendString(g_core_definitions[i].name); + StringList matches; + ListSupportedArchNames(matches); + request.AddCompletions(matches); } - return matches.GetSize(); + return request.GetNumberOfMatches(); } #define CPU_ANY (UINT32_MAX) @@ -602,10 +612,8 @@ const char *ArchSpec::GetArchitectureName() const { bool ArchSpec::IsMIPS() const { const llvm::Triple::ArchType machine = GetMachine(); - if (machine == llvm::Triple::mips || machine == llvm::Triple::mipsel || - machine == llvm::Triple::mips64 || machine == llvm::Triple::mips64el) - return true; - return false; + return machine == llvm::Triple::mips || machine == llvm::Triple::mipsel || + machine == llvm::Triple::mips64 || machine == llvm::Triple::mips64el; } std::string ArchSpec::GetTargetABI() const { @@ -807,6 +815,7 @@ bool ArchSpec::CharIsSignedByDefault() const { case llvm::Triple::ppc64le: case llvm::Triple::systemz: case llvm::Triple::xcore: + case llvm::Triple::arc: return false; } } @@ -890,7 +899,12 @@ void ArchSpec::MergeFrom(const ArchSpec &other) { GetTriple().setOS(other.GetTriple().getOS()); if (GetTriple().getArch() == llvm::Triple::UnknownArch) { GetTriple().setArch(other.GetTriple().getArch()); - UpdateCore(); + + // MachO unknown64 isn't really invalid as the debugger can still obtain + // information from the binary, e.g. line tables. As such, we don't update + // the core here. + if (other.GetCore() != eCore_uknownMach64) + UpdateCore(); } if (GetTriple().getEnvironment() == llvm::Triple::UnknownEnvironment && !TripleVendorWasSpecified()) { @@ -898,9 +912,8 @@ void ArchSpec::MergeFrom(const ArchSpec &other) { GetTriple().setEnvironment(other.GetTriple().getEnvironment()); } // If this and other are both arm ArchSpecs and this ArchSpec is a generic - // "some kind of arm" - // spec but the other ArchSpec is a specific arm core, adopt the specific arm - // core. + // "some kind of arm" spec but the other ArchSpec is a specific arm core, + // adopt the specific arm core. if (GetTriple().getArch() == llvm::Triple::arm && other.GetTriple().getArch() == llvm::Triple::arm && IsCompatibleMatch(other) && GetCore() == ArchSpec::eCore_arm_generic && @@ -926,24 +939,21 @@ bool ArchSpec::SetArchitecture(ArchitectureType arch_type, uint32_t cpu, if (core_def) { m_core = core_def->core; update_triple = false; - // Always use the architecture name because it might be more descriptive - // than the architecture enum ("armv7" -> llvm::Triple::arm). + // Always use the architecture name because it might be more + // descriptive than the architecture enum ("armv7" -> + // llvm::Triple::arm). m_triple.setArchName(llvm::StringRef(core_def->name)); if (arch_type == eArchTypeMachO) { m_triple.setVendor(llvm::Triple::Apple); // Don't set the OS. It could be simulator, macosx, ios, watchos, - // tvos. We could - // get close with the cpu type - but we can't get it right all of the - // time. Better - // to leave this unset so other sections of code will set it when they - // have more - // information. - // NB: don't call m_triple.setOS (llvm::Triple::UnknownOS). That sets - // the OSName to - // "unknown" and the ArchSpec::TripleVendorWasSpecified() method says - // that any - // OSName setting means it was specified. + // tvos, bridgeos. We could get close with the cpu type - but we + // can't get it right all of the time. Better to leave this unset + // so other sections of code will set it when they have more + // information. NB: don't call m_triple.setOS (llvm::Triple::UnknownOS). + // That sets the OSName to "unknown" and the + // ArchSpec::TripleVendorWasSpecified() method says that any OSName + // setting means it was specified. } else if (arch_type == eArchTypeELF) { switch (os) { case llvm::ELF::ELFOSABI_AIX: @@ -972,10 +982,15 @@ bool ArchSpec::SetArchitecture(ArchitectureType arch_type, uint32_t cpu, m_triple.setVendor(llvm::Triple::UnknownVendor); m_triple.setOS(llvm::Triple::UnknownOS); } - // Fall back onto setting the machine type if the arch by name failed... + // Fall back onto setting the machine type if the arch by name + // failed... if (m_triple.getArch() == llvm::Triple::UnknownArch) m_triple.setArch(core_def->machine); } + } else { + Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_TARGET | LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_PLATFORM)); + if (log) + log->Printf("Unable to find a core definition for cpu 0x%" PRIx32 " sub %" PRId32, cpu, sub); } } CoreUpdated(update_triple); @@ -1004,7 +1019,7 @@ bool ArchSpec::IsCompatibleMatch(const ArchSpec &rhs) const { return IsEqualTo(rhs, false); } -static bool isCompatibleEnvironment(llvm::Triple::EnvironmentType lhs, +static bool IsCompatibleEnvironment(llvm::Triple::EnvironmentType lhs, llvm::Triple::EnvironmentType rhs) { if (lhs == rhs) return true; @@ -1015,10 +1030,9 @@ static bool isCompatibleEnvironment(llvm::Triple::EnvironmentType lhs, return true; // If one of the environment is Android and the other one is EABI then they - // are considered to - // be compatible. This is required as a workaround for shared libraries - // compiled for Android - // without the NOTE section indicating that they are using the Android ABI. + // are considered to be compatible. This is required as a workaround for + // shared libraries compiled for Android without the NOTE section indicating + // that they are using the Android ABI. if ((lhs == llvm::Triple::Android && rhs == llvm::Triple::EABI) || (rhs == llvm::Triple::Android && lhs == llvm::Triple::EABI) || (lhs == llvm::Triple::GNUEABI && rhs == llvm::Triple::EABI) || @@ -1050,8 +1064,8 @@ bool ArchSpec::IsEqualTo(const ArchSpec &rhs, bool exact_match) const { if (lhs_triple_vendor != rhs_triple_vendor) { const bool rhs_vendor_specified = rhs.TripleVendorWasSpecified(); const bool lhs_vendor_specified = TripleVendorWasSpecified(); - // Both architectures had the vendor specified, so if they aren't - // equal then we return false + // Both architectures had the vendor specified, so if they aren't equal + // then we return false if (rhs_vendor_specified && lhs_vendor_specified) return false; @@ -1066,8 +1080,8 @@ bool ArchSpec::IsEqualTo(const ArchSpec &rhs, bool exact_match) const { if (lhs_triple_os != rhs_triple_os) { const bool rhs_os_specified = rhs.TripleOSWasSpecified(); const bool lhs_os_specified = TripleOSWasSpecified(); - // Both architectures had the OS specified, so if they aren't - // equal then we return false + // Both architectures had the OS specified, so if they aren't equal then + // we return false if (rhs_os_specified && lhs_os_specified) return false; @@ -1082,9 +1096,7 @@ bool ArchSpec::IsEqualTo(const ArchSpec &rhs, bool exact_match) const { const llvm::Triple::EnvironmentType rhs_triple_env = rhs_triple.getEnvironment(); - if (!isCompatibleEnvironment(lhs_triple_env, rhs_triple_env)) - return false; - return true; + return IsCompatibleEnvironment(lhs_triple_env, rhs_triple_env); } return false; } @@ -1094,9 +1106,9 @@ void ArchSpec::UpdateCore() { const CoreDefinition *core_def = FindCoreDefinition(arch_name); if (core_def) { m_core = core_def->core; - // Set the byte order to the default byte order for an architecture. - // This can be modified if needed for cases when cores handle both - // big and little endian + // Set the byte order to the default byte order for an architecture. This + // can be modified if needed for cases when cores handle both big and + // little endian m_byte_order = core_def->default_byte_order; } else { Clear(); @@ -1193,9 +1205,8 @@ static bool cores_match(const ArchSpec::Core core1, const ArchSpec::Core core2, break; // v. https://en.wikipedia.org/wiki/ARM_Cortex-M#Silicon_customization - // Cortex-M0 - ARMv6-M - armv6m - // Cortex-M3 - ARMv7-M - armv7m - // Cortex-M4 - ARMv7E-M - armv7em + // Cortex-M0 - ARMv6-M - armv6m Cortex-M3 - ARMv7-M - armv7m Cortex-M4 - + // ARMv7E-M - armv7em case ArchSpec::eCore_arm_armv7em: if (!enforce_exact_match) { if (core2 == ArchSpec::eCore_arm_generic) @@ -1211,9 +1222,8 @@ static bool cores_match(const ArchSpec::Core core1, const ArchSpec::Core core2, break; // v. https://en.wikipedia.org/wiki/ARM_Cortex-M#Silicon_customization - // Cortex-M0 - ARMv6-M - armv6m - // Cortex-M3 - ARMv7-M - armv7m - // Cortex-M4 - ARMv7E-M - armv7em + // Cortex-M0 - ARMv6-M - armv6m Cortex-M3 - ARMv7-M - armv7m Cortex-M4 - + // ARMv7E-M - armv7em case ArchSpec::eCore_arm_armv7m: if (!enforce_exact_match) { if (core2 == ArchSpec::eCore_arm_generic) @@ -1242,9 +1252,17 @@ static bool cores_match(const ArchSpec::Core core1, const ArchSpec::Core core2, case ArchSpec::eCore_x86_64_x86_64h: if (!enforce_exact_match) { + if (core2 == ArchSpec::eCore_x86_64_x86_64) + return true; try_inverse = false; + } + break; + + case ArchSpec::eCore_x86_64_amd64: + if (!enforce_exact_match) { if (core2 == ArchSpec::eCore_x86_64_x86_64) return true; + try_inverse = false; } break; @@ -1411,6 +1429,11 @@ bool lldb_private::operator<(const ArchSpec &lhs, const ArchSpec &rhs) { return lhs_core < rhs_core; } + +bool lldb_private::operator==(const ArchSpec &lhs, const ArchSpec &rhs) { + return lhs.GetCore() == rhs.GetCore(); +} + bool ArchSpec::IsFullySpecifiedTriple() const { const auto &user_specified_triple = GetTriple(); @@ -1456,13 +1479,15 @@ bool ArchSpec::IsAlwaysThumbInstructions() const { // Cortex-M0 through Cortex-M7 are ARM processor cores which can only // execute thumb instructions. We map the cores to arch names like this: // - // Cortex-M0, Cortex-M0+, Cortex-M1: armv6m - // Cortex-M3: armv7m - // Cortex-M4, Cortex-M7: armv7em + // Cortex-M0, Cortex-M0+, Cortex-M1: armv6m Cortex-M3: armv7m Cortex-M4, + // Cortex-M7: armv7em if (GetCore() == ArchSpec::Core::eCore_arm_armv7m || GetCore() == ArchSpec::Core::eCore_arm_armv7em || - GetCore() == ArchSpec::Core::eCore_arm_armv6m) { + GetCore() == ArchSpec::Core::eCore_arm_armv6m || + GetCore() == ArchSpec::Core::eCore_thumbv7m || + GetCore() == ArchSpec::Core::eCore_thumbv7em || + GetCore() == ArchSpec::Core::eCore_thumbv6m) { return true; } } diff --git a/gnu/llvm/tools/lldb/tools/lldb-server/CMakeLists.txt b/gnu/llvm/tools/lldb/tools/lldb-server/CMakeLists.txt index f8c57cb9488..0b3cbbacd63 100644 --- a/gnu/llvm/tools/lldb/tools/lldb-server/CMakeLists.txt +++ b/gnu/llvm/tools/lldb/tools/lldb-server/CMakeLists.txt @@ -22,42 +22,15 @@ include_directories( ) endif () -include_directories(../../source) - -set(LLDB_SYSTEM_LIBS) -if (NOT LLDB_DISABLE_LIBEDIT) - list(APPEND LLDB_SYSTEM_LIBS edit) -endif() -if (NOT LLDB_DISABLE_CURSES) - list(APPEND LLDB_SYSTEM_LIBS ${CURSES_LIBRARIES}) - if(LLVM_ENABLE_TERMINFO AND HAVE_TERMINFO) - list(APPEND LLDB_SYSTEM_LIBS ${TERMINFO_LIBS}) - endif() -endif() - -if (NOT HAVE_CXX_ATOMICS64_WITHOUT_LIB ) - list(APPEND LLDB_SYSTEM_LIBS atomic) -endif() - -# On FreeBSD/NetBSD backtrace() is provided by libexecinfo, not libc. -if (CMAKE_SYSTEM_NAME MATCHES "FreeBSD" OR CMAKE_SYSTEM_NAME MATCHES "NetBSD") - list(APPEND LLDB_SYSTEM_LIBS execinfo) -endif() - -if (NOT LLDB_DISABLE_PYTHON AND NOT LLVM_BUILD_STATIC) - list(APPEND LLDB_SYSTEM_LIBS ${PYTHON_LIBRARIES}) -endif() - -list(APPEND LLDB_SYSTEM_LIBS ${system_libs}) +if ( CMAKE_SYSTEM_NAME MATCHES "OpenBSD" ) +include_directories( + ../../../../llvm/include + ../../source/Plugins/Process/OpenBSD + ../../source/Plugins/Process/POSIX + ) +endif () -if (LLVM_BUILD_STATIC) - if (NOT LLDB_DISABLE_PYTHON) - list(APPEND LLDB_SYSTEM_LIBS python2.7 util) - endif() - if (NOT LLDB_DISABLE_CURSES) - list(APPEND LLDB_SYSTEM_LIBS gpm) - endif() -endif() +include_directories(../../source) set(LLDB_PLUGINS) @@ -69,12 +42,25 @@ if(CMAKE_SYSTEM_NAME MATCHES "NetBSD") list(APPEND LLDB_PLUGINS lldbPluginProcessNetBSD) endif() -add_lldb_tool(lldb-server INCLUDE_IN_FRAMEWORK +if(CMAKE_SYSTEM_NAME MATCHES "OpenBSD") + list(APPEND LLDB_PLUGINS lldbPluginProcessOpenBSD) +endif() + +if(CMAKE_SYSTEM_NAME MATCHES "Darwin") + list(APPEND LLDB_PLUGINS lldbPluginObjectFileMachO) +elseif(CMAKE_SYSTEM_NAME MATCHES "Windows") + list(APPEND LLDB_PLUGINS lldbPluginObjectFilePECOFF) +else() + list(APPEND LLDB_PLUGINS lldbPluginObjectFileELF) +endif() + +add_lldb_tool(lldb-server Acceptor.cpp lldb-gdbserver.cpp lldb-platform.cpp lldb-server.cpp LLDBServerUtilities.cpp + SystemInitializerLLGS.cpp LINK_LIBS lldbBase @@ -89,4 +75,4 @@ add_lldb_tool(lldb-server INCLUDE_IN_FRAMEWORK Support ) -target_link_libraries(lldb-server ${LLDB_SYSTEM_LIBS}) +target_link_libraries(lldb-server PRIVATE ${LLDB_SYSTEM_LIBS}) diff --git a/gnu/llvm/tools/lldb/tools/lldb-server/lldb-gdbserver.cpp b/gnu/llvm/tools/lldb/tools/lldb-server/lldb-gdbserver.cpp index f1a9b113c8e..78384e97a00 100644 --- a/gnu/llvm/tools/lldb/tools/lldb-server/lldb-gdbserver.cpp +++ b/gnu/llvm/tools/lldb/tools/lldb-server/lldb-gdbserver.cpp @@ -7,7 +7,6 @@ // //===----------------------------------------------------------------------===// -// C Includes #include <errno.h> #include <stdint.h> #include <stdio.h> @@ -19,8 +18,6 @@ #include <unistd.h> #endif -// C++ Includes - #include "Acceptor.h" #include "LLDBServerUtilities.h" @@ -28,6 +25,7 @@ #include "Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h" #include "lldb/Core/PluginManager.h" #include "lldb/Host/ConnectionFileDescriptor.h" +#include "lldb/Host/FileSystem.h" #include "lldb/Host/HostGetOpt.h" #include "lldb/Host/OptionParser.h" #include "lldb/Host/Pipe.h" @@ -42,6 +40,8 @@ #include "Plugins/Process/Linux/NativeProcessLinux.h" #elif defined(__NetBSD__) #include "Plugins/Process/NetBSD/NativeProcessNetBSD.h" +#elif defined(__OpenBSD__) +#include "Plugins/Process/OpenBSD/NativeProcessOpenBSD.h" #endif #ifndef LLGS_PROGRAM_NAME @@ -63,6 +63,8 @@ namespace { typedef process_linux::NativeProcessLinux::Factory NativeProcessFactory; #elif defined(__NetBSD__) typedef process_netbsd::NativeProcessNetBSD::Factory NativeProcessFactory; +#elif defined(__OpenBSD__) +typedef process_openbsd::NativeProcessOpenBSD::Factory NativeProcessFactory; #else // Dummy implementation to make sure the code compiles class NativeProcessFactory : public NativeProcessProtocol::Factory { @@ -106,6 +108,7 @@ static struct option g_long_options[] = { // than llgs listening for a connection from address on port. {"setsid", no_argument, NULL, 'S'}, // Call setsid() to make llgs run in its own session. + {"fd", required_argument, NULL, 'F'}, {NULL, 0, NULL, 0}}; //---------------------------------------------------------------------- @@ -132,13 +135,13 @@ static void display_usage(const char *progname, const char *subcommand) { "[--log-file log-file-name] " "[--log-channels log-channel-list] " "[--setsid] " + "[--fd file-descriptor]" "[--named-pipe named-pipe-path] " "[--native-regs] " "[--attach pid] " "[[HOST]:PORT] " "[-- PROGRAM ARG1 ARG2 ...]\n", progname, subcommand); - exit(0); } void handle_attach_to_pid(GDBRemoteCommunicationServerLLGS &gdb_server, @@ -176,27 +179,27 @@ void handle_attach(GDBRemoteCommunicationServerLLGS &gdb_server, void handle_launch(GDBRemoteCommunicationServerLLGS &gdb_server, int argc, const char *const argv[]) { - Status error; - error = gdb_server.SetLaunchArguments(argv, argc); - if (error.Fail()) { - fprintf(stderr, "error: failed to set launch args for '%s': %s\n", argv[0], - error.AsCString()); + ProcessLaunchInfo info; + info.GetFlags().Set(eLaunchFlagStopAtEntry | eLaunchFlagDebug | + eLaunchFlagDisableASLR); + info.SetArguments(const_cast<const char **>(argv), true); + + llvm::SmallString<64> cwd; + if (std::error_code ec = llvm::sys::fs::current_path(cwd)) { + llvm::errs() << "Error getting current directory: " << ec.message() << "\n"; exit(1); } + FileSpec cwd_spec(cwd); + FileSystem::Instance().Resolve(cwd_spec); + info.SetWorkingDirectory(cwd_spec); + info.GetEnvironment() = Host::GetEnvironment(); - unsigned int launch_flags = eLaunchFlagStopAtEntry | eLaunchFlagDebug; - - error = gdb_server.SetLaunchFlags(launch_flags); - if (error.Fail()) { - fprintf(stderr, "error: failed to set launch flags for '%s': %s\n", argv[0], - error.AsCString()); - exit(1); - } + gdb_server.SetLaunchInfo(info); - error = gdb_server.LaunchProcess(); + Status error = gdb_server.LaunchProcess(); if (error.Fail()) { - fprintf(stderr, "error: failed to launch '%s': %s\n", argv[0], - error.AsCString()); + llvm::errs() << llvm::formatv("error: failed to launch '{0}': {1}\n", + argv[0], error); exit(1); } } @@ -219,23 +222,44 @@ Status writeSocketIdToPipe(const char *const named_pipe_path, return writeSocketIdToPipe(port_name_pipe, socket_id); } -Status writeSocketIdToPipe(int unnamed_pipe_fd, const std::string &socket_id) { -#if defined(_WIN32) - return Status("Unnamed pipes are not supported on Windows."); -#else - Pipe port_pipe{Pipe::kInvalidDescriptor, unnamed_pipe_fd}; +Status writeSocketIdToPipe(lldb::pipe_t unnamed_pipe, + const std::string &socket_id) { + Pipe port_pipe{LLDB_INVALID_PIPE, unnamed_pipe}; return writeSocketIdToPipe(port_pipe, socket_id); -#endif } void ConnectToRemote(MainLoop &mainloop, GDBRemoteCommunicationServerLLGS &gdb_server, bool reverse_connect, const char *const host_and_port, const char *const progname, const char *const subcommand, - const char *const named_pipe_path, int unnamed_pipe_fd) { + const char *const named_pipe_path, pipe_t unnamed_pipe, + int connection_fd) { Status error; - if (host_and_port && host_and_port[0]) { + std::unique_ptr<Connection> connection_up; + if (connection_fd != -1) { + // Build the connection string. + char connection_url[512]; + snprintf(connection_url, sizeof(connection_url), "fd://%d", connection_fd); + + // Create the connection. +#if !defined LLDB_DISABLE_POSIX && !defined _WIN32 + ::fcntl(connection_fd, F_SETFD, FD_CLOEXEC); +#endif + connection_up.reset(new ConnectionFileDescriptor); + auto connection_result = connection_up->Connect(connection_url, &error); + if (connection_result != eConnectionStatusSuccess) { + fprintf(stderr, "error: failed to connect to client at '%s' " + "(connection status: %d)\n", + connection_url, static_cast<int>(connection_result)); + exit(-1); + } + if (error.Fail()) { + fprintf(stderr, "error: failed to connect to client at '%s': %s\n", + connection_url, error.AsCString()); + exit(-1); + } + } else if (host_and_port && host_and_port[0]) { // Parse out host and port. std::string final_host_and_port; std::string connection_host; @@ -255,7 +279,6 @@ void ConnectToRemote(MainLoop &mainloop, connection_portno = StringConvert::ToUInt32(connection_port.c_str(), 0); } - std::unique_ptr<Connection> connection_up; if (reverse_connect) { // llgs will connect to the gdb-remote client. @@ -263,7 +286,7 @@ void ConnectToRemote(MainLoop &mainloop, // Ensure we have a port number for the connection. if (connection_portno == 0) { fprintf(stderr, "error: port number must be specified on when using " - "reverse connect"); + "reverse connect\n"); exit(1); } @@ -277,12 +300,12 @@ void ConnectToRemote(MainLoop &mainloop, auto connection_result = connection_up->Connect(connection_url, &error); if (connection_result != eConnectionStatusSuccess) { fprintf(stderr, "error: failed to connect to client at '%s' " - "(connection status: %d)", + "(connection status: %d)\n", connection_url, static_cast<int>(connection_result)); exit(-1); } if (error.Fail()) { - fprintf(stderr, "error: failed to connect to client at '%s': %s", + fprintf(stderr, "error: failed to connect to client at '%s': %s\n", connection_url, error.AsCString()); exit(-1); } @@ -290,7 +313,7 @@ void ConnectToRemote(MainLoop &mainloop, std::unique_ptr<Acceptor> acceptor_up( Acceptor::Create(final_host_and_port, false, error)); if (error.Fail()) { - fprintf(stderr, "failed to create acceptor: %s", error.AsCString()); + fprintf(stderr, "failed to create acceptor: %s\n", error.AsCString()); exit(1); } error = acceptor_up->Listen(1); @@ -304,15 +327,15 @@ void ConnectToRemote(MainLoop &mainloop, if (named_pipe_path && named_pipe_path[0]) { error = writeSocketIdToPipe(named_pipe_path, socket_id); if (error.Fail()) - fprintf(stderr, "failed to write to the named pipe \'%s\': %s", + fprintf(stderr, "failed to write to the named pipe \'%s\': %s\n", named_pipe_path, error.AsCString()); } // If we have an unnamed pipe to write the socket id back to, do that // now. - else if (unnamed_pipe_fd >= 0) { - error = writeSocketIdToPipe(unnamed_pipe_fd, socket_id); + else if (unnamed_pipe != LLDB_INVALID_PIPE) { + error = writeSocketIdToPipe(unnamed_pipe, socket_id); if (error.Fail()) - fprintf(stderr, "failed to write to the unnamed pipe: %s", + fprintf(stderr, "failed to write to the unnamed pipe: %s\n", error.AsCString()); } } else { @@ -328,14 +351,14 @@ void ConnectToRemote(MainLoop &mainloop, } connection_up.reset(conn); } - error = gdb_server.InitializeConnection(std::move(connection_up)); - if (error.Fail()) { - fprintf(stderr, "Failed to initialize connection: %s\n", - error.AsCString()); - exit(-1); - } - printf("Connection established.\n"); } + error = gdb_server.InitializeConnection(std::move(connection_up)); + if (error.Fail()) { + fprintf(stderr, "Failed to initialize connection: %s\n", + error.AsCString()); + exit(-1); + } + printf("Connection established.\n"); } //---------------------------------------------------------------------- @@ -362,8 +385,9 @@ int main_gdbserver(int argc, char *argv[]) { std::string log_file; StringRef log_channels; // e.g. "lldb process threads:gdb-remote default:linux all" - int unnamed_pipe_fd = -1; + lldb::pipe_t unnamed_pipe = LLDB_INVALID_PIPE; bool reverse_connect = false; + int connection_fd = -1; // ProcessLaunchInfo launch_info; ProcessAttachInfo attach_info; @@ -402,7 +426,7 @@ int main_gdbserver(int argc, char *argv[]) { case 'U': // unnamed pipe if (optarg && optarg[0]) - unnamed_pipe_fd = StringConvert::ToUInt32(optarg, -1); + unnamed_pipe = (pipe_t)StringConvert::ToUInt64(optarg, -1); break; case 'r': @@ -413,6 +437,10 @@ int main_gdbserver(int argc, char *argv[]) { reverse_connect = true; break; + case 'F': + connection_fd = StringConvert::ToUInt32(optarg, -1); + break; + #ifndef _WIN32 case 'S': // Put llgs into a new session. Terminals group processes @@ -472,7 +500,8 @@ int main_gdbserver(int argc, char *argv[]) { argc -= optind; argv += optind; - if (argc == 0) { + if (argc == 0 && connection_fd == -1) { + fputs("No arguments\n", stderr); display_usage(progname, subcommand); exit(255); } @@ -500,8 +529,8 @@ int main_gdbserver(int argc, char *argv[]) { printf("%s-%s", LLGS_PROGRAM_NAME, LLGS_VERSION_STR); ConnectToRemote(mainloop, gdb_server, reverse_connect, host_and_port, - progname, subcommand, named_pipe_path.c_str(), - unnamed_pipe_fd); + progname, subcommand, named_pipe_path.c_str(), + unnamed_pipe, connection_fd); if (!gdb_server.IsConnected()) { fprintf(stderr, "no connection information provided, unable to run\n"); diff --git a/gnu/usr.bin/clang/Makefile b/gnu/usr.bin/clang/Makefile index 13656a7cf6d..7774de69a80 100644 --- a/gnu/usr.bin/clang/Makefile +++ b/gnu/usr.bin/clang/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.11 2019/03/05 09:44:38 jsg Exp $ +# $OpenBSD: Makefile,v 1.12 2019/11/09 16:45:48 mortimer Exp $ .include <bsd.own.mk> @@ -87,6 +87,7 @@ SUBDIR+=liblldbTarget SUBDIR+=liblldbUtility SUBDIR+=lldb +SUBDIR+=lldb-server .include <bsd.obj.mk> .include <bsd.subdir.mk> diff --git a/gnu/usr.bin/clang/liblldbPluginProcess/Makefile b/gnu/usr.bin/clang/liblldbPluginProcess/Makefile index a06e216090b..acbb117b1d1 100644 --- a/gnu/usr.bin/clang/liblldbPluginProcess/Makefile +++ b/gnu/usr.bin/clang/liblldbPluginProcess/Makefile @@ -1,11 +1,12 @@ -# $OpenBSD: Makefile,v 1.3 2019/06/23 22:07:44 patrick Exp $ +# $OpenBSD: Makefile,v 1.4 2019/11/09 16:45:48 mortimer Exp $ LIB= lldbPluginProcess NOPIC= NOPROFILE= .include <bsd.own.mk> -SRCS= DynamicRegisterInfo.cpp \ +SRCS= CrashReason.cpp \ + DynamicRegisterInfo.cpp \ FreeBSDSignals.cpp \ GDBRemoteClientBase.cpp \ GDBRemoteCommunication.cpp \ @@ -13,6 +14,7 @@ SRCS= DynamicRegisterInfo.cpp \ GDBRemoteCommunicationHistory.cpp \ GDBRemoteCommunicationReplayServer.cpp \ GDBRemoteCommunicationServer.cpp \ + GDBRemoteCommunicationServerCommon.cpp \ GDBRemoteCommunicationServerLLGS.cpp \ GDBRemoteCommunicationServerPlatform.cpp \ GDBRemoteRegisterContext.cpp \ @@ -25,13 +27,19 @@ SRCS= DynamicRegisterInfo.cpp \ MinidumpParser.cpp \ MinidumpTypes.cpp \ MipsLinuxSignals.cpp \ + NativeProcessOpenBSD.cpp \ + NativeRegisterContextOpenBSD.cpp \ + NativeRegisterContextOpenBSD_x86_64.cpp \ NativeRegisterContextRegisterInfo.cpp \ + NativeThreadOpenBSD.cpp \ NetBSDSignals.cpp \ ProcessElfCore.cpp \ ProcessGDBRemote.cpp \ ProcessGDBRemoteLog.cpp \ ProcessMachCore.cpp \ + ProcessMessage.cpp \ ProcessMinidump.cpp \ + ProcessPOSIXLog.cpp \ RegisterContextDarwin_arm.cpp \ RegisterContextDarwin_arm64.cpp \ RegisterContextDarwin_i386.cpp \ @@ -93,6 +101,8 @@ SRCS= DynamicRegisterInfo.cpp \ .PATH: ${.CURDIR}/../../../llvm/tools/lldb/source/Plugins/Process/gdb-remote .PATH: ${.CURDIR}/../../../llvm/tools/lldb/source/Plugins/Process/mach-core .PATH: ${.CURDIR}/../../../llvm/tools/lldb/source/Plugins/Process/minidump +.PATH: ${.CURDIR}/../../../llvm/tools/lldb/source/Plugins/Process/POSIX +.PATH: ${.CURDIR}/../../../llvm/tools/lldb/source/Plugins/Process/OpenBSD install: @# Nothing here so far ... diff --git a/gnu/usr.bin/clang/lldb-server/Makefile b/gnu/usr.bin/clang/lldb-server/Makefile new file mode 100644 index 00000000000..2e1c46ef1bd --- /dev/null +++ b/gnu/usr.bin/clang/lldb-server/Makefile @@ -0,0 +1,81 @@ +# $OpenBSD: Makefile,v 1.1 2019/11/09 16:45:48 mortimer Exp $ + +.include <bsd.own.mk> + +NOPROG= lldb-server +BINDIR= /usr/bin +NOMAN= + +SRCS= Acceptor.cpp \ + LLDBServerUtilities.cpp \ + SystemInitializerLLGS.cpp \ + lldb-platform.cpp \ + lldb-gdbserver.cpp \ + lldb-server.cpp \ + lldb.cpp \ + +LDADD+= -lcurses -ledit -lpanel + + +.PATH: ${.CURDIR}/../../../llvm/tools/lldb/source +.PATH: ${.CURDIR}/../../../llvm/tools/lldb/tools/lldb-server + +LLVM_LIBDEPS= clangAST \ + clangAnalysis \ + clangBasic \ + clangBasicTargets \ + clangCodeGen \ + clangDriver \ + clangDriverArch \ + clangEdit \ + clangFrontend \ + clangLex \ + clangParse \ + clangRewrite \ + clangRewriteFrontend \ + clangSema \ + clangSerialization \ + lldbABI \ + lldbAPI \ + lldbBreakpoint \ + lldbCommands \ + lldbCore \ + lldbDataFormatters \ + lldbExpression \ + lldbHostCommon \ + lldbHostOpenBSD \ + lldbHostPOSIX \ + lldbInitialization \ + lldbInterpreter \ + lldbPluginArchitecture \ + lldbPluginDisassembler \ + lldbPluginDynamicLoader \ + lldbPluginExpressionParser \ + lldbPluginInstruction \ + lldbPluginInstrumentationRuntime \ + lldbPluginJITLoader \ + lldbPluginLanguage \ + lldbPluginLanguageRuntime \ + lldbPluginMemoryHistory \ + lldbPluginObjectContainer \ + lldbPluginObjectFile \ + lldbPluginOperatingSystem \ + lldbPluginPlatform \ + lldbPluginProcess \ + lldbPluginScriptInterpreter \ + lldbPluginStructuredData \ + lldbPluginSymbolFile \ + lldbPluginSymbolVendor \ + lldbPluginSystemRuntime \ + lldbPluginUnwindAssembly \ + lldbSymbol \ + lldbTarget \ + lldbUtility + + +LDADD+= -L ${.OBJDIR}/../libLLVM -lLLVM + +.include <bsd.prog.mk> + +CPPFLAGS+= ${LLDB_INCLUDES} \ + ${CLANG_INCLUDES} |