Vendor import of lldb trunk r301939:

https://llvm.org/svn/llvm-project/lldb/trunk@301939
This commit is contained in:
Dimitry Andric 2017-05-02 18:31:19 +00:00
parent 5060b64b7d
commit 773dd0e6e6
71 changed files with 1552 additions and 1049 deletions
CMakeLists.txt
cmake
include/lldb
lldb.xcodeproj
packages/Python/lldbsuite/test
lang/c/shared_lib
make
tools/lldb-mi/control
source
tools
debugserver
lldb-server
unittests

@ -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)

@ -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)

@ -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 &regex,
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
)

@ -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, &regex_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 &regex,
@ -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
...

@ -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"); }