1 //===-- PlatformAndroid.cpp -------------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 // C Includes 11 // C++ Includes 12 // Other libraries and framework includes 13 #include "lldb/Core/Log.h" 14 #include "lldb/Core/PluginManager.h" 15 #include "lldb/Host/HostInfo.h" 16 #include "Utility/UriParser.h" 17 18 // Project includes 19 #include "AdbClient.h" 20 #include "PlatformAndroid.h" 21 #include "PlatformAndroidRemoteGDBServer.h" 22 23 using namespace lldb; 24 using namespace lldb_private; 25 using namespace lldb_private::platform_android; 26 27 static uint32_t g_initialize_count = 0; 28 29 void 30 PlatformAndroid::Initialize () 31 { 32 PlatformLinux::Initialize (); 33 34 if (g_initialize_count++ == 0) 35 { 36 #if defined(__ANDROID__) 37 PlatformSP default_platform_sp (new PlatformAndroid(true)); 38 default_platform_sp->SetSystemArchitecture(HostInfo::GetArchitecture()); 39 Platform::SetHostPlatform (default_platform_sp); 40 #endif 41 PluginManager::RegisterPlugin (PlatformAndroid::GetPluginNameStatic(false), 42 PlatformAndroid::GetPluginDescriptionStatic(false), 43 PlatformAndroid::CreateInstance); 44 } 45 } 46 47 void 48 PlatformAndroid::Terminate () 49 { 50 if (g_initialize_count > 0) 51 { 52 if (--g_initialize_count == 0) 53 { 54 PluginManager::UnregisterPlugin (PlatformAndroid::CreateInstance); 55 } 56 } 57 58 PlatformLinux::Terminate (); 59 } 60 61 PlatformSP 62 PlatformAndroid::CreateInstance (bool force, const ArchSpec *arch) 63 { 64 Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_PLATFORM)); 65 if (log) 66 { 67 const char *arch_name; 68 if (arch && arch->GetArchitectureName ()) 69 arch_name = arch->GetArchitectureName (); 70 else 71 arch_name = "<null>"; 72 73 const char *triple_cstr = arch ? arch->GetTriple ().getTriple ().c_str() : "<null>"; 74 75 log->Printf ("PlatformAndroid::%s(force=%s, arch={%s,%s})", __FUNCTION__, force ? "true" : "false", arch_name, triple_cstr); 76 } 77 78 bool create = force; 79 if (create == false && arch && arch->IsValid()) 80 { 81 const llvm::Triple &triple = arch->GetTriple(); 82 switch (triple.getVendor()) 83 { 84 case llvm::Triple::PC: 85 create = true; 86 break; 87 88 #if defined(__ANDROID__) 89 // Only accept "unknown" for the vendor if the host is android and 90 // it "unknown" wasn't specified (it was just returned because it 91 // was NOT specified_ 92 case llvm::Triple::VendorType::UnknownVendor: 93 create = !arch->TripleVendorWasSpecified(); 94 break; 95 #endif 96 default: 97 break; 98 } 99 100 if (create) 101 { 102 switch (triple.getOS()) 103 { 104 case llvm::Triple::Android: 105 break; 106 107 #if defined(__ANDROID__) 108 // Only accept "unknown" for the OS if the host is android and 109 // it "unknown" wasn't specified (it was just returned because it 110 // was NOT specified) 111 case llvm::Triple::OSType::UnknownOS: 112 create = !arch->TripleOSWasSpecified(); 113 break; 114 #endif 115 default: 116 create = false; 117 break; 118 } 119 } 120 } 121 122 if (create) 123 { 124 if (log) 125 log->Printf ("PlatformAndroid::%s() creating remote-android platform", __FUNCTION__); 126 return PlatformSP(new PlatformAndroid(false)); 127 } 128 129 if (log) 130 log->Printf ("PlatformAndroid::%s() aborting creation of remote-android platform", __FUNCTION__); 131 132 return PlatformSP(); 133 } 134 135 PlatformAndroid::PlatformAndroid (bool is_host) : 136 PlatformLinux(is_host) 137 { 138 } 139 140 PlatformAndroid::~PlatformAndroid() 141 { 142 } 143 144 ConstString 145 PlatformAndroid::GetPluginNameStatic (bool is_host) 146 { 147 if (is_host) 148 { 149 static ConstString g_host_name(Platform::GetHostPlatformName ()); 150 return g_host_name; 151 } 152 else 153 { 154 static ConstString g_remote_name("remote-android"); 155 return g_remote_name; 156 } 157 } 158 159 const char * 160 PlatformAndroid::GetPluginDescriptionStatic (bool is_host) 161 { 162 if (is_host) 163 return "Local Android user platform plug-in."; 164 else 165 return "Remote Android user platform plug-in."; 166 } 167 168 ConstString 169 PlatformAndroid::GetPluginName() 170 { 171 return GetPluginNameStatic(IsHost()); 172 } 173 174 Error 175 PlatformAndroid::ConnectRemote(Args& args) 176 { 177 m_device_id.clear(); 178 179 if (IsHost()) 180 { 181 return Error ("can't connect to the host platform '%s', always connected", GetPluginName().GetCString()); 182 } 183 184 if (!m_remote_platform_sp) 185 m_remote_platform_sp = PlatformSP(new PlatformAndroidRemoteGDBServer()); 186 187 int port; 188 std::string scheme, host, path; 189 const char *url = args.GetArgumentAtIndex(0); 190 if (!url) 191 return Error("URL is null."); 192 if (!UriParser::Parse(url, scheme, host, port, path)) 193 return Error("Invalid URL: %s", url); 194 if (scheme == "adb") 195 m_device_id = host; 196 197 auto error = PlatformLinux::ConnectRemote(args); 198 if (error.Success()) 199 { 200 AdbClient adb; 201 error = AdbClient::CreateByDeviceID(m_device_id, adb); 202 if (error.Fail()) 203 return error; 204 205 m_device_id = adb.GetDeviceID(); 206 } 207 return error; 208 } 209 210 Error 211 PlatformAndroid::GetFile (const FileSpec& source, 212 const FileSpec& destination) 213 { 214 if (IsHost() || !m_remote_platform_sp) 215 return PlatformLinux::GetFile(source, destination); 216 217 FileSpec source_spec (source.GetPath (false), false, FileSpec::ePathSyntaxPosix); 218 if (source_spec.IsRelative()) 219 source_spec = GetRemoteWorkingDirectory ().CopyByAppendingPathComponent (source_spec.GetCString (false)); 220 221 AdbClient adb (m_device_id); 222 return adb.PullFile (source_spec, destination); 223 } 224 225 Error 226 PlatformAndroid::PutFile (const FileSpec& source, 227 const FileSpec& destination, 228 uint32_t uid, 229 uint32_t gid) 230 { 231 if (IsHost() || !m_remote_platform_sp) 232 return PlatformLinux::PutFile (source, destination, uid, gid); 233 234 FileSpec destination_spec (destination.GetPath (false), false, FileSpec::ePathSyntaxPosix); 235 if (destination_spec.IsRelative()) 236 destination_spec = GetRemoteWorkingDirectory ().CopyByAppendingPathComponent (destination_spec.GetCString (false)); 237 238 AdbClient adb (m_device_id); 239 // TODO: Set correct uid and gid on remote file. 240 return adb.PushFile(source, destination_spec); 241 } 242 243 const char * 244 PlatformAndroid::GetCacheHostname () 245 { 246 return m_device_id.c_str (); 247 } 248 249 Error 250 PlatformAndroid::DownloadModuleSlice (const FileSpec &src_file_spec, 251 const uint64_t src_offset, 252 const uint64_t src_size, 253 const FileSpec &dst_file_spec) 254 { 255 if (src_offset != 0) 256 return Error ("Invalid offset - %" PRIu64, src_offset); 257 258 return GetFile (src_file_spec, dst_file_spec); 259 } 260