frida-trace
Overview
frida-trace dynamically traces function calls at runtime by auto-generating JavaScript handler scripts for each matched function. Handlers are written to disk and can be edited live — frida-trace reloads them automatically. Supports native, Objective-C, Swift, Java, and JNI targets across macOS, iOS, Android, Windows, and Linux.
Prerequisites:
frida-toolsinstalled (pip install frida-tools)- For USB/remote targets: platform-appropriate
frida-serverbinary running on the device - For Android:
adbconnectivity; pushfrida-serverto/data/local/tmp/and run it
CLI Syntax
frida-trace [options] target
target is either a process name, bundle identifier, or is specified via -p/-f/-n/-N.
Full Option Reference
Connection Options
| Flag | Long form | Description |
|---|---|---|
-D ID | --device ID | Connect to device with the given ID |
-U | --usb | Connect to USB-attached device |
-R | --remote | Connect to remote frida-server (default port 27042) |
-H HOST | --host HOST | Connect to remote frida-server on HOST |
--certificate CERT | Expect TLS certificate from HOST | |
--origin ORIGIN | Set HTTP Origin header on remote connection | |
--token TOKEN | Authenticate with HOST using TOKEN | |
--keepalive-interval N | Keepalive in seconds; 0 disables; -1 auto-selects (default) | |
--p2p | Establish peer-to-peer connection with target | |
--stun-server ADDRESS | STUN server for --p2p | |
--relay addr,user,pass,turn-{udp|tcp|tls} | Add TURN relay for --p2p |
Target Selection
| Flag | Long form | Description |
|---|---|---|
-f TARGET | --file TARGET | Spawn and attach to file/bundle |
-F | --attach-frontmost | Attach to frontmost application |
-n NAME | --attach-name NAME | Attach to process by name |
-N IDENTIFIER | --attach-identifier IDENTIFIER | Attach to process by bundle identifier |
-p PID | --attach-pid PID | Attach to process by PID |
-W PATTERN | --await PATTERN | Wait for spawn matching PATTERN before attaching |
--stdio {inherit,pipe} | stdio behavior when spawning (default: inherit) | |
--aux option | Set aux spawn option, e.g. "uid=(int)42" (types: string, bool, int) | |
--realm {native,emulated} | Realm to attach in |
Function / Symbol Filtering
These options build a working set procedurally (see Working Set Semantics).
| Flag | Long form | Description |
|---|---|---|
-I MODULE | --include-module MODULE | Include all functions in MODULE (glob) |
-X MODULE | --exclude-module MODULE | Exclude all functions in MODULE (glob) |
-i FUNCTION | --include FUNCTION | Include [MODULE!]FUNCTION (glob) |
-x FUNCTION | --exclude FUNCTION | Exclude [MODULE!]FUNCTION (glob) |
-a MODULE!OFFSET | --add MODULE!OFFSET | Include unexported function by hex offset |
-T INCLUDE_IMPORTS | --include-imports INCLUDE_IMPORTS | Include program’s imports |
-t MODULE | --include-module-imports MODULE | Include all imports of MODULE |
-m OBJC_METHOD | --include-objc-method OBJC_METHOD | Include Objective-C method |
-M OBJC_METHOD | --exclude-objc-method OBJC_METHOD | Exclude Objective-C method |
-y SWIFT_FUNC | --include-swift-func SWIFT_FUNC | Include Swift function |
-Y SWIFT_FUNC | --exclude-swift-func SWIFT_FUNC | Exclude Swift function |
-j JAVA_METHOD | --include-java-method JAVA_METHOD | Include Java method (supports modifier flags) |
-J JAVA_METHOD | --exclude-java-method JAVA_METHOD | Exclude Java method |
-s DEBUG_SYMBOL | --include-debug-symbol DEBUG_SYMBOL | Include by debug symbol name |
Output & Session Options
| Flag | Long form | Description |
|---|---|---|
-q | --quiet | Do not format output messages |
-d | --decorate | Add module name to auto-generated onEnter log statement |
-S PATH | --init-session PATH | Execute JavaScript file(s) before first handler runs |
-P JSON | --parameters JSON | Assign JSON to global parameters variable in all handlers |
-o OUTPUT | --output OUTPUT | Dump messages to file |
-O FILE | --options-file FILE | Read additional CLI options from text file (can nest -O) |
--ui-port PORT | Serve the trace UI on TCP port PORT |
Runtime Options
| Flag | Description |
|---|---|
--runtime {qjs,v8} | JavaScript engine: qjs (QuickJS, default) or v8 |
--debug | Enable Node.js-compatible script debugger |
--squelch-crash | Suppress crash report output to console |
--version | Print version and exit |
Pattern Syntax for -i / -x
Both MODULE and FUNCTION parts are glob patterns. Accepted forms:
| Pattern | Meaning |
|---|---|
MODULE!FUNCTION | Specific function in specific module |
FUNCTION | Function name in all modules |
!FUNCTION | Equivalent to FUNCTION (explicit “any module”) |
MODULE! | All functions in MODULE (equivalent to -I MODULE) |
-i / -x Examples
| Option | Matches |
|---|---|
-i "msvcrt.dll!*cpy*" | All functions with cpy in name, only in msvcrt.dll |
-i "*free*" | All functions with free in name in ALL modules |
-i "!*free*" | Same as above |
-i "gdi32.dll!" | All functions in gdi32.dll (same as -I "gdi32.dll") |
Java Method Pattern Modifiers (-j)
Append /flags to the pattern. Supported flags:
| Flag | Meaning |
|---|---|
s | Match on full signature (not just method name) |
i | Case-insensitive match |
u | User-defined classes only (exclude SDK/framework classes) |
Example: -j '*!*certificate*/isu' — trace all methods with “certificate” in signature, case-insensitive, user classes only.
Working Set Semantics
frida-trace maintains an internal working set of (module, function) pairs to trace. Include/exclude options modify this set procedurally — order on the command line matters.
Example: Trace str* and mem* functions except those in msvcrt.dll.
Three orderings, three different results (functions exist in ucrtbase.dll, ntdll.dll, msvcrt.dll):
# Order 1: -i "str*" -i "mem*" -X "msvcrt.dll"
# str* → 80 entries (3 modules)
# mem* → +18 entries → 98 total
# -X msvcrt.dll → removes 34 entries → FINAL: 64 entries
# Order 2: -i "str*" -X "msvcrt.dll" -i "mem*"
# str* → 80 entries
# -X msvcrt.dll → removes 28 str* entries → 52 entries
# mem* → +18 entries (including msvcrt.dll again) → FINAL: 70 entries
# Order 3: -X "msvcrt.dll" -i "str*" -i "mem*"
# -X msvcrt.dll → working set empty, nothing removed
# str* → 80 entries
# mem* → +18 entries → FINAL: 98 entries
Key rule: -X/-x only removes entries already in the working set at the time of evaluation.
Handler Script Structure
frida-trace auto-generates a .js handler file per traced function under __handlers__/<module>/<function>.js. The file is watched — edit and save to apply changes live without restarting.
1{
2 onEnter(log, args, state) {
3 // Called when function is entered
4 // args: NativePointer[] — indexed by argument position
5 // state: object — persists between onEnter and onLeave of the same call
6 log('functionName()');
7 },
8
9 onLeave(log, retval, state) {
10 // Called when function returns
11 // retval: NativePointer — the return value
12 // state: same object as onEnter
13 }
14}
Handler API
| Parameter | Type | Available in | Description |
|---|---|---|---|
log | function(string) | both | Emit a log line to output |
args | NativePointer[] | onEnter | Function arguments as pointers |
retval | NativePointer | onLeave | Return value as pointer |
state | object | both | Shared state between enter/leave; also shared across all handlers when set via --init-session |
Access this inside handlers as the Frida InvocationContext — use this.returnAddress, this.threadId, this.context, etc.
-d / --decorate: Module Name in Log Output
Without --decorate:
1onEnter(log, args, state) {
2 log('memcpy()');
3},
With --decorate:
1onEnter(log, args, state) {
2 log('memcpy() [msvcrt.dll]');
3},
Useful when the same function name exists in multiple modules.
-a: Trace Unexported Functions by Offset
Trace functions not exported by their module (e.g. static C/C++ functions) using a known offset from the module base:
1frida-trace -p 1372 -a "libjpeg.so!0x4793c"
Format: MODULE!0xHEXOFFSET
frida-trace generates a handler file for each -a entry.
-P: Pass JSON Parameters to All Handlers
Assigns a JSON object to the global parameters variable accessible in every handler:
1# Linux/macOS
2frida-trace -p 1372 -P '{"displayPid": true}' -i "memcpy"
3
4# Windows (escape inner quotes with double-double-quotes)
5frida-trace -p 1372 -P "{""displayPid"": true}" -i "memcpy"
Handler usage:
1{
2 onEnter(log, args, state) {
3 log('memcpy() [msvcrt.dll]');
4 if (parameters.displayPid) {
5 log(`Process ID: ${Process.id}`);
6 }
7 },
8 onLeave(log, retval, state) {}
9}
-S: Session Initialization Scripts
Executes one or more JavaScript files before the first handler runs. Files can:
- Define globally visible functions (callable from any handler)
- Store data in the global
stateobject (accessible in all handlers asstate.propertyName)
Multiple -S flags may be specified; files are executed in order.
1frida-trace -p 6980 --decorate -i "gdi32full.dll!ExtTextOutW" -S core.js -S ms-windows.js
Session Script Example: core.js
1// Clone args into invCtx.args so they're accessible in onLeave()
2function cloneArgs(args, numArgs, invCtx) {
3 const items = [];
4 for (let i = 0; i !== numArgs; i++)
5 items.push(args[i]);
6 invCtx.args = items;
7}
8
9// Decode bitmask value using a Map<flagValue, flagName>
10function decodeBitflags(value, spec) {
11 if (value === 0) return '0';
12 const flags = [];
13 let pending = value;
14 for (const [flagValue, flagName] of spec.entries()) {
15 if ((value & flagValue) !== 0) {
16 flags.push(flagName);
17 pending &= ~flagValue;
18 if (pending === 0) break;
19 }
20 }
21 if (pending !== 0) flags.push(`0x${pending.toString(16)}`);
22 return flags.join(' | ');
23}
24
25// Hex dump `length` bytes at `address`, output via log()
26function prettyHexdump(log, desc, address, length) {
27 const lines = [];
28 prettyHexdumpLines(lines, desc, address, length);
29 log(lines.join('\n'));
30}
31
32function prettyHexdumpLines(lines, desc, address, length, indent = '\t\t') {
33 lines.push(`${desc} [${length} bytes]`);
34 try {
35 const s = hexdump(address, { length });
36 for (const line of s.split('\n')) lines.push(`${indent}${line}`);
37 } catch (e) {
38 lines.push(`${indent}WARNING: address is NOT VALID (${address})`);
39 }
40}
Session Script Example: ms-windows.js (depends on core.js)
1const extTextOptionsSpec = new Map([
2 [0x00004, 'ETO_CLIPPED'],
3 [0x00010, 'ETO_GLYPH_INDEX'],
4 [0x01000, 'ETO_IGNORELANGUAGE'],
5 [0x00800, 'ETO_NUMERICSLATIN'],
6 [0x00400, 'ETO_NUMERICSLOCAL'],
7 [0x00002, 'ETO_OPAQUE'],
8 [0x02000, 'ETO_PDY'],
9 [0x00080, 'ETO_RTLREADING'],
10 [0x10000, 'ETO_REVERSE_INDEX_MAP'],
11]);
12
13function decodeExttextoutOptions(flags) {
14 return decodeBitflags(flags, extTextOptionsSpec);
15}
16
17function rectStructToString(lprect) {
18 if (lprect.isNull()) return 'LPRECT is null';
19 const left = lprect.readU32();
20 const top = lprect.add(4).readU32();
21 const right = lprect.add(8).readU32();
22 const bottom = lprect.add(12).readU32();
23 return `(left, top, right, bottom) = (${left}, ${top}, ${right}, ${bottom})`;
24}
Namespace Isolation Pattern
To avoid name collisions across session scripts, scope functions to a named global:
1global.MyLibrary = {
2 doX() { /* ... */ },
3 doY() { /* ... */ }
4};
-O: Options File
Pass CLI options from a text file. Options may span multiple lines; the file itself may include further -O references.
1frida-trace -p 9753 --decorate -O additional-options.txt
additional-options.txt:
-i "gdi32full.dll!ExtTextOutW"
-S core.js -S ms-windows.js
-O module-offset-options.txt
module-offset-options.txt:
-a "gdi32full.dll!0x3918DC" -a "gdi32full.dll!0xBE7458"
-a "gdi32full.dll!0xBF9904"
Useful when the command line exceeds the OS maximum length.
USB Device Setup
When tracing a remote device via -U:
- Download the matching
frida-serverbinary from frida/frida releases - Push to device:
adb push frida-server-<ver>-android-arm /data/local/tmp/ - Start server:
adb shell "/data/local/tmp/frida-server &" - Run
frida-trace -U ...
Quick-Reference Examples
1# Trace recv*/send* in Safari with module decoration
2frida-trace --decorate -i "recv*" -i "send*" Safari
3
4# Trace a specific ObjC method
5frida-trace -m "-[NSView drawRect:]" Safari
6
7# Spawn iOS app and trace crypto APIs (USB)
8frida-trace -U -f com.toyopagroup.picaboo -I "libcommonCrypto*"
9
10# Spawn Android app and trace Java methods matching "certificate" (v8 runtime)
11frida-trace -U -f com.google.android.youtube --runtime=v8 -j '*!*certificate*/isu'
12
13# Trace all JNI functions in Android app
14frida-trace -U -i "Java_*" com.samsung.faceservice
15
16# Trace mem* functions in a Windows process, excluding msvcrt.dll
17frida-trace -p 1372 -i "msvcrt.dll!*mem*"
18
19# Trace *open* everywhere except msvcrt.dll
20frida-trace -p 1372 -i "*open*" -x "msvcrt.dll!*open*"
21
22# Trace unexported function by offset
23frida-trace -p 1372 -a "libjpeg.so!0x4793c"