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/LLDBLog.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) {
62  Log *log = GetLog(LLDBLog::Platform);
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 
133 llvm::StringRef PlatformAndroid::GetPluginDescriptionStatic(bool is_host) {
134  if (is_host)
135  return "Local Android user platform plug-in.";
136  return "Remote Android user platform plug-in.";
137 }
138 
140  m_device_id.clear();
141 
142  if (IsHost())
143  return Status("can't connect to the host platform, always connected");
144 
147 
148  const char *url = args.GetArgumentAtIndex(0);
149  if (!url)
150  return Status("URL is null.");
151  llvm::Optional<URI> parsed_url = URI::Parse(url);
152  if (!parsed_url)
153  return Status("Invalid URL: %s", url);
154  if (parsed_url->hostname != "localhost")
155  m_device_id = parsed_url->hostname.str();
156 
157  auto error = PlatformLinux::ConnectRemote(args);
158  if (error.Success()) {
159  AdbClient adb;
161  if (error.Fail())
162  return error;
163 
164  m_device_id = adb.GetDeviceID();
165  }
166  return error;
167 }
168 
170  const FileSpec &destination) {
171  if (IsHost() || !m_remote_platform_sp)
172  return PlatformLinux::GetFile(source, destination);
173 
174  FileSpec source_spec(source.GetPath(false), FileSpec::Style::posix);
175  if (source_spec.IsRelative())
177  source_spec.GetCString(false));
178 
179  Status error;
180  auto sync_service = GetSyncService(error);
181  if (error.Fail())
182  return error;
183 
184  uint32_t mode = 0, size = 0, mtime = 0;
185  error = sync_service->Stat(source_spec, mode, size, mtime);
186  if (error.Fail())
187  return error;
188 
189  if (mode != 0)
190  return sync_service->PullFile(source_spec, destination);
191 
192  auto source_file = source_spec.GetCString(false);
193 
194  Log *log = GetLog(LLDBLog::Platform);
195  LLDB_LOGF(log, "Got mode == 0 on '%s': try to get file via 'shell cat'",
196  source_file);
197 
198  if (strchr(source_file, '\'') != nullptr)
199  return Status("Doesn't support single-quotes in filenames");
200 
201  // mode == 0 can signify that adbd cannot access the file due security
202  // constraints - try "cat ..." as a fallback.
203  AdbClient adb(m_device_id);
204 
205  char cmd[PATH_MAX];
206  snprintf(cmd, sizeof(cmd), "cat '%s'", source_file);
207 
208  return adb.ShellToFile(cmd, minutes(1), destination);
209 }
210 
212  const FileSpec &destination, uint32_t uid,
213  uint32_t gid) {
214  if (IsHost() || !m_remote_platform_sp)
215  return PlatformLinux::PutFile(source, destination, uid, gid);
216 
217  FileSpec destination_spec(destination.GetPath(false), FileSpec::Style::posix);
218  if (destination_spec.IsRelative())
220  destination_spec.GetCString(false));
221 
222  // TODO: Set correct uid and gid on remote file.
223  Status error;
224  auto sync_service = GetSyncService(error);
225  if (error.Fail())
226  return error;
227  return sync_service->PushFile(source, destination_spec);
228 }
229 
230 const char *PlatformAndroid::GetCacheHostname() { return m_device_id.c_str(); }
231 
233  const uint64_t src_offset,
234  const uint64_t src_size,
235  const FileSpec &dst_file_spec) {
236  if (src_offset != 0)
237  return Status("Invalid offset - %" PRIu64, src_offset);
238 
239  return GetFile(src_file_spec, dst_file_spec);
240 }
241 
243  Status error = PlatformLinux::DisconnectRemote();
244  if (error.Success()) {
245  m_device_id.clear();
246  m_sdk_version = 0;
247  }
248  return error;
249 }
250 
253 }
254 
256  if (!IsConnected())
257  return 0;
258 
259  if (m_sdk_version != 0)
260  return m_sdk_version;
261 
262  std::string version_string;
263  AdbClient adb(m_device_id);
264  Status error =
265  adb.Shell("getprop ro.build.version.sdk", seconds(5), &version_string);
266  version_string = llvm::StringRef(version_string).trim().str();
267 
268  if (error.Fail() || version_string.empty()) {
269  Log *log = GetLog(LLDBLog::Platform);
270  LLDB_LOGF(log, "Get SDK version failed. (error: %s, output: %s)",
271  error.AsCString(), version_string.c_str());
272  return 0;
273  }
274 
275  // FIXME: improve error handling
276  llvm::to_integer(version_string, m_sdk_version);
277  return m_sdk_version;
278 }
279 
280 Status PlatformAndroid::DownloadSymbolFile(const lldb::ModuleSP &module_sp,
281  const FileSpec &dst_file_spec) {
282  // For oat file we can try to fetch additional debug info from the device
283  ConstString extension = module_sp->GetFileSpec().GetFileNameExtension();
284  if (extension != ".oat" && extension != ".odex")
285  return Status(
286  "Symbol file downloading only supported for oat and odex files");
287 
288  // If we have no information about the platform file we can't execute oatdump
289  if (!module_sp->GetPlatformFileSpec())
290  return Status("No platform file specified");
291 
292  // Symbolizer isn't available before SDK version 23
293  if (GetSdkVersion() < 23)
294  return Status("Symbol file generation only supported on SDK 23+");
295 
296  // If we already have symtab then we don't have to try and generate one
297  if (module_sp->GetSectionList()->FindSectionByName(ConstString(".symtab")) !=
298  nullptr)
299  return Status("Symtab already available in the module");
300 
301  AdbClient adb(m_device_id);
302  std::string tmpdir;
303  Status error = adb.Shell("mktemp --directory --tmpdir /data/local/tmp",
304  seconds(5), &tmpdir);
305  if (error.Fail() || tmpdir.empty())
306  return Status("Failed to generate temporary directory on the device (%s)",
307  error.AsCString());
308  tmpdir = llvm::StringRef(tmpdir).trim().str();
309 
310  // Create file remover for the temporary directory created on the device
311  std::unique_ptr<std::string, std::function<void(std::string *)>>
312  tmpdir_remover(&tmpdir, [&adb](std::string *s) {
313  StreamString command;
314  command.Printf("rm -rf %s", s->c_str());
315  Status error = adb.Shell(command.GetData(), seconds(5), nullptr);
316 
317  Log *log = GetLog(LLDBLog::Platform);
318  if (log && error.Fail())
319  LLDB_LOGF(log, "Failed to remove temp directory: %s", error.AsCString());
320  });
321 
322  FileSpec symfile_platform_filespec(tmpdir);
323  symfile_platform_filespec.AppendPathComponent("symbolized.oat");
324 
325  // Execute oatdump on the remote device to generate a file with symtab
326  StreamString command;
327  command.Printf("oatdump --symbolize=%s --output=%s",
328  module_sp->GetPlatformFileSpec().GetCString(false),
329  symfile_platform_filespec.GetCString(false));
330  error = adb.Shell(command.GetData(), minutes(1), nullptr);
331  if (error.Fail())
332  return Status("Oatdump failed: %s", error.AsCString());
333 
334  // Download the symbolfile from the remote device
335  return GetFile(symfile_platform_filespec, dst_file_spec);
336 }
337 
339  m_os_version = llvm::VersionTuple(GetSdkVersion());
340  return !m_os_version.empty();
341 }
342 
343 llvm::StringRef
345  SymbolContextList matching_symbols;
346  std::vector<const char *> dl_open_names = { "__dl_dlopen", "dlopen" };
347  const char *dl_open_name = nullptr;
348  Target &target = process->GetTarget();
349  for (auto name: dl_open_names) {
351  ConstString(name), eFunctionNameTypeFull, matching_symbols);
352  if (matching_symbols.GetSize()) {
353  dl_open_name = name;
354  break;
355  }
356  }
357  // Older platform versions have the dl function symbols mangled
358  if (dl_open_name == dl_open_names[0])
359  return R"(
360  extern "C" void* dlopen(const char*, int) asm("__dl_dlopen");
361  extern "C" void* dlsym(void*, const char*) asm("__dl_dlsym");
362  extern "C" int dlclose(void*) asm("__dl_dlclose");
363  extern "C" char* dlerror(void) asm("__dl_dlerror");
364  )";
365 
367 }
368 
370  if (m_adb_sync_svc && m_adb_sync_svc->IsConnected())
371  return m_adb_sync_svc.get();
372 
373  AdbClient adb(m_device_id);
375  return (error.Success()) ? m_adb_sync_svc.get() : nullptr;
376 }
lldb_private::RemoteAwarePlatform::IsConnected
bool IsConnected() const override
Definition: RemoteAwarePlatform.cpp:344
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:358
lldb_private::platform_android::PlatformAndroid::GetDefaultMemoryCacheLineSize
uint32_t GetDefaultMemoryCacheLineSize() override
Allow the platform to set preferred memory cache line size.
Definition: PlatformAndroid.cpp:251
g_android_default_cache_size
static const unsigned int g_android_default_cache_size
Definition: PlatformAndroid.cpp:32
lldb_private::URI::Parse
static llvm::Optional< URI > Parse(llvm::StringRef uri)
Definition: UriParser.cpp:27
lldb_private::platform_android::PlatformAndroid::ConnectRemote
Status ConnectRemote(Args &args) override
Definition: PlatformAndroid.cpp:139
lldb_private::platform_android::PlatformAndroid::GetLibdlFunctionDeclarations
llvm::StringRef GetLibdlFunctionDeclarations(lldb_private::Process *process) override
Definition: PlatformAndroid.cpp:344
LLDB_LOGF
#define LLDB_LOGF(log,...)
Definition: Log.h:270
lldb_private::Process
Definition: Process.h:338
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:232
lldb_private::Process::GetTarget
Target & GetTarget()
Get the target object pointer for this module.
Definition: Process.h:1206
lldb_private::SymbolContextList
Definition: SymbolContext.h:379
lldb_private::Platform::m_os_version
llvm::VersionTuple m_os_version
Definition: Platform.h:879
AdbClient.h
lldb_private::Args
Definition: Args.h:33
lldb_private::ArchSpec::GetTriple
llvm::Triple & GetTriple()
Architecture triple accessor.
Definition: ArchSpec.h:455
lldb_private::platform_android::PlatformAndroid::GetCacheHostname
const char * GetCacheHostname() override
Definition: PlatformAndroid.cpp:230
lldb_private::Target
Definition: Target.h:464
Section.h
lldb_private::Target::GetImages
const ModuleList & GetImages() const
Get accessor for the images for this process.
Definition: Target.h:938
lldb_private::FileSpec::GetCString
const char * GetCString(bool denormalize=true) const
Definition: FileSpec.cpp:363
Target.h
lldb_private::platform_android::PlatformAndroid::GetSdkVersion
uint32_t GetSdkVersion()
Definition: PlatformAndroid.cpp:255
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:369
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:211
lldb_private::SymbolContextList::GetSize
uint32_t GetSize() const
Get accessor for a symbol context list size.
Definition: SymbolContext.cpp:1279
lldb_private::ConstString
Definition: ConstString.h:40
lldb_private::StreamString
Definition: StreamString.h:23
lldb_private::platform_android::PlatformAndroid::DownloadSymbolFile
Status DownloadSymbolFile(const lldb::ModuleSP &module_sp, const FileSpec &dst_file_spec) override
Definition: PlatformAndroid.cpp:280
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:353
lldb_private::FileSpec::CopyByAppendingPathComponent
FileSpec CopyByAppendingPathComponent(llvm::StringRef component) const
Definition: FileSpec.cpp:399
ValueObject.h
lldb_private::ArchSpec::TripleEnvironmentWasSpecified
bool TripleEnvironmentWasSpecified() const
Definition: ArchSpec.h:364
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:76
PlatformAndroid.h
lldb_private::Status
Definition: Status.h:44
PlatformPOSIX::GetLibdlFunctionDeclarations
virtual llvm::StringRef GetLibdlFunctionDeclarations(lldb_private::Process *process)
Definition: PlatformPOSIX.cpp:968
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:474
lldb_private::ArchSpec::GetArchitectureName
const char * GetArchitectureName() const
Returns a static string representing the current architecture.
Definition: ArchSpec.cpp:539
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::AdbClient::SyncService
Definition: AdbClient.h:35
lldb_private::platform_android::PlatformAndroid::GetRemoteOSVersion
bool GetRemoteOSVersion() override
Definition: PlatformAndroid.cpp:338
lldb_private::platform_android::PlatformAndroid::m_sdk_version
uint32_t m_sdk_version
Definition: PlatformAndroid.h:78
lldb_private::platform_android::PlatformAndroid::m_device_id
std::string m_device_id
Definition: PlatformAndroid.h:77
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::LLDBLog::Platform
@ Platform
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:242
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:275
lldb_private::ModuleList::FindFunctionSymbols
void FindFunctionSymbols(ConstString name, lldb::FunctionNameType name_type_mask, SymbolContextList &sc_list)
Definition: ModuleList.cpp:446
LLDB_PLUGIN_DEFINE
#define LLDB_PLUGIN_DEFINE(PluginName)
Definition: PluginManager.h:31
lldb_private::Log
Definition: Log.h:48
UriParser.h
lldb_private::platform_android::PlatformAndroid::GetFile
Status GetFile(const FileSpec &source, const FileSpec &destination) override
Definition: PlatformAndroid.cpp:169
lldb_private::Platform::IsHost
bool IsHost() const
Definition: Platform.h:420
PATH_MAX
#define PATH_MAX
Definition: windows/PosixApi.h:25
lldb_private::GetLog
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
Definition: Log.h:235
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:347
g_initialize_count
static uint32_t g_initialize_count
Definition: PlatformAndroid.cpp:31
lldb
Definition: SBAddress.h:15
lldb_private::platform_android::PlatformAndroid::GetPluginDescriptionStatic
static llvm::StringRef GetPluginDescriptionStatic(bool is_host)
Definition: PlatformAndroid.cpp:133
LLDBLog.h
lldb_private::platform_android::AdbClient::Shell
Status Shell(const char *command, std::chrono::milliseconds timeout, std::string *output)
Definition: AdbClient.cpp:384