aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2017-07-13 19:26:17 +0000
committerDimitry Andric <dim@FreeBSD.org>2017-07-13 19:26:17 +0000
commite75e363cb71a7339552b9d943e78ac62b737379b (patch)
tree29ec5bd173694acbbcbb8207114ef7ca189436ba
parent1b306c26ade71504511d2fa75b03dfaee77f9620 (diff)
downloadsrc-e75e363cb71a7339552b9d943e78ac62b737379b.tar.gz
src-e75e363cb71a7339552b9d943e78ac62b737379b.zip
Vendor import of lldb trunk r307894:vendor/lldb/lldb-trunk-r307894
Notes
Notes: svn path=/vendor/lldb/dist/; revision=320967 svn path=/vendor/lldb/lldb-trunk-r307894/; revision=320968; tag=vendor/lldb/lldb-trunk-r307894
-rw-r--r--docs/lldb-gdb-remote.txt45
-rw-r--r--include/lldb/Host/Host.h18
-rw-r--r--include/lldb/Host/common/NativeProcessProtocol.h123
-rw-r--r--lit/lit.cfg6
-rw-r--r--lldb.xcodeproj/project.pbxproj38
-rw-r--r--packages/Python/lldbsuite/test/expression_command/call-restarts/TestCallThatRestarts.py24
-rw-r--r--packages/Python/lldbsuite/test/expression_command/call-throws/TestCallThatThrows.py24
-rw-r--r--packages/Python/lldbsuite/test/expression_command/char/TestExprsChar.py21
-rw-r--r--packages/Python/lldbsuite/test/expression_command/fixits/TestFixIts.py24
-rw-r--r--packages/Python/lldbsuite/test/expression_command/issue_11588/Test11588.py23
-rw-r--r--packages/Python/lldbsuite/test/expression_command/macros/TestMacros.py28
-rw-r--r--packages/Python/lldbsuite/test/expression_command/options/TestExprOptions.py21
-rw-r--r--packages/Python/lldbsuite/test/expression_command/save_jit_objects/TestSaveJITObjects.py13
-rw-r--r--packages/Python/lldbsuite/test/expression_command/timeout/TestCallWithTimeout.py28
-rw-r--r--packages/Python/lldbsuite/test/functionalities/mtc/simple/Makefile6
-rw-r--r--packages/Python/lldbsuite/test/functionalities/mtc/simple/TestMTCSimple.py57
-rw-r--r--packages/Python/lldbsuite/test/functionalities/mtc/simple/main.m15
-rw-r--r--packages/Python/lldbsuite/test/functionalities/return-value/TestReturnValue.py2
-rw-r--r--packages/Python/lldbsuite/test/functionalities/signal/raise/TestRaise.py5
-rw-r--r--packages/Python/lldbsuite/test/functionalities/signal/raise/main.c7
-rw-r--r--packages/Python/lldbsuite/test/functionalities/ubsan/user-expression/Makefile6
-rw-r--r--packages/Python/lldbsuite/test/functionalities/ubsan/user-expression/TestUbsanUserExpression.py49
-rw-r--r--packages/Python/lldbsuite/test/functionalities/ubsan/user-expression/main.c9
-rw-r--r--packages/Python/lldbsuite/test/lang/go/types/TestGoASTContext.py1
-rw-r--r--packages/Python/lldbsuite/test/lldbplatformutil.py14
-rw-r--r--packages/Python/lldbsuite/test/lldbutil.py41
-rw-r--r--packages/Python/lldbsuite/test/make/Android.rules4
-rw-r--r--packages/Python/lldbsuite/test/sample_test/TestSampleTest.py40
-rw-r--r--source/Commands/CommandObjectThread.cpp6
-rw-r--r--source/Core/DumpDataExtractor.cpp3
-rw-r--r--source/Host/common/File.cpp74
-rw-r--r--source/Host/common/MainLoop.cpp27
-rw-r--r--source/Host/common/NativeProcessProtocol.cpp33
-rw-r--r--source/Host/common/SocketAddress.cpp2
-rw-r--r--source/Host/macosx/Host.mm6
-rw-r--r--source/Host/posix/ConnectionFileDescriptorPosix.cpp21
-rw-r--r--source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.cpp76
-rw-r--r--source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.h69
-rw-r--r--source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp4
-rw-r--r--source/Plugins/InstrumentationRuntime/ASan/ASanRuntime.cpp6
-rw-r--r--source/Plugins/InstrumentationRuntime/MainThreadChecker/MainThreadCheckerRuntime.cpp5
-rw-r--r--source/Plugins/InstrumentationRuntime/TSan/TSanRuntime.cpp6
-rw-r--r--source/Plugins/InstrumentationRuntime/UBSan/UBSanRuntime.cpp3
-rw-r--r--source/Plugins/Language/ObjC/Cocoa.cpp12
-rw-r--r--source/Plugins/Platform/Android/PlatformAndroid.cpp8
-rw-r--r--source/Plugins/Platform/Android/PlatformAndroid.h2
-rw-r--r--source/Plugins/Platform/POSIX/PlatformPOSIX.cpp8
-rw-r--r--source/Plugins/Platform/POSIX/PlatformPOSIX.h4
-rw-r--r--source/Plugins/Process/FreeBSD/ProcessMonitor.cpp24
-rw-r--r--source/Plugins/Process/Linux/NativeProcessLinux.cpp317
-rw-r--r--source/Plugins/Process/Linux/NativeProcessLinux.h37
-rw-r--r--source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp6
-rwxr-xr-xsource/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp21
-rw-r--r--source/Plugins/Process/Linux/ProcessorTrace.cpp37
-rw-r--r--source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp265
-rw-r--r--source/Plugins/Process/NetBSD/NativeProcessNetBSD.h28
-rw-r--r--source/Plugins/Process/gdb-remote/CMakeLists.txt8
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp28
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h3
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp26
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h7
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp9
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp71
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h15
-rw-r--r--source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp1
-rw-r--r--source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp14
-rw-r--r--source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp20
-rw-r--r--source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.h2
-rw-r--r--source/Utility/StringExtractorGDBRemote.cpp37
-rw-r--r--source/Utility/StringExtractorGDBRemote.h4
-rw-r--r--tools/lldb-server/CMakeLists.txt12
-rw-r--r--tools/lldb-server/lldb-gdbserver.cpp34
-rw-r--r--tools/lldb-server/lldb-platform.cpp57
-rw-r--r--unittests/Process/Linux/ProcessorTraceTest.cpp32
-rw-r--r--unittests/UnwindAssembly/x86/Testx86AssemblyInspectionEngine.cpp25
-rwxr-xr-xwww/architecture.html294
-rwxr-xr-xwww/architecture/index.html133
-rw-r--r--www/sidebar.incl2
78 files changed, 1151 insertions, 1485 deletions
diff --git a/docs/lldb-gdb-remote.txt b/docs/lldb-gdb-remote.txt
index a4427a70444d..0000738b556b 100644
--- a/docs/lldb-gdb-remote.txt
+++ b/docs/lldb-gdb-remote.txt
@@ -126,6 +126,32 @@ read packet: $OK#00
This packet can be sent one or more times _prior_ to sending a "A" packet.
//----------------------------------------------------------------------
+// "QEnableErrorStrings"
+//
+// BRIEF
+// This packet enables reporting of Error strings in remote packet
+// replies from the server to client. If the server supports this
+// feature, it should send an OK response. The client can expect the
+// following error replies if this feature is enabled in the server ->
+//
+// EXX;AAAAAAAAA
+//
+// where AAAAAAAAA will be a hex encoded ASCII string.
+// XX is hex encoded byte number.
+//
+// It must be noted that even if the client has enabled reporting
+// strings in error replies, it must not expect error strings to all
+// error replies.
+//
+// PRIORITY TO IMPLEMENT
+// Low. Only needed if the remote target wants to provide strings that
+// are human readable along with an error code.
+//----------------------------------------------------------------------
+
+send packet: $QErrorStringInPacketSupported
+read packet: $OK#00
+
+//----------------------------------------------------------------------
// "QSetSTDIN:<ascii-hex-path>"
// "QSetSTDOUT:<ascii-hex-path>"
// "QSetSTDERR:<ascii-hex-path>"
@@ -250,11 +276,12 @@ read packet: OK
//
// Each tracing instance is identified by a trace id which is returned
// as the reply to this packet. In case the tracing failed to begin an
-// error code is returned instead.
+// error code along with a hex encoded ASCII message is returned
+// instead.
//----------------------------------------------------------------------
send packet: jTraceStart:{"type":<type>,"buffersize":<buffersize>}]
-read packet: <trace id>/E<error code>
+read packet: <trace id>/E<error code>;AAAAAAAAA
//----------------------------------------------------------------------
// jTraceStop:
@@ -283,12 +310,12 @@ read packet: <trace id>/E<error code>
// to stop tracing on that thread.
// ========== ====================================================
//
-// An OK response is sent in case of success else an error code is
-// returned.
+// An OK response is sent in case of success else an error code along
+// with a hex encoded ASCII message is returned.
//----------------------------------------------------------------------
send packet: jTraceStop:{"traceid":<trace id>}]
-read packet: <OK response>/E<error code>
+read packet: <OK response>/E<error code>;AAAAAAAAA
//----------------------------------------------------------------------
// jTraceBufferRead:
@@ -317,11 +344,11 @@ read packet: <OK response>/E<error code>
// ========== ====================================================
//
// The trace data is sent as raw binary data if the read was successful
-// else an error code is sent.
+// else an error code along with a hex encoded ASCII message is sent.
//----------------------------------------------------------------------
send packet: jTraceBufferRead:{"traceid":<trace id>,"offset":<byteoffset>,"buffersize":<byte_count>}]
-read packet: <binary trace data>/E<error code>
+read packet: <binary trace data>/E<error code>;AAAAAAAAA
//----------------------------------------------------------------------
// jTraceMetaRead:
@@ -359,11 +386,11 @@ read packet: <binary trace data>/E<error code>
// gdb-remote protocol has certain limitations, binary escaping
// convention is used.
// In case the trace instance with the <trace id> was not found, an
-// error code is returned.
+// error code along with a hex encoded ASCII message is returned.
//----------------------------------------------------------------------
send packet: jTraceConfigRead:{"traceid":<trace id>}
-read packet: {"conf1":<conf1>,"conf2":<conf2>,"params":{"paramName":paramValue}]}];/E<error code>
+read packet: {"conf1":<conf1>,"conf2":<conf2>,"params":{"paramName":paramValue}]}];/E<error code>;AAAAAAAAA
//----------------------------------------------------------------------
// "qRegisterInfo<hex-reg-id>"
diff --git a/include/lldb/Host/Host.h b/include/lldb/Host/Host.h
index c41e4796f532..da0b8e14c4a7 100644
--- a/include/lldb/Host/Host.h
+++ b/include/lldb/Host/Host.h
@@ -7,14 +7,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef liblldb_Host_h_
-#define liblldb_Host_h_
-#if defined(__cplusplus)
-
-#include <stdarg.h>
-
-#include <map>
-#include <string>
+#ifndef LLDB_HOST_HOST_H
+#define LLDB_HOST_HOST_H
#include "lldb/Host/File.h"
#include "lldb/Host/HostThread.h"
@@ -22,6 +16,11 @@
#include "lldb/Utility/StringList.h"
#include "lldb/lldb-private-forward.h"
#include "lldb/lldb-private.h"
+#include <cerrno>
+#include <map>
+#include <stdarg.h>
+#include <string>
+#include <type_traits>
namespace lldb_private {
@@ -254,5 +253,4 @@ template <> struct format_provider<lldb_private::WaitStatus> {
};
} // namespace llvm
-#endif // #if defined(__cplusplus)
-#endif // liblldb_Host_h_
+#endif // LLDB_HOST_HOST_H
diff --git a/include/lldb/Host/common/NativeProcessProtocol.h b/include/lldb/Host/common/NativeProcessProtocol.h
index a97540499cd3..5f2157510c0a 100644
--- a/include/lldb/Host/common/NativeProcessProtocol.h
+++ b/include/lldb/Host/common/NativeProcessProtocol.h
@@ -19,6 +19,7 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Error.h"
#include "llvm/Support/MemoryBuffer.h"
#include <vector>
@@ -244,68 +245,57 @@ public:
virtual Status GetFileLoadAddress(const llvm::StringRef &file_name,
lldb::addr_t &load_addr) = 0;
- //------------------------------------------------------------------
- /// Launch a process for debugging. This method will create an concrete
- /// instance of NativeProcessProtocol, based on the host platform.
- /// (e.g. NativeProcessLinux on linux, etc.)
- ///
- /// @param[in] launch_info
- /// Information required to launch the process.
- ///
- /// @param[in] native_delegate
- /// The delegate that will receive messages regarding the
- /// inferior. Must outlive the NativeProcessProtocol
- /// instance.
- ///
- /// @param[in] mainloop
- /// The mainloop instance with which the process can register
- /// callbacks. Must outlive the NativeProcessProtocol
- /// instance.
- ///
- /// @param[out] process_sp
- /// On successful return from the method, this parameter
- /// contains the shared pointer to the
- /// NativeProcessProtocol that can be used to manipulate
- /// the native process.
- ///
- /// @return
- /// An error object indicating if the operation succeeded,
- /// and if not, what error occurred.
- //------------------------------------------------------------------
- static Status Launch(ProcessLaunchInfo &launch_info,
- NativeDelegate &native_delegate, MainLoop &mainloop,
- NativeProcessProtocolSP &process_sp);
-
- //------------------------------------------------------------------
- /// Attach to an existing process. This method will create an concrete
- /// instance of NativeProcessProtocol, based on the host platform.
- /// (e.g. NativeProcessLinux on linux, etc.)
- ///
- /// @param[in] pid
- /// pid of the process locatable
- ///
- /// @param[in] native_delegate
- /// The delegate that will receive messages regarding the
- /// inferior. Must outlive the NativeProcessProtocol
- /// instance.
- ///
- /// @param[in] mainloop
- /// The mainloop instance with which the process can register
- /// callbacks. Must outlive the NativeProcessProtocol
- /// instance.
- ///
- /// @param[out] process_sp
- /// On successful return from the method, this parameter
- /// contains the shared pointer to the
- /// NativeProcessProtocol that can be used to manipulate
- /// the native process.
- ///
- /// @return
- /// An error object indicating if the operation succeeded,
- /// and if not, what error occurred.
- //------------------------------------------------------------------
- static Status Attach(lldb::pid_t pid, NativeDelegate &native_delegate,
- MainLoop &mainloop, NativeProcessProtocolSP &process_sp);
+ class Factory {
+ public:
+ virtual ~Factory();
+ //------------------------------------------------------------------
+ /// Launch a process for debugging.
+ ///
+ /// @param[in] launch_info
+ /// Information required to launch the process.
+ ///
+ /// @param[in] native_delegate
+ /// The delegate that will receive messages regarding the
+ /// inferior. Must outlive the NativeProcessProtocol
+ /// instance.
+ ///
+ /// @param[in] mainloop
+ /// The mainloop instance with which the process can register
+ /// callbacks. Must outlive the NativeProcessProtocol
+ /// instance.
+ ///
+ /// @return
+ /// A NativeProcessProtocol shared pointer if the operation succeeded or
+ /// an error object if it failed.
+ //------------------------------------------------------------------
+ virtual llvm::Expected<NativeProcessProtocolSP>
+ Launch(ProcessLaunchInfo &launch_info, NativeDelegate &native_delegate,
+ MainLoop &mainloop) const = 0;
+
+ //------------------------------------------------------------------
+ /// Attach to an existing process.
+ ///
+ /// @param[in] pid
+ /// pid of the process locatable
+ ///
+ /// @param[in] native_delegate
+ /// The delegate that will receive messages regarding the
+ /// inferior. Must outlive the NativeProcessProtocol
+ /// instance.
+ ///
+ /// @param[in] mainloop
+ /// The mainloop instance with which the process can register
+ /// callbacks. Must outlive the NativeProcessProtocol
+ /// instance.
+ ///
+ /// @return
+ /// A NativeProcessProtocol shared pointer if the operation succeeded or
+ /// an error object if it failed.
+ //------------------------------------------------------------------
+ virtual llvm::Expected<NativeProcessProtocolSP>
+ Attach(lldb::pid_t pid, NativeDelegate &native_delegate,
+ MainLoop &mainloop) const = 0;
+ };
//------------------------------------------------------------------
/// StartTracing API for starting a tracing instance with the
@@ -413,10 +403,10 @@ protected:
lldb::pid_t m_pid;
std::vector<NativeThreadProtocolSP> m_threads;
- lldb::tid_t m_current_thread_id;
+ lldb::tid_t m_current_thread_id = LLDB_INVALID_THREAD_ID;
mutable std::recursive_mutex m_threads_mutex;
- lldb::StateType m_state;
+ lldb::StateType m_state = lldb::eStateInvalid;
mutable std::recursive_mutex m_state_mutex;
llvm::Optional<WaitStatus> m_exit_status;
@@ -427,7 +417,7 @@ protected:
NativeWatchpointList m_watchpoint_list;
HardwareBreakpointMap m_hw_breakpoints_map;
int m_terminal_fd;
- uint32_t m_stop_id;
+ uint32_t m_stop_id = 0;
// Set of signal numbers that LLDB directly injects back to inferior
// without stopping it.
@@ -438,7 +428,8 @@ protected:
// then the process should be attached to. When attaching to a process
// lldb_private::Host calls should be used to locate the process to attach to,
// and then this function should be called.
- NativeProcessProtocol(lldb::pid_t pid);
+ NativeProcessProtocol(lldb::pid_t pid, int terminal_fd,
+ NativeDelegate &delegate);
// -----------------------------------------------------------
// Internal interface for state handling
diff --git a/lit/lit.cfg b/lit/lit.cfg
index a3d5f9ca7524..8dea61b27169 100644
--- a/lit/lit.cfg
+++ b/lit/lit.cfg
@@ -95,8 +95,8 @@ if config.test_exec_root is None:
lit_config.fatal('No site specific configuration available!')
# Get the source and object roots.
- llvm_src_root = lit.util.capture(['llvm-config', '--src-root']).strip()
- llvm_obj_root = lit.util.capture(['llvm-config', '--obj-root']).strip()
+ llvm_src_root = subprocess.check_output(['llvm-config', '--src-root']).strip()
+ llvm_obj_root = subprocess.check_output(['llvm-config', '--obj-root']).strip()
lldb_src_root = os.path.join(llvm_src_root, "tools", "lldb")
lldb_obj_root = os.path.join(llvm_obj_root, "tools", "lldb")
@@ -132,7 +132,7 @@ if not os.path.exists(config.cxx):
if platform.system() in ['Darwin']:
try:
- out = lit.util.capture(['xcrun', '--show-sdk-path']).strip()
+ out = subprocess.check_output(['xcrun', '--show-sdk-path']).strip()
res = 0
except OSError:
res = -1
diff --git a/lldb.xcodeproj/project.pbxproj b/lldb.xcodeproj/project.pbxproj
index 8c59fc888412..8353da30bd8e 100644
--- a/lldb.xcodeproj/project.pbxproj
+++ b/lldb.xcodeproj/project.pbxproj
@@ -868,6 +868,8 @@
966C6B7C18E6A56A0093F5EC /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 966C6B7818E6A56A0093F5EC /* libz.dylib */; };
9694FA711B32AA64005EBB16 /* ABISysV_mips.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9694FA6F1B32AA64005EBB16 /* ABISysV_mips.cpp */; };
9A0FDEA71E8EF5110086B2F5 /* RegisterContextLinux_mips.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9A0FDE971E8EF5010086B2F5 /* RegisterContextLinux_mips.cpp */; };
+ 9A1542F91F0EE48600DEA1D8 /* MockTildeExpressionResolver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9A1542F51F0EE44000DEA1D8 /* MockTildeExpressionResolver.cpp */; };
+ 9A1542FA1F0EE48600DEA1D8 /* TestUtilities.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9A1542F71F0EE44000DEA1D8 /* TestUtilities.cpp */; };
9A19A6AF1163BBB200E0D453 /* SBValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 9A19A6A51163BB7E00E0D453 /* SBValue.h */; settings = {ATTRIBUTES = (Public, ); }; };
9A19A6B01163BBB300E0D453 /* SBValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9A19A6AD1163BB9800E0D453 /* SBValue.cpp */; };
9A1E595C1EB2B141002206A5 /* SBTrace.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9A1E59521EB2B0B9002206A5 /* SBTrace.cpp */; };
@@ -2815,6 +2817,11 @@
9A0FDE991E8EF5010086B2F5 /* RegisterInfos_arm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegisterInfos_arm.h; path = Utility/RegisterInfos_arm.h; sourceTree = "<group>"; };
9A0FDE9A1E8EF5010086B2F5 /* RegisterInfos_arm64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegisterInfos_arm64.h; path = Utility/RegisterInfos_arm64.h; sourceTree = "<group>"; };
9A0FDE9B1E8EF5010086B2F5 /* RegisterInfos_mips.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegisterInfos_mips.h; path = Utility/RegisterInfos_mips.h; sourceTree = "<group>"; };
+ 9A1542F41F0EE44000DEA1D8 /* CMakeLists.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = CMakeLists.txt; sourceTree = "<group>"; };
+ 9A1542F51F0EE44000DEA1D8 /* MockTildeExpressionResolver.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = MockTildeExpressionResolver.cpp; sourceTree = "<group>"; };
+ 9A1542F61F0EE44000DEA1D8 /* MockTildeExpressionResolver.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MockTildeExpressionResolver.h; sourceTree = "<group>"; };
+ 9A1542F71F0EE44000DEA1D8 /* TestUtilities.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = TestUtilities.cpp; sourceTree = "<group>"; };
+ 9A1542F81F0EE44000DEA1D8 /* TestUtilities.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TestUtilities.h; sourceTree = "<group>"; };
9A19A6A51163BB7E00E0D453 /* SBValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBValue.h; path = include/lldb/API/SBValue.h; sourceTree = "<group>"; };
9A19A6AD1163BB9800E0D453 /* SBValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBValue.cpp; path = source/API/SBValue.cpp; sourceTree = "<group>"; };
9A1E59521EB2B0B9002206A5 /* SBTrace.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBTrace.cpp; path = source/API/SBTrace.cpp; sourceTree = "<group>"; };
@@ -3305,6 +3312,7 @@
2321F9421BDD343A00BA9A93 /* Utility */ = {
isa = PBXGroup;
children = (
+ 9A1542F31F0EE44000DEA1D8 /* Helpers */,
2321F9431BDD346100BA9A93 /* CMakeLists.txt */,
23CB15041D66CD9200EDDDE1 /* Inputs */,
2321F9441BDD346100BA9A93 /* StringExtractorTest.cpp */,
@@ -6216,6 +6224,18 @@
name = "SysV-mips";
sourceTree = "<group>";
};
+ 9A1542F31F0EE44000DEA1D8 /* Helpers */ = {
+ isa = PBXGroup;
+ children = (
+ 9A1542F41F0EE44000DEA1D8 /* CMakeLists.txt */,
+ 9A1542F51F0EE44000DEA1D8 /* MockTildeExpressionResolver.cpp */,
+ 9A1542F61F0EE44000DEA1D8 /* MockTildeExpressionResolver.h */,
+ 9A1542F71F0EE44000DEA1D8 /* TestUtilities.cpp */,
+ 9A1542F81F0EE44000DEA1D8 /* TestUtilities.h */,
+ );
+ path = Helpers;
+ sourceTree = "<group>";
+ };
AE44FB371BB35A2E0033EB62 /* Go */ = {
isa = PBXGroup;
children = (
@@ -7003,12 +7023,14 @@
23CB15371D66DA9300EDDDE1 /* PythonTestSuite.cpp in Sources */,
23E2E5321D903832006F38BB /* BreakpointIDTest.cpp in Sources */,
23CB15381D66DA9300EDDDE1 /* PythonExceptionStateTests.cpp in Sources */,
+ 9A1542F91F0EE48600DEA1D8 /* MockTildeExpressionResolver.cpp in Sources */,
23CB15391D66DA9300EDDDE1 /* DataExtractorTest.cpp in Sources */,
23CB153A1D66DA9300EDDDE1 /* GDBRemoteClientBaseTest.cpp in Sources */,
23CB153B1D66DA9300EDDDE1 /* SocketTest.cpp in Sources */,
23CB153C1D66DA9300EDDDE1 /* TestArgs.cpp in Sources */,
23CB153D1D66DA9300EDDDE1 /* GDBRemoteCommunicationClientTest.cpp in Sources */,
23CB153E1D66DA9300EDDDE1 /* PythonDataObjectsTests.cpp in Sources */,
+ 9A1542FA1F0EE48600DEA1D8 /* TestUtilities.cpp in Sources */,
23CB153F1D66DA9300EDDDE1 /* SymbolsTest.cpp in Sources */,
AFEC5FD81D94F9380076A480 /* Testx86AssemblyInspectionEngine.cpp in Sources */,
23CB15401D66DA9300EDDDE1 /* TestClangASTContext.cpp in Sources */,
@@ -8256,7 +8278,7 @@
"$(LLVM_SOURCE_DIR)/tools/clang/include",
"$(LLVM_BUILD_DIR)/$(LLVM_BUILD_DIR_ARCH)/tools/clang/include",
);
- LLDB_GTESTS_CFLAGS = "-I $(LLVM_SOURCE_DIR)/utils/unittest/googletest/include -I $(LLVM_SOURCE_DIR)/include -I $(LLVM_BUILD_DIR)/x86_64/include -I include -I source -I $(PYTHON_FRAMEWORK_PATH)/Headers";
+ LLDB_GTESTS_CFLAGS = "-I ${SOURCE_ROOT} -I $(LLVM_SOURCE_DIR)/utils/unittest/googlemock/include -I $(LLVM_SOURCE_DIR)/utils/unittest/googletest/include -I $(LLVM_SOURCE_DIR)/include -I $(LLVM_BUILD_DIR)/x86_64/include -I include -I source -I $(PYTHON_FRAMEWORK_PATH)/Headers";
LLDB_GTESTS_LDFLAGS = "$(LLVM_BUILD_DIR)/x86_64/lib/libgtest.a -L $(PYTHON_FRAMEWORK_PATH)/Versions/$(PYTHON_VERSION_MAJOR).$(PYTHON_VERSION_MINOR)/lib -l python$(PYTHON_VERSION_MAJOR).$(PYTHON_VERSION_MINOR)";
OTHER_CFLAGS = (
"-fno-rtti",
@@ -8298,7 +8320,7 @@
"$(LLVM_SOURCE_DIR)/tools/clang/include",
"$(LLVM_BUILD_DIR)/$(LLVM_BUILD_DIR_ARCH)/tools/clang/include",
);
- LLDB_GTESTS_CFLAGS = "-I $(LLVM_SOURCE_DIR)/utils/unittest/googletest/include -I $(LLVM_SOURCE_DIR)/include -I $(LLVM_BUILD_DIR)/x86_64/include -I include -I source -I $(PYTHON_FRAMEWORK_PATH)/Headers";
+ LLDB_GTESTS_CFLAGS = "-I ${SOURCE_ROOT} -I $(LLVM_SOURCE_DIR)/utils/unittest/googlemock/include -I $(LLVM_SOURCE_DIR)/utils/unittest/googletest/include -I $(LLVM_SOURCE_DIR)/include -I $(LLVM_BUILD_DIR)/x86_64/include -I include -I source -I $(PYTHON_FRAMEWORK_PATH)/Headers";
LLDB_GTESTS_LDFLAGS = "$(LLVM_BUILD_DIR)/x86_64/lib/libgtest.a -L $(PYTHON_FRAMEWORK_PATH)/Versions/$(PYTHON_VERSION_MAJOR).$(PYTHON_VERSION_MINOR)/lib -l python$(PYTHON_VERSION_MAJOR).$(PYTHON_VERSION_MINOR)";
OTHER_CFLAGS = (
"-fno-rtti",
@@ -8340,7 +8362,7 @@
"$(LLVM_SOURCE_DIR)/tools/clang/include",
"$(LLVM_BUILD_DIR)/$(LLVM_BUILD_DIR_ARCH)/tools/clang/include",
);
- LLDB_GTESTS_CFLAGS = "-I $(LLVM_SOURCE_DIR)/utils/unittest/googletest/include -I $(LLVM_SOURCE_DIR)/include -I $(LLVM_BUILD_DIR)/x86_64/include -I include -I source -I $(PYTHON_FRAMEWORK_PATH)/Headers";
+ LLDB_GTESTS_CFLAGS = "-I ${SOURCE_ROOT} -I $(LLVM_SOURCE_DIR)/utils/unittest/googlemock/include -I $(LLVM_SOURCE_DIR)/utils/unittest/googletest/include -I $(LLVM_SOURCE_DIR)/include -I $(LLVM_BUILD_DIR)/x86_64/include -I include -I source -I $(PYTHON_FRAMEWORK_PATH)/Headers";
LLDB_GTESTS_LDFLAGS = "$(LLVM_BUILD_DIR)/x86_64/lib/libgtest.a -L $(PYTHON_FRAMEWORK_PATH)/Versions/$(PYTHON_VERSION_MAJOR).$(PYTHON_VERSION_MINOR)/lib -l python$(PYTHON_VERSION_MAJOR).$(PYTHON_VERSION_MINOR)";
OTHER_CFLAGS = (
"-fno-rtti",
@@ -8382,7 +8404,7 @@
"$(LLVM_SOURCE_DIR)/tools/clang/include",
"$(LLVM_BUILD_DIR)/$(LLVM_BUILD_DIR_ARCH)/tools/clang/include",
);
- LLDB_GTESTS_CFLAGS = "-I $(LLVM_SOURCE_DIR)/utils/unittest/googletest/include -I $(LLVM_SOURCE_DIR)/include -I $(LLVM_BUILD_DIR)/x86_64/include -I include -I source -I $(PYTHON_FRAMEWORK_PATH)/Headers";
+ LLDB_GTESTS_CFLAGS = "-I ${SOURCE_ROOT} -I $(LLVM_SOURCE_DIR)/utils/unittest/googlemock/include -I $(LLVM_SOURCE_DIR)/utils/unittest/googletest/include -I $(LLVM_SOURCE_DIR)/include -I $(LLVM_BUILD_DIR)/x86_64/include -I include -I source -I $(PYTHON_FRAMEWORK_PATH)/Headers";
LLDB_GTESTS_LDFLAGS = "$(LLVM_BUILD_DIR)/x86_64/lib/libgtest.a -L $(PYTHON_FRAMEWORK_PATH)/Versions/$(PYTHON_VERSION_MAJOR).$(PYTHON_VERSION_MINOR)/lib -l python$(PYTHON_VERSION_MAJOR).$(PYTHON_VERSION_MINOR)";
OTHER_CFLAGS = (
"-fno-rtti",
@@ -8424,7 +8446,7 @@
"$(LLVM_SOURCE_DIR)/tools/clang/include",
"$(LLVM_BUILD_DIR)/$(LLVM_BUILD_DIR_ARCH)/tools/clang/include",
);
- LLDB_GTESTS_CFLAGS = "-I $(LLVM_SOURCE_DIR)/utils/unittest/googletest/include -I $(LLVM_SOURCE_DIR)/include -I $(LLVM_BUILD_DIR)/x86_64/include -I include -I source -I $(PYTHON_FRAMEWORK_PATH)/Headers";
+ LLDB_GTESTS_CFLAGS = "-I ${SOURCE_ROOT} -I $(LLVM_SOURCE_DIR)/utils/unittest/googlemock/include -I $(LLVM_SOURCE_DIR)/utils/unittest/googletest/include -I $(LLVM_SOURCE_DIR)/include -I $(LLVM_BUILD_DIR)/x86_64/include -I include -I source -I $(PYTHON_FRAMEWORK_PATH)/Headers";
LLDB_GTESTS_LDFLAGS = "$(LLVM_BUILD_DIR)/x86_64/lib/libgtest.a -L $(PYTHON_FRAMEWORK_PATH)/Versions/$(PYTHON_VERSION_MAJOR).$(PYTHON_VERSION_MINOR)/lib -l python$(PYTHON_VERSION_MAJOR).$(PYTHON_VERSION_MINOR)";
OTHER_CFLAGS = (
"-fno-rtti",
@@ -8466,7 +8488,7 @@
"$(LLVM_SOURCE_DIR)/tools/clang/include",
"$(LLVM_BUILD_DIR)/$(LLVM_BUILD_DIR_ARCH)/tools/clang/include",
);
- LLDB_GTESTS_CFLAGS = "-I $(LLVM_SOURCE_DIR)/utils/unittest/googletest/include -I $(LLVM_SOURCE_DIR)/include -I $(LLVM_BUILD_DIR)/x86_64/include -I include -I source -I $(PYTHON_FRAMEWORK_PATH)/Headers";
+ LLDB_GTESTS_CFLAGS = "-I ${SOURCE_ROOT} -I $(LLVM_SOURCE_DIR)/utils/unittest/googlemock/include -I $(LLVM_SOURCE_DIR)/utils/unittest/googletest/include -I $(LLVM_SOURCE_DIR)/include -I $(LLVM_BUILD_DIR)/x86_64/include -I include -I source -I $(PYTHON_FRAMEWORK_PATH)/Headers";
LLDB_GTESTS_LDFLAGS = "$(LLVM_BUILD_DIR)/x86_64/lib/libgtest.a -L $(PYTHON_FRAMEWORK_PATH)/Versions/$(PYTHON_VERSION_MAJOR).$(PYTHON_VERSION_MINOR)/lib -l python$(PYTHON_VERSION_MAJOR).$(PYTHON_VERSION_MINOR)";
OTHER_CFLAGS = (
"-fno-rtti",
@@ -8508,7 +8530,7 @@
"$(LLVM_SOURCE_DIR)/tools/clang/include",
"$(LLVM_BUILD_DIR)/$(LLVM_BUILD_DIR_ARCH)/tools/clang/include",
);
- LLDB_GTESTS_CFLAGS = "-I $(LLVM_SOURCE_DIR)/utils/unittest/googletest/include -I $(LLVM_SOURCE_DIR)/include -I $(LLVM_BUILD_DIR)/x86_64/include -I include -I source -I $(PYTHON_FRAMEWORK_PATH)/Headers";
+ LLDB_GTESTS_CFLAGS = "-I ${SOURCE_ROOT} -I $(LLVM_SOURCE_DIR)/utils/unittest/googlemock/include -I $(LLVM_SOURCE_DIR)/utils/unittest/googletest/include -I $(LLVM_SOURCE_DIR)/include -I $(LLVM_BUILD_DIR)/x86_64/include -I include -I source -I $(PYTHON_FRAMEWORK_PATH)/Headers";
LLDB_GTESTS_LDFLAGS = "$(LLVM_BUILD_DIR)/x86_64/lib/libgtest.a -L $(PYTHON_FRAMEWORK_PATH)/Versions/$(PYTHON_VERSION_MAJOR).$(PYTHON_VERSION_MINOR)/lib -l python$(PYTHON_VERSION_MAJOR).$(PYTHON_VERSION_MINOR)";
OTHER_CFLAGS = (
"-fno-rtti",
@@ -8550,7 +8572,7 @@
"$(LLVM_SOURCE_DIR)/tools/clang/include",
"$(LLVM_BUILD_DIR)/$(LLVM_BUILD_DIR_ARCH)/tools/clang/include",
);
- LLDB_GTESTS_CFLAGS = "-I $(LLVM_SOURCE_DIR)/utils/unittest/googletest/include -I $(LLVM_SOURCE_DIR)/include -I $(LLVM_BUILD_DIR)/x86_64/include -I include -I source -I $(PYTHON_FRAMEWORK_PATH)/Headers";
+ LLDB_GTESTS_CFLAGS = "-I ${SOURCE_ROOT} -I $(LLVM_SOURCE_DIR)/utils/unittest/googlemock/include -I $(LLVM_SOURCE_DIR)/utils/unittest/googletest/include -I $(LLVM_SOURCE_DIR)/include -I $(LLVM_BUILD_DIR)/x86_64/include -I include -I source -I $(PYTHON_FRAMEWORK_PATH)/Headers";
LLDB_GTESTS_LDFLAGS = "$(LLVM_BUILD_DIR)/x86_64/lib/libgtest.a -L $(PYTHON_FRAMEWORK_PATH)/Versions/$(PYTHON_VERSION_MAJOR).$(PYTHON_VERSION_MINOR)/lib -l python$(PYTHON_VERSION_MAJOR).$(PYTHON_VERSION_MINOR)";
OTHER_CFLAGS = (
"-fno-rtti",
diff --git a/packages/Python/lldbsuite/test/expression_command/call-restarts/TestCallThatRestarts.py b/packages/Python/lldbsuite/test/expression_command/call-restarts/TestCallThatRestarts.py
index 0b9ad0ed6323..5eb7b309c94a 100644
--- a/packages/Python/lldbsuite/test/expression_command/call-restarts/TestCallThatRestarts.py
+++ b/packages/Python/lldbsuite/test/expression_command/call-restarts/TestCallThatRestarts.py
@@ -48,28 +48,8 @@ class ExprCommandThatRestartsTestCase(TestBase):
"Restored the zeroth frame correctly")
def call_function(self):
- exe_name = "a.out"
- exe = os.path.join(os.getcwd(), exe_name)
-
- target = self.dbg.CreateTarget(exe)
- self.assertTrue(target, VALID_TARGET)
- empty = lldb.SBFileSpec()
- breakpoint = target.BreakpointCreateBySourceRegex(
- 'Stop here in main.', self.main_source_spec)
- self.assertTrue(breakpoint.GetNumLocations() > 0, VALID_BREAKPOINT)
-
- # Launch the process, and do not stop at the entry point.
- process = target.LaunchSimple(
- None, None, self.get_process_working_directory())
-
- self.assertTrue(process, PROCESS_IS_VALID)
-
- # Frame #0 should be at our breakpoint.
- threads = lldbutil.get_threads_stopped_at_breakpoint(
- process, breakpoint)
-
- self.assertTrue(len(threads) == 1)
- self.thread = threads[0]
+ (target, process, self.thread, bkpt) = lldbutil.run_to_source_breakpoint(self,
+ 'Stop here in main.', self.main_source_spec)
# Make sure the SIGCHLD behavior is pass/no-stop/no-notify:
return_obj = lldb.SBCommandReturnObject()
diff --git a/packages/Python/lldbsuite/test/expression_command/call-throws/TestCallThatThrows.py b/packages/Python/lldbsuite/test/expression_command/call-throws/TestCallThatThrows.py
index e5162609dfa6..f2ec340ac845 100644
--- a/packages/Python/lldbsuite/test/expression_command/call-throws/TestCallThatThrows.py
+++ b/packages/Python/lldbsuite/test/expression_command/call-throws/TestCallThatThrows.py
@@ -37,28 +37,8 @@ class ExprCommandWithThrowTestCase(TestBase):
def call_function(self):
"""Test calling function that throws."""
- exe_name = "a.out"
- exe = os.path.join(os.getcwd(), exe_name)
-
- target = self.dbg.CreateTarget(exe)
- self.assertTrue(target, VALID_TARGET)
-
- breakpoint = target.BreakpointCreateBySourceRegex(
- 'I am about to throw.', self.main_source_spec)
- self.assertTrue(breakpoint.GetNumLocations() > 0, VALID_BREAKPOINT)
-
- # Launch the process, and do not stop at the entry point.
- process = target.LaunchSimple(
- None, None, self.get_process_working_directory())
-
- self.assertTrue(process, PROCESS_IS_VALID)
-
- # Frame #0 should be at our breakpoint.
- threads = lldbutil.get_threads_stopped_at_breakpoint(
- process, breakpoint)
-
- self.assertTrue(len(threads) == 1)
- self.thread = threads[0]
+ (target, process, self.thread, bkpt) = lldbutil.run_to_source_breakpoint(self,
+ 'I am about to throw.', self.main_source_spec)
options = lldb.SBExpressionOptions()
options.SetUnwindOnError(True)
diff --git a/packages/Python/lldbsuite/test/expression_command/char/TestExprsChar.py b/packages/Python/lldbsuite/test/expression_command/char/TestExprsChar.py
index a771e7004c94..74991999d926 100644
--- a/packages/Python/lldbsuite/test/expression_command/char/TestExprsChar.py
+++ b/packages/Python/lldbsuite/test/expression_command/char/TestExprsChar.py
@@ -17,29 +17,14 @@ class ExprCharTestCase(TestBase):
self.main_source = "main.cpp"
self.main_source_spec = lldb.SBFileSpec(self.main_source)
- self.exe = os.path.join(os.getcwd(), "a.out")
def do_test(self, dictionary=None):
"""These basic expression commands should work as expected."""
self.build(dictionary=dictionary)
- target = self.dbg.CreateTarget(self.exe)
- self.assertTrue(target)
-
- breakpoint = target.BreakpointCreateBySourceRegex(
- '// Break here', self.main_source_spec)
- self.assertTrue(breakpoint)
-
- # Launch the process, and do not stop at the entry point.
- process = target.LaunchSimple(
- None, None, self.get_process_working_directory())
- self.assertTrue(process)
-
- threads = lldbutil.get_threads_stopped_at_breakpoint(
- process, breakpoint)
- self.assertEqual(len(threads), 1)
-
- frame = threads[0].GetFrameAtIndex(0)
+ (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(self,
+ '// Break here', self.main_source_spec)
+ frame = thread.GetFrameAtIndex(0)
value = frame.EvaluateExpression("foo(c)")
self.assertTrue(value.IsValid())
diff --git a/packages/Python/lldbsuite/test/expression_command/fixits/TestFixIts.py b/packages/Python/lldbsuite/test/expression_command/fixits/TestFixIts.py
index 418c5325ad08..4b096149e728 100644
--- a/packages/Python/lldbsuite/test/expression_command/fixits/TestFixIts.py
+++ b/packages/Python/lldbsuite/test/expression_command/fixits/TestFixIts.py
@@ -37,28 +37,8 @@ class ExprCommandWithFixits(TestBase):
def try_expressions(self):
"""Test calling expressions with errors that can be fixed by the FixIts."""
- exe_name = "a.out"
- exe = os.path.join(os.getcwd(), exe_name)
-
- target = self.dbg.CreateTarget(exe)
- self.assertTrue(target, VALID_TARGET)
-
- breakpoint = target.BreakpointCreateBySourceRegex(
- 'Stop here to evaluate expressions', self.main_source_spec)
- self.assertTrue(breakpoint.GetNumLocations() > 0, VALID_BREAKPOINT)
-
- # Launch the process, and do not stop at the entry point.
- process = target.LaunchSimple(
- None, None, self.get_process_working_directory())
-
- self.assertTrue(process, PROCESS_IS_VALID)
-
- # Frame #0 should be at our breakpoint.
- threads = lldbutil.get_threads_stopped_at_breakpoint(
- process, breakpoint)
-
- self.assertTrue(len(threads) == 1)
- self.thread = threads[0]
+ (target, process, self.thread, bkpt) = lldbutil.run_to_source_breakpoint(self,
+ 'Stop here to evaluate expressions', self.main_source_spec)
options = lldb.SBExpressionOptions()
options.SetAutoApplyFixIts(True)
diff --git a/packages/Python/lldbsuite/test/expression_command/issue_11588/Test11588.py b/packages/Python/lldbsuite/test/expression_command/issue_11588/Test11588.py
index afb497e04b5b..a2d68cffe548 100644
--- a/packages/Python/lldbsuite/test/expression_command/issue_11588/Test11588.py
+++ b/packages/Python/lldbsuite/test/expression_command/issue_11588/Test11588.py
@@ -32,26 +32,9 @@ class Issue11581TestCase(TestBase):
"""valobj.AddressOf() should return correct values."""
self.build()
- exe = os.path.join(os.getcwd(), "a.out")
-
- target = self.dbg.CreateTarget(exe)
- self.assertTrue(target, VALID_TARGET)
-
- breakpoint = target.BreakpointCreateBySourceRegex(
- 'Set breakpoint here.', lldb.SBFileSpec("main.cpp", False))
-
- process = target.LaunchSimple(
- None, None, self.get_process_working_directory())
- self.assertTrue(process, "Created a process.")
- self.assertTrue(
- process.GetState() == lldb.eStateStopped,
- "Stopped it too.")
-
- thread_list = lldbutil.get_threads_stopped_at_breakpoint(
- process, breakpoint)
- self.assertTrue(len(thread_list) == 1)
- thread = thread_list[0]
-
+ (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(self,
+ 'Set breakpoint here.',
+ lldb.SBFileSpec("main.cpp", False))
self.runCmd("command script import --allow-reload s11588.py")
self.runCmd(
"type synthetic add --python-class s11588.Issue11581SyntheticProvider StgClosure")
diff --git a/packages/Python/lldbsuite/test/expression_command/macros/TestMacros.py b/packages/Python/lldbsuite/test/expression_command/macros/TestMacros.py
index 70b862bf4867..817f6cb3944a 100644
--- a/packages/Python/lldbsuite/test/expression_command/macros/TestMacros.py
+++ b/packages/Python/lldbsuite/test/expression_command/macros/TestMacros.py
@@ -30,32 +30,8 @@ class TestMacros(TestBase):
src_file_spec = lldb.SBFileSpec(src_file)
self.assertTrue(src_file_spec.IsValid(), "Main source file")
- # Get the path of the executable
- cwd = os.getcwd()
- exe_file = "a.out"
- exe_path = os.path.join(cwd, exe_file)
-
- # Load the executable
- target = self.dbg.CreateTarget(exe_path)
- self.assertTrue(target.IsValid(), VALID_TARGET)
-
- # Set breakpoints
- bp1 = target.BreakpointCreateBySourceRegex("Break here", src_file_spec)
- self.assertTrue(
- bp1.IsValid() and bp1.GetNumLocations() >= 1,
- VALID_BREAKPOINT)
-
- # Launch the process
- process = target.LaunchSimple(
- None, None, self.get_process_working_directory())
- self.assertTrue(process.IsValid(), PROCESS_IS_VALID)
-
- # Get the thread of the process
- self.assertTrue(
- process.GetState() == lldb.eStateStopped,
- PROCESS_STOPPED)
- thread = lldbutil.get_stopped_thread(
- process, lldb.eStopReasonBreakpoint)
+ (target, process, thread, bp1) = lldbutil.run_to_source_breakpoint(
+ self, "Break here", src_file_spec)
# Get frame for current thread
frame = thread.GetSelectedFrame()
diff --git a/packages/Python/lldbsuite/test/expression_command/options/TestExprOptions.py b/packages/Python/lldbsuite/test/expression_command/options/TestExprOptions.py
index 0d1a17352a3f..b4e9a8bfeab8 100644
--- a/packages/Python/lldbsuite/test/expression_command/options/TestExprOptions.py
+++ b/packages/Python/lldbsuite/test/expression_command/options/TestExprOptions.py
@@ -37,25 +37,10 @@ class ExprOptionsTestCase(TestBase):
# Set debugger into synchronous mode
self.dbg.SetAsync(False)
- # Create a target by the debugger.
- target = self.dbg.CreateTarget(self.exe)
- self.assertTrue(target, VALID_TARGET)
+ (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(
+ self, '// breakpoint_in_main', self.main_source_spec)
- # Set breakpoints inside main.
- breakpoint = target.BreakpointCreateBySourceRegex(
- '// breakpoint_in_main', self.main_source_spec)
- self.assertTrue(breakpoint)
-
- # Now launch the process, and do not stop at entry point.
- process = target.LaunchSimple(
- None, None, self.get_process_working_directory())
- self.assertTrue(process, PROCESS_IS_VALID)
-
- threads = lldbutil.get_threads_stopped_at_breakpoint(
- process, breakpoint)
- self.assertEqual(len(threads), 1)
-
- frame = threads[0].GetFrameAtIndex(0)
+ frame = thread.GetFrameAtIndex(0)
options = lldb.SBExpressionOptions()
# test --language on C++ expression using the SB API's
diff --git a/packages/Python/lldbsuite/test/expression_command/save_jit_objects/TestSaveJITObjects.py b/packages/Python/lldbsuite/test/expression_command/save_jit_objects/TestSaveJITObjects.py
index 7f796971d0ed..f6938b1ea98b 100644
--- a/packages/Python/lldbsuite/test/expression_command/save_jit_objects/TestSaveJITObjects.py
+++ b/packages/Python/lldbsuite/test/expression_command/save_jit_objects/TestSaveJITObjects.py
@@ -31,17 +31,10 @@ class SaveJITObjectsTestCase(TestBase):
src_file = "main.c"
src_file_spec = lldb.SBFileSpec(src_file)
- exe_path = os.path.join(os.getcwd(), "a.out")
- target = self.dbg.CreateTarget(exe_path)
+ (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(
+ self, "break", src_file_spec)
- breakpoint = target.BreakpointCreateBySourceRegex(
- "break", src_file_spec)
-
- process = target.LaunchSimple(None, None,
- self.get_process_working_directory())
-
- thread = process.GetSelectedThread()
- frame = thread.GetSelectedFrame()
+ frame = thread.frames[0]
cleanJITFiles()
frame.EvaluateExpression("(void*)malloc(0x1)")
diff --git a/packages/Python/lldbsuite/test/expression_command/timeout/TestCallWithTimeout.py b/packages/Python/lldbsuite/test/expression_command/timeout/TestCallWithTimeout.py
index 29c03b1d7ef9..7862477001ea 100644
--- a/packages/Python/lldbsuite/test/expression_command/timeout/TestCallWithTimeout.py
+++ b/packages/Python/lldbsuite/test/expression_command/timeout/TestCallWithTimeout.py
@@ -25,36 +25,14 @@ class ExprCommandWithTimeoutsTestCase(TestBase):
@expectedFlakeyFreeBSD("llvm.org/pr19605")
@expectedFailureAll(
oslist=[
- "windows",
- "macosx"],
+ "windows"],
bugnumber="llvm.org/pr21765")
def test(self):
"""Test calling std::String member function."""
self.build()
- exe_name = "a.out"
- exe = os.path.join(os.getcwd(), exe_name)
-
- target = self.dbg.CreateTarget(exe)
- self.assertTrue(target, VALID_TARGET)
-
- breakpoint = target.BreakpointCreateBySourceRegex(
- 'stop here in main.', self.main_source_spec)
- self.assertTrue(breakpoint, VALID_BREAKPOINT)
- self.runCmd("breakpoint list")
-
- # Launch the process, and do not stop at the entry point.
- process = target.LaunchSimple(
- None, None, self.get_process_working_directory())
-
- self.assertTrue(process, PROCESS_IS_VALID)
-
- # Frame #0 should be on self.step_out_of_malloc.
- threads = lldbutil.get_threads_stopped_at_breakpoint(
- process, breakpoint)
-
- self.assertTrue(len(threads) == 1)
- thread = threads[0]
+ (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(
+ self, 'stop here in main.', self.main_source_spec)
# First set the timeout too short, and make sure we fail.
options = lldb.SBExpressionOptions()
diff --git a/packages/Python/lldbsuite/test/functionalities/mtc/simple/Makefile b/packages/Python/lldbsuite/test/functionalities/mtc/simple/Makefile
new file mode 100644
index 000000000000..5665652329dc
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/mtc/simple/Makefile
@@ -0,0 +1,6 @@
+LEVEL = ../../../make
+
+OBJC_SOURCES := main.m
+LDFLAGS = $(CFLAGS) -lobjc -framework Foundation -framework AppKit
+
+include $(LEVEL)/Makefile.rules
diff --git a/packages/Python/lldbsuite/test/functionalities/mtc/simple/TestMTCSimple.py b/packages/Python/lldbsuite/test/functionalities/mtc/simple/TestMTCSimple.py
new file mode 100644
index 000000000000..6a779ecfac5b
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/mtc/simple/TestMTCSimple.py
@@ -0,0 +1,57 @@
+"""
+Tests basic Main Thread Checker support (detecting a main-thread-only violation).
+"""
+
+import os
+import time
+import lldb
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test.decorators import *
+import lldbsuite.test.lldbutil as lldbutil
+from lldbsuite.test.lldbplatformutil import *
+import json
+
+
+class MTCSimpleTestCase(TestBase):
+
+ mydir = TestBase.compute_mydir(__file__)
+
+ @skipUnlessDarwin
+ def test(self):
+ self.mtc_dylib_path = findMainThreadCheckerDylib()
+ if self.mtc_dylib_path == "":
+ self.skipTest("This test requires libMainThreadChecker.dylib.")
+
+ self.build()
+ self.mtc_tests()
+
+ def setUp(self):
+ # Call super's setUp().
+ TestBase.setUp(self)
+
+ def mtc_tests(self):
+ # Load the test
+ exe = os.path.join(os.getcwd(), "a.out")
+ self.expect("file " + exe, patterns=["Current executable set to .*a.out"])
+
+ self.runCmd("env DYLD_INSERT_LIBRARIES=%s" % self.mtc_dylib_path)
+ self.runCmd("run")
+
+ process = self.dbg.GetSelectedTarget().process
+ thread = process.GetSelectedThread()
+ frame = thread.GetSelectedFrame()
+
+ self.expect("thread info", substrs=['stop reason = -[NSView superview] must be used from main thread only'])
+
+ self.expect(
+ "thread info -s",
+ substrs=["instrumentation_class", "api_name", "class_name", "selector", "description"])
+ self.assertEqual(thread.GetStopReason(), lldb.eStopReasonInstrumentation)
+ output_lines = self.res.GetOutput().split('\n')
+ json_line = '\n'.join(output_lines[2:])
+ data = json.loads(json_line)
+ self.assertEqual(data["instrumentation_class"], "MainThreadChecker")
+ self.assertEqual(data["api_name"], "-[NSView superview]")
+ self.assertEqual(data["class_name"], "NSView")
+ self.assertEqual(data["selector"], "superview")
+ self.assertEqual(data["description"], "-[NSView superview] must be used from main thread only")
diff --git a/packages/Python/lldbsuite/test/functionalities/mtc/simple/main.m b/packages/Python/lldbsuite/test/functionalities/mtc/simple/main.m
new file mode 100644
index 000000000000..651347cf74ee
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/mtc/simple/main.m
@@ -0,0 +1,15 @@
+#import <Foundation/Foundation.h>
+#import <AppKit/AppKit.h>
+
+int main() {
+ NSView *view = [[NSView alloc] init];
+ dispatch_group_t g = dispatch_group_create();
+ dispatch_group_enter(g);
+ [NSThread detachNewThreadWithBlock:^{
+ @autoreleasepool {
+ [view superview];
+ }
+ dispatch_group_leave(g);
+ }];
+ dispatch_group_wait(g, DISPATCH_TIME_FOREVER);
+}
diff --git a/packages/Python/lldbsuite/test/functionalities/return-value/TestReturnValue.py b/packages/Python/lldbsuite/test/functionalities/return-value/TestReturnValue.py
index cf435a4aae91..1750bd31b3df 100644
--- a/packages/Python/lldbsuite/test/functionalities/return-value/TestReturnValue.py
+++ b/packages/Python/lldbsuite/test/functionalities/return-value/TestReturnValue.py
@@ -31,8 +31,6 @@ class ReturnValueTestCase(TestBase):
"<=",
"3.6"],
archs=["i386"])
- @expectedFailureAll(compiler="clang", compiler_version=["<=", "5.0.300080"],
- triple='.*-android', archs=["i386"])
@expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778")
@add_test_categories(['pyapi'])
def test_with_python(self):
diff --git a/packages/Python/lldbsuite/test/functionalities/signal/raise/TestRaise.py b/packages/Python/lldbsuite/test/functionalities/signal/raise/TestRaise.py
index efadea51f669..79175562fe7a 100644
--- a/packages/Python/lldbsuite/test/functionalities/signal/raise/TestRaise.py
+++ b/packages/Python/lldbsuite/test/functionalities/signal/raise/TestRaise.py
@@ -16,6 +16,7 @@ from lldbsuite.test import lldbutil
class RaiseTestCase(TestBase):
mydir = TestBase.compute_mydir(__file__)
+ NO_DEBUG_INFO_TESTCASE = True
def test_sigstop(self):
self.build()
@@ -29,6 +30,10 @@ class RaiseTestCase(TestBase):
self.build()
self.signal_test('SIGRTMIN', True)
+ def test_sigtrap(self):
+ self.build()
+ self.signal_test('SIGTRAP', True)
+
def launch(self, target, signal):
# launch the process, do not stop at entry point.
process = target.LaunchSimple(
diff --git a/packages/Python/lldbsuite/test/functionalities/signal/raise/main.c b/packages/Python/lldbsuite/test/functionalities/signal/raise/main.c
index 8827174e758e..4203fe5d4c89 100644
--- a/packages/Python/lldbsuite/test/functionalities/signal/raise/main.c
+++ b/packages/Python/lldbsuite/test/functionalities/signal/raise/main.c
@@ -10,6 +10,11 @@ void handler(int signo)
int main (int argc, char *argv[])
{
+ if (signal(SIGTRAP, handler) == SIG_ERR)
+ {
+ perror("signal(SIGTRAP)");
+ return 1;
+ }
#ifndef __APPLE__
// Real time signals not supported on apple platforms.
if (signal(SIGRTMIN, handler) == SIG_ERR)
@@ -27,6 +32,8 @@ int main (int argc, char *argv[])
if (strcmp(argv[1], "SIGSTOP") == 0)
raise(SIGSTOP);
+ else if (strcmp(argv[1], "SIGTRAP") == 0)
+ raise(SIGTRAP);
#ifndef __APPLE__
else if (strcmp(argv[1], "SIGRTMIN") == 0)
raise(SIGRTMIN);
diff --git a/packages/Python/lldbsuite/test/functionalities/ubsan/user-expression/Makefile b/packages/Python/lldbsuite/test/functionalities/ubsan/user-expression/Makefile
new file mode 100644
index 000000000000..6e7d19b6f48c
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/ubsan/user-expression/Makefile
@@ -0,0 +1,6 @@
+LEVEL = ../../../make
+
+C_SOURCES := main.c
+CFLAGS_EXTRAS := -fsanitize=undefined -g
+
+include $(LEVEL)/Makefile.rules
diff --git a/packages/Python/lldbsuite/test/functionalities/ubsan/user-expression/TestUbsanUserExpression.py b/packages/Python/lldbsuite/test/functionalities/ubsan/user-expression/TestUbsanUserExpression.py
new file mode 100644
index 000000000000..a5e5f572a979
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/ubsan/user-expression/TestUbsanUserExpression.py
@@ -0,0 +1,49 @@
+"""
+Test that hitting a UBSan issue while running user expression doesn't break the evaluation.
+"""
+
+import os
+import time
+import lldb
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test.decorators import *
+import lldbsuite.test.lldbutil as lldbutil
+import json
+
+
+class UbsanUserExpressionTestCase(TestBase):
+
+ mydir = TestBase.compute_mydir(__file__)
+
+ @skipUnlessUndefinedBehaviorSanitizer
+ def test(self):
+ self.build()
+ self.ubsan_tests()
+
+ def setUp(self):
+ # Call super's setUp().
+ TestBase.setUp(self)
+ self.line_breakpoint = line_number('main.c', '// breakpoint line')
+
+ def ubsan_tests(self):
+ # Load the test
+ exe = os.path.join(os.getcwd(), "a.out")
+ self.expect(
+ "file " + exe,
+ patterns=["Current executable set to .*a.out"])
+
+ self.runCmd("breakpoint set -f main.c -l %d" % self.line_breakpoint)
+
+ self.runCmd("run")
+
+ process = self.dbg.GetSelectedTarget().process
+ thread = process.GetSelectedThread()
+ frame = thread.GetSelectedFrame()
+
+ self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
+ substrs=['stopped', 'stop reason = breakpoint'])
+
+ self.expect("p foo()", substrs=["(int) $0 = 42"])
+
+ self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
+ substrs=['stopped', 'stop reason = breakpoint'])
diff --git a/packages/Python/lldbsuite/test/functionalities/ubsan/user-expression/main.c b/packages/Python/lldbsuite/test/functionalities/ubsan/user-expression/main.c
new file mode 100644
index 000000000000..4786aaa89b27
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/ubsan/user-expression/main.c
@@ -0,0 +1,9 @@
+int foo() {
+ int data[4];
+ int x = *(int *)(((char *)&data[0]) + 2);
+ return 42;
+}
+
+int main() {
+ return 0; // breakpoint line
+}
diff --git a/packages/Python/lldbsuite/test/lang/go/types/TestGoASTContext.py b/packages/Python/lldbsuite/test/lang/go/types/TestGoASTContext.py
index 8e158c3e82d4..9571e259629f 100644
--- a/packages/Python/lldbsuite/test/lang/go/types/TestGoASTContext.py
+++ b/packages/Python/lldbsuite/test/lang/go/types/TestGoASTContext.py
@@ -20,6 +20,7 @@ class TestGoASTContext(TestBase):
@skipIfRemote # Not remote test suit ready
@no_debug_info_test
@skipUnlessGoInstalled
+ @expectedFailureAll(bugnumber="llvm.org/pr33643")
def test_with_dsym_and_python_api(self):
"""Test GoASTContext dwarf parsing."""
self.buildGo()
diff --git a/packages/Python/lldbsuite/test/lldbplatformutil.py b/packages/Python/lldbsuite/test/lldbplatformutil.py
index 89ce1d468bd0..4f45643241ed 100644
--- a/packages/Python/lldbsuite/test/lldbplatformutil.py
+++ b/packages/Python/lldbsuite/test/lldbplatformutil.py
@@ -8,6 +8,7 @@ import itertools
import re
import subprocess
import sys
+import os
# Third-party modules
import six
@@ -140,6 +141,19 @@ def platformIsDarwin():
return getPlatform() in getDarwinOSTriples()
+def findMainThreadCheckerDylib():
+ if not platformIsDarwin():
+ return ""
+
+ with os.popen('xcode-select -p') as output:
+ xcode_developer_path = output.read().strip()
+ mtc_dylib_path = '%s/usr/lib/libMainThreadChecker.dylib' % xcode_developer_path
+ if os.path.isfile(mtc_dylib_path):
+ return mtc_dylib_path
+
+ return ""
+
+
class _PlatformContext(object):
"""Value object class which contains platform-specific options."""
diff --git a/packages/Python/lldbsuite/test/lldbutil.py b/packages/Python/lldbsuite/test/lldbutil.py
index 7732dbe6dff3..58a1ead1ea0b 100644
--- a/packages/Python/lldbsuite/test/lldbutil.py
+++ b/packages/Python/lldbsuite/test/lldbutil.py
@@ -725,6 +725,47 @@ def get_crashed_threads(test, process):
threads.append(thread)
return threads
+def run_to_source_breakpoint(test, bkpt_pattern, source_spec, launch_info = None, exe_name = "a.out", in_cwd = True):
+ """Start up a target, using exe_name as the executable, and run it to
+ a breakpoint set by source regex bkpt_pattern.
+ If you want to pass in launch arguments or environment variables, you can optionally pass in
+ an SBLaunchInfo. If you do that, remember to set the working directory as well.
+ If your executable isn't called a.out, you can pass that in. And if your executable isn't
+ in the CWD, pass in the absolute path to the executable in exe_name, and set in_cwd to False.
+ If the target isn't valid, the breakpoint isn't found, or hit, the
+ function will cause a testsuite failure.
+ If successful it returns a tuple with the target process and thread that hit the breakpoint."""
+
+ if in_cwd:
+ exe = os.path.join(os.getcwd(), exe_name)
+
+ # Create the target
+ target = test.dbg.CreateTarget(exe)
+ test.assertTrue(target, "Target: %s is not valid."%(exe_name))
+
+ # Set the breakpoints
+ breakpoint = target.BreakpointCreateBySourceRegex(
+ bkpt_pattern, source_spec)
+ test.assertTrue(breakpoint.GetNumLocations() > 0,
+ 'No locations found for source breakpoint: "%s"'%(bkpt_pattern))
+
+ # Launch the process, and do not stop at the entry point.
+ if not launch_info:
+ launch_info = lldb.SBLaunchInfo(None)
+ launch_info.SetWorkingDirectory(test.get_process_working_directory())
+
+ error = lldb.SBError()
+ process = target.Launch(launch_info, error)
+
+ test.assertTrue(process, "Could not create a valid process for %s: %s"%(exe_name, error.GetCString()))
+
+ # Frame #0 should be at our breakpoint.
+ threads = get_threads_stopped_at_breakpoint(
+ process, breakpoint)
+
+ test.assertTrue(len(threads) == 1, "Expected 1 thread to stop at breakpoint, %d did."%(len(threads)))
+ thread = threads[0]
+ return (target, process, thread, breakpoint)
def continue_to_breakpoint(process, bkpt):
""" Continues the process, if it stops, returns the threads stopped at bkpt; otherwise, returns None"""
diff --git a/packages/Python/lldbsuite/test/make/Android.rules b/packages/Python/lldbsuite/test/make/Android.rules
index 0a725494d354..058401f425ad 100644
--- a/packages/Python/lldbsuite/test/make/Android.rules
+++ b/packages/Python/lldbsuite/test/make/Android.rules
@@ -90,7 +90,3 @@ else
ARCH_LDFLAGS += $(NDK_ROOT)/sources/cxx-stl/gnu-libstdc++/4.9/libs/$(STL_ARCH)/libgnustl_static.a
endif
-
-ifeq "$(ARCH)" "i386"
- ARCH_CFLAGS += -mstackrealign
-endif
diff --git a/packages/Python/lldbsuite/test/sample_test/TestSampleTest.py b/packages/Python/lldbsuite/test/sample_test/TestSampleTest.py
index bb34727ff81b..9a1748bbabb5 100644
--- a/packages/Python/lldbsuite/test/sample_test/TestSampleTest.py
+++ b/packages/Python/lldbsuite/test/sample_test/TestSampleTest.py
@@ -25,6 +25,7 @@ class RenameThisSampleTestTestCase(TestBase):
def test_sample_rename_this(self):
"""There can be many tests in a test case - describe this test here."""
self.build()
+ self.main_source_file = lldb.SBFileSpec("main.c")
self.sample_test()
def setUp(self):
@@ -33,40 +34,15 @@ class RenameThisSampleTestTestCase(TestBase):
def sample_test(self):
"""You might use the test implementation in several ways, say so here."""
- exe = os.path.join(os.getcwd(), "a.out")
- # Create a target by the debugger.
- target = self.dbg.CreateTarget(exe)
- self.assertTrue(target, VALID_TARGET)
+ # This function starts a process, "a.out" by default, sets a source
+ # breakpoint, runs to it, and returns the thread, process & target.
+ # It optionally takes an SBLaunchOption argument if you want to pass
+ # arguments or environment variables.
+ (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(self,
+ "Set a breakpoint here", self.main_source_file)
- # Now create a breakpoint in main.c at the source matching
- # "Set a breakpoint here"
- breakpoint = target.BreakpointCreateBySourceRegex(
- "Set a breakpoint here", lldb.SBFileSpec("main.c"))
- self.assertTrue(breakpoint and
- breakpoint.GetNumLocations() >= 1,
- VALID_BREAKPOINT)
-
- error = lldb.SBError()
- # This is the launch info. If you want to launch with arguments or
- # environment variables, add them using SetArguments or
- # SetEnvironmentEntries
-
- launch_info = lldb.SBLaunchInfo(None)
- process = target.Launch(launch_info, error)
- self.assertTrue(process, PROCESS_IS_VALID)
-
- # Did we hit our breakpoint?
- from lldbsuite.test.lldbutil import get_threads_stopped_at_breakpoint
- threads = get_threads_stopped_at_breakpoint(process, breakpoint)
- self.assertTrue(
- len(threads) == 1,
- "There should be a thread stopped at our breakpoint")
-
- # The hit count for the breakpoint should be 1.
- self.assertTrue(breakpoint.GetHitCount() == 1)
-
- frame = threads[0].GetFrameAtIndex(0)
+ frame = thread.GetFrameAtIndex(0)
test_var = frame.FindVariable("test_var")
self.assertTrue(test_var.GetError().Success(), "Failed to fetch test_var")
test_value = test_var.GetValueAsUnsigned()
diff --git a/source/Commands/CommandObjectThread.cpp b/source/Commands/CommandObjectThread.cpp
index 687187b26ccd..6a933df43e14 100644
--- a/source/Commands/CommandObjectThread.cpp
+++ b/source/Commands/CommandObjectThread.cpp
@@ -161,9 +161,9 @@ public:
// List the common thread ID's
const std::vector<uint32_t> &thread_index_ids =
stack.GetUniqueThreadIndexIDs();
- strm.Printf("%lu thread(s) ", thread_index_ids.size());
+ strm.Format("{0} thread(s) ", thread_index_ids.size());
for (const uint32_t &thread_index_id : thread_index_ids) {
- strm.Printf("#%u ", thread_index_id);
+ strm.Format("#{0} ", thread_index_id);
}
strm.EOL();
@@ -209,7 +209,7 @@ protected:
Process *process = m_exe_ctx.GetProcessPtr();
Thread *thread = process->GetThreadList().FindThreadByID(tid).get();
if (thread == nullptr) {
- result.AppendErrorWithFormat("Failed to process thread# %llu.\n", tid);
+ result.AppendErrorWithFormatv("Failed to process thread #{0}.\n", tid);
result.SetStatus(eReturnStatusFailed);
return false;
}
diff --git a/source/Core/DumpDataExtractor.cpp b/source/Core/DumpDataExtractor.cpp
index 2b7abd60f8bc..c2a9115c3068 100644
--- a/source/Core/DumpDataExtractor.cpp
+++ b/source/Core/DumpDataExtractor.cpp
@@ -154,7 +154,8 @@ lldb::offset_t lldb_private::DumpDataExtractor(
target_sp = exe_scope->CalculateTarget();
if (target_sp) {
DisassemblerSP disassembler_sp(Disassembler::FindPlugin(
- target_sp->GetArchitecture(), nullptr, nullptr));
+ target_sp->GetArchitecture(),
+ target_sp->GetDisassemblyFlavor(), nullptr));
if (disassembler_sp) {
lldb::addr_t addr = base_addr + start_offset;
lldb_private::Address so_addr;
diff --git a/source/Host/common/File.cpp b/source/Host/common/File.cpp
index 3de93ebc220b..90a4462c6ca9 100644
--- a/source/Host/common/File.cpp
+++ b/source/Host/common/File.cpp
@@ -24,10 +24,12 @@
#endif
#include "llvm/Support/ConvertUTF.h"
+#include "llvm/Support/Errno.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Process.h" // for llvm::sys::Process::FileDescriptorHasColors()
#include "lldb/Host/Config.h"
+#include "lldb/Host/Host.h"
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/FileSpec.h"
#include "lldb/Utility/Log.h"
@@ -133,9 +135,8 @@ FILE *File::GetStream() {
m_should_close_fd = true;
}
- do {
- m_stream = ::fdopen(m_descriptor, mode);
- } while (m_stream == NULL && errno == EINTR);
+ m_stream =
+ llvm::sys::RetryAfterSignal(nullptr, ::fdopen, m_descriptor, mode);
// If we got a stream, then we own the stream and should no
// longer own the descriptor because fclose() will close it for us
@@ -157,6 +158,19 @@ void File::SetStream(FILE *fh, bool transfer_ownership) {
m_own_stream = transfer_ownership;
}
+static int DoOpen(const char *path, int flags, int mode) {
+#ifdef _MSC_VER
+ std::wstring wpath;
+ if (!llvm::ConvertUTF8toWide(path, wpath))
+ return -1;
+ int result;
+ ::_wsopen_s(&result, wpath.c_str(), flags, _SH_DENYNO, mode);
+ return result;
+#else
+ return ::open(path, flags, mode);
+#endif
+}
+
Status File::Open(const char *path, uint32_t options, uint32_t permissions) {
Status error;
if (IsValid())
@@ -222,20 +236,7 @@ Status File::Open(const char *path, uint32_t options, uint32_t permissions) {
mode |= S_IXOTH;
}
- do {
-#ifdef _MSC_VER
- std::wstring wpath;
- if (!llvm::ConvertUTF8toWide(path, wpath)) {
- m_descriptor = -1;
- error.SetErrorString("Error converting path to UTF-16");
- return error;
- }
- ::_wsopen_s(&m_descriptor, wpath.c_str(), oflag, _SH_DENYNO, mode);
-#else
- m_descriptor = ::open(path, oflag, mode);
-#endif
- } while (m_descriptor < 0 && errno == EINTR);
-
+ m_descriptor = llvm::sys::RetryAfterSignal(-1, DoOpen, path, oflag, mode);
if (!DescriptorIsValid())
error.SetErrorToErrno();
else {
@@ -421,12 +422,7 @@ off_t File::SeekFromEnd(off_t offset, Status *error_ptr) {
Status File::Flush() {
Status error;
if (StreamIsValid()) {
- int err = 0;
- do {
- err = ::fflush(m_stream);
- } while (err == EOF && errno == EINTR);
-
- if (err == EOF)
+ if (llvm::sys::RetryAfterSignal(EOF, ::fflush, m_stream) == EOF)
error.SetErrorToErrno();
} else if (!DescriptorIsValid()) {
error.SetErrorString("invalid file handle");
@@ -442,12 +438,7 @@ Status File::Sync() {
if (err == 0)
error.SetErrorToGenericError();
#else
- int err = 0;
- do {
- err = ::fsync(m_descriptor);
- } while (err == -1 && errno == EINTR);
-
- if (err == -1)
+ if (llvm::sys::RetryAfterSignal(-1, ::fsync, m_descriptor) == -1)
error.SetErrorToErrno();
#endif
} else {
@@ -497,10 +488,7 @@ Status File::Read(void *buf, size_t &num_bytes) {
ssize_t bytes_read = -1;
if (DescriptorIsValid()) {
- do {
- bytes_read = ::read(m_descriptor, buf, num_bytes);
- } while (bytes_read < 0 && errno == EINTR);
-
+ bytes_read = llvm::sys::RetryAfterSignal(-1, ::read, m_descriptor, buf, num_bytes);
if (bytes_read == -1) {
error.SetErrorToErrno();
num_bytes = 0;
@@ -559,10 +547,8 @@ Status File::Write(const void *buf, size_t &num_bytes) {
ssize_t bytes_written = -1;
if (DescriptorIsValid()) {
- do {
- bytes_written = ::write(m_descriptor, buf, num_bytes);
- } while (bytes_written < 0 && errno == EINTR);
-
+ bytes_written =
+ llvm::sys::RetryAfterSignal(-1, ::write, m_descriptor, buf, num_bytes);
if (bytes_written == -1) {
error.SetErrorToErrno();
num_bytes = 0;
@@ -624,11 +610,8 @@ Status File::Read(void *buf, size_t &num_bytes, off_t &offset) {
#ifndef _WIN32
int fd = GetDescriptor();
if (fd != kInvalidDescriptor) {
- ssize_t bytes_read = -1;
- do {
- bytes_read = ::pread(fd, buf, num_bytes, offset);
- } while (bytes_read < 0 && errno == EINTR);
-
+ ssize_t bytes_read =
+ llvm::sys::RetryAfterSignal(-1, ::pread, fd, buf, num_bytes, offset);
if (bytes_read < 0) {
num_bytes = 0;
error.SetErrorToErrno();
@@ -730,11 +713,8 @@ Status File::Write(const void *buf, size_t &num_bytes, off_t &offset) {
int fd = GetDescriptor();
if (fd != kInvalidDescriptor) {
#ifndef _WIN32
- ssize_t bytes_written = -1;
- do {
- bytes_written = ::pwrite(m_descriptor, buf, num_bytes, offset);
- } while (bytes_written < 0 && errno == EINTR);
-
+ ssize_t bytes_written =
+ llvm::sys::RetryAfterSignal(-1, ::pwrite, m_descriptor, buf, num_bytes, offset);
if (bytes_written < 0) {
num_bytes = 0;
error.SetErrorToErrno();
diff --git a/source/Host/common/MainLoop.cpp b/source/Host/common/MainLoop.cpp
index 7de6f7fa865d..c0c4471e735f 100644
--- a/source/Host/common/MainLoop.cpp
+++ b/source/Host/common/MainLoop.cpp
@@ -193,10 +193,16 @@ Status MainLoop::RunImpl::Poll() {
void MainLoop::RunImpl::ProcessEvents() {
#ifdef FORCE_PSELECT
- for (const auto &fd : loop.m_read_fds) {
- if (!FD_ISSET(fd.first, &read_fd_set))
- continue;
- IOObject::WaitableHandle handle = fd.first;
+ // Collect first all readable file descriptors into a separate vector and then
+ // iterate over it to invoke callbacks. Iterating directly over
+ // loop.m_read_fds is not possible because the callbacks can modify the
+ // container which could invalidate the iterator.
+ std::vector<IOObject::WaitableHandle> fds;
+ for (const auto &fd : loop.m_read_fds)
+ if (FD_ISSET(fd.first, &read_fd_set))
+ fds.push_back(fd.first);
+
+ for (const auto &handle : fds) {
#else
for (const auto &fd : read_fds) {
if ((fd.revents & POLLIN) == 0)
@@ -209,13 +215,16 @@ void MainLoop::RunImpl::ProcessEvents() {
loop.ProcessReadObject(handle);
}
- for (const auto &entry : loop.m_signals) {
+ std::vector<int> signals;
+ for (const auto &entry : loop.m_signals)
+ if (g_signal_flags[entry.first] != 0)
+ signals.push_back(entry.first);
+
+ for (const auto &signal : signals) {
if (loop.m_terminate_request)
return;
- if (g_signal_flags[entry.first] == 0)
- continue; // No signal
- g_signal_flags[entry.first] = 0;
- loop.ProcessSignal(entry.first);
+ g_signal_flags[signal] = 0;
+ loop.ProcessSignal(signal);
}
}
#endif
diff --git a/source/Host/common/NativeProcessProtocol.cpp b/source/Host/common/NativeProcessProtocol.cpp
index 341c301dc9c5..b5b6e9d8b923 100644
--- a/source/Host/common/NativeProcessProtocol.cpp
+++ b/source/Host/common/NativeProcessProtocol.cpp
@@ -29,11 +29,13 @@ using namespace lldb_private;
// NativeProcessProtocol Members
// -----------------------------------------------------------------------------
-NativeProcessProtocol::NativeProcessProtocol(lldb::pid_t pid)
- : m_pid(pid), m_threads(), m_current_thread_id(LLDB_INVALID_THREAD_ID),
- m_threads_mutex(), m_state(lldb::eStateInvalid), m_state_mutex(),
- m_delegates_mutex(), m_delegates(), m_breakpoint_list(),
- m_watchpoint_list(), m_terminal_fd(-1), m_stop_id(0) {}
+NativeProcessProtocol::NativeProcessProtocol(lldb::pid_t pid, int terminal_fd,
+ NativeDelegate &delegate)
+ : m_pid(pid), m_terminal_fd(terminal_fd) {
+ bool registered = RegisterNativeDelegate(delegate);
+ assert(registered);
+ (void)registered;
+}
lldb_private::Status NativeProcessProtocol::Interrupt() {
Status error;
@@ -488,23 +490,4 @@ Status NativeProcessProtocol::ResolveProcessArchitecture(lldb::pid_t pid,
"failed to retrieve a valid architecture from the exe module");
}
-#if !defined(__linux__) && !defined(__NetBSD__)
-// These need to be implemented to support lldb-gdb-server on a given platform.
-// Stubs are
-// provided to make the rest of the code link on non-supported platforms.
-
-Status NativeProcessProtocol::Launch(ProcessLaunchInfo &launch_info,
- NativeDelegate &native_delegate,
- MainLoop &mainloop,
- NativeProcessProtocolSP &process_sp) {
- llvm_unreachable("Platform has no NativeProcessProtocol support");
-}
-
-Status NativeProcessProtocol::Attach(lldb::pid_t pid,
- NativeDelegate &native_delegate,
- MainLoop &mainloop,
- NativeProcessProtocolSP &process_sp) {
- llvm_unreachable("Platform has no NativeProcessProtocol support");
-}
-
-#endif
+NativeProcessProtocol::Factory::~Factory() = default;
diff --git a/source/Host/common/SocketAddress.cpp b/source/Host/common/SocketAddress.cpp
index 440ae5d9027f..41150fa7fd74 100644
--- a/source/Host/common/SocketAddress.cpp
+++ b/source/Host/common/SocketAddress.cpp
@@ -201,7 +201,7 @@ const SocketAddress &SocketAddress::
operator=(const struct addrinfo *addr_info) {
Clear();
if (addr_info && addr_info->ai_addr && addr_info->ai_addrlen > 0 &&
- addr_info->ai_addrlen <= sizeof m_socket_addr) {
+ size_t(addr_info->ai_addrlen) <= sizeof m_socket_addr) {
::memcpy(&m_socket_addr, addr_info->ai_addr, addr_info->ai_addrlen);
}
return *this;
diff --git a/source/Host/macosx/Host.mm b/source/Host/macosx/Host.mm
index bbf70cd4c4b3..75624ef21f43 100644
--- a/source/Host/macosx/Host.mm
+++ b/source/Host/macosx/Host.mm
@@ -74,6 +74,7 @@
#include "lldb/Utility/StructuredData.h"
#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Errno.h"
#include "cfcpp/CFCBundle.h"
#include "cfcpp/CFCMutableArray.h"
@@ -1663,10 +1664,7 @@ HostThread Host::StartMonitoringChildProcess(
int wait_pid = 0;
bool cancel = false;
bool exited = false;
- do {
- wait_pid = ::waitpid(pid, &status, 0);
- } while (wait_pid < 0 && errno == EINTR);
-
+ wait_pid = llvm::sys::RetryAfterSignal(-1, ::waitpid, pid, &status, 0);
if (wait_pid >= 0) {
int signal = 0;
int exit_status = 0;
diff --git a/source/Host/posix/ConnectionFileDescriptorPosix.cpp b/source/Host/posix/ConnectionFileDescriptorPosix.cpp
index 6b0f069c35a9..105ef0f23d46 100644
--- a/source/Host/posix/ConnectionFileDescriptorPosix.cpp
+++ b/source/Host/posix/ConnectionFileDescriptorPosix.cpp
@@ -245,11 +245,7 @@ ConnectionStatus ConnectionFileDescriptor::Connect(llvm::StringRef path,
} else if ((addr = GetURLAddress(path, FILE_SCHEME))) {
std::string addr_str = addr->str();
// file:///PATH
- int fd = -1;
- do {
- fd = ::open(addr_str.c_str(), O_RDWR);
- } while (fd == -1 && errno == EINTR);
-
+ int fd = llvm::sys::RetryAfterSignal(-1, ::open, addr_str.c_str(), O_RDWR);
if (fd == -1) {
if (error_ptr)
error_ptr->SetErrorToErrno();
@@ -620,20 +616,17 @@ ConnectionFileDescriptor::BytesAvailable(const Timeout<std::micro> &timeout,
if (select_helper.FDIsSetRead(pipe_fd)) {
// There is an interrupt or exit command in the command pipe
// Read the data from that pipe:
- char buffer[1];
-
- ssize_t bytes_read;
-
- do {
- bytes_read = ::read(pipe_fd, buffer, sizeof(buffer));
- } while (bytes_read < 0 && errno == EINTR);
+ char c;
- switch (buffer[0]) {
+ ssize_t bytes_read = llvm::sys::RetryAfterSignal(-1, ::read, pipe_fd, &c, 1);
+ assert(bytes_read == 1);
+ (void)bytes_read;
+ switch (c) {
case 'q':
if (log)
log->Printf("%p ConnectionFileDescriptor::BytesAvailable() "
"got data: %c from the command channel.",
- static_cast<void *>(this), buffer[0]);
+ static_cast<void *>(this), c);
return eConnectionStatusEndOfFile;
case 'i':
// Interrupt the current read
diff --git a/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.cpp b/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.cpp
index d385b78e0ec4..5dbb3bb4ef7e 100644
--- a/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.cpp
+++ b/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.cpp
@@ -63,10 +63,10 @@ void AuxVector::ParseAuxv(DataExtractor &data) {
if (!ParseAuxvEntry(data, entry, &offset, byte_size))
break;
- if (entry.type == AT_NULL)
+ if (entry.type == AUXV_AT_NULL)
break;
- if (entry.type == AT_IGNORE)
+ if (entry.type == AUXV_AT_IGNORE)
continue;
m_auxv.push_back(entry);
@@ -110,43 +110,43 @@ void AuxVector::DumpToLog(Log *log) const {
const char *AuxVector::GetEntryName(EntryType type) {
const char *name = "AT_???";
-#define ENTRY_NAME(_type) \
- _type: \
- name = #_type
+#define ENTRY_NAME(_type) \
+ _type: \
+ name = #_type + 5
switch (type) {
- case ENTRY_NAME(AT_NULL); break;
- case ENTRY_NAME(AT_IGNORE); break;
- case ENTRY_NAME(AT_EXECFD); break;
- case ENTRY_NAME(AT_PHDR); break;
- case ENTRY_NAME(AT_PHENT); break;
- case ENTRY_NAME(AT_PHNUM); break;
- case ENTRY_NAME(AT_PAGESZ); break;
- case ENTRY_NAME(AT_BASE); break;
- case ENTRY_NAME(AT_FLAGS); break;
- case ENTRY_NAME(AT_ENTRY); break;
- case ENTRY_NAME(AT_NOTELF); break;
- case ENTRY_NAME(AT_UID); break;
- case ENTRY_NAME(AT_EUID); break;
- case ENTRY_NAME(AT_GID); break;
- case ENTRY_NAME(AT_EGID); break;
- case ENTRY_NAME(AT_CLKTCK); break;
- case ENTRY_NAME(AT_PLATFORM); break;
- case ENTRY_NAME(AT_HWCAP); break;
- case ENTRY_NAME(AT_FPUCW); break;
- case ENTRY_NAME(AT_DCACHEBSIZE); break;
- case ENTRY_NAME(AT_ICACHEBSIZE); break;
- case ENTRY_NAME(AT_UCACHEBSIZE); break;
- case ENTRY_NAME(AT_IGNOREPPC); break;
- case ENTRY_NAME(AT_SECURE); break;
- case ENTRY_NAME(AT_BASE_PLATFORM); break;
- case ENTRY_NAME(AT_RANDOM); break;
- case ENTRY_NAME(AT_EXECFN); break;
- case ENTRY_NAME(AT_SYSINFO); break;
- case ENTRY_NAME(AT_SYSINFO_EHDR); break;
- case ENTRY_NAME(AT_L1I_CACHESHAPE); break;
- case ENTRY_NAME(AT_L1D_CACHESHAPE); break;
- case ENTRY_NAME(AT_L2_CACHESHAPE); break;
- case ENTRY_NAME(AT_L3_CACHESHAPE); break;
+ case ENTRY_NAME(AUXV_AT_NULL); break;
+ case ENTRY_NAME(AUXV_AT_IGNORE); break;
+ case ENTRY_NAME(AUXV_AT_EXECFD); break;
+ case ENTRY_NAME(AUXV_AT_PHDR); break;
+ case ENTRY_NAME(AUXV_AT_PHENT); break;
+ case ENTRY_NAME(AUXV_AT_PHNUM); break;
+ case ENTRY_NAME(AUXV_AT_PAGESZ); break;
+ case ENTRY_NAME(AUXV_AT_BASE); break;
+ case ENTRY_NAME(AUXV_AT_FLAGS); break;
+ case ENTRY_NAME(AUXV_AT_ENTRY); break;
+ case ENTRY_NAME(AUXV_AT_NOTELF); break;
+ case ENTRY_NAME(AUXV_AT_UID); break;
+ case ENTRY_NAME(AUXV_AT_EUID); break;
+ case ENTRY_NAME(AUXV_AT_GID); break;
+ case ENTRY_NAME(AUXV_AT_EGID); break;
+ case ENTRY_NAME(AUXV_AT_CLKTCK); break;
+ case ENTRY_NAME(AUXV_AT_PLATFORM); break;
+ case ENTRY_NAME(AUXV_AT_HWCAP); break;
+ case ENTRY_NAME(AUXV_AT_FPUCW); break;
+ case ENTRY_NAME(AUXV_AT_DCACHEBSIZE); break;
+ case ENTRY_NAME(AUXV_AT_ICACHEBSIZE); break;
+ case ENTRY_NAME(AUXV_AT_UCACHEBSIZE); break;
+ case ENTRY_NAME(AUXV_AT_IGNOREPPC); break;
+ case ENTRY_NAME(AUXV_AT_SECURE); break;
+ case ENTRY_NAME(AUXV_AT_BASE_PLATFORM); break;
+ case ENTRY_NAME(AUXV_AT_RANDOM); break;
+ case ENTRY_NAME(AUXV_AT_EXECFN); break;
+ case ENTRY_NAME(AUXV_AT_SYSINFO); break;
+ case ENTRY_NAME(AUXV_AT_SYSINFO_EHDR); break;
+ case ENTRY_NAME(AUXV_AT_L1I_CACHESHAPE); break;
+ case ENTRY_NAME(AUXV_AT_L1D_CACHESHAPE); break;
+ case ENTRY_NAME(AUXV_AT_L2_CACHESHAPE); break;
+ case ENTRY_NAME(AUXV_AT_L3_CACHESHAPE); break;
}
#undef ENTRY_NAME
diff --git a/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.h b/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.h
index 9c3e1b002a24..cf9da0808357 100644
--- a/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.h
+++ b/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.h
@@ -42,41 +42,42 @@ public:
/// Constants describing the type of entry.
/// On Linux, running "LD_SHOW_AUXV=1 ./executable" will spew AUX information.
+ /// Added AUXV prefix to avoid potential conflicts with system-defined macros
enum EntryType {
- AT_NULL = 0, ///< End of auxv.
- AT_IGNORE = 1, ///< Ignore entry.
- AT_EXECFD = 2, ///< File descriptor of program.
- AT_PHDR = 3, ///< Program headers.
- AT_PHENT = 4, ///< Size of program header.
- AT_PHNUM = 5, ///< Number of program headers.
- AT_PAGESZ = 6, ///< Page size.
- AT_BASE = 7, ///< Interpreter base address.
- AT_FLAGS = 8, ///< Flags.
- AT_ENTRY = 9, ///< Program entry point.
- AT_NOTELF = 10, ///< Set if program is not an ELF.
- AT_UID = 11, ///< UID.
- AT_EUID = 12, ///< Effective UID.
- AT_GID = 13, ///< GID.
- AT_EGID = 14, ///< Effective GID.
- AT_CLKTCK = 17, ///< Clock frequency (e.g. times(2)).
- AT_PLATFORM = 15, ///< String identifying platform.
- AT_HWCAP = 16, ///< Machine dependent hints about processor capabilities.
- AT_FPUCW = 18, ///< Used FPU control word.
- AT_DCACHEBSIZE = 19, ///< Data cache block size.
- AT_ICACHEBSIZE = 20, ///< Instruction cache block size.
- AT_UCACHEBSIZE = 21, ///< Unified cache block size.
- AT_IGNOREPPC = 22, ///< Entry should be ignored.
- AT_SECURE = 23, ///< Boolean, was exec setuid-like?
- AT_BASE_PLATFORM = 24, ///< String identifying real platforms.
- AT_RANDOM = 25, ///< Address of 16 random bytes.
- AT_EXECFN = 31, ///< Filename of executable.
- AT_SYSINFO = 32, ///< Pointer to the global system page used for system
- ///calls and other nice things.
- AT_SYSINFO_EHDR = 33,
- AT_L1I_CACHESHAPE = 34, ///< Shapes of the caches.
- AT_L1D_CACHESHAPE = 35,
- AT_L2_CACHESHAPE = 36,
- AT_L3_CACHESHAPE = 37,
+ AUXV_AT_NULL = 0, ///< End of auxv.
+ AUXV_AT_IGNORE = 1, ///< Ignore entry.
+ AUXV_AT_EXECFD = 2, ///< File descriptor of program.
+ AUXV_AT_PHDR = 3, ///< Program headers.
+ AUXV_AT_PHENT = 4, ///< Size of program header.
+ AUXV_AT_PHNUM = 5, ///< Number of program headers.
+ AUXV_AT_PAGESZ = 6, ///< Page size.
+ AUXV_AT_BASE = 7, ///< Interpreter base address.
+ AUXV_AT_FLAGS = 8, ///< Flags.
+ AUXV_AT_ENTRY = 9, ///< Program entry point.
+ AUXV_AT_NOTELF = 10, ///< Set if program is not an ELF.
+ AUXV_AT_UID = 11, ///< UID.
+ AUXV_AT_EUID = 12, ///< Effective UID.
+ AUXV_AT_GID = 13, ///< GID.
+ AUXV_AT_EGID = 14, ///< Effective GID.
+ AUXV_AT_CLKTCK = 17, ///< Clock frequency (e.g. times(2)).
+ AUXV_AT_PLATFORM = 15, ///< String identifying platform.
+ AUXV_AT_HWCAP = 16, ///< Machine dependent hints about processor capabilities.
+ AUXV_AT_FPUCW = 18, ///< Used FPU control word.
+ AUXV_AT_DCACHEBSIZE = 19, ///< Data cache block size.
+ AUXV_AT_ICACHEBSIZE = 20, ///< Instruction cache block size.
+ AUXV_AT_UCACHEBSIZE = 21, ///< Unified cache block size.
+ AUXV_AT_IGNOREPPC = 22, ///< Entry should be ignored.
+ AUXV_AT_SECURE = 23, ///< Boolean, was exec setuid-like?
+ AUXV_AT_BASE_PLATFORM = 24, ///< String identifying real platforms.
+ AUXV_AT_RANDOM = 25, ///< Address of 16 random bytes.
+ AUXV_AT_EXECFN = 31, ///< Filename of executable.
+ AUXV_AT_SYSINFO = 32, ///< Pointer to the global system page used for system
+ ///calls and other nice things.
+ AUXV_AT_SYSINFO_EHDR = 33,
+ AUXV_AT_L1I_CACHESHAPE = 34, ///< Shapes of the caches.
+ AUXV_AT_L1D_CACHESHAPE = 35,
+ AUXV_AT_L2_CACHESHAPE = 36,
+ AUXV_AT_L3_CACHESHAPE = 37,
};
private:
diff --git a/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp b/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
index 0092535648bd..a7afeb6d68c3 100644
--- a/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
+++ b/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
@@ -576,7 +576,7 @@ addr_t DynamicLoaderPOSIXDYLD::ComputeLoadOffset() {
}
void DynamicLoaderPOSIXDYLD::EvalVdsoStatus() {
- AuxVector::iterator I = m_auxv->FindEntry(AuxVector::AT_SYSINFO_EHDR);
+ AuxVector::iterator I = m_auxv->FindEntry(AuxVector::AUXV_AT_SYSINFO_EHDR);
if (I != m_auxv->end())
m_vdso_base = I->value;
@@ -589,7 +589,7 @@ addr_t DynamicLoaderPOSIXDYLD::GetEntryPoint() {
if (m_auxv.get() == NULL)
return LLDB_INVALID_ADDRESS;
- AuxVector::iterator I = m_auxv->FindEntry(AuxVector::AT_ENTRY);
+ AuxVector::iterator I = m_auxv->FindEntry(AuxVector::AUXV_AT_ENTRY);
if (I == m_auxv->end())
return LLDB_INVALID_ADDRESS;
diff --git a/source/Plugins/InstrumentationRuntime/ASan/ASanRuntime.cpp b/source/Plugins/InstrumentationRuntime/ASan/ASanRuntime.cpp
index af242d786a5f..9a6e39be0bfd 100644
--- a/source/Plugins/InstrumentationRuntime/ASan/ASanRuntime.cpp
+++ b/source/Plugins/InstrumentationRuntime/ASan/ASanRuntime.cpp
@@ -247,12 +247,16 @@ bool AddressSanitizerRuntime::NotifyBreakpointHit(
AddressSanitizerRuntime *const instance =
static_cast<AddressSanitizerRuntime *>(baton);
+ ProcessSP process_sp = instance->GetProcessSP();
+
+ if (process_sp->GetModIDRef().IsLastResumeForUserExpression())
+ return false;
+
StructuredData::ObjectSP report = instance->RetrieveReportData();
std::string description;
if (report) {
description = instance->FormatDescription(report);
}
- ProcessSP process_sp = instance->GetProcessSP();
// Make sure this is the right process
if (process_sp && process_sp == context->exe_ctx_ref.GetProcessSP()) {
ThreadSP thread_sp = context->exe_ctx_ref.GetThreadSP();
diff --git a/source/Plugins/InstrumentationRuntime/MainThreadChecker/MainThreadCheckerRuntime.cpp b/source/Plugins/InstrumentationRuntime/MainThreadChecker/MainThreadCheckerRuntime.cpp
index 3c22b81df7a4..eb238419ab18 100644
--- a/source/Plugins/InstrumentationRuntime/MainThreadChecker/MainThreadCheckerRuntime.cpp
+++ b/source/Plugins/InstrumentationRuntime/MainThreadChecker/MainThreadCheckerRuntime.cpp
@@ -141,7 +141,7 @@ MainThreadCheckerRuntime::RetrieveReportData(ExecutionContextRef exe_ctx_ref) {
d->AddStringItem("class_name", className);
d->AddStringItem("selector", selector);
d->AddStringItem("description",
- apiName + " must be called from main thread only");
+ apiName + " must be used from main thread only");
d->AddIntegerItem("tid", thread_sp->GetIndexID());
d->AddItem("trace", trace_sp);
return dict_sp;
@@ -163,6 +163,9 @@ bool MainThreadCheckerRuntime::NotifyBreakpointHit(
process_sp != context->exe_ctx_ref.GetProcessSP())
return false;
+ if (process_sp->GetModIDRef().IsLastResumeForUserExpression())
+ return false;
+
StructuredData::ObjectSP report =
instance->RetrieveReportData(context->exe_ctx_ref);
diff --git a/source/Plugins/InstrumentationRuntime/TSan/TSanRuntime.cpp b/source/Plugins/InstrumentationRuntime/TSan/TSanRuntime.cpp
index f60df0463346..cf9ba60c7b60 100644
--- a/source/Plugins/InstrumentationRuntime/TSan/TSanRuntime.cpp
+++ b/source/Plugins/InstrumentationRuntime/TSan/TSanRuntime.cpp
@@ -803,6 +803,11 @@ bool ThreadSanitizerRuntime::NotifyBreakpointHit(
ThreadSanitizerRuntime *const instance =
static_cast<ThreadSanitizerRuntime *>(baton);
+ ProcessSP process_sp = instance->GetProcessSP();
+
+ if (process_sp->GetModIDRef().IsLastResumeForUserExpression())
+ return false;
+
StructuredData::ObjectSP report =
instance->RetrieveReportData(context->exe_ctx_ref);
std::string stop_reason_description;
@@ -851,7 +856,6 @@ bool ThreadSanitizerRuntime::NotifyBreakpointHit(
all_addresses_are_same);
}
- ProcessSP process_sp = instance->GetProcessSP();
// Make sure this is the right process
if (process_sp && process_sp == context->exe_ctx_ref.GetProcessSP()) {
ThreadSP thread_sp = context->exe_ctx_ref.GetThreadSP();
diff --git a/source/Plugins/InstrumentationRuntime/UBSan/UBSanRuntime.cpp b/source/Plugins/InstrumentationRuntime/UBSan/UBSanRuntime.cpp
index 023af84179aa..28c28e41ef44 100644
--- a/source/Plugins/InstrumentationRuntime/UBSan/UBSanRuntime.cpp
+++ b/source/Plugins/InstrumentationRuntime/UBSan/UBSanRuntime.cpp
@@ -217,6 +217,9 @@ bool UndefinedBehaviorSanitizerRuntime::NotifyBreakpointHit(
process_sp != context->exe_ctx_ref.GetProcessSP())
return false;
+ if (process_sp->GetModIDRef().IsLastResumeForUserExpression())
+ return false;
+
StructuredData::ObjectSP report =
instance->RetrieveReportData(context->exe_ctx_ref);
diff --git a/source/Plugins/Language/ObjC/Cocoa.cpp b/source/Plugins/Language/ObjC/Cocoa.cpp
index 2ba005e02ad4..8f4997533212 100644
--- a/source/Plugins/Language/ObjC/Cocoa.cpp
+++ b/source/Plugins/Language/ObjC/Cocoa.cpp
@@ -543,6 +543,7 @@ bool lldb_private::formatters::NSNumberSummaryProvider(
}
uint64_t value = 0;
+ bool success = false;
switch (type_code) {
case TypeCodes::sint8:
value = process_sp->ReadUnsignedIntegerFromMemory(data_location, 1, 0,
@@ -550,6 +551,7 @@ bool lldb_private::formatters::NSNumberSummaryProvider(
if (error.Fail())
return false;
NSNumber_FormatChar(valobj, stream, (char)value, options.GetLanguage());
+ success = true;
break;
case TypeCodes::sint16:
value = process_sp->ReadUnsignedIntegerFromMemory(data_location, 2, 0,
@@ -558,6 +560,7 @@ bool lldb_private::formatters::NSNumberSummaryProvider(
return false;
NSNumber_FormatShort(valobj, stream, (short)value,
options.GetLanguage());
+ success = true;
break;
case TypeCodes::sint32:
value = process_sp->ReadUnsignedIntegerFromMemory(data_location, 4, 0,
@@ -565,6 +568,7 @@ bool lldb_private::formatters::NSNumberSummaryProvider(
if (error.Fail())
return false;
NSNumber_FormatInt(valobj, stream, (int)value, options.GetLanguage());
+ success = true;
break;
case TypeCodes::sint64:
value = process_sp->ReadUnsignedIntegerFromMemory(data_location, 8, 0,
@@ -572,6 +576,7 @@ bool lldb_private::formatters::NSNumberSummaryProvider(
if (error.Fail())
return false;
NSNumber_FormatLong(valobj, stream, value, options.GetLanguage());
+ success = true;
break;
case TypeCodes::f32:
{
@@ -582,6 +587,7 @@ bool lldb_private::formatters::NSNumberSummaryProvider(
float flt_value = 0.0f;
memcpy(&flt_value, &flt_as_int, sizeof(flt_as_int));
NSNumber_FormatFloat(valobj, stream, flt_value, options.GetLanguage());
+ success = true;
break;
}
case TypeCodes::f64:
@@ -593,6 +599,7 @@ bool lldb_private::formatters::NSNumberSummaryProvider(
double dbl_value = 0.0;
memcpy(&dbl_value, &dbl_as_lng, sizeof(dbl_as_lng));
NSNumber_FormatDouble(valobj, stream, dbl_value, options.GetLanguage());
+ success = true;
break;
}
case TypeCodes::sint128: // internally, this is the same
@@ -608,12 +615,11 @@ bool lldb_private::formatters::NSNumberSummaryProvider(
return false;
llvm::APInt i128_value(128, words);
NSNumber_FormatInt128(valobj, stream, i128_value, options.GetLanguage());
+ success = true;
break;
}
- default:
- return false;
}
- return true;
+ return success;
}
}
diff --git a/source/Plugins/Platform/Android/PlatformAndroid.cpp b/source/Plugins/Platform/Android/PlatformAndroid.cpp
index d896a9f99e63..0f37da60d5d6 100644
--- a/source/Plugins/Platform/Android/PlatformAndroid.cpp
+++ b/source/Plugins/Platform/Android/PlatformAndroid.cpp
@@ -366,13 +366,17 @@ bool PlatformAndroid::GetRemoteOSVersion() {
return m_major_os_version != 0;
}
-const char *PlatformAndroid::GetLibdlFunctionDeclarations() const {
- return R"(
+llvm::StringRef PlatformAndroid::GetLibdlFunctionDeclarations() {
+ // Older platform versions have the dl function symbols mangled
+ if (GetSdkVersion() < 26)
+ return R"(
extern "C" void* dlopen(const char*, int) asm("__dl_dlopen");
extern "C" void* dlsym(void*, const char*) asm("__dl_dlsym");
extern "C" int dlclose(void*) asm("__dl_dlclose");
extern "C" char* dlerror(void) asm("__dl_dlerror");
)";
+
+ return PlatformPOSIX::GetLibdlFunctionDeclarations();
}
AdbClient::SyncService *PlatformAndroid::GetSyncService(Status &error) {
diff --git a/source/Plugins/Platform/Android/PlatformAndroid.h b/source/Plugins/Platform/Android/PlatformAndroid.h
index 8fb4cc71a69f..638dba973369 100644
--- a/source/Plugins/Platform/Android/PlatformAndroid.h
+++ b/source/Plugins/Platform/Android/PlatformAndroid.h
@@ -76,7 +76,7 @@ protected:
Status DownloadSymbolFile(const lldb::ModuleSP &module_sp,
const FileSpec &dst_file_spec) override;
- const char *GetLibdlFunctionDeclarations() const override;
+ llvm::StringRef GetLibdlFunctionDeclarations() override;
private:
AdbClient::SyncService *GetSyncService(Status &error);
diff --git a/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp b/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp
index f4cf22ad7583..013c33def13b 100644
--- a/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp
+++ b/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp
@@ -884,7 +884,7 @@ void PlatformPOSIX::CalculateTrapHandlerSymbolNames() {
Status PlatformPOSIX::EvaluateLibdlExpression(
lldb_private::Process *process, const char *expr_cstr,
- const char *expr_prefix, lldb::ValueObjectSP &result_valobj_sp) {
+ llvm::StringRef expr_prefix, lldb::ValueObjectSP &result_valobj_sp) {
DynamicLoader *loader = process->GetDynamicLoader();
if (loader) {
Status error = loader->CanLoadImage();
@@ -944,7 +944,7 @@ uint32_t PlatformPOSIX::DoLoadImage(lldb_private::Process *process,
the_result;
)",
path);
- const char *prefix = GetLibdlFunctionDeclarations();
+ llvm::StringRef prefix = GetLibdlFunctionDeclarations();
lldb::ValueObjectSP result_valobj_sp;
error = EvaluateLibdlExpression(process, expr.GetData(), prefix,
result_valobj_sp);
@@ -992,7 +992,7 @@ Status PlatformPOSIX::UnloadImage(lldb_private::Process *process,
StreamString expr;
expr.Printf("dlclose((void *)0x%" PRIx64 ")", image_addr);
- const char *prefix = GetLibdlFunctionDeclarations();
+ llvm::StringRef prefix = GetLibdlFunctionDeclarations();
lldb::ValueObjectSP result_valobj_sp;
Status error = EvaluateLibdlExpression(process, expr.GetData(), prefix,
result_valobj_sp);
@@ -1024,7 +1024,7 @@ lldb::ProcessSP PlatformPOSIX::ConnectProcess(llvm::StringRef connect_url,
error);
}
-const char *PlatformPOSIX::GetLibdlFunctionDeclarations() const {
+llvm::StringRef PlatformPOSIX::GetLibdlFunctionDeclarations() {
return R"(
extern "C" void* dlopen(const char*, int);
extern "C" void* dlsym(void*, const char*);
diff --git a/source/Plugins/Platform/POSIX/PlatformPOSIX.h b/source/Plugins/Platform/POSIX/PlatformPOSIX.h
index 742702b07b88..ebc36c2461db 100644
--- a/source/Plugins/Platform/POSIX/PlatformPOSIX.h
+++ b/source/Plugins/Platform/POSIX/PlatformPOSIX.h
@@ -198,10 +198,10 @@ protected:
lldb_private::Status
EvaluateLibdlExpression(lldb_private::Process *process, const char *expr_cstr,
- const char *expr_prefix,
+ llvm::StringRef expr_prefix,
lldb::ValueObjectSP &result_valobj_sp);
- virtual const char *GetLibdlFunctionDeclarations() const;
+ virtual llvm::StringRef GetLibdlFunctionDeclarations();
private:
DISALLOW_COPY_AND_ASSIGN(PlatformPOSIX);
diff --git a/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp b/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp
index 10dd14753914..a4f5f02dde62 100644
--- a/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp
+++ b/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp
@@ -746,15 +746,9 @@ ProcessMonitor::ProcessMonitor(
if (!error.Success())
return;
-WAIT_AGAIN:
- // Wait for the operation thread to initialize.
- if (sem_wait(&args->m_semaphore)) {
- if (errno == EINTR)
- goto WAIT_AGAIN;
- else {
- error.SetErrorToErrno();
- return;
- }
+ if (llvm::sys::RetryAfterSignal(-1, sem_wait, &args->m_semaphore) == -1) {
+ error.SetErrorToErrno();
+ return;
}
// Check that the launch was a success.
@@ -790,15 +784,9 @@ ProcessMonitor::ProcessMonitor(ProcessFreeBSD *process, lldb::pid_t pid,
if (!error.Success())
return;
-WAIT_AGAIN:
- // Wait for the operation thread to initialize.
- if (sem_wait(&args->m_semaphore)) {
- if (errno == EINTR)
- goto WAIT_AGAIN;
- else {
- error.SetErrorToErrno();
- return;
- }
+ if (llvm::sys::RetryAfterSignal(-1, sem_wait, &args->m_semaphore) == -1) {
+ error.SetErrorToErrno();
+ return;
}
// Check that the attach was a success.
diff --git a/source/Plugins/Process/Linux/NativeProcessLinux.cpp b/source/Plugins/Process/Linux/NativeProcessLinux.cpp
index 8e378802de9c..d988ee93a2bc 100644
--- a/source/Plugins/Process/Linux/NativeProcessLinux.cpp
+++ b/source/Plugins/Process/Linux/NativeProcessLinux.cpp
@@ -214,207 +214,122 @@ static Status EnsureFDFlags(int fd, int flags) {
// Public Static Methods
// -----------------------------------------------------------------------------
-Status NativeProcessProtocol::Launch(
- ProcessLaunchInfo &launch_info,
- NativeProcessProtocol::NativeDelegate &native_delegate, MainLoop &mainloop,
- NativeProcessProtocolSP &native_process_sp) {
+llvm::Expected<NativeProcessProtocolSP>
+NativeProcessLinux::Factory::Launch(ProcessLaunchInfo &launch_info,
+ NativeDelegate &native_delegate,
+ MainLoop &mainloop) const {
Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
- Status error;
+ MaybeLogLaunchInfo(launch_info);
- // Verify the working directory is valid if one was specified.
- FileSpec working_dir{launch_info.GetWorkingDirectory()};
- if (working_dir && (!working_dir.ResolvePath() ||
- !llvm::sys::fs::is_directory(working_dir.GetPath()))) {
- error.SetErrorStringWithFormat("No such file or directory: %s",
- working_dir.GetCString());
- return error;
+ 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();
}
- // Create the NativeProcessLinux in launch mode.
- native_process_sp.reset(new NativeProcessLinux());
-
- if (!native_process_sp->RegisterNativeDelegate(native_delegate)) {
- native_process_sp.reset();
- error.SetErrorStringWithFormat("failed to register the native delegate");
- return error;
+ // 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");
- error = std::static_pointer_cast<NativeProcessLinux>(native_process_sp)
- ->LaunchInferior(mainloop, launch_info);
+ ArchSpec arch;
+ if ((status = ResolveProcessArchitecture(pid, arch)).Fail())
+ return status.ToError();
- if (error.Fail()) {
- native_process_sp.reset();
- LLDB_LOG(log, "failed to launch process: {0}", error);
- return error;
- }
+ // Set the architecture to the exe architecture.
+ LLDB_LOG(log, "pid = {0:x}, detected architecture {1}", pid,
+ arch.GetArchitectureName());
- launch_info.SetProcessID(native_process_sp->GetID());
+ status = SetDefaultPtraceOpts(pid);
+ if (status.Fail()) {
+ LLDB_LOG(log, "failed to set default ptrace options: {0}", status);
+ return status.ToError();
+ }
- return error;
+ std::shared_ptr<NativeProcessLinux> process_sp(new NativeProcessLinux(
+ pid, launch_info.GetPTY().ReleaseMasterFileDescriptor(), native_delegate,
+ arch, mainloop));
+ process_sp->InitializeThreads({pid});
+ return process_sp;
}
-Status NativeProcessProtocol::Attach(
+llvm::Expected<NativeProcessProtocolSP> NativeProcessLinux::Factory::Attach(
lldb::pid_t pid, NativeProcessProtocol::NativeDelegate &native_delegate,
- MainLoop &mainloop, NativeProcessProtocolSP &native_process_sp) {
+ MainLoop &mainloop) const {
Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
LLDB_LOG(log, "pid = {0:x}", pid);
// Retrieve the architecture for the running process.
- ArchSpec process_arch;
- Status error = ResolveProcessArchitecture(pid, process_arch);
- if (!error.Success())
- return error;
+ ArchSpec arch;
+ Status status = ResolveProcessArchitecture(pid, arch);
+ if (!status.Success())
+ return status.ToError();
- std::shared_ptr<NativeProcessLinux> native_process_linux_sp(
- new NativeProcessLinux());
+ auto tids_or = NativeProcessLinux::Attach(pid);
+ if (!tids_or)
+ return tids_or.takeError();
- if (!native_process_linux_sp->RegisterNativeDelegate(native_delegate)) {
- error.SetErrorStringWithFormat("failed to register the native delegate");
- return error;
- }
-
- native_process_linux_sp->AttachToInferior(mainloop, pid, error);
- if (!error.Success())
- return error;
-
- native_process_sp = native_process_linux_sp;
- return error;
+ std::shared_ptr<NativeProcessLinux> process_sp(
+ new NativeProcessLinux(pid, -1, native_delegate, arch, mainloop));
+ process_sp->InitializeThreads(*tids_or);
+ return process_sp;
}
// -----------------------------------------------------------------------------
// Public Instance Methods
// -----------------------------------------------------------------------------
-NativeProcessLinux::NativeProcessLinux()
- : NativeProcessProtocol(LLDB_INVALID_PROCESS_ID), m_arch(),
- m_supports_mem_region(eLazyBoolCalculate), m_mem_region_cache(),
- m_pending_notification_tid(LLDB_INVALID_THREAD_ID),
- m_pt_proces_trace_id(LLDB_INVALID_UID) {}
-
-void NativeProcessLinux::AttachToInferior(MainLoop &mainloop, lldb::pid_t pid,
- Status &error) {
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
- LLDB_LOG(log, "pid = {0:x}", pid);
+NativeProcessLinux::NativeProcessLinux(::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(); }, error);
- if (!m_sigchld_handle)
- return;
-
- error = ResolveProcessArchitecture(pid, m_arch);
- if (!error.Success())
- return;
-
- // Set the architecture to the exe architecture.
- LLDB_LOG(log, "pid = {0:x}, detected architecture {1}", pid,
- m_arch.GetArchitectureName());
- m_pid = pid;
- SetState(eStateAttaching);
-
- Attach(pid, error);
+ SIGCHLD, [this](MainLoopBase &) { SigchldHandler(); }, status);
+ assert(m_sigchld_handle && status.Success());
}
-Status NativeProcessLinux::LaunchInferior(MainLoop &mainloop,
- ProcessLaunchInfo &launch_info) {
- Status error;
- m_sigchld_handle = mainloop.RegisterSignal(
- SIGCHLD, [this](MainLoopBase &) { SigchldHandler(); }, error);
- if (!m_sigchld_handle)
- return error;
-
- SetState(eStateLaunching);
-
- MaybeLogLaunchInfo(launch_info);
-
- ::pid_t pid =
- ProcessLauncherPosixFork().LaunchProcess(launch_info, error).GetProcessId();
- if (error.Fail())
- return error;
-
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
-
- // Wait for the child process to trap on its call to execve.
- ::pid_t wpid;
- int status;
- if ((wpid = waitpid(pid, &status, 0)) < 0) {
- error.SetErrorToErrno();
- LLDB_LOG(log, "waitpid for inferior failed with %s", error);
-
- // Mark the inferior as invalid.
- // FIXME this could really use a new state - eStateLaunchFailure. For now,
- // using eStateInvalid.
- SetState(StateType::eStateInvalid);
-
- return error;
- }
- assert(WIFSTOPPED(status) && (wpid == static_cast<::pid_t>(pid)) &&
- "Could not sync with inferior process.");
-
- LLDB_LOG(log, "inferior started, now in stopped state");
- error = SetDefaultPtraceOpts(pid);
- if (error.Fail()) {
- LLDB_LOG(log, "failed to set default ptrace options: {0}", error);
-
- // Mark the inferior as invalid.
- // FIXME this could really use a new state - eStateLaunchFailure. For now,
- // using eStateInvalid.
- SetState(StateType::eStateInvalid);
-
- return error;
- }
-
- // Release the master terminal descriptor and pass it off to the
- // NativeProcessLinux instance. Similarly stash the inferior pid.
- m_terminal_fd = launch_info.GetPTY().ReleaseMasterFileDescriptor();
- m_pid = pid;
- launch_info.SetProcessID(pid);
-
- if (m_terminal_fd != -1) {
- error = EnsureFDFlags(m_terminal_fd, O_NONBLOCK);
- if (error.Fail()) {
- LLDB_LOG(log,
- "inferior EnsureFDFlags failed for ensuring terminal "
- "O_NONBLOCK setting: {0}",
- error);
-
- // Mark the inferior as invalid.
- // FIXME this could really use a new state - eStateLaunchFailure. For
- // now, using eStateInvalid.
- SetState(StateType::eStateInvalid);
-
- return error;
- }
+void NativeProcessLinux::InitializeThreads(llvm::ArrayRef<::pid_t> tids) {
+ for (const auto &tid : tids) {
+ NativeThreadLinuxSP thread_sp = AddThread(tid);
+ assert(thread_sp && "AddThread() returned a nullptr thread");
+ thread_sp->SetStoppedBySignal(SIGSTOP);
+ ThreadWasCreated(*thread_sp);
}
- LLDB_LOG(log, "adding pid = {0}", pid);
- ResolveProcessArchitecture(m_pid, m_arch);
- NativeThreadLinuxSP thread_sp = AddThread(pid);
- assert(thread_sp && "AddThread() returned a nullptr thread");
- thread_sp->SetStoppedBySignal(SIGSTOP);
- ThreadWasCreated(*thread_sp);
-
// Let our process instance know the thread has stopped.
- SetCurrentThreadID(thread_sp->GetID());
- SetState(StateType::eStateStopped);
+ SetCurrentThreadID(tids[0]);
+ SetState(StateType::eStateStopped, false);
- if (error.Fail())
- LLDB_LOG(log, "inferior launching failed {0}", error);
- return error;
+ // Proccess any signals we received before installing our handler
+ SigchldHandler();
}
-::pid_t NativeProcessLinux::Attach(lldb::pid_t pid, Status &error) {
+llvm::Expected<std::vector<::pid_t>> NativeProcessLinux::Attach(::pid_t pid) {
Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
+ Status status;
// Use a map to keep track of the threads which we have attached/need to
// attach.
Host::TidMap tids_to_attach;
- if (pid <= 1) {
- error.SetErrorToGenericError();
- error.SetErrorString("Attaching to process 1 is not allowed.");
- return -1;
- }
-
while (Host::FindProcessThreads(pid, tids_to_attach)) {
for (Host::TidMap::iterator it = tids_to_attach.begin();
it != tids_to_attach.end();) {
@@ -423,48 +338,36 @@ Status NativeProcessLinux::LaunchInferior(MainLoop &mainloop,
// Attach to the requested process.
// An attach will cause the thread to stop with a SIGSTOP.
- error = PtraceWrapper(PTRACE_ATTACH, tid);
- if (error.Fail()) {
+ if ((status = PtraceWrapper(PTRACE_ATTACH, tid)).Fail()) {
// No such thread. The thread may have exited.
// More error handling may be needed.
- if (error.GetError() == ESRCH) {
+ if (status.GetError() == ESRCH) {
it = tids_to_attach.erase(it);
continue;
- } else
- return -1;
+ }
+ return status.ToError();
}
- int status;
+ int wpid =
+ llvm::sys::RetryAfterSignal(-1, ::waitpid, tid, nullptr, __WALL);
// Need to use __WALL otherwise we receive an error with errno=ECHLD
// At this point we should have a thread stopped if waitpid succeeds.
- if ((status = waitpid(tid, NULL, __WALL)) < 0) {
+ if (wpid < 0) {
// No such thread. The thread may have exited.
// More error handling may be needed.
if (errno == ESRCH) {
it = tids_to_attach.erase(it);
continue;
- } else {
- error.SetErrorToErrno();
- return -1;
}
+ return llvm::errorCodeToError(
+ std::error_code(errno, std::generic_category()));
}
- error = SetDefaultPtraceOpts(tid);
- if (error.Fail())
- return -1;
+ if ((status = SetDefaultPtraceOpts(tid)).Fail())
+ return status.ToError();
LLDB_LOG(log, "adding tid = {0}", tid);
it->second = true;
-
- // Create the thread, mark it as stopped.
- NativeThreadLinuxSP thread_sp(AddThread(static_cast<lldb::tid_t>(tid)));
- assert(thread_sp && "AddThread() returned a nullptr");
-
- // This will notify this is a new thread and tell the system it is
- // stopped.
- thread_sp->SetStoppedBySignal(SIGSTOP);
- ThreadWasCreated(*thread_sp);
- SetCurrentThreadID(thread_sp->GetID());
}
// move the loop forward
@@ -472,17 +375,16 @@ Status NativeProcessLinux::LaunchInferior(MainLoop &mainloop,
}
}
- if (tids_to_attach.size() > 0) {
- m_pid = pid;
- // Let our process instance know the thread has stopped.
- SetState(StateType::eStateStopped);
- } else {
- error.SetErrorToGenericError();
- error.SetErrorString("No such process.");
- return -1;
- }
+ size_t tid_count = tids_to_attach.size();
+ if (tid_count == 0)
+ return llvm::make_error<StringError>("No such process",
+ llvm::inconvertibleErrorCode());
- return pid;
+ std::vector<::pid_t> tids;
+ tids.reserve(tid_count);
+ for (const auto &p : tids_to_attach)
+ tids.push_back(p.first);
+ return std::move(tids);
}
Status NativeProcessLinux::SetDefaultPtraceOpts(lldb::pid_t pid) {
@@ -662,14 +564,11 @@ void NativeProcessLinux::WaitForNewThread(::pid_t tid) {
// The thread is not tracked yet, let's wait for it to appear.
int status = -1;
- ::pid_t wait_pid;
- do {
- LLDB_LOG(log,
- "received thread creation event for tid {0}. tid not tracked "
- "yet, waiting for thread to appear...",
- tid);
- wait_pid = waitpid(tid, &status, __WALL);
- } while (wait_pid == -1 && errno == EINTR);
+ LLDB_LOG(log,
+ "received thread creation event for tid {0}. tid not tracked "
+ "yet, waiting for thread to appear...",
+ tid);
+ ::pid_t wait_pid = llvm::sys::RetryAfterSignal(-1, ::waitpid, tid, &status, __WALL);
// Since we are waiting on a specific tid, this must be the creation event.
// But let's do some checks just in case.
if (wait_pid != tid) {
@@ -897,11 +796,9 @@ void NativeProcessLinux::MonitorSIGTRAP(const siginfo_t &info,
break;
default:
- LLDB_LOG(
- log,
- "received unknown SIGTRAP stop event ({0}, pid {1} tid {2}, resuming",
- info.si_code, GetID(), thread.GetID());
- llvm_unreachable("Unexpected SIGTRAP code!");
+ LLDB_LOG(log, "received unknown SIGTRAP stop event ({0}, pid {1} tid {2}",
+ info.si_code, GetID(), thread.GetID());
+ MonitorSignal(info, thread, false);
break;
}
}
@@ -2363,15 +2260,13 @@ void NativeProcessLinux::SigchldHandler() {
// Process all pending waitpid notifications.
while (true) {
int status = -1;
- ::pid_t wait_pid = waitpid(-1, &status, __WALL | __WNOTHREAD | WNOHANG);
+ ::pid_t wait_pid = llvm::sys::RetryAfterSignal(-1, ::waitpid, -1, &status,
+ __WALL | __WNOTHREAD | WNOHANG);
if (wait_pid == 0)
break; // We are done.
if (wait_pid == -1) {
- if (errno == EINTR)
- continue;
-
Status error(errno, eErrorTypePOSIX);
LLDB_LOG(log, "waitpid (-1, &status, _) failed: {0}", error);
break;
diff --git a/source/Plugins/Process/Linux/NativeProcessLinux.h b/source/Plugins/Process/Linux/NativeProcessLinux.h
index 6bf093f6a39a..9584713d3654 100644
--- a/source/Plugins/Process/Linux/NativeProcessLinux.h
+++ b/source/Plugins/Process/Linux/NativeProcessLinux.h
@@ -39,15 +39,18 @@ namespace process_linux {
///
/// Changes in the inferior process state are broadcasted.
class NativeProcessLinux : public NativeProcessProtocol {
- friend Status NativeProcessProtocol::Launch(
- ProcessLaunchInfo &launch_info, NativeDelegate &native_delegate,
- MainLoop &mainloop, NativeProcessProtocolSP &process_sp);
+public:
+ class Factory : public NativeProcessProtocol::Factory {
+ public:
+ llvm::Expected<NativeProcessProtocolSP>
+ Launch(ProcessLaunchInfo &launch_info, NativeDelegate &native_delegate,
+ MainLoop &mainloop) const override;
- friend Status NativeProcessProtocol::Attach(
- lldb::pid_t pid, NativeProcessProtocol::NativeDelegate &native_delegate,
- MainLoop &mainloop, NativeProcessProtocolSP &process_sp);
+ llvm::Expected<NativeProcessProtocolSP>
+ Attach(lldb::pid_t pid, NativeDelegate &native_delegate,
+ MainLoop &mainloop) const override;
+ };
-public:
// ---------------------------------------------------------------------
// NativeProcessProtocol Interface
// ---------------------------------------------------------------------
@@ -144,10 +147,10 @@ private:
MainLoop::SignalHandleUP m_sigchld_handle;
ArchSpec m_arch;
- LazyBool m_supports_mem_region;
+ LazyBool m_supports_mem_region = eLazyBoolCalculate;
std::vector<std::pair<MemoryRegionInfo, FileSpec>> m_mem_region_cache;
- lldb::tid_t m_pending_notification_tid;
+ lldb::tid_t m_pending_notification_tid = LLDB_INVALID_THREAD_ID;
// List of thread ids stepping with a breakpoint with the address of
// the relevan breakpoint
@@ -156,19 +159,15 @@ private:
// ---------------------------------------------------------------------
// Private Instance Methods
// ---------------------------------------------------------------------
- NativeProcessLinux();
-
- Status LaunchInferior(MainLoop &mainloop, ProcessLaunchInfo &launch_info);
-
- /// Attaches to an existing process. Forms the
- /// implementation of Process::DoAttach
- void AttachToInferior(MainLoop &mainloop, lldb::pid_t pid, Status &error);
+ NativeProcessLinux(::pid_t pid, int terminal_fd, NativeDelegate &delegate,
+ const ArchSpec &arch, MainLoop &mainloop);
- ::pid_t Attach(lldb::pid_t pid, Status &error);
+ // Returns a list of process threads that we have attached to.
+ static llvm::Expected<std::vector<::pid_t>> Attach(::pid_t pid);
static Status SetDefaultPtraceOpts(const lldb::pid_t);
- static void *MonitorThread(void *baton);
+ void InitializeThreads(llvm::ArrayRef<::pid_t> tids);
void MonitorCallback(lldb::pid_t pid, bool exited, WaitStatus status);
@@ -280,7 +279,7 @@ private:
// same process user id.
llvm::DenseSet<lldb::tid_t> m_pt_traced_thread_group;
- lldb::user_id_t m_pt_proces_trace_id;
+ lldb::user_id_t m_pt_proces_trace_id = LLDB_INVALID_UID;
TraceOptions m_pt_process_trace_config;
};
diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp b/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
index c3b58f16256a..1a5b304ac697 100644
--- a/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
+++ b/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
@@ -680,7 +680,7 @@ Status NativeRegisterContextLinux_arm64::ClearAllHardwareWatchpoints() {
return error;
lldb::addr_t tempAddr = 0;
- uint32_t tempControl = 0, tempRefCount = 0;
+ uint32_t tempControl = 0;
for (uint32_t i = 0; i < m_max_hwp_supported; i++) {
if (m_hwp_regs[i].control & 0x01) {
@@ -858,7 +858,7 @@ Status NativeRegisterContextLinux_arm64::DoReadRegisterValue(
RegisterValue &value) {
Status error;
if (offset > sizeof(struct user_pt_regs)) {
- uintptr_t offset = offset - sizeof(struct user_pt_regs);
+ offset -= sizeof(struct user_pt_regs);
if (offset > sizeof(struct user_fpsimd_state)) {
error.SetErrorString("invalid offset value");
return error;
@@ -905,7 +905,7 @@ Status NativeRegisterContextLinux_arm64::DoWriteRegisterValue(
Status error;
::pid_t tid = m_thread.GetID();
if (offset > sizeof(struct user_pt_regs)) {
- uintptr_t offset = offset - sizeof(struct user_pt_regs);
+ offset -= sizeof(struct user_pt_regs);
if (offset > sizeof(struct user_fpsimd_state)) {
error.SetErrorString("invalid offset value");
return error;
diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp b/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp
index 59dc9e9f7d45..e44e03b46b5c 100755
--- a/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp
+++ b/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp
@@ -646,13 +646,6 @@ Status NativeRegisterContextLinux_x86_64::ReadAllRegisterValues(
Status error;
data_sp.reset(new DataBufferHeap(REG_CONTEXT_SIZE, 0));
- if (!data_sp) {
- error.SetErrorStringWithFormat(
- "failed to allocate DataBufferHeap instance of size %" PRIu64,
- REG_CONTEXT_SIZE);
- return error;
- }
-
error = ReadGPR();
if (error.Fail())
return error;
@@ -662,13 +655,6 @@ Status NativeRegisterContextLinux_x86_64::ReadAllRegisterValues(
return error;
uint8_t *dst = data_sp->GetBytes();
- if (dst == nullptr) {
- error.SetErrorStringWithFormat("DataBufferHeap instance of size %" PRIu64
- " returned a null pointer",
- REG_CONTEXT_SIZE);
- return error;
- }
-
::memcpy(dst, &m_gpr_x86_64, GetRegisterInfoInterface().GetGPRSize());
dst += GetRegisterInfoInterface().GetGPRSize();
if (m_xstate_type == XStateType::FXSAVE)
@@ -741,10 +727,9 @@ Status NativeRegisterContextLinux_x86_64::WriteAllRegisterValues(
}
if (data_sp->GetByteSize() != REG_CONTEXT_SIZE) {
- error.SetErrorStringWithFormat(
- "NativeRegisterContextLinux_x86_64::%s data_sp contained mismatched "
- "data size, expected %" PRIu64 ", actual %" PRIu64,
- __FUNCTION__, REG_CONTEXT_SIZE, data_sp->GetByteSize());
+ error.SetErrorStringWithFormatv(
+ "data_sp contained mismatched data size, expected {0}, actual {1}",
+ REG_CONTEXT_SIZE, data_sp->GetByteSize());
return error;
}
diff --git a/source/Plugins/Process/Linux/ProcessorTrace.cpp b/source/Plugins/Process/Linux/ProcessorTrace.cpp
index 7043d50256e6..505c526ab70d 100644
--- a/source/Plugins/Process/Linux/ProcessorTrace.cpp
+++ b/source/Plugins/Process/Linux/ProcessorTrace.cpp
@@ -46,13 +46,11 @@ Status ProcessorTraceMonitor::GetTraceConfig(TraceOptions &config) const {
Status ProcessorTraceMonitor::StartTrace(lldb::pid_t pid, lldb::tid_t tid,
const TraceOptions &config) {
- Status error;
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE));
- LLDB_LOG(log, "{0}", config.getThreadID());
-
#ifndef PERF_ATTR_SIZE_VER5
llvm_unreachable("perf event not supported");
#else
+ Status error;
+ Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE));
LLDB_LOG(log, "called thread id {0}", tid);
uint64_t page_size = getpagesize();
@@ -61,12 +59,11 @@ Status ProcessorTraceMonitor::StartTrace(lldb::pid_t pid, lldb::tid_t tid,
uint64_t numpages = static_cast<uint64_t>(
llvm::PowerOf2Floor((bufsize + page_size - 1) / page_size));
- numpages = std::max(1ul, numpages);
+ numpages = std::max<uint64_t>(1, numpages);
bufsize = page_size * numpages;
numpages = static_cast<uint64_t>(
llvm::PowerOf2Floor((metabufsize + page_size - 1) / page_size));
- numpages = std::max(0ul, numpages);
metabufsize = page_size * numpages;
perf_event_attr attr;
@@ -117,7 +114,7 @@ Status ProcessorTraceMonitor::StartTrace(lldb::pid_t pid, lldb::tid_t tid,
return error;
}
- m_fd = std::move(std::unique_ptr<int, file_close>(new int(fd), file_close()));
+ m_fd = std::unique_ptr<int, file_close>(new int(fd), file_close());
errno = 0;
auto base =
@@ -129,9 +126,9 @@ Status ProcessorTraceMonitor::StartTrace(lldb::pid_t pid, lldb::tid_t tid,
return error;
}
- m_mmap_meta = std::move(std::unique_ptr<perf_event_mmap_page, munmap_delete>(
+ m_mmap_meta = std::unique_ptr<perf_event_mmap_page, munmap_delete>(
reinterpret_cast<perf_event_mmap_page *>(base),
- munmap_delete(metabufsize + page_size)));
+ munmap_delete(metabufsize + page_size));
m_mmap_meta->aux_offset = m_mmap_meta->data_offset + m_mmap_meta->data_size;
m_mmap_meta->aux_size = bufsize;
@@ -145,10 +142,10 @@ Status ProcessorTraceMonitor::StartTrace(lldb::pid_t pid, lldb::tid_t tid,
error.SetErrorString("Trace buffer allocation failed");
return error;
}
- m_mmap_aux = std::move(std::unique_ptr<uint8_t, munmap_delete>(
- reinterpret_cast<uint8_t *>(mmap_aux), munmap_delete(bufsize)));
-#endif
+ m_mmap_aux = std::unique_ptr<uint8_t, munmap_delete>(
+ reinterpret_cast<uint8_t *>(mmap_aux), munmap_delete(bufsize));
return error;
+#endif
}
llvm::MutableArrayRef<uint8_t> ProcessorTraceMonitor::GetDataBuffer() {
@@ -251,14 +248,14 @@ ProcessorTraceMonitor::Create(lldb::pid_t pid, lldb::tid_t tid,
Status error;
if (tid == LLDB_INVALID_THREAD_ID) {
error.SetErrorString("thread not specified");
- return std::move(error.ToError());
+ return error.ToError();
}
ProcessorTraceMonitorUP pt_monitor_up(new ProcessorTraceMonitor);
error = pt_monitor_up->StartTrace(pid, tid, config);
if (error.Fail())
- return std::move(error.ToError());
+ return error.ToError();
pt_monitor_up->SetThreadID(tid);
@@ -274,13 +271,11 @@ ProcessorTraceMonitor::Create(lldb::pid_t pid, lldb::tid_t tid,
Status
ProcessorTraceMonitor::ReadPerfTraceAux(llvm::MutableArrayRef<uint8_t> &buffer,
size_t offset) {
-
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE));
- Status error;
-
#ifndef PERF_ATTR_SIZE_VER5
llvm_unreachable("perf event not supported");
#else
+ Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE));
+ Status error;
uint64_t head = m_mmap_meta->aux_head;
LLDB_LOG(log, "Aux size -{0} , Head - {1}", m_mmap_meta->aux_size, head);
@@ -306,12 +301,12 @@ ProcessorTraceMonitor::ReadPerfTraceAux(llvm::MutableArrayRef<uint8_t> &buffer,
Status
ProcessorTraceMonitor::ReadPerfTraceData(llvm::MutableArrayRef<uint8_t> &buffer,
size_t offset) {
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE));
- uint64_t bytes_remaining = buffer.size();
- Status error;
#ifndef PERF_ATTR_SIZE_VER5
llvm_unreachable("perf event not supported");
#else
+ Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE));
+ uint64_t bytes_remaining = buffer.size();
+ Status error;
uint64_t head = m_mmap_meta->data_head;
diff --git a/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp b/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp
index a4d775860a65..b9ef02efa65d 100644
--- a/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp
+++ b/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp
@@ -21,6 +21,7 @@
#include "lldb/Host/common/NativeRegisterContext.h"
#include "lldb/Host/posix/ProcessLauncherPosixFork.h"
#include "lldb/Target/Process.h"
+#include "llvm/Support/Errno.h"
// System includes - They have to be included after framework includes because
// they define some
@@ -63,81 +64,101 @@ static Status EnsureFDFlags(int fd, int flags) {
// Public Static Methods
// -----------------------------------------------------------------------------
-Status NativeProcessProtocol::Launch(
- ProcessLaunchInfo &launch_info,
- NativeProcessProtocol::NativeDelegate &native_delegate, MainLoop &mainloop,
- NativeProcessProtocolSP &native_process_sp) {
+llvm::Expected<NativeProcessProtocolSP>
+NativeProcessNetBSD::Factory::Launch(ProcessLaunchInfo &launch_info,
+ NativeDelegate &native_delegate,
+ MainLoop &mainloop) const {
Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
- Status error;
+ 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();
+ }
- // Verify the working directory is valid if one was specified.
- FileSpec working_dir{launch_info.GetWorkingDirectory()};
- if (working_dir && (!working_dir.ResolvePath() ||
- !llvm::sys::fs::is_directory(working_dir.GetPath()))) {
- error.SetErrorStringWithFormat("No such file or directory: %s",
- working_dir.GetCString());
- return error;
+ // 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");
- // Create the NativeProcessNetBSD in launch mode.
- native_process_sp.reset(new NativeProcessNetBSD());
+ ArchSpec arch;
+ if ((status = ResolveProcessArchitecture(pid, arch)).Fail())
+ return status.ToError();
- if (!native_process_sp->RegisterNativeDelegate(native_delegate)) {
- native_process_sp.reset();
- error.SetErrorStringWithFormat("failed to register the native delegate");
- return error;
- }
+ // Set the architecture to the exe architecture.
+ LLDB_LOG(log, "pid = {0:x}, detected architecture {1}", pid,
+ arch.GetArchitectureName());
- error = std::static_pointer_cast<NativeProcessNetBSD>(native_process_sp)
- ->LaunchInferior(mainloop, launch_info);
+ std::shared_ptr<NativeProcessNetBSD> process_sp(new NativeProcessNetBSD(
+ pid, launch_info.GetPTY().ReleaseMasterFileDescriptor(), native_delegate,
+ arch, mainloop));
- if (error.Fail()) {
- native_process_sp.reset();
- LLDB_LOG(log, "failed to launch process: {0}", error);
- return error;
- }
+ status = process_sp->ReinitializeThreads();
+ if (status.Fail())
+ return status.ToError();
- launch_info.SetProcessID(native_process_sp->GetID());
+ for (const auto &thread_sp : process_sp->m_threads) {
+ static_pointer_cast<NativeThreadNetBSD>(thread_sp)->SetStoppedBySignal(
+ SIGSTOP);
+ }
+ process_sp->SetState(StateType::eStateStopped);
- return error;
+ return process_sp;
}
-Status NativeProcessProtocol::Attach(
+llvm::Expected<NativeProcessProtocolSP> NativeProcessNetBSD::Factory::Attach(
lldb::pid_t pid, NativeProcessProtocol::NativeDelegate &native_delegate,
- MainLoop &mainloop, NativeProcessProtocolSP &native_process_sp) {
+ MainLoop &mainloop) const {
Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
LLDB_LOG(log, "pid = {0:x}", pid);
// Retrieve the architecture for the running process.
- ArchSpec process_arch;
- Status error = ResolveProcessArchitecture(pid, process_arch);
- if (!error.Success())
- return error;
+ ArchSpec arch;
+ Status status = ResolveProcessArchitecture(pid, arch);
+ if (!status.Success())
+ return status.ToError();
- std::shared_ptr<NativeProcessNetBSD> native_process_netbsd_sp(
- new NativeProcessNetBSD());
+ std::shared_ptr<NativeProcessNetBSD> process_sp(
+ new NativeProcessNetBSD(pid, -1, native_delegate, arch, mainloop));
- if (!native_process_netbsd_sp->RegisterNativeDelegate(native_delegate)) {
- error.SetErrorStringWithFormat("failed to register the native delegate");
- return error;
- }
-
- native_process_netbsd_sp->AttachToInferior(mainloop, pid, error);
- if (!error.Success())
- return error;
+ status = process_sp->Attach();
+ if (!status.Success())
+ return status.ToError();
- native_process_sp = native_process_netbsd_sp;
- return error;
+ return process_sp;
}
// -----------------------------------------------------------------------------
// Public Instance Methods
// -----------------------------------------------------------------------------
-NativeProcessNetBSD::NativeProcessNetBSD()
- : NativeProcessProtocol(LLDB_INVALID_PROCESS_ID), m_arch(),
- m_supports_mem_region(eLazyBoolCalculate), m_mem_region_cache() {}
+NativeProcessNetBSD::NativeProcessNetBSD(::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 NativeProcessNetBSD::MonitorCallback(lldb::pid_t pid, int signal) {
@@ -709,126 +730,17 @@ Status NativeProcessNetBSD::GetFileLoadAddress(const llvm::StringRef &file_name,
return Status();
}
-Status NativeProcessNetBSD::LaunchInferior(MainLoop &mainloop,
- ProcessLaunchInfo &launch_info) {
- Status error;
- m_sigchld_handle = mainloop.RegisterSignal(
- SIGCHLD, [this](MainLoopBase &) { SigchldHandler(); }, error);
- if (!m_sigchld_handle)
- return error;
-
- SetState(eStateLaunching);
-
- ::pid_t pid = ProcessLauncherPosixFork()
- .LaunchProcess(launch_info, error)
- .GetProcessId();
- if (error.Fail())
- return error;
-
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
-
- // Wait for the child process to trap on its call to execve.
- ::pid_t wpid;
- int status;
- if ((wpid = waitpid(pid, &status, 0)) < 0) {
- error.SetErrorToErrno();
- LLDB_LOG(log, "waitpid for inferior failed with %s", error);
-
- // Mark the inferior as invalid.
- // FIXME this could really use a new state - eStateLaunchFailure. For
- // now, using eStateInvalid.
- SetState(StateType::eStateInvalid);
-
- return error;
- }
- assert(WIFSTOPPED(status) && (wpid == static_cast<::pid_t>(pid)) &&
- "Could not sync with inferior process.");
-
- LLDB_LOG(log, "inferior started, now in stopped state");
-
- // Release the master terminal descriptor and pass it off to the
- // NativeProcessNetBSD instance. Similarly stash the inferior pid.
- m_terminal_fd = launch_info.GetPTY().ReleaseMasterFileDescriptor();
- m_pid = pid;
- launch_info.SetProcessID(pid);
-
- if (m_terminal_fd != -1) {
- error = EnsureFDFlags(m_terminal_fd, O_NONBLOCK);
- if (error.Fail()) {
- LLDB_LOG(log,
- "inferior EnsureFDFlags failed for ensuring terminal "
- "O_NONBLOCK setting: {0}",
- error);
-
- // Mark the inferior as invalid.
- // FIXME this could really use a new state - eStateLaunchFailure. For
- // now, using eStateInvalid.
- SetState(StateType::eStateInvalid);
-
- return error;
- }
- }
-
- LLDB_LOG(log, "adding pid = {0}", pid);
-
- ResolveProcessArchitecture(m_pid, m_arch);
-
- error = ReinitializeThreads();
- if (error.Fail()) {
- SetState(StateType::eStateInvalid);
- return error;
- }
-
- for (const auto &thread_sp : m_threads) {
- static_pointer_cast<NativeThreadNetBSD>(thread_sp)->SetStoppedBySignal(
- SIGSTOP);
- }
-
- /* Set process stopped */
- SetState(StateType::eStateStopped);
-
- if (error.Fail())
- LLDB_LOG(log, "inferior launching failed {0}", error);
- return error;
-}
-
-void NativeProcessNetBSD::AttachToInferior(MainLoop &mainloop, lldb::pid_t pid,
- Status &error) {
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
- LLDB_LOG(log, "pid = {0:x}", pid);
-
- m_sigchld_handle = mainloop.RegisterSignal(
- SIGCHLD, [this](MainLoopBase &) { SigchldHandler(); }, error);
- if (!m_sigchld_handle)
- return;
-
- error = ResolveProcessArchitecture(pid, m_arch);
- if (!error.Success())
- return;
-
- // Set the architecture to the exe architecture.
- LLDB_LOG(log, "pid = {0:x}, detected architecture {1}", pid,
- m_arch.GetArchitectureName());
-
- m_pid = pid;
- SetState(eStateAttaching);
-
- Attach(pid, error);
-}
-
void NativeProcessNetBSD::SigchldHandler() {
Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
// Process all pending waitpid notifications.
int status;
- ::pid_t wait_pid = waitpid(GetID(), &status, WALLSIG | WNOHANG);
+ ::pid_t wait_pid =
+ llvm::sys::RetryAfterSignal(-1, waitpid, GetID(), &status, WALLSIG | WNOHANG);
if (wait_pid == 0)
return; // We are done.
if (wait_pid == -1) {
- if (errno == EINTR)
- return;
-
Status error(errno, eErrorTypePOSIX);
LLDB_LOG(log, "waitpid ({0}, &status, _) failed: {1}", GetID(), error);
}
@@ -880,33 +792,23 @@ NativeThreadNetBSDSP NativeProcessNetBSD::AddThread(lldb::tid_t thread_id) {
return thread_sp;
}
-::pid_t NativeProcessNetBSD::Attach(lldb::pid_t pid, Status &error) {
- if (pid <= 1) {
- error.SetErrorToGenericError();
- error.SetErrorString("Attaching to process 1 is not allowed.");
- return -1;
- }
-
+Status NativeProcessNetBSD::Attach() {
// Attach to the requested process.
// An attach will cause the thread to stop with a SIGSTOP.
- error = PtraceWrapper(PT_ATTACH, pid);
- if (error.Fail())
- return -1;
+ Status status = PtraceWrapper(PT_ATTACH, m_pid);
+ if (status.Fail())
+ return status;
- int status;
+ int wstatus;
// Need to use WALLSIG otherwise we receive an error with errno=ECHLD
// At this point we should have a thread stopped if waitpid succeeds.
- if ((status = waitpid(pid, NULL, WALLSIG)) < 0)
- return -1;
-
- m_pid = pid;
+ if ((wstatus = waitpid(m_pid, NULL, WALLSIG)) < 0)
+ return Status(errno, eErrorTypePOSIX);
/* Initialize threads */
- error = ReinitializeThreads();
- if (error.Fail()) {
- SetState(StateType::eStateInvalid);
- return -1;
- }
+ status = ReinitializeThreads();
+ if (status.Fail())
+ return status;
for (const auto &thread_sp : m_threads) {
static_pointer_cast<NativeThreadNetBSD>(thread_sp)->SetStoppedBySignal(
@@ -915,8 +817,7 @@ NativeThreadNetBSDSP NativeProcessNetBSD::AddThread(lldb::tid_t thread_id) {
// Let our process instance know the thread has stopped.
SetState(StateType::eStateStopped);
-
- return pid;
+ return Status();
}
Status NativeProcessNetBSD::ReadMemory(lldb::addr_t addr, void *buf,
diff --git a/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h b/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h
index 7a1303faea68..34b892f1fc88 100644
--- a/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h
+++ b/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h
@@ -31,15 +31,18 @@ namespace process_netbsd {
///
/// Changes in the inferior process state are broadcasted.
class NativeProcessNetBSD : public NativeProcessProtocol {
- friend Status NativeProcessProtocol::Launch(
- ProcessLaunchInfo &launch_info, NativeDelegate &native_delegate,
- MainLoop &mainloop, NativeProcessProtocolSP &process_sp);
+public:
+ class Factory : public NativeProcessProtocol::Factory {
+ public:
+ llvm::Expected<NativeProcessProtocolSP>
+ Launch(ProcessLaunchInfo &launch_info, NativeDelegate &native_delegate,
+ MainLoop &mainloop) const override;
- friend Status NativeProcessProtocol::Attach(
- lldb::pid_t pid, NativeProcessProtocol::NativeDelegate &native_delegate,
- MainLoop &mainloop, NativeProcessProtocolSP &process_sp);
+ llvm::Expected<NativeProcessProtocolSP>
+ Attach(lldb::pid_t pid, NativeDelegate &native_delegate,
+ MainLoop &mainloop) const override;
+ };
-public:
// ---------------------------------------------------------------------
// NativeProcessProtocol Interface
// ---------------------------------------------------------------------
@@ -107,21 +110,19 @@ protected:
private:
MainLoop::SignalHandleUP m_sigchld_handle;
ArchSpec m_arch;
- LazyBool m_supports_mem_region;
+ LazyBool m_supports_mem_region = eLazyBoolCalculate;
std::vector<std::pair<MemoryRegionInfo, FileSpec>> m_mem_region_cache;
// ---------------------------------------------------------------------
// Private Instance Methods
// ---------------------------------------------------------------------
- NativeProcessNetBSD();
+ NativeProcessNetBSD(::pid_t pid, int terminal_fd, NativeDelegate &delegate,
+ const ArchSpec &arch, MainLoop &mainloop);
bool HasThreadNoLock(lldb::tid_t thread_id);
NativeThreadNetBSDSP AddThread(lldb::tid_t thread_id);
- Status LaunchInferior(MainLoop &mainloop, ProcessLaunchInfo &launch_info);
- void AttachToInferior(MainLoop &mainloop, lldb::pid_t pid, Status &error);
-
void MonitorCallback(lldb::pid_t pid, int signal);
void MonitorExited(lldb::pid_t pid, WaitStatus status);
void MonitorSIGSTOP(lldb::pid_t pid);
@@ -133,8 +134,7 @@ private:
Status PopulateMemoryRegionCache();
void SigchldHandler();
- ::pid_t Attach(lldb::pid_t pid, Status &error);
-
+ Status Attach();
Status ReinitializeThreads();
};
diff --git a/source/Plugins/Process/gdb-remote/CMakeLists.txt b/source/Plugins/Process/gdb-remote/CMakeLists.txt
index 3d008f42499d..5e51feef1d3f 100644
--- a/source/Plugins/Process/gdb-remote/CMakeLists.txt
+++ b/source/Plugins/Process/gdb-remote/CMakeLists.txt
@@ -7,14 +7,6 @@ set(LLDB_PLUGINS
lldbPluginPlatformMacOSX
)
-if(CMAKE_SYSTEM_NAME MATCHES "Linux|Android")
- list(APPEND LLDB_PLUGINS lldbPluginProcessLinux)
-endif()
-
-if(CMAKE_SYSTEM_NAME MATCHES "NetBSD")
- list(APPEND LLDB_PLUGINS lldbPluginProcessNetBSD)
-endif()
-
add_lldb_library(lldbPluginProcessGDBRemote PLUGIN
GDBRemoteClientBase.cpp
GDBRemoteCommunication.cpp
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
index 33aed7a43c4a..e6fd386b903b 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
@@ -86,6 +86,7 @@ GDBRemoteCommunicationClient::GDBRemoteCommunicationClient()
m_supports_jLoadedDynamicLibrariesInfos(eLazyBoolCalculate),
m_supports_jGetSharedCacheInfo(eLazyBoolCalculate),
m_supports_QPassSignals(eLazyBoolCalculate),
+ m_supports_error_string_reply(eLazyBoolCalculate),
m_supports_qProcessInfoPID(true), m_supports_qfProcessInfo(true),
m_supports_qUserName(true), m_supports_qGroupName(true),
m_supports_qThreadStopInfo(true), m_supports_z0(true),
@@ -596,6 +597,21 @@ bool GDBRemoteCommunicationClient::GetThreadExtendedInfoSupported() {
return m_supports_jThreadExtendedInfo;
}
+void GDBRemoteCommunicationClient::EnableErrorStringInPacket() {
+ if (m_supports_error_string_reply == eLazyBoolCalculate) {
+ StringExtractorGDBRemote response;
+ // We try to enable error strings in remote packets
+ // but if we fail, we just work in the older way.
+ m_supports_error_string_reply = eLazyBoolNo;
+ if (SendPacketAndWaitForResponse("QEnableErrorStrings", response, false) ==
+ PacketResult::Success) {
+ if (response.IsOKResponse()) {
+ m_supports_error_string_reply = eLazyBoolYes;
+ }
+ }
+ }
+}
+
bool GDBRemoteCommunicationClient::GetLoadedDynamicLibrariesInfosSupported() {
if (m_supports_jLoadedDynamicLibrariesInfos == eLazyBoolCalculate) {
StringExtractorGDBRemote response;
@@ -3181,8 +3197,8 @@ GDBRemoteCommunicationClient::SendStartTracePacket(const TraceOptions &options,
true) ==
GDBRemoteCommunication::PacketResult::Success) {
if (!response.IsNormalResponse()) {
- error.SetError(response.GetError(), eErrorTypeGeneric);
- LLDB_LOG(log, "Target does not support Tracing");
+ error = response.GetStatus();
+ LLDB_LOG(log, "Target does not support Tracing , error {0}", error);
} else {
ret_uid = response.GetHexMaxU64(false, LLDB_INVALID_UID);
}
@@ -3219,7 +3235,7 @@ GDBRemoteCommunicationClient::SendStopTracePacket(lldb::user_id_t uid,
true) ==
GDBRemoteCommunication::PacketResult::Success) {
if (!response.IsOKResponse()) {
- error.SetError(response.GetError(), eErrorTypeGeneric);
+ error = response.GetStatus();
LLDB_LOG(log, "stop tracing failed");
}
} else {
@@ -3234,6 +3250,7 @@ GDBRemoteCommunicationClient::SendStopTracePacket(lldb::user_id_t uid,
Status GDBRemoteCommunicationClient::SendGetDataPacket(
lldb::user_id_t uid, lldb::tid_t thread_id,
llvm::MutableArrayRef<uint8_t> &buffer, size_t offset) {
+
StreamGDBRemote escaped_packet;
escaped_packet.PutCString("jTraceBufferRead:");
return SendGetTraceDataPacket(escaped_packet, uid, thread_id, buffer, offset);
@@ -3242,6 +3259,7 @@ Status GDBRemoteCommunicationClient::SendGetDataPacket(
Status GDBRemoteCommunicationClient::SendGetMetaDataPacket(
lldb::user_id_t uid, lldb::tid_t thread_id,
llvm::MutableArrayRef<uint8_t> &buffer, size_t offset) {
+
StreamGDBRemote escaped_packet;
escaped_packet.PutCString("jTraceMetaRead:");
return SendGetTraceDataPacket(escaped_packet, uid, thread_id, buffer, offset);
@@ -3308,7 +3326,7 @@ GDBRemoteCommunicationClient::SendGetTraceConfigPacket(lldb::user_id_t uid,
custom_params_sp));
}
} else {
- error.SetError(response.GetError(), eErrorTypeGeneric);
+ error = response.GetStatus();
}
} else {
LLDB_LOG(log, "failed to send packet");
@@ -3344,7 +3362,7 @@ Status GDBRemoteCommunicationClient::SendGetTraceDataPacket(
size_t filled_size = response.GetHexBytesAvail(buffer);
buffer = llvm::MutableArrayRef<uint8_t>(buffer.data(), filled_size);
} else {
- error.SetError(response.GetError(), eErrorTypeGeneric);
+ error = response.GetStatus();
buffer = buffer.slice(buffer.size());
}
} else {
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
index a38110faaec6..712d85eed082 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
@@ -340,6 +340,8 @@ public:
bool GetQXferAuxvReadSupported();
+ void EnableErrorStringInPacket();
+
bool GetQXferLibrariesReadSupported();
bool GetQXferLibrariesSVR4ReadSupported();
@@ -549,6 +551,7 @@ protected:
LazyBool m_supports_jLoadedDynamicLibrariesInfos;
LazyBool m_supports_jGetSharedCacheInfo;
LazyBool m_supports_QPassSignals;
+ LazyBool m_supports_error_string_reply;
bool m_supports_qProcessInfoPID : 1, m_supports_qfProcessInfo : 1,
m_supports_qUserName : 1, m_supports_qGroupName : 1,
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
index dac675ee9432..4be92b79fd1a 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
@@ -20,6 +20,7 @@
// Project includes
#include "ProcessGDBRemoteLog.h"
#include "Utility/StringExtractorGDBRemote.h"
+#include "lldb/Utility/StreamString.h"
using namespace lldb;
using namespace lldb_private;
@@ -27,7 +28,12 @@ using namespace lldb_private::process_gdb_remote;
GDBRemoteCommunicationServer::GDBRemoteCommunicationServer(
const char *comm_name, const char *listener_name)
- : GDBRemoteCommunication(comm_name, listener_name), m_exit_now(false) {}
+ : GDBRemoteCommunication(comm_name, listener_name), m_exit_now(false) {
+ RegisterPacketHandler(
+ StringExtractorGDBRemote::eServerPacketType_QEnableErrorStrings,
+ [this](StringExtractorGDBRemote packet, Status &error, bool &interrupt,
+ bool &quit) { return this->Handle_QErrorStringEnable(packet); });
+}
GDBRemoteCommunicationServer::~GDBRemoteCommunicationServer() {}
@@ -100,6 +106,24 @@ GDBRemoteCommunicationServer::SendErrorResponse(uint8_t err) {
}
GDBRemoteCommunication::PacketResult
+GDBRemoteCommunicationServer::SendErrorResponse(const Status &error) {
+ if (m_send_error_strings) {
+ lldb_private::StreamString packet;
+ packet.Printf("E%2.2x;", static_cast<uint8_t>(error.GetError()));
+ packet.PutCStringAsRawHex8(error.AsCString());
+ return SendPacketNoLock(packet.GetString());
+ } else
+ return SendErrorResponse(error.GetError());
+}
+
+GDBRemoteCommunication::PacketResult
+GDBRemoteCommunicationServer::Handle_QErrorStringEnable(
+ StringExtractorGDBRemote &packet) {
+ m_send_error_strings = true;
+ return SendOKResponse();
+}
+
+GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServer::SendIllFormedResponse(
const StringExtractorGDBRemote &failed_packet, const char *message) {
Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PACKETS));
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h
index 6eb25f8b9f98..a35352480040 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h
@@ -57,6 +57,13 @@ protected:
bool m_exit_now; // use in asynchronous handling to indicate process should
// exit.
+ bool m_send_error_strings; // If the client enables this then
+ // we will send error strings as well.
+
+ PacketResult Handle_QErrorStringEnable(StringExtractorGDBRemote &packet);
+
+ PacketResult SendErrorResponse(const Status &error);
+
PacketResult SendUnimplementedResponse(const char *packet);
PacketResult SendErrorResponse(uint8_t error);
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp
index de2400c51ba3..f53db502be93 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp
@@ -1046,14 +1046,9 @@ GDBRemoteCommunicationServerCommon::Handle_A(StringExtractorGDBRemote &packet) {
if (success) {
m_process_launch_error = LaunchProcess();
- if (m_process_launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID) {
+ if (m_process_launch_error.Success())
return SendOKResponse();
- } else {
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
- if (log)
- log->Printf("LLGSPacketHandler::%s failed to launch exe: %s",
- __FUNCTION__, m_process_launch_error.AsCString());
- }
+ LLDB_LOG(log, "failed to launch exe: {0}", m_process_launch_error);
}
return SendErrorResponse(8);
}
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
index 7523260c13e4..a7fe4ee3b147 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
@@ -73,15 +73,11 @@ enum GDBRemoteServerError {
// GDBRemoteCommunicationServerLLGS constructor
//----------------------------------------------------------------------
GDBRemoteCommunicationServerLLGS::GDBRemoteCommunicationServerLLGS(
- MainLoop &mainloop)
+ MainLoop &mainloop, const NativeProcessProtocol::Factory &process_factory)
: GDBRemoteCommunicationServerCommon("gdb-remote.server",
"gdb-remote.server.rx_packet"),
- m_mainloop(mainloop), m_current_tid(LLDB_INVALID_THREAD_ID),
- m_continue_tid(LLDB_INVALID_THREAD_ID), m_debugged_process_mutex(),
- m_debugged_process_sp(), m_stdio_communication("process.stdio"),
- m_inferior_prev_state(StateType::eStateInvalid),
- m_saved_registers_map(), m_next_saved_registers_id(1),
- m_handshake_completed(false) {
+ m_mainloop(mainloop), m_process_factory(process_factory),
+ m_stdio_communication("process.stdio") {
RegisterPacketHandlers();
}
@@ -241,19 +237,20 @@ Status GDBRemoteCommunicationServerLLGS::LaunchProcess() {
const bool default_to_use_pty = true;
m_process_launch_info.FinalizeFileActions(nullptr, default_to_use_pty);
- Status error;
{
std::lock_guard<std::recursive_mutex> guard(m_debugged_process_mutex);
assert(!m_debugged_process_sp && "lldb-server creating debugged "
"process but one already exists");
- error = NativeProcessProtocol::Launch(m_process_launch_info, *this,
- m_mainloop, m_debugged_process_sp);
- }
-
- if (!error.Success()) {
- fprintf(stderr, "%s: failed to launch executable %s", __FUNCTION__,
- m_process_launch_info.GetArguments().GetArgumentAtIndex(0));
- return error;
+ 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;
+ }
+ m_debugged_process_sp = *process_or;
}
// Handle mirroring of inferior stdout/stderr over the gdb-remote protocol
@@ -279,9 +276,9 @@ Status GDBRemoteCommunicationServerLLGS::LaunchProcess() {
log->Printf("ProcessGDBRemoteCommunicationServerLLGS::%s setting "
"inferior STDIO fd to %d",
__FUNCTION__, terminal_fd);
- error = SetSTDIOFileDescriptor(terminal_fd);
- if (error.Fail())
- return error;
+ Status status = SetSTDIOFileDescriptor(terminal_fd);
+ if (status.Fail())
+ return status;
} else {
if (log)
log->Printf("ProcessGDBRemoteCommunicationServerLLGS::%s ignoring "
@@ -298,14 +295,12 @@ Status GDBRemoteCommunicationServerLLGS::LaunchProcess() {
printf("Launched '%s' as process %" PRIu64 "...\n",
m_process_launch_info.GetArguments().GetArgumentAtIndex(0),
- m_process_launch_info.GetProcessID());
+ m_debugged_process_sp->GetID());
- return error;
+ return Status();
}
Status GDBRemoteCommunicationServerLLGS::AttachToProcess(lldb::pid_t pid) {
- Status error;
-
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
if (log)
log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64,
@@ -321,13 +316,14 @@ Status GDBRemoteCommunicationServerLLGS::AttachToProcess(lldb::pid_t pid) {
pid, m_debugged_process_sp->GetID());
// Try to attach.
- error = NativeProcessProtocol::Attach(pid, *this, m_mainloop,
- m_debugged_process_sp);
- if (!error.Success()) {
- fprintf(stderr, "%s: failed to attach to process %" PRIu64 ": %s",
- __FUNCTION__, pid, error.AsCString());
- return error;
+ auto process_or = m_process_factory.Attach(pid, *this, m_mainloop);
+ if (!process_or) {
+ Status status(process_or.takeError());
+ llvm::errs() << llvm::formatv("failed to attach to process {0}: {1}", pid,
+ status);
+ return status;
}
+ m_debugged_process_sp = *process_or;
// Setup stdout/stderr mapping from inferior.
auto terminal_fd = m_debugged_process_sp->GetTerminalFileDescriptor();
@@ -336,9 +332,9 @@ Status GDBRemoteCommunicationServerLLGS::AttachToProcess(lldb::pid_t pid) {
log->Printf("ProcessGDBRemoteCommunicationServerLLGS::%s setting "
"inferior STDIO fd to %d",
__FUNCTION__, terminal_fd);
- error = SetSTDIOFileDescriptor(terminal_fd);
- if (error.Fail())
- return error;
+ Status status = SetSTDIOFileDescriptor(terminal_fd);
+ if (status.Fail())
+ return status;
} else {
if (log)
log->Printf("ProcessGDBRemoteCommunicationServerLLGS::%s ignoring "
@@ -347,8 +343,7 @@ Status GDBRemoteCommunicationServerLLGS::AttachToProcess(lldb::pid_t pid) {
}
printf("Attached to process %" PRIu64 "...\n", pid);
-
- return error;
+ return Status();
}
void GDBRemoteCommunicationServerLLGS::InitializeDelegate(
@@ -1128,7 +1123,7 @@ GDBRemoteCommunicationServerLLGS::Handle_jTraceStart(
uid = m_debugged_process_sp->StartTrace(options, error);
LLDB_LOG(log, "uid is {0} , error is {1}", uid, error.GetError());
if (error.Fail())
- return SendErrorResponse(error.GetError());
+ return SendErrorResponse(error);
StreamGDBRemote response;
response.Printf("%" PRIx64, uid);
@@ -1165,7 +1160,7 @@ GDBRemoteCommunicationServerLLGS::Handle_jTraceStop(
Status error = m_debugged_process_sp->StopTrace(uid, tid);
if (error.Fail())
- return SendErrorResponse(error.GetError());
+ return SendErrorResponse(error);
return SendOKResponse();
}
@@ -1208,7 +1203,7 @@ GDBRemoteCommunicationServerLLGS::Handle_jTraceConfigRead(
Status error = m_debugged_process_sp->GetTraceConfig(uid, options);
if (error.Fail())
- return SendErrorResponse(error.GetError());
+ return SendErrorResponse(error);
StreamGDBRemote escaped_response;
StructuredData::Dictionary json_packet;
@@ -1284,7 +1279,7 @@ GDBRemoteCommunicationServerLLGS::Handle_jTraceRead(
error = m_debugged_process_sp->GetMetaData(uid, tid, buf, offset);
if (error.Fail())
- return SendErrorResponse(error.GetError());
+ return SendErrorResponse(error);
for (auto i : buf)
response.PutHex8(i);
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h
index a7d7850d454f..b065642d4aed 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h
@@ -39,7 +39,9 @@ public:
//------------------------------------------------------------------
// Constructors and Destructors
//------------------------------------------------------------------
- GDBRemoteCommunicationServerLLGS(MainLoop &mainloop);
+ GDBRemoteCommunicationServerLLGS(
+ MainLoop &mainloop,
+ const NativeProcessProtocol::Factory &process_factory);
//------------------------------------------------------------------
/// Specify the program to launch and its arguments.
@@ -108,20 +110,21 @@ public:
protected:
MainLoop &m_mainloop;
MainLoop::ReadHandleUP m_network_handle_up;
- lldb::tid_t m_current_tid;
- lldb::tid_t m_continue_tid;
+ const NativeProcessProtocol::Factory &m_process_factory;
+ lldb::tid_t m_current_tid = LLDB_INVALID_THREAD_ID;
+ lldb::tid_t m_continue_tid = LLDB_INVALID_THREAD_ID;
std::recursive_mutex m_debugged_process_mutex;
NativeProcessProtocolSP m_debugged_process_sp;
Communication m_stdio_communication;
MainLoop::ReadHandleUP m_stdio_handle_up;
- lldb::StateType m_inferior_prev_state;
+ lldb::StateType m_inferior_prev_state = lldb::StateType::eStateInvalid;
std::unique_ptr<llvm::MemoryBuffer> m_active_auxv_buffer_up;
std::mutex m_saved_registers_mutex;
std::unordered_map<uint32_t, lldb::DataBufferSP> m_saved_registers_map;
- uint32_t m_next_saved_registers_id;
- bool m_handshake_completed : 1;
+ uint32_t m_next_saved_registers_id = 1;
+ bool m_handshake_completed = false;
PacketResult SendONotification(const char *buffer, uint32_t len);
diff --git a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
index 042c96111bb3..8a66f3865ebc 100644
--- a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -1031,6 +1031,7 @@ Status ProcessGDBRemote::ConnectToDebugserver(llvm::StringRef connect_url) {
m_gdb_comm.GetHostInfo();
m_gdb_comm.GetVContSupported('c');
m_gdb_comm.GetVAttachOrWaitSupported();
+ m_gdb_comm.EnableErrorStringInPacket();
// Ask the remote server for the default thread id
if (GetTarget().GetNonStopModeEnabled())
diff --git a/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp b/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
index b7fbd7347d08..6c39690268c6 100644
--- a/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
+++ b/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
@@ -1857,14 +1857,12 @@ StructuredData::DictionarySP ScriptInterpreterPython::GetDynamicSettings(
return StructuredData::DictionarySP();
PythonObject reply_pyobj;
- {
- Locker py_lock(this,
- Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
- TargetSP target_sp(target->shared_from_this());
- reply_pyobj.Reset(PyRefType::Owned,
- (PyObject *)g_swig_plugin_get(generic->GetValue(),
- setting_name, target_sp));
- }
+ Locker py_lock(this,
+ Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
+ TargetSP target_sp(target->shared_from_this());
+ reply_pyobj.Reset(PyRefType::Owned,
+ (PyObject *)g_swig_plugin_get(generic->GetValue(),
+ setting_name, target_sp));
PythonDictionary py_dict(PyRefType::Borrowed, reply_pyobj.get());
return py_dict.CreateStructuredDictionary();
diff --git a/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp b/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp
index 9d79a411faad..aa15063ac0dc 100644
--- a/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp
+++ b/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp
@@ -604,9 +604,10 @@ uint32_t x86AssemblyInspectionEngine::extract_4(uint8_t *b) {
}
bool x86AssemblyInspectionEngine::instruction_length(uint8_t *insn_p,
- int &length) {
+ int &length,
+ uint32_t buffer_remaining_bytes) {
- const uint32_t max_op_byte_size = m_arch.GetMaximumOpcodeByteSize();
+ uint32_t max_op_byte_size = std::min(buffer_remaining_bytes, m_arch.GetMaximumOpcodeByteSize());
llvm::SmallVector<uint8_t, 32> opcode_data;
opcode_data.resize(max_op_byte_size);
@@ -698,8 +699,9 @@ bool x86AssemblyInspectionEngine::GetNonCallSiteUnwindPlanFromAssembly(
bool row_updated = false; // The UnwindPlan::Row 'row' has been updated
m_cur_insn = data + current_func_text_offset;
- if (!instruction_length(m_cur_insn, insn_len) || insn_len == 0 ||
- insn_len > kMaxInstructionByteSize) {
+ if (!instruction_length(m_cur_insn, insn_len, size - current_func_text_offset)
+ || insn_len == 0
+ || insn_len > kMaxInstructionByteSize) {
// An unrecognized/junk instruction
break;
}
@@ -1002,8 +1004,9 @@ bool x86AssemblyInspectionEngine::AugmentUnwindPlanFromCallSite(
while (offset < size) {
m_cur_insn = data + offset;
int insn_len;
- if (!instruction_length(m_cur_insn, insn_len) || insn_len == 0 ||
- insn_len > kMaxInstructionByteSize) {
+ if (!instruction_length(m_cur_insn, insn_len, size - offset)
+ || insn_len == 0
+ || insn_len > kMaxInstructionByteSize) {
// An unrecognized/junk instruction.
break;
}
@@ -1214,8 +1217,9 @@ bool x86AssemblyInspectionEngine::FindFirstNonPrologueInstruction(
int scratch;
m_cur_insn = data + offset;
- if (!instruction_length(m_cur_insn, insn_len) ||
- insn_len > kMaxInstructionByteSize || insn_len == 0) {
+ if (!instruction_length(m_cur_insn, insn_len, size - offset)
+ || insn_len > kMaxInstructionByteSize
+ || insn_len == 0) {
// An error parsing the instruction, i.e. probably data/garbage - stop
// scanning
break;
diff --git a/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.h b/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.h
index 2e7875966cb6..97441d362973 100644
--- a/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.h
+++ b/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.h
@@ -113,7 +113,7 @@ private:
bool ret_pattern_p();
uint32_t extract_4(uint8_t *b);
- bool instruction_length(uint8_t *insn, int &length);
+ bool instruction_length(uint8_t *insn, int &length, uint32_t buffer_remaining_bytes);
bool machine_regno_to_lldb_regno(int machine_regno, uint32_t &lldb_regno);
diff --git a/source/Utility/StringExtractorGDBRemote.cpp b/source/Utility/StringExtractorGDBRemote.cpp
index 3473a9e96689..8e50c0106a48 100644
--- a/source/Utility/StringExtractorGDBRemote.cpp
+++ b/source/Utility/StringExtractorGDBRemote.cpp
@@ -19,8 +19,18 @@ StringExtractorGDBRemote::GetResponseType() const {
switch (m_packet[0]) {
case 'E':
- if (m_packet.size() == 3 && isxdigit(m_packet[1]) && isxdigit(m_packet[2]))
- return eError;
+ if (isxdigit(m_packet[1]) && isxdigit(m_packet[2])) {
+ if (m_packet.size() == 3)
+ return eError;
+ llvm::StringRef packet_ref(m_packet);
+ if (packet_ref[3] == ';') {
+ auto err_string = packet_ref.substr(4);
+ for (auto e : err_string)
+ if (!isxdigit(e))
+ return eResponse;
+ return eError;
+ }
+ }
break;
case 'O':
@@ -86,6 +96,8 @@ StringExtractorGDBRemote::GetServerPacketType() const {
return eServerPacketType_QEnvironment;
if (PACKET_STARTS_WITH("QEnvironmentHexEncoded:"))
return eServerPacketType_QEnvironmentHexEncoded;
+ if (PACKET_STARTS_WITH("QEnableErrorStrings"))
+ return eServerPacketType_QEnableErrorStrings;
break;
case 'P':
@@ -438,8 +450,8 @@ bool StringExtractorGDBRemote::IsNormalResponse() const {
}
bool StringExtractorGDBRemote::IsErrorResponse() const {
- return GetResponseType() == eError && m_packet.size() == 3 &&
- isxdigit(m_packet[1]) && isxdigit(m_packet[2]);
+ return GetResponseType() == eError && isxdigit(m_packet[1]) &&
+ isxdigit(m_packet[2]);
}
uint8_t StringExtractorGDBRemote::GetError() {
@@ -450,6 +462,23 @@ uint8_t StringExtractorGDBRemote::GetError() {
return 0;
}
+lldb_private::Status StringExtractorGDBRemote::GetStatus() {
+ lldb_private::Status error;
+ if (GetResponseType() == eError) {
+ SetFilePos(1);
+ uint8_t errc = GetHexU8(255);
+ error.SetError(errc, lldb::eErrorTypeGeneric);
+
+ error.SetErrorStringWithFormat("Error %u", errc);
+ std::string error_messg;
+ if (GetChar() == ';') {
+ GetHexByteString(error_messg);
+ error.SetErrorString(error_messg);
+ }
+ }
+ return error;
+}
+
size_t StringExtractorGDBRemote::GetEscapedBinaryData(std::string &str) {
// Just get the data bytes in the string as
// GDBRemoteCommunication::CheckForPacket()
diff --git a/source/Utility/StringExtractorGDBRemote.h b/source/Utility/StringExtractorGDBRemote.h
index 473cab04f800..f4ed642a706e 100644
--- a/source/Utility/StringExtractorGDBRemote.h
+++ b/source/Utility/StringExtractorGDBRemote.h
@@ -10,6 +10,7 @@
#ifndef utility_StringExtractorGDBRemote_h_
#define utility_StringExtractorGDBRemote_h_
+#include "lldb/Utility/Status.h"
#include "lldb/Utility/StringExtractor.h"
#include "llvm/ADT/StringRef.h" // for StringRef
@@ -72,6 +73,7 @@ public:
eServerPacketType_qGetWorkingDir,
eServerPacketType_qFileLoadAddress,
eServerPacketType_QEnvironment,
+ eServerPacketType_QEnableErrorStrings,
eServerPacketType_QLaunchArch,
eServerPacketType_QSetDisableASLR,
eServerPacketType_QSetDetachOnError,
@@ -190,6 +192,8 @@ public:
// digits. Otherwise the error encoded in XX is returned.
uint8_t GetError();
+ lldb_private::Status GetStatus();
+
size_t GetEscapedBinaryData(std::string &str);
protected:
diff --git a/tools/lldb-server/CMakeLists.txt b/tools/lldb-server/CMakeLists.txt
index 4f76ebd6881c..f8c57cb9488f 100644
--- a/tools/lldb-server/CMakeLists.txt
+++ b/tools/lldb-server/CMakeLists.txt
@@ -59,6 +59,16 @@ if (LLVM_BUILD_STATIC)
endif()
endif()
+set(LLDB_PLUGINS)
+
+if(CMAKE_SYSTEM_NAME MATCHES "Linux|Android")
+ list(APPEND LLDB_PLUGINS lldbPluginProcessLinux)
+endif()
+
+if(CMAKE_SYSTEM_NAME MATCHES "NetBSD")
+ list(APPEND LLDB_PLUGINS lldbPluginProcessNetBSD)
+endif()
+
add_lldb_tool(lldb-server INCLUDE_IN_FRAMEWORK
Acceptor.cpp
lldb-gdbserver.cpp
@@ -72,7 +82,7 @@ add_lldb_tool(lldb-server INCLUDE_IN_FRAMEWORK
lldbHost
lldbInitialization
lldbInterpreter
- ${EXTRA_LLDB_LIBS}
+ ${LLDB_PLUGINS}
${LLDB_SYSTEM_LIBS}
LINK_COMPONENTS
diff --git a/tools/lldb-server/lldb-gdbserver.cpp b/tools/lldb-server/lldb-gdbserver.cpp
index 412d775e8394..337f244c2c2d 100644
--- a/tools/lldb-server/lldb-gdbserver.cpp
+++ b/tools/lldb-server/lldb-gdbserver.cpp
@@ -33,10 +33,17 @@
#include "lldb/Host/Pipe.h"
#include "lldb/Host/Socket.h"
#include "lldb/Host/StringConvert.h"
+#include "lldb/Host/common/NativeProcessProtocol.h"
#include "lldb/Utility/Status.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Errno.h"
+#if defined(__linux__)
+#include "Plugins/Process/Linux/NativeProcessLinux.h"
+#elif defined(__NetBSD__)
+#include "Plugins/Process/NetBSD/NativeProcessNetBSD.h"
+#endif
+
#ifndef LLGS_PROGRAM_NAME
#define LLGS_PROGRAM_NAME "lldb-server"
#endif
@@ -51,6 +58,30 @@ using namespace lldb_private;
using namespace lldb_private::lldb_server;
using namespace lldb_private::process_gdb_remote;
+namespace {
+#if defined(__linux__)
+typedef process_linux::NativeProcessLinux::Factory NativeProcessFactory;
+#elif defined(__NetBSD__)
+typedef process_netbsd::NativeProcessNetBSD::Factory NativeProcessFactory;
+#else
+// Dummy implementation to make sure the code compiles
+class NativeProcessFactory : public NativeProcessProtocol::Factory {
+public:
+ llvm::Expected<NativeProcessProtocolSP>
+ Launch(ProcessLaunchInfo &launch_info,
+ NativeProcessProtocol::NativeDelegate &delegate,
+ MainLoop &mainloop) const override {
+ llvm_unreachable("Not implemented");
+ }
+ llvm::Expected<NativeProcessProtocolSP>
+ Attach(lldb::pid_t pid, NativeProcessProtocol::NativeDelegate &delegate,
+ MainLoop &mainloop) const override {
+ llvm_unreachable("Not implemented");
+ }
+};
+#endif
+}
+
//----------------------------------------------------------------------
// option descriptors for getopt_long_only()
//----------------------------------------------------------------------
@@ -446,7 +477,8 @@ int main_gdbserver(int argc, char *argv[]) {
exit(255);
}
- GDBRemoteCommunicationServerLLGS gdb_server(mainloop);
+ NativeProcessFactory factory;
+ GDBRemoteCommunicationServerLLGS gdb_server(mainloop, factory);
const char *const host_and_port = argv[0];
argc -= 1;
diff --git a/tools/lldb-server/lldb-platform.cpp b/tools/lldb-server/lldb-platform.cpp
index 8d45682566b9..ec5b781dac48 100644
--- a/tools/lldb-server/lldb-platform.cpp
+++ b/tools/lldb-server/lldb-platform.cpp
@@ -197,46 +197,41 @@ int main_platform(int argc, char *argv[]) {
break;
case 'p': {
- char *end = NULL;
- long tmp_port_offset = strtoul(optarg, &end, 0);
- if (end && *end == '\0') {
- if (LOW_PORT <= tmp_port_offset && tmp_port_offset <= HIGH_PORT) {
- port_offset = (uint16_t)tmp_port_offset;
- } else {
- fprintf(stderr, "error: port offset %li is not in the valid user "
- "port range of %u - %u\n",
- tmp_port_offset, LOW_PORT, HIGH_PORT);
- option_error = 5;
- }
- } else {
- fprintf(stderr, "error: invalid port offset string %s\n", optarg);
+ if (!llvm::to_integer(optarg, port_offset)) {
+ llvm::errs() << "error: invalid port offset string " << optarg << "\n";
option_error = 4;
+ break;
+ }
+ if (port_offset < LOW_PORT || port_offset > HIGH_PORT) {
+ llvm::errs() << llvm::formatv("error: port offset {0} is not in the "
+ "valid user port range of {1} - {2}\n",
+ port_offset, LOW_PORT, HIGH_PORT);
+ option_error = 5;
}
} break;
case 'P':
case 'm':
case 'M': {
- char *end = NULL;
- long portnum = strtoul(optarg, &end, 0);
- if (end && *end == '\0') {
- if (LOW_PORT <= portnum && portnum <= HIGH_PORT) {
- if (ch == 'P')
- gdbserver_portmap[(uint16_t)portnum] = LLDB_INVALID_PROCESS_ID;
- else if (ch == 'm')
- min_gdbserver_port = portnum;
- else
- max_gdbserver_port = portnum;
- } else {
- fprintf(stderr, "error: port number %li is not in the valid user "
- "port range of %u - %u\n",
- portnum, LOW_PORT, HIGH_PORT);
- option_error = 1;
- }
- } else {
- fprintf(stderr, "error: invalid port number string %s\n", optarg);
+ uint16_t portnum;
+ if (!llvm::to_integer(optarg, portnum)) {
+ llvm::errs() << "error: invalid port number string " << optarg << "\n";
option_error = 2;
+ break;
+ }
+ if (portnum < LOW_PORT || portnum > HIGH_PORT) {
+ llvm::errs() << llvm::formatv("error: port number {0} is not in the "
+ "valid user port range of {1} - {2}\n",
+ portnum, LOW_PORT, HIGH_PORT);
+ option_error = 1;
+ break;
}
+ if (ch == 'P')
+ gdbserver_portmap[portnum] = LLDB_INVALID_PROCESS_ID;
+ else if (ch == 'm')
+ min_gdbserver_port = portnum;
+ else
+ max_gdbserver_port = portnum;
} break;
case 'h': /* fall-through is intentional */
diff --git a/unittests/Process/Linux/ProcessorTraceTest.cpp b/unittests/Process/Linux/ProcessorTraceTest.cpp
index b732934d014d..67381b6ddca3 100644
--- a/unittests/Process/Linux/ProcessorTraceTest.cpp
+++ b/unittests/Process/Linux/ProcessorTraceTest.cpp
@@ -30,42 +30,40 @@ size_t ReadCylicBufferWrapper(void *buf, size_t buf_size, void *cyc_buf,
}
TEST(CyclicBuffer, EdgeCases) {
- size_t bytes_read = 0;
+ size_t bytes_read;
uint8_t cyclic_buffer[6] = {'l', 'i', 'c', 'c', 'y', 'c'};
// We will always leave the last bytes untouched
// so that string comparisions work.
- char bigger_buffer[10] = {};
- char equal_size_buffer[7] = {};
char smaller_buffer[4] = {};
// empty buffer to read into
bytes_read = ReadCylicBufferWrapper(smaller_buffer, 0, cyclic_buffer,
sizeof(cyclic_buffer), 3, 0);
- ASSERT_EQ(0, bytes_read);
+ ASSERT_EQ(0u, bytes_read);
// empty cyclic buffer
bytes_read = ReadCylicBufferWrapper(smaller_buffer, sizeof(smaller_buffer),
cyclic_buffer, 0, 3, 0);
- ASSERT_EQ(0, bytes_read);
+ ASSERT_EQ(0u, bytes_read);
// bigger offset
bytes_read =
ReadCylicBufferWrapper(smaller_buffer, sizeof(smaller_buffer),
cyclic_buffer, sizeof(cyclic_buffer), 3, 6);
- ASSERT_EQ(0, bytes_read);
+ ASSERT_EQ(0u, bytes_read);
// wrong offset
bytes_read =
ReadCylicBufferWrapper(smaller_buffer, sizeof(smaller_buffer),
cyclic_buffer, sizeof(cyclic_buffer), 3, 7);
- ASSERT_EQ(0, bytes_read);
+ ASSERT_EQ(0u, bytes_read);
// wrong start
bytes_read =
ReadCylicBufferWrapper(smaller_buffer, sizeof(smaller_buffer),
cyclic_buffer, sizeof(cyclic_buffer), 3, 7);
- ASSERT_EQ(0, bytes_read);
+ ASSERT_EQ(0u, bytes_read);
}
TEST(CyclicBuffer, EqualSizeBuffer) {
@@ -73,7 +71,7 @@ TEST(CyclicBuffer, EqualSizeBuffer) {
uint8_t cyclic_buffer[6] = {'l', 'i', 'c', 'c', 'y', 'c'};
char cyclic[] = "cyclic";
- for (int i = 0; i < sizeof(cyclic); i++) {
+ for (size_t i = 0; i < sizeof(cyclic); i++) {
// We will always leave the last bytes untouched
// so that string comparisions work.
char equal_size_buffer[7] = {};
@@ -86,7 +84,7 @@ TEST(CyclicBuffer, EqualSizeBuffer) {
}
TEST(CyclicBuffer, SmallerSizeBuffer) {
- size_t bytes_read = 0;
+ size_t bytes_read;
uint8_t cyclic_buffer[6] = {'l', 'i', 'c', 'c', 'y', 'c'};
// We will always leave the last bytes untouched
@@ -95,25 +93,25 @@ TEST(CyclicBuffer, SmallerSizeBuffer) {
bytes_read =
ReadCylicBufferWrapper(smaller_buffer, (sizeof(smaller_buffer) - 1),
cyclic_buffer, sizeof(cyclic_buffer), 3, 0);
- ASSERT_EQ(3, bytes_read);
+ ASSERT_EQ(3u, bytes_read);
ASSERT_STREQ(smaller_buffer, "cyc");
bytes_read =
ReadCylicBufferWrapper(smaller_buffer, (sizeof(smaller_buffer) - 1),
cyclic_buffer, sizeof(cyclic_buffer), 3, 1);
- ASSERT_EQ(3, bytes_read);
+ ASSERT_EQ(3u, bytes_read);
ASSERT_STREQ(smaller_buffer, "ycl");
bytes_read =
ReadCylicBufferWrapper(smaller_buffer, (sizeof(smaller_buffer) - 1),
cyclic_buffer, sizeof(cyclic_buffer), 3, 2);
- ASSERT_EQ(3, bytes_read);
+ ASSERT_EQ(3u, bytes_read);
ASSERT_STREQ(smaller_buffer, "cli");
bytes_read =
ReadCylicBufferWrapper(smaller_buffer, (sizeof(smaller_buffer) - 1),
cyclic_buffer, sizeof(cyclic_buffer), 3, 3);
- ASSERT_EQ(3, bytes_read);
+ ASSERT_EQ(3u, bytes_read);
ASSERT_STREQ(smaller_buffer, "lic");
{
@@ -121,7 +119,7 @@ TEST(CyclicBuffer, SmallerSizeBuffer) {
bytes_read =
ReadCylicBufferWrapper(smaller_buffer, (sizeof(smaller_buffer) - 1),
cyclic_buffer, sizeof(cyclic_buffer), 3, 4);
- ASSERT_EQ(2, bytes_read);
+ ASSERT_EQ(2u, bytes_read);
ASSERT_STREQ(smaller_buffer, "ic");
}
{
@@ -129,7 +127,7 @@ TEST(CyclicBuffer, SmallerSizeBuffer) {
bytes_read =
ReadCylicBufferWrapper(smaller_buffer, (sizeof(smaller_buffer) - 1),
cyclic_buffer, sizeof(cyclic_buffer), 3, 5);
- ASSERT_EQ(1, bytes_read);
+ ASSERT_EQ(1u, bytes_read);
ASSERT_STREQ(smaller_buffer, "c");
}
}
@@ -139,7 +137,7 @@ TEST(CyclicBuffer, BiggerSizeBuffer) {
uint8_t cyclic_buffer[6] = {'l', 'i', 'c', 'c', 'y', 'c'};
char cyclic[] = "cyclic";
- for (int i = 0; i < sizeof(cyclic); i++) {
+ for (size_t i = 0; i < sizeof(cyclic); i++) {
// We will always leave the last bytes untouched
// so that string comparisions work.
char bigger_buffer[10] = {};
diff --git a/unittests/UnwindAssembly/x86/Testx86AssemblyInspectionEngine.cpp b/unittests/UnwindAssembly/x86/Testx86AssemblyInspectionEngine.cpp
index e97760967197..c3591b2d73e1 100644
--- a/unittests/UnwindAssembly/x86/Testx86AssemblyInspectionEngine.cpp
+++ b/unittests/UnwindAssembly/x86/Testx86AssemblyInspectionEngine.cpp
@@ -2415,3 +2415,28 @@ TEST_F(Testx86AssemblyInspectionEngine, TestStackRealign32BitDisp_x86_64) {
EXPECT_EQ(rsp_plus_8,
plan.GetRowForFunctionOffset(sizeof(data) - 1)->GetCFAValue());
}
+
+// Give the disassembler random bytes to test that it doesn't exceed
+// the bounds of the array when run under clang's address sanitizer.
+TEST_F(Testx86AssemblyInspectionEngine, TestDisassemblyJunkBytes) {
+ AddressRange sample_range;
+ UnwindPlan unwind_plan(eRegisterKindLLDB);
+ std::unique_ptr<x86AssemblyInspectionEngine> engine32 = Geti386Inspector();
+ std::unique_ptr<x86AssemblyInspectionEngine> engine64 = Getx86_64Inspector();
+
+ uint8_t data[] = {
+ 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };
+
+ sample_range = AddressRange(0x1000, sizeof(data));
+
+ EXPECT_TRUE(engine32->GetNonCallSiteUnwindPlanFromAssembly(
+ data, sizeof(data), sample_range, unwind_plan));
+
+ unwind_plan.Clear();
+
+ EXPECT_TRUE(engine64->GetNonCallSiteUnwindPlanFromAssembly(
+ data, sizeof(data), sample_range, unwind_plan));
+
+}
+
diff --git a/www/architecture.html b/www/architecture.html
deleted file mode 100755
index eb178febde54..000000000000
--- a/www/architecture.html
+++ /dev/null
@@ -1,294 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
-<link href="style.css" rel="stylesheet" type="text/css" />
-<title>LLDB Architecture</title>
-</head>
-
-<body>
- <div class="www_title">
- The <strong>LLDB</strong> Debugger
- </div>
-
-<div id="container">
- <div id="content">
-
- <!--#include virtual="sidebar.incl"-->
-
- <div id="middle">
- <div class="post">
- <h1 class ="postheader">Architecture</h1>
- <div class="postcontent">
-
- <p>LLDB is a large and complex codebase. This section will help you become more familiar with
- the pieces that make up LLDB and give a general overview of the general architecture.</p>
- </div>
- <div class="postfooter"></div>
- </div>
- <div class="post">
- <h1 class ="postheader">Code Layout</h1>
- <div class="postcontent">
-
- <p>LLDB has many code groupings that makeup the source base:</p>
- <ul>
- <li><a href="#api">API</a></li>
- <li><a href="#breakpoint">Breakpoint</a></li>
- <li><a href="#commands">Commands</a></li>
- <li><a href="#core">Core</a></li>
- <li><a href="#dataformatters">DataFormatters</a></li>
- <li><a href="#expression">Expression</a></li>
- <li><a href="#host">Host</a></li>
- <li><a href="#interpreter">Interpreter</a></li>
- <li><a href="#symbol">Symbol</a></li>
- <li><a href="#targ">Target</a></li>
- <li><a href="#utility">Utility</a></li>
- </ul>
- </div>
- <div class="postfooter"></div>
- </div>
- <a name="api"></a>
- <div class="post">
- <h1 class ="postheader">API</h1>
- <div class="postcontent">
-
- <p>The API folder contains the public interface to LLDB.</p>
- <p>We are currently vending a C++ API. In order to be able to add
- methods to this API and allow people to link to our classes,
- we have certain rules that we must follow:</p>
- <ul>
- <li>Classes can't inherit from any other classes.</li>
- <li>Classes can't contain virtual methods.</li>
- <li>Classes should be compatible with script bridging utilities like <a href="http://www.swig.org/">swig</a>.</li>
- <li>Classes should be lightweight and be backed by a single member. Pointers (or shared pointers) are the preferred choice since they allow changing the contents of the backend without affecting the public object layout.</li>
- <li>The interface should be as minimal as possible in order to give a complete API.</li>
- </ul>
- <p>By adhering to these rules we should be able to continue to
- vend a C++ API, and make changes to the API as any additional
- methods added to these classes will just be a dynamic loader
- lookup and they won't affect the class layout (since they
- aren't virtual methods, and no members can be added to the
- class).</p>
- </div>
- <div class="postfooter"></div>
- </div>
- <a name="breakpoint"></a>
- <div class="post">
- <h1 class ="postheader">Breakpoint</h1>
- <div class="postcontent">
-
- <p>A collection of classes that implement our breakpoint classes.
- Breakpoints are resolved symbolically and always continue to
- resolve themselves as your program runs. Whether settings breakpoints
- by file and line, by symbol name, by symbol regular expression,
- or by address, breakpoints will keep trying to resolve new locations
- each time shared libraries are loaded. Breakpoints will of course
- unresolve themselves when shared libraries are unloaded. Breakpoints
- can also be scoped to be set only in a specific shared library. By
- default, breakpoints can be set in any shared library and will continue
- to attempt to be resolved with each shared library load.</p>
- <p>Breakpoint options can be set on the breakpoint,
- or on the individual locations. This allows flexibility when dealing
- with breakpoints and allows us to do what the user wants.</p>
- </div>
- <div class="postfooter"></div>
- </div>
- <a name="commands"></a>
- <div class="post">
- <h1 class ="postheader">Commands</h1>
- <div class="postcontent">
-
- <p>The command source files represent objects that implement
- the functionality for all textual commands available
- in our command line interface.</p>
- <p>Every command is backed by a <b>lldb_private::CommandObject</b>
- or <b>lldb_private::CommandObjectMultiword</b> object.</p>
- <p><b>lldb_private::CommandObjectMultiword</b> are commands that
- have subcommands and allow command line commands to be
- logically grouped into a hierarchy.</p>
- <p><b>lldb_private::CommandObject</b> command line commands
- are the objects that implement the functionality of the
- command. They can optionally define
- options for themselves, as well as group those options into
- logical groups that can go together. The help system is
- tied into these objects and can extract the syntax and
- option groupings to display appropriate help for each
- command.</p>
- </div>
- <div class="postfooter"></div>
- </div>
- <a name="core"></a>
- <div class="post">
- <h1 class ="postheader">Core</h1>
- <div class="postcontent">
-
- <p>The Core source files contain basic functionality that
- is required in the debugger. A wide variety of classes
- are implemented:</p>
-
- <ul>
- <li>Address (section offset addressing)</li>
- <li>AddressRange</li>
- <li>Architecture specification</li>
- <li>Broadcaster / Event / Listener </li>
- <li>Communication classes that use Connection objects</li>
- <li>Uniqued C strings</li>
- <li>Data extraction</li>
- <li>File specifications</li>
- <li>Mangled names</li>
- <li>Regular expressions</li>
- <li>Source manager</li>
- <li>Streams</li>
- <li>Value objects</li>
- </ul>
- </div>
- <div class="postfooter"></div>
- </div>
- <a name="dataformatters"></a>
- <div class="post">
- <h1 class ="postheader">DataFormatters</h1>
- <div class="postcontent">
-
- <p>A collection of classes that implement the data formatters subsystem.</p>
-
- <p>For a general user-level introduction to data formatters, you can look <a href="varformats.html">here</a>.
- <p>A 10,000 foot view of the data formatters is based upon the <code>DataVisualization</code> class.
- <code>DataVisualization</code> is the very high level entry point into the data formatters. It vends a stable interface in face of changing internals
- and is the recommended entry point for components of LLDB that need to ask questions of the data formatters.
- The main questions one can ask of <code>DataVisualization</code> are:
- <ul>
- <li>given a ValueObject, retrieve the formatters to be used for it</li>
- <li>given a type, retrieve the formatters to be used for it. This is not an "exact" question,
- i.e. one can retrieve a formatter from a type name which would not be used to then format ValueObjects of that type</li>
- <li>given a name, retrieve a category of that name, optionally creating it if needed - more generally, categories management</li>
- <li>given an identifier and a summary, store it as a named summary - more generally, named summary management</li>
- </ul>
-
- <p>For people actively maintaining the data formatters subsystem itself, however, the FormatManager class is the relevant point of entry.
- This class is subject to more frequent changes as the formatters evolve. Currently, it provides a thin caching layer on top of a list of categories
- that each export a group of formatters.
- </p>
- <p>From an end-user perspective, the "type" LLDB command is the point of access to the data formatters. A large group of generally-useful formatters
- is provided by default and loaded upon debugger startup.
- </div>
- <div class="postfooter"></div>
- </div>
- <a name="expression"></a>
- <div class="post">
- <h1 class ="postheader">Expression</h1>
- <div class="postcontent">
-
- <p>Expression parsing files cover everything from evaluating
- DWARF expressions, to evaluating expressions using
- Clang.</p>
- <p>The DWARF expression parser has been heavily modified to
- support type promotion, new opcodes needed for evaluating
- expressions with symbolic variable references (expression local variables,
- program variables), and other operators required by
- typical expressions such as assign, address of, float/double/long
- double floating point values, casting, and more. The
- DWARF expression parser uses a stack of lldb_private::Value
- objects. These objects know how to do the standard C type
- promotion, and allow for symbolic references to variables
- in the program and in the LLDB process (expression local
- and expression global variables).</p>
- <p>The expression parser uses a full instance of the Clang
- compiler in order to accurately evaluate expressions.
- Hooks have been put into Clang so that the compiler knows
- to ask about identifiers it doesn't know about. Once
- expressions have be compiled into an AST, we can then
- traverse this AST and either generate a DWARF expression
- that contains simple opcodes that can be quickly re-evaluated
- each time an expression needs to be evaluated, or JIT'ed
- up into code that can be run on the process being debugged.</p>
- </div>
- <div class="postfooter"></div>
- </div>
- <a name="host"></a>
- <div class="post">
- <h1 class ="postheader">Host</h1>
- <div class="postcontent">
-
- <p>LLDB tries to abstract itself from the host upon which
- it is currently running by providing a host abstraction
- layer. This layer involves everything from spawning, detaching,
- joining and killing native in-process threads, to getting
- current information about the current host.</p>
- <p>Host functionality includes abstraction layers for:</p>
- <ul>
- <li>Mutexes</li>
- <li>Conditions</li>
- <li>Timing functions</li>
- <li>Thread functions</li>
- <li>Host target triple</li>
- <li>Host child process notifications</li>
- <li>Host specific types</li>
- </ul>
- </div>
- <div class="postfooter"></div>
- </div>
- <a name="interpreter"></a>
- <div class="post">
- <h1 class ="postheader">Interpreter</h1>
- <div class="postcontent">
-
- <p>The interpreter classes are the classes responsible for
- being the base classes needed for each command object,
- and is responsible for tracking and running command line
- commands.</p>
- </div>
- <div class="postfooter"></div>
- </div>
- <a name="symbol"></a>
- <div class="post">
- <h1 class ="postheader">Symbol</h1>
- <div class="postcontent">
- <p>Symbol classes involve everything needed in order to parse
- object files and debug symbols. All the needed classes
- for compilation units (code and debug info for a source file),
- functions, lexical blocks within functions, inlined
- functions, types, declaration locations, and variables
- are in this section.</p>
- </div>
- <div class="postfooter"></div>
- </div>
- <a name="targ"></a>
- <div class="post">
- <h1 class ="postheader">Target</h1>
- <div class="postcontent">
-
- <p>Classes that are related to a debug target include:</p>
- <ul>
- <li>Target</li>
- <li>Process</li>
- <li>Thread</li>
- <li>Stack frames</li>
- <li>Stack frame registers</li>
- <li>ABI for function calling in process being debugged</li>
- <li>Execution context batons</li>
- </ul>
- </div>
- <div class="postfooter"></div>
- </div>
- <a name="utility"></a>
- <div class="post">
- <h1 class ="postheader">Utility</h1>
- <div class="postcontent">
-
- <p>Utility files should be as stand alone as possible and
- available for LLDB, plug-ins or related
- applications to use.</p>
- <p>Files found in the Utility section include:</p>
- <ul>
- <li>Pseudo-terminal support</li>
- <li>Register numbering for specific architectures.</li>
- <li>String data extractors</li>
- </ul>
- </div>
- <div class="postfooter"></div>
- </div>
- </div>
- </div>
-</div>
-</body>
-</html>
diff --git a/www/architecture/index.html b/www/architecture/index.html
index fd75603f6405..312476fe6edf 100755
--- a/www/architecture/index.html
+++ b/www/architecture/index.html
@@ -119,30 +119,26 @@
</div>
<a name="core"></a>
<div class="post">
- <h1 class ="postheader">Core</h1>
- <div class="postcontent">
-
- <p>The Core source files contain basic functionality that
- is required in the debugger. A wide variety of classes
- are implemented:</p>
-
- <ul>
- <li>Address (section offset addressing)</li>
- <li>AddressRange</li>
- <li>Architecture specification</li>
- <li>Broadcaster / Event / Listener </li>
- <li>Communication classes that use Connection objects</li>
- <li>Uniqued C strings</li>
- <li>Data extraction</li>
- <li>File specifications</li>
- <li>Mangled names</li>
- <li>Regular expressions</li>
- <li>Source manager</li>
- <li>Streams</li>
- <li>Value objects</li>
- </ul>
- </div>
- <div class="postfooter"></div>
+ <h1 class ="postheader">Core</h1>
+ <div class="postcontent">
+ <p>
+ The Core source files contain basic functionality
+ that is required in the debugger as well as the
+ class represeting the debugger it self (Debugger). A
+ wide variety of classes are implemented:
+ </p>
+ <ul>
+ <li>Address (section offset addressing)</li>
+ <li>AddressRange</li>
+ <li>Architecture specification</li>
+ <li>Broadcaster / Event / Listener </li>
+ <li>Communication classes that use Connection objects</li>
+ <li>Mangled names</li>
+ <li>Source manager</li>
+ <li>Value objects</li>
+ </ul>
+ </div>
+ <div class="postfooter"></div>
</div>
<a name="dataformatters"></a>
<div class="post">
@@ -193,26 +189,27 @@
</div>
<a name="host"></a>
<div class="post">
- <h1 class ="postheader">Host</h1>
- <div class="postcontent">
-
- <p>LLDB tries to abstract itself from the host upon which
- it is currently running by providing a host abstraction
- layer. This layer involves everything from spawning, detaching,
- joining and killing native in-process threads, to getting
- current information about the current host.</p>
- <p>Host functionality includes abstraction layers for:</p>
- <ul>
- <li>Mutexes</li>
- <li>Conditions</li>
- <li>Timing functions</li>
- <li>Thread functions</li>
- <li>Host target triple</li>
- <li>Host child process notifications</li>
- <li>Host specific types</li>
- </ul>
- </div>
- <div class="postfooter"></div>
+ <h1 class ="postheader">Host</h1>
+ <div class="postcontent">
+ <p>
+ LLDB tries to abstract itself from the host upon which
+ it is currently running by providing a host abstraction
+ layer. This layer includes functionality, whose
+ implementation varies wildly from host to host.
+ </p>
+ <p>Host functionality includes abstraction layers for:</p>
+ <ul>
+ <li>Information about the host system (triple, list of running processes, etc.)</li>
+ <li>Launching processes</li>
+ <li>Various OS primitives like pipes and sockets</li>
+ </ul>
+ <p>
+ It also includes the base classes of the
+ NativeProcess/Thread hierarchy, which is used by
+ lldb-server.
+ </p>
+ </div>
+ <div class="postfooter"></div>
</div>
<a name="interpreter"></a>
<div class="post">
@@ -259,20 +256,40 @@
</div>
<a name="utility"></a>
<div class="post">
- <h1 class ="postheader">Utility</h1>
- <div class="postcontent">
-
- <p>Utility files should be as stand alone as possible and
- available for LLDB, plug-ins or related
- applications to use.</p>
- <p>Files found in the Utility section include:</p>
- <ul>
- <li>Pseudo-terminal support</li>
- <li>Register numbering for specific architectures.</li>
- <li>String data extractors</li>
- </ul>
- </div>
- <div class="postfooter"></div>
+ <h1 class ="postheader">Utility</h1>
+ <div class="postcontent">
+ <p>
+ This module contains the lowest layers of LLDB. A
+ lot of these classes don't really have anything to
+ do with debugging -- they are just there because the
+ higher layers of the debugger use these clasess
+ to implement their functionality. Others are data
+ structures used in many other parts of the debugger
+ (TraceOptions). Most of the functionality in this
+ module could be useful in an application that is
+ <strong>not</strong> a debugger; however, providing
+ a general purpose C++ library is an explicit
+ non-goal of this module.
+ </p>
+ <p>
+ This module provides following functionality:
+ </p>
+ <ul>
+ <li>Abstract path manipulation (FileSpec)</li>
+ <li>Data buffers (DataBuffer, DataEncoder, DataExtractor)</li>
+ <li>Logging</li>
+ <li>Structured data manipulation (JSON)</li>
+ <li>Streams</li>
+ <li>Timers</li>
+ <li>etc.</li>
+ </ul>
+ <p>
+ For historic reasons, some of this functionality
+ overlaps that which is provided by the LLVM support
+ library.
+ </p>
+ </div>
+ <div class="postfooter"></div>
</div>
</div>
</div>
diff --git a/www/sidebar.incl b/www/sidebar.incl
index 184a022790e2..8c5cca373653 100644
--- a/www/sidebar.incl
+++ b/www/sidebar.incl
@@ -49,7 +49,7 @@
<li><a href="/build.html">Build</a></li>
<li><a href="/test.html">Test</a></li>
<li><a href="/SB-api-coding-rules.html">SB API Coding Rules</a></li>
- <li><a href="http://llvm.org/bugs">Bug Reports</a></li>
+ <li><a href="http://bugs.llvm.org">Bug Reports</a></li>
<li><a href="http://llvm.org/svn/llvm-project/lldb/trunk">Browse SVN</a></li>
<li><a href="http://llvm.org/viewvc/llvm-project/lldb/trunk">Browse ViewVC</a></li>
</ul>