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:


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

FlagLong formDescription
-D ID--device IDConnect to device with the given ID
-U--usbConnect to USB-attached device
-R--remoteConnect to remote frida-server (default port 27042)
-H HOST--host HOSTConnect to remote frida-server on HOST
--certificate CERTExpect TLS certificate from HOST
--origin ORIGINSet HTTP Origin header on remote connection
--token TOKENAuthenticate with HOST using TOKEN
--keepalive-interval NKeepalive in seconds; 0 disables; -1 auto-selects (default)
--p2pEstablish peer-to-peer connection with target
--stun-server ADDRESSSTUN server for --p2p
--relay addr,user,pass,turn-{udp|tcp|tls}Add TURN relay for --p2p

Target Selection

FlagLong formDescription
-f TARGET--file TARGETSpawn and attach to file/bundle
-F--attach-frontmostAttach to frontmost application
-n NAME--attach-name NAMEAttach to process by name
-N IDENTIFIER--attach-identifier IDENTIFIERAttach to process by bundle identifier
-p PID--attach-pid PIDAttach to process by PID
-W PATTERN--await PATTERNWait for spawn matching PATTERN before attaching
--stdio {inherit,pipe}stdio behavior when spawning (default: inherit)
--aux optionSet 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).

FlagLong formDescription
-I MODULE--include-module MODULEInclude all functions in MODULE (glob)
-X MODULE--exclude-module MODULEExclude all functions in MODULE (glob)
-i FUNCTION--include FUNCTIONInclude [MODULE!]FUNCTION (glob)
-x FUNCTION--exclude FUNCTIONExclude [MODULE!]FUNCTION (glob)
-a MODULE!OFFSET--add MODULE!OFFSETInclude unexported function by hex offset
-T INCLUDE_IMPORTS--include-imports INCLUDE_IMPORTSInclude program’s imports
-t MODULE--include-module-imports MODULEInclude all imports of MODULE
-m OBJC_METHOD--include-objc-method OBJC_METHODInclude Objective-C method
-M OBJC_METHOD--exclude-objc-method OBJC_METHODExclude Objective-C method
-y SWIFT_FUNC--include-swift-func SWIFT_FUNCInclude Swift function
-Y SWIFT_FUNC--exclude-swift-func SWIFT_FUNCExclude Swift function
-j JAVA_METHOD--include-java-method JAVA_METHODInclude Java method (supports modifier flags)
-J JAVA_METHOD--exclude-java-method JAVA_METHODExclude Java method
-s DEBUG_SYMBOL--include-debug-symbol DEBUG_SYMBOLInclude by debug symbol name

Output & Session Options

FlagLong formDescription
-q--quietDo not format output messages
-d--decorateAdd module name to auto-generated onEnter log statement
-S PATH--init-session PATHExecute JavaScript file(s) before first handler runs
-P JSON--parameters JSONAssign JSON to global parameters variable in all handlers
-o OUTPUT--output OUTPUTDump messages to file
-O FILE--options-file FILERead additional CLI options from text file (can nest -O)
--ui-port PORTServe the trace UI on TCP port PORT

Runtime Options

FlagDescription
--runtime {qjs,v8}JavaScript engine: qjs (QuickJS, default) or v8
--debugEnable Node.js-compatible script debugger
--squelch-crashSuppress crash report output to console
--versionPrint version and exit

Pattern Syntax for -i / -x

Both MODULE and FUNCTION parts are glob patterns. Accepted forms:

PatternMeaning
MODULE!FUNCTIONSpecific function in specific module
FUNCTIONFunction name in all modules
!FUNCTIONEquivalent to FUNCTION (explicit “any module”)
MODULE!All functions in MODULE (equivalent to -I MODULE)

-i / -x Examples

OptionMatches
-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:

FlagMeaning
sMatch on full signature (not just method name)
iCase-insensitive match
uUser-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

ParameterTypeAvailable inDescription
logfunction(string)bothEmit a log line to output
argsNativePointer[]onEnterFunction arguments as pointers
retvalNativePointeronLeaveReturn value as pointer
stateobjectbothShared 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:

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:

  1. Download the matching frida-server binary from frida/frida releases
  2. Push to device: adb push frida-server-<ver>-android-arm /data/local/tmp/
  3. Start server: adb shell "/data/local/tmp/frida-server &"
  4. 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"