jtrace - augmented, Linux/Android aware strace with plugin architecture
jtrace tool is another one of my tools that started in order to address a shortcoming - in this case, the lack of
strace(1) for ARM64. This was (somewhat) rectified with Google's finally providing one in their emulator image (which they finally produced as part of M), but the implementation is still buggy and falls short of the true power of system call tracing. So I decided to write my own. As in other cases, the tool evolved and actually became useful by its own right, so I'm releasing it. (I also feel bad about forgetting to give my Androidevotee followers a present like the one I gave the Applytes)
This tool is provided as one of the free downloads provided for the "Android Internals" book (http://NewAndroidBook.com/). You are welcome to use it even if you don't buy the book (though naturally you're even more welcome to buy the book :-). I used it extensively in my research, and provide plenty of use cases as experiments and examples in Volume II (especially for dealing with Binder).
The tool's latest stable version, as a tar file with binaries - presently ARM64 and x86_64 , can always be obtained at this page right here. If you want my "nightly" build (a much more frequently updated, albeit potentially less stable build) it's here. An older version did support ARM32, but it doesn't make sense to support it anymore.
jtrace offers several significant advantages over
- Android-awareness: Not just dumping system calls, but actually deciphering some socket based I/O, including
- System Property settings (for PID 1,
/init) - see examples, below
- Input events (for InputReader) - see examples, below
- Binder message parsing (auto detected). For some processes (notably,
ActivityManager) it will actually decipher the parcels as well! And more will be added with plugins (this is presently unstable)
- .. And I'm working on intents and InputDispatcher, so expect these soon
- System Property settings (for PID 1,
- Colorized output: Actually very useful considering the copious output involved
- Thread name capabilities: Android uses
prctl(2)to name threads (especially in
system_server). You can attach directly to a target thread by specifying its name.
- Plugins: Enabling anyone to interface with the tool by providing their own shared object, which
jtracewill be happy to load, and call back.
- Fault injection: (beta): Allowing you to intercept and actually block certain system calls, or alter their arguments/return value - Still working on this one and not ready for mass consumption
- Automatically tags descriptors returned from
open[at](2)/etc. so you can find them in copious output
For updates, you might want to check out the RSS feed, or follow my company's feed, @Technologeeks, which (aside from the occasional OS X/iOS related stuff) tweets about updates to this and other tools.
jtrace is designed to be as compatible with
strace(1) as possible.
If you're not too familiar with
strace(1), you ought to be - no native level developer, on any Linux or Android - can afford to remain unaware of this amazingly powerful piece of work. I myself owe a fair deal of my knowledge to countless hours spent using this tool to trace all sorts of binaries to figure out how things really work, without reading any source code (which often didn't exist openly).
As is usual, running it with no arguments will produce a usage message.
Tracing property operations
All property set operations have to go through
init - so to get those, just attach to it!
As you can see above,
jtrace will show you the full operation involved - from getting the socket request, through checking SELinux, and the setting of the properties. But
grep(1) is your friend if you just want to get the properties being set.
(you won't be able to trace property get operations - not due to a
jtrace limitation, but because these are performed in-memory and do not involve syscalls)
--thread you can attach to
InputReader thread (without needing to dig up its PID), and
jtrace will be smart enough to figure when input events are involved, and decode them for you!
Binder, only the most critical and least comprehensible IPC/RPC mechanism in Android, is slowly yielding before
jtrace! New version A) doesn't crash on it and B) already supports quite a few interfaces! You can isolate Binder messages by
Note the use of
-f to auto-attach to threads - since Binder spawns a thread pool (might crash in rare cases, I got that bug). I'm also working on deep message tracing (i.e. with arguments, like it does for servicemanager). If AIDL finally does cpp, this will make my life easier. Expect more soon.
- Jtrace for ARM 32
- Jtrace for Android x86!
- Jtrace for Linux!
- SDK for plugins - so you can interface with jtrace and write your own hooks! IMHO, this can be huge and open up a world of third party plugins! The API is designed to be as architecture agnostic as possible, wherein you provide a shared object (.so) that calls on
jtrace's engine, without worrying about registers and memory APIs - you just call on a standardized, argument-centric API I've provided:
12/05/2021 - AIDL awareness
jtrace64 (the Android version) is now compiled with AIDLwise - a small library capable of parsing AIDL files - so if you drop AIDLs in
JAIDL_DIR it will automatically look foor them whenever tracing binder. The
jtrace.tgz download now comes bundled with "12.0.aidls.tgz" - just unpack them, set the dir, and start tracing:
Example Plugin Usage
JTrace now auto-loads plugins. Drop your plugin into the JTrace directory (specified by
JTRACE_EXT_PATH or in
setprop feature. This has changed in Oreo to the setprop v2 format. Although
jtrace innately supports v1, without a plugin v2 would look like this:
But with the plugin, it looks soooo much better:
Another example, for lmkd:
Get the source of the sample plugin for /dev/kgsl-3dd0
Get the source of the sample plugin for /dev/socket/lmkd
Get the jtraceAPI.h (latest)