100e305d2STamas Berghammer //===-- PlatformAndroid.cpp -------------------------------------*- C++ -*-===// 200e305d2STamas Berghammer // 300e305d2STamas Berghammer // The LLVM Compiler Infrastructure 400e305d2STamas Berghammer // 500e305d2STamas Berghammer // This file is distributed under the University of Illinois Open Source 600e305d2STamas Berghammer // License. See LICENSE.TXT for details. 700e305d2STamas Berghammer // 800e305d2STamas Berghammer //===----------------------------------------------------------------------===// 900e305d2STamas Berghammer 1000e305d2STamas Berghammer // C Includes 1100e305d2STamas Berghammer // C++ Includes 1200e305d2STamas Berghammer // Other libraries and framework includes 1300e305d2STamas Berghammer #include "lldb/Core/Log.h" 1400e305d2STamas Berghammer #include "lldb/Core/PluginManager.h" 151c6a1ea9STamas Berghammer #include "lldb/Host/HostInfo.h" 163ea689b3SChaoren Lin #include "Utility/UriParser.h" 1700e305d2STamas Berghammer 1800e305d2STamas Berghammer // Project includes 196f001068SOleksiy Vyalov #include "AdbClient.h" 2000e305d2STamas Berghammer #include "PlatformAndroid.h" 2100e305d2STamas Berghammer #include "PlatformAndroidRemoteGDBServer.h" 2200e305d2STamas Berghammer 2300e305d2STamas Berghammer using namespace lldb; 2400e305d2STamas Berghammer using namespace lldb_private; 25db264a6dSTamas Berghammer using namespace lldb_private::platform_android; 2600e305d2STamas Berghammer 2700e305d2STamas Berghammer static uint32_t g_initialize_count = 0; 2800e305d2STamas Berghammer 2900e305d2STamas Berghammer void 3000e305d2STamas Berghammer PlatformAndroid::Initialize () 3100e305d2STamas Berghammer { 323c4f89d7STamas Berghammer PlatformLinux::Initialize (); 333c4f89d7STamas Berghammer 3400e305d2STamas Berghammer if (g_initialize_count++ == 0) 3500e305d2STamas Berghammer { 361c6a1ea9STamas Berghammer #if defined(__ANDROID__) 371c6a1ea9STamas Berghammer PlatformSP default_platform_sp (new PlatformAndroid(true)); 381c6a1ea9STamas Berghammer default_platform_sp->SetSystemArchitecture(HostInfo::GetArchitecture()); 391c6a1ea9STamas Berghammer Platform::SetHostPlatform (default_platform_sp); 401c6a1ea9STamas Berghammer #endif 411c6a1ea9STamas Berghammer PluginManager::RegisterPlugin (PlatformAndroid::GetPluginNameStatic(false), 421c6a1ea9STamas Berghammer PlatformAndroid::GetPluginDescriptionStatic(false), 4300e305d2STamas Berghammer PlatformAndroid::CreateInstance); 4400e305d2STamas Berghammer } 4500e305d2STamas Berghammer } 4600e305d2STamas Berghammer 4700e305d2STamas Berghammer void 4800e305d2STamas Berghammer PlatformAndroid::Terminate () 4900e305d2STamas Berghammer { 5000e305d2STamas Berghammer if (g_initialize_count > 0) 5100e305d2STamas Berghammer { 5200e305d2STamas Berghammer if (--g_initialize_count == 0) 5300e305d2STamas Berghammer { 5400e305d2STamas Berghammer PluginManager::UnregisterPlugin (PlatformAndroid::CreateInstance); 5500e305d2STamas Berghammer } 5600e305d2STamas Berghammer } 573c4f89d7STamas Berghammer 583c4f89d7STamas Berghammer PlatformLinux::Terminate (); 5900e305d2STamas Berghammer } 6000e305d2STamas Berghammer 6100e305d2STamas Berghammer PlatformSP 6200e305d2STamas Berghammer PlatformAndroid::CreateInstance (bool force, const ArchSpec *arch) 6300e305d2STamas Berghammer { 64db264a6dSTamas Berghammer Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_PLATFORM)); 6500e305d2STamas Berghammer if (log) 6600e305d2STamas Berghammer { 6700e305d2STamas Berghammer const char *arch_name; 6800e305d2STamas Berghammer if (arch && arch->GetArchitectureName ()) 6900e305d2STamas Berghammer arch_name = arch->GetArchitectureName (); 7000e305d2STamas Berghammer else 7100e305d2STamas Berghammer arch_name = "<null>"; 7200e305d2STamas Berghammer 7300e305d2STamas Berghammer const char *triple_cstr = arch ? arch->GetTriple ().getTriple ().c_str() : "<null>"; 7400e305d2STamas Berghammer 7500e305d2STamas Berghammer log->Printf ("PlatformAndroid::%s(force=%s, arch={%s,%s})", __FUNCTION__, force ? "true" : "false", arch_name, triple_cstr); 7600e305d2STamas Berghammer } 7700e305d2STamas Berghammer 7800e305d2STamas Berghammer bool create = force; 7900e305d2STamas Berghammer if (create == false && arch && arch->IsValid()) 8000e305d2STamas Berghammer { 8100e305d2STamas Berghammer const llvm::Triple &triple = arch->GetTriple(); 8200e305d2STamas Berghammer switch (triple.getVendor()) 8300e305d2STamas Berghammer { 8400e305d2STamas Berghammer case llvm::Triple::PC: 8500e305d2STamas Berghammer create = true; 8600e305d2STamas Berghammer break; 8700e305d2STamas Berghammer 8800e305d2STamas Berghammer #if defined(__ANDROID__) 8900e305d2STamas Berghammer // Only accept "unknown" for the vendor if the host is android and 9000e305d2STamas Berghammer // it "unknown" wasn't specified (it was just returned because it 9100e305d2STamas Berghammer // was NOT specified_ 9200e305d2STamas Berghammer case llvm::Triple::VendorType::UnknownVendor: 9300e305d2STamas Berghammer create = !arch->TripleVendorWasSpecified(); 9400e305d2STamas Berghammer break; 9500e305d2STamas Berghammer #endif 9600e305d2STamas Berghammer default: 9700e305d2STamas Berghammer break; 9800e305d2STamas Berghammer } 9900e305d2STamas Berghammer 10000e305d2STamas Berghammer if (create) 10100e305d2STamas Berghammer { 10200e305d2STamas Berghammer switch (triple.getOS()) 10300e305d2STamas Berghammer { 1041c6a1ea9STamas Berghammer case llvm::Triple::Android: 10500e305d2STamas Berghammer break; 10600e305d2STamas Berghammer 10700e305d2STamas Berghammer #if defined(__ANDROID__) 10800e305d2STamas Berghammer // Only accept "unknown" for the OS if the host is android and 10900e305d2STamas Berghammer // it "unknown" wasn't specified (it was just returned because it 11000e305d2STamas Berghammer // was NOT specified) 11100e305d2STamas Berghammer case llvm::Triple::OSType::UnknownOS: 11200e305d2STamas Berghammer create = !arch->TripleOSWasSpecified(); 11300e305d2STamas Berghammer break; 11400e305d2STamas Berghammer #endif 11500e305d2STamas Berghammer default: 11600e305d2STamas Berghammer create = false; 11700e305d2STamas Berghammer break; 11800e305d2STamas Berghammer } 11900e305d2STamas Berghammer } 12000e305d2STamas Berghammer } 12100e305d2STamas Berghammer 12200e305d2STamas Berghammer if (create) 12300e305d2STamas Berghammer { 12400e305d2STamas Berghammer if (log) 12500e305d2STamas Berghammer log->Printf ("PlatformAndroid::%s() creating remote-android platform", __FUNCTION__); 1261c6a1ea9STamas Berghammer return PlatformSP(new PlatformAndroid(false)); 12700e305d2STamas Berghammer } 12800e305d2STamas Berghammer 12900e305d2STamas Berghammer if (log) 13000e305d2STamas Berghammer log->Printf ("PlatformAndroid::%s() aborting creation of remote-android platform", __FUNCTION__); 13100e305d2STamas Berghammer 13200e305d2STamas Berghammer return PlatformSP(); 13300e305d2STamas Berghammer } 13400e305d2STamas Berghammer 1351c6a1ea9STamas Berghammer PlatformAndroid::PlatformAndroid (bool is_host) : 1361c6a1ea9STamas Berghammer PlatformLinux(is_host) 13700e305d2STamas Berghammer { 13800e305d2STamas Berghammer } 13900e305d2STamas Berghammer 14000e305d2STamas Berghammer PlatformAndroid::~PlatformAndroid() 14100e305d2STamas Berghammer { 14200e305d2STamas Berghammer } 14300e305d2STamas Berghammer 144db264a6dSTamas Berghammer ConstString 1451c6a1ea9STamas Berghammer PlatformAndroid::GetPluginNameStatic (bool is_host) 1461c6a1ea9STamas Berghammer { 1471c6a1ea9STamas Berghammer if (is_host) 1481c6a1ea9STamas Berghammer { 1491c6a1ea9STamas Berghammer static ConstString g_host_name(Platform::GetHostPlatformName ()); 1501c6a1ea9STamas Berghammer return g_host_name; 1511c6a1ea9STamas Berghammer } 1521c6a1ea9STamas Berghammer else 15300e305d2STamas Berghammer { 15400e305d2STamas Berghammer static ConstString g_remote_name("remote-android"); 15500e305d2STamas Berghammer return g_remote_name; 15600e305d2STamas Berghammer } 1571c6a1ea9STamas Berghammer } 15800e305d2STamas Berghammer 15900e305d2STamas Berghammer const char * 1601c6a1ea9STamas Berghammer PlatformAndroid::GetPluginDescriptionStatic (bool is_host) 16100e305d2STamas Berghammer { 1621c6a1ea9STamas Berghammer if (is_host) 1631c6a1ea9STamas Berghammer return "Local Android user platform plug-in."; 1641c6a1ea9STamas Berghammer else 16500e305d2STamas Berghammer return "Remote Android user platform plug-in."; 16600e305d2STamas Berghammer } 16700e305d2STamas Berghammer 168db264a6dSTamas Berghammer ConstString 16900e305d2STamas Berghammer PlatformAndroid::GetPluginName() 17000e305d2STamas Berghammer { 1711c6a1ea9STamas Berghammer return GetPluginNameStatic(IsHost()); 17200e305d2STamas Berghammer } 17300e305d2STamas Berghammer 17400e305d2STamas Berghammer Error 17500e305d2STamas Berghammer PlatformAndroid::ConnectRemote(Args& args) 17600e305d2STamas Berghammer { 1776f001068SOleksiy Vyalov m_device_id.clear(); 1786f001068SOleksiy Vyalov 1791c6a1ea9STamas Berghammer if (IsHost()) 1801c6a1ea9STamas Berghammer { 1811c6a1ea9STamas Berghammer return Error ("can't connect to the host platform '%s', always connected", GetPluginName().GetCString()); 1821c6a1ea9STamas Berghammer } 1831c6a1ea9STamas Berghammer 18400e305d2STamas Berghammer if (!m_remote_platform_sp) 18500e305d2STamas Berghammer m_remote_platform_sp = PlatformSP(new PlatformAndroidRemoteGDBServer()); 1866f001068SOleksiy Vyalov 1873ea689b3SChaoren Lin int port; 1883ea689b3SChaoren Lin std::string scheme, host, path; 1893ea689b3SChaoren Lin const char *url = args.GetArgumentAtIndex(0); 1903ea689b3SChaoren Lin if (!url) 1913ea689b3SChaoren Lin return Error("URL is null."); 1923ea689b3SChaoren Lin if (!UriParser::Parse(url, scheme, host, port, path)) 1933ea689b3SChaoren Lin return Error("Invalid URL: %s", url); 1943ea689b3SChaoren Lin if (scheme == "adb") 1953ea689b3SChaoren Lin m_device_id = host; 1963ea689b3SChaoren Lin 1976f001068SOleksiy Vyalov auto error = PlatformLinux::ConnectRemote(args); 1986f001068SOleksiy Vyalov if (error.Success()) 1996f001068SOleksiy Vyalov { 2006f001068SOleksiy Vyalov AdbClient adb; 2013ea689b3SChaoren Lin error = AdbClient::CreateByDeviceID(m_device_id, adb); 2026f001068SOleksiy Vyalov if (error.Fail()) 2036f001068SOleksiy Vyalov return error; 2046f001068SOleksiy Vyalov 2056f001068SOleksiy Vyalov m_device_id = adb.GetDeviceID(); 2066f001068SOleksiy Vyalov } 2076f001068SOleksiy Vyalov return error; 2086f001068SOleksiy Vyalov } 2096f001068SOleksiy Vyalov 2100b5ebef7SOleksiy Vyalov Error 2110b5ebef7SOleksiy Vyalov PlatformAndroid::GetFile (const FileSpec& source, 2120b5ebef7SOleksiy Vyalov const FileSpec& destination) 2130b5ebef7SOleksiy Vyalov { 214291f59c5SOleksiy Vyalov if (IsHost() || !m_remote_platform_sp) 2150b5ebef7SOleksiy Vyalov return PlatformLinux::GetFile(source, destination); 216291f59c5SOleksiy Vyalov 217*32a9da56SOleksiy Vyalov FileSpec source_spec (source.GetPath (false), false, FileSpec::ePathSyntaxPosix); 218*32a9da56SOleksiy Vyalov if (source_spec.IsRelativeToCurrentWorkingDirectory ()) 219*32a9da56SOleksiy Vyalov source_spec = GetRemoteWorkingDirectory ().CopyByAppendingPathComponent (source_spec.GetCString (false)); 220291f59c5SOleksiy Vyalov 221291f59c5SOleksiy Vyalov AdbClient adb (m_device_id); 222291f59c5SOleksiy Vyalov return adb.PullFile (source_spec, destination); 2230b5ebef7SOleksiy Vyalov } 2240b5ebef7SOleksiy Vyalov 2250b5ebef7SOleksiy Vyalov Error 2260b5ebef7SOleksiy Vyalov PlatformAndroid::PutFile (const FileSpec& source, 2270b5ebef7SOleksiy Vyalov const FileSpec& destination, 22862efb1f6SRobert Flack uint32_t uid, 22962efb1f6SRobert Flack uint32_t gid) 23062efb1f6SRobert Flack { 23162efb1f6SRobert Flack if (!IsHost() && m_remote_platform_sp) 23262efb1f6SRobert Flack { 23362efb1f6SRobert Flack AdbClient adb (m_device_id); 23462efb1f6SRobert Flack // TODO: Set correct uid and gid on remote file. 23562efb1f6SRobert Flack return adb.PushFile(source, destination); 23662efb1f6SRobert Flack } 23762efb1f6SRobert Flack return PlatformLinux::PutFile(source, destination, uid, gid); 23862efb1f6SRobert Flack } 23962efb1f6SRobert Flack 2406f001068SOleksiy Vyalov const char * 2416f001068SOleksiy Vyalov PlatformAndroid::GetCacheHostname () 2426f001068SOleksiy Vyalov { 2436f001068SOleksiy Vyalov return m_device_id.c_str (); 24400e305d2STamas Berghammer } 24509e9079dSOleksiy Vyalov 24609e9079dSOleksiy Vyalov Error 24709e9079dSOleksiy Vyalov PlatformAndroid::DownloadModuleSlice (const FileSpec &src_file_spec, 24809e9079dSOleksiy Vyalov const uint64_t src_offset, 24909e9079dSOleksiy Vyalov const uint64_t src_size, 25009e9079dSOleksiy Vyalov const FileSpec &dst_file_spec) 25109e9079dSOleksiy Vyalov { 25209e9079dSOleksiy Vyalov if (src_offset != 0) 25309e9079dSOleksiy Vyalov return Error ("Invalid offset - %" PRIu64, src_offset); 25409e9079dSOleksiy Vyalov 2550b5ebef7SOleksiy Vyalov return GetFile (src_file_spec, dst_file_spec); 25609e9079dSOleksiy Vyalov } 257