Create new platform: remote-android

* Create new platform plugin for lldb
* Create HostInfo class for android
* Create ProcessLauncher for android

Differential Revision: http://reviews.llvm.org/D7584

llvm-svn: 228943
This commit is contained in:
Tamas Berghammer 2015-02-12 18:13:44 +00:00
parent 97eac4089a
commit 00e305d281
20 changed files with 780 additions and 53 deletions

View File

@ -25,6 +25,7 @@ set( LLDB_USED_LIBS
lldbPluginObjectContainerMachOArchive
lldbPluginProcessGDBRemote
lldbPluginProcessUtility
lldbPluginPlatformAndroid
lldbPluginPlatformGDB
lldbPluginPlatformFreeBSD
lldbPluginPlatformKalimba

View File

@ -236,12 +236,16 @@ public:
GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &proc_info);
#if defined (__APPLE__) || defined (__linux__) || defined (__FreeBSD__) || defined (__GLIBC__) || defined (__NetBSD__)
#if !defined(__ANDROID__) && !defined(__ANDROID_NDK__)
static short GetPosixspawnFlags(const ProcessLaunchInfo &launch_info);
static Error LaunchProcessPosixSpawn(const char *exe_path, const ProcessLaunchInfo &launch_info, lldb::pid_t &pid);
static bool AddPosixSpawnFileAction(void *file_actions, const FileAction *info, Log *log, Error &error);
#endif
#endif // !defined(__ANDROID__) && !defined(__ANDROID_NDK__)
#endif // defined (__APPLE__) || defined (__linux__) || defined (__FreeBSD__) || defined (__GLIBC__) || defined(__NetBSD__)
static const lldb_private::UnixSignalsSP&
GetUnixSignals ();

View File

@ -38,8 +38,13 @@
#include "lldb/Host/windows/HostInfoWindows.h"
#define HOST_INFO_TYPE HostInfoWindows
#elif defined(__linux__)
#if defined(__ANDROID_NDK__)
#include "lldb/Host/android/HostInfoAndroid.h"
#define HOST_INFO_TYPE HostInfoAndroid
#else
#include "lldb/Host/linux/HostInfoLinux.h"
#define HOST_INFO_TYPE HostInfoLinux
#endif
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
#include "lldb/Host/freebsd/HostInfoFreeBSD.h"
#define HOST_INFO_TYPE HostInfoFreeBSD

View File

@ -0,0 +1,33 @@
//===-- HostInfoAndroid.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_android_HostInfoAndroid_h_
#define lldb_Host_android_HostInfoAndroid_h_
#include "lldb/Host/linux/HostInfoLinux.h"
namespace lldb_private
{
class HostInfoAndroid : public HostInfoLinux
{
friend class HostInfoBase;
private:
// Static class, unconstructable.
HostInfoAndroid();
~HostInfoAndroid();
protected:
static void ComputeHostArchitectureSupport(ArchSpec &arch_32, ArchSpec &arch_64);
};
} // end of namespace lldb_private
#endif // #ifndef lldb_Host_android_HostInfoAndroid_h_

View File

@ -0,0 +1,26 @@
//===-- ProcessLauncherAndroid.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_android_ProcessLauncherAndroid_h_
#define lldb_Host_android_ProcessLauncherAndroid_h_
#include "lldb/Host/ProcessLauncher.h"
namespace lldb_private
{
class ProcessLauncherAndroid : public ProcessLauncher
{
public:
virtual HostProcess LaunchProcess(const ProcessLaunchInfo &launch_info, Error &error);
};
} // end of namespace lldb_private
#endif

View File

