LLDB  mainline
PlatformAndroid.cpp
Go to the documentation of this file.
1 //===-- PlatformAndroid.cpp -----------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "lldb/Core/Module.h"
11 #include "lldb/Core/Section.h"
12 #include "lldb/Core/ValueObject.h"
13 #include "lldb/Host/HostInfo.h"
15 #include "lldb/Utility/Log.h"
16 #include "lldb/Utility/Scalar.h"
17 #include "lldb/Utility/UriParser.h"
18 
19 #include "AdbClient.h"
20 #include "PlatformAndroid.h"
22 #include "lldb/Target/Target.h"
23 
24 using namespace lldb;
25 using namespace lldb_private;
26 using namespace lldb_private::platform_android;
27 using namespace std::chrono;
28 
30 
32 static const unsigned int g_android_default_cache_size =
33  2048; // Fits inside 4k adb packet.
34 
35 void PlatformAndroid::Initialize() {
36  PlatformLinux::Initialize();
37 
38  if (g_initialize_count++ == 0) {
39 #if defined(__ANDROID__)
40  PlatformSP default_platform_sp(new PlatformAndroid(true));
41  default_platform_sp->SetSystemArchitecture(HostInfo::GetArchitecture());
42  Platform::SetHostPlatform(default_platform_sp);
43 #endif
44  PluginManager::RegisterPlugin(
45  PlatformAndroid::GetPluginNameStatic(false),
46  PlatformAndroid::GetPluginDescriptionStatic(false),
47  PlatformAndroid::CreateInstance);
48  }
49 }
50 
51 void PlatformAndroid::Terminate() {
52  if (g_initialize_count > 0) {
53  if (--g_initialize_count == 0) {
54  PluginManager::UnregisterPlugin(PlatformAndroid::CreateInstance);
55  }
56  }
57 
58  PlatformLinux::Terminate();
59 }
60 
61 PlatformSP PlatformAndroid::CreateInstance(bool force, const ArchSpec *arch) {
63  if (log) {
64  const char *arch_name;
65  if (arch && arch->GetArchitectureName())
66  arch_name = arch->GetArchitectureName();
67  else
68  arch_name = "<null>";
69 
70  const char *triple_cstr =
71  arch ? arch->GetTriple().getTriple().c_str() : "<null>";
72 
73  LLDB_LOGF(log, "PlatformAndroid::%s(force=%s, arch={%s,%s})", __FUNCTION__,
74  force ? "true" : "false", arch_name, triple_cstr);
75  }
76 
77  bool create = force;
78  if (!create && arch && arch->IsValid()) {
79  const llvm::Triple &triple = arch->GetTriple();
80  switch (triple.getVendor()) {
81  case llvm::Triple::PC:
82  create = true;
83  break;
84 
85 #if defined(__ANDROID__)
86  // Only accept "unknown" for the vendor if the host is android and if
87  // "unknown" wasn't specified (it was just returned because it was NOT
88  // specified).
89  case llvm::Triple::VendorType::UnknownVendor:
90  create = !arch->TripleVendorWasSpecified();
91  break;
92 #endif
93  default:
94  break;
95  }
96 
97  if (create) {
98  switch (triple.getEnvironment()) {
99  case llvm::Triple::Android:
100  break;
101 
102 #if defined(__ANDROID__)
103  // Only accept "unknown" for the OS if the host is android and it
104  // "unknown" wasn't specified (it was just returned because it was NOT
105  // specified)
106  case llvm::Triple::EnvironmentType::UnknownEnvironment:
107  create = !arch->TripleEnvironmentWasSpecified();
108  break;
109 #endif
110  default:
111  create = false;
112  break;
113  }
114  }
115  }
116 
117  if (create) {
118  LLDB_LOGF(log, "PlatformAndroid::%s() creating remote-android platform",
119  __FUNCTION__);
120  return PlatformSP(new PlatformAndroid(false));
121  }
122 
123  LLDB_LOGF(
124  log, "PlatformAndroid::%s() aborting creation of remote-android platform",
125  __FUNCTION__);
126 
127  return PlatformSP();
128 }
129 
130 PlatformAndroid::PlatformAndroid(bool is_host)
131  : PlatformLinux(is_host), m_sdk_version(0) {}
132 
134  if (is_host) {
135  static ConstString g_host_name(Platform::GetHostPlatformName());
136  return g_host_name;
137  } else {
138  static ConstString g_remote_name("remote-android");
139  return g_remote_name;
140  }
141 }
142 
144  if (is_host)
145  return "Local Android user platform plug-in.";
146  else
147  return "Remote Android user platform plug-in.";
148 }
149 
151  return GetPluginNameStatic(IsHost());
152 }
153 
155  m_device_id.clear();
156 
157  if (IsHost()) {
158  return Status("can't connect to the host platform '%s', always connected",
159  GetPluginName().GetCString());
160  }
161 
164 
165  int port;
166  llvm::StringRef scheme, host, path;
167  const char *url = args.GetArgumentAtIndex(0);
168  if (!url)
169  return Status("URL is null.");
170  if (!UriParser::Parse(url, scheme, host, port, path))
171  return Status("Invalid URL: %s", url);
172  if (host != "localhost")
173  m_device_id = std::string(host);
174 
175  auto error = PlatformLinux::ConnectRemote(args);
176  if (error.Success()) {
177  AdbClient adb;
179  if (error.Fail())
180  return error;
181 
182  m_device_id = adb.GetDeviceID();
183  }
184  return error;
185 }
186 
188  const FileSpec &destination) {
189  if (IsHost() || !m_remote_platform_sp)
190  return PlatformLinux::GetFile(source, destination);
191 
192  FileSpec source_spec(source.GetPath(false), FileSpec::Style::posix);
193  if (source_spec.IsRelative())
195  source_spec.GetCString(false));
196 
197  Status error;
198  auto sync_service = GetSyncService(error);
199  if (error.Fail())
200  return error;
201 
202  uint32_t mode = 0, size = 0, mtime = 0;
203  error = sync_service->Stat(source_spec, mode, size, mtime);
204  if (error.Fail())
205  return error;
206 
207  if (mode != 0)
208  return sync_service->PullFile(source_spec, destination);
209 
210  auto source_file = source_spec.GetCString(false);
211 
213  LLDB_LOGF(log, "Got mode == 0 on '%s': try to get file via 'shell cat'",
214  source_file);
215 
216  if (strchr(source_file, '\'') != nullptr)
217  return Status("Doesn't support single-quotes in filenames");
218 
219  // mode == 0 can signify that adbd cannot access the file due security
220  // constraints - try "cat ..." as a fallback.
221  AdbClient adb(m_device_id);
222 
223  char cmd[PATH_MAX];
224  snprintf(cmd, sizeof(cmd), "cat '%s'", source_file);
225 
226  return adb.ShellToFile(cmd, minutes(1), destination);
227 }
228 
230  const FileSpec &destination, uint32_t uid,
231  uint32_t gid) {
232  if (IsHost() || !m_remote_platform_sp)
233  return PlatformLinux::PutFile(source, destination, uid, gid);
234 
235  FileSpec destination_spec(destination.GetPath(false), FileSpec::Style::posix);
236  if (destination_spec.IsRelative())
238  destination_spec.GetCString(false));
239 
240  // TODO: Set correct uid and gid on remote file.
241  Status error;
242  auto sync_service = GetSyncService(error);
243  if (error.Fail())
244  return error;
245  return sync_service->PushFile(source, destination_spec);
246 }
247 
248 const char *PlatformAndroid::GetCacheHostname() { return m_device_id.c_str(); }
249 
251  const uint64_t src_offset,
252  const uint64_t src_size,
253  const FileSpec &dst_file_spec) {
254  if (src_offset != 0)
255  return Status("Invalid offset - %" PRIu64, src_offset);
256 
257  return GetFile(src_file_spec, dst_file_spec);
258 }
259 
261  Status error = PlatformLinux::DisconnectRemote();
262  if (error.Success()) {
263  m_device_id.clear();
264  m_sdk_version = 0;
265  }
266  return error;
267 }
268 
271 }
272 
274  if (!IsConnected())
275  return 0;
276 
277  if (m_sdk_version != 0)
278  return m_sdk_version;
279 
280  std::string version_string;
281  AdbClient adb(m_device_id);
282  Status error =
283  adb.Shell("getprop ro.build.version.sdk", seconds(5), &version_string);
284  version_string = llvm::StringRef(version_string).trim().str();
285 
286  if (error.Fail() || version_string.empty()) {
288  LLDB_LOGF(log, "Get SDK version failed. (error: %s, output: %s)",
289  error.AsCString(), version_string.c_str());
290  return 0;
291  }
292 
293  m_sdk_version = StringConvert::ToUInt32(version_string.c_str());
294  return m_sdk_version;
295 }
296 
297 Status PlatformAndroid::DownloadSymbolFile(const lldb::ModuleSP &module_sp,
298  const FileSpec &dst_file_spec) {
299  // For oat file we can try to fetch additional debug info from the device
300  ConstString extension = module_sp->GetFileSpec().GetFileNameExtension();
301  if (extension != ".oat" && extension != ".odex")
302  return Status(
303  "Symbol file downloading only supported for oat and odex files");
304 
305  // If we have no information about the platform file we can't execute oatdump
306  if (!module_sp->GetPlatformFileSpec())
307  return Status("No platform file specified");
308 
309  // Symbolizer isn't available before SDK version 23
310  if (GetSdkVersion() < 23)
311  return Status("Symbol file generation only supported on SDK 23+");
312 
313  // If we already have symtab then we don't have to try and generate one
314  if (module_sp->GetSectionList()->FindSectionByName(ConstString(".symtab")) !=
315  nullptr)
316  return Status("Symtab already available in the module");
317 
318  AdbClient adb(m_device_id);
319  std::string tmpdir;
320  Status error = adb.Shell("mktemp --directory --tmpdir /data/local/tmp",
321  seconds(5), &tmpdir);
322  if (error.Fail() || tmpdir.empty())
323  return Status("Failed to generate temporary directory on the device (%s)",
324  error.AsCString());
325  tmpdir = llvm::StringRef(tmpdir).trim().str();
326 
327  // Create file remover for the temporary directory created on the device
328  std::unique_ptr<std::string, std::function<void(std::string *)>>
329  tmpdir_remover(&tmpdir, [&adb](std::string *s) {
330  StreamString command;
331  command.Printf("rm -rf %s", s->c_str());
332  Status error = adb.Shell(command.GetData(), seconds(5), nullptr);
333 
335  if (log && error.Fail())
336  LLDB_LOGF(log, "Failed to remove temp directory: %s", error.AsCString());
337  });
338 
339  FileSpec symfile_platform_filespec(tmpdir);
340  symfile_platform_filespec.AppendPathComponent("symbolized.oat");
341 
342  // Execute oatdump on the remote device to generate a file with symtab
343  StreamString command;
344  command.Printf("oatdump --symbolize=%s --output=%s",
345  module_sp->GetPlatformFileSpec().GetCString(false),
346  symfile_platform_filespec.GetCString(false));
347  error = adb.Shell(command.GetData(), minutes(1), nullptr);
348  if (error.Fail())
349  return Status("Oatdump failed: %s", error.AsCString());
350 
351  // Download the symbolfile from the remote device
352  return GetFile(symfile_platform_filespec, dst_file_spec);
353 }
354 
356  m_os_version = llvm::VersionTuple(GetSdkVersion());
357  return !m_os_version.empty();
358 }
359 
360 llvm::StringRef
362  SymbolContextList matching_symbols;
363  std::vector<const char *> dl_open_names = { "__dl_dlopen", "dlopen" };
364  const char *dl_open_name = nullptr;
365  Target &target = process->GetTarget();
366  for (auto name: dl_open_names) {
368  ConstString(name), eFunctionNameTypeFull, matching_symbols);
369  if (matching_symbols.GetSize()) {
370  dl_open_name = name;
371  break;
372  }
373  }
374  // Older platform versions have the dl function symbols mangled
375  if (dl_open_name == dl_open_names[0])
376  return R"(
377  extern "C" void* dlopen(const char*, int) asm("__dl_dlopen");
378  extern "C" void* dlsym(void*, const char*) asm("__dl_dlsym");
379  extern "C" int dlclose(void*) asm("__dl_dlclose");
380  extern "C" char* dlerror(void) asm("__dl_dlerror");
381  )";
382 
384 }
385 
387  if (m_adb_sync_svc && m_adb_sync_svc->IsConnected())
388  return m_adb_sync_svc.get();
389 
390  AdbClient adb(m_device_id);
392  return (error.Success()) ? m_adb_sync_svc.get() : nullptr;
393 }
lldb_private::RemoteAwarePlatform::IsConnected
bool IsConnected() const override
Definition: RemoteAwarePlatform.cpp:380
Scalar.h
lldb_private::platform_android::AdbClient::CreateByDeviceID
static Status CreateByDeviceID(const std::string &device_id, AdbClient &adb)
Definition: AdbClient.cpp:95
lldb_private::ArchSpec
Definition: ArchSpec.h:33
lldb_private::ArchSpec::TripleVendorWasSpecified
bool TripleVendorWasSpecified() const
Definition: ArchSpec.h:347
lldb_private::platform_android::PlatformAndroid::GetDefaultMemoryCacheLineSize
uint32_t GetDefaultMemoryCacheLineSize() override
Allow the platform to set preferred memory cache line size.
Definition: PlatformAndroid.cpp:269
g_android_default_cache_size
static const unsigned int g_android_default_cache_size
Definition: PlatformAndroid.cpp:32
lldb_private::platform_android::PlatformAndroid::ConnectRemote
Status ConnectRemote(Args &args) override
Definition: PlatformAndroid.cpp:154
lldb_private::platform_android::PlatformAndroid::GetLibdlFunctionDeclarations
llvm::StringRef GetLibdlFunctionDeclarations(lldb_private::Process *process) override
Definition: PlatformAndroid.cpp:361
LLDB_LOGF
#define LLDB_LOGF(log,...)
Definition: Log.h:249
lldb_private::Process
Definition: Process.h:341
Module.h
lldb_private::platform_android::PlatformAndroid::DownloadModuleSlice
Status DownloadModuleSlice(const FileSpec &src_file_spec, const uint64_t src_offset, const uint64_t src_size, const FileSpec &dst_file_spec) override
Definition: PlatformAndroid.cpp:250
lldb_private::Process::GetTarget
Target & GetTarget()
Get the target object pointer for this module.
Definition: Process.h:1194
LIBLLDB_LOG_PLATFORM
#define LIBLLDB_LOG_PLATFORM
Definition: Logging.h:39
lldb_private::SymbolContextList
Definition: SymbolContext.h:379
lldb_private::Platform::m_os_version
llvm::VersionTuple m_os_version
Definition: Platform.h:889
AdbClient.h
lldb_private::platform_android::PlatformAndroid::GetPluginNameStatic
static ConstString GetPluginNameStatic(bool is_host)
Definition: PlatformAndroid.cpp:133
lldb_private::Args
Definition: Args.h:33
lldb_private::ArchSpec::GetTriple
llvm::Triple & GetTriple()
Architecture triple accessor.
Definition: ArchSpec.h:444
lldb_private::platform_android::PlatformAndroid::GetCacheHostname
const char * GetCacheHostname() override
Definition: PlatformAndroid.cpp:248
lldb_private::Target
Definition: Target.h:445
Section.h
lldb_private::Target::GetImages
const ModuleList & GetImages() const
Get accessor for the images for this process.
Definition: Target.h:919
lldb_private::FileSpec::GetCString
const char * GetCString(bool denormalize=true) const
Definition: FileSpec.cpp:364
Target.h
lldb_private::platform_android::PlatformAndroid::GetSdkVersion
uint32_t GetSdkVersion()
Definition: PlatformAndroid.cpp:273
lldb_private::FileSpec
Definition: FileSpec.h:56
error
static llvm::raw_ostream & error(Stream &strm)
Definition: CommandReturnObject.cpp:17
StringConvert.h
Log.h
lldb_private::platform_android
Definition: AdbClient.h:24
lldb_private::platform_android::PlatformAndroid::GetPluginName
ConstString GetPluginName() override
Definition: PlatformAndroid.cpp:150
lldb_private::platform_android::PlatformAndroid::GetSyncService
AdbClient::SyncService * GetSyncService(Status &error)
Definition: PlatformAndroid.cpp:386
lldb_private::platform_android::AdbClient::GetDeviceID
const std::string & GetDeviceID() const
Definition: AdbClient.cpp:131
lldb_private::UriParser::Parse
static bool Parse(llvm::StringRef uri, llvm::StringRef &scheme, llvm::StringRef &hostname, int &port, llvm::StringRef &path)
Definition: UriParser.cpp:19
lldb_private::StreamString::GetData
const char * GetData() const
Definition: StreamString.h:43
lldb_private::RemoteAwarePlatform::m_remote_platform_sp
lldb::PlatformSP m_remote_platform_sp
Definition: RemoteAwarePlatform.h:104
lldb_private::platform_android::PlatformAndroid::PutFile
Status PutFile(const FileSpec &source, const FileSpec &destination, uint32_t uid=UINT32_MAX, uint32_t gid=UINT32_MAX) override
Definition: PlatformAndroid.cpp:229
lldb_private::SymbolContextList::GetSize
uint32_t GetSize() const
Get accessor for a symbol context list size.
Definition: SymbolContext.cpp:1281
lldb_private::ConstString
Definition: ConstString.h:40
lldb_private::StreamString
Definition: StreamString.h:23
lldb_private::GetLogIfAllCategoriesSet
Log * GetLogIfAllCategoriesSet(uint32_t mask)
Definition: Logging.cpp:58
lldb_private::platform_android::PlatformAndroid::DownloadSymbolFile
Status DownloadSymbolFile(const lldb::ModuleSP &module_sp, const FileSpec &dst_file_spec) override
Definition: PlatformAndroid.cpp:297
HostInfo.h
string
string(SUBSTRING ${p} 10 -1 pStripped) if($
Definition: Plugins/CMakeLists.txt:39
lldb_private::ArchSpec::IsValid
bool IsValid() const
Tests if this ArchSpec is valid.
Definition: ArchSpec.h:342
lldb_private::FileSpec::CopyByAppendingPathComponent
FileSpec CopyByAppendingPathComponent(llvm::StringRef component) const
Definition: FileSpec.cpp:400
ValueObject.h
lldb_private::ArchSpec::TripleEnvironmentWasSpecified
bool TripleEnvironmentWasSpecified() const
Definition: ArchSpec.h:353
lldb_private::platform_android::PlatformAndroid
Definition: PlatformAndroid.h:22
lldb_private::platform_android::PlatformAndroid::m_adb_sync_svc
std::unique_ptr< AdbClient::SyncService > m_adb_sync_svc
Definition: PlatformAndroid.h:74
PlatformAndroid.h
lldb_private::Status
Definition: Status.h:44
PlatformPOSIX::GetLibdlFunctionDeclarations
virtual llvm::StringRef GetLibdlFunctionDeclarations(lldb_private::Process *process)
Definition: PlatformPOSIX.cpp:1000
lldb_private::Args::GetArgumentAtIndex
const char * GetArgumentAtIndex(size_t idx) const
Gets the NULL terminated C string argument pointer for the argument at index idx.
Definition: Args.cpp:259
lldb_private::FileSpec::IsRelative
bool IsRelative() const
Returns true if the filespec represents a relative path.
Definition: FileSpec.cpp:475
lldb_private::ArchSpec::GetArchitectureName
const char * GetArchitectureName() const
Returns a static string representing the current architecture.
Definition: ArchSpec.cpp:538
uint32_t
lldb_private::platform_android::AdbClient
Definition: AdbClient.h:26
PlatformAndroidRemoteGDBServer.h
lldb_private::platform_android::AdbClient::GetSyncService
std::unique_ptr< SyncService > GetSyncService(Status &error)
Definition: AdbClient.cpp:421
lldb_private::platform_android::PlatformAndroid::GetPluginDescriptionStatic
static const char * GetPluginDescriptionStatic(bool is_host)
Definition: PlatformAndroid.cpp:143
lldb_private::platform_android::AdbClient::SyncService
Definition: AdbClient.h:35
lldb_private::platform_android::PlatformAndroid::GetRemoteOSVersion
bool GetRemoteOSVersion() override
Definition: PlatformAndroid.cpp:355
lldb_private::platform_android::PlatformAndroid::m_sdk_version
uint32_t m_sdk_version
Definition: PlatformAndroid.h:76
lldb_private::platform_android::PlatformAndroid::m_device_id
std::string m_device_id
Definition: PlatformAndroid.h:75
PluginManager.h
lldb_private::Stream::Printf
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Definition: Stream.cpp:107
lldb_private::platform_android::PlatformAndroidRemoteGDBServer
Definition: PlatformAndroidRemoteGDBServer.h:24
lldb_private
A class that represents a running process on the host machine.
Definition: SBCommandInterpreterRunOptions.h:16
lldb_private::platform_android::PlatformAndroid::DisconnectRemote
Status DisconnectRemote() override
Definition: PlatformAndroid.cpp:260
lldb_private::platform_android::AdbClient::ShellToFile
Status ShellToFile(const char *command, std::chrono::milliseconds timeout, const FileSpec &output_file_spec)
Definition: AdbClient.cpp:400
lldb_private::StringConvert::ToUInt32
uint32_t ToUInt32(const char *s, uint32_t fail_value=0, int base=0, bool *success_ptr=nullptr)
Definition: StringConvert.cpp:32
lldb_private::RemoteAwarePlatform::GetRemoteWorkingDirectory
FileSpec GetRemoteWorkingDirectory() override
Definition: RemoteAwarePlatform.cpp:302
lldb_private::ModuleList::FindFunctionSymbols
void FindFunctionSymbols(ConstString name, lldb::FunctionNameType name_type_mask, SymbolContextList &sc_list)
Definition: ModuleList.cpp:396
LLDB_PLUGIN_DEFINE
#define LLDB_PLUGIN_DEFINE(PluginName)
Definition: PluginManager.h:31
lldb_private::Log
Definition: Log.h:49
UriParser.h
lldb_private::platform_android::PlatformAndroid::GetFile
Status GetFile(const FileSpec &source, const FileSpec &destination) override
Definition: PlatformAndroid.cpp:187
lldb_private::Platform::IsHost
bool IsHost() const
Definition: Platform.h:442
PATH_MAX
#define PATH_MAX
Definition: windows/PosixApi.h:25
lldb_private::FileSpec::GetPath
size_t GetPath(char *path, size_t max_path_length, bool denormalize=true) const
Extract the full path to the file.
Definition: FileSpec.cpp:348
g_initialize_count
static uint32_t g_initialize_count
Definition: PlatformAndroid.cpp:31
lldb_private::Platform::GetHostPlatformName
static const char * GetHostPlatformName()
Definition: Platform.cpp:60
lldb
Definition: SBAddress.h:15
lldb_private::platform_android::AdbClient::Shell
Status Shell(const char *command, std::chrono::milliseconds timeout, std::string *output)
Definition: AdbClient.cpp:388