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 
136  if (is_host) {
137  static ConstString g_host_name(Platform::GetHostPlatformName());
138  return g_host_name;
139  } else {
140  static ConstString g_remote_name("remote-android");
141  return g_remote_name;
142  }
143 }
144 
146  if (is_host)
147  return "Local Android user platform plug-in.";
148  else
149  return "Remote Android user platform plug-in.";
150 }
151 
153  return GetPluginNameStatic(IsHost());
154 }
155 
157  m_device_id.clear();
158 
159  if (IsHost()) {
160  return Status("can't connect to the host platform '%s', always connected",
161  GetPluginName().GetCString());
162  }
163 
166 
167  int port;
168  llvm::StringRef scheme, host, path;
169  const char *url = args.GetArgumentAtIndex(0);
170  if (!url)
171  return Status("URL is null.");
172  if (!UriParser::Parse(url, scheme, host, port, path))
173  return Status("Invalid URL: %s", url);
174  if (host != "localhost")
175  m_device_id = std::string(host);
176 
177  auto error = PlatformLinux::ConnectRemote(args);
178  if (error.Success()) {
179  AdbClient adb;
181  if (error.Fail())
182  return error;
183 
184  m_device_id = adb.GetDeviceID();
185  }
186  return error;
187 }
188 
190  const FileSpec &destination) {
191  if (IsHost() || !m_remote_platform_sp)
192  return PlatformLinux::GetFile(source, destination);
193 
194  FileSpec source_spec(source.GetPath(false), FileSpec::Style::posix);
195  if (source_spec.IsRelative())
197  source_spec.GetCString(false));
198 
199  Status error;
200  auto sync_service = GetSyncService(error);
201  if (error.Fail())
202  return error;
203 
204  uint32_t mode = 0, size = 0, mtime = 0;
205  error = sync_service->Stat(source_spec, mode, size, mtime);
206  if (error.Fail())
207  return error;
208 
209  if (mode != 0)
210  return sync_service->PullFile(source_spec, destination);
211 
212  auto source_file = source_spec.GetCString(false);
213 
215  LLDB_LOGF(log, "Got mode == 0 on '%s': try to get file via 'shell cat'",
216  source_file);
217 
218  if (strchr(source_file, '\'') != nullptr)
219  return Status("Doesn't support single-quotes in filenames");
220 
221  // mode == 0 can signify that adbd cannot access the file due security
222  // constraints - try "cat ..." as a fallback.
223  AdbClient adb(m_device_id);
224 
225  char cmd[PATH_MAX];
226  snprintf(cmd, sizeof(cmd), "cat '%s'", source_file);
227 
228  return adb.ShellToFile(cmd, minutes(1), destination);
229 }
230 
232  const FileSpec &destination, uint32_t uid,
233  uint32_t gid) {
234  if (IsHost() || !m_remote_platform_sp)
235  return PlatformLinux::PutFile(source, destination, uid, gid);
236 
237  FileSpec destination_spec(destination.GetPath(false), FileSpec::Style::posix);
238  if (destination_spec.IsRelative())
240  destination_spec.GetCString(false));
241 
242  // TODO: Set correct uid and gid on remote file.
243  Status error;
244  auto sync_service = GetSyncService(error);
245  if (error.Fail())
246  return error;
247  return sync_service->PushFile(source, destination_spec);
248 }
249 
250 const char *PlatformAndroid::GetCacheHostname() { return m_device_id.c_str(); }
251 
253  const uint64_t src_offset,
254  const uint64_t src_size,
255  const FileSpec &dst_file_spec) {
256  if (src_offset != 0)
257  return Status("Invalid offset - %" PRIu64, src_offset);
258 
259  return GetFile(src_file_spec, dst_file_spec);
260 }
261 
263  Status error = PlatformLinux::DisconnectRemote();
264  if (error.Success()) {
265  m_device_id.clear();
266  m_sdk_version = 0;
267  }
268  return error;
269 }
270 
273 }
274 
276  if (!IsConnected())
277  return 0;
278 
279  if (m_sdk_version != 0)
280  return m_sdk_version;
281 
282  std::string version_string;
283  AdbClient adb(m_device_id);
284  Status error =
285  adb.Shell("getprop ro.build.version.sdk", seconds(5), &version_string);
286  version_string = llvm::StringRef(version_string).trim().str();
287 
288  if (error.Fail() || version_string.empty()) {
290  LLDB_LOGF(log, "Get SDK version failed. (error: %s, output: %s)",
291  error.AsCString(), version_string.c_str());
292  return 0;
293  }
294 
295  m_sdk_version = StringConvert::ToUInt32(version_string.c_str());
296  return m_sdk_version;
297 }
298 
299 Status PlatformAndroid::DownloadSymbolFile(const lldb::ModuleSP &module_sp,
300  const FileSpec &dst_file_spec) {
301  // For oat file we can try to fetch additional debug info from the device
302  ConstString extension = module_sp->GetFileSpec().GetFileNameExtension();
303  if (extension != ".oat" && extension != ".odex")
304  return Status(
305  "Symbol file downloading only supported for oat and odex files");
306 
307  // If we have no information about the platform file we can't execute oatdump
308  if (!module_sp->GetPlatformFileSpec())
309  return Status("No platform file specified");
310 
311  // Symbolizer isn't available before SDK version 23
312  if (GetSdkVersion() < 23)
313  return Status("Symbol file generation only supported on SDK 23+");
314 
315  // If we already have symtab then we don't have to try and generate one
316  if (module_sp->GetSectionList()->FindSectionByName(ConstString(".symtab")) !=
317  nullptr)
318  return Status("Symtab already available in the module");
319 
320  AdbClient adb(m_device_id);
321  std::string tmpdir;
322  Status error = adb.Shell("mktemp --directory --tmpdir /data/local/tmp",
323  seconds(5), &tmpdir);
324  if (error.Fail() || tmpdir.empty())
325  return Status("Failed to generate temporary directory on the device (%s)",
326  error.AsCString());
327  tmpdir = llvm::StringRef(tmpdir).trim().str();
328 
329  // Create file remover for the temporary directory created on the device
330  std::unique_ptr<std::string, std::function<void(std::string *)>>
331  tmpdir_remover(&tmpdir, [&adb](std::string *s) {
332  StreamString command;
333  command.Printf("rm -rf %s", s->c_str());
334  Status error = adb.Shell(command.GetData(), seconds(5), nullptr);
335 
337  if (log && error.Fail())
338  LLDB_LOGF(log, "Failed to remove temp directory: %s", error.AsCString());
339  });
340 
341  FileSpec symfile_platform_filespec(tmpdir);
342  symfile_platform_filespec.AppendPathComponent("symbolized.oat");
343 
344  // Execute oatdump on the remote device to generate a file with symtab
345  StreamString command;
346  command.Printf("oatdump --symbolize=%s --output=%s",
347  module_sp->GetPlatformFileSpec().GetCString(false),
348  symfile_platform_filespec.GetCString(false));
349  error = adb.Shell(command.GetData(), minutes(1), nullptr);
350  if (error.Fail())
351  return Status("Oatdump failed: %s", error.AsCString());
352 
353  // Download the symbolfile from the remote device
354  return GetFile(symfile_platform_filespec, dst_file_spec);
355 }
356 
358  m_os_version = llvm::VersionTuple(GetSdkVersion());
359  return !m_os_version.empty();
360 }
361 
362 llvm::StringRef
364  SymbolContextList matching_symbols;
365  std::vector<const char *> dl_open_names = { "__dl_dlopen", "dlopen" };
366  const char *dl_open_name = nullptr;
367  Target &target = process->GetTarget();
368  for (auto name: dl_open_names) {
370  ConstString(name), eFunctionNameTypeFull, matching_symbols);
371  if (matching_symbols.GetSize()) {
372  dl_open_name = name;
373  break;
374  }
375  }
376  // Older platform versions have the dl function symbols mangled
377  if (dl_open_name == dl_open_names[0])
378  return R"(
379  extern "C" void* dlopen(const char*, int) asm("__dl_dlopen");
380  extern "C" void* dlsym(void*, const char*) asm("__dl_dlsym");
381  extern "C" int dlclose(void*) asm("__dl_dlclose");
382  extern "C" char* dlerror(void) asm("__dl_dlerror");
383  )";
384 
386 }
387 
389  if (m_adb_sync_svc && m_adb_sync_svc->IsConnected())
390  return m_adb_sync_svc.get();
391 
392  AdbClient adb(m_device_id);
393  m_adb_sync_svc = adb.GetSyncService(error);
394  return (error.Success()) ? m_adb_sync_svc.get() : nullptr;
395 }
A command line argument class.
Definition: Args.h:33
Defines a list of symbol context objects.
A class that represents a running process on the host machine.
static const char * GetPluginDescriptionStatic(bool is_host)
const std::string & GetDeviceID() const
Definition: AdbClient.cpp:131
bool TripleEnvironmentWasSpecified() const
Definition: ArchSpec.h:343
bool IsHost() const
Definition: Platform.h:439
A file utility class.
Definition: FileSpec.h:56
An architecture specification class.
Definition: ArchSpec.h:33
static const char * GetHostPlatformName()
Definition: Platform.cpp:63
static const unsigned int g_android_default_cache_size
#define LIBLLDB_LOG_PLATFORM
Definition: Logging.h:39
std::unique_ptr< SyncService > GetSyncService(Status &error)
Definition: AdbClient.cpp:421
const char * GetData() const
Definition: StreamString.h:43
bool IsValid() const
Tests if this ArchSpec is valid.
Definition: ArchSpec.h:332
const char * GetArgumentAtIndex(size_t idx) const
Gets the NULL terminated C string argument pointer for the argument at index idx. ...
Definition: Args.cpp:256
llvm::Triple & GetTriple()
Architecture triple accessor.
Definition: ArchSpec.h:434
uint32_t GetSize() const
Get accessor for a symbol context list size.
Status Shell(const char *command, std::chrono::milliseconds timeout, std::string *output)
Definition: AdbClient.cpp:388
bool TripleVendorWasSpecified() const
Definition: ArchSpec.h:337
Status GetFile(const FileSpec &source, const FileSpec &destination) override
const char * GetArchitectureName() const
Returns a static string representing the current architecture.
Definition: ArchSpec.cpp:585
Status ShellToFile(const char *command, std::chrono::milliseconds timeout, const FileSpec &output_file_spec)
Definition: AdbClient.cpp:400
#define LLDB_PLUGIN_DEFINE(PluginName)
Definition: PluginManager.h:31
FileSpec CopyByAppendingPathComponent(llvm::StringRef component) const
Definition: FileSpec.cpp:400
static llvm::raw_ostream & error(Stream &strm)
Log * GetLogIfAllCategoriesSet(uint32_t mask)
Definition: Logging.cpp:58
virtual llvm::StringRef GetLibdlFunctionDeclarations(lldb_private::Process *process)
A plug-in interface definition class for debugging a process.
Definition: Process.h:362
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Definition: Stream.cpp:107
bool Success() const
Test for success condition.
Definition: Status.cpp:288
static Status CreateByDeviceID(const std::string &device_id, AdbClient &adb)
Definition: AdbClient.cpp:95
void FindFunctionSymbols(ConstString name, lldb::FunctionNameType name_type_mask, SymbolContextList &sc_list)
Definition: ModuleList.cpp:385
const ModuleList & GetImages() const
Get accessor for the images for this process.
Definition: Target.h:900
#define LLDB_LOGF(log,...)
Definition: Log.h:249
Target & GetTarget()
Get the target object pointer for this module.
Definition: Process.h:1210
Status DownloadSymbolFile(const lldb::ModuleSP &module_sp, const FileSpec &dst_file_spec) override
static ConstString GetPluginNameStatic(bool is_host)
uint32_t GetDefaultMemoryCacheLineSize() override
Allow the platform to set preferred memory cache line size.
A uniqued constant string class.
Definition: ConstString.h:40
bool Fail() const
Test for error condition.
Definition: Status.cpp:182
Definition: SBAddress.h:15
uint32_t ToUInt32(const char *s, uint32_t fail_value=0, int base=0, bool *success_ptr=nullptr)
std::unique_ptr< AdbClient::SyncService > m_adb_sync_svc
#define PATH_MAX
static uint32_t g_initialize_count
static bool Parse(llvm::StringRef uri, llvm::StringRef &scheme, llvm::StringRef &hostname, int &port, llvm::StringRef &path)
Definition: UriParser.cpp:19
AdbClient::SyncService * GetSyncService(Status &error)
const char * AsCString(const char *default_error_str="unknown error") const
Get the error string associated with the current error.
Definition: Status.cpp:131
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
Status DownloadModuleSlice(const FileSpec &src_file_spec, const uint64_t src_offset, const uint64_t src_size, const FileSpec &dst_file_spec) override
Status PutFile(const FileSpec &source, const FileSpec &destination, uint32_t uid=UINT32_MAX, uint32_t gid=UINT32_MAX) override
llvm::VersionTuple m_os_version
Definition: Platform.h:866
llvm::StringRef GetLibdlFunctionDeclarations(lldb_private::Process *process) override
An error handling class.
Definition: Status.h:44