27using namespace std::chrono;
33#define LLDB_PROPERTIES_android
34#include "PlatformAndroidProperties.inc"
37#define LLDB_PROPERTIES_android
38#include "PlatformAndroidPropertiesEnum.inc"
44 m_collection_sp = std::make_shared<OptionValueProperties>(
46 m_collection_sp->Initialize(g_android_properties);
51 static PluginProperties g_settings;
56const unsigned int g_android_default_cache_size =
62 PlatformLinux::Initialize();
65#if defined(__ANDROID__)
67 default_platform_sp->SetSystemArchitecture(HostInfo::GetArchitecture());
84 PlatformLinux::Terminate();
90 const char *arch_name;
96 const char *triple_cstr =
97 arch ? arch->
GetTriple().getTriple().c_str() :
"<null>";
99 LLDB_LOGF(log,
"PlatformAndroid::%s(force=%s, arch={%s,%s})", __FUNCTION__,
100 force ?
"true" :
"false", arch_name, triple_cstr);
104 if (!create && arch && arch->
IsValid()) {
105 const llvm::Triple &triple = arch->
GetTriple();
106 switch (triple.getVendor()) {
107 case llvm::Triple::PC:
111#if defined(__ANDROID__)
115 case llvm::Triple::VendorType::UnknownVendor:
124 switch (triple.getEnvironment()) {
125 case llvm::Triple::Android:
128#if defined(__ANDROID__)
132 case llvm::Triple::EnvironmentType::UnknownEnvironment:
144 LLDB_LOGF(log,
"PlatformAndroid::%s() creating remote-android platform",
150 log,
"PlatformAndroid::%s() aborting creation of remote-android platform",
161 "Properties for the Android platform plugin.",
171 return "Local Android user platform plug-in.";
172 return "Remote Android user platform plug-in.";
180 "can't connect to the host platform, always connected");
188 std::optional<URI> parsed_url =
URI::Parse(url);
191 if (parsed_url->hostname !=
"localhost")
194 auto error = PlatformLinux::ConnectRemote(args);
195 if (
error.Success()) {
197 if (!resolved_device_id_or_error)
207 return PlatformLinux::GetFile(source, destination);
218 if (
error.Success() && sync_service) {
219 uint32_t mode = 0, size = 0, mtime = 0;
220 error = sync_service->Stat(source_spec, mode, size, mtime);
221 if (
error.Success()) {
223 return sync_service->PullFile(source_spec, destination);
228 LLDB_LOGF(log,
"Got mode == 0 on '%s': try to get file via 'shell cat'",
229 source_spec.
GetPath(
false).c_str());
234 std::string source_file = source_spec.
GetPath(
false);
237 LLDB_LOGF(log,
"Using shell cat fallback for '%s'", source_file.c_str());
239 if (strchr(source_file.c_str(),
'\'') !=
nullptr)
241 "Doesn't support single-quotes in filenames");
248 snprintf(cmd,
sizeof(cmd),
"%scat '%s'",
GetRunAs().c_str(),
249 source_file.c_str());
251 return adb->ShellToFile(cmd, minutes(1), destination);
255 const FileSpec &destination, uint32_t uid,
258 return PlatformLinux::PutFile(source, destination, uid, gid);
260 FileSpec destination_spec(destination.
GetPath(
false), FileSpec::Style::posix);
263 destination_spec.
GetPath(
false));
270 return sync_service->PushFile(source, destination_spec);
276 const uint64_t src_offset,
277 const uint64_t src_size,
279 std::string source_file = src_file_spec.
GetPath(
false);
280 if (source_file.empty())
283 std::string destination_file = dst_file_spec.
GetPath(
false);
284 if (destination_file.empty())
290 return GetFile(src_file_spec, dst_file_spec);
292 if (source_file.find(
'\'') != std::string::npos)
294 "Doesn't support single-quotes in filenames");
298 static constexpr llvm::StringLiteral k_zip_separator(
"!/");
299 size_t pos = source_file.find(k_zip_separator);
300 if (pos != std::string::npos)
301 source_file.resize(pos);
310 snprintf(cmd,
sizeof(cmd),
311 "%sdd if='%s' iflag=skip_bytes,count_bytes "
312 "skip=%" PRIu64
" count=%" PRIu64
" status=none",
313 GetRunAs().c_str(), source_file.c_str(), src_offset, src_size);
315 return adb->ShellToFile(cmd, minutes(1), dst_file_spec);
320 if (
error.Success()) {
328 return g_android_default_cache_size;
338 std::string version_string;
344 adb->Shell(
"getprop ro.build.version.sdk", seconds(5), &version_string);
345 version_string = llvm::StringRef(version_string).trim().str();
347 if (
error.Fail() || version_string.empty()) {
349 LLDB_LOGF(log,
"Get SDK version failed. (error: %s, output: %s)",
350 error.AsCString(), version_string.c_str());
362 llvm::StringRef extension = module_sp->GetFileSpec().GetFileNameExtension();
363 if (extension !=
".oat" && extension !=
".odex")
365 "Symbol file downloading only supported for oat and odex files");
368 if (!module_sp->GetPlatformFileSpec())
374 "Symbol file generation only supported on SDK 23+");
377 if (module_sp->GetSectionList()->FindSectionByName(
ConstString(
".symtab")) !=
386 error = adb->Shell(
"mktemp --directory --tmpdir /data/local/tmp", seconds(5),
388 if (
error.Fail() || tmpdir.empty())
390 "Failed to generate temporary directory on the device (%s)",
392 tmpdir = llvm::StringRef(tmpdir).trim().str();
395 std::unique_ptr<std::string, std::function<void(std::string *)>>
396 tmpdir_remover(&tmpdir, [&adb](std::string *s) {
398 command.
Printf(
"rm -rf %s", s->c_str());
402 if (log &&
error.Fail())
403 LLDB_LOGF(log,
"Failed to remove temp directory: %s",
407 FileSpec symfile_platform_filespec(tmpdir);
408 symfile_platform_filespec.AppendPathComponent(
"symbolized.oat");
412 command.
Printf(
"oatdump --symbolize=%s --output=%s",
413 module_sp->GetPlatformFileSpec().GetPath(
false).c_str(),
414 symfile_platform_filespec.GetPath(
false).c_str());
415 error = adb->Shell(command.
GetData(), minutes(1),
nullptr);
421 return GetFile(symfile_platform_filespec, dst_file_spec);
432 std::vector<const char *> dl_open_names = {
"__dl_dlopen",
"dlopen"};
433 const char *dl_open_name =
nullptr;
435 for (
auto *name : dl_open_names) {
437 ConstString(name), eFunctionNameTypeFull, matching_symbols);
438 if (matching_symbols.
GetSize()) {
444 if (dl_open_name == dl_open_names[0])
446 extern "C" void* dlopen(const char*, int) asm("__dl_dlopen");
447 extern "C" void* dlsym(void*, const char*) asm("__dl_dlsym");
448 extern "C" int dlclose(void*) asm("__dl_dlclose");
449 extern "C" char* dlerror(void) asm("__dl_dlerror");
457 error = adb->Connect();
463 ePropertyPlatformPackageName,
"");
468 if (!run_as.empty()) {
477 return std::string(
"run-as '") + run_as.str() +
"' ";
492 std::string status_output;
495 "cat /proc/%llu/status 2>/dev/null | grep -E '^(PPid|Uid|Gid):'",
496 static_cast<unsigned long long>(pid));
498 status_adb->Shell(status_cmd.
GetData(), seconds(5), &status_output);
500 if (status_error.
Fail() || status_output.empty())
503 llvm::SmallVector<llvm::StringRef, 16> lines;
504 llvm::StringRef(status_output).split(lines,
'\n');
506 for (llvm::StringRef line : lines) {
508 if (line.starts_with(
"PPid:")) {
509 llvm::StringRef ppid_str = line.substr(5).trim();
511 if (llvm::to_integer(ppid_str, ppid))
513 }
else if (line.starts_with(
"Uid:")) {
514 llvm::SmallVector<llvm::StringRef, 4> uid_parts;
515 line.substr(4).trim().split(uid_parts,
'\t', -1,
false);
516 if (uid_parts.size() >= 2) {
518 if (llvm::to_integer(uid_parts[0].trim(), uid))
520 if (llvm::to_integer(uid_parts[1].trim(), euid))
523 }
else if (line.starts_with(
"Gid:")) {
524 llvm::SmallVector<llvm::StringRef, 4> gid_parts;
525 line.substr(4).trim().split(gid_parts,
'\t', -1,
false);
526 if (gid_parts.size() >= 2) {
528 if (llvm::to_integer(gid_parts[0].trim(), gid))
530 if (llvm::to_integer(gid_parts[1].trim(), egid))
546 std::string cmdline_output;
548 cmdline_cmd.
Printf(
"cat /proc/%llu/cmdline 2>/dev/null | tr '\\000' ' '",
549 static_cast<unsigned long long>(pid));
551 cmdline_adb->Shell(cmdline_cmd.
GetData(), seconds(5), &cmdline_output);
553 if (cmdline_error.
Fail() || cmdline_output.empty())
556 cmdline_output = llvm::StringRef(cmdline_output).trim().str();
557 if (cmdline_output.empty())
560 llvm::SmallVector<llvm::StringRef, 16> args;
561 llvm::StringRef(cmdline_output).split(args,
' ', -1,
false);
567 for (
size_t i = 1; i < args.size(); i++) {
568 if (!args[i].empty())
583 std::string exe_output;
585 exe_cmd.
Printf(
"readlink /proc/%llu/exe 2>/dev/null",
586 static_cast<unsigned long long>(pid));
587 Status exe_error = exe_adb->Shell(exe_cmd.
GetData(), seconds(5), &exe_output);
589 if (exe_error.
Fail() || exe_output.empty())
592 exe_output = llvm::StringRef(exe_output).trim().str();
596 if (exe_output.find(
"64") != std::string::npos ||
597 exe_output.find(
"arm64") != std::string::npos ||
598 exe_output.find(
"aarch64") != std::string::npos) {
599 arch.
SetTriple(
"aarch64-unknown-linux-android");
600 }
else if (exe_output.find(
"x86_64") != std::string::npos) {
601 arch.
SetTriple(
"x86_64-unknown-linux-android");
602 }
else if (exe_output.find(
"x86") != std::string::npos ||
603 exe_output.find(
"i686") != std::string::npos) {
604 arch.
SetTriple(
"i686-unknown-linux-android");
607 arch.
SetTriple(
"armv7-unknown-linux-android");
624 return PlatformLinux::FindProcesses(match_info, proc_infos);
642 if (process_name.empty())
650 LLDB_LOGF(log,
"PlatformAndroid::%s failed to get ADB client: %s",
651 __FUNCTION__,
error.AsCString());
657 std::string pidof_output;
659 command.
Printf(
"pidof '%s'", process_name.c_str());
660 error = adb->Shell(command.
GetData(), seconds(5), &pidof_output);
664 LLDB_LOG(log,
"PlatformAndroid::{} 'pidof {}' failed: {}", __FUNCTION__,
665 process_name.c_str(),
error.AsCString());
672 pidof_output = llvm::StringRef(pidof_output).trim().str();
673 if (pidof_output.empty()) {
675 LLDB_LOGF(log,
"PlatformAndroid::%s no process found with name '%s'",
676 __FUNCTION__, process_name.c_str());
681 llvm::SmallVector<llvm::StringRef, 8> pid_strings;
682 llvm::StringRef(pidof_output).split(pid_strings,
' ', -1,
false);
687 uint32_t num_matches = 0;
688 for (llvm::StringRef pid_str : pid_strings) {
689 pid_str = pid_str.trim();
694 if (!llvm::to_integer(pid_str, pid)) {
695 LLDB_LOGF(log,
"PlatformAndroid::%s failed to parse PID from: '%s'",
696 __FUNCTION__, pid_str.str().c_str());
700 ProcessInstanceInfo process_info;
703 FileSpec::Style::posix);
711 if (match_info.
Matches(process_info)) {
712 proc_infos.push_back(process_info);
715 LLDB_LOGF(log,
"PlatformAndroid::%s found process '%s' with PID %llu",
716 __FUNCTION__, process_name.c_str(),
717 static_cast<unsigned long long>(pid));
725 auto sync_service = std::make_unique<AdbSyncService>(
m_device_id);
726 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)