Vendor import of lldb trunk r301939:
https://llvm.org/svn/llvm-project/lldb/trunk@301939
This commit is contained in:
parent
5060b64b7d
commit
773dd0e6e6
CMakeLists.txt
cmake
include/lldb
lldb.xcodeproj
packages/Python/lldbsuite/test
source
Core
Host
Interpreter
Plugins
Language/CPlusPlus
LanguageRuntime/ObjC/AppleObjCRuntime
ObjectContainer/BSD-Archive
ObjectFile/ELF
Platform/Android
SymbolFile/DWARF
Symbol
Target
Utility
tools
debugserver
lldb-server
unittests
Host
ObjectFile/ELF
Process/gdb-remote
debugserver
@ -1,8 +1,15 @@
|
||||
cmake_minimum_required(VERSION 3.4.3)
|
||||
|
||||
include(cmake/modules/LLDBStandalone.cmake)
|
||||
include(cmake/modules/LLDBConfig.cmake)
|
||||
include(cmake/modules/AddLLDB.cmake)
|
||||
# Add path for custom modules
|
||||
set(CMAKE_MODULE_PATH
|
||||
${CMAKE_MODULE_PATH}
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/cmake"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules"
|
||||
)
|
||||
|
||||
include(LLDBStandalone)
|
||||
include(LLDBConfig)
|
||||
include(AddLLDB)
|
||||
|
||||
if (CMAKE_SYSTEM_NAME MATCHES "Windows|Android")
|
||||
set(LLDB_DEFAULT_DISABLE_LIBEDIT 1)
|
||||
|
14
cmake/XcodeHeaderGenerator/CMakeLists.txt
Normal file
14
cmake/XcodeHeaderGenerator/CMakeLists.txt
Normal file
@ -0,0 +1,14 @@
|
||||
cmake_minimum_required(VERSION 3.4.3)
|
||||
|
||||
project(XcodeConfig C CXX)
|
||||
|
||||
set(CMAKE_MODULE_PATH
|
||||
${CMAKE_MODULE_PATH}
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/.."
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/../modules"
|
||||
)
|
||||
|
||||
set(LLDB_CONFIG_HEADER_INPUT
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../include/lldb/Host/Config.h.cmake)
|
||||
|
||||
include(LLDBGenerateConfig)
|
@ -426,20 +426,4 @@ if ((CMAKE_SYSTEM_NAME MATCHES "Android") AND LLVM_BUILD_STATIC AND
|
||||
endif()
|
||||
|
||||
find_package(Backtrace)
|
||||
|
||||
include(CheckIncludeFile)
|
||||
check_include_file(termios.h HAVE_TERMIOS_H)
|
||||
check_include_file(sys/event.h HAVE_SYS_EVENT_H)
|
||||
|
||||
# These checks exist in LLVM's configuration, so I want to match the LLVM names
|
||||
# so that the check isn't duplicated, but we translate them into the LLDB names
|
||||
# so that I don't have to change all the uses at the moment.
|
||||
set(LLDB_CONFIG_TERMIOS_SUPPORTED ${HAVE_TERMIOS_H})
|
||||
if(NOT UNIX)
|
||||
set(LLDB_DISABLE_POSIX 1)
|
||||
endif()
|
||||
|
||||
# This should be done at the end
|
||||
configure_file(
|
||||
${LLDB_INCLUDE_ROOT}/lldb/Host/Config.h.cmake
|
||||
${CMAKE_CURRENT_BINARY_DIR}/include/lldb/Host/Config.h)
|
||||
include(LLDBGenerateConfig)
|
||||
|
35
cmake/modules/LLDBGenerateConfig.cmake
Normal file
35
cmake/modules/LLDBGenerateConfig.cmake
Normal file
@ -0,0 +1,35 @@
|
||||
# This file contains all the logic for running configure-time checks
|
||||
|
||||
include(CheckSymbolExists)
|
||||
include(CheckIncludeFile)
|
||||
include(CheckIncludeFiles)
|
||||
|
||||
set(CMAKE_REQUIRED_DEFINITIONS -D_GNU_SOURCE)
|
||||
check_symbol_exists(ppoll poll.h HAVE_PPOLL)
|
||||
set(CMAKE_REQUIRED_DEFINITIONS)
|
||||
check_symbol_exists(sigaction signal.h HAVE_SIGACTION)
|
||||
|
||||
check_include_file(termios.h HAVE_TERMIOS_H)
|
||||
check_include_files("sys/types.h;sys/event.h" HAVE_SYS_EVENT_H)
|
||||
|
||||
# These checks exist in LLVM's configuration, so I want to match the LLVM names
|
||||
# so that the check isn't duplicated, but we translate them into the LLDB names
|
||||
# so that I don't have to change all the uses at the moment.
|
||||
set(LLDB_CONFIG_TERMIOS_SUPPORTED ${HAVE_TERMIOS_H})
|
||||
if(NOT UNIX)
|
||||
set(LLDB_DISABLE_POSIX 1)
|
||||
endif()
|
||||
|
||||
if(NOT LLDB_CONFIG_HEADER_INPUT)
|
||||
set(LLDB_CONFIG_HEADER_INPUT ${LLDB_INCLUDE_ROOT}/lldb/Host/Config.h.cmake)
|
||||
endif()
|
||||
|
||||
if(NOT LLDB_CONFIG_HEADER_OUTPUT)
|
||||
set(LLDB_CONFIG_HEADER_OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/include/lldb/Host/Config.h)
|
||||
endif()
|
||||
|
||||
# This should be done at the end
|
||||
configure_file(
|
||||
${LLDB_CONFIG_HEADER_INPUT}
|
||||
${LLDB_CONFIG_HEADER_OUTPUT}
|
||||
)
|
@ -614,6 +614,8 @@ public:
|
||||
|
||||
const FileSpec &GetSymbolFileFileSpec() const { return m_symfile_spec; }
|
||||
|
||||
void PreloadSymbols();
|
||||
|
||||
void SetSymbolFileFileSpec(const FileSpec &file);
|
||||
|
||||
const llvm::sys::TimePoint<> &GetModificationTime() const {
|
||||
|
@ -59,4 +59,4 @@ private:
|
||||
};
|
||||
}
|
||||
|
||||
#endif // liblldb_TraceOptions_h_
|
||||
#endif // liblldb_TraceOptions_h_
|
||||
|
@ -17,10 +17,9 @@
|
||||
|
||||
// Other libraries and framework includes
|
||||
// Project includes
|
||||
#include "lldb/Utility/ConstString.h"
|
||||
#include "lldb/Utility/RegularExpression.h"
|
||||
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
|
||||
namespace lldb_private {
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
@ -37,13 +36,17 @@ public:
|
||||
struct Entry {
|
||||
Entry() {}
|
||||
|
||||
Entry(llvm::StringRef cstr) : cstring(cstr), value() {}
|
||||
Entry(ConstString cstr) : cstring(cstr), value() {}
|
||||
|
||||
Entry(llvm::StringRef cstr, const T &v) : cstring(cstr), value(v) {}
|
||||
Entry(ConstString cstr, const T &v) : cstring(cstr), value(v) {}
|
||||
|
||||
bool operator<(const Entry &rhs) const { return cstring < rhs.cstring; }
|
||||
// This is only for uniqueness, not lexicographical ordering, so we can
|
||||
// just compare pointers.
|
||||
bool operator<(const Entry &rhs) const {
|
||||
return cstring.GetCString() < rhs.cstring.GetCString();
|
||||
}
|
||||
|
||||
llvm::StringRef cstring;
|
||||
ConstString cstring;
|
||||
T value;
|
||||
};
|
||||
|
||||
@ -52,7 +55,7 @@ public:
|
||||
// this map, then later call UniqueCStringMap<T>::Sort() before doing
|
||||
// any searches by name.
|
||||
//------------------------------------------------------------------
|
||||
void Append(llvm::StringRef unique_cstr, const T &value) {
|
||||
void Append(ConstString unique_cstr, const T &value) {
|
||||
m_map.push_back(typename UniqueCStringMap<T>::Entry(unique_cstr, value));
|
||||
}
|
||||
|
||||
@ -64,7 +67,7 @@ public:
|
||||
// Call this function to always keep the map sorted when putting
|
||||
// entries into the map.
|
||||
//------------------------------------------------------------------
|
||||
void Insert(llvm::StringRef unique_cstr, const T &value) {
|
||||
void Insert(ConstString unique_cstr, const T &value) {
|
||||
typename UniqueCStringMap<T>::Entry e(unique_cstr, value);
|
||||
m_map.insert(std::upper_bound(m_map.begin(), m_map.end(), e), e);
|
||||
}
|
||||
@ -87,7 +90,7 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
llvm::StringRef GetCStringAtIndexUnchecked(uint32_t idx) const {
|
||||
ConstString GetCStringAtIndexUnchecked(uint32_t idx) const {
|
||||
return m_map[idx].cstring;
|
||||
}
|
||||
|
||||
@ -101,8 +104,8 @@ public:
|
||||
return m_map[idx].value;
|
||||
}
|
||||
|
||||
llvm::StringRef GetCStringAtIndex(uint32_t idx) const {
|
||||
return ((idx < m_map.size()) ? m_map[idx].cstring : llvm::StringRef());
|
||||
ConstString GetCStringAtIndex(uint32_t idx) const {
|
||||
return ((idx < m_map.size()) ? m_map[idx].cstring : ConstString());
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
@ -113,7 +116,7 @@ public:
|
||||
// T values and only if there is a sensible failure value that can
|
||||
// be returned and that won't match any existing values.
|
||||
//------------------------------------------------------------------
|
||||
T Find(llvm::StringRef unique_cstr, T fail_value) const {
|
||||
T Find(ConstString unique_cstr, T fail_value) const {
|
||||
Entry search_entry(unique_cstr);
|
||||
const_iterator end = m_map.end();
|
||||
const_iterator pos = std::lower_bound(m_map.begin(), end, search_entry);
|
||||
@ -131,15 +134,12 @@ public:
|
||||
// The caller is responsible for ensuring that the collection does
|
||||
// not change during while using the returned pointer.
|
||||
//------------------------------------------------------------------
|
||||
const Entry *FindFirstValueForName(llvm::StringRef unique_cstr) const {
|
||||
const Entry *FindFirstValueForName(ConstString unique_cstr) const {
|
||||
Entry search_entry(unique_cstr);
|
||||
const_iterator end = m_map.end();
|
||||
const_iterator pos = std::lower_bound(m_map.begin(), end, search_entry);
|
||||
if (pos != end) {
|
||||
llvm::StringRef pos_cstr = pos->cstring;
|
||||
if (pos_cstr == unique_cstr)
|
||||
return &(*pos);
|
||||
}
|
||||
if (pos != end && pos->cstring == unique_cstr)
|
||||
return &(*pos);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -164,7 +164,7 @@ public:
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
size_t GetValues(llvm::StringRef unique_cstr, std::vector<T> &values) const {
|
||||
size_t GetValues(ConstString unique_cstr, std::vector<T> &values) const {
|
||||
const size_t start_size = values.size();
|
||||
|
||||
Entry search_entry(unique_cstr);
|
||||
@ -186,7 +186,7 @@ public:
|
||||
|
||||
const_iterator pos, end = m_map.end();
|
||||
for (pos = m_map.begin(); pos != end; ++pos) {
|
||||
if (regex.Execute(pos->cstring))
|
||||
if (regex.Execute(pos->cstring.GetCString()))
|
||||
values.push_back(pos->value);
|
||||
}
|
||||
|
||||
@ -240,7 +240,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
size_t Erase(llvm::StringRef unique_cstr) {
|
||||
size_t Erase(ConstString unique_cstr) {
|
||||
size_t num_removed = 0;
|
||||
Entry search_entry(unique_cstr);
|
||||
iterator end = m_map.end();
|
||||
|
@ -18,6 +18,10 @@
|
||||
|
||||
#define HAVE_SYS_EVENT_H 1
|
||||
|
||||
#define HAVE_PPOLL 0
|
||||
|
||||
#define HAVE_SIGACTION 1
|
||||
|
||||
#else
|
||||
|
||||
#error This file is only used by the Xcode build.
|
||||
|
@ -16,4 +16,8 @@
|
||||
|
||||
#cmakedefine01 HAVE_SYS_EVENT_H
|
||||
|
||||
#cmakedefine01 HAVE_PPOLL
|
||||
|
||||
#cmakedefine01 HAVE_SIGACTION
|
||||
|
||||
#endif // #ifndef LLDB_HOST_CONFIG_H
|
||||
|
@ -10,16 +10,96 @@
|
||||
#ifndef lldb_Host_MainLoop_h_
|
||||
#define lldb_Host_MainLoop_h_
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "lldb/Host/Config.h"
|
||||
#include "lldb/Host/MainLoopBase.h"
|
||||
namespace lldb_private {
|
||||
typedef MainLoopBase MainLoop;
|
||||
}
|
||||
#else
|
||||
#include "lldb/Host/posix/MainLoopPosix.h"
|
||||
namespace lldb_private {
|
||||
typedef MainLoopPosix MainLoop;
|
||||
}
|
||||
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
|
||||
#if !HAVE_PPOLL && !HAVE_SYS_EVENT_H
|
||||
#define SIGNAL_POLLING_UNSUPPORTED 1
|
||||
#endif
|
||||
|
||||
namespace lldb_private {
|
||||
|
||||
// Implementation of the MainLoopBase class. It can monitor file descriptors for
|
||||
// readability using ppoll, kqueue, poll or WSAPoll. On Windows it only supports
|
||||
// polling sockets, and will not work on generic file handles or pipes. On
|
||||
// systems without kqueue or ppoll handling singnals is not supported. In
|
||||
// addition to the common base, this class provides the ability to invoke a
|
||||
// given handler when a signal is received.
|
||||
//
|
||||
// Since this class is primarily intended to be used for single-threaded
|
||||
// processing, it does not attempt to perform any internal synchronisation and
|
||||
// any concurrent accesses must be protected externally. However, it is
|
||||
// perfectly legitimate to have more than one instance of this class running on
|
||||
// separate threads, or even a single thread (with some limitations on signal
|
||||
// monitoring).
|
||||
// TODO: Add locking if this class is to be used in a multi-threaded context.
|
||||
class MainLoop : public MainLoopBase {
|
||||
private:
|
||||
class SignalHandle;
|
||||
|
||||
public:
|
||||
typedef std::unique_ptr<SignalHandle> SignalHandleUP;
|
||||
|
||||
~MainLoop() override;
|
||||
|
||||
ReadHandleUP RegisterReadObject(const lldb::IOObjectSP &object_sp,
|
||||
const Callback &callback,
|
||||
Error &error) override;
|
||||
|
||||
// Listening for signals from multiple MainLoop instances is perfectly safe as
|
||||
// long as they don't try to listen for the same signal. The callback function
|
||||
// is invoked when the control returns to the Run() function, not when the
|
||||
// hander is executed. This mean that you can treat the callback as a normal
|
||||
// function and perform things which would not be safe in a signal handler.
|
||||
// However, since the callback is not invoked synchronously, you cannot use
|
||||
// this mechanism to handle SIGSEGV and the like.
|
||||
SignalHandleUP RegisterSignal(int signo, const Callback &callback,
|
||||
Error &error);
|
||||
|
||||
Error Run() override;
|
||||
|
||||
// This should only be performed from a callback. Do not attempt to terminate
|
||||
// the processing from another thread.
|
||||
// TODO: Add synchronization if we want to be terminated from another thread.
|
||||
void RequestTermination() override { m_terminate_request = true; }
|
||||
|
||||
protected:
|
||||
void UnregisterReadObject(IOObject::WaitableHandle handle) override;
|
||||
|
||||
void UnregisterSignal(int signo);
|
||||
|
||||
private:
|
||||
class SignalHandle {
|
||||
public:
|
||||
~SignalHandle() { m_mainloop.UnregisterSignal(m_signo); }
|
||||
|
||||
private:
|
||||
SignalHandle(MainLoop &mainloop, int signo)
|
||||
: m_mainloop(mainloop), m_signo(signo) {}
|
||||
|
||||
MainLoop &m_mainloop;
|
||||
int m_signo;
|
||||
|
||||
friend class MainLoop;
|
||||
DISALLOW_COPY_AND_ASSIGN(SignalHandle);
|
||||
};
|
||||
|
||||
struct SignalInfo {
|
||||
Callback callback;
|
||||
#if HAVE_SIGACTION
|
||||
struct sigaction old_action;
|
||||
#endif
|
||||
bool was_blocked : 1;
|
||||
};
|
||||
class RunImpl;
|
||||
|
||||
llvm::DenseMap<IOObject::WaitableHandle, Callback> m_read_fds;
|
||||
llvm::DenseMap<int, SignalInfo> m_signals;
|
||||
bool m_terminate_request : 1;
|
||||
};
|
||||
|
||||
} // namespace lldb_private
|
||||
|
||||
#endif // lldb_Host_MainLoop_h_
|
||||
|
@ -14,9 +14,7 @@
|
||||
// to provide a minimum level of compatibility across all platforms to rely
|
||||
// on various posix api functionality.
|
||||
|
||||
#include "llvm/Support/Compiler.h"
|
||||
|
||||
#if defined(LLVM_ON_WIN32)
|
||||
#if defined(_WIN32)
|
||||
#include "lldb/Host/windows/PosixApi.h"
|
||||
#endif
|
||||
|
||||
|
@ -57,8 +57,7 @@ public:
|
||||
|
||||
virtual Error Connect(llvm::StringRef name) = 0;
|
||||
virtual Error Listen(llvm::StringRef name, int backlog) = 0;
|
||||
virtual Error Accept(llvm::StringRef name, bool child_processes_inherit,
|
||||
Socket *&socket) = 0;
|
||||
virtual Error Accept(Socket *&socket) = 0;
|
||||
|
||||
// Initialize a Tcp Socket object in listening mode. listen and accept are
|
||||
// implemented
|
||||
@ -103,7 +102,8 @@ public:
|
||||
int32_t &port, Error *error_ptr);
|
||||
|
||||
protected:
|
||||
Socket(NativeSocket socket, SocketProtocol protocol, bool should_close);
|
||||
Socket(SocketProtocol protocol, bool should_close,
|
||||
bool m_child_process_inherit);
|
||||
|
||||
virtual size_t Send(const void *buf, const size_t num_bytes);
|
||||
|
||||
@ -117,6 +117,7 @@ protected:
|
||||
|
||||
SocketProtocol m_protocol;
|
||||
NativeSocket m_socket;
|
||||
bool m_child_processes_inherit;
|
||||
};
|
||||
|
||||
} // namespace lldb_private
|
||||
|
@ -11,12 +11,16 @@
|
||||
#define liblldb_TCPSocket_h_
|
||||
|
||||
#include "lldb/Host/Socket.h"
|
||||
#include "lldb/Host/SocketAddress.h"
|
||||
#include <map>
|
||||
|
||||
namespace lldb_private {
|
||||
class TCPSocket : public Socket {
|
||||
public:
|
||||
TCPSocket(NativeSocket socket, bool should_close);
|
||||
TCPSocket(bool child_processes_inherit, Error &error);
|
||||
TCPSocket(bool should_close, bool child_processes_inherit);
|
||||
TCPSocket(NativeSocket socket, bool should_close,
|
||||
bool child_processes_inherit);
|
||||
~TCPSocket() override;
|
||||
|
||||
// returns port number or 0 if error
|
||||
uint16_t GetLocalPortNumber() const;
|
||||
@ -37,8 +41,18 @@ public:
|
||||
|
||||
Error Connect(llvm::StringRef name) override;
|
||||
Error Listen(llvm::StringRef name, int backlog) override;
|
||||
Error Accept(llvm::StringRef name, bool child_processes_inherit,
|
||||
Socket *&conn_socket) override;
|
||||
Error Accept(Socket *&conn_socket) override;
|
||||
|
||||
Error CreateSocket(int domain);
|
||||
|
||||
bool IsValid() const override;
|
||||
|
||||
private:
|
||||
TCPSocket(NativeSocket socket, const TCPSocket &listen_socket);
|
||||
|
||||
void CloseListenSockets();
|
||||
|
||||
std::map<int, SocketAddress> m_listen_sockets;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -15,19 +15,20 @@
|
||||
namespace lldb_private {
|
||||
class UDPSocket : public Socket {
|
||||
public:
|
||||
UDPSocket(bool child_processes_inherit, Error &error);
|
||||
UDPSocket(bool should_close, bool child_processes_inherit);
|
||||
|
||||
static Error Connect(llvm::StringRef name, bool child_processes_inherit,
|
||||
Socket *&socket);
|
||||
|
||||
private:
|
||||
UDPSocket(NativeSocket socket);
|
||||
UDPSocket(NativeSocket socket, const UDPSocket &listen_socket);
|
||||
|
||||
size_t Send(const void *buf, const size_t num_bytes) override;
|
||||
Error Connect(llvm::StringRef name) override;
|
||||
Error Listen(llvm::StringRef name, int backlog) override;
|
||||
Error Accept(llvm::StringRef name, bool child_processes_inherit,
|
||||
Socket *&socket) override;
|
||||
Error Accept(Socket *&socket) override;
|
||||
|
||||
Error CreateSocket();
|
||||
|
||||
SocketAddress m_sockaddr;
|
||||
};
|
||||
|
@ -15,7 +15,7 @@
|
||||
namespace lldb_private {
|
||||
class AbstractSocket : public DomainSocket {
|
||||
public:
|
||||
AbstractSocket(bool child_processes_inherit, Error &error);
|
||||
AbstractSocket(bool child_processes_inherit);
|
||||
|
||||
protected:
|
||||
size_t GetNameOffset() const override;
|
||||
|
@ -15,22 +15,20 @@
|
||||
namespace lldb_private {
|
||||
class DomainSocket : public Socket {
|
||||
public:
|
||||
DomainSocket(bool child_processes_inherit, Error &error);
|
||||
DomainSocket(bool should_close, bool child_processes_inherit);
|
||||
|
||||
Error Connect(llvm::StringRef name) override;
|
||||
Error Listen(llvm::StringRef name, int backlog) override;
|
||||
Error Accept(llvm::StringRef name, bool child_processes_inherit,
|
||||
Socket *&socket) override;
|
||||
Error Accept(Socket *&socket) override;
|
||||
|
||||
protected:
|
||||
DomainSocket(SocketProtocol protocol, bool child_processes_inherit,
|
||||
Error &error);
|
||||
DomainSocket(SocketProtocol protocol, bool child_processes_inherit);
|
||||
|
||||
virtual size_t GetNameOffset() const;
|
||||
virtual void DeleteSocketFile(llvm::StringRef name);
|
||||
|
||||
private:
|
||||
DomainSocket(NativeSocket socket);
|
||||
DomainSocket(NativeSocket socket, const DomainSocket &listen_socket);
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -1,104 +0,0 @@
|
||||
//===-- MainLoopPosix.h -----------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef lldb_Host_posix_MainLoopPosix_h_
|
||||
#define lldb_Host_posix_MainLoopPosix_h_
|
||||
|
||||
#include "lldb/Host/MainLoopBase.h"
|
||||
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
|
||||
namespace lldb_private {
|
||||
|
||||
// Posix implementation of the MainLoopBase class. It can monitor file
|
||||
// descriptors for
|
||||
// readability using pselect. In addition to the common base, this class
|
||||
// provides the ability to
|
||||
// invoke a given handler when a signal is received.
|
||||
//
|
||||
// Since this class is primarily intended to be used for single-threaded
|
||||
// processing, it does not
|
||||
// attempt to perform any internal synchronisation and any concurrent accesses
|
||||
// must be protected
|
||||
// externally. However, it is perfectly legitimate to have more than one
|
||||
// instance of this class
|
||||
// running on separate threads, or even a single thread (with some limitations
|
||||
// on signal
|
||||
// monitoring).
|
||||
// TODO: Add locking if this class is to be used in a multi-threaded context.
|
||||
class MainLoopPosix : public MainLoopBase {
|
||||
private:
|
||||
class SignalHandle;
|
||||
|
||||
public:
|
||||
typedef std::unique_ptr<SignalHandle> SignalHandleUP;
|
||||
|
||||
~MainLoopPosix() override;
|
||||
|
||||
ReadHandleUP RegisterReadObject(const lldb::IOObjectSP &object_sp,
|
||||
const Callback &callback,
|
||||
Error &error) override;
|
||||
|
||||
// Listening for signals from multiple MainLoopPosix instances is perfectly
|
||||
// safe as long as they
|
||||
// don't try to listen for the same signal. The callback function is invoked
|
||||
// when the control
|
||||
// returns to the Run() function, not when the hander is executed. This means
|
||||
// that you can
|
||||
// treat the callback as a normal function and perform things which would not
|
||||
// be safe in a
|
||||
// signal handler. However, since the callback is not invoked synchronously,
|
||||
// you cannot use
|
||||
// this mechanism to handle SIGSEGV and the like.
|
||||
SignalHandleUP RegisterSignal(int signo, const Callback &callback,
|
||||
Error &error);
|
||||
|
||||
Error Run() override;
|
||||
|
||||
// This should only be performed from a callback. Do not attempt to terminate
|
||||
// the processing
|
||||
// from another thread.
|
||||
// TODO: Add synchronization if we want to be terminated from another thread.
|
||||
void RequestTermination() override { m_terminate_request = true; }
|
||||
|
||||
protected:
|
||||
void UnregisterReadObject(IOObject::WaitableHandle handle) override;
|
||||
|
||||
void UnregisterSignal(int signo);
|
||||
|
||||
private:
|
||||
class SignalHandle {
|
||||
public:
|
||||
~SignalHandle() { m_mainloop.UnregisterSignal(m_signo); }
|
||||
|
||||
private:
|
||||
SignalHandle(MainLoopPosix &mainloop, int signo)
|
||||
: m_mainloop(mainloop), m_signo(signo) {}
|
||||
|
||||
MainLoopPosix &m_mainloop;
|
||||
int m_signo;
|
||||
|
||||
friend class MainLoopPosix;
|
||||
DISALLOW_COPY_AND_ASSIGN(SignalHandle);
|
||||
};
|
||||
|
||||
struct SignalInfo {
|
||||
Callback callback;
|
||||
struct sigaction old_action;
|
||||
bool was_blocked : 1;
|
||||
};
|
||||
|
||||
llvm::DenseMap<IOObject::WaitableHandle, Callback> m_read_fds;
|
||||
llvm::DenseMap<int, SignalInfo> m_signals;
|
||||
bool m_terminate_request : 1;
|
||||
};
|
||||
|
||||
} // namespace lldb_private
|
||||
|
||||
#endif // lldb_Host_posix_MainLoopPosix_h_
|
@ -805,9 +805,9 @@ public:
|
||||
bool IsInMemory() const { return m_memory_addr != LLDB_INVALID_ADDRESS; }
|
||||
|
||||
// Strip linker annotations (such as @@VERSION) from symbol names.
|
||||
virtual std::string
|
||||
virtual llvm::StringRef
|
||||
StripLinkerSymbolAnnotations(llvm::StringRef symbol_name) const {
|
||||
return symbol_name.str();
|
||||
return symbol_name;
|
||||
}
|
||||
|
||||
static lldb::SymbolType GetSymbolTypeFromName(
|
||||
|
@ -180,6 +180,8 @@ public:
|
||||
uint32_t type_mask,
|
||||
lldb_private::TypeList &type_list) = 0;
|
||||
|
||||
virtual void PreloadSymbols();
|
||||
|
||||
virtual lldb_private::TypeSystem *
|
||||
GetTypeSystemForLanguage(lldb::LanguageType language);
|
||||
|
||||
|
@ -40,6 +40,7 @@ public:
|
||||
Symtab(ObjectFile *objfile);
|
||||
~Symtab();
|
||||
|
||||
void PreloadSymbols();
|
||||
void Reserve(size_t count);
|
||||
Symbol *Resize(size_t count);
|
||||
uint32_t AddSymbol(const Symbol &symbol);
|
||||
|
@ -82,6 +82,10 @@ public:
|
||||
|
||||
bool SetPreferDynamicValue(lldb::DynamicValueType d);
|
||||
|
||||
bool GetPreloadSymbols() const;
|
||||
|
||||
void SetPreloadSymbols(bool b);
|
||||
|
||||
bool GetDisableASLR() const;
|
||||
|
||||
void SetDisableASLR(bool b);
|
||||
|
@ -665,7 +665,6 @@
|
||||
26FFC19D14FC072100087D58 /* DynamicLoaderPOSIXDYLD.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26FFC19714FC072100087D58 /* DynamicLoaderPOSIXDYLD.cpp */; };
|
||||
304B2E461CAAA57B007829FE /* ClangUtil.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3032B1B61CAAA3D1004BE1AB /* ClangUtil.cpp */; };
|
||||
30B38A001CAAA6D7009524E3 /* ClangUtil.h in Headers */ = {isa = PBXBuildFile; fileRef = 3032B1B91CAAA400004BE1AB /* ClangUtil.h */; };
|
||||
30DED5DE1B4ECB49004CC508 /* MainLoopPosix.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 30DED5DC1B4ECB17004CC508 /* MainLoopPosix.cpp */; };
|
||||
332CCB181AFF41620034D4C4 /* SBLanguageRuntime.h in Headers */ = {isa = PBXBuildFile; fileRef = 3392EBB71AFF402200858B9F /* SBLanguageRuntime.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
33E5E8471A674FB60024ED68 /* StringConvert.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 33E5E8411A672A240024ED68 /* StringConvert.cpp */; };
|
||||
3F8160A61AB9F7DD001DA9DF /* Logging.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3F8160A51AB9F7DD001DA9DF /* Logging.cpp */; };
|
||||
@ -868,6 +867,8 @@
|
||||
9A0FDEA71E8EF5110086B2F5 /* RegisterContextLinux_mips.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9A0FDE971E8EF5010086B2F5 /* RegisterContextLinux_mips.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 */; };
|
||||
9A1E595D1EB2B141002206A5 /* SBTraceOptions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9A1E59531EB2B0B9002206A5 /* SBTraceOptions.cpp */; };
|
||||
9A22A161135E30370024DDC3 /* EmulateInstructionARM.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9A22A15D135E30370024DDC3 /* EmulateInstructionARM.cpp */; };
|
||||
9A22A163135E30370024DDC3 /* EmulationStateARM.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9A22A15F135E30370024DDC3 /* EmulationStateARM.cpp */; };
|
||||
9A357583116CFDEE00E8ED2F /* SBValueList.h in Headers */ = {isa = PBXBuildFile; fileRef = 9A357582116CFDEE00E8ED2F /* SBValueList.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
@ -876,6 +877,8 @@
|
||||
9A357673116E7B6400E8ED2F /* SBStringList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9A357672116E7B6400E8ED2F /* SBStringList.cpp */; };
|
||||
9A3576A8116E9AB700E8ED2F /* SBHostOS.h in Headers */ = {isa = PBXBuildFile; fileRef = 9A3576A7116E9AB700E8ED2F /* SBHostOS.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
9A3576AA116E9AC700E8ED2F /* SBHostOS.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9A3576A9116E9AC700E8ED2F /* SBHostOS.cpp */; };
|
||||
9A36D24D1EB3BE7F00AAD9EA /* SBTrace.h in Headers */ = {isa = PBXBuildFile; fileRef = 9A1E59581EB2B10D002206A5 /* SBTrace.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
9A36D24E1EB3BE7F00AAD9EA /* SBTraceOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 9A1E59591EB2B10D002206A5 /* SBTraceOptions.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
9A4F35101368A51A00823F52 /* StreamAsynchronousIO.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9A4F350F1368A51A00823F52 /* StreamAsynchronousIO.cpp */; };
|
||||
9A77AD541E64E2760025CE04 /* RegisterInfoPOSIX_arm.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9A77AD501E64E24E0025CE04 /* RegisterInfoPOSIX_arm.cpp */; };
|
||||
9AC7038E117674FB0086C050 /* SBInstruction.h in Headers */ = {isa = PBXBuildFile; fileRef = 9AC7038D117674EB0086C050 /* SBInstruction.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
@ -978,6 +981,7 @@
|
||||
B2A58724143119D50092BFBA /* SBWatchpoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B2A58723143119D50092BFBA /* SBWatchpoint.cpp */; };
|
||||
B2B7CCEB15D1BD6700EEFB57 /* CommandObjectWatchpointCommand.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B2B7CCEA15D1BD6600EEFB57 /* CommandObjectWatchpointCommand.cpp */; };
|
||||
B2B7CCF015D1C20F00EEFB57 /* WatchpointOptions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B2B7CCEF15D1C20F00EEFB57 /* WatchpointOptions.cpp */; };
|
||||
D67521381EA17C4200439694 /* MainLoop.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D67521351EA17C3900439694 /* MainLoop.cpp */; };
|
||||
E769331C1A94D15400C73337 /* lldb-gdbserver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26D6F3F4183E7F9300194858 /* lldb-gdbserver.cpp */; };
|
||||
E769331E1A94D18100C73337 /* lldb-server.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E769331D1A94D18100C73337 /* lldb-server.cpp */; };
|
||||
E7723D441AC4A7FB002BA082 /* RegisterContextPOSIXCore_arm64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E7723D421AC4A7FB002BA082 /* RegisterContextPOSIXCore_arm64.cpp */; };
|
||||
@ -2319,7 +2323,6 @@
|
||||
26FFC19814FC072100087D58 /* DynamicLoaderPOSIXDYLD.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DynamicLoaderPOSIXDYLD.h; sourceTree = "<group>"; };
|
||||
3032B1B61CAAA3D1004BE1AB /* ClangUtil.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ClangUtil.cpp; path = source/Symbol/ClangUtil.cpp; sourceTree = "<group>"; };
|
||||
3032B1B91CAAA400004BE1AB /* ClangUtil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ClangUtil.h; path = include/lldb/Symbol/ClangUtil.h; sourceTree = "<group>"; };
|
||||
30DED5DC1B4ECB17004CC508 /* MainLoopPosix.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MainLoopPosix.cpp; sourceTree = "<group>"; };
|
||||
33064C991A5C7A330033D415 /* UriParser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = UriParser.cpp; path = source/Utility/UriParser.cpp; sourceTree = "<group>"; };
|
||||
3392EBB71AFF402200858B9F /* SBLanguageRuntime.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBLanguageRuntime.h; path = include/lldb/API/SBLanguageRuntime.h; sourceTree = "<group>"; };
|
||||
33E5E8411A672A240024ED68 /* StringConvert.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StringConvert.cpp; sourceTree = "<group>"; };
|
||||
@ -2810,6 +2813,10 @@
|
||||
9A0FDE9B1E8EF5010086B2F5 /* RegisterInfos_mips.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegisterInfos_mips.h; path = Utility/RegisterInfos_mips.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>"; };
|
||||
9A1E59531EB2B0B9002206A5 /* SBTraceOptions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBTraceOptions.cpp; path = source/API/SBTraceOptions.cpp; sourceTree = "<group>"; };
|
||||
9A1E59581EB2B10D002206A5 /* SBTrace.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBTrace.h; path = include/lldb/API/SBTrace.h; sourceTree = "<group>"; };
|
||||
9A1E59591EB2B10D002206A5 /* SBTraceOptions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBTraceOptions.h; path = include/lldb/API/SBTraceOptions.h; sourceTree = "<group>"; };
|
||||
9A22A15D135E30370024DDC3 /* EmulateInstructionARM.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = EmulateInstructionARM.cpp; sourceTree = "<group>"; };
|
||||
9A22A15E135E30370024DDC3 /* EmulateInstructionARM.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EmulateInstructionARM.h; sourceTree = "<group>"; };
|
||||
9A22A15F135E30370024DDC3 /* EmulationStateARM.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = EmulationStateARM.cpp; sourceTree = "<group>"; };
|
||||
@ -3051,6 +3058,7 @@
|
||||
B2B7CCED15D1BFB700EEFB57 /* WatchpointOptions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WatchpointOptions.h; path = include/lldb/Breakpoint/WatchpointOptions.h; sourceTree = "<group>"; };
|
||||
B2B7CCEF15D1C20F00EEFB57 /* WatchpointOptions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = WatchpointOptions.cpp; path = source/Breakpoint/WatchpointOptions.cpp; sourceTree = "<group>"; };
|
||||
B2D3033612EFA5C500F84EB3 /* InstructionUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = InstructionUtils.h; path = Utility/InstructionUtils.h; sourceTree = "<group>"; };
|
||||
D67521351EA17C3900439694 /* MainLoop.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MainLoop.cpp; sourceTree = "<group>"; };
|
||||
E73A15A41B548EC500786197 /* GDBRemoteSignals.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = GDBRemoteSignals.cpp; path = Utility/GDBRemoteSignals.cpp; sourceTree = "<group>"; };
|
||||
E73A15A51B548EC500786197 /* GDBRemoteSignals.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GDBRemoteSignals.h; path = Utility/GDBRemoteSignals.h; sourceTree = "<group>"; };
|
||||
E769331D1A94D18100C73337 /* lldb-server.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "lldb-server.cpp"; path = "tools/lldb-server/lldb-server.cpp"; sourceTree = "<group>"; };
|
||||
@ -4004,6 +4012,10 @@
|
||||
8CCB017F19BA4DD00009FD44 /* SBThreadCollection.cpp */,
|
||||
4C56543419D2297A002E9C44 /* SBThreadPlan.h */,
|
||||
4C56543619D22B32002E9C44 /* SBThreadPlan.cpp */,
|
||||
9A1E59581EB2B10D002206A5 /* SBTrace.h */,
|
||||
9A1E59521EB2B0B9002206A5 /* SBTrace.cpp */,
|
||||
9A1E59591EB2B10D002206A5 /* SBTraceOptions.h */,
|
||||
9A1E59531EB2B0B9002206A5 /* SBTraceOptions.cpp */,
|
||||
2617447911685869005ADD65 /* SBType.h */,
|
||||
261744771168585B005ADD65 /* SBType.cpp */,
|
||||
9475C18514E5E9C5001BFC6D /* SBTypeCategory.h */,
|
||||
@ -5667,7 +5679,6 @@
|
||||
children = (
|
||||
2579065E1BD0488D00178368 /* DomainSocket.cpp */,
|
||||
255EFF751AFABA950069F277 /* LockFilePosix.cpp */,
|
||||
30DED5DC1B4ECB17004CC508 /* MainLoopPosix.cpp */,
|
||||
AFDFDFD019E34D3400EAE509 /* ConnectionFileDescriptorPosix.cpp */,
|
||||
3FDFDDC5199D37ED009756A7 /* FileSystem.cpp */,
|
||||
3FDFE53019A292F0009756A7 /* HostInfoPosix.cpp */,
|
||||
@ -5902,6 +5913,7 @@
|
||||
69A01E1A1236C5D400C660B5 /* common */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D67521351EA17C3900439694 /* MainLoop.cpp */,
|
||||
2579065A1BD0488100178368 /* TCPSocket.cpp */,
|
||||
2579065B1BD0488100178368 /* UDPSocket.cpp */,
|
||||
255EFF731AFABA720069F277 /* LockFileBase.cpp */,
|
||||
@ -6419,6 +6431,7 @@
|
||||
254FBBA31A9166F100BD6378 /* SBAttachInfo.h in Headers */,
|
||||
26680221115FD13D008E1FE4 /* SBDefines.h in Headers */,
|
||||
8CCB018219BA4E270009FD44 /* SBThreadCollection.h in Headers */,
|
||||
9A36D24D1EB3BE7F00AAD9EA /* SBTrace.h in Headers */,
|
||||
AF0EBBEC185941360059E52F /* SBQueue.h in Headers */,
|
||||
26680222115FD13D008E1FE4 /* SBError.h in Headers */,
|
||||
26680223115FD13D008E1FE4 /* SBEvent.h in Headers */,
|
||||
@ -6457,6 +6470,7 @@
|
||||
941BCC8014E48C4000BB969C /* SBTypeFormat.h in Headers */,
|
||||
9475C18F14E5F858001BFC6D /* SBTypeNameSpecifier.h in Headers */,
|
||||
941BCC8114E48C4000BB969C /* SBTypeSummary.h in Headers */,
|
||||
9A36D24E1EB3BE7F00AAD9EA /* SBTraceOptions.h in Headers */,
|
||||
23059A121958B3B2007B8189 /* SBUnixSignals.h in Headers */,
|
||||
941BCC8214E48C4000BB969C /* SBTypeSynthetic.h in Headers */,
|
||||
9A19A6AF1163BBB200E0D453 /* SBValue.h in Headers */,
|
||||
@ -7022,6 +7036,7 @@
|
||||
23DCEA461D1C4D0F00A602B4 /* SBMemoryRegionInfo.cpp in Sources */,
|
||||
26680330116005E7008E1FE4 /* SBDebugger.cpp in Sources */,
|
||||
26680331116005E9008E1FE4 /* SBCommunication.cpp in Sources */,
|
||||
9A1E595D1EB2B141002206A5 /* SBTraceOptions.cpp in Sources */,
|
||||
26680332116005EA008E1FE4 /* SBCommandReturnObject.cpp in Sources */,
|
||||
26680333116005EC008E1FE4 /* SBCommandInterpreter.cpp in Sources */,
|
||||
26680335116005EE008E1FE4 /* SBBroadcaster.cpp in Sources */,
|
||||
@ -7042,6 +7057,7 @@
|
||||
261744781168585B005ADD65 /* SBType.cpp in Sources */,
|
||||
9A35758E116CFE0F00E8ED2F /* SBValueList.cpp in Sources */,
|
||||
9A357673116E7B6400E8ED2F /* SBStringList.cpp in Sources */,
|
||||
9A1E595C1EB2B141002206A5 /* SBTrace.cpp in Sources */,
|
||||
9A3576AA116E9AC700E8ED2F /* SBHostOS.cpp in Sources */,
|
||||
9AC703AF117675410086C050 /* SBInstruction.cpp in Sources */,
|
||||
9AC703B1117675490086C050 /* SBInstructionList.cpp in Sources */,
|
||||
@ -7292,6 +7308,7 @@
|
||||
945261C41B9A11FC00BF138D /* LibCxxUnorderedMap.cpp in Sources */,
|
||||
26CEB5F218762056008F575A /* CommandObjectGUI.cpp in Sources */,
|
||||
AF3A4AD21EA05C4700B5DEB4 /* PlatformRemoteDarwinDevice.cpp in Sources */,
|
||||
D67521381EA17C4200439694 /* MainLoop.cpp in Sources */,
|
||||
2689008013353E2200698AC0 /* CommandInterpreter.cpp in Sources */,
|
||||
AF77E0A41A033D360096C0EA /* RegisterContextPOSIX_powerpc.cpp in Sources */,
|
||||
4CDB8D6D1DBA91B6006C5B13 /* LibStdcppUniquePointer.cpp in Sources */,
|
||||
@ -7784,7 +7801,6 @@
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
30DED5DE1B4ECB49004CC508 /* MainLoopPosix.cpp in Sources */,
|
||||
E769331C1A94D15400C73337 /* lldb-gdbserver.cpp in Sources */,
|
||||
26DC6A1D1337FECA00FF7998 /* lldb-platform.cpp in Sources */,
|
||||
E769331E1A94D18100C73337 /* lldb-server.cpp in Sources */,
|
||||
|
@ -13,14 +13,13 @@ class SharedLibTestCase(TestBase):
|
||||
|
||||
mydir = TestBase.compute_mydir(__file__)
|
||||
|
||||
def test_expr(self):
|
||||
"""Test that types work when defined in a shared library and forward-declared in the main executable"""
|
||||
def common_test_expr(self, preload_symbols):
|
||||
if "clang" in self.getCompiler() and "3.4" in self.getCompilerVersion():
|
||||
self.skipTest(
|
||||
"llvm.org/pr16214 -- clang emits partial DWARF for structures referenced via typedef")
|
||||
|
||||
self.build()
|
||||
self.common_setup()
|
||||
self.common_setup(preload_symbols)
|
||||
|
||||
# This should display correctly.
|
||||
self.expect(
|
||||
@ -31,6 +30,18 @@ class SharedLibTestCase(TestBase):
|
||||
"(sub_foo)",
|
||||
"other_element = 3"])
|
||||
|
||||
self.expect(
|
||||
"expression GetMeASubFoo(my_foo_ptr)",
|
||||
startstr="(sub_foo *) $")
|
||||
|
||||
def test_expr(self):
|
||||
"""Test that types work when defined in a shared library and forward-declared in the main executable"""
|
||||
self.common_test_expr(True)
|
||||
|
||||
def test_expr_no_preload(self):
|
||||
"""Test that types work when defined in a shared library and forward-declared in the main executable, but with preloading disabled"""
|
||||
self.common_test_expr(False)
|
||||
|
||||
@unittest2.expectedFailure("rdar://problem/10704639")
|
||||
def test_frame_variable(self):
|
||||
"""Test that types work when defined in a shared library and forward-declared in the main executable"""
|
||||
@ -54,7 +65,7 @@ class SharedLibTestCase(TestBase):
|
||||
self.line = line_number(self.source, '// Set breakpoint 0 here.')
|
||||
self.shlib_names = ["foo"]
|
||||
|
||||
def common_setup(self):
|
||||
def common_setup(self, preload_symbols = True):
|
||||
# Run in synchronous mode
|
||||
self.dbg.SetAsync(False)
|
||||
|
||||
@ -62,6 +73,8 @@ class SharedLibTestCase(TestBase):
|
||||
target = self.dbg.CreateTarget("a.out")
|
||||
self.assertTrue(target, VALID_TARGET)
|
||||
|
||||
self.runCmd("settings set target.preload-symbols " + str(preload_symbols).lower())
|
||||
|
||||
# Break inside the foo function which takes a bar_ptr argument.
|
||||
lldbutil.run_break_set_by_file_and_line(
|
||||
self, self.source, self.line, num_expected_locations=1, loc_exact=True)
|
||||
|
@ -63,6 +63,7 @@ endif
|
||||
GCC_TOOLCHAIN = $(NDK_ROOT)/toolchains/$(TOOLCHAIN_DIR)/prebuilt/$(HOST_TAG)
|
||||
|
||||
OBJCOPY ?= $(GCC_TOOLCHAIN)/bin/$(TOOL_PREFIX)-objcopy
|
||||
ARCHIVER ?= $(GCC_TOOLCHAIN)/bin/$(TOOL_PREFIX)-ar
|
||||
|
||||
ifeq "$(findstring clang,$(CC))" "clang"
|
||||
ARCH_CFLAGS += -target $(TRIPLE) -gcc-toolchain $(GCC_TOOLCHAIN)
|
||||
|
@ -319,8 +319,16 @@ class MiExecTestCase(lldbmi_testcase.MiTestCaseBase):
|
||||
# -exec-step can keep us in the g_MyFunction for gcc
|
||||
self.runCmd("-exec-finish --frame 0")
|
||||
self.expect("\^running")
|
||||
self.expect(
|
||||
"\*stopped,reason=\"end-stepping-range\".+?main\.cpp\",line=\"30\"")
|
||||
it = self.expect(["\*stopped,reason=\"end-stepping-range\".+?main\.cpp\",line=\"30\"",
|
||||
"\*stopped,reason=\"end-stepping-range\".+?main\.cpp\",line=\"29\""])
|
||||
|
||||
if it == 1:
|
||||
# Call to s_MyFunction may not follow immediately after g_MyFunction.
|
||||
# There might be some instructions in between to restore caller-saved registers.
|
||||
# We need to get past these instructions with a next to reach call to s_MyFunction.
|
||||
self.runCmd("-exec-next --thread 1")
|
||||
self.expect("\^running")
|
||||
self.expect("\*stopped,reason=\"end-stepping-range\".+?main\.cpp\",line=\"30\"")
|
||||
|
||||
# Test that -exec-step steps into s_MyFunction
|
||||
# (and that --frame is optional)
|
||||
|
@ -1432,6 +1432,22 @@ size_t Module::FindSymbolsMatchingRegExAndType(const RegularExpression ®ex,
|
||||
return sc_list.GetSize() - initial_size;
|
||||
}
|
||||
|
||||
void Module::PreloadSymbols() {
|
||||
std::lock_guard<std::recursive_mutex> guard(m_mutex);
|
||||
SymbolVendor * sym_vendor = GetSymbolVendor();
|
||||
if (!sym_vendor) {
|
||||
return;
|
||||
}
|
||||
// Prime the symbol file first, since it adds symbols to the symbol table.
|
||||
if (SymbolFile *symbol_file = sym_vendor->GetSymbolFile()) {
|
||||
symbol_file->PreloadSymbols();
|
||||
}
|
||||
// Now we can prime the symbol table.
|
||||
if (Symtab * symtab = sym_vendor->GetSymtab()) {
|
||||
symtab->PreloadSymbols();
|
||||
}
|
||||
}
|
||||
|
||||
void Module::SetSymbolFileFileSpec(const FileSpec &file) {
|
||||
if (!file.Exists())
|
||||
return;
|
||||
|
@ -15,6 +15,7 @@ add_host_subdirectory(common
|
||||
common/HostThread.cpp
|
||||
common/IOObject.cpp
|
||||
common/LockFileBase.cpp
|
||||
common/MainLoop.cpp
|
||||
common/MonitoringProcessLauncher.cpp
|
||||
common/NativeBreakpoint.cpp
|
||||
common/NativeBreakpointList.cpp
|
||||
@ -85,7 +86,6 @@ else()
|
||||
posix/HostProcessPosix.cpp
|
||||
posix/HostThreadPosix.cpp
|
||||
posix/LockFilePosix.cpp
|
||||
posix/MainLoopPosix.cpp
|
||||
posix/PipePosix.cpp
|
||||
posix/ProcessLauncherPosixFork.cpp
|
||||
)
|
||||
|
382
source/Host/common/MainLoop.cpp
Normal file
382
source/Host/common/MainLoop.cpp
Normal file
@ -0,0 +1,382 @@
|
||||
//===-- MainLoop.cpp --------------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/Config/llvm-config.h"
|
||||
|
||||
#include "lldb/Host/MainLoop.h"
|
||||
#include "lldb/Utility/Error.h"
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cerrno>
|
||||
#include <csignal>
|
||||
#include <vector>
|
||||
#include <time.h>
|
||||
|
||||
#if HAVE_SYS_EVENT_H
|
||||
#include <sys/event.h>
|
||||
#elif defined(LLVM_ON_WIN32)
|
||||
#include <winsock2.h>
|
||||
#else
|
||||
#include <poll.h>
|
||||
#endif
|
||||
|
||||
#ifdef LLVM_ON_WIN32
|
||||
#define POLL WSAPoll
|
||||
#else
|
||||
#define POLL poll
|
||||
#endif
|
||||
|
||||
#ifdef __ANDROID__
|
||||
#define FORCE_PSELECT
|
||||
#endif
|
||||
|
||||
#if SIGNAL_POLLING_UNSUPPORTED
|
||||
#ifdef LLVM_ON_WIN32
|
||||
typedef int sigset_t;
|
||||
typedef int siginfo_t;
|
||||
#endif
|
||||
|
||||
int ppoll(struct pollfd *fds, size_t nfds, const struct timespec *timeout_ts,
|
||||
const sigset_t *) {
|
||||
int timeout =
|
||||
(timeout_ts == nullptr)
|
||||
? -1
|
||||
: (timeout_ts->tv_sec * 1000 + timeout_ts->tv_nsec / 1000000);
|
||||
return POLL(fds, nfds, timeout);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
using namespace lldb;
|
||||
using namespace lldb_private;
|
||||
|
||||
static sig_atomic_t g_signal_flags[NSIG];
|
||||
|
||||
static void SignalHandler(int signo, siginfo_t *info, void *) {
|
||||
assert(signo < NSIG);
|
||||
g_signal_flags[signo] = 1;
|
||||
}
|
||||
|
||||
class MainLoop::RunImpl {
|
||||
public:
|
||||
// TODO: Use llvm::Expected<T>
|
||||
static std::unique_ptr<RunImpl> Create(MainLoop &loop, Error &error);
|
||||
~RunImpl();
|
||||
|
||||
Error Poll();
|
||||
|
||||
template <typename F> void ForEachReadFD(F &&f);
|
||||
template <typename F> void ForEachSignal(F &&f);
|
||||
|
||||
private:
|
||||
MainLoop &loop;
|
||||
|
||||
#if HAVE_SYS_EVENT_H
|
||||
int queue_id;
|
||||
std::vector<struct kevent> in_events;
|
||||
struct kevent out_events[4];
|
||||
int num_events = -1;
|
||||
|
||||
RunImpl(MainLoop &loop, int queue_id) : loop(loop), queue_id(queue_id) {
|
||||
in_events.reserve(loop.m_read_fds.size() + loop.m_signals.size());
|
||||
}
|
||||
#else
|
||||
std::vector<int> signals;
|
||||
#ifdef FORCE_PSELECT
|
||||
fd_set read_fd_set;
|
||||
#else
|
||||
std::vector<struct pollfd> read_fds;
|
||||
#endif
|
||||
|
||||
RunImpl(MainLoop &loop) : loop(loop) {
|
||||
signals.reserve(loop.m_signals.size());
|
||||
}
|
||||
|
||||
sigset_t get_sigmask();
|
||||
#endif
|
||||
};
|
||||
|
||||
#if HAVE_SYS_EVENT_H
|
||||
MainLoop::RunImpl::~RunImpl() {
|
||||
int r = close(queue_id);
|
||||
assert(r == 0);
|
||||
(void)r;
|
||||
}
|
||||
std::unique_ptr<MainLoop::RunImpl> MainLoop::RunImpl::Create(MainLoop &loop, Error &error)
|
||||
{
|
||||
error.Clear();
|
||||
int queue_id = kqueue();
|
||||
if(queue_id < 0) {
|
||||
error = Error(errno, eErrorTypePOSIX);
|
||||
return nullptr;
|
||||
}
|
||||
return std::unique_ptr<RunImpl>(new RunImpl(loop, queue_id));
|
||||
}
|
||||
|
||||
Error MainLoop::RunImpl::Poll() {
|
||||
in_events.resize(loop.m_read_fds.size() + loop.m_signals.size());
|
||||
unsigned i = 0;
|
||||
for (auto &fd : loop.m_read_fds)
|
||||
EV_SET(&in_events[i++], fd.first, EVFILT_READ, EV_ADD, 0, 0, 0);
|
||||
|
||||
for (const auto &sig : loop.m_signals)
|
||||
EV_SET(&in_events[i++], sig.first, EVFILT_SIGNAL, EV_ADD, 0, 0, 0);
|
||||
|
||||
num_events = kevent(queue_id, in_events.data(), in_events.size(), out_events,
|
||||
llvm::array_lengthof(out_events), nullptr);
|
||||
|
||||
if (num_events < 0)
|
||||
return Error("kevent() failed with error %d\n", num_events);
|
||||
return Error();
|
||||
}
|
||||
|
||||
template <typename F> void MainLoop::RunImpl::ForEachReadFD(F &&f) {
|
||||
assert(num_events >= 0);
|
||||
for (int i = 0; i < num_events; ++i) {
|
||||
f(out_events[i].ident);
|
||||
if (loop.m_terminate_request)
|
||||
return;
|
||||
}
|
||||
}
|
||||
template <typename F> void MainLoop::RunImpl::ForEachSignal(F && f) {}
|
||||
#else
|
||||
MainLoop::RunImpl::~RunImpl() {}
|
||||
std::unique_ptr<MainLoop::RunImpl> MainLoop::RunImpl::Create(MainLoop &loop, Error &error)
|
||||
{
|
||||
error.Clear();
|
||||
return std::unique_ptr<RunImpl>(new RunImpl(loop));
|
||||
}
|
||||
|
||||
sigset_t MainLoop::RunImpl::get_sigmask() {
|
||||
#if SIGNAL_POLLING_UNSUPPORTED
|
||||
return 0;
|
||||
#else
|
||||
sigset_t sigmask;
|
||||
int ret = pthread_sigmask(SIG_SETMASK, nullptr, &sigmask);
|
||||
assert(ret == 0);
|
||||
(void) ret;
|
||||
|
||||
for (const auto &sig : loop.m_signals) {
|
||||
signals.push_back(sig.first);
|
||||
sigdelset(&sigmask, sig.first);
|
||||
}
|
||||
return sigmask;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef FORCE_PSELECT
|
||||
Error MainLoop::RunImpl::Poll() {
|
||||
signals.clear();
|
||||
|
||||
FD_ZERO(&read_fd_set);
|
||||
int nfds = 0;
|
||||
for (const auto &fd : loop.m_read_fds) {
|
||||
FD_SET(fd.first, &read_fd_set);
|
||||
nfds = std::max(nfds, fd.first + 1);
|
||||
}
|
||||
|
||||
sigset_t sigmask = get_sigmask();
|
||||
if (pselect(nfds, &read_fd_set, nullptr, nullptr, nullptr, &sigmask) == -1 &&
|
||||
errno != EINTR)
|
||||
return Error(errno, eErrorTypePOSIX);
|
||||
|
||||
return Error();
|
||||
}
|
||||
|
||||
template <typename F> void MainLoop::RunImpl::ForEachReadFD(F &&f) {
|
||||
for (const auto &fd : loop.m_read_fds) {
|
||||
if(!FD_ISSET(fd.first, &read_fd_set))
|
||||
continue;
|
||||
|
||||
f(fd.first);
|
||||
if (loop.m_terminate_request)
|
||||
return;
|
||||
}
|
||||
}
|
||||
#else
|
||||
Error MainLoop::RunImpl::Poll() {
|
||||
signals.clear();
|
||||
read_fds.clear();
|
||||
|
||||
sigset_t sigmask = get_sigmask();
|
||||
|
||||
for (const auto &fd : loop.m_read_fds) {
|
||||
struct pollfd pfd;
|
||||
pfd.fd = fd.first;
|
||||
pfd.events = POLLIN;
|
||||
pfd.revents = 0;
|
||||
read_fds.push_back(pfd);
|
||||
}
|
||||
|
||||
if (ppoll(read_fds.data(), read_fds.size(), nullptr, &sigmask) == -1 &&
|
||||
errno != EINTR)
|
||||
return Error(errno, eErrorTypePOSIX);
|
||||
|
||||
return Error();
|
||||
}
|
||||
|
||||
template <typename F> void MainLoop::RunImpl::ForEachReadFD(F &&f) {
|
||||
for (const auto &fd : read_fds) {
|
||||
if ((fd.revents & POLLIN) == 0)
|
||||
continue;
|
||||
|
||||
f(fd.fd);
|
||||
if (loop.m_terminate_request)
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
template <typename F> void MainLoop::RunImpl::ForEachSignal(F &&f) {
|
||||
for (int sig : signals) {
|
||||
if (g_signal_flags[sig] == 0)
|
||||
continue; // No signal
|
||||
g_signal_flags[sig] = 0;
|
||||
f(sig);
|
||||
|
||||
if (loop.m_terminate_request)
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
MainLoop::~MainLoop() {
|
||||
assert(m_read_fds.size() == 0);
|
||||
assert(m_signals.size() == 0);
|
||||
}
|
||||
|
||||
MainLoop::ReadHandleUP
|
||||
MainLoop::RegisterReadObject(const IOObjectSP &object_sp,
|
||||
const Callback &callback, Error &error) {
|
||||
#ifdef LLVM_ON_WIN32
|
||||
if (object_sp->GetFdType() != IOObject:: eFDTypeSocket) {
|
||||
error.SetErrorString("MainLoop: non-socket types unsupported on Windows");
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
if (!object_sp || !object_sp->IsValid()) {
|
||||
error.SetErrorString("IO object is not valid.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const bool inserted =
|
||||
m_read_fds.insert({object_sp->GetWaitableHandle(), callback}).second;
|
||||
if (!inserted) {
|
||||
error.SetErrorStringWithFormat("File descriptor %d already monitored.",
|
||||
object_sp->GetWaitableHandle());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return CreateReadHandle(object_sp);
|
||||
}
|
||||
|
||||
// We shall block the signal, then install the signal handler. The signal will
|
||||
// be unblocked in
|
||||
// the Run() function to check for signal delivery.
|
||||
MainLoop::SignalHandleUP
|
||||
MainLoop::RegisterSignal(int signo, const Callback &callback,
|
||||
Error &error) {
|
||||
#ifdef SIGNAL_POLLING_UNSUPPORTED
|
||||
error.SetErrorString("Signal polling is not supported on this platform.");
|
||||
return nullptr;
|
||||
#else
|
||||
if (m_signals.find(signo) != m_signals.end()) {
|
||||
error.SetErrorStringWithFormat("Signal %d already monitored.", signo);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
SignalInfo info;
|
||||
info.callback = callback;
|
||||
struct sigaction new_action;
|
||||
new_action.sa_sigaction = &SignalHandler;
|
||||
new_action.sa_flags = SA_SIGINFO;
|
||||
sigemptyset(&new_action.sa_mask);
|
||||
sigaddset(&new_action.sa_mask, signo);
|
||||
|
||||
sigset_t old_set;
|
||||
if (int ret = pthread_sigmask(SIG_BLOCK, &new_action.sa_mask, &old_set)) {
|
||||
error.SetErrorStringWithFormat("pthread_sigmask failed with error %d\n",
|
||||
ret);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
info.was_blocked = sigismember(&old_set, signo);
|
||||
if (sigaction(signo, &new_action, &info.old_action) == -1) {
|
||||
error.SetErrorToErrno();
|
||||
if (!info.was_blocked)
|
||||
pthread_sigmask(SIG_UNBLOCK, &new_action.sa_mask, nullptr);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
m_signals.insert({signo, info});
|
||||
g_signal_flags[signo] = 0;
|
||||
|
||||
return SignalHandleUP(new SignalHandle(*this, signo));
|
||||
#endif
|
||||
}
|
||||
|
||||
void MainLoop::UnregisterReadObject(IOObject::WaitableHandle handle) {
|
||||
bool erased = m_read_fds.erase(handle);
|
||||
UNUSED_IF_ASSERT_DISABLED(erased);
|
||||
assert(erased);
|
||||
}
|
||||
|
||||
void MainLoop::UnregisterSignal(int signo) {
|
||||
#if SIGNAL_POLLING_UNSUPPORTED
|
||||
Error("Signal polling is not supported on this platform.");
|
||||
#else
|
||||
// We undo the actions of RegisterSignal on a best-effort basis.
|
||||
auto it = m_signals.find(signo);
|
||||
assert(it != m_signals.end());
|
||||
|
||||
sigaction(signo, &it->second.old_action, nullptr);
|
||||
|
||||
sigset_t set;
|
||||
sigemptyset(&set);
|
||||
sigaddset(&set, signo);
|
||||
pthread_sigmask(it->second.was_blocked ? SIG_BLOCK : SIG_UNBLOCK, &set,
|
||||
nullptr);
|
||||
|
||||
m_signals.erase(it);
|
||||
#endif
|
||||
}
|
||||
|
||||
Error MainLoop::Run() {
|
||||
m_terminate_request = false;
|
||||
|
||||
Error error;
|
||||
auto impl = RunImpl::Create(*this, error);
|
||||
if (!impl)
|
||||
return error;
|
||||
|
||||
// run until termination or until we run out of things to listen to
|
||||
while (!m_terminate_request && (!m_read_fds.empty() || !m_signals.empty())) {
|
||||
|
||||
error = impl->Poll();
|
||||
if (error.Fail())
|
||||
return error;
|
||||
|
||||
impl->ForEachSignal([&](int sig) {
|
||||
auto it = m_signals.find(sig);
|
||||
if (it != m_signals.end())
|
||||
it->second.callback(*this); // Do the work
|
||||
});
|
||||
if (m_terminate_request)
|
||||
return Error();
|
||||
|
||||
impl->ForEachReadFD([&](int fd) {
|
||||
auto it = m_read_fds.find(fd);
|
||||
if (it != m_read_fds.end())
|
||||
it->second(*this); // Do the work
|
||||
});
|
||||
if (m_terminate_request)
|
||||
return Error();
|
||||
}
|
||||
return Error();
|
||||
}
|
@ -18,6 +18,8 @@
|
||||
#include "lldb/Utility/Log.h"
|
||||
#include "lldb/Utility/RegularExpression.h"
|
||||
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
|
||||
#ifndef LLDB_DISABLE_POSIX
|
||||
#include "lldb/Host/posix/DomainSocket.h"
|
||||
|
||||
@ -67,9 +69,11 @@ bool IsInterrupted() {
|
||||
}
|
||||
}
|
||||
|
||||
Socket::Socket(NativeSocket socket, SocketProtocol protocol, bool should_close)
|
||||
Socket::Socket(SocketProtocol protocol, bool should_close,
|
||||
bool child_processes_inherit)
|
||||
: IOObject(eFDTypeSocket, should_close), m_protocol(protocol),
|
||||
m_socket(socket) {}
|
||||
m_socket(kInvalidSocketValue),
|
||||
m_child_processes_inherit(child_processes_inherit) {}
|
||||
|
||||
Socket::~Socket() { Close(); }
|
||||
|
||||
@ -81,14 +85,17 @@ std::unique_ptr<Socket> Socket::Create(const SocketProtocol protocol,
|
||||
std::unique_ptr<Socket> socket_up;
|
||||
switch (protocol) {
|
||||
case ProtocolTcp:
|
||||
socket_up.reset(new TCPSocket(child_processes_inherit, error));
|
||||
socket_up =
|
||||
llvm::make_unique<TCPSocket>(true, child_processes_inherit);
|
||||
break;
|
||||
case ProtocolUdp:
|
||||
socket_up.reset(new UDPSocket(child_processes_inherit, error));
|
||||
socket_up =
|
||||
llvm::make_unique<UDPSocket>(true, child_processes_inherit);
|
||||
break;
|
||||
case ProtocolUnixDomain:
|
||||
#ifndef LLDB_DISABLE_POSIX
|
||||
socket_up.reset(new DomainSocket(child_processes_inherit, error));
|
||||
socket_up =
|
||||
llvm::make_unique<DomainSocket>(true, child_processes_inherit);
|
||||
#else
|
||||
error.SetErrorString(
|
||||
"Unix domain sockets are not supported on this platform.");
|
||||
@ -96,7 +103,8 @@ std::unique_ptr<Socket> Socket::Create(const SocketProtocol protocol,
|
||||
break;
|
||||
case ProtocolUnixAbstract:
|
||||
#ifdef __linux__
|
||||
socket_up.reset(new AbstractSocket(child_processes_inherit, error));
|
||||
socket_up =
|
||||
llvm::make_unique<AbstractSocket>(child_processes_inherit);
|
||||
#else
|
||||
error.SetErrorString(
|
||||
"Abstract domain sockets are not supported on this platform.");
|
||||
@ -145,7 +153,7 @@ Error Socket::TcpListen(llvm::StringRef host_and_port,
|
||||
return error;
|
||||
|
||||
std::unique_ptr<TCPSocket> listen_socket(
|
||||
new TCPSocket(child_processes_inherit, error));
|
||||
new TCPSocket(true, child_processes_inherit));
|
||||
if (error.Fail())
|
||||
return error;
|
||||
|
||||
@ -208,7 +216,7 @@ Error Socket::UnixDomainAccept(llvm::StringRef name,
|
||||
if (error.Fail())
|
||||
return error;
|
||||
|
||||
error = listen_socket->Accept(name, child_processes_inherit, socket);
|
||||
error = listen_socket->Accept(socket);
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -240,18 +248,22 @@ Error Socket::UnixAbstractAccept(llvm::StringRef name,
|
||||
if (error.Fail())
|
||||
return error;
|
||||
|
||||
error = listen_socket->Accept(name, child_processes_inherit, socket);
|
||||
error = listen_socket->Accept(socket);
|
||||
return error;
|
||||
}
|
||||
|
||||
bool Socket::DecodeHostAndPort(llvm::StringRef host_and_port,
|
||||
std::string &host_str, std::string &port_str,
|
||||
int32_t &port, Error *error_ptr) {
|
||||
static RegularExpression g_regex(llvm::StringRef("([^:]+):([0-9]+)"));
|
||||
static RegularExpression g_regex(
|
||||
llvm::StringRef("([^:]+|\\[[0-9a-fA-F:]+.*\\]):([0-9]+)"));
|
||||
RegularExpression::Match regex_match(2);
|
||||
if (g_regex.Execute(host_and_port, ®ex_match)) {
|
||||
if (regex_match.GetMatchAtIndex(host_and_port.data(), 1, host_str) &&
|
||||
regex_match.GetMatchAtIndex(host_and_port.data(), 2, port_str)) {
|
||||
// IPv6 addresses are wrapped in [] when specified with ports
|
||||
if (host_str.front() == '[' && host_str.back() == ']')
|
||||
host_str = host_str.substr(1, host_str.size() - 2);
|
||||
bool ok = false;
|
||||
port = StringConvert::ToUInt32(port_str.c_str(), UINT32_MAX, 10, &ok);
|
||||
if (ok && port <= UINT16_MAX) {
|
||||
@ -404,12 +416,12 @@ NativeSocket Socket::CreateSocket(const int domain, const int type,
|
||||
const int protocol,
|
||||
bool child_processes_inherit, Error &error) {
|
||||
error.Clear();
|
||||
auto socketType = type;
|
||||
auto socket_type = type;
|
||||
#ifdef SOCK_CLOEXEC
|
||||
if (!child_processes_inherit)
|
||||
socketType |= SOCK_CLOEXEC;
|
||||
socket_type |= SOCK_CLOEXEC;
|
||||
#endif
|
||||
auto sock = ::socket(domain, socketType, protocol);
|
||||
auto sock = ::socket(domain, socket_type, protocol);
|
||||
if (sock == kInvalidSocketValue)
|
||||
SetLastError(error);
|
||||
|
||||
|
@ -6,6 +6,12 @@
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Note: This file is used on Darwin by debugserver, so it needs to remain as
|
||||
// self contained as possible, and devoid of references to LLVM unless
|
||||
// there is compelling reason.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#define _WINSOCK_DEPRECATED_NO_WARNINGS
|
||||
@ -227,7 +233,8 @@ bool SocketAddress::getaddrinfo(const char *host, const char *service,
|
||||
int ai_flags) {
|
||||
Clear();
|
||||
|
||||
auto addresses = GetAddressInfo(host, service, ai_family, ai_socktype, ai_protocol, ai_flags);
|
||||
auto addresses = GetAddressInfo(host, service, ai_family, ai_socktype,
|
||||
ai_protocol, ai_flags);
|
||||
if (!addresses.empty())
|
||||
*this = addresses[0];
|
||||
return IsValid();
|
||||
|
@ -14,30 +14,57 @@
|
||||
#include "lldb/Host/common/TCPSocket.h"
|
||||
|
||||
#include "lldb/Host/Config.h"
|
||||
#include "lldb/Host/MainLoop.h"
|
||||
#include "lldb/Utility/Log.h"
|
||||
|
||||
#include "llvm/Config/llvm-config.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
||||
#ifndef LLDB_DISABLE_POSIX
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
|
||||
#if defined(LLVM_ON_WIN32)
|
||||
#include <winsock2.h>
|
||||
#endif
|
||||
|
||||
#ifdef LLVM_ON_WIN32
|
||||
#define CLOSE_SOCKET closesocket
|
||||
typedef const char *set_socket_option_arg_type;
|
||||
#else
|
||||
#define CLOSE_SOCKET ::close
|
||||
typedef const void *set_socket_option_arg_type;
|
||||
#endif
|
||||
|
||||
using namespace lldb;
|
||||
using namespace lldb_private;
|
||||
|
||||
namespace {
|
||||
|
||||
const int kDomain = AF_INET;
|
||||
const int kType = SOCK_STREAM;
|
||||
}
|
||||
|
||||
TCPSocket::TCPSocket(NativeSocket socket, bool should_close)
|
||||
: Socket(socket, ProtocolTcp, should_close) {}
|
||||
TCPSocket::TCPSocket(bool should_close, bool child_processes_inherit)
|
||||
: Socket(ProtocolTcp, should_close, child_processes_inherit) {}
|
||||
|
||||
TCPSocket::TCPSocket(bool child_processes_inherit, Error &error)
|
||||
: TCPSocket(CreateSocket(kDomain, kType, IPPROTO_TCP,
|
||||
child_processes_inherit, error),
|
||||
true) {}
|
||||
TCPSocket::TCPSocket(NativeSocket socket, const TCPSocket &listen_socket)
|
||||
: Socket(ProtocolTcp, listen_socket.m_should_close_fd,
|
||||
listen_socket.m_child_processes_inherit) {
|
||||
m_socket = socket;
|
||||
}
|
||||
|
||||
TCPSocket::TCPSocket(NativeSocket socket, bool should_close,
|
||||
bool child_processes_inherit)
|
||||
: Socket(ProtocolTcp, should_close, child_processes_inherit) {
|
||||
m_socket = socket;
|
||||
}
|
||||
|
||||
TCPSocket::~TCPSocket() { CloseListenSockets(); }
|
||||
|
||||
bool TCPSocket::IsValid() const {
|
||||
return m_socket != kInvalidSocketValue || m_listen_sockets.size() != 0;
|
||||
}
|
||||
|
||||
// Return the port number that is being used by the socket.
|
||||
uint16_t TCPSocket::GetLocalPortNumber() const {
|
||||
@ -46,6 +73,12 @@ uint16_t TCPSocket::GetLocalPortNumber() const {
|
||||
socklen_t sock_addr_len = sock_addr.GetMaxLength();
|
||||
if (::getsockname(m_socket, sock_addr, &sock_addr_len) == 0)
|
||||
return sock_addr.GetPort();
|
||||
} else if (!m_listen_sockets.empty()) {
|
||||
SocketAddress sock_addr;
|
||||
socklen_t sock_addr_len = sock_addr.GetMaxLength();
|
||||
if (::getsockname(m_listen_sockets.begin()->first, sock_addr,
|
||||
&sock_addr_len) == 0)
|
||||
return sock_addr.GetPort();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -84,9 +117,18 @@ std::string TCPSocket::GetRemoteIPAddress() const {
|
||||
return "";
|
||||
}
|
||||
|
||||
Error TCPSocket::CreateSocket(int domain) {
|
||||
Error error;
|
||||
if (IsValid())
|
||||
error = Close();
|
||||
if (error.Fail())
|
||||
return error;
|
||||
m_socket = Socket::CreateSocket(domain, kType, IPPROTO_TCP,
|
||||
m_child_processes_inherit, error);
|
||||
return error;
|
||||
}
|
||||
|
||||
Error TCPSocket::Connect(llvm::StringRef name) {
|
||||
if (m_socket == kInvalidSocketValue)
|
||||
return Error("Invalid socket");
|
||||
|
||||
Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_COMMUNICATION));
|
||||
if (log)
|
||||
@ -99,146 +141,140 @@ Error TCPSocket::Connect(llvm::StringRef name) {
|
||||
if (!DecodeHostAndPort(name, host_str, port_str, port, &error))
|
||||
return error;
|
||||
|
||||
struct sockaddr_in sa;
|
||||
::memset(&sa, 0, sizeof(sa));
|
||||
sa.sin_family = kDomain;
|
||||
sa.sin_port = htons(port);
|
||||
auto addresses = lldb_private::SocketAddress::GetAddressInfo(
|
||||
host_str.c_str(), NULL, AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP);
|
||||
for (auto address : addresses) {
|
||||
error = CreateSocket(address.GetFamily());
|
||||
if (error.Fail())
|
||||
continue;
|
||||
|
||||
int inet_pton_result = ::inet_pton(kDomain, host_str.c_str(), &sa.sin_addr);
|
||||
address.SetPort(port);
|
||||
|
||||
if (inet_pton_result <= 0) {
|
||||
struct hostent *host_entry = gethostbyname(host_str.c_str());
|
||||
if (host_entry)
|
||||
host_str = ::inet_ntoa(*(struct in_addr *)*host_entry->h_addr_list);
|
||||
inet_pton_result = ::inet_pton(kDomain, host_str.c_str(), &sa.sin_addr);
|
||||
if (inet_pton_result <= 0) {
|
||||
if (inet_pton_result == -1)
|
||||
SetLastError(error);
|
||||
else
|
||||
error.SetErrorStringWithFormat("invalid host string: '%s'",
|
||||
host_str.c_str());
|
||||
|
||||
return error;
|
||||
if (-1 == ::connect(GetNativeSocket(), &address.sockaddr(),
|
||||
address.GetLength())) {
|
||||
CLOSE_SOCKET(GetNativeSocket());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (-1 ==
|
||||
::connect(GetNativeSocket(), (const struct sockaddr *)&sa, sizeof(sa))) {
|
||||
SetLastError(error);
|
||||
SetOptionNoDelay();
|
||||
|
||||
error.Clear();
|
||||
return error;
|
||||
}
|
||||
|
||||
// Keep our TCP packets coming without any delays.
|
||||
SetOptionNoDelay();
|
||||
error.Clear();
|
||||
error.SetErrorString("Failed to connect port");
|
||||
return error;
|
||||
}
|
||||
|
||||
Error TCPSocket::Listen(llvm::StringRef name, int backlog) {
|
||||
Error error;
|
||||
|
||||
// enable local address reuse
|
||||
SetOptionReuseAddress();
|
||||
|
||||
Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION));
|
||||
if (log)
|
||||
log->Printf("TCPSocket::%s (%s)", __FUNCTION__, name.data());
|
||||
|
||||
Error error;
|
||||
std::string host_str;
|
||||
std::string port_str;
|
||||
int32_t port = INT32_MIN;
|
||||
if (!DecodeHostAndPort(name, host_str, port_str, port, &error))
|
||||
return error;
|
||||
|
||||
SocketAddress bind_addr;
|
||||
if (host_str == "*")
|
||||
host_str = "0.0.0.0";
|
||||
auto addresses = lldb_private::SocketAddress::GetAddressInfo(
|
||||
host_str.c_str(), NULL, AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP);
|
||||
for (auto address : addresses) {
|
||||
int fd = Socket::CreateSocket(address.GetFamily(), kType, IPPROTO_TCP,
|
||||
m_child_processes_inherit, error);
|
||||
if (error.Fail()) {
|
||||
error.Clear();
|
||||
continue;
|
||||
}
|
||||
|
||||
// Only bind to the loopback address if we are expecting a connection from
|
||||
// localhost to avoid any firewall issues.
|
||||
const bool bind_addr_success = (host_str == "127.0.0.1")
|
||||
? bind_addr.SetToLocalhost(kDomain, port)
|
||||
: bind_addr.SetToAnyAddress(kDomain, port);
|
||||
// enable local address reuse
|
||||
int option_value = 1;
|
||||
set_socket_option_arg_type option_value_p =
|
||||
reinterpret_cast<set_socket_option_arg_type>(&option_value);
|
||||
::setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, option_value_p,
|
||||
sizeof(option_value));
|
||||
|
||||
if (!bind_addr_success) {
|
||||
error.SetErrorString("Failed to bind port");
|
||||
return error;
|
||||
address.SetPort(port);
|
||||
|
||||
int err = ::bind(fd, &address.sockaddr(), address.GetLength());
|
||||
if (-1 != err)
|
||||
err = ::listen(fd, backlog);
|
||||
|
||||
if (-1 == err) {
|
||||
CLOSE_SOCKET(fd);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (port == 0) {
|
||||
socklen_t sa_len = address.GetLength();
|
||||
if (getsockname(fd, &address.sockaddr(), &sa_len) == 0)
|
||||
port = address.GetPort();
|
||||
}
|
||||
m_listen_sockets[fd] = address;
|
||||
}
|
||||
|
||||
int err = ::bind(GetNativeSocket(), bind_addr, bind_addr.GetLength());
|
||||
if (err != -1)
|
||||
err = ::listen(GetNativeSocket(), backlog);
|
||||
|
||||
if (err == -1)
|
||||
SetLastError(error);
|
||||
|
||||
if (m_listen_sockets.size() == 0)
|
||||
error.SetErrorString("Failed to connect port");
|
||||
return error;
|
||||
}
|
||||
|
||||
Error TCPSocket::Accept(llvm::StringRef name, bool child_processes_inherit,
|
||||
Socket *&conn_socket) {
|
||||
Error error;
|
||||
std::string host_str;
|
||||
std::string port_str;
|
||||
int32_t port;
|
||||
if (!DecodeHostAndPort(name, host_str, port_str, port, &error))
|
||||
return error;
|
||||
void TCPSocket::CloseListenSockets() {
|
||||
for (auto socket : m_listen_sockets)
|
||||
CLOSE_SOCKET(socket.first);
|
||||
m_listen_sockets.clear();
|
||||
}
|
||||
|
||||
const sa_family_t family = kDomain;
|
||||
const int socktype = kType;
|
||||
const int protocol = IPPROTO_TCP;
|
||||
SocketAddress listen_addr;
|
||||
if (host_str.empty())
|
||||
listen_addr.SetToLocalhost(family, port);
|
||||
else if (host_str.compare("*") == 0)
|
||||
listen_addr.SetToAnyAddress(family, port);
|
||||
else {
|
||||
if (!listen_addr.getaddrinfo(host_str.c_str(), port_str.c_str(), family,
|
||||
socktype, protocol)) {
|
||||
error.SetErrorStringWithFormat("unable to resolve hostname '%s'",
|
||||
host_str.c_str());
|
||||
Error TCPSocket::Accept(Socket *&conn_socket) {
|
||||
Error error;
|
||||
if (m_listen_sockets.size() == 0) {
|
||||
error.SetErrorString("No open listening sockets!");
|
||||
return error;
|
||||
}
|
||||
|
||||
int sock = -1;
|
||||
int listen_sock = -1;
|
||||
lldb_private::SocketAddress AcceptAddr;
|
||||
MainLoop accept_loop;
|
||||
std::vector<MainLoopBase::ReadHandleUP> handles;
|
||||
for (auto socket : m_listen_sockets) {
|
||||
auto fd = socket.first;
|
||||
auto inherit = this->m_child_processes_inherit;
|
||||
auto io_sp = IOObjectSP(new TCPSocket(socket.first, false, inherit));
|
||||
handles.emplace_back(accept_loop.RegisterReadObject(
|
||||
io_sp, [fd, inherit, &sock, &AcceptAddr, &error,
|
||||
&listen_sock](MainLoopBase &loop) {
|
||||
socklen_t sa_len = AcceptAddr.GetMaxLength();
|
||||
sock = AcceptSocket(fd, &AcceptAddr.sockaddr(), &sa_len, inherit,
|
||||
error);
|
||||
listen_sock = fd;
|
||||
loop.RequestTermination();
|
||||
}, error));
|
||||
if (error.Fail())
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
bool accept_connection = false;
|
||||
std::unique_ptr<TCPSocket> accepted_socket;
|
||||
|
||||
// Loop until we are happy with our connection
|
||||
while (!accept_connection) {
|
||||
struct sockaddr_in accept_addr;
|
||||
::memset(&accept_addr, 0, sizeof accept_addr);
|
||||
#if !(defined(__linux__) || defined(_WIN32))
|
||||
accept_addr.sin_len = sizeof accept_addr;
|
||||
#endif
|
||||
socklen_t accept_addr_len = sizeof accept_addr;
|
||||
|
||||
int sock = AcceptSocket(GetNativeSocket(), (struct sockaddr *)&accept_addr,
|
||||
&accept_addr_len, child_processes_inherit, error);
|
||||
|
||||
accept_loop.Run();
|
||||
|
||||
if (error.Fail())
|
||||
break;
|
||||
return error;
|
||||
|
||||
bool is_same_addr = true;
|
||||
#if !(defined(__linux__) || (defined(_WIN32)))
|
||||
is_same_addr = (accept_addr_len == listen_addr.sockaddr_in().sin_len);
|
||||
#endif
|
||||
if (is_same_addr)
|
||||
is_same_addr = (accept_addr.sin_addr.s_addr ==
|
||||
listen_addr.sockaddr_in().sin_addr.s_addr);
|
||||
|
||||
if (is_same_addr ||
|
||||
(listen_addr.sockaddr_in().sin_addr.s_addr == INADDR_ANY)) {
|
||||
accept_connection = true;
|
||||
accepted_socket.reset(new TCPSocket(sock, true));
|
||||
} else {
|
||||
const uint8_t *accept_ip = (const uint8_t *)&accept_addr.sin_addr.s_addr;
|
||||
const uint8_t *listen_ip =
|
||||
(const uint8_t *)&listen_addr.sockaddr_in().sin_addr.s_addr;
|
||||
::fprintf(stderr, "error: rejecting incoming connection from %u.%u.%u.%u "
|
||||
"(expecting %u.%u.%u.%u)\n",
|
||||
accept_ip[0], accept_ip[1], accept_ip[2], accept_ip[3],
|
||||
listen_ip[0], listen_ip[1], listen_ip[2], listen_ip[3]);
|
||||
accepted_socket.reset();
|
||||
lldb_private::SocketAddress &AddrIn = m_listen_sockets[listen_sock];
|
||||
if (!AddrIn.IsAnyAddr() && AcceptAddr != AddrIn) {
|
||||
CLOSE_SOCKET(sock);
|
||||
llvm::errs() << llvm::formatv(
|
||||
"error: rejecting incoming connection from {0} (expecting {1})",
|
||||
AcceptAddr.GetIPAddress(), AddrIn.GetIPAddress());
|
||||
continue;
|
||||
}
|
||||
accept_connection = true;
|
||||
accepted_socket.reset(new TCPSocket(sock, *this));
|
||||
}
|
||||
|
||||
if (!accepted_socket)
|
||||
|
@ -28,41 +28,31 @@ const int kDomain = AF_INET;
|
||||
const int kType = SOCK_DGRAM;
|
||||
|
||||
static const char *g_not_supported_error = "Not supported";
|
||||
} // namespace
|
||||
|
||||
UDPSocket::UDPSocket(bool should_close, bool child_processes_inherit)
|
||||
: Socket(ProtocolUdp, should_close, child_processes_inherit) {}
|
||||
|
||||
UDPSocket::UDPSocket(NativeSocket socket, const UDPSocket &listen_socket)
|
||||
: Socket(ProtocolUdp, listen_socket.m_should_close_fd,
|
||||
listen_socket.m_child_processes_inherit) {
|
||||
m_socket = socket;
|
||||
}
|
||||
|
||||
UDPSocket::UDPSocket(NativeSocket socket) : Socket(socket, ProtocolUdp, true) {}
|
||||
|
||||
UDPSocket::UDPSocket(bool child_processes_inherit, Error &error)
|
||||
: UDPSocket(
|
||||
CreateSocket(kDomain, kType, 0, child_processes_inherit, error)) {}
|
||||
|
||||
size_t UDPSocket::Send(const void *buf, const size_t num_bytes) {
|
||||
return ::sendto(m_socket, static_cast<const char *>(buf), num_bytes, 0,
|
||||
m_sockaddr, m_sockaddr.GetLength());
|
||||
}
|
||||
|
||||
Error UDPSocket::Connect(llvm::StringRef name) {
|
||||
return Error("%s", g_not_supported_error);
|
||||
}
|
||||
|
||||
Error UDPSocket::Listen(llvm::StringRef name, int backlog) {
|
||||
return Error("%s", g_not_supported_error);
|
||||
}
|
||||
|
||||
Error UDPSocket::Accept(llvm::StringRef name, bool child_processes_inherit,
|
||||
Socket *&socket) {
|
||||
return Error("%s", g_not_supported_error);
|
||||
}
|
||||
|
||||
Error UDPSocket::Connect(llvm::StringRef name, bool child_processes_inherit,
|
||||
Socket *&socket) {
|
||||
std::unique_ptr<UDPSocket> final_socket;
|
||||
|
||||
Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION));
|
||||
if (log)
|
||||
log->Printf("UDPSocket::%s (host/port = %s)", __FUNCTION__, name.data());
|
||||
|
||||
Error error;
|
||||
if (error.Fail())
|
||||
return error;
|
||||
|
||||
std::string host_str;
|
||||
std::string port_str;
|
||||
int32_t port = INT32_MIN;
|
||||
@ -94,12 +84,11 @@ Error UDPSocket::Connect(llvm::StringRef name, bool child_processes_inherit,
|
||||
for (struct addrinfo *service_info_ptr = service_info_list;
|
||||
service_info_ptr != nullptr;
|
||||
service_info_ptr = service_info_ptr->ai_next) {
|
||||
auto send_fd = CreateSocket(
|
||||
m_socket = Socket::CreateSocket(
|
||||
service_info_ptr->ai_family, service_info_ptr->ai_socktype,
|
||||
service_info_ptr->ai_protocol, child_processes_inherit, error);
|
||||
service_info_ptr->ai_protocol, m_child_processes_inherit, error);
|
||||
if (error.Success()) {
|
||||
final_socket.reset(new UDPSocket(send_fd));
|
||||
final_socket->m_sockaddr = service_info_ptr;
|
||||
m_sockaddr = service_info_ptr;
|
||||
break;
|
||||
} else
|
||||
continue;
|
||||
@ -107,16 +96,17 @@ Error UDPSocket::Connect(llvm::StringRef name, bool child_processes_inherit,
|
||||
|
||||
::freeaddrinfo(service_info_list);
|
||||
|
||||
if (!final_socket)
|
||||
if (IsValid())
|
||||
return error;
|
||||
|
||||
SocketAddress bind_addr;
|
||||
|
||||
// Only bind to the loopback address if we are expecting a connection from
|
||||
// localhost to avoid any firewall issues.
|
||||
const bool bind_addr_success = (host_str == "127.0.0.1" || host_str == "localhost")
|
||||
? bind_addr.SetToLocalhost(kDomain, port)
|
||||
: bind_addr.SetToAnyAddress(kDomain, port);
|
||||
const bool bind_addr_success =
|
||||
(host_str == "127.0.0.1" || host_str == "localhost")
|
||||
? bind_addr.SetToLocalhost(kDomain, port)
|
||||
: bind_addr.SetToAnyAddress(kDomain, port);
|
||||
|
||||
if (!bind_addr_success) {
|
||||
error.SetErrorString("Failed to get hostspec to bind for");
|
||||
@ -125,13 +115,37 @@ Error UDPSocket::Connect(llvm::StringRef name, bool child_processes_inherit,
|
||||
|
||||
bind_addr.SetPort(0); // Let the source port # be determined dynamically
|
||||
|
||||
err = ::bind(final_socket->GetNativeSocket(), bind_addr, bind_addr.GetLength());
|
||||
err = ::bind(m_socket, bind_addr, bind_addr.GetLength());
|
||||
|
||||
struct sockaddr_in source_info;
|
||||
socklen_t address_len = sizeof (struct sockaddr_in);
|
||||
err = ::getsockname(final_socket->GetNativeSocket(), (struct sockaddr *) &source_info, &address_len);
|
||||
|
||||
socket = final_socket.release();
|
||||
error.Clear();
|
||||
return error;
|
||||
}
|
||||
|
||||
Error UDPSocket::Listen(llvm::StringRef name, int backlog) {
|
||||
return Error("%s", g_not_supported_error);
|
||||
}
|
||||
|
||||
Error UDPSocket::Accept(Socket *&socket) {
|
||||
return Error("%s", g_not_supported_error);
|
||||
}
|
||||
|
||||
Error UDPSocket::CreateSocket() {
|
||||
Error error;
|
||||
if (IsValid())
|
||||
error = Close();
|
||||
if (error.Fail())
|
||||
return error;
|
||||
m_socket =
|
||||
Socket::CreateSocket(kDomain, kType, 0, m_child_processes_inherit, error);
|
||||
return error;
|
||||
}
|
||||
|
||||
Error UDPSocket::Connect(llvm::StringRef name, bool child_processes_inherit,
|
||||
Socket *&socket) {
|
||||
std::unique_ptr<UDPSocket> final_socket(
|
||||
new UDPSocket(true, child_processes_inherit));
|
||||
Error error = final_socket->Connect(name);
|
||||
if (!error.Fail())
|
||||
socket = final_socket.release();
|
||||
return error;
|
||||
}
|
||||
|
@ -14,8 +14,8 @@
|
||||
using namespace lldb;
|
||||
using namespace lldb_private;
|
||||
|
||||
AbstractSocket::AbstractSocket(bool child_processes_inherit, Error &error)
|
||||
: DomainSocket(ProtocolUnixAbstract, child_processes_inherit, error) {}
|
||||
AbstractSocket::AbstractSocket(bool child_processes_inherit)
|
||||
: DomainSocket(ProtocolUnixAbstract, child_processes_inherit) {}
|
||||
|
||||
size_t AbstractSocket::GetNameOffset() const { return 1; }
|
||||
|
||||
|
@ -218,7 +218,7 @@ ConnectionStatus ConnectionFileDescriptor::Connect(llvm::StringRef path,
|
||||
// assume we don't own it.
|
||||
|
||||
std::unique_ptr<TCPSocket> tcp_socket;
|
||||
tcp_socket.reset(new TCPSocket(fd, false));
|
||||
tcp_socket.reset(new TCPSocket(fd, false, false));
|
||||
// Try and get a socket option from this file descriptor to
|
||||
// see if this is a socket and set m_is_socket accordingly.
|
||||
int resuse;
|
||||
@ -720,7 +720,7 @@ ConnectionFileDescriptor::SocketListenAndAccept(llvm::StringRef s,
|
||||
|
||||
listening_socket_up.reset(socket);
|
||||
socket = nullptr;
|
||||
error = listening_socket_up->Accept(s, m_child_processes_inherit, socket);
|
||||
error = listening_socket_up->Accept(socket);
|
||||
listening_socket_up.reset();
|
||||
if (error_ptr)
|
||||
*error_ptr = error;
|
||||
|
@ -56,19 +56,21 @@ bool SetSockAddr(llvm::StringRef name, const size_t name_offset,
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
DomainSocket::DomainSocket(NativeSocket socket)
|
||||
: Socket(socket, ProtocolUnixDomain, true) {}
|
||||
|
||||
DomainSocket::DomainSocket(bool child_processes_inherit, Error &error)
|
||||
: DomainSocket(
|
||||
CreateSocket(kDomain, kType, 0, child_processes_inherit, error)) {}
|
||||
DomainSocket::DomainSocket(bool should_close, bool child_processes_inherit)
|
||||
: Socket(ProtocolUnixDomain, should_close, child_processes_inherit) {}
|
||||
|
||||
DomainSocket::DomainSocket(SocketProtocol protocol,
|
||||
bool child_processes_inherit, Error &error)
|
||||
: Socket(CreateSocket(kDomain, kType, 0, child_processes_inherit, error),
|
||||
protocol, true) {}
|
||||
bool child_processes_inherit)
|
||||
: Socket(protocol, true, child_processes_inherit) {}
|
||||
|
||||
DomainSocket::DomainSocket(NativeSocket socket,
|
||||
const DomainSocket &listen_socket)
|
||||
: Socket(ProtocolUnixDomain, listen_socket.m_should_close_fd,
|
||||
listen_socket.m_child_processes_inherit) {
|
||||
m_socket = socket;
|
||||
}
|
||||
|
||||
Error DomainSocket::Connect(llvm::StringRef name) {
|
||||
sockaddr_un saddr_un;
|
||||
@ -77,6 +79,9 @@ Error DomainSocket::Connect(llvm::StringRef name) {
|
||||
return Error("Failed to set socket address");
|
||||
|
||||
Error error;
|
||||
m_socket = CreateSocket(kDomain, kType, 0, m_child_processes_inherit, error);
|
||||
if (error.Fail())
|
||||
return error;
|
||||
if (::connect(GetNativeSocket(), (struct sockaddr *)&saddr_un, saddr_un_len) <
|
||||
0)
|
||||
SetLastError(error);
|
||||
@ -93,6 +98,9 @@ Error DomainSocket::Listen(llvm::StringRef name, int backlog) {
|
||||
DeleteSocketFile(name);
|
||||
|
||||
Error error;
|
||||
m_socket = CreateSocket(kDomain, kType, 0, m_child_processes_inherit, error);
|
||||
if (error.Fail())
|
||||
return error;
|
||||
if (::bind(GetNativeSocket(), (struct sockaddr *)&saddr_un, saddr_un_len) ==
|
||||
0)
|
||||
if (::listen(GetNativeSocket(), backlog) == 0)
|
||||
@ -102,13 +110,12 @@ Error DomainSocket::Listen(llvm::StringRef name, int backlog) {
|
||||
return error;
|
||||
}
|
||||
|
||||
Error DomainSocket::Accept(llvm::StringRef name, bool child_processes_inherit,
|
||||
Socket *&socket) {
|
||||
Error DomainSocket::Accept(Socket *&socket) {
|
||||
Error error;
|
||||
auto conn_fd = AcceptSocket(GetNativeSocket(), nullptr, nullptr,
|
||||
child_processes_inherit, error);
|
||||
m_child_processes_inherit, error);
|
||||
if (error.Success())
|
||||
socket = new DomainSocket(conn_fd);
|
||||
socket = new DomainSocket(conn_fd, *this);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
@ -1,182 +0,0 @@
|
||||
//===-- MainLoopPosix.cpp ---------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "lldb/Host/posix/MainLoopPosix.h"
|
||||
#include "lldb/Utility/Error.h"
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cerrno>
|
||||
#include <csignal>
|
||||
#include <sys/select.h>
|
||||
#include <vector>
|
||||
|
||||
using namespace lldb;
|
||||
using namespace lldb_private;
|
||||
|
||||
static sig_atomic_t g_signal_flags[NSIG];
|
||||
|
||||
static void SignalHandler(int signo, siginfo_t *info, void *) {
|
||||
assert(signo < NSIG);
|
||||
g_signal_flags[signo] = 1;
|
||||
}
|
||||
|
||||
MainLoopPosix::~MainLoopPosix() {
|
||||
assert(m_read_fds.size() == 0);
|
||||
assert(m_signals.size() == 0);
|
||||
}
|
||||
|
||||
MainLoopPosix::ReadHandleUP
|
||||
MainLoopPosix::RegisterReadObject(const IOObjectSP &object_sp,
|
||||
const Callback &callback, Error &error) {
|
||||
if (!object_sp || !object_sp->IsValid()) {
|
||||
error.SetErrorString("IO object is not valid.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const bool inserted =
|
||||
m_read_fds.insert({object_sp->GetWaitableHandle(), callback}).second;
|
||||
if (!inserted) {
|
||||
error.SetErrorStringWithFormat("File descriptor %d already monitored.",
|
||||
object_sp->GetWaitableHandle());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return CreateReadHandle(object_sp);
|
||||
}
|
||||
|
||||
// We shall block the signal, then install the signal handler. The signal will
|
||||
// be unblocked in
|
||||
// the Run() function to check for signal delivery.
|
||||
MainLoopPosix::SignalHandleUP
|
||||
MainLoopPosix::RegisterSignal(int signo, const Callback &callback,
|
||||
Error &error) {
|
||||
if (m_signals.find(signo) != m_signals.end()) {
|
||||
error.SetErrorStringWithFormat("Signal %d already monitored.", signo);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
SignalInfo info;
|
||||
info.callback = callback;
|
||||
struct sigaction new_action;
|
||||
new_action.sa_sigaction = &SignalHandler;
|
||||
new_action.sa_flags = SA_SIGINFO;
|
||||
sigemptyset(&new_action.sa_mask);
|
||||
sigaddset(&new_action.sa_mask, signo);
|
||||
|
||||
sigset_t old_set;
|
||||
if (int ret = pthread_sigmask(SIG_BLOCK, &new_action.sa_mask, &old_set)) {
|
||||
error.SetErrorStringWithFormat("pthread_sigmask failed with error %d\n",
|
||||
ret);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
info.was_blocked = sigismember(&old_set, signo);
|
||||
if (sigaction(signo, &new_action, &info.old_action) == -1) {
|
||||
error.SetErrorToErrno();
|
||||
if (!info.was_blocked)
|
||||
pthread_sigmask(SIG_UNBLOCK, &new_action.sa_mask, nullptr);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
m_signals.insert({signo, info});
|
||||
g_signal_flags[signo] = 0;
|
||||
|
||||
return SignalHandleUP(new SignalHandle(*this, signo));
|
||||
}
|
||||
|
||||
void MainLoopPosix::UnregisterReadObject(IOObject::WaitableHandle handle) {
|
||||
bool erased = m_read_fds.erase(handle);
|
||||
UNUSED_IF_ASSERT_DISABLED(erased);
|
||||
assert(erased);
|
||||
}
|
||||
|
||||
void MainLoopPosix::UnregisterSignal(int signo) {
|
||||
// We undo the actions of RegisterSignal on a best-effort basis.
|
||||
auto it = m_signals.find(signo);
|
||||
assert(it != m_signals.end());
|
||||
|
||||
sigaction(signo, &it->second.old_action, nullptr);
|
||||
|
||||
sigset_t set;
|
||||
sigemptyset(&set);
|
||||
sigaddset(&set, signo);
|
||||
pthread_sigmask(it->second.was_blocked ? SIG_BLOCK : SIG_UNBLOCK, &set,
|
||||
nullptr);
|
||||
|
||||
m_signals.erase(it);
|
||||
}
|
||||
|
||||
Error MainLoopPosix::Run() {
|
||||
std::vector<int> signals;
|
||||
sigset_t sigmask;
|
||||
std::vector<int> read_fds;
|
||||
fd_set read_fd_set;
|
||||
m_terminate_request = false;
|
||||
|
||||
// run until termination or until we run out of things to listen to
|
||||
while (!m_terminate_request && (!m_read_fds.empty() || !m_signals.empty())) {
|
||||
// To avoid problems with callbacks changing the things we're supposed to
|
||||
// listen to, we
|
||||
// will store the *real* list of events separately.
|
||||
signals.clear();
|
||||
read_fds.clear();
|
||||
FD_ZERO(&read_fd_set);
|
||||
int nfds = 0;
|
||||
|
||||
if (int ret = pthread_sigmask(SIG_SETMASK, nullptr, &sigmask))
|
||||
return Error("pthread_sigmask failed with error %d\n", ret);
|
||||
|
||||
for (const auto &fd : m_read_fds) {
|
||||
read_fds.push_back(fd.first);
|
||||
FD_SET(fd.first, &read_fd_set);
|
||||
nfds = std::max(nfds, fd.first + 1);
|
||||
}
|
||||
|
||||
for (const auto &sig : m_signals) {
|
||||
signals.push_back(sig.first);
|
||||
sigdelset(&sigmask, sig.first);
|
||||
}
|
||||
|
||||
if (pselect(nfds, &read_fd_set, nullptr, nullptr, nullptr, &sigmask) ==
|
||||
-1 &&
|
||||
errno != EINTR)
|
||||
return Error(errno, eErrorTypePOSIX);
|
||||
|
||||
for (int sig : signals) {
|
||||
if (g_signal_flags[sig] == 0)
|
||||
continue; // No signal
|
||||
g_signal_flags[sig] = 0;
|
||||
|
||||
auto it = m_signals.find(sig);
|
||||
if (it == m_signals.end())
|
||||
continue; // Signal must have gotten unregistered in the meantime
|
||||
|
||||
it->second.callback(*this); // Do the work
|
||||
|
||||
if (m_terminate_request)
|
||||
return Error();
|
||||
}
|
||||
|
||||
for (int fd : read_fds) {
|
||||
if (!FD_ISSET(fd, &read_fd_set))
|
||||
continue; // Not ready
|
||||
|
||||
auto it = m_read_fds.find(fd);
|
||||
if (it == m_read_fds.end())
|
||||
continue; // File descriptor must have gotten unregistered in the
|
||||
// meantime
|
||||
|
||||
it->second(*this); // Do the work
|
||||
|
||||
if (m_terminate_request)
|
||||
return Error();
|
||||
}
|
||||
}
|
||||
return Error();
|
||||
}
|
@ -645,8 +645,8 @@ void CommandInterpreter::LoadCommandDictionary() {
|
||||
"gdb-remote [<hostname>:]<portnum>", 2, 0, false));
|
||||
if (connect_gdb_remote_cmd_ap.get()) {
|
||||
if (connect_gdb_remote_cmd_ap->AddRegexCommand(
|
||||
"^([^:]+:[[:digit:]]+)$",
|
||||
"process connect --plugin gdb-remote connect://%1") &&
|
||||
"^([^:]+|\\[[0-9a-fA-F:]+.*\\]):([0-9]+)$",
|
||||
"process connect --plugin gdb-remote connect://%1:%2") &&
|
||||
connect_gdb_remote_cmd_ap->AddRegexCommand(
|
||||
"^([[:digit:]]+)$",
|
||||
"process connect --plugin gdb-remote connect://localhost:%1")) {
|
||||
|
@ -37,7 +37,7 @@ void OptionValueEnumeration::DumpValue(const ExecutionContext *exe_ctx,
|
||||
const size_t count = m_enumerations.GetSize();
|
||||
for (size_t i = 0; i < count; ++i) {
|
||||
if (m_enumerations.GetValueAtIndexUnchecked(i).value == m_current_value) {
|
||||
strm.PutCString(m_enumerations.GetCStringAtIndex(i));
|
||||
strm.PutCString(m_enumerations.GetCStringAtIndex(i).GetStringRef());
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -58,8 +58,7 @@ Error OptionValueEnumeration::SetValueFromString(llvm::StringRef value,
|
||||
case eVarSetOperationAssign: {
|
||||
ConstString const_enumerator_name(value.trim());
|
||||
const EnumerationMapEntry *enumerator_entry =
|
||||
m_enumerations.FindFirstValueForName(
|
||||
const_enumerator_name.GetStringRef());
|
||||
m_enumerations.FindFirstValueForName(const_enumerator_name);
|
||||
if (enumerator_entry) {
|
||||
m_current_value = enumerator_entry->value.value;
|
||||
NotifyValueChanged();
|
||||
@ -69,10 +68,10 @@ Error OptionValueEnumeration::SetValueFromString(llvm::StringRef value,
|
||||
const size_t count = m_enumerations.GetSize();
|
||||
if (count) {
|
||||
error_strm.Printf(", valid values are: %s",
|
||||
m_enumerations.GetCStringAtIndex(0).str().c_str());
|
||||
m_enumerations.GetCStringAtIndex(0).GetCString());
|
||||
for (size_t i = 1; i < count; ++i) {
|
||||
error_strm.Printf(", %s",
|
||||
m_enumerations.GetCStringAtIndex(i).str().c_str());
|
||||
m_enumerations.GetCStringAtIndex(i).GetCString());
|
||||
}
|
||||
}
|
||||
error.SetErrorString(error_strm.GetString());
|
||||
@ -99,7 +98,7 @@ void OptionValueEnumeration::SetEnumerations(
|
||||
ConstString const_enumerator_name(enumerators[i].string_value);
|
||||
EnumeratorInfo enumerator_info = {enumerators[i].value,
|
||||
enumerators[i].usage};
|
||||
m_enumerations.Append(const_enumerator_name.GetStringRef(),
|
||||
m_enumerations.Append(const_enumerator_name,
|
||||
enumerator_info);
|
||||
}
|
||||
m_enumerations.Sort();
|
||||
@ -119,14 +118,14 @@ size_t OptionValueEnumeration::AutoComplete(
|
||||
const uint32_t num_enumerators = m_enumerations.GetSize();
|
||||
if (!s.empty()) {
|
||||
for (size_t i = 0; i < num_enumerators; ++i) {
|
||||
llvm::StringRef name = m_enumerations.GetCStringAtIndex(i);
|
||||
llvm::StringRef name = m_enumerations.GetCStringAtIndex(i).GetStringRef();
|
||||
if (name.startswith(s))
|
||||
matches.AppendString(name);
|
||||
}
|
||||
} else {
|
||||
// only suggest "true" or "false" by default
|
||||
for (size_t i = 0; i < num_enumerators; ++i)
|
||||
matches.AppendString(m_enumerations.GetCStringAtIndex(i));
|
||||
matches.AppendString(m_enumerations.GetCStringAtIndex(i).GetStringRef());
|
||||
}
|
||||
return matches.GetSize();
|
||||
}
|
||||
|
@ -59,7 +59,7 @@ void OptionValueProperties::Initialize(const PropertyDefinition *defs) {
|
||||
for (size_t i = 0; defs[i].name; ++i) {
|
||||
Property property(defs[i]);
|
||||
assert(property.IsValid());
|
||||
m_name_to_index.Append(property.GetName(), m_properties.size());
|
||||
m_name_to_index.Append(ConstString(property.GetName()), m_properties.size());
|
||||
property.GetValue()->SetParent(shared_from_this());
|
||||
m_properties.push_back(property);
|
||||
}
|
||||
@ -78,7 +78,7 @@ void OptionValueProperties::AppendProperty(const ConstString &name,
|
||||
bool is_global,
|
||||
const OptionValueSP &value_sp) {
|
||||
Property property(name, desc, is_global, value_sp);
|
||||
m_name_to_index.Append(name.GetStringRef(), m_properties.size());
|
||||
m_name_to_index.Append(name, m_properties.size());
|
||||
m_properties.push_back(property);
|
||||
value_sp->SetParent(shared_from_this());
|
||||
m_name_to_index.Sort();
|
||||
@ -108,7 +108,7 @@ OptionValueProperties::GetValueForKey(const ExecutionContext *exe_ctx,
|
||||
const ConstString &key,
|
||||
bool will_modify) const {
|
||||
lldb::OptionValueSP value_sp;
|
||||
size_t idx = m_name_to_index.Find(key.GetStringRef(), SIZE_MAX);
|
||||
size_t idx = m_name_to_index.Find(key, SIZE_MAX);
|
||||
if (idx < m_properties.size())
|
||||
value_sp = GetPropertyAtIndex(exe_ctx, will_modify, idx)->GetValue();
|
||||
return value_sp;
|
||||
@ -218,7 +218,7 @@ Error OptionValueProperties::SetSubValue(const ExecutionContext *exe_ctx,
|
||||
|
||||
uint32_t
|
||||
OptionValueProperties::GetPropertyIndex(const ConstString &name) const {
|
||||
return m_name_to_index.Find(name.GetStringRef(), SIZE_MAX);
|
||||
return m_name_to_index.Find(name, SIZE_MAX);
|
||||
}
|
||||
|
||||
const Property *
|
||||
@ -227,7 +227,7 @@ OptionValueProperties::GetProperty(const ExecutionContext *exe_ctx,
|
||||
const ConstString &name) const {
|
||||
return GetPropertyAtIndex(
|
||||
exe_ctx, will_modify,
|
||||
m_name_to_index.Find(name.GetStringRef(), SIZE_MAX));
|
||||
m_name_to_index.Find(name, SIZE_MAX));
|
||||
}
|
||||
|
||||
const Property *OptionValueProperties::GetPropertyAtIndex(
|
||||
|
@ -271,144 +271,6 @@ bool CPlusPlusLanguage::ExtractContextAndIdentifier(
|
||||
return false;
|
||||
}
|
||||
|
||||
class CPPRuntimeEquivalents {
|
||||
public:
|
||||
CPPRuntimeEquivalents() {
|
||||
m_impl.Append(ConstString("std::basic_string<char, std::char_traits<char>, "
|
||||
"std::allocator<char> >")
|
||||
.GetStringRef(),
|
||||
ConstString("basic_string<char>"));
|
||||
|
||||
// these two (with a prefixed std::) occur when c++stdlib string class
|
||||
// occurs as a template argument in some STL container
|
||||
m_impl.Append(ConstString("std::basic_string<char, std::char_traits<char>, "
|
||||
"std::allocator<char> >")
|
||||
.GetStringRef(),
|
||||
ConstString("std::basic_string<char>"));
|
||||
|
||||
m_impl.Sort();
|
||||
}
|
||||
|
||||
void Add(ConstString &type_name, ConstString &type_equivalent) {
|
||||
m_impl.Insert(type_name.GetStringRef(), type_equivalent);
|
||||
}
|
||||
|
||||
uint32_t FindExactMatches(ConstString &type_name,
|
||||
std::vector<ConstString> &equivalents) {
|
||||
uint32_t count = 0;
|
||||
|
||||
for (ImplData match =
|
||||
m_impl.FindFirstValueForName(type_name.GetStringRef());
|
||||
match != nullptr; match = m_impl.FindNextValueForName(match)) {
|
||||
equivalents.push_back(match->value);
|
||||
count++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
// partial matches can occur when a name with equivalents is a template
|
||||
// argument.
|
||||
// e.g. we may have "class Foo" be a match for "struct Bar". if we have a
|
||||
// typename
|
||||
// such as "class Templatized<class Foo, Anything>" we want this to be
|
||||
// replaced with
|
||||
// "class Templatized<struct Bar, Anything>". Since partial matching is time
|
||||
// consuming
|
||||
// once we get a partial match, we add it to the exact matches list for faster
|
||||
// retrieval
|
||||
uint32_t FindPartialMatches(ConstString &type_name,
|
||||
std::vector<ConstString> &equivalents) {
|
||||
uint32_t count = 0;
|
||||
|
||||
llvm::StringRef type_name_cstr = type_name.GetStringRef();
|
||||
|
||||
size_t items_count = m_impl.GetSize();
|
||||
|
||||
for (size_t item = 0; item < items_count; item++) {
|
||||
llvm::StringRef key_cstr = m_impl.GetCStringAtIndex(item);
|
||||
if (type_name_cstr.contains(key_cstr)) {
|
||||
count += AppendReplacements(type_name_cstr, key_cstr, equivalents);
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string &replace(std::string &target, std::string &pattern,
|
||||
std::string &with) {
|
||||
size_t pos;
|
||||
size_t pattern_len = pattern.size();
|
||||
|
||||
while ((pos = target.find(pattern)) != std::string::npos)
|
||||
target.replace(pos, pattern_len, with);
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
uint32_t AppendReplacements(llvm::StringRef original,
|
||||
llvm::StringRef matching_key,
|
||||
std::vector<ConstString> &equivalents) {
|
||||
std::string matching_key_str(matching_key);
|
||||
ConstString original_const(original);
|
||||
|
||||
uint32_t count = 0;
|
||||
|
||||
for (ImplData match = m_impl.FindFirstValueForName(matching_key);
|
||||
match != nullptr; match = m_impl.FindNextValueForName(match)) {
|
||||
std::string target(original);
|
||||
std::string equiv_class(match->value.AsCString());
|
||||
|
||||
replace(target, matching_key_str, equiv_class);
|
||||
|
||||
ConstString target_const(target.c_str());
|
||||
|
||||
// you will most probably want to leave this off since it might make this map
|
||||
// grow indefinitely
|
||||
#ifdef ENABLE_CPP_EQUIVALENTS_MAP_TO_GROW
|
||||
Add(original_const, target_const);
|
||||
#endif
|
||||
equivalents.push_back(target_const);
|
||||
|
||||
count++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
typedef UniqueCStringMap<ConstString> Impl;
|
||||
typedef const Impl::Entry *ImplData;
|
||||
Impl m_impl;
|
||||
};
|
||||
|
||||
static CPPRuntimeEquivalents &GetEquivalentsMap() {
|
||||
static CPPRuntimeEquivalents g_equivalents_map;
|
||||
return g_equivalents_map;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
CPlusPlusLanguage::FindEquivalentNames(ConstString type_name,
|
||||
std::vector<ConstString> &equivalents) {
|
||||
uint32_t count = GetEquivalentsMap().FindExactMatches(type_name, equivalents);
|
||||
|
||||
bool might_have_partials =
|
||||
(count == 0) // if we have a full name match just use it
|
||||
&& (strchr(type_name.AsCString(), '<') !=
|
||||
nullptr // we should only have partial matches when templates are
|
||||
// involved, check that we have
|
||||
&& strchr(type_name.AsCString(), '>') != nullptr); // angle brackets
|
||||
// in the type_name
|
||||
// before trying to
|
||||
// scan for partial
|
||||
// matches
|
||||
|
||||
if (might_have_partials)
|
||||
count = GetEquivalentsMap().FindPartialMatches(type_name, equivalents);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/// Given a mangled function `mangled`, replace all the primitive function type
|
||||
/// arguments of `search` with type `replace`.
|
||||
static ConstString SubsPrimitiveParmItanium(llvm::StringRef mangled,
|
||||
|
@ -119,18 +119,6 @@ public:
|
||||
llvm::StringRef &context,
|
||||
llvm::StringRef &identifier);
|
||||
|
||||
// in some cases, compilers will output different names for one same type.
|
||||
// when that happens, it might be impossible
|
||||
// to construct SBType objects for a valid type, because the name that is
|
||||
// available is not the same as the name that
|
||||
// can be used as a search key in FindTypes(). the equivalents map here is
|
||||
// meant to return possible alternative names
|
||||
// for a type through which a search can be conducted. Currently, this is only
|
||||
// enabled for C++ but can be extended
|
||||
// to ObjC or other languages if necessary
|
||||
static uint32_t FindEquivalentNames(ConstString type_name,
|
||||
std::vector<ConstString> &equivalents);
|
||||
|
||||
// Given a mangled function name, calculates some alternative manglings since
|
||||
// the compiler mangling may not line up with the symbol we are expecting
|
||||
static uint32_t
|
||||
|
@ -219,6 +219,7 @@ size_t lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::
|
||||
CalculateNumChildren() {
|
||||
static ConstString g___pair3_("__pair3_");
|
||||
static ConstString g___first_("__first_");
|
||||
static ConstString g___value_("__value_");
|
||||
|
||||
if (m_count != UINT32_MAX)
|
||||
return m_count;
|
||||
@ -227,7 +228,22 @@ size_t lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::
|
||||
ValueObjectSP m_item(m_tree->GetChildMemberWithName(g___pair3_, true));
|
||||
if (!m_item)
|
||||
return 0;
|
||||
m_item = m_item->GetChildMemberWithName(g___first_, true);
|
||||
|
||||
switch (m_item->GetCompilerType().GetNumDirectBaseClasses()) {
|
||||
case 1:
|
||||
// Assume a pre llvm r300140 __compressed_pair implementation:
|
||||
m_item = m_item->GetChildMemberWithName(g___first_, true);
|
||||
break;
|
||||
case 2: {
|
||||
// Assume a post llvm r300140 __compressed_pair implementation:
|
||||
ValueObjectSP first_elem_parent = m_item->GetChildAtIndex(0, true);
|
||||
m_item = first_elem_parent->GetChildMemberWithName(g___value_, true);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!m_item)
|
||||
return 0;
|
||||
m_count = m_item->GetValueAsUnsigned(0);
|
||||
|
@ -94,9 +94,30 @@ lldb::ValueObjectSP lldb_private::formatters::
|
||||
node_sp->GetChildMemberWithName(ConstString("__hash_"), true);
|
||||
if (!hash_sp || !value_sp) {
|
||||
if (!m_element_type) {
|
||||
auto first_sp = m_backend.GetChildAtNamePath({ConstString("__table_"),
|
||||
ConstString("__p1_"),
|
||||
ConstString("__first_")});
|
||||
auto p1_sp = m_backend.GetChildAtNamePath({ConstString("__table_"),
|
||||
ConstString("__p1_")});
|
||||
if (!p1_sp)
|
||||
return nullptr;
|
||||
|
||||
ValueObjectSP first_sp = nullptr;
|
||||
switch (p1_sp->GetCompilerType().GetNumDirectBaseClasses()) {
|
||||
case 1:
|
||||
// Assume a pre llvm r300140 __compressed_pair implementation:
|
||||
first_sp = p1_sp->GetChildMemberWithName(ConstString("__first_"),
|
||||
true);
|
||||
break;
|
||||
case 2: {
|
||||
// Assume a post llvm r300140 __compressed_pair implementation:
|
||||
ValueObjectSP first_elem_parent_sp =
|
||||
p1_sp->GetChildAtIndex(0, true);
|
||||
first_sp = p1_sp->GetChildMemberWithName(ConstString("__value_"),
|
||||
true);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!first_sp)
|
||||
return nullptr;
|
||||
m_element_type = first_sp->GetCompilerType();
|
||||
@ -152,22 +173,39 @@ bool lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::
|
||||
m_backend.GetChildMemberWithName(ConstString("__table_"), true);
|
||||
if (!table_sp)
|
||||
return false;
|
||||
ValueObjectSP num_elements_sp = table_sp->GetChildAtNamePath(
|
||||
{ConstString("__p2_"), ConstString("__first_")});
|
||||
|
||||
ValueObjectSP p2_sp = table_sp->GetChildMemberWithName(
|
||||
ConstString("__p2_"), true);
|
||||
ValueObjectSP num_elements_sp = nullptr;
|
||||
llvm::SmallVector<ConstString, 3> next_path;
|
||||
switch (p2_sp->GetCompilerType().GetNumDirectBaseClasses()) {
|
||||
case 1:
|
||||
// Assume a pre llvm r300140 __compressed_pair implementation:
|
||||
num_elements_sp = p2_sp->GetChildMemberWithName(
|
||||
ConstString("__first_"), true);
|
||||
next_path.append({ConstString("__p1_"), ConstString("__first_"),
|
||||
ConstString("__next_")});
|
||||
break;
|
||||
case 2: {
|
||||
// Assume a post llvm r300140 __compressed_pair implementation:
|
||||
ValueObjectSP first_elem_parent = p2_sp->GetChildAtIndex(0, true);
|
||||
num_elements_sp = first_elem_parent->GetChildMemberWithName(
|
||||
ConstString("__value_"), true);
|
||||
next_path.append({ConstString("__p1_"), ConstString("__value_"),
|
||||
ConstString("__next_")});
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!num_elements_sp)
|
||||
return false;
|
||||
m_num_elements = num_elements_sp->GetValueAsUnsigned(0);
|
||||
m_tree =
|
||||
table_sp
|
||||
->GetChildAtNamePath({ConstString("__p1_"), ConstString("__first_"),
|
||||
ConstString("__next_")})
|
||||
.get();
|
||||
m_tree = table_sp->GetChildAtNamePath(next_path).get();
|
||||
if (m_num_elements > 0)
|
||||
m_next_element =
|
||||
table_sp
|
||||
->GetChildAtNamePath({ConstString("__p1_"), ConstString("__first_"),
|
||||
ConstString("__next_")})
|
||||
.get();
|
||||
table_sp->GetChildAtNamePath(next_path).get();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -127,8 +127,25 @@ bool lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::Update() {
|
||||
m_backend.GetChildMemberWithName(ConstString("__end_cap_"), true));
|
||||
if (!data_type_finder_sp)
|
||||
return false;
|
||||
data_type_finder_sp = data_type_finder_sp->GetChildMemberWithName(
|
||||
|
||||
switch (data_type_finder_sp->GetCompilerType().GetNumDirectBaseClasses()) {
|
||||
case 1:
|
||||
// Assume a pre llvm r300140 __compressed_pair implementation:
|
||||
data_type_finder_sp = data_type_finder_sp->GetChildMemberWithName(
|
||||
ConstString("__first_"), true);
|
||||
break;
|
||||
case 2: {
|
||||
// Assume a post llvm r300140 __compressed_pair implementation:
|
||||
ValueObjectSP first_elem_parent_sp =
|
||||
data_type_finder_sp->GetChildAtIndex(0, true);
|
||||
data_type_finder_sp = first_elem_parent_sp->GetChildMemberWithName(
|
||||
ConstString("__value_"), true);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!data_type_finder_sp)
|
||||
return false;
|
||||
m_element_type = data_type_finder_sp->GetCompilerType().GetPointeeType();
|
||||
|
@ -355,9 +355,14 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
clang::IdentifierInfo **identifier_infos = selector_components.data();
|
||||
if (!identifier_infos) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
clang::Selector sel = ast_ctx.Selectors.getSelector(
|
||||
is_zero_argument ? 0 : selector_components.size(),
|
||||
selector_components.data());
|
||||
identifier_infos);
|
||||
|
||||
clang::QualType ret_type =
|
||||
ClangUtil::GetQualType(type_realizer_sp->RealizeType(
|
||||
|
@ -158,7 +158,7 @@ size_t ObjectContainerBSDArchive::Archive::ParseObjects() {
|
||||
size_t obj_idx = m_objects.size();
|
||||
m_objects.push_back(obj);
|
||||
// Insert all of the C strings out of order for now...
|
||||
m_object_name_to_index_map.Append(obj.ar_name.GetStringRef(), obj_idx);
|
||||
m_object_name_to_index_map.Append(obj.ar_name, obj_idx);
|
||||
offset += obj.ar_file_size;
|
||||
obj.Clear();
|
||||
} while (data.ValidOffset(offset));
|
||||
@ -174,8 +174,7 @@ ObjectContainerBSDArchive::Archive::FindObject(
|
||||
const ConstString &object_name,
|
||||
const llvm::sys::TimePoint<> &object_mod_time) {
|
||||
const ObjectNameToIndexMap::Entry *match =
|
||||
m_object_name_to_index_map.FindFirstValueForName(
|
||||
object_name.GetStringRef());
|
||||
m_object_name_to_index_map.FindFirstValueForName(object_name);
|
||||
if (match) {
|
||||
if (object_mod_time != llvm::sys::TimePoint<>()) {
|
||||
const uint64_t object_date = llvm::sys::toTimeT(object_mod_time);
|
||||
|
@ -1808,10 +1808,10 @@ DataExtractor ObjectFileELF::GetSegmentDataByIndex(lldb::user_id_t id) {
|
||||
segment_header->p_filesz);
|
||||
}
|
||||
|
||||
std::string
|
||||
llvm::StringRef
|
||||
ObjectFileELF::StripLinkerSymbolAnnotations(llvm::StringRef symbol_name) const {
|
||||
size_t pos = symbol_name.find('@');
|
||||
return symbol_name.substr(0, pos).str();
|
||||
return symbol_name.substr(0, pos);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
@ -2418,7 +2418,7 @@ unsigned ObjectFileELF::ParseSymbols(Symtab *symtab, user_id_t start_id,
|
||||
.emplace(sect_name.GetCString(),
|
||||
module_section_list->FindSectionByName(sect_name))
|
||||
.first;
|
||||
if (section_it->second && section_it->second->GetFileSize())
|
||||
if (section_it->second)
|
||||
symbol_section_sp = section_it->second;
|
||||
}
|
||||
|
||||
|
@ -152,7 +152,7 @@ public:
|
||||
// Returns segment data for the given index.
|
||||
lldb_private::DataExtractor GetSegmentDataByIndex(lldb::user_id_t id);
|
||||
|
||||
std::string
|
||||
llvm::StringRef
|
||||
StripLinkerSymbolAnnotations(llvm::StringRef symbol_name) const override;
|
||||
|
||||
private:
|
||||
|
@ -67,7 +67,7 @@ static Error DeleteForwardPortWithAdb(uint16_t local_port,
|
||||
|
||||
static Error FindUnusedPort(uint16_t &port) {
|
||||
Error error;
|
||||
std::unique_ptr<TCPSocket> tcp_socket(new TCPSocket(false, error));
|
||||
std::unique_ptr<TCPSocket> tcp_socket(new TCPSocket(true, false));
|
||||
if (error.Fail())
|
||||
return error;
|
||||
|
||||
|
@ -3900,10 +3900,9 @@ bool DWARFASTParserClang::CopyUniqueClassMethodTypes(
|
||||
if (src_name) {
|
||||
ConstString src_const_name(src_name);
|
||||
if (src_die.GetAttributeValueAsUnsigned(DW_AT_artificial, 0))
|
||||
src_name_to_die_artificial.Append(src_const_name.GetStringRef(),
|
||||
src_die);
|
||||
src_name_to_die_artificial.Append(src_const_name, src_die);
|
||||
else
|
||||
src_name_to_die.Append(src_const_name.GetStringRef(), src_die);
|
||||
src_name_to_die.Append(src_const_name, src_die);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3920,10 +3919,9 @@ bool DWARFASTParserClang::CopyUniqueClassMethodTypes(
|
||||
if (dst_name) {
|
||||
ConstString dst_const_name(dst_name);
|
||||
if (dst_die.GetAttributeValueAsUnsigned(DW_AT_artificial, 0))
|
||||
dst_name_to_die_artificial.Append(dst_const_name.GetStringRef(),
|
||||
dst_die);
|
||||
dst_name_to_die_artificial.Append(dst_const_name, dst_die);
|
||||
else
|
||||
dst_name_to_die.Append(dst_const_name.GetStringRef(), dst_die);
|
||||
dst_name_to_die.Append(dst_const_name, dst_die);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4036,7 +4034,7 @@ bool DWARFASTParserClang::CopyUniqueClassMethodTypes(
|
||||
src_name_to_die.Sort();
|
||||
|
||||
for (idx = 0; idx < dst_size; ++idx) {
|
||||
llvm::StringRef dst_name = dst_name_to_die.GetCStringAtIndex(idx);
|
||||
ConstString dst_name = dst_name_to_die.GetCStringAtIndex(idx);
|
||||
dst_die = dst_name_to_die.GetValueAtIndexUnchecked(idx);
|
||||
src_die = src_name_to_die.Find(dst_name, DWARFDIE());
|
||||
|
||||
@ -4091,7 +4089,7 @@ bool DWARFASTParserClang::CopyUniqueClassMethodTypes(
|
||||
dst_name_to_die_artificial.Sort();
|
||||
|
||||
for (idx = 0; idx < src_size_artificial; ++idx) {
|
||||
llvm::StringRef src_name_artificial =
|
||||
ConstString src_name_artificial =
|
||||
src_name_to_die_artificial.GetCStringAtIndex(idx);
|
||||
src_die = src_name_to_die_artificial.GetValueAtIndexUnchecked(idx);
|
||||
dst_die =
|
||||
@ -4135,13 +4133,13 @@ bool DWARFASTParserClang::CopyUniqueClassMethodTypes(
|
||||
|
||||
if (dst_size_artificial) {
|
||||
for (idx = 0; idx < dst_size_artificial; ++idx) {
|
||||
llvm::StringRef dst_name_artificial =
|
||||
ConstString dst_name_artificial =
|
||||
dst_name_to_die_artificial.GetCStringAtIndex(idx);
|
||||
dst_die = dst_name_to_die_artificial.GetValueAtIndexUnchecked(idx);
|
||||
if (log)
|
||||
log->Printf("warning: need to create artificial method for 0x%8.8x for "
|
||||
"method '%s'",
|
||||
dst_die.GetOffset(), dst_name_artificial.str().c_str());
|
||||
dst_die.GetOffset(), dst_name_artificial.GetCString());
|
||||
|
||||
failures.Append(dst_die);
|
||||
}
|
||||
|
@ -28,11 +28,11 @@ void NameToDIE::Finalize() {
|
||||
}
|
||||
|
||||
void NameToDIE::Insert(const ConstString &name, const DIERef &die_ref) {
|
||||
m_map.Append(name.GetStringRef(), die_ref);
|
||||
m_map.Append(name, die_ref);
|
||||
}
|
||||
|
||||
size_t NameToDIE::Find(const ConstString &name, DIEArray &info_array) const {
|
||||
return m_map.GetValues(name.GetStringRef(), info_array);
|
||||
return m_map.GetValues(name, info_array);
|
||||
}
|
||||
|
||||
size_t NameToDIE::Find(const RegularExpression ®ex,
|
||||
@ -55,15 +55,15 @@ size_t NameToDIE::FindAllEntriesForCompileUnit(dw_offset_t cu_offset,
|
||||
void NameToDIE::Dump(Stream *s) {
|
||||
const uint32_t size = m_map.GetSize();
|
||||
for (uint32_t i = 0; i < size; ++i) {
|
||||
llvm::StringRef cstr = m_map.GetCStringAtIndex(i);
|
||||
ConstString cstr = m_map.GetCStringAtIndex(i);
|
||||
const DIERef &die_ref = m_map.GetValueAtIndexUnchecked(i);
|
||||
s->Printf("%p: {0x%8.8x/0x%8.8x} \"%s\"\n", (const void *)cstr.data(),
|
||||
die_ref.cu_offset, die_ref.die_offset, cstr.str().c_str());
|
||||
s->Printf("%p: {0x%8.8x/0x%8.8x} \"%s\"\n", (const void *)cstr.GetCString(),
|
||||
die_ref.cu_offset, die_ref.die_offset, cstr.GetCString());
|
||||
}
|
||||
}
|
||||
|
||||
void NameToDIE::ForEach(
|
||||
std::function<bool(llvm::StringRef name, const DIERef &die_ref)> const
|
||||
std::function<bool(ConstString name, const DIERef &die_ref)> const
|
||||
&callback) const {
|
||||
const uint32_t size = m_map.GetSize();
|
||||
for (uint32_t i = 0; i < size; ++i) {
|
||||
|
@ -43,7 +43,8 @@ public:
|
||||
DIEArray &info_array) const;
|
||||
|
||||
void
|
||||
ForEach(std::function<bool(llvm::StringRef name, const DIERef &die_ref)> const
|
||||
ForEach(std::function<bool(lldb_private::ConstString name,
|
||||
const DIERef &die_ref)> const
|
||||
&callback) const;
|
||||
|
||||
protected:
|
||||
|
@ -1917,6 +1917,12 @@ uint32_t SymbolFileDWARF::ResolveSymbolContext(const FileSpec &file_spec,
|
||||
return sc_list.GetSize() - prev_size;
|
||||
}
|
||||
|
||||
void SymbolFileDWARF::PreloadSymbols() {
|
||||
std::lock_guard<std::recursive_mutex> guard(
|
||||
GetObjectFile()->GetModule()->GetMutex());
|
||||
Index();
|
||||
}
|
||||
|
||||
void SymbolFileDWARF::Index() {
|
||||
if (m_indexed)
|
||||
return;
|
||||
|
@ -226,6 +226,8 @@ public:
|
||||
const lldb_private::ConstString &name,
|
||||
const lldb_private::CompilerDeclContext *parent_decl_ctx) override;
|
||||
|
||||
void PreloadSymbols() override;
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// PluginInterface protocol
|
||||
//------------------------------------------------------------------
|
||||
|
@ -378,10 +378,9 @@ static void ParseLangArgs(LangOptions &Opts, InputKind IK, const char *triple) {
|
||||
// Set some properties which depend solely on the input kind; it would be nice
|
||||
// to move these to the language standard, and have the driver resolve the
|
||||
// input kind + language standard.
|
||||
if (IK == IK_Asm) {
|
||||
if (IK.getLanguage() == InputKind::Asm) {
|
||||
Opts.AsmPreprocessor = 1;
|
||||
} else if (IK == IK_ObjC || IK == IK_ObjCXX || IK == IK_PreprocessedObjC ||
|
||||
IK == IK_PreprocessedObjCXX) {
|
||||
} else if (IK.isObjectiveC()) {
|
||||
Opts.ObjC1 = Opts.ObjC2 = 1;
|
||||
}
|
||||
|
||||
@ -389,30 +388,24 @@ static void ParseLangArgs(LangOptions &Opts, InputKind IK, const char *triple) {
|
||||
|
||||
if (LangStd == LangStandard::lang_unspecified) {
|
||||
// Based on the base language, pick one.
|
||||
switch (IK) {
|
||||
case IK_None:
|
||||
case IK_AST:
|
||||
case IK_LLVM_IR:
|
||||
case IK_RenderScript:
|
||||
switch (IK.getLanguage()) {
|
||||
case InputKind::Unknown:
|
||||
case InputKind::LLVM_IR:
|
||||
case InputKind::RenderScript:
|
||||
llvm_unreachable("Invalid input kind!");
|
||||
case IK_OpenCL:
|
||||
LangStd = LangStandard::lang_opencl;
|
||||
case InputKind::OpenCL:
|
||||
LangStd = LangStandard::lang_opencl10;
|
||||
break;
|
||||
case IK_CUDA:
|
||||
case IK_PreprocessedCuda:
|
||||
case InputKind::CUDA:
|
||||
LangStd = LangStandard::lang_cuda;
|
||||
break;
|
||||
case IK_Asm:
|
||||
case IK_C:
|
||||
case IK_PreprocessedC:
|
||||
case IK_ObjC:
|
||||
case IK_PreprocessedObjC:
|
||||
case InputKind::Asm:
|
||||
case InputKind::C:
|
||||
case InputKind::ObjC:
|
||||
LangStd = LangStandard::lang_gnu99;
|
||||
break;
|
||||
case IK_CXX:
|
||||
case IK_PreprocessedCXX:
|
||||
case IK_ObjCXX:
|
||||
case IK_PreprocessedObjCXX:
|
||||
case InputKind::CXX:
|
||||
case InputKind::ObjCXX:
|
||||
LangStd = LangStandard::lang_gnucxx98;
|
||||
break;
|
||||
}
|
||||
@ -432,7 +425,7 @@ static void ParseLangArgs(LangOptions &Opts, InputKind IK, const char *triple) {
|
||||
Opts.WChar = true;
|
||||
|
||||
// OpenCL has some additional defaults.
|
||||
if (LangStd == LangStandard::lang_opencl) {
|
||||
if (LangStd == LangStandard::lang_opencl10) {
|
||||
Opts.OpenCL = 1;
|
||||
Opts.AltiVec = 1;
|
||||
Opts.CXXOperatorNames = 1;
|
||||
@ -784,8 +777,8 @@ IdentifierTable *ClangASTContext::getIdentifierTable() {
|
||||
LangOptions *ClangASTContext::getLanguageOptions() {
|
||||
if (m_language_options_ap.get() == nullptr) {
|
||||
m_language_options_ap.reset(new LangOptions());
|
||||
ParseLangArgs(*m_language_options_ap, IK_ObjCXX, GetTargetTriple());
|
||||
// InitializeLangOptions(*m_language_options_ap, IK_ObjCXX);
|
||||
ParseLangArgs(*m_language_options_ap, InputKind::ObjCXX, GetTargetTriple());
|
||||
// InitializeLangOptions(*m_language_options_ap, InputKind::ObjCXX);
|
||||
}
|
||||
return m_language_options_ap.get();
|
||||
}
|
||||
@ -961,75 +954,60 @@ ClangASTContext::GetBasicTypeEnumeration(const ConstString &name) {
|
||||
static llvm::once_flag g_once_flag;
|
||||
llvm::call_once(g_once_flag, []() {
|
||||
// "void"
|
||||
g_type_map.Append(ConstString("void").GetStringRef(), eBasicTypeVoid);
|
||||
g_type_map.Append(ConstString("void"), eBasicTypeVoid);
|
||||
|
||||
// "char"
|
||||
g_type_map.Append(ConstString("char").GetStringRef(), eBasicTypeChar);
|
||||
g_type_map.Append(ConstString("signed char").GetStringRef(),
|
||||
eBasicTypeSignedChar);
|
||||
g_type_map.Append(ConstString("unsigned char").GetStringRef(),
|
||||
eBasicTypeUnsignedChar);
|
||||
g_type_map.Append(ConstString("wchar_t").GetStringRef(), eBasicTypeWChar);
|
||||
g_type_map.Append(ConstString("signed wchar_t").GetStringRef(),
|
||||
eBasicTypeSignedWChar);
|
||||
g_type_map.Append(ConstString("unsigned wchar_t").GetStringRef(),
|
||||
g_type_map.Append(ConstString("char"), eBasicTypeChar);
|
||||
g_type_map.Append(ConstString("signed char"), eBasicTypeSignedChar);
|
||||
g_type_map.Append(ConstString("unsigned char"), eBasicTypeUnsignedChar);
|
||||
g_type_map.Append(ConstString("wchar_t"), eBasicTypeWChar);
|
||||
g_type_map.Append(ConstString("signed wchar_t"), eBasicTypeSignedWChar);
|
||||
g_type_map.Append(ConstString("unsigned wchar_t"),
|
||||
eBasicTypeUnsignedWChar);
|
||||
// "short"
|
||||
g_type_map.Append(ConstString("short").GetStringRef(), eBasicTypeShort);
|
||||
g_type_map.Append(ConstString("short int").GetStringRef(),
|
||||
eBasicTypeShort);
|
||||
g_type_map.Append(ConstString("unsigned short").GetStringRef(),
|
||||
eBasicTypeUnsignedShort);
|
||||
g_type_map.Append(ConstString("unsigned short int").GetStringRef(),
|
||||
g_type_map.Append(ConstString("short"), eBasicTypeShort);
|
||||
g_type_map.Append(ConstString("short int"), eBasicTypeShort);
|
||||
g_type_map.Append(ConstString("unsigned short"), eBasicTypeUnsignedShort);
|
||||
g_type_map.Append(ConstString("unsigned short int"),
|
||||
eBasicTypeUnsignedShort);
|
||||
|
||||
// "int"
|
||||
g_type_map.Append(ConstString("int").GetStringRef(), eBasicTypeInt);
|
||||
g_type_map.Append(ConstString("signed int").GetStringRef(),
|
||||
eBasicTypeInt);
|
||||
g_type_map.Append(ConstString("unsigned int").GetStringRef(),
|
||||
eBasicTypeUnsignedInt);
|
||||
g_type_map.Append(ConstString("unsigned").GetStringRef(),
|
||||
eBasicTypeUnsignedInt);
|
||||
g_type_map.Append(ConstString("int"), eBasicTypeInt);
|
||||
g_type_map.Append(ConstString("signed int"), eBasicTypeInt);
|
||||
g_type_map.Append(ConstString("unsigned int"), eBasicTypeUnsignedInt);
|
||||
g_type_map.Append(ConstString("unsigned"), eBasicTypeUnsignedInt);
|
||||
|
||||
// "long"
|
||||
g_type_map.Append(ConstString("long").GetStringRef(), eBasicTypeLong);
|
||||
g_type_map.Append(ConstString("long int").GetStringRef(), eBasicTypeLong);
|
||||
g_type_map.Append(ConstString("unsigned long").GetStringRef(),
|
||||
eBasicTypeUnsignedLong);
|
||||
g_type_map.Append(ConstString("unsigned long int").GetStringRef(),
|
||||
g_type_map.Append(ConstString("long"), eBasicTypeLong);
|
||||
g_type_map.Append(ConstString("long int"), eBasicTypeLong);
|
||||
g_type_map.Append(ConstString("unsigned long"), eBasicTypeUnsignedLong);
|
||||
g_type_map.Append(ConstString("unsigned long int"),
|
||||
eBasicTypeUnsignedLong);
|
||||
|
||||
// "long long"
|
||||
g_type_map.Append(ConstString("long long").GetStringRef(),
|
||||
eBasicTypeLongLong);
|
||||
g_type_map.Append(ConstString("long long int").GetStringRef(),
|
||||
eBasicTypeLongLong);
|
||||
g_type_map.Append(ConstString("unsigned long long").GetStringRef(),
|
||||
g_type_map.Append(ConstString("long long"), eBasicTypeLongLong);
|
||||
g_type_map.Append(ConstString("long long int"), eBasicTypeLongLong);
|
||||
g_type_map.Append(ConstString("unsigned long long"),
|
||||
eBasicTypeUnsignedLongLong);
|
||||
g_type_map.Append(ConstString("unsigned long long int").GetStringRef(),
|
||||
g_type_map.Append(ConstString("unsigned long long int"),
|
||||
eBasicTypeUnsignedLongLong);
|
||||
|
||||
// "int128"
|
||||
g_type_map.Append(ConstString("__int128_t").GetStringRef(),
|
||||
eBasicTypeInt128);
|
||||
g_type_map.Append(ConstString("__uint128_t").GetStringRef(),
|
||||
eBasicTypeUnsignedInt128);
|
||||
g_type_map.Append(ConstString("__int128_t"), eBasicTypeInt128);
|
||||
g_type_map.Append(ConstString("__uint128_t"), eBasicTypeUnsignedInt128);
|
||||
|
||||
// Miscellaneous
|
||||
g_type_map.Append(ConstString("bool").GetStringRef(), eBasicTypeBool);
|
||||
g_type_map.Append(ConstString("float").GetStringRef(), eBasicTypeFloat);
|
||||
g_type_map.Append(ConstString("double").GetStringRef(), eBasicTypeDouble);
|
||||
g_type_map.Append(ConstString("long double").GetStringRef(),
|
||||
eBasicTypeLongDouble);
|
||||
g_type_map.Append(ConstString("id").GetStringRef(), eBasicTypeObjCID);
|
||||
g_type_map.Append(ConstString("SEL").GetStringRef(), eBasicTypeObjCSel);
|
||||
g_type_map.Append(ConstString("nullptr").GetStringRef(),
|
||||
eBasicTypeNullPtr);
|
||||
g_type_map.Append(ConstString("bool"), eBasicTypeBool);
|
||||
g_type_map.Append(ConstString("float"), eBasicTypeFloat);
|
||||
g_type_map.Append(ConstString("double"), eBasicTypeDouble);
|
||||
g_type_map.Append(ConstString("long double"), eBasicTypeLongDouble);
|
||||
g_type_map.Append(ConstString("id"), eBasicTypeObjCID);
|
||||
g_type_map.Append(ConstString("SEL"), eBasicTypeObjCSel);
|
||||
g_type_map.Append(ConstString("nullptr"), eBasicTypeNullPtr);
|
||||
g_type_map.Sort();
|
||||
});
|
||||
|
||||
return g_type_map.Find(name.GetStringRef(), eBasicTypeInvalid);
|
||||
return g_type_map.Find(name, eBasicTypeInvalid);
|
||||
}
|
||||
return eBasicTypeInvalid;
|
||||
}
|
||||
|
@ -598,33 +598,32 @@ GoASTContext::GetBasicTypeEnumeration(lldb::opaque_compiler_type_t type) {
|
||||
static llvm::once_flag g_once_flag;
|
||||
llvm::call_once(g_once_flag, []() {
|
||||
// "void"
|
||||
g_type_map.Append(ConstString("void").GetStringRef(), eBasicTypeVoid);
|
||||
g_type_map.Append(ConstString("void"), eBasicTypeVoid);
|
||||
// "int"
|
||||
g_type_map.Append(ConstString("int").GetStringRef(), eBasicTypeInt);
|
||||
g_type_map.Append(ConstString("uint").GetStringRef(),
|
||||
eBasicTypeUnsignedInt);
|
||||
g_type_map.Append(ConstString("int"), eBasicTypeInt);
|
||||
g_type_map.Append(ConstString("uint"), eBasicTypeUnsignedInt);
|
||||
|
||||
// Miscellaneous
|
||||
g_type_map.Append(ConstString("bool").GetStringRef(), eBasicTypeBool);
|
||||
g_type_map.Append(ConstString("bool"), eBasicTypeBool);
|
||||
|
||||
// Others. Should these map to C types?
|
||||
g_type_map.Append(ConstString("byte").GetStringRef(), eBasicTypeOther);
|
||||
g_type_map.Append(ConstString("uint8").GetStringRef(), eBasicTypeOther);
|
||||
g_type_map.Append(ConstString("uint16").GetStringRef(), eBasicTypeOther);
|
||||
g_type_map.Append(ConstString("uint32").GetStringRef(), eBasicTypeOther);
|
||||
g_type_map.Append(ConstString("uint64").GetStringRef(), eBasicTypeOther);
|
||||
g_type_map.Append(ConstString("int8").GetStringRef(), eBasicTypeOther);
|
||||
g_type_map.Append(ConstString("int16").GetStringRef(), eBasicTypeOther);
|
||||
g_type_map.Append(ConstString("int32").GetStringRef(), eBasicTypeOther);
|
||||
g_type_map.Append(ConstString("int64").GetStringRef(), eBasicTypeOther);
|
||||
g_type_map.Append(ConstString("float32").GetStringRef(), eBasicTypeOther);
|
||||
g_type_map.Append(ConstString("float64").GetStringRef(), eBasicTypeOther);
|
||||
g_type_map.Append(ConstString("uintptr").GetStringRef(), eBasicTypeOther);
|
||||
g_type_map.Append(ConstString("byte"), eBasicTypeOther);
|
||||
g_type_map.Append(ConstString("uint8"), eBasicTypeOther);
|
||||
g_type_map.Append(ConstString("uint16"), eBasicTypeOther);
|
||||
g_type_map.Append(ConstString("uint32"), eBasicTypeOther);
|
||||
g_type_map.Append(ConstString("uint64"), eBasicTypeOther);
|
||||
g_type_map.Append(ConstString("int8"), eBasicTypeOther);
|
||||
g_type_map.Append(ConstString("int16"), eBasicTypeOther);
|
||||
g_type_map.Append(ConstString("int32"), eBasicTypeOther);
|
||||
g_type_map.Append(ConstString("int64"), eBasicTypeOther);
|
||||
g_type_map.Append(ConstString("float32"), eBasicTypeOther);
|
||||
g_type_map.Append(ConstString("float64"), eBasicTypeOther);
|
||||
g_type_map.Append(ConstString("uintptr"), eBasicTypeOther);
|
||||
|
||||
g_type_map.Sort();
|
||||
});
|
||||
|
||||
return g_type_map.Find(name.GetStringRef(), eBasicTypeInvalid);
|
||||
return g_type_map.Find(name, eBasicTypeInvalid);
|
||||
}
|
||||
return eBasicTypeInvalid;
|
||||
}
|
||||
|
@ -21,6 +21,10 @@
|
||||
|
||||
using namespace lldb_private;
|
||||
|
||||
void SymbolFile::PreloadSymbols() {
|
||||
// No-op for most implementations.
|
||||
}
|
||||
|
||||
SymbolFile *SymbolFile::FindPlugin(ObjectFile *obj_file) {
|
||||
std::unique_ptr<SymbolFile> best_symfile_ap;
|
||||
if (obj_file != nullptr) {
|
||||
|
@ -263,36 +263,35 @@ void Symtab::InitNameIndexes() {
|
||||
continue;
|
||||
|
||||
const Mangled &mangled = symbol->GetMangled();
|
||||
entry.cstring = mangled.GetMangledName().GetStringRef();
|
||||
if (!entry.cstring.empty()) {
|
||||
entry.cstring = mangled.GetMangledName();
|
||||
if (entry.cstring) {
|
||||
m_name_to_index.Append(entry);
|
||||
|
||||
if (symbol->ContainsLinkerAnnotations()) {
|
||||
// If the symbol has linker annotations, also add the version without
|
||||
// the annotations.
|
||||
entry.cstring = ConstString(m_objfile->StripLinkerSymbolAnnotations(
|
||||
entry.cstring))
|
||||
.GetStringRef();
|
||||
entry.cstring.GetStringRef()));
|
||||
m_name_to_index.Append(entry);
|
||||
}
|
||||
|
||||
const SymbolType symbol_type = symbol->GetType();
|
||||
if (symbol_type == eSymbolTypeCode ||
|
||||
symbol_type == eSymbolTypeResolver) {
|
||||
if (entry.cstring[0] == '_' && entry.cstring[1] == 'Z' &&
|
||||
(entry.cstring[2] != 'T' && // avoid virtual table, VTT structure,
|
||||
// typeinfo structure, and typeinfo
|
||||
// name
|
||||
entry.cstring[2] != 'G' && // avoid guard variables
|
||||
entry.cstring[2] != 'Z')) // named local entities (if we
|
||||
llvm::StringRef entry_ref(entry.cstring.GetStringRef());
|
||||
if (entry_ref[0] == '_' && entry_ref[1] == 'Z' &&
|
||||
(entry_ref[2] != 'T' && // avoid virtual table, VTT structure,
|
||||
// typeinfo structure, and typeinfo
|
||||
// name
|
||||
entry_ref[2] != 'G' && // avoid guard variables
|
||||
entry_ref[2] != 'Z')) // named local entities (if we
|
||||
// eventually handle eSymbolTypeData,
|
||||
// we will want this back)
|
||||
{
|
||||
CPlusPlusLanguage::MethodName cxx_method(
|
||||
mangled.GetDemangledName(lldb::eLanguageTypeC_plus_plus));
|
||||
entry.cstring =
|
||||
ConstString(cxx_method.GetBasename()).GetStringRef();
|
||||
if (!entry.cstring.empty()) {
|
||||
entry.cstring = ConstString(cxx_method.GetBasename());
|
||||
if (entry.cstring) {
|
||||
// ConstString objects permanently store the string in the pool so
|
||||
// calling
|
||||
// GetCString() on the value gets us a const char * that will
|
||||
@ -300,7 +299,8 @@ void Symtab::InitNameIndexes() {
|
||||
const char *const_context =
|
||||
ConstString(cxx_method.GetContext()).GetCString();
|
||||
|
||||
if (entry.cstring[0] == '~' ||
|
||||
entry_ref = entry.cstring.GetStringRef();
|
||||
if (entry_ref[0] == '~' ||
|
||||
!cxx_method.GetQualifiers().empty()) {
|
||||
// The first character of the demangled basename is '~' which
|
||||
// means we have a class destructor. We can use this information
|
||||
@ -341,17 +341,15 @@ void Symtab::InitNameIndexes() {
|
||||
}
|
||||
}
|
||||
|
||||
entry.cstring =
|
||||
mangled.GetDemangledName(symbol->GetLanguage()).GetStringRef();
|
||||
if (!entry.cstring.empty()) {
|
||||
entry.cstring = mangled.GetDemangledName(symbol->GetLanguage());
|
||||
if (entry.cstring) {
|
||||
m_name_to_index.Append(entry);
|
||||
|
||||
if (symbol->ContainsLinkerAnnotations()) {
|
||||
// If the symbol has linker annotations, also add the version without
|
||||
// the annotations.
|
||||
entry.cstring = ConstString(m_objfile->StripLinkerSymbolAnnotations(
|
||||
entry.cstring))
|
||||
.GetStringRef();
|
||||
entry.cstring.GetStringRef()));
|
||||
m_name_to_index.Append(entry);
|
||||
}
|
||||
}
|
||||
@ -359,15 +357,15 @@ void Symtab::InitNameIndexes() {
|
||||
// If the demangled name turns out to be an ObjC name, and
|
||||
// is a category name, add the version without categories to the index
|
||||
// too.
|
||||
ObjCLanguage::MethodName objc_method(entry.cstring, true);
|
||||
ObjCLanguage::MethodName objc_method(entry.cstring.GetStringRef(), true);
|
||||
if (objc_method.IsValid(true)) {
|
||||
entry.cstring = objc_method.GetSelector().GetStringRef();
|
||||
entry.cstring = objc_method.GetSelector();
|
||||
m_selector_to_index.Append(entry);
|
||||
|
||||
ConstString objc_method_no_category(
|
||||
objc_method.GetFullNameWithoutCategory(true));
|
||||
if (objc_method_no_category) {
|
||||
entry.cstring = objc_method_no_category.GetStringRef();
|
||||
entry.cstring = objc_method_no_category;
|
||||
m_name_to_index.Append(entry);
|
||||
}
|
||||
}
|
||||
@ -427,6 +425,11 @@ void Symtab::InitNameIndexes() {
|
||||
}
|
||||
}
|
||||
|
||||
void Symtab::PreloadSymbols() {
|
||||
std::lock_guard<std::recursive_mutex> guard(m_mutex);
|
||||
InitNameIndexes();
|
||||
}
|
||||
|
||||
void Symtab::AppendSymbolNamesToMap(const IndexCollection &indexes,
|
||||
bool add_demangled, bool add_mangled,
|
||||
NameToIndexMap &name_to_index_map) const {
|
||||
@ -444,15 +447,14 @@ void Symtab::AppendSymbolNamesToMap(const IndexCollection &indexes,
|
||||
|
||||
const Mangled &mangled = symbol->GetMangled();
|
||||
if (add_demangled) {
|
||||
entry.cstring =
|
||||
mangled.GetDemangledName(symbol->GetLanguage()).GetStringRef();
|
||||
if (!entry.cstring.empty())
|
||||
entry.cstring = mangled.GetDemangledName(symbol->GetLanguage());
|
||||
if (entry.cstring)
|
||||
name_to_index_map.Append(entry);
|
||||
}
|
||||
|
||||
if (add_mangled) {
|
||||
entry.cstring = mangled.GetMangledName().GetStringRef();
|
||||
if (!entry.cstring.empty())
|
||||
entry.cstring = mangled.GetMangledName();
|
||||
if (entry.cstring)
|
||||
name_to_index_map.Append(entry);
|
||||
}
|
||||
}
|
||||
@ -625,7 +627,7 @@ uint32_t Symtab::AppendSymbolIndexesWithName(const ConstString &symbol_name,
|
||||
if (!m_name_indexes_computed)
|
||||
InitNameIndexes();
|
||||
|
||||
return m_name_to_index.GetValues(symbol_name.GetStringRef(), indexes);
|
||||
return m_name_to_index.GetValues(symbol_name, indexes);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -644,7 +646,7 @@ uint32_t Symtab::AppendSymbolIndexesWithName(const ConstString &symbol_name,
|
||||
|
||||
std::vector<uint32_t> all_name_indexes;
|
||||
const size_t name_match_count =
|
||||
m_name_to_index.GetValues(symbol_name.GetStringRef(), all_name_indexes);
|
||||
m_name_to_index.GetValues(symbol_name, all_name_indexes);
|
||||
for (size_t i = 0; i < name_match_count; ++i) {
|
||||
if (CheckSymbolAtIndex(all_name_indexes[i], symbol_debug_type,
|
||||
symbol_visibility))
|
||||
@ -1068,8 +1070,6 @@ size_t Symtab::FindFunctionSymbols(const ConstString &name,
|
||||
size_t count = 0;
|
||||
std::vector<uint32_t> symbol_indexes;
|
||||
|
||||
llvm::StringRef name_cstr = name.GetStringRef();
|
||||
|
||||
// eFunctionNameTypeAuto should be pre-resolved by a call to
|
||||
// Module::LookupInfo::LookupInfo()
|
||||
assert((name_type_mask & eFunctionNameTypeAuto) == 0);
|
||||
@ -1107,7 +1107,7 @@ size_t Symtab::FindFunctionSymbols(const ConstString &name,
|
||||
|
||||
if (!m_basename_to_index.IsEmpty()) {
|
||||
const UniqueCStringMap<uint32_t>::Entry *match;
|
||||
for (match = m_basename_to_index.FindFirstValueForName(name_cstr);
|
||||
for (match = m_basename_to_index.FindFirstValueForName(name);
|
||||
match != nullptr;
|
||||
match = m_basename_to_index.FindNextValueForName(match)) {
|
||||
symbol_indexes.push_back(match->value);
|
||||
@ -1121,7 +1121,7 @@ size_t Symtab::FindFunctionSymbols(const ConstString &name,
|
||||
|
||||
if (!m_method_to_index.IsEmpty()) {
|
||||
const UniqueCStringMap<uint32_t>::Entry *match;
|
||||
for (match = m_method_to_index.FindFirstValueForName(name_cstr);
|
||||
for (match = m_method_to_index.FindFirstValueForName(name);
|
||||
match != nullptr;
|
||||
match = m_method_to_index.FindNextValueForName(match)) {
|
||||
symbol_indexes.push_back(match->value);
|
||||
@ -1135,7 +1135,7 @@ size_t Symtab::FindFunctionSymbols(const ConstString &name,
|
||||
|
||||
if (!m_selector_to_index.IsEmpty()) {
|
||||
const UniqueCStringMap<uint32_t>::Entry *match;
|
||||
for (match = m_selector_to_index.FindFirstValueForName(name_cstr);
|
||||
for (match = m_selector_to_index.FindFirstValueForName(name);
|
||||
match != nullptr;
|
||||
match = m_selector_to_index.FindNextValueForName(match)) {
|
||||
symbol_indexes.push_back(match->value);
|
||||
|
@ -1870,6 +1870,11 @@ ModuleSP Target::GetSharedModule(const ModuleSpec &module_spec,
|
||||
}
|
||||
}
|
||||
|
||||
// Preload symbols outside of any lock, so hopefully we can do this for
|
||||
// each library in parallel.
|
||||
if (GetPreloadSymbols())
|
||||
module_sp->PreloadSymbols();
|
||||
|
||||
if (old_module_sp &&
|
||||
m_images.GetIndexForModule(old_module_sp.get()) !=
|
||||
LLDB_INVALID_INDEX32) {
|
||||
@ -3277,6 +3282,8 @@ static PropertyDefinition g_properties[] = {
|
||||
{"detach-on-error", OptionValue::eTypeBoolean, false, true, nullptr,
|
||||
nullptr, "debugserver will detach (rather than killing) a process if it "
|
||||
"loses connection with lldb."},
|
||||
{"preload-symbols", OptionValue::eTypeBoolean, false, true, nullptr, nullptr,
|
||||
"Enable loading of symbol tables before they are needed."},
|
||||
{"disable-aslr", OptionValue::eTypeBoolean, false, true, nullptr, nullptr,
|
||||
"Disable Address Space Layout Randomization (ASLR)"},
|
||||
{"disable-stdio", OptionValue::eTypeBoolean, false, false, nullptr, nullptr,
|
||||
@ -3379,6 +3386,7 @@ enum {
|
||||
ePropertyOutputPath,
|
||||
ePropertyErrorPath,
|
||||
ePropertyDetachOnError,
|
||||
ePropertyPreloadSymbols,
|
||||
ePropertyDisableASLR,
|
||||
ePropertyDisableSTDIO,
|
||||
ePropertyInlineStrategy,
|
||||
@ -3641,6 +3649,17 @@ bool TargetProperties::SetPreferDynamicValue(lldb::DynamicValueType d) {
|
||||
return m_collection_sp->SetPropertyAtIndexAsEnumeration(nullptr, idx, d);
|
||||
}
|
||||
|
||||
bool TargetProperties::GetPreloadSymbols() const {
|
||||
const uint32_t idx = ePropertyPreloadSymbols;
|
||||
return m_collection_sp->GetPropertyAtIndexAsBoolean(
|
||||
nullptr, idx, g_properties[idx].default_uint_value != 0);
|
||||
}
|
||||
|
||||
void TargetProperties::SetPreloadSymbols(bool b) {
|
||||
const uint32_t idx = ePropertyPreloadSymbols;
|
||||
m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b);
|
||||
}
|
||||
|
||||
bool TargetProperties::GetDisableASLR() const {
|
||||
const uint32_t idx = ePropertyDisableASLR;
|
||||
return m_collection_sp->GetPropertyAtIndexAsBoolean(
|
||||
|
@ -38,14 +38,13 @@ public:
|
||||
|
||||
static StringPoolEntryType &
|
||||
GetStringMapEntryFromKeyData(const char *keyData) {
|
||||
char *ptr = const_cast<char *>(keyData) - sizeof(StringPoolEntryType);
|
||||
return *reinterpret_cast<StringPoolEntryType *>(ptr);
|
||||
return StringPoolEntryType::GetStringMapEntryFromKeyData(keyData);
|
||||
}
|
||||
|
||||
size_t GetConstCStringLength(const char *ccstr) const {
|
||||
static size_t GetConstCStringLength(const char *ccstr) {
|
||||
if (ccstr != nullptr) {
|
||||
const uint8_t h = hash(llvm::StringRef(ccstr));
|
||||
llvm::sys::SmartScopedReader<false> rlock(m_string_pools[h].m_mutex);
|
||||
// Since the entry is read only, and we derive the entry entirely from the
|
||||
// pointer, we don't need the lock.
|
||||
const StringPoolEntryType &entry = GetStringMapEntryFromKeyData(ccstr);
|
||||
return entry.getKey().size();
|
||||
}
|
||||
@ -218,10 +217,8 @@ bool ConstString::operator<(const ConstString &rhs) const {
|
||||
if (m_string == rhs.m_string)
|
||||
return false;
|
||||
|
||||
llvm::StringRef lhs_string_ref(m_string,
|
||||
StringPool().GetConstCStringLength(m_string));
|
||||
llvm::StringRef rhs_string_ref(
|
||||
rhs.m_string, StringPool().GetConstCStringLength(rhs.m_string));
|
||||
llvm::StringRef lhs_string_ref(GetStringRef());
|
||||
llvm::StringRef rhs_string_ref(rhs.GetStringRef());
|
||||
|
||||
// If both have valid C strings, then return the comparison
|
||||
if (lhs_string_ref.data() && rhs_string_ref.data())
|
||||
@ -240,7 +237,7 @@ Stream &lldb_private::operator<<(Stream &s, const ConstString &str) {
|
||||
}
|
||||
|
||||
size_t ConstString::GetLength() const {
|
||||
return StringPool().GetConstCStringLength(m_string);
|
||||
return Pool::GetConstCStringLength(m_string);
|
||||
}
|
||||
|
||||
bool ConstString::Equals(const ConstString &lhs, const ConstString &rhs,
|
||||
@ -255,10 +252,8 @@ bool ConstString::Equals(const ConstString &lhs, const ConstString &rhs,
|
||||
return false;
|
||||
|
||||
// perform case insensitive equality test
|
||||
llvm::StringRef lhs_string_ref(
|
||||
lhs.m_string, StringPool().GetConstCStringLength(lhs.m_string));
|
||||
llvm::StringRef rhs_string_ref(
|
||||
rhs.m_string, StringPool().GetConstCStringLength(rhs.m_string));
|
||||
llvm::StringRef lhs_string_ref(lhs.GetStringRef());
|
||||
llvm::StringRef rhs_string_ref(rhs.GetStringRef());
|
||||
return lhs_string_ref.equals_lower(rhs_string_ref);
|
||||
}
|
||||
|
||||
@ -270,10 +265,8 @@ int ConstString::Compare(const ConstString &lhs, const ConstString &rhs,
|
||||
if (lhs_cstr == rhs_cstr)
|
||||
return 0;
|
||||
if (lhs_cstr && rhs_cstr) {
|
||||
llvm::StringRef lhs_string_ref(
|
||||
lhs_cstr, StringPool().GetConstCStringLength(lhs_cstr));
|
||||
llvm::StringRef rhs_string_ref(
|
||||
rhs_cstr, StringPool().GetConstCStringLength(rhs_cstr));
|
||||
llvm::StringRef lhs_string_ref(lhs.GetStringRef());
|
||||
llvm::StringRef rhs_string_ref(rhs.GetStringRef());
|
||||
|
||||
if (case_sensitive) {
|
||||
return lhs_string_ref.compare(rhs_string_ref);
|
||||
|
@ -101,6 +101,7 @@
|
||||
AF48558D1D75127500D19C07 /* StdStringExtractor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF48558B1D75126800D19C07 /* StdStringExtractor.cpp */; };
|
||||
AFA3FCA11E39984900218D5E /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 49D404611E39260F00570CDC /* Foundation.framework */; };
|
||||
AFEC3364194A8B0B00FF05C6 /* Genealogy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AFEC3363194A8B0B00FF05C6 /* Genealogy.cpp */; };
|
||||
D6631CA91E848FE9006A7B11 /* SocketAddress.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D6631CA81E848FE9006A7B11 /* SocketAddress.cpp */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
@ -219,6 +220,7 @@
|
||||
AF67ABFF0D34604D0022D128 /* PseudoTerminal.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PseudoTerminal.cpp; sourceTree = "<group>"; };
|
||||
AF67AC000D34604D0022D128 /* PseudoTerminal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PseudoTerminal.h; sourceTree = "<group>"; };
|
||||
AFEC3363194A8B0B00FF05C6 /* Genealogy.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Genealogy.cpp; sourceTree = "<group>"; };
|
||||
D6631CA81E848FE9006A7B11 /* SocketAddress.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = SocketAddress.cpp; path = ../../source/Host/common/SocketAddress.cpp; sourceTree = "<group>"; };
|
||||
ED128B7918E1F163003F6A7B /* libpmenergy.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libpmenergy.dylib; path = usr/lib/libpmenergy.dylib; sourceTree = SDKROOT; };
|
||||
ED128B7A18E1F163003F6A7B /* libpmsample.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libpmsample.dylib; path = usr/lib/libpmsample.dylib; sourceTree = SDKROOT; };
|
||||
EF88788B0D9C7558001831DA /* com.apple.debugserver.applist.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = com.apple.debugserver.applist.plist; sourceTree = "<group>"; };
|
||||
@ -251,6 +253,7 @@
|
||||
08FB7794FE84155DC02AAC07 /* dbgnub */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D6631CA81E848FE9006A7B11 /* SocketAddress.cpp */,
|
||||
26ACA3330D3E94F200A2120B /* Framework */,
|
||||
26C637D50C71334A0024798E /* source */,
|
||||
1AB674ADFE9D54B511CA2CBB /* Products */,
|
||||
@ -577,6 +580,7 @@
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
D6631CA91E848FE9006A7B11 /* SocketAddress.cpp in Sources */,
|
||||
26CE05A7115C360D0022F371 /* DNBError.cpp in Sources */,
|
||||
26CE05A8115C36170022F371 /* DNBThreadResumeActions.cpp in Sources */,
|
||||
26CE05A9115C36250022F371 /* debugserver.cpp in Sources */,
|
||||
|
@ -62,6 +62,7 @@ set(lldbDebugserverCommonSources
|
||||
StdStringExtractor.cpp
|
||||
# JSON reader depends on the following LLDB-common files
|
||||
${LLDB_SOURCE_DIR}/source/Host/common/StringConvert.cpp
|
||||
${LLDB_SOURCE_DIR}/source/Host/common/SocketAddress.cpp
|
||||
# end JSON reader dependencies
|
||||
libdebugserver.cpp
|
||||
PseudoTerminal.cpp
|
||||
|
@ -17,10 +17,15 @@
|
||||
#include <arpa/inet.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <map>
|
||||
#include <netdb.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <sys/event.h>
|
||||
#include <termios.h>
|
||||
#include <vector>
|
||||
|
||||
#include "lldb/Host/SocketAddress.h"
|
||||
|
||||
#ifdef WITH_LOCKDOWN
|
||||
#include "lockdown.h"
|
||||
@ -66,176 +71,161 @@ rnb_err_t RNBSocket::Listen(const char *listen_host, uint16_t port,
|
||||
// Disconnect without saving errno
|
||||
Disconnect(false);
|
||||
|
||||
// Now figure out the hostname that will be attaching and palce it into
|
||||
struct sockaddr_in listen_addr;
|
||||
::memset(&listen_addr, 0, sizeof listen_addr);
|
||||
listen_addr.sin_len = sizeof listen_addr;
|
||||
listen_addr.sin_family = AF_INET;
|
||||
listen_addr.sin_port = htons(port);
|
||||
listen_addr.sin_addr.s_addr = INADDR_ANY;
|
||||
|
||||
if (!ResolveIPV4HostName(listen_host, listen_addr.sin_addr.s_addr)) {
|
||||
DNBLogThreaded("error: failed to resolve connecting host '%s'",
|
||||
listen_host);
|
||||
return rnb_err;
|
||||
}
|
||||
|
||||
DNBError err;
|
||||
int listen_fd = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
if (listen_fd == -1)
|
||||
err.SetError(errno, DNBError::POSIX);
|
||||
|
||||
if (err.Fail() || DNBLogCheckLogBit(LOG_RNB_COMM))
|
||||
err.LogThreaded("::socket ( domain = AF_INET, type = SOCK_STREAM, protocol "
|
||||
"= IPPROTO_TCP ) => socket = %i",
|
||||
listen_fd);
|
||||
|
||||
if (err.Fail())
|
||||
return rnb_err;
|
||||
|
||||
// enable local address reuse
|
||||
SetSocketOption(listen_fd, SOL_SOCKET, SO_REUSEADDR, 1);
|
||||
|
||||
struct sockaddr_in sa;
|
||||
::memset(&sa, 0, sizeof sa);
|
||||
sa.sin_len = sizeof sa;
|
||||
sa.sin_family = AF_INET;
|
||||
sa.sin_port = htons(port);
|
||||
sa.sin_addr.s_addr = INADDR_ANY; // Let incoming connections bind to any host
|
||||
// network interface (this is NOT who can
|
||||
// connect to us)
|
||||
int error = ::bind(listen_fd, (struct sockaddr *)&sa, sizeof(sa));
|
||||
if (error == -1)
|
||||
err.SetError(errno, DNBError::POSIX);
|
||||
|
||||
if (err.Fail() || DNBLogCheckLogBit(LOG_RNB_COMM))
|
||||
err.LogThreaded(
|
||||
"::bind ( socket = %i, (struct sockaddr *) &sa, sizeof(sa)) )",
|
||||
listen_fd);
|
||||
|
||||
if (err.Fail()) {
|
||||
ClosePort(listen_fd, false);
|
||||
int queue_id = kqueue();
|
||||
if (queue_id < 0) {
|
||||
err.SetError(errno, DNBError::MachKernel);
|
||||
err.LogThreaded("error: failed to create kqueue.");
|
||||
return rnb_err;
|
||||
}
|
||||
|
||||
error = ::listen(listen_fd, 5);
|
||||
if (error == -1)
|
||||
err.SetError(errno, DNBError::POSIX);
|
||||
std::map<int, lldb_private::SocketAddress> sockets;
|
||||
auto addresses = lldb_private::SocketAddress::GetAddressInfo(
|
||||
listen_host, NULL, AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP);
|
||||
|
||||
if (err.Fail() || DNBLogCheckLogBit(LOG_RNB_COMM))
|
||||
err.LogThreaded("::listen ( socket = %i, backlog = 1 )", listen_fd);
|
||||
for (auto address : addresses) {
|
||||
int sock_fd = ::socket(address.GetFamily(), SOCK_STREAM, IPPROTO_TCP);
|
||||
if (sock_fd == -1)
|
||||
continue;
|
||||
|
||||
if (err.Fail()) {
|
||||
ClosePort(listen_fd, false);
|
||||
return rnb_err;
|
||||
}
|
||||
SetSocketOption(sock_fd, SOL_SOCKET, SO_REUSEADDR, 1);
|
||||
|
||||
if (callback) {
|
||||
// We were asked to listen on port zero which means we
|
||||
// must now read the actual port that was given to us
|
||||
// as port zero is a special code for "find an open port
|
||||
// for me".
|
||||
if (port == 0) {
|
||||
socklen_t sa_len = sizeof(sa);
|
||||
if (getsockname(listen_fd, (struct sockaddr *)&sa, &sa_len) == 0) {
|
||||
port = ntohs(sa.sin_port);
|
||||
callback(callback_baton, port);
|
||||
}
|
||||
} else {
|
||||
callback(callback_baton, port);
|
||||
address.SetPort(port);
|
||||
|
||||
int error = ::bind(sock_fd, &address.sockaddr(), address.GetLength());
|
||||
if (error == -1) {
|
||||
ClosePort(sock_fd, false);
|
||||
continue;
|
||||
}
|
||||
|
||||
error = ::listen(sock_fd, 5);
|
||||
if (error == -1) {
|
||||
ClosePort(sock_fd, false);
|
||||
continue;
|
||||
}
|
||||
|
||||
// We were asked to listen on port zero which means we must now read the
|
||||
// actual port that was given to us as port zero is a special code for "find
|
||||
// an open port for me". This will only execute on the first socket created,
|
||||
// subesquent sockets will reuse this port number.
|
||||
if (port == 0) {
|
||||
socklen_t sa_len = address.GetLength();
|
||||
if (getsockname(sock_fd, &address.sockaddr(), &sa_len) == 0)
|
||||
port = address.GetPort();
|
||||
}
|
||||
|
||||
sockets[sock_fd] = address;
|
||||
}
|
||||
|
||||
struct sockaddr_in accept_addr;
|
||||
::memset(&accept_addr, 0, sizeof accept_addr);
|
||||
accept_addr.sin_len = sizeof accept_addr;
|
||||
if (sockets.size() == 0) {
|
||||
err.SetError(errno, DNBError::POSIX);
|
||||
err.LogThreaded("::listen or ::bind failed");
|
||||
return rnb_err;
|
||||
}
|
||||
|
||||
if (callback)
|
||||
callback(callback_baton, port);
|
||||
|
||||
std::vector<struct kevent> events;
|
||||
events.resize(sockets.size());
|
||||
int i = 0;
|
||||
for (auto socket : sockets) {
|
||||
EV_SET(&events[i++], socket.first, EVFILT_READ, EV_ADD, 0, 0, 0);
|
||||
}
|
||||
|
||||
bool accept_connection = false;
|
||||
|
||||
// Loop until we are happy with our connection
|
||||
while (!accept_connection) {
|
||||
socklen_t accept_addr_len = sizeof accept_addr;
|
||||
m_fd =
|
||||
::accept(listen_fd, (struct sockaddr *)&accept_addr, &accept_addr_len);
|
||||
|
||||
if (m_fd == -1)
|
||||
err.SetError(errno, DNBError::POSIX);
|
||||
struct kevent event_list[4];
|
||||
int num_events =
|
||||
kevent(queue_id, events.data(), events.size(), event_list, 4, NULL);
|
||||
|
||||
if (err.Fail() || DNBLogCheckLogBit(LOG_RNB_COMM))
|
||||
err.LogThreaded(
|
||||
"::accept ( socket = %i, address = %p, address_len = %u )", listen_fd,
|
||||
&accept_addr, accept_addr_len);
|
||||
if (num_events < 0) {
|
||||
err.SetError(errno, DNBError::MachKernel);
|
||||
err.LogThreaded("error: kevent() failed.");
|
||||
}
|
||||
|
||||
if (err.Fail())
|
||||
break;
|
||||
for (int i = 0; i < num_events; ++i) {
|
||||
auto sock_fd = event_list[i].ident;
|
||||
auto socket_pair = sockets.find(sock_fd);
|
||||
if (socket_pair == sockets.end())
|
||||
continue;
|
||||
|
||||
if (listen_addr.sin_addr.s_addr == INADDR_ANY)
|
||||
accept_connection = true;
|
||||
else {
|
||||
if (accept_addr_len == listen_addr.sin_len &&
|
||||
accept_addr.sin_addr.s_addr == listen_addr.sin_addr.s_addr) {
|
||||
lldb_private::SocketAddress &addr_in = socket_pair->second;
|
||||
lldb_private::SocketAddress accept_addr;
|
||||
socklen_t sa_len = accept_addr.GetMaxLength();
|
||||
m_fd = ::accept(sock_fd, &accept_addr.sockaddr(), &sa_len);
|
||||
|
||||
if (m_fd == -1) {
|
||||
err.SetError(errno, DNBError::POSIX);
|
||||
err.LogThreaded("error: Socket accept failed.");
|
||||
}
|
||||
|
||||
if (addr_in.IsAnyAddr())
|
||||
accept_connection = true;
|
||||
} else {
|
||||
::close(m_fd);
|
||||
m_fd = -1;
|
||||
const uint8_t *accept_ip =
|
||||
(const uint8_t *)&accept_addr.sin_addr.s_addr;
|
||||
const uint8_t *listen_ip =
|
||||
(const uint8_t *)&listen_addr.sin_addr.s_addr;
|
||||
::fprintf(stderr, "error: rejecting incoming connection from "
|
||||
"%u.%u.%u.%u (expecting %u.%u.%u.%u)\n",
|
||||
accept_ip[0], accept_ip[1], accept_ip[2], accept_ip[3],
|
||||
listen_ip[0], listen_ip[1], listen_ip[2], listen_ip[3]);
|
||||
DNBLogThreaded("error: rejecting connection from %u.%u.%u.%u "
|
||||
"(expecting %u.%u.%u.%u)",
|
||||
accept_ip[0], accept_ip[1], accept_ip[2], accept_ip[3],
|
||||
listen_ip[0], listen_ip[1], listen_ip[2], listen_ip[3]);
|
||||
else {
|
||||
if (accept_addr == addr_in)
|
||||
accept_connection = true;
|
||||
else {
|
||||
::close(m_fd);
|
||||
m_fd = -1;
|
||||
::fprintf(
|
||||
stderr,
|
||||
"error: rejecting incoming connection from %s (expecting %s)\n",
|
||||
accept_addr.GetIPAddress().c_str(),
|
||||
addr_in.GetIPAddress().c_str());
|
||||
DNBLogThreaded("error: rejecting connection from %s (expecting %s)\n",
|
||||
accept_addr.GetIPAddress().c_str(),
|
||||
addr_in.GetIPAddress().c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (err.Fail())
|
||||
break;
|
||||
}
|
||||
for (auto socket : sockets) {
|
||||
int ListenFd = socket.first;
|
||||
ClosePort(ListenFd, false);
|
||||
}
|
||||
|
||||
ClosePort(listen_fd, false);
|
||||
|
||||
if (err.Fail()) {
|
||||
if (err.Fail())
|
||||
return rnb_err;
|
||||
} else {
|
||||
// Keep our TCP packets coming without any delays.
|
||||
SetSocketOption(m_fd, IPPROTO_TCP, TCP_NODELAY, 1);
|
||||
}
|
||||
|
||||
// Keep our TCP packets coming without any delays.
|
||||
SetSocketOption(m_fd, IPPROTO_TCP, TCP_NODELAY, 1);
|
||||
|
||||
return rnb_success;
|
||||
}
|
||||
|
||||
rnb_err_t RNBSocket::Connect(const char *host, uint16_t port) {
|
||||
auto result = rnb_err;
|
||||
Disconnect(false);
|
||||
|
||||
// Create the socket
|
||||
m_fd = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
if (m_fd == -1)
|
||||
return rnb_err;
|
||||
auto addresses = lldb_private::SocketAddress::GetAddressInfo(
|
||||
host, NULL, AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP);
|
||||
|
||||
// Enable local address reuse
|
||||
SetSocketOption(m_fd, SOL_SOCKET, SO_REUSEADDR, 1);
|
||||
for (auto address : addresses) {
|
||||
m_fd = ::socket(address.GetFamily(), SOCK_STREAM, IPPROTO_TCP);
|
||||
if (m_fd == -1)
|
||||
continue;
|
||||
|
||||
struct sockaddr_in sa;
|
||||
::memset(&sa, 0, sizeof(sa));
|
||||
sa.sin_family = AF_INET;
|
||||
sa.sin_port = htons(port);
|
||||
// Enable local address reuse
|
||||
SetSocketOption(m_fd, SOL_SOCKET, SO_REUSEADDR, 1);
|
||||
|
||||
if (!ResolveIPV4HostName(host, sa.sin_addr.s_addr)) {
|
||||
DNBLogThreaded("error: failed to resolve host '%s'", host);
|
||||
Disconnect(false);
|
||||
return rnb_err;
|
||||
address.SetPort(port);
|
||||
|
||||
if (-1 == ::connect(m_fd, &address.sockaddr(), address.GetLength())) {
|
||||
Disconnect(false);
|
||||
continue;
|
||||
}
|
||||
SetSocketOption(m_fd, IPPROTO_TCP, TCP_NODELAY, 1);
|
||||
|
||||
result = rnb_success;
|
||||
break;
|
||||
}
|
||||
|
||||
if (-1 == ::connect(m_fd, (const struct sockaddr *)&sa, sizeof(sa))) {
|
||||
Disconnect(false);
|
||||
return rnb_err;
|
||||
}
|
||||
|
||||
// Keep our TCP packets coming without any delays.
|
||||
SetSocketOption(m_fd, IPPROTO_TCP, TCP_NODELAY, 1);
|
||||
return rnb_success;
|
||||
return result;
|
||||
}
|
||||
|
||||
rnb_err_t RNBSocket::useFD(int fd) {
|
||||
|
@ -1345,10 +1345,18 @@ int main(int argc, char *argv[]) {
|
||||
show_usage_and_exit(1);
|
||||
}
|
||||
// accept 'localhost:' prefix on port number
|
||||
|
||||
int items_scanned = ::sscanf(argv[0], "%[^:]:%i", str, &port);
|
||||
if (items_scanned == 2) {
|
||||
host = str;
|
||||
std::string host_specifier = argv[0];
|
||||
auto colon_location = host_specifier.rfind(':');
|
||||
if (colon_location != std::string::npos) {
|
||||
host = host_specifier.substr(0, colon_location);
|
||||
std::string port_str =
|
||||
host_specifier.substr(colon_location + 1, std::string::npos);
|
||||
char *end_ptr;
|
||||
port = strtoul(port_str.c_str(), &end_ptr, 0);
|
||||
if (end_ptr < port_str.c_str() + port_str.size())
|
||||
show_usage_and_exit(2);
|
||||
if (host.front() == '[' && host.back() == ']')
|
||||
host = host.substr(1, host.size() - 2);
|
||||
DNBLogDebug("host = '%s' port = %i", host.c_str(), port);
|
||||
} else {
|
||||
// No hostname means "localhost"
|
||||
|
@ -62,8 +62,7 @@ Error Acceptor::Listen(int backlog) {
|
||||
|
||||
Error Acceptor::Accept(const bool child_processes_inherit, Connection *&conn) {
|
||||
Socket *conn_socket = nullptr;
|
||||
auto error = m_listener_socket_up->Accept(
|
||||
StringRef(m_name), child_processes_inherit, conn_socket);
|
||||
auto error = m_listener_socket_up->Accept(conn_socket);
|
||||
if (error.Success())
|
||||
conn = new ConnectionFileDescriptor(conn_socket);
|
||||
|
||||
|
@ -44,8 +44,7 @@ protected:
|
||||
const char *listen_remote_address,
|
||||
bool child_processes_inherit, Socket **accept_socket,
|
||||
Error *error) {
|
||||
*error = listen_socket->Accept(listen_remote_address,
|
||||
child_processes_inherit, *accept_socket);
|
||||
*error = listen_socket->Accept(*accept_socket);
|
||||
}
|
||||
|
||||
template <typename SocketType>
|
||||
@ -56,7 +55,7 @@ protected:
|
||||
bool child_processes_inherit = false;
|
||||
Error error;
|
||||
std::unique_ptr<SocketType> listen_socket_up(
|
||||
new SocketType(child_processes_inherit, error));
|
||||
new SocketType(true, child_processes_inherit));
|
||||
EXPECT_FALSE(error.Fail());
|
||||
error = listen_socket_up->Listen(listen_remote_address, 5);
|
||||
EXPECT_FALSE(error.Fail());
|
||||
@ -70,7 +69,7 @@ protected:
|
||||
|
||||
std::string connect_remote_address = get_connect_addr(*listen_socket_up);
|
||||
std::unique_ptr<SocketType> connect_socket_up(
|
||||
new SocketType(child_processes_inherit, error));
|
||||
new SocketType(true, child_processes_inherit));
|
||||
EXPECT_FALSE(error.Fail());
|
||||
error = connect_socket_up->Connect(connect_remote_address);
|
||||
EXPECT_FALSE(error.Fail());
|
||||
@ -141,6 +140,20 @@ TEST_F(SocketTest, DecodeHostAndPort) {
|
||||
EXPECT_STREQ("65535", port_str.c_str());
|
||||
EXPECT_EQ(65535, port);
|
||||
EXPECT_TRUE(error.Success());
|
||||
|
||||
EXPECT_TRUE(
|
||||
Socket::DecodeHostAndPort("[::1]:12345", host_str, port_str, port, &error));
|
||||
EXPECT_STREQ("::1", host_str.c_str());
|
||||
EXPECT_STREQ("12345", port_str.c_str());
|
||||
EXPECT_EQ(12345, port);
|
||||
EXPECT_TRUE(error.Success());
|
||||
|
||||
EXPECT_TRUE(
|
||||
Socket::DecodeHostAndPort("[abcd:12fg:AF58::1]:12345", host_str, port_str, port, &error));
|
||||
EXPECT_STREQ("abcd:12fg:AF58::1", host_str.c_str());
|
||||
EXPECT_STREQ("12345", port_str.c_str());
|
||||
EXPECT_EQ(12345, port);
|
||||
EXPECT_TRUE(error.Success());
|
||||
}
|
||||
|
||||
#ifndef LLDB_DISABLE_POSIX
|
||||
|
@ -1,7 +1,17 @@
|
||||
add_lldb_unittest(ObjectFileELFTests
|
||||
TestELFHeader.cpp
|
||||
TestObjectFileELF.cpp
|
||||
|
||||
LINK_LIBS
|
||||
lldbPluginObjectFileELF
|
||||
lldbPluginSymbolVendorELF
|
||||
lldbCore
|
||||
)
|
||||
|
||||
add_dependencies(ObjectFileELFTests yaml2obj)
|
||||
add_definitions(-DYAML2OBJ="$<TARGET_FILE:yaml2obj>")
|
||||
|
||||
set(test_inputs
|
||||
sections-resolve-consistently.yaml
|
||||
)
|
||||
add_unittest_inputs(ObjectFileELFTests "${test_inputs}")
|
||||
|
@ -0,0 +1,50 @@
|
||||
--- !ELF
|
||||
FileHeader:
|
||||
Class: ELFCLASS64
|
||||
Data: ELFDATA2LSB
|
||||
Type: ET_EXEC
|
||||
Machine: EM_X86_64
|
||||
Entry: 0x0000000000400180
|
||||
Sections:
|
||||
- Name: .note.gnu.build-id
|
||||
Type: SHT_NOTE
|
||||
Flags: [ SHF_ALLOC ]
|
||||
Address: 0x0000000000400158
|
||||
AddressAlign: 0x0000000000000004
|
||||
Content: 040000001400000003000000474E55003F3EC29E3FD83E49D18C4D49CD8A730CC13117B6
|
||||
- Name: .text
|
||||
Type: SHT_PROGBITS
|
||||
Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
|
||||
Address: 0x0000000000400180
|
||||
AddressAlign: 0x0000000000000010
|
||||
Content: 554889E58B042500106000890425041060005DC3
|
||||
- Name: .data
|
||||
Type: SHT_PROGBITS
|
||||
Flags: [ SHF_WRITE, SHF_ALLOC ]
|
||||
Address: 0x0000000000601000
|
||||
AddressAlign: 0x0000000000000004
|
||||
Content: 2F000000
|
||||
- Name: .bss
|
||||
Type: SHT_NOBITS
|
||||
Flags: [ SHF_WRITE, SHF_ALLOC ]
|
||||
Address: 0x0000000000601004
|
||||
AddressAlign: 0x0000000000000004
|
||||
Size: 0x0000000000000004
|
||||
Symbols:
|
||||
Global:
|
||||
- Name: Y
|
||||
Type: STT_OBJECT
|
||||
Section: .data
|
||||
Value: 0x0000000000601000
|
||||
Size: 0x0000000000000004
|
||||
- Name: _start
|
||||
Type: STT_FUNC
|
||||
Section: .text
|
||||
Value: 0x0000000000400180
|
||||
Size: 0x0000000000000014
|
||||
- Name: X
|
||||
Type: STT_OBJECT
|
||||
Section: .bss
|
||||
Value: 0x0000000000601004
|
||||
Size: 0x0000000000000004
|
||||
...
|
105
unittests/ObjectFile/ELF/TestObjectFileELF.cpp
Normal file
105
unittests/ObjectFile/ELF/TestObjectFileELF.cpp
Normal file
@ -0,0 +1,105 @@
|
||||
//===-- TestObjectFileELF.cpp -----------------------------------*- C++ -*-===//
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "Plugins/ObjectFile/ELF/ObjectFileELF.h"
|
||||
#include "lldb/Core/Module.h"
|
||||
#include "lldb/Core/ModuleSpec.h"
|
||||
#include "lldb/Core/Section.h"
|
||||
#include "lldb/Host/HostInfo.h"
|
||||
#include "llvm/Support/FileUtilities.h"
|
||||
#include "llvm/Support/Path.h"
|
||||
#include "llvm/Support/Program.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "Plugins/SymbolVendor/ELF/SymbolVendorELF.h"
|
||||
|
||||
extern const char *TestMainArgv0;
|
||||
|
||||
using namespace lldb_private;
|
||||
using namespace lldb;
|
||||
|
||||
class ObjectFileELFTest : public testing::Test {
|
||||
public:
|
||||
void SetUp() override {
|
||||
HostInfo::Initialize();
|
||||
ObjectFileELF::Initialize();
|
||||
SymbolVendorELF::Initialize();
|
||||
|
||||
m_inputs_folder = llvm::sys::path::parent_path(TestMainArgv0);
|
||||
llvm::sys::path::append(m_inputs_folder, "Inputs");
|
||||
llvm::sys::fs::make_absolute(m_inputs_folder);
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
SymbolVendorELF::Terminate();
|
||||
ObjectFileELF::Terminate();
|
||||
HostInfo::Terminate();
|
||||
}
|
||||
|
||||
protected:
|
||||
llvm::SmallString<128> m_inputs_folder;
|
||||
};
|
||||
|
||||
#define ASSERT_NO_ERROR(x) \
|
||||
if (std::error_code ASSERT_NO_ERROR_ec = x) { \
|
||||
llvm::SmallString<128> MessageStorage; \
|
||||
llvm::raw_svector_ostream Message(MessageStorage); \
|
||||
Message << #x ": did not return errc::success.\n" \
|
||||
<< "error number: " << ASSERT_NO_ERROR_ec.value() << "\n" \
|
||||
<< "error message: " << ASSERT_NO_ERROR_ec.message() << "\n"; \
|
||||
GTEST_FATAL_FAILURE_(MessageStorage.c_str()); \
|
||||
} else { \
|
||||
}
|
||||
|
||||
TEST_F(ObjectFileELFTest, SectionsResolveConsistently) {
|
||||
llvm::SmallString<128> yaml = m_inputs_folder;
|
||||
llvm::sys::path::append(yaml, "sections-resolve-consistently.yaml");
|
||||
llvm::SmallString<128> obj = m_inputs_folder;
|
||||
ASSERT_NO_ERROR(llvm::sys::fs::createTemporaryFile(
|
||||
"sections-resolve-consistently-%%%%%%", "obj", obj));
|
||||
|
||||
llvm::FileRemover remover(obj);
|
||||
const char *args[] = {YAML2OBJ, yaml.c_str(), nullptr};
|
||||
llvm::StringRef obj_ref = obj;
|
||||
const llvm::StringRef *redirects[] = {nullptr, &obj_ref, nullptr};
|
||||
ASSERT_EQ(0, llvm::sys::ExecuteAndWait(YAML2OBJ, args, nullptr, redirects));
|
||||
uint64_t size;
|
||||
ASSERT_NO_ERROR(llvm::sys::fs::file_size(obj, size));
|
||||
ASSERT_GT(size, 0u);
|
||||
|
||||
ModuleSpec spec{FileSpec(obj, false)};
|
||||
spec.GetSymbolFileSpec().SetFile(obj, false);
|
||||
auto module_sp = std::make_shared<Module>(spec);
|
||||
SectionList *list = module_sp->GetSectionList();
|
||||
ASSERT_NE(nullptr, list);
|
||||
|
||||
auto bss_sp = list->FindSectionByName(ConstString(".bss"));
|
||||
ASSERT_NE(nullptr, bss_sp);
|
||||
auto data_sp = list->FindSectionByName(ConstString(".data"));
|
||||
ASSERT_NE(nullptr, data_sp);
|
||||
auto text_sp = list->FindSectionByName(ConstString(".text"));
|
||||
ASSERT_NE(nullptr, text_sp);
|
||||
|
||||
const Symbol *X = module_sp->FindFirstSymbolWithNameAndType(ConstString("X"),
|
||||
eSymbolTypeAny);
|
||||
ASSERT_NE(nullptr, X);
|
||||
EXPECT_EQ(bss_sp, X->GetAddress().GetSection());
|
||||
|
||||
const Symbol *Y = module_sp->FindFirstSymbolWithNameAndType(ConstString("Y"),
|
||||
eSymbolTypeAny);
|
||||
ASSERT_NE(nullptr, Y);
|
||||
EXPECT_EQ(data_sp, Y->GetAddress().GetSection());
|
||||
|
||||
const Symbol *start = module_sp->FindFirstSymbolWithNameAndType(
|
||||
ConstString("_start"), eSymbolTypeAny);
|
||||
ASSERT_NE(nullptr, start);
|
||||
EXPECT_EQ(text_sp, start->GetAddress().GetSection());
|
||||
}
|
@ -33,15 +33,14 @@ void GDBRemoteTest::TearDownTestCase() {
|
||||
void Connect(GDBRemoteCommunication &client, GDBRemoteCommunication &server) {
|
||||
bool child_processes_inherit = false;
|
||||
Error error;
|
||||
TCPSocket listen_socket(child_processes_inherit, error);
|
||||
TCPSocket listen_socket(true, child_processes_inherit);
|
||||
ASSERT_FALSE(error.Fail());
|
||||
error = listen_socket.Listen("127.0.0.1:0", 5);
|
||||
ASSERT_FALSE(error.Fail());
|
||||
|
||||
Socket *accept_socket;
|
||||
std::future<Error> accept_error = std::async(std::launch::async, [&] {
|
||||
return listen_socket.Accept("127.0.0.1:0", child_processes_inherit,
|
||||
accept_socket);
|
||||
return listen_socket.Accept(accept_socket);
|
||||
});
|
||||
|
||||
char connect_remote_address[64];
|
||||
|
@ -53,9 +53,21 @@ static void ServerCallbackv4(const void *baton, in_port_t port) {
|
||||
}
|
||||
|
||||
void TestSocketListen(const char *addr) {
|
||||
// Skip IPv6 tests if there isn't a valid interafce
|
||||
auto addresses = lldb_private::SocketAddress::GetAddressInfo(
|
||||
addr, NULL, AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP);
|
||||
if (addresses.size() == 0)
|
||||
return;
|
||||
|
||||
char addr_wrap[256];
|
||||
if (addresses.front().GetFamily() == AF_INET6)
|
||||
sprintf(addr_wrap, "[%s]", addr);
|
||||
else
|
||||
sprintf(addr_wrap, "%s", addr);
|
||||
|
||||
RNBSocket server_socket;
|
||||
auto result =
|
||||
server_socket.Listen(addr, 0, ServerCallbackv4, (const void *)addr);
|
||||
server_socket.Listen(addr, 0, ServerCallbackv4, (const void *)addr_wrap);
|
||||
ASSERT_TRUE(result == rnb_success);
|
||||
result = server_socket.Write(hello.c_str(), hello.length());
|
||||
ASSERT_TRUE(result == rnb_success);
|
||||
@ -71,9 +83,20 @@ void TestSocketListen(const char *addr) {
|
||||
|
||||
TEST(RNBSocket, LoopBackListenIPv4) { TestSocketListen("127.0.0.1"); }
|
||||
|
||||
TEST(RNBSocket, LoopBackListenIPv6) { TestSocketListen("::1"); }
|
||||
|
||||
void TestSocketConnect(const char *addr) {
|
||||
// Skip IPv6 tests if there isn't a valid interafce
|
||||
auto addresses = lldb_private::SocketAddress::GetAddressInfo(
|
||||
addr, NULL, AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP);
|
||||
if (addresses.size() == 0)
|
||||
return;
|
||||
|
||||
char addr_wrap[256];
|
||||
sprintf(addr_wrap, "%s:0", addr);
|
||||
if (addresses.front().GetFamily() == AF_INET6)
|
||||
sprintf(addr_wrap, "[%s]:0", addr);
|
||||
else
|
||||
sprintf(addr_wrap, "%s:0", addr);
|
||||
|
||||
Socket *server_socket;
|
||||
Predicate<uint16_t> port_predicate;
|
||||
@ -96,7 +119,7 @@ void TestSocketConnect(const char *addr) {
|
||||
ASSERT_EQ(bye, goodbye);
|
||||
} else {
|
||||
Socket *connected_socket;
|
||||
err = server_socket->Accept(addr_wrap, false, connected_socket);
|
||||
err = server_socket->Accept(connected_socket);
|
||||
if (err.Fail()) {
|
||||
llvm::errs() << err.AsCString();
|
||||
abort();
|
||||
@ -131,3 +154,5 @@ void TestSocketConnect(const char *addr) {
|
||||
}
|
||||
|
||||
TEST(RNBSocket, LoopBackConnectIPv4) { TestSocketConnect("127.0.0.1"); }
|
||||
|
||||
TEST(RNBSocket, LoopBackConnectIPv6) { TestSocketConnect("::1"); }
|
||||
|
Loading…
x
Reference in New Issue
Block a user