Android: How to strace an app using ADB shell am start

我怕爱的太早我们不能终老 提交于 2019-11-28 18:29:29

The "am start" command does not directly run your application; it simply tells Android to do whatever is necessary to, in your example, start a specific activity.

The strace command is normally used as in strace commandname command args and it launches commandname -- easy, but in this Android use case, not helpful. However, strace has a -p option which is helpful to you: strace -p <process id> will let you start tracing the process with the specified id.

If you type ps on your Android system you can locate the process with the name com.akproduction.notepad (probably; by default processes are named for their Android package, but it's possible to change that in the manifest). Then you can start stracing it, wherever it happens to be.

If you need to catch things early in the process, you'll need to either modify the code to cause it to delay until you're ready to trace it, or you'll at least need to get the process running before you start the activity. The second option there is often as easy as starting the activity, then using the back button, then getting your trace ready, then starting the activity again -- but this is always code-specific to the application.

Android apps are actually started by forking the zygote process, so you can trace app initialization by tracing the zygote process and following child processes ('-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

This is an ugly one-liner hack I used today to solve this issue. Assuming the program has some known name, just try attaching to the process as soon as it appears. In this example, I'm interested in all calls to 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
James

Here's a one-liner that grabs the process id and pipes it to strace right after am launches the app. You won't get the first few instructions executed, but it kicks in early enough for my needs.

am start -n com.packagename.here\.ActivityName && set `ps | grep com.packagename.here` && strace -p $2

I would recommend prior to starting your app start strace on zygote process and follow forks. Zygote process is the main process from which every new process forks in Android, including your app. Then you might want to filter the log based on PIDs you are interested in. Example:

ps zygote

get the zygote PID, then

strace -f -p < zygote_PID >

I've found a tricky way to do this and also guarantee that all the syscalls are going to be catch. It can be done even if the app is not debuggable:

  • Set the Activity Manager (am) to put the app in debug mode with a -w option that will halt its execution until it is attached to a debugger
  • Start the application manually (you can just click on the screen on its icon or call it with am start
  • With the application halted, obtain its PID
  • With its PID obtained, call strace to trace this process
  • Finally, attach the debugger so the execution start.

Here are the steps:

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

Now just attach the debugger and enjoy, you can do it for example in Android Studio or Eclipse. From this point on the execution will begin and you will be able to trace it since the very first line of code.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!