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 #include "lldb/Core/Log.h"
11ec3f92a5STamas Berghammer #include "lldb/Core/Module.h"
1200e305d2STamas Berghammer #include "lldb/Core/PluginManager.h"
133cb132a0STamas Berghammer #include "lldb/Core/Scalar.h"
14ec3f92a5STamas Berghammer #include "lldb/Core/Section.h"
153cb132a0STamas Berghammer #include "lldb/Core/ValueObject.h"
161c6a1ea9STamas Berghammer #include "lldb/Host/HostInfo.h"
171d0d90b9STamas Berghammer #include "lldb/Host/StringConvert.h"
185f7e583bSPavel Labath #include "lldb/Utility/UriParser.h"
1900e305d2STamas Berghammer 
2000e305d2STamas Berghammer // Project includes
216f001068SOleksiy Vyalov #include "AdbClient.h"
2200e305d2STamas Berghammer #include "PlatformAndroid.h"
2300e305d2STamas Berghammer #include "PlatformAndroidRemoteGDBServer.h"
2400e305d2STamas Berghammer 
2500e305d2STamas Berghammer using namespace lldb;
2600e305d2STamas Berghammer using namespace lldb_private;
27db264a6dSTamas Berghammer using namespace lldb_private::platform_android;
28ce255ff2SPavel Labath using namespace std::chrono;
2900e305d2STamas Berghammer 
3000e305d2STamas Berghammer static uint32_t g_initialize_count = 0;
31b9c1b51eSKate Stone static const unsigned int g_android_default_cache_size =
32b9c1b51eSKate Stone     2048; // Fits inside 4k adb packet.
3300e305d2STamas Berghammer 
34b9c1b51eSKate Stone void PlatformAndroid::Initialize() {
353c4f89d7STamas Berghammer   PlatformLinux::Initialize();
363c4f89d7STamas Berghammer 
37b9c1b51eSKate Stone   if (g_initialize_count++ == 0) {
381c6a1ea9STamas Berghammer #if defined(__ANDROID__)
391c6a1ea9STamas Berghammer     PlatformSP default_platform_sp(new PlatformAndroid(true));
401c6a1ea9STamas Berghammer     default_platform_sp->SetSystemArchitecture(HostInfo::GetArchitecture());
411c6a1ea9STamas Berghammer     Platform::SetHostPlatform(default_platform_sp);
421c6a1ea9STamas Berghammer #endif
43b9c1b51eSKate Stone     PluginManager::RegisterPlugin(
44b9c1b51eSKate Stone         PlatformAndroid::GetPluginNameStatic(false),
451c6a1ea9STamas Berghammer         PlatformAndroid::GetPluginDescriptionStatic(false),
4600e305d2STamas Berghammer         PlatformAndroid::CreateInstance);
4700e305d2STamas Berghammer   }
4800e305d2STamas Berghammer }
4900e305d2STamas Berghammer 
50b9c1b51eSKate Stone void PlatformAndroid::Terminate() {
51b9c1b51eSKate Stone   if (g_initialize_count > 0) {
52b9c1b51eSKate Stone     if (--g_initialize_count == 0) {
5300e305d2STamas Berghammer       PluginManager::UnregisterPlugin(PlatformAndroid::CreateInstance);
5400e305d2STamas Berghammer     }
5500e305d2STamas Berghammer   }
563c4f89d7STamas Berghammer 
573c4f89d7STamas Berghammer   PlatformLinux::Terminate();
5800e305d2STamas Berghammer }
5900e305d2STamas Berghammer 
60b9c1b51eSKate Stone PlatformSP PlatformAndroid::CreateInstance(bool force, const ArchSpec *arch) {
61db264a6dSTamas Berghammer   Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM));
62b9c1b51eSKate Stone   if (log) {
6300e305d2STamas Berghammer     const char *arch_name;
6400e305d2STamas Berghammer     if (arch && arch->GetArchitectureName())
6500e305d2STamas Berghammer       arch_name = arch->GetArchitectureName();
6600e305d2STamas Berghammer     else
6700e305d2STamas Berghammer       arch_name = "<null>";
6800e305d2STamas Berghammer 
69b9c1b51eSKate Stone     const char *triple_cstr =
70b9c1b51eSKate Stone         arch ? arch->GetTriple().getTriple().c_str() : "<null>";
7100e305d2STamas Berghammer 
72b9c1b51eSKate Stone     log->Printf("PlatformAndroid::%s(force=%s, arch={%s,%s})", __FUNCTION__,
73b9c1b51eSKate Stone                 force ? "true" : "false", arch_name, triple_cstr);
7400e305d2STamas Berghammer   }
7500e305d2STamas Berghammer 
7600e305d2STamas Berghammer   bool create = force;
77b9c1b51eSKate Stone   if (create == false && arch && arch->IsValid()) {
7800e305d2STamas Berghammer     const llvm::Triple &triple = arch->GetTriple();
79b9c1b51eSKate Stone     switch (triple.getVendor()) {
8000e305d2STamas Berghammer     case llvm::Triple::PC:
8100e305d2STamas Berghammer       create = true;
8200e305d2STamas Berghammer       break;
8300e305d2STamas Berghammer 
8400e305d2STamas Berghammer #if defined(__ANDROID__)
8500e305d2STamas Berghammer     // Only accept "unknown" for the vendor if the host is android and
8600e305d2STamas Berghammer     // it "unknown" wasn't specified (it was just returned because it
8700e305d2STamas Berghammer     // was NOT specified_
8800e305d2STamas Berghammer     case llvm::Triple::VendorType::UnknownVendor:
8900e305d2STamas Berghammer       create = !arch->TripleVendorWasSpecified();
9000e305d2STamas Berghammer       break;
9100e305d2STamas Berghammer #endif
9200e305d2STamas Berghammer     default:
9300e305d2STamas Berghammer       break;
9400e305d2STamas Berghammer     }
9500e305d2STamas Berghammer 
96b9c1b51eSKate Stone     if (create) {
97b9c1b51eSKate Stone       switch (triple.getOS()) {
981c6a1ea9STamas Berghammer       case llvm::Triple::Android:
9900e305d2STamas Berghammer         break;
10000e305d2STamas Berghammer 
10100e305d2STamas Berghammer #if defined(__ANDROID__)
10200e305d2STamas Berghammer       // Only accept "unknown" for the OS if the host is android and
10300e305d2STamas Berghammer       // it "unknown" wasn't specified (it was just returned because it
10400e305d2STamas Berghammer       // was NOT specified)
10500e305d2STamas Berghammer       case llvm::Triple::OSType::UnknownOS:
10600e305d2STamas Berghammer         create = !arch->TripleOSWasSpecified();
10700e305d2STamas Berghammer         break;
10800e305d2STamas Berghammer #endif
10900e305d2STamas Berghammer       default:
11000e305d2STamas Berghammer         create = false;
11100e305d2STamas Berghammer         break;
11200e305d2STamas Berghammer       }
11300e305d2STamas Berghammer     }
11400e305d2STamas Berghammer   }
11500e305d2STamas Berghammer 
116b9c1b51eSKate Stone   if (create) {
11700e305d2STamas Berghammer     if (log)
118b9c1b51eSKate Stone       log->Printf("PlatformAndroid::%s() creating remote-android platform",
119b9c1b51eSKate Stone                   __FUNCTION__);
1201c6a1ea9STamas Berghammer     return PlatformSP(new PlatformAndroid(false));
12100e305d2STamas Berghammer   }
12200e305d2STamas Berghammer 
12300e305d2STamas Berghammer   if (log)
124b9c1b51eSKate Stone     log->Printf(
125b9c1b51eSKate Stone         "PlatformAndroid::%s() aborting creation of remote-android platform",
126b9c1b51eSKate Stone         __FUNCTION__);
12700e305d2STamas Berghammer 
12800e305d2STamas Berghammer   return PlatformSP();
12900e305d2STamas Berghammer }
13000e305d2STamas Berghammer 
131b9c1b51eSKate Stone PlatformAndroid::PlatformAndroid(bool is_host)
132b9c1b51eSKate Stone     : PlatformLinux(is_host), m_sdk_version(0) {}
13300e305d2STamas Berghammer 
134b9c1b51eSKate Stone PlatformAndroid::~PlatformAndroid() {}
13500e305d2STamas Berghammer 
136b9c1b51eSKate Stone ConstString PlatformAndroid::GetPluginNameStatic(bool is_host) {
137b9c1b51eSKate Stone   if (is_host) {
1381c6a1ea9STamas Berghammer     static ConstString g_host_name(Platform::GetHostPlatformName());
1391c6a1ea9STamas Berghammer     return g_host_name;
140b9c1b51eSKate Stone   } else {
14100e305d2STamas Berghammer     static ConstString g_remote_name("remote-android");
14200e305d2STamas Berghammer     return g_remote_name;
14300e305d2STamas Berghammer   }
1441c6a1ea9STamas Berghammer }
14500e305d2STamas Berghammer 
146b9c1b51eSKate Stone const char *PlatformAndroid::GetPluginDescriptionStatic(bool is_host) {
1471c6a1ea9STamas Berghammer   if (is_host)
1481c6a1ea9STamas Berghammer     return "Local Android user platform plug-in.";
1491c6a1ea9STamas Berghammer   else
15000e305d2STamas Berghammer     return "Remote Android user platform plug-in.";
15100e305d2STamas Berghammer }
15200e305d2STamas Berghammer 
153b9c1b51eSKate Stone ConstString PlatformAndroid::GetPluginName() {
1541c6a1ea9STamas Berghammer   return GetPluginNameStatic(IsHost());
15500e305d2STamas Berghammer }
15600e305d2STamas Berghammer 
157b9c1b51eSKate Stone Error PlatformAndroid::ConnectRemote(Args &args) {
1586f001068SOleksiy Vyalov   m_device_id.clear();
1596f001068SOleksiy Vyalov 
160b9c1b51eSKate Stone   if (IsHost()) {
161b9c1b51eSKate Stone     return Error("can't connect to the host platform '%s', always connected",
162b9c1b51eSKate Stone                  GetPluginName().GetCString());
1631c6a1ea9STamas Berghammer   }
1641c6a1ea9STamas Berghammer 
16500e305d2STamas Berghammer   if (!m_remote_platform_sp)
16600e305d2STamas Berghammer     m_remote_platform_sp = PlatformSP(new PlatformAndroidRemoteGDBServer());
1676f001068SOleksiy Vyalov 
1683ea689b3SChaoren Lin   int port;
169245f7fdcSZachary Turner   llvm::StringRef scheme, host, path;
1703ea689b3SChaoren Lin   const char *url = args.GetArgumentAtIndex(0);
1713ea689b3SChaoren Lin   if (!url)
1723ea689b3SChaoren Lin     return Error("URL is null.");
1733ea689b3SChaoren Lin   if (!UriParser::Parse(url, scheme, host, port, path))
1743ea689b3SChaoren Lin     return Error("Invalid URL: %s", url);
175a29d6475SOleksiy Vyalov   if (host != "localhost")
1763ea689b3SChaoren Lin     m_device_id = host;
1773ea689b3SChaoren Lin 
1786f001068SOleksiy Vyalov   auto error = PlatformLinux::ConnectRemote(args);
179b9c1b51eSKate Stone   if (error.Success()) {
180d6a143fcSOleksiy Vyalov     AdbClient adb;
181d6a143fcSOleksiy Vyalov     error = AdbClient::CreateByDeviceID(m_device_id, adb);
1826f001068SOleksiy Vyalov     if (error.Fail())
1836f001068SOleksiy Vyalov       return error;
1846f001068SOleksiy Vyalov 
185d6a143fcSOleksiy Vyalov     m_device_id = adb.GetDeviceID();
1866f001068SOleksiy Vyalov   }
1876f001068SOleksiy Vyalov   return error;
1886f001068SOleksiy Vyalov }
1896f001068SOleksiy Vyalov 
190b9c1b51eSKate Stone Error PlatformAndroid::GetFile(const FileSpec &source,
191b9c1b51eSKate Stone                                const FileSpec &destination) {
192291f59c5SOleksiy Vyalov   if (IsHost() || !m_remote_platform_sp)
1930b5ebef7SOleksiy Vyalov     return PlatformLinux::GetFile(source, destination);
194291f59c5SOleksiy Vyalov 
195b9c1b51eSKate Stone   FileSpec source_spec(source.GetPath(false), false,
196b9c1b51eSKate Stone                        FileSpec::ePathSyntaxPosix);
197372e9067SChaoren Lin   if (source_spec.IsRelative())
198b9c1b51eSKate Stone     source_spec = GetRemoteWorkingDirectory().CopyByAppendingPathComponent(
199b9c1b51eSKate Stone         source_spec.GetCString(false));
200291f59c5SOleksiy Vyalov 
201d6a143fcSOleksiy Vyalov   Error error;
202d6a143fcSOleksiy Vyalov   auto sync_service = GetSyncService(error);
203d6a143fcSOleksiy Vyalov   if (error.Fail())
204d6a143fcSOleksiy Vyalov     return error;
205d6a143fcSOleksiy Vyalov 
206c6ac2e1eSOleksiy Vyalov   uint32_t mode = 0, size = 0, mtime = 0;
207c6ac2e1eSOleksiy Vyalov   error = sync_service->Stat(source_spec, mode, size, mtime);
208c6ac2e1eSOleksiy Vyalov   if (error.Fail())
209c6ac2e1eSOleksiy Vyalov     return error;
210c6ac2e1eSOleksiy Vyalov 
211c6ac2e1eSOleksiy Vyalov   if (mode != 0)
212d6a143fcSOleksiy Vyalov     return sync_service->PullFile(source_spec, destination);
213c6ac2e1eSOleksiy Vyalov 
214c6ac2e1eSOleksiy Vyalov   auto source_file = source_spec.GetCString(false);
215c6ac2e1eSOleksiy Vyalov 
216c6ac2e1eSOleksiy Vyalov   Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM));
217c6ac2e1eSOleksiy Vyalov   if (log)
218b9c1b51eSKate Stone     log->Printf("Got mode == 0 on '%s': try to get file via 'shell cat'",
219b9c1b51eSKate Stone                 source_file);
220c6ac2e1eSOleksiy Vyalov 
221c6ac2e1eSOleksiy Vyalov   if (strchr(source_file, '\'') != nullptr)
222c6ac2e1eSOleksiy Vyalov     return Error("Doesn't support single-quotes in filenames");
223c6ac2e1eSOleksiy Vyalov 
224c6ac2e1eSOleksiy Vyalov   // mode == 0 can signify that adbd cannot access the file
225c6ac2e1eSOleksiy Vyalov   // due security constraints - try "cat ..." as a fallback.
226c6ac2e1eSOleksiy Vyalov   AdbClient adb(m_device_id);
227c6ac2e1eSOleksiy Vyalov 
228c6ac2e1eSOleksiy Vyalov   char cmd[PATH_MAX];
229c6ac2e1eSOleksiy Vyalov   snprintf(cmd, sizeof(cmd), "cat '%s'", source_file);
230c6ac2e1eSOleksiy Vyalov 
231ce255ff2SPavel Labath   return adb.ShellToFile(cmd, minutes(1), destination);
2320b5ebef7SOleksiy Vyalov }
2330b5ebef7SOleksiy Vyalov 
234b9c1b51eSKate Stone Error PlatformAndroid::PutFile(const FileSpec &source,
235b9c1b51eSKate Stone                                const FileSpec &destination, uint32_t uid,
236b9c1b51eSKate Stone                                uint32_t gid) {
23717701b59SOleksiy Vyalov   if (IsHost() || !m_remote_platform_sp)
23817701b59SOleksiy Vyalov     return PlatformLinux::PutFile(source, destination, uid, gid);
23917701b59SOleksiy Vyalov 
240b9c1b51eSKate Stone   FileSpec destination_spec(destination.GetPath(false), false,
241b9c1b51eSKate Stone                             FileSpec::ePathSyntaxPosix);
242372e9067SChaoren Lin   if (destination_spec.IsRelative())
243b9c1b51eSKate Stone     destination_spec = GetRemoteWorkingDirectory().CopyByAppendingPathComponent(
244b9c1b51eSKate Stone         destination_spec.GetCString(false));
24517701b59SOleksiy Vyalov 
24662efb1f6SRobert Flack   // TODO: Set correct uid and gid on remote file.
247d6a143fcSOleksiy Vyalov   Error error;
248d6a143fcSOleksiy Vyalov   auto sync_service = GetSyncService(error);
249d6a143fcSOleksiy Vyalov   if (error.Fail())
250d6a143fcSOleksiy Vyalov     return error;
251d6a143fcSOleksiy Vyalov   return sync_service->PushFile(source, destination_spec);
25262efb1f6SRobert Flack }
25362efb1f6SRobert Flack 
254b9c1b51eSKate Stone const char *PlatformAndroid::GetCacheHostname() { return m_device_id.c_str(); }
25509e9079dSOleksiy Vyalov 
256b9c1b51eSKate Stone Error PlatformAndroid::DownloadModuleSlice(const FileSpec &src_file_spec,
25709e9079dSOleksiy Vyalov                                            const uint64_t src_offset,
25809e9079dSOleksiy Vyalov                                            const uint64_t src_size,
259b9c1b51eSKate Stone                                            const FileSpec &dst_file_spec) {
26009e9079dSOleksiy Vyalov   if (src_offset != 0)
26109e9079dSOleksiy Vyalov     return Error("Invalid offset - %" PRIu64, src_offset);
26209e9079dSOleksiy Vyalov 
2630b5ebef7SOleksiy Vyalov   return GetFile(src_file_spec, dst_file_spec);
26409e9079dSOleksiy Vyalov }
2651d0d90b9STamas Berghammer 
266b9c1b51eSKate Stone Error PlatformAndroid::DisconnectRemote() {
2671d0d90b9STamas Berghammer   Error error = PlatformLinux::DisconnectRemote();
268b9c1b51eSKate Stone   if (error.Success()) {
2691d0d90b9STamas Berghammer     m_device_id.clear();
2701d0d90b9STamas Berghammer     m_sdk_version = 0;
2711d0d90b9STamas Berghammer   }
2721d0d90b9STamas Berghammer   return error;
2731d0d90b9STamas Berghammer }
2741d0d90b9STamas Berghammer 
275b9c1b51eSKate Stone uint32_t PlatformAndroid::GetDefaultMemoryCacheLineSize() {
276f2991488SPavel Labath   return g_android_default_cache_size;
277f2991488SPavel Labath }
278f2991488SPavel Labath 
279b9c1b51eSKate Stone uint32_t PlatformAndroid::GetSdkVersion() {
2801d0d90b9STamas Berghammer   if (!IsConnected())
2811d0d90b9STamas Berghammer     return 0;
2821d0d90b9STamas Berghammer 
2831d0d90b9STamas Berghammer   if (m_sdk_version != 0)
2841d0d90b9STamas Berghammer     return m_sdk_version;
2851d0d90b9STamas Berghammer 
2861d0d90b9STamas Berghammer   std::string version_string;
287d6a143fcSOleksiy Vyalov   AdbClient adb(m_device_id);
288b9c1b51eSKate Stone   Error error =
289ce255ff2SPavel Labath       adb.Shell("getprop ro.build.version.sdk", seconds(5), &version_string);
2903e8947beSTamas Berghammer   version_string = llvm::StringRef(version_string).trim().str();
2913e8947beSTamas Berghammer 
292b9c1b51eSKate Stone   if (error.Fail() || version_string.empty()) {
2931d0d90b9STamas Berghammer     Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM);
2941d0d90b9STamas Berghammer     if (log)
2953e8947beSTamas Berghammer       log->Printf("Get SDK version failed. (error: %s, output: %s)",
2963e8947beSTamas Berghammer                   error.AsCString(), version_string.c_str());
2971d0d90b9STamas Berghammer     return 0;
2981d0d90b9STamas Berghammer   }
2991d0d90b9STamas Berghammer 
3001d0d90b9STamas Berghammer   m_sdk_version = StringConvert::ToUInt32(version_string.c_str());
3011d0d90b9STamas Berghammer   return m_sdk_version;
3021d0d90b9STamas Berghammer }
303ec3f92a5STamas Berghammer 
304b9c1b51eSKate Stone Error PlatformAndroid::DownloadSymbolFile(const lldb::ModuleSP &module_sp,
305b9c1b51eSKate Stone                                           const FileSpec &dst_file_spec) {
306ec3f92a5STamas Berghammer   // For oat file we can try to fetch additional debug info from the device
307dba6503aSTamas Berghammer   ConstString extension = module_sp->GetFileSpec().GetFileNameExtension();
308dba6503aSTamas Berghammer   if (extension != ConstString("oat") && extension != ConstString("odex"))
309b9c1b51eSKate Stone     return Error(
310b9c1b51eSKate Stone         "Symbol file downloading only supported for oat and odex files");
311ec3f92a5STamas Berghammer 
312ec3f92a5STamas Berghammer   // If we have no information about the platform file we can't execute oatdump
313ec3f92a5STamas Berghammer   if (!module_sp->GetPlatformFileSpec())
314ec3f92a5STamas Berghammer     return Error("No platform file specified");
315ec3f92a5STamas Berghammer 
316ec3f92a5STamas Berghammer   // Symbolizer isn't available before SDK version 23
317ec3f92a5STamas Berghammer   if (GetSdkVersion() < 23)
318ec3f92a5STamas Berghammer     return Error("Symbol file generation only supported on SDK 23+");
319ec3f92a5STamas Berghammer 
320ec3f92a5STamas Berghammer   // If we already have symtab then we don't have to try and generate one
321b9c1b51eSKate Stone   if (module_sp->GetSectionList()->FindSectionByName(ConstString(".symtab")) !=
322b9c1b51eSKate Stone       nullptr)
323ec3f92a5STamas Berghammer     return Error("Symtab already available in the module");
324ec3f92a5STamas Berghammer 
325d6a143fcSOleksiy Vyalov   AdbClient adb(m_device_id);
3269d8dde8cSTamas Berghammer   std::string tmpdir;
327b9c1b51eSKate Stone   Error error = adb.Shell("mktemp --directory --tmpdir /data/local/tmp",
328ce255ff2SPavel Labath                           seconds(5), &tmpdir);
3299d8dde8cSTamas Berghammer   if (error.Fail() || tmpdir.empty())
330b9c1b51eSKate Stone     return Error("Failed to generate temporary directory on the device (%s)",
331b9c1b51eSKate Stone                  error.AsCString());
332539cd118STamas Berghammer   tmpdir = llvm::StringRef(tmpdir).trim().str();
333ec3f92a5STamas Berghammer 
334ec3f92a5STamas Berghammer   // Create file remover for the temporary directory created on the device
335b9c1b51eSKate Stone   std::unique_ptr<std::string, std::function<void(std::string *)>>
336*3bc714b2SZachary Turner   tmpdir_remover(&tmpdir, [&adb](std::string *s) {
337ec3f92a5STamas Berghammer     StreamString command;
338ec3f92a5STamas Berghammer     command.Printf("rm -rf %s", s->c_str());
339ce255ff2SPavel Labath     Error error = adb.Shell(command.GetData(), seconds(5), nullptr);
340ec3f92a5STamas Berghammer 
341ec3f92a5STamas Berghammer     Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM));
342dd778ca6SOleksiy Vyalov     if (log && error.Fail())
343ec3f92a5STamas Berghammer       log->Printf("Failed to remove temp directory: %s", error.AsCString());
344b9c1b51eSKate Stone   });
345ec3f92a5STamas Berghammer 
346771ef6d4SMalcolm Parsons   FileSpec symfile_platform_filespec(tmpdir, false);
347ec3f92a5STamas Berghammer   symfile_platform_filespec.AppendPathComponent("symbolized.oat");
348ec3f92a5STamas Berghammer 
349ec3f92a5STamas Berghammer   // Execute oatdump on the remote device to generate a file with symtab
3509d8dde8cSTamas Berghammer   StreamString command;
351ec3f92a5STamas Berghammer   command.Printf("oatdump --symbolize=%s --output=%s",
352ec3f92a5STamas Berghammer                  module_sp->GetPlatformFileSpec().GetCString(false),
353ec3f92a5STamas Berghammer                  symfile_platform_filespec.GetCString(false));
354ce255ff2SPavel Labath   error = adb.Shell(command.GetData(), minutes(1), nullptr);
3559d8dde8cSTamas Berghammer   if (error.Fail())
356ec3f92a5STamas Berghammer     return Error("Oatdump failed: %s", error.AsCString());
357ec3f92a5STamas Berghammer 
358ec3f92a5STamas Berghammer   // Download the symbolfile from the remote device
359ec3f92a5STamas Berghammer   return GetFile(symfile_platform_filespec, dst_file_spec);
360ec3f92a5STamas Berghammer }
3613c47151dSTamas Berghammer 
362b9c1b51eSKate Stone bool PlatformAndroid::GetRemoteOSVersion() {
3633c47151dSTamas Berghammer   m_major_os_version = GetSdkVersion();
3643c47151dSTamas Berghammer   m_minor_os_version = 0;
3653c47151dSTamas Berghammer   m_update_os_version = 0;
3663c47151dSTamas Berghammer   return m_major_os_version != 0;
3673c47151dSTamas Berghammer }
3683cb132a0STamas Berghammer 
369b9c1b51eSKate Stone const char *PlatformAndroid::GetLibdlFunctionDeclarations() const {
370fcdde63fSTamas Berghammer   return R"(
371fcdde63fSTamas Berghammer               extern "C" void* dlopen(const char*, int) asm("__dl_dlopen");
372fcdde63fSTamas Berghammer               extern "C" void* dlsym(void*, const char*) asm("__dl_dlsym");
373fcdde63fSTamas Berghammer               extern "C" int   dlclose(void*) asm("__dl_dlclose");
374fcdde63fSTamas Berghammer               extern "C" char* dlerror(void) asm("__dl_dlerror");
3753cb132a0STamas Berghammer              )";
3763cb132a0STamas Berghammer }
377d6a143fcSOleksiy Vyalov 
378b9c1b51eSKate Stone AdbClient::SyncService *PlatformAndroid::GetSyncService(Error &error) {
379d6a143fcSOleksiy Vyalov   if (m_adb_sync_svc && m_adb_sync_svc->IsConnected())
380d6a143fcSOleksiy Vyalov     return m_adb_sync_svc.get();
381d6a143fcSOleksiy Vyalov 
382d6a143fcSOleksiy Vyalov   AdbClient adb(m_device_id);
383d6a143fcSOleksiy Vyalov   m_adb_sync_svc = adb.GetSyncService(error);
384d6a143fcSOleksiy Vyalov   return (error.Success()) ? m_adb_sync_svc.get() : nullptr;
385d6a143fcSOleksiy Vyalov }
386