26using namespace std::chrono;
32#define LLDB_PROPERTIES_android
33#include "PlatformAndroidProperties.inc"
36#define LLDB_PROPERTIES_android
37#include "PlatformAndroidPropertiesEnum.inc"
43 m_collection_sp = std::make_shared<OptionValueProperties>(
45 m_collection_sp->Initialize(g_android_properties);
50 static PluginProperties g_settings;
55const unsigned int g_android_default_cache_size =
61 PlatformLinux::Initialize();
64#if defined(__ANDROID__)
66 default_platform_sp->SetSystemArchitecture(HostInfo::GetArchitecture());
83 PlatformLinux::Terminate();
89 const char *arch_name;
95 const char *triple_cstr =
96 arch ? arch->
GetTriple().getTriple().c_str() :
"<null>";
98 LLDB_LOGF(log,
"PlatformAndroid::%s(force=%s, arch={%s,%s})", __FUNCTION__,
99 force ?
"true" :
"false", arch_name, triple_cstr);
103 if (!create && arch && arch->
IsValid()) {
104 const llvm::Triple &triple = arch->
GetTriple();
105 switch (triple.getVendor()) {
106 case llvm::Triple::PC:
110#if defined(__ANDROID__)
114 case llvm::Triple::VendorType::UnknownVendor:
123 switch (triple.getEnvironment()) {
124 case llvm::Triple::Android:
127#if defined(__ANDROID__)
131 case llvm::Triple::EnvironmentType::UnknownEnvironment:
143 LLDB_LOGF(log,
"PlatformAndroid::%s() creating remote-android platform",
149 log,
"PlatformAndroid::%s() aborting creation of remote-android platform",
160 "Properties for the Android platform plugin.",
170 return "Local Android user platform plug-in.";
171 return "Remote Android user platform plug-in.";
179 "can't connect to the host platform, always connected");
187 std::optional<URI> parsed_url =
URI::Parse(url);
190 if (parsed_url->hostname !=
"localhost")
193 auto error = PlatformLinux::ConnectRemote(args);
194 if (
error.Success()) {
196 if (!resolved_device_id_or_error)
206 return PlatformLinux::GetFile(source, destination);
217 if (
error.Success() && sync_service) {
218 uint32_t mode = 0, size = 0, mtime = 0;
219 error = sync_service->Stat(source_spec, mode, size, mtime);
220 if (
error.Success()) {
222 return sync_service->PullFile(source_spec, destination);
227 LLDB_LOGF(log,
"Got mode == 0 on '%s': try to get file via 'shell cat'",
228 source_spec.
GetPath(
false).c_str());
233 std::string source_file = source_spec.
GetPath(
false);
236 LLDB_LOGF(log,
"Using shell cat fallback for '%s'", source_file.c_str());
238 if (strchr(source_file.c_str(),
'\'') !=
nullptr)
240 "Doesn't support single-quotes in filenames");
247 snprintf(cmd,
sizeof(cmd),
"%scat '%s'",
GetRunAs().c_str(),
248 source_file.c_str());
250 return adb->ShellToFile(cmd, minutes(1), destination);
254 const FileSpec &destination, uint32_t uid,
257 return PlatformLinux::PutFile(source, destination, uid, gid);
259 FileSpec destination_spec(destination.
GetPath(
false), FileSpec::Style::posix);
262 destination_spec.
GetPath(
false));
269 return sync_service->PushFile(source, destination_spec);
275 const uint64_t src_offset,
276 const uint64_t src_size,
278 std::string source_file = src_file_spec.
GetPath(
false);
279 if (source_file.empty())
282 std::string destination_file = dst_file_spec.
GetPath(
false);
283 if (destination_file.empty())
289 return GetFile(src_file_spec, dst_file_spec);
291 if (source_file.find(
'\'') != std::string::npos)
293 "Doesn't support single-quotes in filenames");
297 static constexpr llvm::StringLiteral k_zip_separator(
"!/");
298 size_t pos = source_file.find(k_zip_separator);
299 if (pos != std::string::npos)
300 source_file.resize(pos);
309 snprintf(cmd,
sizeof(cmd),
310 "%sdd if='%s' iflag=skip_bytes,count_bytes "
311 "skip=%" PRIu64
" count=%" PRIu64
" status=none",
312 GetRunAs().c_str(), source_file.c_str(), src_offset, src_size);
314 return adb->ShellToFile(cmd, minutes(1), dst_file_spec);
319 if (
error.Success()) {
327 return g_android_default_cache_size;
337 std::string version_string;
343 adb->Shell(
"getprop ro.build.version.sdk", seconds(5), &version_string);
344 version_string = llvm::StringRef(version_string).trim().str();
346 if (
error.Fail() || version_string.empty()) {
348 LLDB_LOGF(log,
"Get SDK version failed. (error: %s, output: %s)",
349 error.AsCString(), version_string.c_str());
361 llvm::StringRef extension = module_sp->GetFileSpec().GetFileNameExtension();
362 if (extension !=
".oat" && extension !=
".odex")
364 "Symbol file downloading only supported for oat and odex files");
367 if (!module_sp->GetPlatformFileSpec())
373 "Symbol file generation only supported on SDK 23+");
376 if (module_sp->GetSectionList()->FindSectionByName(
ConstString(
".symtab")) !=
385 error = adb->Shell(
"mktemp --directory --tmpdir /data/local/tmp", seconds(5),
387 if (
error.Fail() || tmpdir.empty())
389 "Failed to generate temporary directory on the device (%s)",
391 tmpdir = llvm::StringRef(tmpdir).trim().str();
394 std::unique_ptr<std::string, std::function<void(std::string *)>>
395 tmpdir_remover(&tmpdir, [&adb](std::string *s) {
397 command.
Printf(
"rm -rf %s", s->c_str());
401 if (log &&
error.Fail())
402 LLDB_LOGF(log,
"Failed to remove temp directory: %s",
406 FileSpec symfile_platform_filespec(tmpdir);
407 symfile_platform_filespec.AppendPathComponent(
"symbolized.oat");
411 command.
Printf(
"oatdump --symbolize=%s --output=%s",
412 module_sp->GetPlatformFileSpec().GetPath(
false).c_str(),
413 symfile_platform_filespec.GetPath(
false).c_str());
414 error = adb->Shell(command.
GetData(), minutes(1),
nullptr);
420 return GetFile(symfile_platform_filespec, dst_file_spec);
431 std::vector<const char *> dl_open_names = {
"__dl_dlopen",
"dlopen"};
432 const char *dl_open_name =
nullptr;
434 for (
auto *name : dl_open_names) {
436 ConstString(name), eFunctionNameTypeFull, matching_symbols);
437 if (matching_symbols.
GetSize()) {
443 if (dl_open_name == dl_open_names[0])
445 extern "C" void* dlopen(const char*, int) asm("__dl_dlopen");
446 extern "C" void* dlsym(void*, const char*) asm("__dl_dlsym");
447 extern "C" int dlclose(void*) asm("__dl_dlclose");
448 extern "C" char* dlerror(void) asm("__dl_dlerror");
456 error = adb->Connect();
462 ePropertyPlatformPackageName,
"");
467 if (!run_as.empty()) {
476 return std::string(
"run-as '") + run_as.str() +
"' ";
491 std::string status_output;
494 "cat /proc/%llu/status 2>/dev/null | grep -E '^(PPid|Uid|Gid):'",
495 static_cast<unsigned long long>(pid));
497 status_adb->Shell(status_cmd.
GetData(), seconds(5), &status_output);
499 if (status_error.
Fail() || status_output.empty())
502 llvm::SmallVector<llvm::StringRef, 16> lines;
503 llvm::StringRef(status_output).split(lines,
'\n');
505 for (llvm::StringRef line : lines) {
507 if (line.starts_with(
"PPid:")) {
508 llvm::StringRef ppid_str = line.substr(5).trim();
510 if (llvm::to_integer(ppid_str, ppid))
512 }
else if (line.starts_with(
"Uid:")) {
513 llvm::SmallVector<llvm::StringRef, 4> uid_parts;
514 line.substr(4).trim().split(uid_parts,
'\t', -1,
false);
515 if (uid_parts.size() >= 2) {
517 if (llvm::to_integer(uid_parts[0].trim(), uid))
519 if (llvm::to_integer(uid_parts[1].trim(), euid))
522 }
else if (line.starts_with(
"Gid:")) {
523 llvm::SmallVector<llvm::StringRef, 4> gid_parts;
524 line.substr(4).trim().split(gid_parts,
'\t', -1,
false);
525 if (gid_parts.size() >= 2) {
527 if (llvm::to_integer(gid_parts[0].trim(), gid))
529 if (llvm::to_integer(gid_parts[1].trim(), egid))
545 std::string cmdline_output;
547 cmdline_cmd.
Printf(
"cat /proc/%llu/cmdline 2>/dev/null | tr '\\000' ' '",
548 static_cast<unsigned long long>(pid));
550 cmdline_adb->Shell(cmdline_cmd.
GetData(), seconds(5), &cmdline_output);
552 if (cmdline_error.
Fail() || cmdline_output.empty())
555 cmdline_output = llvm::StringRef(cmdline_output).trim().str();
556 if (cmdline_output.empty())
559 llvm::SmallVector<llvm::StringRef, 16> args;
560 llvm::StringRef(cmdline_output).split(args,
' ', -1,
false);
566 for (
size_t i = 1; i < args.size(); i++) {
567 if (!args[i].empty())
582 std::string exe_output;
584 exe_cmd.
Printf(
"readlink /proc/%llu/exe 2>/dev/null",
585 static_cast<unsigned long long>(pid));
586 Status exe_error = exe_adb->Shell(exe_cmd.
GetData(), seconds(5), &exe_output);
588 if (exe_error.
Fail() || exe_output.empty())
591 exe_output = llvm::StringRef(exe_output).trim().str();
595 if (exe_output.find(
"64") != std::string::npos ||
596 exe_output.find(
"arm64") != std::string::npos ||
597 exe_output.find(
"aarch64") != std::string::npos) {
598 arch.
SetTriple(
"aarch64-unknown-linux-android");
599 }
else if (exe_output.find(
"x86_64") != std::string::npos) {
600 arch.
SetTriple(
"x86_64-unknown-linux-android");
601 }
else if (exe_output.find(
"x86") != std::string::npos ||
602 exe_output.find(
"i686") != std::string::npos) {
603 arch.
SetTriple(
"i686-unknown-linux-android");
606 arch.
SetTriple(
"armv7-unknown-linux-android");
623 return PlatformLinux::FindProcesses(match_info, proc_infos);
641 if (process_name.empty())
649 LLDB_LOGF(log,
"PlatformAndroid::%s failed to get ADB client: %s",
650 __FUNCTION__,
error.AsCString());
656 std::string pidof_output;
658 command.
Printf(
"pidof '%s'", process_name.c_str());
659 error = adb->Shell(command.
GetData(), seconds(5), &pidof_output);
663 LLDB_LOG(log,
"PlatformAndroid::{} 'pidof {}' failed: {}", __FUNCTION__,
664 process_name.c_str(),
error.AsCString());
671 pidof_output = llvm::StringRef(pidof_output).trim().str();
672 if (pidof_output.empty()) {
674 LLDB_LOGF(log,
"PlatformAndroid::%s no process found with name '%s'",
675 __FUNCTION__, process_name.c_str());
680 llvm::SmallVector<llvm::StringRef, 8> pid_strings;
681 llvm::StringRef(pidof_output).split(pid_strings,
' ', -1,
false);
686 uint32_t num_matches = 0;
687 for (llvm::StringRef pid_str : pid_strings) {
688 pid_str = pid_str.trim();
693 if (!llvm::to_integer(pid_str, pid)) {
694 LLDB_LOGF(log,
"PlatformAndroid::%s failed to parse PID from: '%s'",
695 __FUNCTION__, pid_str.str().c_str());
699 ProcessInstanceInfo process_info;
702 FileSpec::Style::posix);
710 if (match_info.
Matches(process_info)) {
711 proc_infos.push_back(process_info);
714 LLDB_LOGF(log,
"PlatformAndroid::%s found process '%s' with PID %llu",
715 __FUNCTION__, process_name.c_str(),
716 static_cast<unsigned long long>(pid));
724 auto sync_service = std::make_unique<AdbSyncService>(
m_device_id);
725 error = sync_service->SetupSyncConnection();
static llvm::raw_ostream & error(Stream &strm)
static DynamicLoaderDarwinKernelProperties & GetGlobalProperties()
#define LLDB_LOG(log,...)
The LLDB_LOG* macros defined below are the way to emit log messages.
#define LLDB_LOGF(log,...)
#define LLDB_PLUGIN_DEFINE(PluginName)
An architecture specification class.
bool IsValid() const
Tests if this ArchSpec is valid.
llvm::Triple & GetTriple()
Architecture triple accessor.
bool TripleEnvironmentWasSpecified() const
bool SetTriple(const llvm::Triple &triple)
Architecture triple setter.
bool TripleVendorWasSpecified() const
const char * GetArchitectureName() const
Returns a static string representing the current architecture.
A command line argument class.
void AppendArgument(llvm::StringRef arg_str, char quote_char='\0')
Appends a new argument to the end of the list argument list.
const char * GetArgumentAtIndex(size_t idx) const
Gets the NULL terminated C string argument pointer for the argument at index idx.
A uniqued constant string class.
llvm::StringRef GetStringRef() const
Get the string value as a llvm::StringRef.
A class to manage flag bits.
void SetFile(llvm::StringRef path, Style style)
Change the file specified with a new path.
FileSpec CopyByAppendingPathComponent(llvm::StringRef component) const
bool IsRelative() const
Returns true if the filespec represents a relative path.
size_t GetPath(char *path, size_t max_path_length, bool denormalize=true) const
Extract the full path to the file.
ConstString GetPathAsConstString(bool denormalize=true) const
Get the full path as a ConstString.
void FindFunctionSymbols(ConstString name, lldb::FunctionNameType name_type_mask, SymbolContextList &sc_list)
static bool RegisterPlugin(llvm::StringRef name, llvm::StringRef description, ABICreateInstance create_callback)
static lldb::OptionValuePropertiesSP GetSettingForPlatformPlugin(Debugger &debugger, llvm::StringRef setting_name)
static bool CreateSettingForPlatformPlugin(Debugger &debugger, const lldb::OptionValuePropertiesSP &properties_sp, llvm::StringRef description, bool is_global_property)
static bool UnregisterPlugin(ABICreateInstance create_callback)
void SetGroupID(uint32_t gid)
void SetArchitecture(const ArchSpec &arch)
void SetArg0(llvm::StringRef arg)
void SetArguments(const Args &args, bool first_arg_is_executable)
void SetProcessID(lldb::pid_t pid)
FileSpec & GetExecutableFile()
void SetUserID(uint32_t uid)
NameMatch GetNameMatchType() const
bool Matches(const ProcessInstanceInfo &proc_info) const
ProcessInstanceInfo & GetProcessInfo()
void SetEffectiveGroupID(uint32_t gid)
void SetParentProcessID(lldb::pid_t pid)
void SetEffectiveUserID(uint32_t uid)
A plug-in interface definition class for debugging a process.
Target & GetTarget()
Get the target object pointer for this module.
T GetPropertyAtIndexAs(uint32_t idx, T default_value, const ExecutionContext *exe_ctx=nullptr) const
static Status FromErrorStringWithFormat(const char *format,...) __attribute__((format(printf
static Status FromErrorString(const char *str)
bool Fail() const
Test for error condition.
static Status FromError(llvm::Error error)
Avoid using this in new code. Migrate APIs to llvm::Expected instead.
const char * GetData() const
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Defines a list of symbol context objects.
uint32_t GetSize() const
Get accessor for a symbol context list size.
const ModuleList & GetImages() const
Get accessor for the images for this process.
A class that represents a running process on the host machine.
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
std::vector< ProcessInstanceInfo > ProcessInstanceInfoList
std::shared_ptr< lldb_private::Platform > PlatformSP
std::shared_ptr< lldb_private::Module > ModuleSP
static std::optional< URI > Parse(llvm::StringRef uri)