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