Skip to content

Commit

Permalink
Support Unit Testing debugserver
Browse files Browse the repository at this point in the history
Summary:
This patch refactors the CMake build system's support for building debugserver to allow us to build the majority of debugserver's sources into the debugserverCommon library which can then be reused by unit tests.

The first unit test I've written tests debug server's ability to accept incoming connections from LLDB. The test forks the process, and one side creates a listening socket using debugserver's socket API, the other side creates a transmitting socket using LLDB's TCPSocket class.

I have no clue where to even start getting this connected into the LLDB Xcode project, so for now these tests are CMake-only.

Reviewers: zturner, labath, jasonmolenda

Subscribers: lldb-commits, mgorny

Differential Revision: https://reviews.llvm.org/D31357

llvm-svn: 300111
  • Loading branch information
Chris Bieneman committed Apr 12, 2017
1 parent 46afbbb commit efd065e
Show file tree
Hide file tree
Showing 6 changed files with 245 additions and 85 deletions.
87 changes: 69 additions & 18 deletions lldb/tools/debugserver/source/CMakeLists.txt
Expand Up @@ -2,12 +2,10 @@ include_directories(${CMAKE_CURRENT_BINARY_DIR}/..)
include_directories(${LLDB_SOURCE_DIR}/source)
include_directories(MacOSX/DarwinLog)

if (CMAKE_SYSTEM_NAME MATCHES "Darwin")
include_directories(MacOSX)
#include_directories(${CMAKE_CURRENT_BINARY_DIR}/MacOSX)
include_directories(MacOSX)
#include_directories(${CMAKE_CURRENT_BINARY_DIR}/MacOSX)

set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -stdlib=libc++ -Wl,-sectcreate,__TEXT,__info_plist,${CMAKE_CURRENT_SOURCE_DIR}/../resources/lldb-debugserver-Info.plist")
endif()
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -stdlib=libc++ -Wl,-sectcreate,__TEXT,__info_plist,${CMAKE_CURRENT_SOURCE_DIR}/../resources/lldb-debugserver-Info.plist")

check_cxx_compiler_flag("-Wno-gnu-zero-variadic-macro-arguments"
CXX_SUPPORTS_NO_GNU_ZERO_VARIADIC_MACRO_ARGUMENTS)
Expand All @@ -27,19 +25,31 @@ if (CXX_SUPPORTS_NO_EXTENDED_OFFSETOF)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-extended-offsetof")
endif ()

if (NOT CMAKE_SYSTEM_NAME MATCHES "Darwin")
add_definitions(
-DDEBUGSERVER_VERSION_STR="${LLDB_VERSION}"
)
endif ()
find_library(COCOA_LIBRARY Cocoa)
add_subdirectory(MacOSX)

if (CMAKE_SYSTEM_NAME MATCHES "Darwin")
find_library(COCOA_LIBRARY Cocoa)
add_subdirectory(MacOSX)
endif()
set(generated_mach_interfaces
${CMAKE_CURRENT_BINARY_DIR}/mach_exc.h
${CMAKE_CURRENT_BINARY_DIR}/mach_excServer.c
${CMAKE_CURRENT_BINARY_DIR}/mach_excUser.c
)
add_custom_command(OUTPUT ${generated_mach_interfaces}
COMMAND mig ${CMAKE_CURRENT_SOURCE_DIR}/MacOSX/dbgnub-mig.defs
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/MacOSX/dbgnub-mig.defs
)