@ -740,6 +740,10 @@
6D55B2901A8A806200A70529 /* GDBRemoteCommunicationServerCommon.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D55B28D1A8A806200A70529 /* GDBRemoteCommunicationServerCommon.cpp */; };
6D55B2911A8A806200A70529 /* GDBRemoteCommunicationServerLLGS.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D55B28E1A8A806200A70529 /* GDBRemoteCommunicationServerLLGS.cpp */; };
6D55B2921A8A806200A70529 /* GDBRemoteCommunicationServerPlatform.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D55B28F1A8A806200A70529 /* GDBRemoteCommunicationServerPlatform.cpp */; };
6D55BAED1A8CD0A800A70529 /* PlatformAndroid.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D55BAE91A8CD08C00A70529 /* PlatformAndroid.cpp */; };
6D55BAEE1A8CD0B200A70529 /* PlatformAndroidRemoteGDBServer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D55BAEB1A8CD08C00A70529 /* PlatformAndroidRemoteGDBServer.cpp */; };
6D55BAEF1A8CD0B700A70529 /* PlatformAndroid.h in Headers */ = {isa = PBXBuildFile; fileRef = 6D55BAEA1A8CD08C00A70529 /* PlatformAndroid.h */; };
6D55BAF01A8CD0BD00A70529 /* PlatformAndroidRemoteGDBServer.h in Headers */ = {isa = PBXBuildFile; fileRef = 6D55BAEC1A8CD08C00A70529 /* PlatformAndroidRemoteGDBServer.h */; };
8C2D6A53197A1EAF006989C9 /* MemoryHistory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8C2D6A52197A1EAF006989C9 /* MemoryHistory.cpp */; };
8C2D6A5E197A250F006989C9 /* MemoryHistoryASan.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8C2D6A5A197A1FDC006989C9 /* MemoryHistoryASan.cpp */; };
8CCB017E19BA28A80009FD44 /* ThreadCollection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CCB017A19BA283D0009FD44 /* ThreadCollection.cpp */; };
@ -2357,6 +2361,16 @@
6D55B2931A8A808400A70529 /* GDBRemoteCommunicationServerCommon.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GDBRemoteCommunicationServerCommon.h; sourceTree = "<group>"; };
6D55B2941A8A808400A70529 /* GDBRemoteCommunicationServerLLGS.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GDBRemoteCommunicationServerLLGS.h; sourceTree = "<group>"; };
6D55B2951A8A808400A70529 /* GDBRemoteCommunicationServerPlatform.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GDBRemoteCommunicationServerPlatform.h; sourceTree = "<group>"; };
6D55BAE01A8CD03D00A70529 /* HostInfoAndroid.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = HostInfoAndroid.cpp; path = source/Host/android/HostInfoAndroid.cpp; sourceTree = "<group>"; };
6D55BAE11A8CD03D00A70529 /* ProcessLauncherAndroid.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = ProcessLauncherAndroid.cpp; path = source/Host/android/ProcessLauncherAndroid.cpp; sourceTree = "<group>"; };
6D55BAE21A8CD06000A70529 /* Android.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Android.h; path = include/lldb/Host/android/Android.h; sourceTree = "<group>"; };
6D55BAE31A8CD06000A70529 /* Config.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Config.h; path = include/lldb/Host/android/Config.h; sourceTree = "<group>"; };
6D55BAE41A8CD06000A70529 /* HostInfoAndroid.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = HostInfoAndroid.h; path = include/lldb/Host/android/HostInfoAndroid.h; sourceTree = "<group>"; };
6D55BAE51A8CD06000A70529 /* ProcessLauncherAndroid.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ProcessLauncherAndroid.h; path = include/lldb/Host/android/ProcessLauncherAndroid.h; sourceTree = "<group>"; };
6D55BAE91A8CD08C00A70529 /* PlatformAndroid.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = PlatformAndroid.cpp; sourceTree = "<group>"; };
6D55BAEA1A8CD08C00A70529 /* PlatformAndroid.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PlatformAndroid.h; sourceTree = "<group>"; };
6D55BAEB1A8CD08C00A70529 /* PlatformAndroidRemoteGDBServer.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = PlatformAndroidRemoteGDBServer.cpp; sourceTree = "<group>"; };
6D55BAEC1A8CD08C00A70529 /* PlatformAndroidRemoteGDBServer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PlatformAndroidRemoteGDBServer.h; sourceTree = "<group>"; };
8C2D6A52197A1EAF006989C9 /* MemoryHistory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MemoryHistory.cpp; path = source/Target/MemoryHistory.cpp; sourceTree = "<group>"; };
8C2D6A54197A1EBE006989C9 /* MemoryHistory.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = MemoryHistory.h; path = include/lldb/Target/MemoryHistory.h; sourceTree = "<group>"; };
8C2D6A5A197A1FDC006989C9 /* MemoryHistoryASan.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MemoryHistoryASan.cpp; sourceTree = "<group>"; };
@ -4255,6 +4269,7 @@
26BC7DD010F1B7C100F91463 /* Host */ = {
isa = PBXGroup;
children = (
6D55B29B1A8CCFF000A70529 /* android */,
33E5E8451A6736D30024ED68 /* StringConvert.h */,
69A01E1A1236C5D400C660B5 /* common */,
3FDFE53919A29399009756A7 /* freebsd */,
@ -4563,6 +4578,7 @@
26C5577E132575B6008FD8FE /* Platform */ = {
isa = PBXGroup;
children = (
6D55BAE61A8CD08C00A70529 /* Android */,
2694E99814FC0BB30076DE67 /* FreeBSD */,
264A97BC133918A30017F0BE /* GDB Server */,
23042D0F1976C9D800621B2C /* Kalimba */,
@ -4930,6 +4946,30 @@
path = source/Host/common;
sourceTree = "<group>";
};
6D55B29B1A8CCFF000A70529 /* android */ = {
isa = PBXGroup;
children = (
6D55BAE21A8CD06000A70529 /* Android.h */,
6D55BAE31A8CD06000A70529 /* Config.h */,
6D55BAE41A8CD06000A70529 /* HostInfoAndroid.h */,
6D55BAE51A8CD06000A70529 /* ProcessLauncherAndroid.h */,
6D55BAE01A8CD03D00A70529 /* HostInfoAndroid.cpp */,
6D55BAE11A8CD03D00A70529 /* ProcessLauncherAndroid.cpp */,
);
name = android;
sourceTree = "<group>";
};
6D55BAE61A8CD08C00A70529 /* Android */ = {
isa = PBXGroup;
children = (
6D55BAE91A8CD08C00A70529 /* PlatformAndroid.cpp */,
6D55BAEA1A8CD08C00A70529 /* PlatformAndroid.h */,
6D55BAEB1A8CD08C00A70529 /* PlatformAndroidRemoteGDBServer.cpp */,
6D55BAEC1A8CD08C00A70529 /* PlatformAndroidRemoteGDBServer.h */,
);
path = Android;
sourceTree = "<group>";
};
8C2D6A58197A1FB9006989C9 /* MemoryHistory */ = {
isa = PBXGroup;
children = (
@ -5232,6 +5272,7 @@
260CC63415D04377002BF2E0 /* OptionValueFileSpec.h in Headers */,
26CFDCA11861638D000E63E5 /* Editline.h in Headers */,
26BC17B018C7F4CB00D2196D /* RegisterContextPOSIXCore_x86_64.h in Headers */,
6D55BAF01A8CD0BD00A70529 /* PlatformAndroidRemoteGDBServer.h in Headers */,
AF9B8F34182DB52900DA866F /* SystemRuntimeMacOSX.h in Headers */,
26474CB518D0CB180073DEBA /* RegisterContextLinux_x86_64.h in Headers */,
26D1804716CEE12C00EDFB5B /* TimeSpecTimeout.h in Headers */,
@ -5247,6 +5288,7 @@
26D1804516CEE12500EDFB5B /* KQueue.h in Headers */,
AF77E0A21A033D360096C0EA /* RegisterContextFreeBSD_powerpc.h in Headers */,
260CC63715D04377002BF2E0 /* OptionValueSInt64.h in Headers */,
6D55BAEF1A8CD0B700A70529 /* PlatformAndroid.h in Headers */,
AF061F8C182C980000B6A19C /* HistoryUnwind.h in Headers */,
264A58EC1A7DBC8C00A6B1B0 /* OptionValueFormatEntity.h in Headers */,
260CC63815D04377002BF2E0 /* OptionValueString.h in Headers */,
@ -5879,6 +5921,7 @@
2689003713353E0400698AC0 /* DataBufferMemoryMap.cpp in Sources */,
2689003813353E0400698AC0 /* DataExtractor.cpp in Sources */,
2689003913353E0400698AC0 /* Debugger.cpp in Sources */,
6D55BAEE1A8CD0B200A70529 /* PlatformAndroidRemoteGDBServer.cpp in Sources */,
2689003A13353E0400698AC0 /* Disassembler.cpp in Sources */,
236124A51986B4E2004EFC37 /* Socket.cpp in Sources */,
3FDFDDBF199D345E009756A7 /* FileCache.cpp in Sources */,
@ -6082,6 +6125,7 @@
268900F013353E6F00698AC0 /* Process.cpp in Sources */,
26BC17AD18C7F4CB00D2196D /* RegisterContextPOSIXCore_mips64.cpp in Sources */,
268900F113353E6F00698AC0 /* RegisterContext.cpp in Sources */,
6D55BAED1A8CD0A800A70529 /* PlatformAndroid.cpp in Sources */,
268900F213353E6F00698AC0 /* SectionLoadList.cpp in Sources */,
942AFF0519F84ABF007B43B4 /* LibCxxVector.cpp in Sources */,
268900F313353E6F00698AC0 /* StackFrame.cpp in Sources */,

View File

@ -71,9 +71,14 @@ else()
posix/HostProcessPosix.cpp
posix/HostThreadPosix.cpp
posix/PipePosix.cpp
posix/ProcessLauncherPosix.cpp
)
if (NOT __ANDROID_NDK__)
add_host_subdirectory(posix
posix/ProcessLauncherPosix.cpp
)
endif()
if (CMAKE_SYSTEM_NAME MATCHES "Darwin")
include_directories(SYSTEM ${LIBXML2_INCLUDE_DIR})
add_host_subdirectory(macosx
@ -93,6 +98,8 @@ else()
elseif (CMAKE_SYSTEM_NAME MATCHES "Linux")
if (__ANDROID_NDK__)
add_host_subdirectory(android
android/HostInfoAndroid.cpp
android/ProcessLauncherAndroid.cpp
linux/Host.cpp
linux/HostInfoLinux.cpp
linux/HostThreadLinux.cpp

View File

@ -0,0 +1,28 @@
//===-- HostInfoAndroid.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/android/HostInfoAndroid.h"
#include "lldb/Host/linux/HostInfoLinux.h"
using namespace lldb_private;
void
HostInfoAndroid::ComputeHostArchitectureSupport(ArchSpec &arch_32, ArchSpec &arch_64)
{
HostInfoLinux::ComputeHostArchitectureSupport(arch_32, arch_64);
if (arch_32.IsValid())
{
arch_32.GetTriple().setEnvironment(llvm::Triple::Android);
}
if (arch_64.IsValid())
{
arch_64.GetTriple().setEnvironment(llvm::Triple::Android);
}
}

View File

@ -0,0 +1,59 @@
//===-- ProcessLauncherAndroid.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/Host.h"
#include "lldb/Host/HostProcess.h"
#include "lldb/Host/android/ProcessLauncherAndroid.h"
#include "lldb/Target/ProcessLaunchInfo.h"
#include <limits.h>
using namespace lldb;
using namespace lldb_private;
HostProcess
ProcessLauncherAndroid::LaunchProcess(const ProcessLaunchInfo &launch_info, Error &error)
{
// TODO: Handle other launch parameters specified in launc_info
char exe_path[PATH_MAX];
launch_info.GetExecutableFile().GetPath(exe_path, sizeof(exe_path));
const size_t err_len = 1024;
char err_str[err_len];
lldb::pid_t pid = ::fork ();
if (pid < 0)
{
// Fork failed
error.SetErrorStringWithFormat("Fork failed with error message: %s", strerror(errno));
return HostProcess(LLDB_INVALID_PROCESS_ID);
}
else if (pid == 0)
{
// Child process
const char **argv = launch_info.GetArguments().GetConstArgumentVector();
const char **envp = launch_info.GetEnvironmentEntries().GetConstArgumentVector();
const char *working_dir = launch_info.GetWorkingDirectory();
if (working_dir != nullptr && working_dir[0])
{
if (::chdir(working_dir) != 0)
exit(-1);
}
execve(argv[0],
const_cast<char *const *>(argv),
const_cast<char *const *>(envp));
exit(-1);
}
return HostProcess(pid);
}

View File

@ -64,6 +64,8 @@
#if defined(_WIN32)
#include "lldb/Host/windows/ProcessLauncherWindows.h"
#elif defined(__ANDROID__) || defined(__ANDROID_NDK__)
#include "lldb/Host/android/ProcessLauncherAndroid.h"
#else
#include "lldb/Host/posix/ProcessLauncherPosix.h"
#endif
@ -671,13 +673,13 @@ Host::RunShellCommand (const char *command,
// systems
#if defined (__APPLE__) || defined (__linux__) || defined (__FreeBSD__) || defined (__GLIBC__) || defined(__NetBSD__)
#if !defined(__ANDROID__) && !defined(__ANDROID_NDK__)
// this method needs to be visible to macosx/Host.cpp and
// common/Host.cpp.
short
Host::GetPosixspawnFlags(const ProcessLaunchInfo &launch_info)
{
#if !defined(__ANDROID__) && !defined(__ANDROID_NDK__)
short flags = POSIX_SPAWN_SETSIGDEF | POSIX_SPAWN_SETSIGMASK;
#if defined (__APPLE__)
@ -720,17 +722,12 @@ Host::GetPosixspawnFlags(const ProcessLaunchInfo &launch_info)
#endif
#endif // #if defined (__APPLE__)
return flags;
#else
assert(false && "Host::GetPosixspawnFlags() not supported on Android");
return 0;
#endif
}
Error
Host::LaunchProcessPosixSpawn(const char *exe_path, const ProcessLaunchInfo &launch_info, lldb::pid_t &pid)
{
Error error;
#if !defined(__ANDROID__) && !defined(__ANDROID_NDK__)
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_HOST | LIBLLDB_LOG_PROCESS));
posix_spawnattr_t attr;
@ -920,9 +917,6 @@ Host::LaunchProcessPosixSpawn(const char *exe_path, const ProcessLaunchInfo &lau
}
#endif
}
#else
error.SetErrorString("Host::LaunchProcessPosixSpawn() not supported on Android");
#endif
return error;
}
@ -930,7 +924,6 @@ Host::LaunchProcessPosixSpawn(const char *exe_path, const ProcessLaunchInfo &lau
bool
Host::AddPosixSpawnFileAction(void *_file_actions, const FileAction *info, Log *log, Error &error)
{
#if !defined(__ANDROID__) && !defined(__ANDROID_NDK__)
if (info == NULL)
return false;
@ -993,12 +986,9 @@ Host::AddPosixSpawnFileAction(void *_file_actions, const FileAction *info, Log *
break;
}
return error.Success();
#else
error.SetErrorString("Host::AddPosixSpawnFileAction() not supported on Android");
return false;
#endif
}
#endif // LaunchProcedssPosixSpawn: Apple, Linux, FreeBSD and other GLIBC systems
#endif // !defined(__ANDROID__) && !defined(__ANDROID_NDK__)
#endif // defined (__APPLE__) || defined (__linux__) || defined (__FreeBSD__) || defined (__GLIBC__) || defined(__NetBSD__)
#if defined(__linux__) || defined(__FreeBSD__) || defined(__GLIBC__) || defined(__NetBSD__) || defined(_WIN32)
// The functions below implement process launching via posix_spawn() for Linux,
@ -1010,6 +1000,8 @@ Host::LaunchProcess (ProcessLaunchInfo &launch_info)
std::unique_ptr<ProcessLauncher> delegate_launcher;
#if defined(_WIN32)
delegate_launcher.reset(new ProcessLauncherWindows());
#elif defined(__ANDROID__) || defined(__ANDROID_NDK__)
delegate_launcher.reset(new ProcessLauncherAndroid());
#else
delegate_launcher.reset(new ProcessLauncherPosix());
#endif

View File

@ -0,0 +1,6 @@
set(LLVM_NO_RTTI 1)
add_lldb_library(lldbPluginPlatformAndroid
PlatformAndroid.cpp
PlatformAndroidRemoteGDBServer.cpp
)

View File

@ -0,0 +1,14 @@
##===- source/Plugins/Platform/Android/Makefile ------------*- Makefile -*-===##
#
# The LLVM Compiler Infrastructure
#
# This file is distributed under the University of Illinois Open Source
# License. See LICENSE.TXT for details.
#
##===----------------------------------------------------------------------===##
LLDB_LEVEL := ../../../..
LIBRARYNAME := lldbPluginPlatformAndroid
BUILD_ARCHIVE = 1
include $(LLDB_LEVEL)/Makefile

View File

@ -0,0 +1,156 @@
//===-- PlatformAndroid.cpp -------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// C Includes
// C++ Includes
// Other libraries and framework includes
#include "lldb/Core/Log.h"
#include "lldb/Core/PluginManager.h"
// Project includes
#include "PlatformAndroid.h"
#include "PlatformAndroidRemoteGDBServer.h"
using namespace lldb;
using namespace lldb_private;
static uint32_t g_initialize_count = 0;
void
PlatformAndroid::Initialize ()
{
if (g_initialize_count++ == 0)
{
PluginManager::RegisterPlugin (PlatformAndroid::GetPluginNameStatic(),
PlatformAndroid::GetPluginDescriptionStatic(),
PlatformAndroid::CreateInstance);
}
}
void
PlatformAndroid::Terminate ()
{
if (g_initialize_count > 0)
{
if (--g_initialize_count == 0)
{
PluginManager::UnregisterPlugin (PlatformAndroid::CreateInstance);
}
}
}
PlatformSP
PlatformAndroid::CreateInstance (bool force, const ArchSpec *arch)
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PLATFORM));
if (log)
{
const char *arch_name;
if (arch && arch->GetArchitectureName ())
arch_name = arch->GetArchitectureName ();
else
arch_name = "<null>";
const char *triple_cstr = arch ? arch->GetTriple ().getTriple ().c_str() : "<null>";
log->Printf ("PlatformAndroid::%s(force=%s, arch={%s,%s})", __FUNCTION__, force ? "true" : "false", arch_name, triple_cstr);
}
bool create = force;
if (create == false && arch && arch->IsValid())
{
const llvm::Triple &triple = arch->GetTriple();
switch (triple.getVendor())
{
case llvm::Triple::PC:
create = true;
break;
#if defined(__ANDROID__)
// Only accept "unknown" for the vendor if the host is android and
// it "unknown" wasn't specified (it was just returned because it
// was NOT specified_
case llvm::Triple::VendorType::UnknownVendor:
create = !arch->TripleVendorWasSpecified();
break;
#endif
default:
break;
}
if (create)
{
switch (triple.getOS())
{
case llvm::Triple::Linux:
break;
#if defined(__ANDROID__)
// Only accept "unknown" for the OS if the host is android and
// it "unknown" wasn't specified (it was just returned because it
// was NOT specified)
case llvm::Triple::OSType::UnknownOS:
create = !arch->TripleOSWasSpecified();
break;
#endif
default:
create = false;
break;
}
}
}
if (create)
{
if (log)
log->Printf ("PlatformAndroid::%s() creating remote-android platform", __FUNCTION__);
return PlatformSP(new PlatformAndroid());
}
if (log)
log->Printf ("PlatformAndroid::%s() aborting creation of remote-android platform", __FUNCTION__);
return PlatformSP();
}
PlatformAndroid::PlatformAndroid () :
PlatformLinux(false) // Platform android is always a remote target
{
}
PlatformAndroid::~PlatformAndroid()
{
}
lldb_private::ConstString
PlatformAndroid::GetPluginNameStatic ()
{
static ConstString g_remote_name("remote-android");
return g_remote_name;
}
const char *
PlatformAndroid::GetPluginDescriptionStatic ()
{
return "Remote Android user platform plug-in.";
}
lldb_private::ConstString
PlatformAndroid::GetPluginName()
{
return GetPluginNameStatic();
}
Error
PlatformAndroid::ConnectRemote (Args& args)
{
if (!m_remote_platform_sp)
m_remote_platform_sp = PlatformSP(new PlatformAndroidRemoteGDBServer());
return PlatformLinux::ConnectRemote (args);
}

View File

@ -0,0 +1,68 @@
//===-- PlatformAndroid.h ---------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef liblldb_PlatformAndroid_h_
#define liblldb_PlatformAndroid_h_
// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
#include "Plugins/Platform/Linux/PlatformLinux.h"
namespace lldb_private {
class PlatformAndroid : public PlatformLinux
{
public:
static void
Initialize ();
static void
Terminate ();
PlatformAndroid ();
virtual
~PlatformAndroid();
//------------------------------------------------------------
// lldb_private::PluginInterface functions
//------------------------------------------------------------
static lldb::PlatformSP
CreateInstance (bool force, const lldb_private::ArchSpec *arch);
static lldb_private::ConstString
GetPluginNameStatic ();
static const char *
GetPluginDescriptionStatic ();
lldb_private::ConstString
GetPluginName() override;
uint32_t
GetPluginVersion() override
{
return 1;
}
//------------------------------------------------------------
// lldb_private::Platform functions
//------------------------------------------------------------
lldb_private::Error
ConnectRemote (lldb_private::Args& args) override;
private:
DISALLOW_COPY_AND_ASSIGN (PlatformAndroid);
};
} // namespace lldb_private
#endif // liblldb_PlatformAndroid_h_

View File

@ -0,0 +1,224 @@
//===-- PlatformAndroidRemoteGDBServer.cpp ----------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// Other libraries and framework includes
#include "lldb/Core/Error.h"
#include "lldb/Host/ConnectionFileDescriptor.h"
#include "llvm/ADT/StringRef.h"
// Project includes
#include "PlatformAndroidRemoteGDBServer.h"
#include "Utility/UriParser.h"
using namespace lldb;
using namespace lldb_private;
static const lldb::pid_t g_remote_platform_pid = 0; // Alias for the process id of lldb-platform
static const uint32_t g_adb_timeout = 10000; // 10 ms
static void
SendMessageToAdb (Connection& conn, const std::string& packet, Error& error)
{
ConnectionStatus status;
char length_buffer[5];
snprintf (length_buffer, sizeof (length_buffer), "%04zx", packet.size());
conn.Write (length_buffer, 4, status, &error);
if (error.Fail ())
return;
conn.Write (packet.c_str(), packet.size(), status, &error);
}
static std::string
ReadMessageFromAdb (Connection& conn, bool has_okay, Error& error)
{
ConnectionStatus status;
char buffer[5];
buffer[4] = 0;
if (has_okay)
{
conn.Read (buffer, 4, g_adb_timeout, status, &error);
if (error.Fail ())
return "";
if (strncmp (buffer, "OKAY", 4) != 0)
{
error.SetErrorStringWithFormat ("\"OKAY\" expected from adb, received: \"%s\"", buffer);
return "";
}
}
conn.Read (buffer, 4, g_adb_timeout, status, &error);
if (error.Fail())
return "";
size_t packet_len = 0;
sscanf(buffer, "%zx", &packet_len);
std::string result(packet_len, 0);
conn.Read (&result[0], packet_len, g_adb_timeout, status, &error);
if (error.Fail ())
return "";
return result;
}
static Error
ForwardPortWithAdb (uint16_t port, std::string& device_id)
{
Error error;
{
// Fetch the device list from ADB and if only 1 device found then use that device
// TODO: Handle the case when more device is available
std::unique_ptr<ConnectionFileDescriptor> conn (new ConnectionFileDescriptor ());
if (conn->Connect ("connect://localhost:5037", &error) != eConnectionStatusSuccess)
return error;
SendMessageToAdb (*conn, "host:devices", error);
if (error.Fail ())
return error;
std::string in_buffer = ReadMessageFromAdb (*conn, true, error);
llvm::StringRef deviceList(in_buffer);
std::pair<llvm::StringRef, llvm::StringRef> devices = deviceList.split ('\n');
if (devices.first.size () == 0 || devices.second.size () > 0)
{
error.SetErrorString ("Wrong number of devices returned from ADB");
return error;
}
device_id = devices.first.split ('\t').first;
}
{
// Forward the port to the (only) connected device
std::unique_ptr<ConnectionFileDescriptor> conn (new ConnectionFileDescriptor ());
if (conn->Connect ("connect://localhost:5037", &error) != eConnectionStatusSuccess)
return error;
char port_buffer[32];
snprintf (port_buffer, sizeof (port_buffer), "tcp:%d;tcp:%d", port, port);
std::string out_buffer = "host-serial:" + device_id + ":forward:" + port_buffer;
SendMessageToAdb (*conn, out_buffer, error);
if (error.Fail ())
return error;
std::string in_buffer = ReadMessageFromAdb (*conn, false, error);
if (in_buffer != "OKAY")
error.SetErrorString (in_buffer.c_str ());
}
return error;
}
static Error
DeleteForwardPortWithAdb (uint16_t port, const std::string& device_id)
{
Error error;
std::unique_ptr<ConnectionFileDescriptor> conn (new ConnectionFileDescriptor ());
if (conn->Connect ("connect://localhost:5037", &error) != eConnectionStatusSuccess)
return error;
char port_buffer[16];
snprintf (port_buffer, sizeof (port_buffer), "tcp:%d", port);
std::string out_buffer = "host-serial:" + device_id + ":killforward:" + port_buffer;
SendMessageToAdb (*conn, out_buffer, error);
if (error.Fail ())
return error;
std::string in_buffer = ReadMessageFromAdb (*conn, true, error);
if (in_buffer != "OKAY")
error.SetErrorString (in_buffer.c_str ());
return error;
}
PlatformAndroidRemoteGDBServer::PlatformAndroidRemoteGDBServer ()
{
}
PlatformAndroidRemoteGDBServer::~PlatformAndroidRemoteGDBServer ()
{
for (const auto& it : m_port_forwards)
{
DeleteForwardPortWithAdb (it.second.first, it.second.second);
}
}
uint16_t
PlatformAndroidRemoteGDBServer::LaunchGDBserverAndGetPort (lldb::pid_t &pid)
{
uint16_t port = m_gdb_client.LaunchGDBserverAndGetPort (pid, "127.0.0.1");
if (port == 0)
return port;
std::string device_id;
Error error = ForwardPortWithAdb (port, device_id);
if (error.Fail ())
return 0;
m_port_forwards[pid] = std::make_pair (port, device_id);
return port;
}
bool
PlatformAndroidRemoteGDBServer::KillSpawnedProcess (lldb::pid_t pid)
{
auto it = m_port_forwards.find (pid);
if (it != m_port_forwards.end ())
{
DeleteForwardPortWithAdb (it->second.first, it->second.second);
m_port_forwards.erase (it);
}
return m_gdb_client.KillSpawnedProcess (pid);
}
Error
PlatformAndroidRemoteGDBServer::ConnectRemote (Args& args)
{
if (args.GetArgumentCount () != 1)
return Error ("\"platform connect\" takes a single argument: <connect-url>");
int port;
std::string scheme, host, path;
const char *url = args.GetArgumentAtIndex (0);
if (!UriParser::Parse (url, scheme, host, port, path))
return Error ("invalid uri");
std::string device_id;
Error error = ForwardPortWithAdb (port, device_id);
if (error.Fail ())
return error;
m_port_forwards[g_remote_platform_pid] = std::make_pair (port, device_id);
return PlatformRemoteGDBServer::ConnectRemote (args);
}
Error
PlatformAndroidRemoteGDBServer::DisconnectRemote ()
{
auto it = m_port_forwards.find (g_remote_platform_pid);
if (it != m_port_forwards.end ())
{
DeleteForwardPortWithAdb (it->second.first, it->second.second);
m_port_forwards.erase (it);
}
return PlatformRemoteGDBServer::DisconnectRemote ();
}

View File

@ -0,0 +1,50 @@
//===-- PlatformAndroidRemoteGDBServer.h ------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef liblldb_PlatformAndroidRemoteGDBServer_h_
#define liblldb_PlatformAndroidRemoteGDBServer_h_
// C Includes
// C++ Includes
#include <map>
#include <utility>
// Other libraries and framework includes
// Project includes
#include "Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h"
class PlatformAndroidRemoteGDBServer : public PlatformRemoteGDBServer
{
public:
PlatformAndroidRemoteGDBServer ();
virtual
~PlatformAndroidRemoteGDBServer ();
lldb_private::Error
ConnectRemote (lldb_private::Args& args) override;
lldb_private::Error
DisconnectRemote () override;
protected:
std::map<lldb::pid_t, std::pair<uint16_t, std::string>> m_port_forwards;
uint16_t
LaunchGDBserverAndGetPort (lldb::pid_t &pid) override;
bool
KillSpawnedProcess (lldb::pid_t pid) override;
private:
DISALLOW_COPY_AND_ASSIGN (PlatformAndroidRemoteGDBServer);
};
#endif // liblldb_PlatformAndroidRemoteGDBServer_h_

View File

@ -11,3 +11,4 @@
add_subdirectory(POSIX)
add_subdirectory(gdb-server)
add_subdirectory(Kalimba)
add_subdirectory(Android)

View File

@ -522,7 +522,7 @@ PlatformRemoteGDBServer::LaunchProcess (ProcessLaunchInfo &launch_info)
Error
PlatformRemoteGDBServer::KillProcess (const lldb::pid_t pid)
{
if (!m_gdb_client.KillSpawnedProcess(pid))
if (!KillSpawnedProcess(pid))
return Error("failed to kill remote spawned process");
return Error();
}
@ -539,22 +539,8 @@ PlatformRemoteGDBServer::DebugProcess (lldb_private::ProcessLaunchInfo &launch_i
if (IsConnected())
{
lldb::pid_t debugserver_pid = LLDB_INVALID_PROCESS_ID;
ArchSpec remote_arch = GetRemoteSystemArchitecture();
llvm::Triple &remote_triple = remote_arch.GetTriple();
uint16_t port = 0;
if (remote_triple.getVendor() == llvm::Triple::Apple && remote_triple.getOS() == llvm::Triple::IOS)
{
// When remote debugging to iOS, we use a USB mux that always talks
// to localhost, so we will need the remote debugserver to accept connections
// only from localhost, no matter what our current hostname is
port = m_gdb_client.LaunchGDBserverAndGetPort(debugserver_pid, "127.0.0.1");
}
else
{
// All other hosts should use their actual hostname
port = m_gdb_client.LaunchGDBserverAndGetPort(debugserver_pid, NULL);
}
uint16_t port = LaunchGDBserverAndGetPort(debugserver_pid);
if (port == 0)
{
error.SetErrorStringWithFormat ("unable to launch a GDB server on '%s'", GetHostname ());
@ -605,7 +591,7 @@ PlatformRemoteGDBServer::DebugProcess (lldb_private::ProcessLaunchInfo &launch_i
else if (debugserver_pid != LLDB_INVALID_PROCESS_ID)
{
printf ("error: connect remote failed (%s)\n", error.AsCString());
m_gdb_client.KillSpawnedProcess(debugserver_pid);
KillSpawnedProcess(debugserver_pid);
}
}
}
@ -617,7 +603,32 @@ PlatformRemoteGDBServer::DebugProcess (lldb_private::ProcessLaunchInfo &launch_i
}
}
return process_sp;
}
uint16_t
PlatformRemoteGDBServer::LaunchGDBserverAndGetPort (lldb::pid_t &pid)
{
ArchSpec remote_arch = GetRemoteSystemArchitecture ();
llvm::Triple &remote_triple = remote_arch.GetTriple ();
if (remote_triple.getVendor () == llvm::Triple::Apple && remote_triple.getOS () == llvm::Triple::IOS)
{
// When remote debugging to iOS, we use a USB mux that always talks
// to localhost, so we will need the remote debugserver to accept connections
// only from localhost, no matter what our current hostname is
return m_gdb_client.LaunchGDBserverAndGetPort (pid, "127.0.0.1");
}
else
{
// All other hosts should use their actual hostname
return m_gdb_client.LaunchGDBserverAndGetPort (pid, NULL);
}
}
bool
PlatformRemoteGDBServer::KillSpawnedProcess (lldb::pid_t pid)
{
return m_gdb_client.KillSpawnedProcess (pid);
}
lldb::ProcessSP
@ -632,22 +643,8 @@ PlatformRemoteGDBServer::Attach (lldb_private::ProcessAttachInfo &attach_info,
if (IsConnected())
{
lldb::pid_t debugserver_pid = LLDB_INVALID_PROCESS_ID;
ArchSpec remote_arch = GetRemoteSystemArchitecture();
llvm::Triple &remote_triple = remote_arch.GetTriple();
uint16_t port = 0;
if (remote_triple.getVendor() == llvm::Triple::Apple && remote_triple.getOS() == llvm::Triple::IOS)
{
// When remote debugging to iOS, we use a USB mux that always talks
// to localhost, so we will need the remote debugserver to accept connections
// only from localhost, no matter what our current hostname is
port = m_gdb_client.LaunchGDBserverAndGetPort(debugserver_pid, "127.0.0.1");
}
else
{
// All other hosts should use their actual hostname
port = m_gdb_client.LaunchGDBserverAndGetPort(debugserver_pid, NULL);
}
uint16_t port = LaunchGDBserverAndGetPort(debugserver_pid);
if (port == 0)
{
error.SetErrorStringWithFormat ("unable to launch a GDB server on '%s'", GetHostname ());
@ -700,7 +697,7 @@ PlatformRemoteGDBServer::Attach (lldb_private::ProcessAttachInfo &attach_info,
if (error.Fail() && debugserver_pid != LLDB_INVALID_PROCESS_ID)
{
m_gdb_client.KillSpawnedProcess(debugserver_pid);
KillSpawnedProcess(debugserver_pid);
}
}
}

View File

@ -217,6 +217,15 @@ protected:
std::string m_platform_description; // After we connect we can get a more complete description of what we are connected to
std::string m_platform_hostname;
// Launch the lldb-gdbserver on the remote host and return the port it is listening on or 0 on
// failure. Subclasses should override this method if they want to do extra actions before or
// after launching the lldb-gdbserver.
virtual uint16_t
LaunchGDBserverAndGetPort (lldb::pid_t &pid);
virtual bool
KillSpawnedProcess (lldb::pid_t pid);
private:
DISALLOW_COPY_AND_ASSIGN (PlatformRemoteGDBServer);

View File

@ -43,6 +43,7 @@
#include "Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h"
#include "Plugins/ObjectFile/ELF/ObjectFileELF.h"
#include "Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h"
#include "Plugins/Platform/Android/PlatformAndroid.h"
#include "Plugins/Platform/FreeBSD/PlatformFreeBSD.h"
#include "Plugins/Platform/Linux/PlatformLinux.h"
#include "Plugins/Platform/POSIX/PlatformPOSIX.h"
@ -173,6 +174,7 @@ lldb_private::Initialize ()
PlatformLinux::Initialize();
PlatformWindows::Initialize();
PlatformKalimba::Initialize();
PlatformAndroid::Initialize();
SymbolFileDWARFDebugMap::Initialize();
ItaniumABILanguageRuntime::Initialize();
#ifndef LLDB_DISABLE_PYTHON
@ -269,6 +271,7 @@ lldb_private::Terminate ()
PlatformLinux::Terminate();
PlatformWindows::Terminate();
PlatformKalimba::Terminate();
PlatformAndroid::Terminate();
SymbolFileDWARFDebugMap::Terminate();
ItaniumABILanguageRuntime::Terminate();
#ifndef LLDB_DISABLE_PYTHON