Android: 如何使用ADB shell am start跟踪应用程序

9
我需要在SDK模拟器中跟踪Android应用程序的帮助。
这是我的设置:
我有一个运行Android API 4.03的Android SDK模拟器,ADB shell连接到模拟器。
我能够使用ADB install filename.apk安装APK
我能够使用ADB shell am start -a android.intent.action.Main -n com.akproduction.notepad/com.akproduction.notepad.NoteList运行应用程序
我尝试使用(ADB shell) strace am start -a android.intent.action.Main -n com.akproduction.notepad/com.akproduction.notepad.NoteList进行跟踪,但我什么也没有得到!
如何跟踪Android应用程序及其安装的运行时行为?
(附注:测试应用程序位于此处。)
7个回答

11

Android应用程序实际上是通过分叉zygote进程启动的,因此您可以通过跟踪zygote进程并跟随子进程('-f')来跟踪应用程序初始化:

setenforce 0  # In Android 4.3 and later, if SELinux is enabled, strace will fail with "strace: wait: Permission denied"

set `ps | grep zygote` ; strace -p $2 -f -tt -T -s 500 -o /sdcard/strace.txt

遇到了Aaron提到的同样问题。有人知道如何处理/解决吗? - docpkd
我在Android 5.1上使用http://benno.id.au/android/strace跟踪zygote时没有遇到任何问题。您使用的是哪个版本的strace / Android?当zygote崩溃时,adb logcat是否显示堆栈跟踪或其他有用信息?请注意,zygote可能会内部抛出并捕获SIGSEGV以处理空指针或一些垃圾收集功能,并且strace将检测并打印此信息,但这不一定表示zygote实际上正在崩溃。您只是在strace输出中看到了SIGSEGV并假设zygote正在崩溃,还是您确定zygote实际上正在崩溃? - Paul Donohue

10

"am start"命令并不直接运行您的应用程序;它只是告诉Android需要做什么来启动一个特定的活动,以您的示例为例。

strace 命令通常使用如下: strace commandname command args ,它启动 commandname -- 简单易用。但在 Android 的情况下,它并没有什么帮助。然而,strace 有一个 -p 选项对您很有帮助:strace -p <process id> 将允许您开始跟踪指定 ID 的进程。

如果您在 Android 系统上键入 ps , 您可以找到名为 com.akproduction.notepad (可能;默认情况下,进程按其 Android 包命名,但在清单中也可能更改)。然后你可以开始 stracing 它,无论它在哪里。

如果您需要在进程早期捕获信息,则需要修改代码以使其延迟直到您准备好跟踪它,或者至少需要在启动活动之前先让进程运行。第二个选项通常很容易,只需启动活动,然后使用返回按钮,然后准备好您的跟踪,然后再次启动活动 -- 但这始终是特定于应用程序的代码。


4

我今天使用的是一个丑陋的单行代码解决了这个问题。假设程序有一个已知的名称,只需在它出现时尝试附加到该进程即可。在此示例中,我对所有对open的调用感兴趣。

while true; do
  while ! ps  | grep -q -i MyProgram; do :; done;
  ps | grep -i MyProgram | while read a b c; do
   strace -e open -f -p $b;
  done;
done

4
这是一个一行命令,获取进程ID并在am启动应用程序后将其传输到strace。您不会得到执行的前几个指令,但它足够早地满足我的需求。 am start -n com.packagename.here\.ActivityName && set `ps | grep com.packagename.here` && strace -p $2

1
根据这个一行代码,我又写了一个可以在Android 9及以上版本上运行的代码: am start -n com.packagename.here\/.MainActivity && sleep 1 && set \pidof com.packagename.here` && strace -f -p $1` - Pellaeon

3

在启动应用程序之前,我建议您在zygote进程上启动strace并跟随fork。 Zygote进程是Android中每个新进程都从中分叉的主要过程,包括您的应用程序。 然后,您可能希望根据您感兴趣的PID过滤日志。 例如:

ps zygote

获取zygote PID,然后

strace -f -p < zygote_PID >


1
我发现了一个巧妙的方法,可以保证所有系统调用都被捕获,即使应用程序不可调试:
  • 使用 Activity Manager (am) 将应用程序设置为调试模式,并使用 -w 选项暂停其执行,直到它连接到调试器
  • 手动启动应用程序(您可以点击屏幕上的图标或使用 am start 调用它)
  • 当应用程序暂停时,获取其 PID
  • 获得其 PID 后,调用 strace 来跟踪此进程
  • 最后,附加调试器以开始执行。
以下是步骤:
adb shell # shell into the device
am set-debug-app -w com.package.name # put app to debug mode
am start com.package.name/com.path.to.MainActivity # start the app
ps -A | grep com.package.name # this will show you the PID
strace -p <PID> > appoutput.txt 2> appstrace.txt 
# strace the program and record its output and strace in txt files

现在只需附加调试器并享受,例如在Android Studio或Eclipse中可以完成此操作。从这一点开始执行,您将能够追踪代码的第一行。

0

如果您拥有root访问权限或设备未启用SELinux,则可以按照Android网站上的方法进行操作:

设置设备以便您可以运行strace。您需要成为root用户,禁用SELinux,并重新启动运行时以删除seccomp过滤器,否则将阻止strace运行: adb root adb shell setenforce 0 adb shell stop adb shell start

为strace日志设置一个全局可写目录,因为strace将在应用程序的uid下运行: adb shell mkdir -m 777 /data/local/tmp/strace

选择要跟踪的进程并启动它: adb shell setprop wrap.com.android.calendar '"logwrapper strace -f -o /data/local/tmp/strace/strace.com.android.calendar.txt"'

正常启动该进程。

https://source.android.com/devices/tech/debug/strace#app-strace


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接