add_lldb_library(lldbDebugserverCommon
debugserver.cpp
set(DEBUGSERVER_VERS_GENERATED_FILE ${CMAKE_CURRENT_BINARY_DIR}/debugserver_vers.c)
set_source_files_properties(${DEBUGSERVER_VERS_GENERATED_FILE} PROPERTIES GENERATED 1)

add_custom_command(OUTPUT ${DEBUGSERVER_VERS_GENERATED_FILE}
COMMAND ${LLDB_SOURCE_DIR}/scripts/generate-vers.pl
${LLDB_SOURCE_DIR}/lldb.xcodeproj/project.pbxproj debugserver
> ${DEBUGSERVER_VERS_GENERATED_FILE}
DEPENDS ${LLDB_SOURCE_DIR}/scripts/generate-vers.pl
${LLDB_SOURCE_DIR}/lldb.xcodeproj/project.pbxproj
)

set(lldbDebugserverCommonSources
DNBArch.cpp
DNBBreakpoint.cpp
DNB.cpp
Expand All @@ -63,12 +73,53 @@ add_lldb_library(lldbDebugserverCommon
RNBSocket.cpp
SysSignal.cpp
TTYState.cpp

MacOSX/CFBundle.cpp
MacOSX/CFString.cpp
MacOSX/Genealogy.cpp
MacOSX/MachException.cpp
MacOSX/MachProcess.mm
MacOSX/MachTask.mm
MacOSX/MachThread.cpp
MacOSX/MachThreadList.cpp
MacOSX/MachVMMemory.cpp
MacOSX/MachVMRegion.cpp
MacOSX/OsLogger.cpp
${generated_mach_interfaces}
${DEBUGSERVER_VERS_GENERATED_FILE})

add_library(lldbDebugserverCommon ${lldbDebugserverCommonSources})

target_link_libraries(lldbDebugserverCommon
INTERFACE ${COCOA_LIBRARY}
lldbDebugserverMacOSX_I386
lldbDebugserverMacOSX_X86_64
lldbDebugserverMacOSX_DarwinLog)

set(LLVM_OPTIONAL_SOURCES ${lldbDebugserverCommonSources})
add_lldb_tool(debugserver INCLUDE_IN_FRAMEWORK
debugserver.cpp

LINK_LIBS
lldbHost
${COCOA_LIBRARY}
lldbDebugserverCommon
)

set(LLDB_CODESIGN_IDENTITY "lldb_codesign"
CACHE STRING "Identity used for code signing. Set to empty string to skip the signing step.")
if (NOT ("${LLDB_CODESIGN_IDENTITY}" STREQUAL ""))
execute_process(
COMMAND xcrun -f codesign_allocate
OUTPUT_STRIP_TRAILING_WHITESPACE
OUTPUT_VARIABLE CODESIGN_ALLOCATE
)
add_custom_command(TARGET debugserver
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E env CODESIGN_ALLOCATE=${CODESIGN_ALLOCATE}
codesign --force --sign ${LLDB_CODESIGN_IDENTITY}
$<TARGET_FILE:debugserver>
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/bin
)
endif()



Expand Down
67 changes: 0 additions & 67 deletions lldb/tools/debugserver/source/MacOSX/CMakeLists.txt
Expand Up @@ -6,70 +6,3 @@ add_subdirectory(x86_64)
add_subdirectory(DarwinLog)

include_directories(..)

set(generated_mach_interfaces
${CMAKE_CURRENT_BINARY_DIR}/mach_exc.h
${CMAKE_CURRENT_BINARY_DIR}/mach_excServer.c
${CMAKE_CURRENT_BINARY_DIR}/mach_excUser.c
)
add_custom_command(OUTPUT ${generated_mach_interfaces}
COMMAND mig ${CMAKE_CURRENT_SOURCE_DIR}/dbgnub-mig.defs
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/dbgnub-mig.defs
)

set(DEBUGSERVER_VERS_GENERATED_FILE ${CMAKE_CURRENT_BINARY_DIR}/debugserver_vers.c)
set_source_files_properties(${DEBUGSERVER_VERS_GENERATED_FILE} PROPERTIES GENERATED 1)

add_custom_command(OUTPUT ${DEBUGSERVER_VERS_GENERATED_FILE}
COMMAND ${LLDB_SOURCE_DIR}/scripts/generate-vers.pl
${LLDB_SOURCE_DIR}/lldb.xcodeproj/project.pbxproj debugserver
> ${DEBUGSERVER_VERS_GENERATED_FILE}
DEPENDS ${LLDB_SOURCE_DIR}/scripts/generate-vers.pl
${LLDB_SOURCE_DIR}/lldb.xcodeproj/project.pbxproj
)

add_lldb_tool(debugserver INCLUDE_IN_FRAMEWORK
CFBundle.cpp
CFString.cpp
Genealogy.cpp
MachException.cpp
MachProcess.mm
MachTask.mm
MachThread.cpp
MachThreadList.cpp
MachVMMemory.cpp
MachVMRegion.cpp
OsLogger.cpp
${generated_mach_interfaces}
${DEBUGSERVER_VERS_GENERATED_FILE}

LINK_LIBS
lldbDebugserverCommon
lldbDebugserverMacOSX_I386
lldbDebugserverMacOSX_X86_64
lldbDebugserverMacOSX_DarwinLog
)

set_source_files_properties(
HasAVX.s
# Necessary since compilation will fail with stand-alone assembler
PROPERTIES LANGUAGE C COMPILE_FLAGS "-x assembler-with-cpp"
)

set(LLDB_CODESIGN_IDENTITY "lldb_codesign"
CACHE STRING "Identity used for code signing. Set to empty string to skip the signing step.")
if (NOT ("${LLDB_CODESIGN_IDENTITY}" STREQUAL ""))
execute_process(
COMMAND xcrun -f codesign_allocate
OUTPUT_STRIP_TRAILING_WHITESPACE
OUTPUT_VARIABLE CODESIGN_ALLOCATE
)
add_custom_command(TARGET debugserver
POST_BUILD
# Note: --entitlements option removed (see comment above).
COMMAND ${CMAKE_COMMAND} -E env CODESIGN_ALLOCATE=${CODESIGN_ALLOCATE}
codesign --force --sign ${LLDB_CODESIGN_IDENTITY}
$<TARGET_FILE:debugserver>
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/bin
)
endif()
4 changes: 4 additions & 0 deletions lldb/unittests/CMakeLists.txt
Expand Up @@ -70,3 +70,7 @@ add_subdirectory(SymbolFile)
add_subdirectory(Target)
add_subdirectory(UnwindAssembly)
add_subdirectory(Utility)

if(LLDB_CAN_USE_DEBUGSERVER)
add_subdirectory(debugserver)
endif()
19 changes: 19 additions & 0 deletions lldb/unittests/debugserver/CMakeLists.txt
@@ -0,0 +1,19 @@
# Note: debugserver is a Darwin-only implementation of a remote debugging
# server. It is not intended to be used on other platforms. The tests are here
# because using the LLDB Host API is convienent and allows testing of both parts
# of the debugserver communication path. If you are looking for a non-darwin
# remote debugging server, please use lldb-server.

include_directories(${LLDB_SOURCE_DIR}/tools/debugserver/source
${LLDB_SOURCE_DIR}/tools/debugserver/source/MacOSX)

add_lldb_unittest(debugserverTests
RNBSocketTest.cpp
debugserver_LogCallback.cpp

LINK_LIBS
lldbDebugserverCommon
lldbHost
LINK_COMPONENTS
Support
)
133 changes: 133 additions & 0 deletions lldb/unittests/debugserver/RNBSocketTest.cpp
@@ -0,0 +1,133 @@
//===-- RNBSocketTest.cpp ---------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "gtest/gtest.h"

#include <arpa/inet.h>
#include <sys/sysctl.h>
#include <unistd.h>

#include "RNBDefs.h"
#include "RNBSocket.h"
#include "lldb/Host/Socket.h"
#include "lldb/Host/StringConvert.h"
#include "lldb/Host/common/TCPSocket.h"

using namespace lldb_private;

std::string hello = "Hello, world!";
std::string goodbye = "Goodbye!";

static void ServerCallbackv4(const void *baton, in_port_t port) {
auto child_pid = fork();
if (child_pid == 0) {
Socket *client_socket;
char addr_buffer[256];
sprintf(addr_buffer, "%s:%d", baton, port);
Error err = Socket::TcpConnect(addr_buffer, false, client_socket);
if (err.Fail())
abort();
char buffer[32];
size_t read_size = 32;
err = client_socket->Read((void *)&buffer[0], read_size);
if (err.Fail())
abort();
std::string Recv(&buffer[0], read_size);
if (Recv != hello)
abort();
size_t write_size = goodbye.length();
err = client_socket->Write(goodbye.c_str(), write_size);
if (err.Fail())
abort();
if (write_size != goodbye.length())
abort();
delete client_socket;
exit(0);
}
}

void TestSocketListen(const char *addr) {
RNBSocket server_socket;
auto result =
server_socket.Listen(addr, 0, ServerCallbackv4, (const void *)addr);
ASSERT_TRUE(result == rnb_success);
result = server_socket.Write(hello.c_str(), hello.length());
ASSERT_TRUE(result == rnb_success);
std::string bye;
result = server_socket.Read(bye);
ASSERT_TRUE(result == rnb_success);
ASSERT_EQ(bye, goodbye);

int exit_status;
wait(&exit_status);
ASSERT_EQ(exit_status, 0);
}

TEST(RNBSocket, LoopBackListenIPv4) { TestSocketListen("127.0.0.1"); }

void TestSocketConnect(const char *addr) {
char addr_wrap[256];
sprintf(addr_wrap, "%s:0", addr);

Socket *server_socket;
Predicate<uint16_t> port_predicate;
port_predicate.SetValue(0, eBroadcastNever);
Error err =
Socket::TcpListen(addr_wrap, false, server_socket, &port_predicate);
ASSERT_FALSE(err.Fail());

auto port = ((TCPSocket *)server_socket)->GetLocalPortNumber();
auto child_pid = fork();
if (child_pid != 0) {
RNBSocket client_socket;
auto result = client_socket.Connect(addr, port);
ASSERT_TRUE(result == rnb_success);
result = client_socket.Write(hello.c_str(), hello.length());
ASSERT_TRUE(result == rnb_success);
std::string bye;
result = client_socket.Read(bye);
ASSERT_TRUE(result == rnb_success);
ASSERT_EQ(bye, goodbye);
} else {
Socket *connected_socket;
err = server_socket->Accept(addr_wrap, false, connected_socket);
if (err.Fail()) {
llvm::errs() << err.AsCString();
abort();
}
char buffer[32];
size_t read_size = 32;
err = connected_socket->Read((void *)&buffer[0], read_size);
if (err.Fail()) {
llvm::errs() << err.AsCString();
abort();
}
std::string Recv(&buffer[0], read_size);
if (Recv != hello) {
llvm::errs() << err.AsCString();
abort();
}
size_t write_size = goodbye.length();
err = connected_socket->Write(goodbye.c_str(), write_size);
if (err.Fail()) {
llvm::errs() << err.AsCString();
abort();
}
if (write_size != goodbye.length()) {
llvm::errs() << err.AsCString();
abort();
}
exit(0);
}
int exit_status;
wait(&exit_status);
ASSERT_EQ(exit_status, 0);
}

TEST(RNBSocket, LoopBackConnectIPv4) { TestSocketConnect("127.0.0.1"); }
20 changes: 20 additions & 0 deletions lldb/unittests/debugserver/debugserver_LogCallback.cpp
@@ -0,0 +1,20 @@
//===-- debugserver_LogCallback.cpp -----------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

//------------------------------------------------------------------------------
// this function is defined in debugserver.cpp, but is needed to link the
// debugserver Common library. It is for logging only, so it is left
// unimplemented here.
//------------------------------------------------------------------------------

#include <stdint.h>
#include <stdarg.h>

void FileLogCallback(void *baton, uint32_t flags, const char *format,
va_list args) {}

0 comments on commit efd065e

Please sign in to comment.