Compare commits

...
123 Commits
Author SHA1 Message Date
Ole André Vadla Ravnås 36200d4c17 subprojects: Prepare for release 2025-06-20 15:45:32 +02:00
Ole André Vadla Ravnås bd1f855f4a subprojects: Bump outdated 2025-06-20 15:44:10 +02:00
Ole André Vadla RavnåsandHåvard Sørbø d752b63d3f package-manager: Improve manifest handling
To get us closer to npm's behavior.

Co-authored-by: Håvard Sørbø <[email protected]>
2025-06-20 15:43:29 +02:00
Ole André Vadla Ravnås a66e35d457 package-manager: Improve progress reporting 2025-06-20 11:46:30 +02:00
Ole André Vadla Ravnås 931270de32 package-manager: Refactor a little bit 2025-06-20 11:45:50 +02:00
Ole André Vadla Ravnås 90d54afbf4 promise: Add Future.then() and Future.get_result() 2025-06-20 10:58:00 +02:00
Ole André Vadla Ravnås 0a75b51e7b package-manager: Fix dependency install deadlock
A deadlock could occur when a package's sub-dependency was also a
dependency of another package higher up in the installation stack.
The sub-dependency would wait for the higher-level package to be
physically installed, but that package would not complete its own
installation until its sub-dependencies were resolved, creating a
circular wait.

Refactor the installation logic to first perform the physical
installation of a package. Once the package is on disk, a promise
tracking its physical presence is resolved. Only then does the process
recurse to install the package's own dependencies. This ensures that
any other part of the installation process waiting for this specific
package can proceed, breaking the cycle.
2025-06-20 10:17:38 +02:00
Ole André Vadla Ravnås 20d5d121b7 subprojects: Prepare for release 2025-06-20 01:13:54 +02:00
Ole André Vadla Ravnås dc71534220 subprojects: Bump outdated 2025-06-20 01:12:26 +02:00
Ole André Vadla Ravnås 35afee9b4a package-manager: Handle tarballs with root entries
Like if there's a directory entry for "package/", or somehow any files
at the root level.
2025-06-20 01:11:39 +02:00
Ole André Vadla Ravnås 7b130e6eba package-manager: Fix handling of scoped specs 2025-06-20 01:11:39 +02:00
Ole André Vadla Ravnås d28c46c332 package-manager: Fix a stylistic inconsistency 2025-06-20 01:11:39 +02:00
Ole André Vadla Ravnås ab103a73ca package-manager: Simplify substring logic 2025-06-20 01:11:39 +02:00
Ole André Vadla Ravnås 7b7d9acf8c subprojects: Prepare for release 2025-06-19 23:25:44 +02:00
Ole André Vadla Ravnås 215076a0fa subprojects: Bump outdated 2025-06-19 23:23:46 +02:00
Ole André Vadla Ravnås 3d47bf73b4 package-manager: Only report installed packages
The toplevel packages that were left untouched should not be included.

Also simplify the install() logic while at it.
2025-06-19 23:22:22 +02:00
Ole André Vadla Ravnås 7d84a44c7f package-manager: Fix the lockfile up-to-date path 2025-06-19 22:55:19 +02:00
Ole André Vadla Ravnås ef7e0a88e0 package-manager: Fix two stylistic inconsistencies 2025-06-19 22:53:09 +02:00
Ole André Vadla Ravnås 1f95416a77 subprojects: Prepare for release 2025-06-19 21:03:42 +02:00
Ole André Vadla Ravnås 80c7ec2dce meson: Fix build when libsoup is a subproject 2025-06-19 20:23:30 +02:00
Ole André Vadla Ravnås 69c68fdf7f subprojects: Bump outdated 2025-06-19 20:18:51 +02:00
Ole André Vadla Ravnås 7070042128 compiler: Make backend a shared library on Android
To avoid dynamic linking issues due to thread-local storage. This was
caused by our previous hack where we pretended Android was GOOS=linux
to work around the Go toolchain refusing `-buildmode=c-archive` for
GOOS=android.
2025-06-19 20:17:06 +02:00
Ole André Vadla Ravnås 9a4ce30be5 post-process: Support skipping ELF-cleaner step
It seems to corrupt shared library ELFs generated by the Go toolchain.
2025-06-19 20:08:47 +02:00
Ole André Vadla Ravnås 7731aea6f7 linux: Split out useful primitives into base
- check_kernel_version()
- FileDescriptor
- PidFileDescriptor
- MemoryFileDescriptor
2025-06-19 20:08:47 +02:00
Ole André Vadla Ravnås 3f8ace5f7b subprojects: Prepare for release 2025-06-18 23:34:57 +02:00
Ole André Vadla Ravnås d1e8aaa8e6 subprojects: Bump outdated 2025-06-18 23:33:44 +02:00
Ole André Vadla Ravnås 28a1084e7d compiler: Bump @frida/net to 5.0.0 2025-06-18 23:16:34 +02:00
Ole André Vadla Ravnås ac62e5d96d package-manager: Fix manifest progress
It should not have details, so it ends up in the toplevel progress
group, as far as UIs are concerned.
2025-06-18 22:56:43 +02:00
Ole André Vadla Ravnås 05bdfde104 package-manager: Add url property to Package
Only present in search results.
2025-06-18 19:49:44 +02:00
Ole André Vadla Ravnås 938e724f2d package-manager: Fix a stylistic inconsistency 2025-06-18 19:48:05 +02:00
Ole André Vadla Ravnås bf1d417445 Add PackageManager
To aid in discovering and installing Frida-specific packages without the
need for Node.js + npm. Power users and package maintainers will still
typically be using npm though. The goal is to streamline the consumption
of bridges and other Frida-specific packages.
2025-06-17 12:40:37 +02:00
Ole André Vadla Ravnås d9317e6265 base: Add FS namespace with filesystem helpers 2025-06-17 10:28:26 +02:00
Ole André Vadla Ravnås 01fd21f004 buffer: Add BufferReader.skip() 2025-06-17 10:28:26 +02:00
Ole André Vadla Ravnås e576f36f05 buffer: Allow trailing NULs in read_fixed_string() 2025-06-17 10:28:26 +02:00
He Li 9a7623a448 compiler: Fix missing shim assets (#1176)
Previously, the embeddedShims glob only matched files up to two directory
levels deep. This caused imports like:

    open node_modules/@frida/assert/internal/util/comparisons.js:
    file does not exist

This change adds an extra glob pattern that matches one more directory
level, allowing shim assets located one level deeper to be found correctly.
2025-06-17 10:27:49 +02:00
Ole André Vadla Ravnås 7dc0b5e4ee subprojects: Prepare for release 2025-06-13 16:28:17 +02:00
Ole André Vadla Ravnås a18eab4afa subprojects: Bump outdated 2025-06-13 16:27:21 +02:00
WorksButNotTested 8a30f241d1 ci: Fix builds of helpers and labrats 2025-06-13 16:25:05 +02:00
WorksButNotTested 78fbe5a20b tests: Disable slow test on armbe8 2025-06-13 16:25:05 +02:00
Ole André Vadla Ravnås e667582d54 android: Bump frida-java-bridge in system-server 2025-06-13 16:22:25 +02:00
Ole André Vadla Ravnås f5dd273c8c subprojects: Prepare for release 2025-06-10 22:09:49 +02:00
Ole André Vadla Ravnås 5438597c19 subprojects: Bump outdated 2025-06-10 22:05:53 +02:00
WorksButNotTested bb1f944f43 ci: Fix emulator error propagation 2025-06-10 22:05:07 +02:00
Ole André Vadla Ravnås 294df78147 darwin: Bump frida-objc-bridge in internal agents 2025-06-10 22:04:16 +02:00
Ole André Vadla Ravnås 2f1d24f96f android: Bump frida-java-bridge in system-server 2025-06-10 22:02:29 +02:00
Ole André Vadla Ravnås 918c83d25c compiler: Update package-lock.json 2025-06-10 21:07:51 +02:00
Ole André Vadla Ravnås a580d22bb6 agents: Switch esbuild platform to node
Internal agent bundles were still built with `--platform=neutral`, so
esbuild ignored each package’s package.json metadata. Modules that
rely on Node-style resolution could therefore fail to bundle.
2025-06-10 21:04:44 +02:00
Ole André Vadla Ravnås 238b81c26d compiler: Switch esbuild platform to node
Neutral mode ignores package.json, so modules that rely on "main" or
"exports" fields were left unresolved. Setting PlatformNode lets esbuild
read package.json and resolve such modules correctly.

No functional change for code that was already valid under Neutral; it
just unbreaks packages that expect Node semantics.

Kudos to @hsorbo for helping track this one down.
2025-06-10 20:59:21 +02:00
Ole André Vadla Ravnås 413ba51568 plist: Fix XML output of empty dicts/arrays
Apple’s encoder emits <dict/> and <array/> for empty collections; we were
producing <dict></dict> and <array></array>. The stricter form makes it
harder to compare plists byte-for-byte.

Our to_xml() now emits the self-closing tags so its XML output matches
Apple’s encoder.
2025-06-10 20:48:55 +02:00
Ole André Vadla Ravnås 3767957065 plist: Fix offsetIntSize for binary output
When to_binary() builds a bplist, the trailer’s offset-size field must
encode the offset of the offset table itself. We were deriving
offsetIntSize from the last object’s offset, so a plist whose table began
at 0x100 or beyond could still advertise size = 1 and be rejected by
Core Foundation as corrupt.

Size is now chosen from offset_table_offset. The XML path (to_xml())
is unaffected.

Kudos to @mrmacete for helping track this one down.
2025-06-10 20:41:36 +02:00
Ole André Vadla Ravnås ec3b864007 subprojects: Prepare for release 2025-06-07 13:32:23 +02:00
Ole André Vadla Ravnås 93fc48d20e subprojects: Bump outdated 2025-06-07 13:30:19 +02:00
Ole André Vadla Ravnås 4f120d9e46 meson: Simplify the Vala flags logic 2025-06-07 13:29:46 +02:00
Ole André Vadla Ravnås f9ee24038b gadget: Correct QuickJS big-endian bytecode check 2025-06-07 13:27:49 +02:00
Ole André Vadla Ravnås 5692298b03 subprojects: Bump outdated 2025-06-07 11:23:12 +02:00
Ole André Vadla Ravnås 375be6181a compiler: Rename conflictful Go symbols in backend
To avoid conflicts when we're linked into a Go binary.
2025-06-07 11:22:36 +02:00
Ole André Vadla Ravnås e5fa1b1fab api: Add version defines and macros 2025-06-07 11:20:23 +02:00
Ole André Vadla Ravnås 8e76c7257b subprojects: Prepare for release 2025-06-06 22:11:36 +02:00
Ole André Vadla Ravnås 282927b5b6 subprojects: Bump outdated 2025-06-06 22:10:29 +02:00
Ole André Vadla Ravnås fe235491a5 compiler: Make the DeviceManager optional
It is no longer used, but we cannot drop the constructor argument
without breaking API.
2025-06-06 22:09:40 +02:00
Ole André Vadla Ravnås 46d4d1223a subprojects: Prepare for release 2025-06-06 14:11:13 +02:00
Ole André Vadla Ravnås 6f8d8cba28 linux: Fix the system-server.js build system logic 2025-06-06 13:26:51 +02:00
Ole André Vadla Ravnås 2ee3926912 subprojects: Bump outdated 2025-06-06 12:38:22 +02:00
Ole André Vadla Ravnås 11f93e20b8 compile-js-agent: Remove commented “npm link” example
As it is no longer relevant.
2025-06-06 12:37:32 +02:00
Ole André Vadla Ravnås ad15eb2b01 darwin: Switch reportcrash.js bundling to ESBuild 2025-06-06 12:36:27 +02:00
Ole André Vadla Ravnås 26c9cf3cc5 darwin: Switch osanalytics.js bundling to ESBuild 2025-06-06 12:34:21 +02:00
Ole André Vadla Ravnås 8176ea1361 linux: Switch system-server.js bundling to ESBuild 2025-06-06 12:29:35 +02:00
Ole André Vadla Ravnås ecc63e5591 barebone: Simplify the ESBuild invocation 2025-06-06 12:27:23 +02:00
Ole André Vadla Ravnås ac5898a547 barebone: Fix ESM-handling
Where we failed to await the returned Promise, so any errors would end
up being swallowed.
2025-06-06 11:38:16 +02:00
Ole André Vadla Ravnås 055360cbb6 barebone: Remove bridge globals 2025-06-06 11:37:07 +02:00
Ole André Vadla Ravnås c9b18a5f4b barebone: Switch runtime bundling to ESBuild 2025-06-06 11:36:28 +02:00
Ole André Vadla Ravnås eb55aef18e subprojects: Prepare for release 2025-06-05 22:05:20 +02:00
Ole André Vadla Ravnås 11ba9175d0 subprojects: Bump outdated 2025-06-05 21:11:15 +02:00
Ole André Vadla Ravnås 6dd7e203bf ci: Fix a stylistic inconsistency 2025-06-05 20:07:22 +02:00
Ole André Vadla Ravnås 3a312faa1e ci: Fix the Windows build step 2025-06-05 19:27:22 +02:00
Ole André Vadla Ravnås 6f97782eff meson: Warn when Compiler backend is auto-disabled 2025-06-05 19:21:48 +02:00
Ole André Vadla Ravnås 412e525210 cgo: Fix path logic when consumed as a subproject 2025-06-05 19:21:16 +02:00
Ole André Vadla Ravnås c6e8ef5a29 ci: Clean up and fix Compiler backend enable logic 2025-06-05 19:14:45 +02:00
Ole André Vadla Ravnås 0df0eefdc9 cgo: Treat arm64e as unsupported
As cgo does not yet support it.
2025-06-05 19:08:26 +02:00
Ole André Vadla Ravnås dc60f8bf10 ci: Simplify the Compiler backend enable logic 2025-06-05 19:01:31 +02:00
Ole André Vadla Ravnås 2b9f3764c5 ci: Disable Compiler backend for the emulator job 2025-06-05 18:55:35 +02:00
Ole André Vadla Ravnås 89e01be599 ci: Skip tests on macOS for now
So we can get back to a green baseline.
2025-06-05 18:49:26 +02:00
Ole André Vadla Ravnås 228a37fabf ci: Fix the compiler backend option passed in 2025-06-05 18:36:03 +02:00
Ole André Vadla Ravnås 40ec5e03cc subprojects: Bump outdated 2025-06-05 17:02:16 +02:00
Ole André Vadla RavnåsandHåvard Sørbø 6acb6da386 ci: Explicitly enable compiler
So it's not silently disabled in cases where cgo should be available.

Co-authored-by: Håvard Sørbø <[email protected]>
2025-06-05 17:00:49 +02:00
Ole André Vadla RavnåsandHåvard Sørbø 9b9c91c1f2 ci: Improve naming of the Go toolchain steps
Co-authored-by: Håvard Sørbø <[email protected]>
2025-06-05 17:00:49 +02:00
Ole André Vadla Ravnås c5809da386 ci: Temporarily remove the FreeBSD/arm64 job
Until we have a working runner for it.
2025-06-05 17:00:49 +02:00
Ole André Vadla RavnåsandHåvard Sørbø 6b76a1b2d4 ci: Fix the native Windows/x86 job
Which was building for x86_64 instead of x86.

Co-authored-by: Håvard Sørbø <[email protected]>
2025-06-05 17:00:49 +02:00
Ole André Vadla Ravnås 3da7b8bbd0 submodules: Bump releng 2025-06-05 17:00:49 +02:00
Ole André Vadla Ravnås adc93c3bf8 ci: Add native job for Windows/arm64 2025-06-05 17:00:49 +02:00
Ole André Vadla Ravnås b85397b690 ci: Install MinGW in the Windows native jobs 2025-06-05 17:00:49 +02:00
Ole André Vadla Ravnås b22326f233 ci: Add Go to the build jobs 2025-06-05 17:00:49 +02:00
Ole André Vadla Ravnås 531cfb17c0 ci: Remove trailing whitespace 2025-06-05 17:00:49 +02:00
Ole André Vadla RavnåsandHåvard Sørbø 0a4bb7aed5 compiler: Normalize paths passed to typescript-go
So it also works on Windows.

Co-authored-by: Håvard Sørbø <[email protected]>
2025-06-05 17:00:49 +02:00
Ole André Vadla RavnåsandHåvard Sørbø 274898d39c compiler: Fix handling of TypeScript diagnostics
Where ESBuild Message entries without notes were incorrectly handled.

Co-authored-by: Håvard Sørbø <[email protected]>
2025-06-05 17:00:49 +02:00
Ole André Vadla RavnåsandHåvard Sørbø c6c30833c8 compiler: Avoid Go alignment bug on Windows/x86_64
Where C arguments passed on the stack that are smaller than 8 bytes are
incorrectly laid out when calling into the Go runtime.

Co-authored-by: Håvard Sørbø <[email protected]>
2025-06-05 17:00:49 +02:00
Ole André Vadla RavnåsandHåvard Sørbø 7b30a9c516 compiler: Fix cross-platform build issues
Co-authored-by: Håvard Sørbø <[email protected]>
2025-06-05 17:00:49 +02:00
Ole André Vadla Ravnås 32220057a8 meson: Allow compiler backend w/o local backend
Now that it no longer needs it for script execution.
2025-06-02 09:39:34 +02:00
Ole André Vadla RavnåsandHåvard Sørbø b7284691ca compiler: Move to ESBuild and typescript-go
For massively improved performance, and to reduce our maintenance burden
by no longer having to maintain a bundler.

Also add options to configure the output and bundle format, and support
disabling type checks.

Co-authored-by: Håvard Sørbø <[email protected]>
2025-06-01 23:46:10 +02:00
Ole André Vadla Ravnås 71a1b0f800 subprojects: Bump outdated 2025-06-01 11:04:52 +02:00
Ole André Vadla Ravnås b8b42a904b submodules: Bump releng 2025-06-01 11:04:51 +02:00
WorksButNotTested fdb4c5107c ci: Add jobs that test on armbe8 and arm64be (#1162) 2025-05-29 21:30:35 +02:00
Francesco Tamagni 8108d4d954 Plug Interceptor singleton leaks (#1167) 2025-05-29 21:29:15 +02:00
Ole André Vadla Ravnås 44a9757589 subprojects: Prepare for release 2025-05-29 17:32:06 +02:00
Ole André Vadla Ravnås 8c939d4954 subprojects: Bump outdated 2025-05-29 17:30:09 +02:00
Francesco Tamagni 8bb0dd14a4 device: Allow agent sessions to detach before release (#1164)
To be robust against scenarios where an out-of-order detach could lead
to indefinite hang at release time.
2025-05-29 17:22:57 +02:00
Ole André Vadla Ravnås 59619f57ca subprojects: Prepare for release 2025-05-28 23:17:01 +02:00
Ole André Vadla Ravnås 5ed7378bb0 subprojects: Bump outdated 2025-05-28 23:16:07 +02:00
londek 4d2bba4b2a darwin: Fix the launchd agent (#1166)
Which was still using an old GumJS API that is now gone.
2025-05-28 23:11:27 +02:00
Ole André Vadla Ravnås e2e2eaab82 subprojects: Prepare for release 2025-05-24 21:03:20 +02:00
Ole André Vadla Ravnås d286cbb09c subprojects: Bump outdated 2025-05-24 21:01:59 +02:00
Ole André Vadla Ravnås c910622a6a compile-js-agent: Explicitly run the build script
To ensure incremental compilation works consistently, as `npm install`
will not always run the `prepare` script.
2025-05-24 21:00:59 +02:00
Ole André Vadla Ravnås 7599500a3b compile-js-agent: Add commented “npm link” example 2025-05-24 20:59:14 +02:00
Ole André Vadla Ravnås fe4db7e37f compile-js-agent: Improve error-reporting
By capturing both stdout and stderr.
2025-05-24 20:58:33 +02:00
Ole André Vadla Ravnås 6064d0c084 Fix agents generated by latest frida-compile
We need to explicitly declare internal agents as ESM now that the
TypeScript compiler is more conformant and ends up generating CommonJS
glue code.

This fixes our Darwin and Android agents, as well as the Barebone
backend's script runtime.
2025-05-24 20:50:43 +02:00
Ole André Vadla Ravnås f970529e08 subprojects: Prepare for release 2025-05-22 21:39:32 +02:00
Ole André Vadla Ravnås 031614ddc2 compiler: Fix asset bundling logic on Windows
Where virtual paths were stored with the wrong path separator.
2025-05-22 21:20:34 +02:00
Ole André Vadla Ravnås 71d82bcebc subprojects: Bump outdated 2025-05-22 18:22:36 +02:00
Ole André Vadla Ravnås 9c7759cb53 tests: Adjust profile-compiler.sh to new layout 2025-05-22 18:20:21 +02:00
Ole André Vadla Ravnås 11b3e1415f Upgrade to frida-compile 18
Now with TypeScript 5.8.3, latest frida-fs, etc.
2025-05-22 18:17:44 +02:00
Ole André Vadla Ravnås 420370257e subprojects: Prepare for release 2025-05-20 23:12:10 +02:00
Ole André Vadla Ravnås 36948a3f22 subprojects: Bump outdated 2025-05-20 23:10:16 +02:00
Ole André Vadla Ravnås 9fd3a7e104 compiler: Bump @frida/rollup-plugin-node-polyfills
Which was depending on the old frida-fs.
2025-05-20 23:08:11 +02:00
75 changed files with 7919 additions and 5384 deletions

No files matched your search

+190 -15
View File
@@ -16,13 +16,13 @@ jobs:
strategy:
matrix:
include:
- { id: windows-x86_64, runner: '"windows-latest"' }
- { id: windows-x86, runner: '"windows-latest"' }
- { id: macos-x86_64, runner: '"macos-latest"' }
- { id: macos-arm64, runner: '"macos-latest"' }
- { id: linux-x86_64, runner: '"ubuntu-latest"' }
- { id: linux-x86, runner: '"ubuntu-latest"' }
- { id: freebsd-arm64, runner: '["self-hosted", "freebsd", "arm64"]' }
- { id: windows-arm64, runner: '"windows-11-arm"', sys: CLANGARM64, pkg: 'mingw-w64-clang-aarch64-clang' }
- { id: windows-x86_64, runner: '"windows-latest"', sys: MINGW64, pkg: 'mingw-w64-x86_64-gcc' }
- { id: windows-x86, runner: '"windows-latest"', sys: MINGW32, pkg: 'mingw-w64-i686-gcc' }
- { id: macos-x86_64, runner: '"macos-latest"' }
- { id: macos-arm64, runner: '"macos-latest"' }
- { id: linux-x86_64, runner: '"ubuntu-latest"' }
- { id: linux-x86, runner: '"ubuntu-latest"' }
fail-fast: false
runs-on: ${{ fromJSON(matrix.runner) }}
steps:
@@ -30,6 +30,18 @@ jobs:
uses: actions/checkout@v4
with:
submodules: recursive
- name: Install MinGW toolchain for cgo support
if: ${{ startsWith(matrix.id, 'windows-') }}
id: msys2
uses: msys2/setup-msys2@v2
with:
msystem: ${{ matrix.sys }}
install: ${{ matrix.pkg }}
- name: Install Go toolchain
uses: actions/setup-go@v5
with:
go-version-file: 'src/compiler/go.mod'
cache-dependency-path: 'src/compiler/go.mod'
- name: Set up Apple certificates
if: ${{ startsWith(matrix.id, 'macos-') }}
uses: ./.github/actions/setup-apple-certificates
@@ -48,18 +60,29 @@ jobs:
- name: Build
if: ${{ startsWith(matrix.id, 'windows-') }}
run: |
.\configure ${{ env.FRIDA_CORE_OPTIONS }}
.\configure `
--host=${{ matrix.id }} `
--enable-compiler-backend `
${{ env.FRIDA_CORE_OPTIONS }}
.\make
env:
MSYS2_LOCATION: ${{ steps.msys2.outputs.msys2-location }}
- name: Build
if: ${{ !startsWith(matrix.id, 'windows-') && matrix.id != 'linux-x86' }}
run: |
./configure ${{ env.FRIDA_CORE_OPTIONS }}
./configure \
--enable-compiler-backend \
${{ env.FRIDA_CORE_OPTIONS }}
make
- name: Build
if: matrix.id == 'linux-x86'
run: |
CC="gcc -m32" CXX="g++ -m32" STRIP="strip" \
./configure --build=linux-x86 --host=linux-x86 ${{ env.FRIDA_CORE_OPTIONS }}
./configure \
--build=linux-x86 \
--host=linux-x86 \
--enable-compiler-backend \
${{ env.FRIDA_CORE_OPTIONS }}
make
- name: Upload devkit
if: ${{ !startsWith(matrix.id, 'linux-') }}
@@ -68,6 +91,7 @@ jobs:
name: core-devkit-${{ matrix.id }}
path: build/src/devkit/
- name: Test
if: ${{ matrix.id != 'windows-arm64' && !startsWith(matrix.id, 'macos-') }}
run: make test
cross:
@@ -91,9 +115,17 @@ jobs:
run: |
sudo apt-get update
sudo apt-get install ${{ matrix.pkg }}
- name: Install Go toolchain
uses: actions/setup-go@v5
with:
go-version-file: 'src/compiler/go.mod'
cache-dependency-path: 'src/compiler/go.mod'
- name: Build
run: |
./configure ${{ matrix.opts }} ${{ env.FRIDA_CORE_OPTIONS }}
./configure \
${{ matrix.opts }} \
${{ !contains(matrix.id, 'mips') && '--enable-compiler-backend' || '' }} \
${{ env.FRIDA_CORE_OPTIONS }}
make
- name: Upload devkit
if: ${{ !startsWith(matrix.id, 'linux-') }}
@@ -114,9 +146,17 @@ jobs:
uses: actions/checkout@v4
with:
submodules: recursive
- name: Install Go toolchain
uses: actions/setup-go@v5
with:
go-version-file: 'src/compiler/go.mod'
cache-dependency-path: 'src/compiler/go.mod'
- name: Build
run: |
./configure --host=$XTOOLS_HOST ${{ env.FRIDA_CORE_OPTIONS }}
./configure \
--host=$XTOOLS_HOST \
${{ !startsWith(matrix.arch, 'mips') && '--enable-compiler-backend' || '' }} \
${{ env.FRIDA_CORE_OPTIONS }}
make
- name: Upload devkit
uses: actions/upload-artifact@v4
@@ -127,6 +167,131 @@ jobs:
if: matrix.arch == 'x86' || matrix.arch == 'x86_64'
run: make test
emulator:
strategy:
matrix:
arch: [armbe8, arm64be]
fail-fast: false
runs-on: ubuntu-latest
container: ghcr.io/frida/x-tools-linux-${{ matrix.arch }}:latest
steps:
- name: Check out repo
uses: actions/checkout@v4
with:
submodules: recursive
- name: Build
run: |
./configure --host=$XTOOLS_HOST --without-prebuilds=sdk:host --enable-tests
make
- name: Run custom container
uses: addnab/docker-run-action@v3
with:
image: docker:stable
options: -v ${{ github.workspace }}:/workspace:delegated
run: |
cat <<EOF > /workspace/initscript
#!/bin/sh
dmesg -n1
mount -t proc none /proc
mount -t sysfs none /sys
mount -t tmpfs none /tmp
mount -t devtmpfs none /dev
mount -t 9p -o rw,sync,dirsync,relatime,trans=virtio,msize=131072,version=9p2000.L host0 /workspace
ip link set lo up
ip addr add 192.168.76.20/24 dev eth0
ip link set eth0 up
ip route add default via 192.168.76.2 dev eth0
export LD_LIBRARY_PATH=/lib:/lib64:/libilp32
/sbin/entropy
cat /etc/motd
export PS1='\u@frida:\w\$ '
/root/frida-tests
status=\$?
echo "exit status: \$status"
if [ \$status -eq 0 ]; then
echo EXIT_OK
elif [ \$status -gt 128 ]; then
signal=\$((\$status - 128))
echo "EXIT_FAIL (terminated by signal \$signal)"
else
echo "EXIT_FAIL (exit code \$status)"
fi
EOF
cat <<EOF > /workspace/launch.sh
#!/bin/sh
LOGFILE=/workspace/qemu.log
: > "\$LOGFILE"
timeout 120 qemu-system-aarch64 \
-M virt \
-machine virtualization=true \
-machine type=virt \
-cpu cortex-a72 \
-smp 4 \
-kernel /root/Image.gz \
-initrd /root/initramfs.img \
-append 'earlyprintk=serial,ttyAMA0 console=ttyAMA0 coredump_filter=0x3f' \
-m 4096M \
-net nic,id=eth \
-net user,id=mynet,net=192.168.76.0/24 \
-virtfs local,path=/workspace/,mount_tag=host0,security_model=passthrough,id=host0 \
-nographic \
-no-reboot \
>> "\$LOGFILE" 2>&1 &
QEMU_PID=\$!
echo "QEMU started with PID \$QEMU_PID"
tail -n 0 -f "\$LOGFILE" | while read line; do
echo "\$line"
echo "\$line" | grep "EXIT_OK" >/dev/null 2>&1
if [ \$? -eq 0 ]; then
echo "Success signal received from guest. Killing QEMU..."
kill -9 "\$QEMU_PID"
cat -n "\$LOGFILE"
exit 0
fi
echo "\$line" | grep "EXIT_FAIL" >/dev/null 2>&1
if [ \$? -eq 0 ]; then
echo "Failure signal received from guest. Killing QEMU..."
kill -9 "\$QEMU_PID"
cat -n "\$LOGFILE"
exit 1
fi
if ! kill -0 "\$QEMU_PID" 2>/dev/null; then
echo "QEMU process has exited."
cat -n "\$LOGFILE"
exit 1
fi
done
EOF
cat <<EOF > /workspace/Dockerfile.ci
FROM ghcr.io/frida/x-tools-linux-be-target:latest
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update && \
apt-get install -y \
cpio
RUN mkdir /tmp/initramfs
WORKDIR /tmp/initramfs
RUN cpio --extract < /root/initramfs.img
RUN mkdir /tmp/initramfs/workspace
COPY initscript /tmp/initramfs/init
RUN chmod +x /tmp/initramfs/init
COPY build/tests /tmp/initramfs/root/
RUN find . | cpio -o --format=newc -R root:root > /root/initramfs.img
COPY launch.sh /root/launch.sh
RUN chmod +x /root/launch.sh
ENTRYPOINT ["/root/launch.sh"]
EOF
docker build -t ci-image -f /workspace/Dockerfile.ci /workspace
docker run --rm -v /workspace:/workspace ci-image
mobile:
strategy:
matrix:
@@ -143,6 +308,11 @@ jobs:
uses: actions/checkout@v4
with:
submodules: recursive
- name: Install Go toolchain
uses: actions/setup-go@v5
with:
go-version-file: 'src/compiler/go.mod'
cache-dependency-path: 'src/compiler/go.mod'
- name: Set up Apple certificates
if: startsWith(matrix.id, 'ios-')
uses: ./.github/actions/setup-apple-certificates
@@ -160,7 +330,10 @@ jobs:
run: echo ANDROID_NDK_ROOT=${{ steps.setup-ndk.outputs.ndk-path }} >> $GITHUB_ENV
- name: Build
run: |
./configure --host=${{ matrix.id }} ${{ env.FRIDA_CORE_OPTIONS }}
./configure \
--host=${{ matrix.id }} \
--enable-compiler-backend \
${{ env.FRIDA_CORE_OPTIONS }}
make
- name: Upload devkit
uses: actions/upload-artifact@v4
@@ -250,6 +423,7 @@ jobs:
strategy:
matrix:
arch: [x86, x86_64, arm, armbe8, arm64, arm64be, arm64beilp32, mips, mipsel, mips64, mips64el]
fail-fast: false
runs-on: ubuntu-latest
container: ghcr.io/frida/core-linux-helpers-${{ matrix.arch }}:latest
steps:
@@ -263,7 +437,7 @@ jobs:
- name: Check for unexpected changes
run: |
git config --global --add safe.directory "$(realpath .)"
status_output="$(git status --porcelain)"
status_output=$(git status --porcelain tests/labrats/{resident-agent,simple-agent}-linux-${{ matrix.arch }}.so tests/labrats/{forker,sleeper,spawner}-linux-${{ matrix.arch }})
if [ -n "$status_output" ]; then
echo "Unexpected changes detected:"
echo "$status_output"
@@ -282,6 +456,7 @@ jobs:
strategy:
matrix:
arch: [x86, x86_64, arm, armbe8, arm64, arm64be, arm64beilp32, mips, mipsel, mips64, mips64el]
fail-fast: false
runs-on: ubuntu-latest
container: ghcr.io/frida/core-linux-helpers-${{ matrix.arch }}:latest
steps:
@@ -295,7 +470,7 @@ jobs:
- name: Check for unexpected changes
run: |
git config --global --add safe.directory "$(realpath .)"
status_output="$(git status --porcelain)"
status_output=$(git status --porcelain src/linux/helpers/{bootstrapper,loader}-${{ matrix.arch }}.bin)
if [ -n "$status_output" ]; then
echo "Unexpected changes detected:"
echo "$status_output"
+3
View File
@@ -435,6 +435,7 @@ def compile(privdir: Path, state: State):
environ={**build_env, **group.extra_environ},
allowed_prebuilds=state.allowed_prebuilds,
extra_meson_options=[
"-Dcompiler_backend=disabled",
"-Dhelper_modern=",
"-Dhelper_legacy=",
"-Dagent_modern=",
@@ -499,6 +500,8 @@ def option_should_be_forwarded(k: "OptionKey",
if k.is_project():
if is_for_us:
if k.name == "compiler_backend":
return False
tokens = k.name.split("_")
if tokens[0] in {"helper", "agent"} and tokens[-1] in {"modern", "legacy"}:
return False
+14 -1
View File
@@ -446,7 +446,14 @@ namespace Frida {
public string read_fixed_string (size_t offset, size_t size) throws Error {
string * start = (string *) get_pointer (offset, size);
string val = start->substring (0, (long) size);
size_t max_length = size - offset;
string * end = memchr (start, 0, max_length);
size_t n;
if (end != null)
n = end - start;
else
n = size;
string val = start->substring (0, (long) n);
if (!val.validate ())
throw new Error.PROTOCOL ("Invalid UTF-8 string");
return val;
@@ -579,6 +586,12 @@ namespace Frida {
return val;
}
public unowned BufferReader skip (size_t n) throws Error {
check_available (n);
offset += n;
return this;
}
private void check_available (size_t n) throws Error {
if (available < n)
throw new Error.PROTOCOL ("Malformed buffer: truncated");
+114
View File
@@ -0,0 +1,114 @@
namespace Frida.FS {
public void mkdirp (File dir, Cancellable? cancellable = null) throws Error {
try {
dir.make_directory_with_parents (cancellable);
} catch (GLib.Error e) {
if (!(e is IOError.EXISTS))
throw new Error.PERMISSION_DENIED ("%s", e.message);
}
}
public void rmtree (File dir, Cancellable? cancellable = null) throws Error {
rmtree_worker (dir, 0, cancellable);
}
private void rmtree_worker (File dir, uint depth, Cancellable? cancellable = null) throws Error {
FileEnumerator enumerator;
try {
enumerator = dir.enumerate_children (FileAttribute.STANDARD_NAME, NOFOLLOW_SYMLINKS, cancellable);
} catch (GLib.Error e) {
if (depth == 0 && e is IOError.NOT_FOUND)
return;
throw new Error.PERMISSION_DENIED ("%s", e.message);
}
try {
FileInfo? info;
File? child;
while (enumerator.iterate (out info, out child, cancellable) && info != null) {
if (info == null)
continue;
if (info.get_file_type () == DIRECTORY)
rmtree (child, cancellable);
else
child.delete (cancellable);
}
dir.delete (cancellable);
} catch (GLib.Error e) {
if (!(e is IOError.EXISTS))
throw new Error.PERMISSION_DENIED ("%s", e.message);
}
}
public async void rmtree_async (File dir, Cancellable? cancellable = null) throws Error, IOError {
yield rmtree_async_worker (dir, 0, cancellable);
}
private async void rmtree_async_worker (File dir, uint depth, Cancellable? cancellable = null) throws Error, IOError {
int io_priority = Priority.DEFAULT;
FileEnumerator enumerator;
try {
enumerator = yield dir.enumerate_children_async (FileAttribute.STANDARD_NAME, NOFOLLOW_SYMLINKS, io_priority,
cancellable);
} catch (GLib.Error e) {
if (depth == 0 && e is IOError.NOT_FOUND)
return;
throw new Error.PERMISSION_DENIED ("%s", e.message);
}
try {
while (true) {
var batch = yield enumerator.next_files_async (1000, io_priority, cancellable);
if (batch.is_empty ())
break;
foreach (FileInfo info in batch) {
File child = dir.get_child (info.get_name ());
if (info.get_file_type () == DIRECTORY)
yield rmtree_async_worker (child, depth + 1, cancellable);
else
yield child.delete_async (io_priority, cancellable);
}
}
yield dir.delete_async (io_priority, cancellable);
} catch (GLib.Error e) {
throw new Error.PERMISSION_DENIED ("%s", e.message);
}
}
public async string read_all_text (File f, Cancellable? cancellable) throws Error, IOError {
Bytes b = yield read_all_bytes (f, cancellable);
string text = (string) b.get_data ();
if (!text.validate ())
throw new Error.PROTOCOL ("Unable to read '%s': invalid UTF-8", f.get_parse_name ());
return text;
}
public async void write_all_text (File f, string t, Cancellable? cancellable) throws Error, IOError {
yield write_all_bytes (f, new Bytes (t.data), cancellable);
}
public async Bytes read_all_bytes (File f, Cancellable? cancellable) throws Error, IOError {
try {
return yield f.load_bytes_async (cancellable, null);
} catch (GLib.Error e) {
if (e is IOError.CANCELLED)
throw (IOError) e;
if (e is IOError.NOT_FOUND)
throw new Error.INVALID_ARGUMENT ("%s", e.message);
throw new Error.PERMISSION_DENIED ("%s", e.message);
}
}
public async void write_all_bytes (File f, Bytes b, Cancellable? cancellable) throws Error, IOError {
try {
yield f.replace_contents_bytes_async (b, null, false, FileCreateFlags.NONE, cancellable, null);
} catch (GLib.Error e) {
if (e is IOError.CANCELLED)
throw (IOError) e;
throw new Error.PERMISSION_DENIED ("%s", e.message);
}
}
}
@@ -1,5 +1,5 @@
#ifndef __FRIDA_SYSCALL_H__
#define __FRIDA_SYSCALL_H__
#ifndef __FRIDA_LINUX_SYSCALL_H__
#define __FRIDA_LINUX_SYSCALL_H__
#include <linux/unistd.h>
#include <sys/syscall.h>
@@ -14,7 +14,7 @@ namespace Frida {
[CCode (cheader_filename = "sys/mman.h", cname = "MAP_ANONYMOUS")]
public const int MAP_ANONYMOUS;
[CCode (cheader_filename = "linux/frida-syscall.h", cprefix = "SYS_", has_type_id = false)]
[CCode (cheader_filename = "linux-syscall.h", cprefix = "SYS_", has_type_id = false)]
public enum SysCall {
memfd_create,
pidfd_getfd,
+107
View File
@@ -0,0 +1,107 @@
namespace Frida {
private uint linux_major = 0;
private uint linux_minor = 0;
public bool check_kernel_version (uint major, uint minor) {
if (linux_major == 0) {
var name = Posix.utsname ();
name.release.scanf ("%u.%u", out linux_major, out linux_minor);
}
return (linux_major == major && linux_minor >= minor) || linux_major > major;
}
public class FileDescriptor : Object, FileDescriptorBased {
public int handle;
public FileDescriptor (int handle) {
this.handle = handle;
}
~FileDescriptor () {
if (handle != -1)
Posix.close (handle);
}
public int steal () {
int result = handle;
handle = -1;
return result;
}
public int get_fd () {
return handle;
}
}
public sealed class PidFileDescriptor : FileDescriptor {
private uint pid;
private PidFileDescriptor (int fd, uint pid) {
base (fd);
this.pid = pid;
}
public static bool is_supported () {
return check_kernel_version (5, 3);
}
public static bool getfd_is_supported () {
return check_kernel_version (5, 6);
}
public static PidFileDescriptor from_pid (uint pid) throws Error {
int fd = pidfd_open (pid, 0);
if (fd == -1)
throw_pidfd_error (pid, errno);
return new PidFileDescriptor (fd, pid);
}
public FileDescriptor getfd (int targetfd) throws Error {
int fd = pidfd_getfd (handle, targetfd, 0);
if (fd == -1)
throw_pidfd_error (pid, errno);
return new FileDescriptor (fd);
}
private static int pidfd_open (uint pid, uint flags) {
return Linux.syscall (SysCall.pidfd_open, pid, flags);
}
private static int pidfd_getfd (int pidfd, int targetfd, uint flags) {
return Linux.syscall (SysCall.pidfd_getfd, pidfd, targetfd, flags);
}
[NoReturn]
private static void throw_pidfd_error (uint pid, int err) throws Error {
switch (err) {
case Posix.ESRCH:
throw new Error.PROCESS_NOT_FOUND ("Process not found");
case Posix.EPERM:
throw new Error.PERMISSION_DENIED ("Unable to use pidfd for pid %u: %s", pid, strerror (err));
default:
throw new Error.NOT_SUPPORTED ("Unable to use pidfd for pid %u: %s", pid, strerror (err));
}
}
}
namespace MemoryFileDescriptor {
public bool is_supported () {
return check_kernel_version (3, 17);
}
public static FileDescriptor from_bytes (string name, Bytes bytes) {
assert (is_supported ());
var fd = new FileDescriptor (memfd_create (name, 0));
unowned uint8[] data = bytes.get_data ();
ssize_t n = Posix.write (fd.handle, data, data.length);
assert (n == data.length);
return fd;
}
private int memfd_create (string name, uint flags) {
return Linux.syscall (SysCall.memfd_create, name, flags);
}
}
}
+17 -1
View File
@@ -9,6 +9,7 @@ base_sources = [
'p2p-glue.c',
'dbus.vala',
'promise.vala',
'fs.vala',
'socket.vala',
'socket-glue.c',
'buffer.vala',
@@ -28,6 +29,15 @@ if host_os_family == 'darwin'
base_sources += 'corefoundation.vala'
endif
if host_os_family == 'linux'
base_sources += 'linux.vala'
extra_vala_args += [
'--pkg=linux',
'--pkg=linux-system',
'--pkg=posix',
]
endif
extra_deps = []
if host_os_family != 'windows'
extra_vala_args += '--pkg=gio-unix-2.0'
@@ -45,6 +55,12 @@ if host_os_family == 'darwin'
'--pkg=darwin-xpc',
]
endif
if host_os_family == 'linux'
base_vala_args += [
'--vapidir=' + meson.current_source_dir(),
'--pkg=gio-unix-2.0',
]
endif
base_gir_name = f'FridaBase-@[email protected]'
@@ -62,7 +78,7 @@ base = static_library('frida-base-' + api_version, base_sources,
base_dep = declare_dependency(
include_directories: include_directories('.'),
link_with: base,
dependencies: [nice_dep, json_glib_dep, gum_dep],
dependencies: [nice_dep, json_glib_dep, gum_dep] + extra_deps,
)
base_build_dir = meson.current_build_dir()
+52 -12
View File
@@ -46,7 +46,8 @@ namespace Frida {
}
private GLib.Error? _error;
private Gee.ArrayQueue<CompletionFuncEntry> on_complete;
private Gee.ArrayQueue<CompletionFuncEntry>? on_complete;
private Gee.ArrayQueue<ThenHandlerEntry<T>>? on_then;
public async T wait_async (Cancellable? cancellable) throws Frida.Error, IOError {
if (_ready)
@@ -74,7 +75,21 @@ namespace Frida {
return get_result ();
}
private T get_result () throws Frida.Error, IOError {
public void then (owned FutureCompletionHandler<T> handler) {
if (_ready) {
schedule (() => {
handler (this);
return Source.REMOVE;
});
return;
}
if (on_then == null)
on_then = new Gee.ArrayQueue<ThenHandlerEntry<T>> ();
on_then.offer (new ThenHandlerEntry<T> ((owned) handler));
}
public T get_result () throws Frida.Error, IOError {
if (error != null) {
if (error is Frida.Error)
throw (Frida.Error) error;
@@ -111,19 +126,32 @@ namespace Frida {
internal void transition_to_ready () {
_ready = true;
if (on_complete != null && !on_complete.is_empty) {
var source = new IdleSource ();
source.set_priority (Priority.HIGH);
source.set_callback (() => {
CompletionFuncEntry? entry;
while ((entry = on_complete.poll ()) != null)
entry.func ();
on_complete = null;
return false;
if (on_complete != null || on_then != null) {
schedule (() => {
if (on_complete != null) {
CompletionFuncEntry? entry;
while ((entry = on_complete.poll ()) != null)
entry.func ();
on_complete = null;
}
if (on_then != null) {
ThenHandlerEntry? entry;
while ((entry = on_then.poll ()) != null)
entry.handler (this);
on_then = null;
}
return Source.REMOVE;
});
source.attach (MainContext.get_thread_default ());
}
}
private static void schedule (owned SourceFunc function) {
var source = new IdleSource ();
source.set_callback ((owned) function);
source.attach (MainContext.get_thread_default ());
}
}
private class CompletionFuncEntry {
@@ -133,6 +161,14 @@ namespace Frida {
this.func = (owned) func;
}
}
private class ThenHandlerEntry<T> {
public FutureCompletionHandler<T> handler;
public ThenHandlerEntry (owned FutureCompletionHandler<T> handler) {
this.handler = (owned) handler;
}
}
}
public interface Future<T> : Object {
@@ -140,5 +176,9 @@ namespace Frida {
public abstract T? value { get; }
public abstract GLib.Error? error { get; }
public abstract async T wait_async (Cancellable? cancellable) throws Frida.Error, IOError;
public abstract void then (owned FutureCompletionHandler<T> handler);
public abstract T get_result () throws Frida.Error, IOError;
}
public delegate void FutureCompletionHandler<T> (Future<T> future);
}
+7 -1
View File
@@ -1242,7 +1242,13 @@ namespace Frida.Gadget {
}
private sealed class Script : Object, RpcPeer {
private const uint8 QUICKJS_BYTECODE_MAGIC = 0x02;
private const uint8 QUICKJS_BYTECODE_MAGIC =
#if BIG_ENDIAN
0x42
#else
0x02
#endif
;
public enum ChangeBehavior {
IGNORE,
+7 -7
View File
@@ -55,6 +55,7 @@ struct _FridaUnwindHookState
gpointer set_info_original;
void (* set_info) (gpointer cursor, gint is_return_address);
gpointer (* get_reg) (gpointer cursor, gint reg);
GumInterceptor * interceptor;
};
#if __has_feature (ptrauth_calls)
@@ -97,7 +98,6 @@ _frida_unwind_sitter_hook_libunwind (void)
#if GLIB_SIZEOF_VOID_P == 8
gpointer * set_info_slot;
gpointer get_reg_impl;
GumInterceptor * interceptor;
if (state != NULL)
return;
@@ -121,8 +121,9 @@ _frida_unwind_sitter_hook_libunwind (void)
state->set_info = FRIDA_RESIGN_PTR (state->set_info_original);
state->get_reg = FRIDA_RESIGN_PTR (get_reg_impl);
interceptor = gum_interceptor_obtain ();
if (gum_interceptor_replace (interceptor, state->set_info_original, frida_unwind_cursor_set_info_replacement, NULL, NULL)
state->interceptor = gum_interceptor_obtain ();
if (gum_interceptor_replace (state->interceptor, state->set_info_original, frida_unwind_cursor_set_info_replacement, NULL, NULL)
!= GUM_REPLACE_OK)
goto unsupported_version;
@@ -137,13 +138,12 @@ unsupported_version:
void
_frida_unwind_sitter_unhook_libunwind (void)
{
GumInterceptor * interceptor;
if (state == NULL)
return;
interceptor = gum_interceptor_obtain ();
gum_interceptor_revert (interceptor, state->set_info_original);
gum_interceptor_revert (state->interceptor, state->set_info_original);
g_object_unref (state->interceptor);
g_slice_free (FridaUnwindHookState, state);
state = NULL;
+94 -62
View File
@@ -6,6 +6,8 @@ project('frida-core', 'vala', 'c', 'cpp',
default_options: ['c_std=gnu99,c99', 'cpp_std=c++17'],
)
fs = import('fs')
if not meson.get_compiler('vala').version().endswith('-frida')
error('''Incompatible Vala compiler detected.
@@ -20,7 +22,7 @@ cc = meson.get_compiler('c')
cpp = meson.get_compiler('cpp')
releng = meson.global_source_root() / 'releng'
if not import('fs').exists(releng)
if not fs.exists(releng)
releng = meson.project_source_root() / 'releng'
endif
@@ -98,11 +100,6 @@ else
host_cpu_mode = '32'
endif
host_docks_mobile_devices = host_os in ['windows', 'macos', 'linux'] and host_cpu_mode == '64'
gumjs_archs = {
'x86': 'ia32',
'x86_64': 'x64',
}
host_arch_gumjs = gumjs_archs.get(host_arch, host_arch)
if host_os_family == 'darwin'
c_languages += ['objc', 'objcpp']
@@ -362,6 +359,44 @@ if host_os == 'android'
])
endif
if host_toolchain == 'microsoft'
lib = find_program('lib')
ar = ''
nm = ''
ranlib = ''
strip = ''
else
lib = ''
ar = find_program('ar')
nm = find_program('nm')
ranlib = find_program('ranlib')
strip = find_program('strip')
endif
if host_os_family != 'windows'
if host_os_family == 'darwin'
readelf = ''
otool = find_program('otool')
libtool = find_program('libtool')
else
readelf = find_program('readelf')
otool = ''
libtool = ''
endif
else
readelf = ''
otool = ''
libtool = ''
endif
if host_os_family == 'darwin'
install_name_tool = find_program('install_name_tool')
lipo = find_program('lipo')
codesign = find_program('codesign')
else
install_name_tool = ''
lipo = ''
codesign = ''
endif
have_local_backend = get_option('local_backend').allowed()
have_fruity_backend = get_option('fruity_backend') \
.disable_auto_if(not host_docks_mobile_devices) \
@@ -374,15 +409,54 @@ have_barebone_backend = get_option('barebone_backend') \
.disable_if(not quickjs_dep.found()) \
.disable_auto_if(not host_docks_mobile_devices) \
.allowed()
have_compiler_backend = get_option('compiler_backend') \
.disable_if(not have_local_backend, error_message: 'compiler backend requires the local backend for script execution') \
.disable_auto_if(host_os == 'watchos') \
.allowed()
if get_option('compiler_snapshot').auto()
# Generating our snapshot with V8's CPU simulator takes a very long time.
generate_compiler_snapshot = meson.can_run_host_binaries()
else
generate_compiler_snapshot = get_option('compiler_snapshot').enabled()
compiler_backend_opt = get_option('compiler_backend') \
.disable_auto_if(host_os == 'watchos')
have_compiler_backend = false
if compiler_backend_opt.allowed()
go = find_program('go', native: true, required: false)
if go.found()
message('Detecting cgo availability')
detect_output = run_command(
[
python,
files('tools' / 'cgo' / 'detect.py'),
go,
host_os,
host_abi,
shlib_suffix,
cc.get_id(),
'>>>', cc.cmd_array(), '<<<',
'>>>', ar, '<<<',
'>>>', nm, '<<<',
'>>>', ranlib, '<<<',
],
capture: true,
check: true
).stdout()
lines = detect_output.split('\n')
status = lines[0]
if status == 'ok'
have_compiler_backend = true
tokens = lines[1].split(' ')
go_mode = tokens[0]
go_config = tokens[1]
compiler_backend_static_compilation = go_mode == 'c-archive'
if compiler_backend_static_compilation
vala_flags += '--define=COMPILER_BACKEND_STATIC_COMPILATION'
endif
else
error_message = lines[1]
if compiler_backend_opt.enabled()
error(error_message)
else
warning(f'Building without Compiler backend: @error_message@')
endif
endif
elif compiler_backend_opt.enabled()
error('Need Go >= 1.24 to build the Compiler backend powered by ESBuild and typescript-go')
else
warning('Building without Compiler backend: Go >= 1.24 not found')
endif
endif
build_gadget = get_option('gadget') \
@@ -452,12 +526,6 @@ gumjs_inspector_vala_args = ['--pkg=frida-gumjs-inspector-1.0', gum_vala_args]
have_v8 = gumjs_dep.get_variable('gumjs_v8') == 'enabled'
if have_v8
vala_flags += ['--define=HAVE_V8']
v8_mksnapshot = find_program('v8-mksnapshot-@0@-@1@'.format(host_os, host_abi), required: false)
if not v8_mksnapshot.found()
v8_mksnapshot = ''
endif
else
v8_mksnapshot = ''
endif
backend_deps_private = []
@@ -579,42 +647,6 @@ if host_os in ['ios', 'tvos']
backend_libs_private += ['-Wl,-framework,CoreGraphics', '-Wl,-framework,UIKit']
endif
if host_toolchain == 'microsoft'
lib = find_program('lib')
ar = ''
nm = ''
strip = ''
else
lib = ''
ar = find_program('ar')
nm = find_program('nm')
strip = find_program('strip')
endif
if host_os_family != 'windows'
if host_os_family == 'darwin'
readelf = ''
otool = find_program('otool')
libtool = find_program('libtool')
else
readelf = find_program('readelf')
otool = ''
libtool = ''
endif
else
readelf = ''
otool = ''
libtool = ''
endif
if host_os_family == 'darwin'
install_name_tool = find_program('install_name_tool')
lipo = find_program('lipo')
codesign = find_program('codesign')
else
install_name_tool = ''
lipo = ''
codesign = ''
endif
if get_option('devkits').length() != 0
if get_option('default_library') != 'static'
error('Devkits can only be generated from static libraries')
@@ -708,14 +740,15 @@ vala_flags += [
'--pkg', 'config',
]
vala_flags += ['--define=' + host_os_family.to_upper()]
vala_flags += '--define=' + host_os_family.to_upper()
if host_os != host_os_family
vala_flags += ['--define=' + host_os.to_upper()]
vala_flags += '--define=' + host_os.to_upper()
endif
vala_flags += ['--define=' + host_arch.to_upper()]
vala_flags += '--define=' + host_arch.to_upper()
if host_abi != host_arch
vala_flags += ['--define=' + host_abi.to_upper()]
vala_flags += '--define=' + host_abi.to_upper()
endif
vala_flags += '--define=' + host_machine.endian().to_upper() + '_ENDIAN'
add_project_arguments(vala_flags, language: 'vala')
add_project_arguments('-I' + vapidir, language: 'c')
@@ -760,7 +793,6 @@ summary(
'assets': get_option('assets'),
'mapper': have_mapper,
'connectivity': tls_provider_dep.found(),
'compiler_snapshot': generate_compiler_snapshot,
'gadget': build_gadget,
'server': build_server,
'portal': build_portal,
+1 -7
View File
@@ -37,13 +37,7 @@ option('barebone_backend',
option('compiler_backend',
type: 'feature',
value: 'auto',
description: 'Include frida-compile backend powered by GumJS',
)
option('compiler_snapshot',
type: 'feature',
value: 'auto',
description: 'Speed up compiler startup by using a snapshot'
description: 'Include frida-compile backend powered by ESBuild and typescript-go',
)
option('assets',
+1 -1
Submodule releng updated: 5d9edf166c...e10baa39a2.
+40 -5
View File
@@ -26,6 +26,11 @@ OBJECT_TYPE_PATTERN = re.compile(r"\bpublic\s+(sealed )?(class|interface)\s+(\w+
def main():
parser = argparse.ArgumentParser(description="Generate refined Frida API definitions")
parser.add_argument('--output', dest='output_type', choices=['bundle', 'header', 'gir', 'vapi', 'vapi-stamp'], default='bundle')
parser.add_argument('frida_version', metavar='frida-version', type=str)
parser.add_argument('frida_major_version', metavar='frida-major-version', type=str)
parser.add_argument('frida_minor_version', metavar='frida-minor-version', type=str)
parser.add_argument('frida_micro_version', metavar='frida-micro-version', type=str)
parser.add_argument('frida_nano_version', metavar='frida-nano-version', type=str)
parser.add_argument('api_version', metavar='api-version', type=str)
parser.add_argument('core_header', metavar='/path/to/frida-core.h', type=argparse.FileType('r', encoding='utf-8'))
parser.add_argument('core_gir', metavar='/path/to/Frida-x.y.gir', type=argparse.FileType('r', encoding='utf-8'))
@@ -38,6 +43,13 @@ def main():
args = parser.parse_args()
output_type = args.output_type
frida_version = args.frida_version
frida_version_components = (
args.frida_major_version,
args.frida_minor_version,
args.frida_micro_version,
args.frida_nano_version,
)
api_version = args.api_version
core_header = args.core_header.read()
core_gir = args.core_gir.read()
@@ -53,6 +65,7 @@ def main():
toplevel_names = [
"frida.vala",
"package-manager.vala",
"control-service.vala",
"portal-service.vala",
"file-monitor.vala",
@@ -78,7 +91,7 @@ def main():
elif output_type == 'vapi':
enable_vapi = True
api = parse_api(api_version, toplevel_code, core_header, core_vapi, base_header, base_vapi)
api = parse_api(frida_version, frida_version_components, api_version, toplevel_code, core_header, core_vapi, base_header, base_vapi)
if enable_header:
emit_header(api, output_dir)
@@ -93,7 +106,26 @@ def emit_header(api, output_dir):
with OutputFile(output_dir / 'frida-core.h') as output_header_file:
output_header_file.write("#ifndef __FRIDA_CORE_H__\n#define __FRIDA_CORE_H__\n\n")
output_header_file.write("#include <glib.h>\n#include <glib-object.h>\n#include <gio/gio.h>\n#include <json-glib/json-glib.h>\n")
output_header_file.write("#include <glib.h>\n#include <glib-object.h>\n#include <gio/gio.h>\n#include <json-glib/json-glib.h>\n\n")
output_header_file.write(f"#define FRIDA_VERSION \"{api.frida_version}\"\n\n")
for name, value in zip(['MAJOR', 'MINOR', 'MICRO', 'NANO'], api.frida_version_components):
output_header_file.write(f"#define FRIDA_{name}_VERSION {value}\n")
output_header_file.write("""
#define FRIDA_CHECK_VERSION(maj, min, mic) \\
(FRIDA_CURRENT_VERSION >= FRIDA_VERSION_ENCODE ((maj), (min), (mic)))
#define FRIDA_CURRENT_VERSION \\
FRIDA_VERSION_ENCODE ( \\
FRIDA_MAJOR_VERSION, \\
FRIDA_MINOR_VERSION, \\
FRIDA_MICRO_VERSION)
#define FRIDA_VERSION_ENCODE(maj, min, mic) \\
(((maj) * 1000000U) + ((min) * 1000U) + (mic))
""")
output_header_file.write("\nG_BEGIN_DECLS\n")
@@ -271,7 +303,7 @@ def emit_vapi(api, output_dir):
output_deps_file.write("gobject-2.0\n")
output_deps_file.write("gio-2.0\n")
def parse_api(api_version, toplevel_code, core_header, core_vapi, base_header, base_vapi):
def parse_api(frida_version, frida_version_components, api_version, toplevel_code, core_header, core_vapi, base_header, base_vapi):
all_headers = core_header + "\n" + base_header
all_enum_names = [m.group(1) for m in re.finditer(r"^\t+public\s+enum\s+(\w+)\s+", toplevel_code + "\n" + base_vapi, re.MULTILINE)]
@@ -464,7 +496,7 @@ def parse_api(api_version, toplevel_code, core_header, core_vapi, base_header, b
m = re.search(r"^[\w\*]+ frida_{}.+?;".format(f.name), all_headers, re.MULTILINE | re.DOTALL)
f.c_prototype = beautify_cprototype(m.group(0))
return ApiSpec(api_version, object_types, functions, enum_types, error_types)
return ApiSpec(frida_version, frida_version_components, api_version, object_types, functions, enum_types, error_types)
def function_is_public(name):
return not name.startswith("_") and \
@@ -478,7 +510,8 @@ def function_is_public(name):
"parse_control_address",
"parse_cluster_address",
"parse_socket_address",
"negotiate_connection"
"negotiate_connection",
"check_kernel_version",
]
def parse_vala_object_types(source) -> List[ApiObjectType]:
@@ -489,6 +522,8 @@ def parse_vapi_functions(vapi) -> List[ApiFunction]:
@dataclass
class ApiSpec:
frida_version: str
frida_version_components: List[int]
version: str
object_types: List[ApiObjectType]
functions: List[ApiFunction]
+5
View File
@@ -3,6 +3,11 @@ fs = import('fs')
generate_api = [python, files('generate.py')]
generate_api_args = [
frida_version,
frida_major_version.to_string(),
frida_minor_version.to_string(),
frida_micro_version.to_string(),
frida_nano_version.to_string(),
api_version,
core_build_dir / 'frida-core.h',
core_build_dir / core_gir_name,
+2 -1
View File
@@ -465,7 +465,8 @@ namespace Frida {
public async void load_script (AgentScriptId script_id, Cancellable? cancellable) throws Error, IOError {
check_open ();
get_script (script_id).load ();
var script = get_script (script_id);
yield script.load (cancellable);
}
public async void eternalize_script (AgentScriptId script_id, Cancellable? cancellable) throws Error, IOError {
+443 -445
View File
@@ -9,318 +9,434 @@
"version": "1.0.0",
"devDependencies": {
"@types/frida-gum": "^19.0.0",
"frida-compile": "^17.0.0"
"esbuild": "^0.25.5",
"typescript": "^5.8.3"
}
},
"node_modules/@frida/assert": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/@frida/assert/-/assert-3.0.2.tgz",
"integrity": "sha512-JXJq5SbXGrM5EkjrZKfRmB29zOoEOix02NC6A5TSJ+C1GE/X051EinJJsuOO2pEOx7KZwpvAHvS0WXW0+levKg==",
"dev": true
},
"node_modules/@frida/base64-js": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/@frida/base64-js/-/base64-js-2.0.3.tgz",
"integrity": "sha512-2w0F+1TynOTCZ/v7du9LdHPWwq0lJhazjo2fF9upMyQmA1zHetT14fLuQ1v/6T0qPgyeEGkiSrybstU8EsgeUA==",
"dev": true,
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
]
},
"node_modules/@frida/buffer": {
"version": "7.0.4",
"resolved": "https://registry.npmjs.org/@frida/buffer/-/buffer-7.0.4.tgz",
"integrity": "sha512-RxQ1lZRRiCJj7nhcCiD8xeJx0NsLpGGnjqsmTg7jShGmbnVFMN5W7+J+3gqdPSQhc/IxNBIWc6zRXVp4+qnYHg==",
"dev": true,
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
"node_modules/@esbuild/aix-ppc64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.5.tgz",
"integrity": "sha512-9o3TMmpmftaCMepOdA5k/yDw8SfInyzWWTjYTFCX3kPSDJMROQTb8jg+h9Cnwnmm1vOzvxN7gIfB5V2ewpjtGA==",
"cpu": [
"ppc64"
],
"dependencies": {
"base64-js": "^1.5.1",
"ieee754": "^1.2.1"
}
},
"node_modules/@frida/crosspath": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/@frida/crosspath/-/crosspath-3.0.0.tgz",
"integrity": "sha512-bNdO1spIPD2P40XtK89N49oZpJhstdlnkJZcD4yJ17jrdkm9Ctu0sd9MIEX6Z8Tm8ydhVJBAOMEKl9/R27onAQ==",
"dev": true,
"dependencies": {
"@types/node": "^17.0.36"
},
"license": "MIT",
"optional": true,
"os": [
"aix"
],
"engines": {
"node": ">=14.9.0"
"node": ">=18"
}
},
"node_modules/@frida/crypto": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@frida/crypto/-/crypto-1.0.1.tgz",
"integrity": "sha512-WXTkVjESvX8TIVXIynJJv9BKSIdQP0Iis04StIXknkDi1ULdMlrypA9p5C4KW1H6GCkNsVnKbybpzsulYCTvag==",
"dev": true,
"license": "MIT"
},
"node_modules/@frida/diagnostics_channel": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@frida/diagnostics_channel/-/diagnostics_channel-1.0.0.tgz",
"integrity": "sha512-mYX1jp/5Bpk24tHArJNx65iCk7qSuV8YJkdU0gFNVtJUXxfV8BG5WuPa4mL+ynxsbWWpsg/cwKZbLAepYKTdQQ==",
"dev": true
},
"node_modules/@frida/events": {
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/@frida/events/-/events-4.0.4.tgz",
"integrity": "sha512-qJVQ6VWHf9sjUKuiJzoCAC00frbpcwxeYfvQ+PP9LU/d70j+QvjWgYe98Qa3ekLaBU6r/AvWm8ThKCDUCLWrQQ==",
"node_modules/@esbuild/android-arm": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.5.tgz",
"integrity": "sha512-AdJKSPeEHgi7/ZhuIPtcQKr5RQdo6OO2IL87JkianiMYMPbCtot9fxPbrMiBADOWWm3T2si9stAiVsGbTQFkbA==",
"cpu": [
"arm"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"android"
],
"engines": {
"node": ">=0.8.x"
"node": ">=18"
}
},
"node_modules/@frida/http": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/@frida/http/-/http-4.0.2.tgz",
"integrity": "sha512-cvkc7ex7GmVXVOWqtjXKBWUUbYEBgpNRKZbEEoMeI8KiIs8zejKwg+N7rx7296Ao+EP3+xcUr4wBVr3xLaUVfQ==",
"node_modules/@esbuild/android-arm64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.5.tgz",
"integrity": "sha512-VGzGhj4lJO+TVGV1v8ntCZWJktV7SGCs3Pn1GRWI1SBFtRALoomm8k5E9Pmwg3HOAal2VDc2F9+PM/rEY6oIDg==",
"cpu": [
"arm64"
],
"dev": true,
"dependencies": {
"http-parser-js": "^0.5.3"
}
},
"node_modules/@frida/http-parser-js": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@frida/http-parser-js/-/http-parser-js-1.0.0.tgz",
"integrity": "sha512-2nMrNXt/OeTlWbqnE8AH4Sfz4I2+BGoN206dzKEyC/g2svtn83Xu+zuv/V3TkwrA27s26Mcy84ZwsXeNlqNxUQ==",
"dev": true
},
"node_modules/@frida/https": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@frida/https/-/https-1.0.0.tgz",
"integrity": "sha512-OiqQ6qsALcWOktRLq07oJ0i6sH8eX6MXb/MdZS1qVKDRf6wchH4Pjn6fiLB+pt/OlYbggk+DOfpHwSdjTwuHMQ==",
"dev": true
},
"node_modules/@frida/ieee754": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/@frida/ieee754/-/ieee754-2.0.2.tgz",
"integrity": "sha512-wlcUebnne4ENN7GDr5pTH598ZDLMVOsh0FjenxeVOe6u7ewZkz9gGRnLnZKJAm9kl5G6XhdxhI0cSXVQK/rQUw==",
"dev": true,
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
]
},
"node_modules/@frida/net": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/@frida/net/-/net-4.0.2.tgz",
"integrity": "sha512-qQRe7hQ+ZfCcG/SE3P1TRqQ9bmuK/T7wPCYaT4z56rBPWAxsaQbQHpX4fR6OrFaSDr7X0xJLsTbdIp9hGhhLZg==",
"dev": true
},
"node_modules/@frida/os": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@frida/os/-/os-1.0.2.tgz",
"integrity": "sha512-3ISAiGNiyIya3QN2EHBCz1wqP0enTdSxP99wUeroeh8+AQRmgoOr/5TRnrVry8pe378anay3fmV/tdUMMSkehQ==",
"dev": true
},
"node_modules/@frida/path": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/@frida/path/-/path-2.0.3.tgz",
"integrity": "sha512-2RQy36QatoC846fzBhBhV8sXMsSOBGoYvwTHeaE1zUdz7F4RNScP4QEekTTooBYWYX/XjiF36KQpYAzc9OYFtg==",
"dev": true
},
"node_modules/@frida/process": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/@frida/process/-/process-1.2.1.tgz",
"integrity": "sha512-nvCu22DstFW2ttGFtOKekHM7vnjbZm+XgtvavOt427GNT6uV7k0JYK9tnMbcLMRWv57DG6udAmuJlWs8Paq1ag==",
"dev": true
},
"node_modules/@frida/punycode": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/@frida/punycode/-/punycode-3.0.0.tgz",
"integrity": "sha512-XVSDY2KamDs1D5/fTVgHcOSNxdU4kTboxzqJMBbTjcQC7XScIT9c0EfbwKCq7Kci6gWQdsHSCr7lU+9Oc4KAdg==",
"dev": true
},
"node_modules/@frida/querystring": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@frida/querystring/-/querystring-1.0.0.tgz",
"integrity": "sha512-15m1fOZPmoO/vWlgPJrG/J9/BJDz6a2/JpVGpS8ynNzo+fBhTznaStX5nHxUs24mVTqh/OqLo0EiYJM5WWHXxg==",
"dev": true
},
"node_modules/@frida/readable-stream": {
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/@frida/readable-stream/-/readable-stream-4.1.3.tgz",
"integrity": "sha512-ntGUFmi+CryRGRJIK13a/VST2Ad19uivbln8Xd92vKPAARq+6vMIASDyZIqyl5BLRccfiyCHdYgrgQ6RI5rUig==",
"dev": true
},
"node_modules/@frida/reserved-words": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@frida/reserved-words/-/reserved-words-1.0.0.tgz",
"integrity": "sha512-2yG/XxJlsGlk/mm6eZTb4OAaQEhkTI2qaFfZFtAsrA/XuCpuMWkS4y/guyBlsRu4hAuhK2HPmNM8+OLLK1zM9Q==",
"dev": true
},
"node_modules/@frida/stream": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@frida/stream/-/stream-1.0.2.tgz",
"integrity": "sha512-4OuaC1ztmEKgTq3WeBhsy8Oq+AwW9n9cYnvLklcC9jwD93AEwgbWpecLlxJCVuALvTMdhKPg0nQVfyGYP/i9Bw==",
"dev": true,
"dependencies": {
"@frida/readable-stream": "^4.1.3"
}
},
"node_modules/@frida/string_decoder": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@frida/string_decoder/-/string_decoder-2.0.0.tgz",
"integrity": "sha512-in371tYZMHQiW9HF5MS3JDw6Ao6tyBoq34UWy2rzOswYyMG1rpizh85ofi/yVkxDiaqybEZefxzkVittpPGT6g==",
"dev": true
},
"node_modules/@frida/terser": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@frida/terser/-/terser-1.0.0.tgz",
"integrity": "sha512-59h9WuNzD1Rx/zwoWqQ/FW/4Y/Q3R91Eng2hEwdHapqiTDvtKbZ08F6CynCR7ZVinrh4tLYsF46AtVPTz1ys9g==",
"dev": true,
"dependencies": {
"@jridgewell/source-map": "^0.3.2",
"acorn": "^8.5.0",
"commander": "^2.20.0",
"source-map-support": "~0.5.20"
},
"bin": {
"terser": "bin/terser"
},
"license": "MIT",
"optional": true,
"os": [
"android"
],
"engines": {
"node": ">=10"
"node": ">=18"
}
},
"node_modules/@frida/terser/node_modules/commander": {
"version": "2.20.3",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
"dev": true
},
"node_modules/@frida/timers": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/@frida/timers/-/timers-3.0.0.tgz",
"integrity": "sha512-3b+0igv10aT8TMxefrTAd06rActqbxJLY2Xkkq9vYcPBffB/yHszl0NYIp/5ko8WC3ecDYPU6bQiY6fjs72zTA==",
"dev": true
},
"node_modules/@frida/tty": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@frida/tty/-/tty-1.0.0.tgz",
"integrity": "sha512-p/kjLnKYxEAB1MdYP8+5rKv9CsHzyA+0jg9BcGETzjQVKHHcroHDULRxDYUh+DC7qs6cpX8QdDQh9E+a6ydgsQ==",
"dev": true
},
"node_modules/@frida/url": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@frida/url/-/url-1.0.2.tgz",
"integrity": "sha512-ZKunbKJHMr8w2Eb/5K1avy0MzK1B998S17wYXNv3RmzBGxMm8S5T0F3qEpRxkU7/72P8m4izyQU87fWl+FjQsQ==",
"node_modules/@esbuild/android-x64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.5.tgz",
"integrity": "sha512-D2GyJT1kjvO//drbRT3Hib9XPwQeWd9vZoBJn+bu/lVsOZ13cqNdDeqIF/xQ5/VmWvMduP6AmXvylO/PIc2isw==",
"cpu": [
"x64"
],
"dev": true,
"dependencies": {
"@frida/punycode": "^3.0.0",
"@frida/querystring": "^1.0.0"
}
},
"node_modules/@frida/util": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/@frida/util/-/util-1.0.3.tgz",
"integrity": "sha512-htcG3uDiRXv89ERVNNYhfase39kJ2X75ZARfrYcYEtJLFEsSk0nemM1YnEIR4CjrHvdvkWHrwgKkS+acOyoNEg==",
"dev": true
},
"node_modules/@frida/vm": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@frida/vm/-/vm-2.0.0.tgz",
"integrity": "sha512-7fsjLWscZT5odNIBtg6qbLNI+vAk1xmii6H5W2kaYkMYt0vRohQEcDSUWacA+eaWlu5SvMjZI82Yibj/3G9pJw==",
"dev": true
},
"node_modules/@jridgewell/gen-mapping": {
"version": "0.3.3",
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz",
"integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==",
"dev": true,
"dependencies": {
"@jridgewell/set-array": "^1.0.1",
"@jridgewell/sourcemap-codec": "^1.4.10",
"@jridgewell/trace-mapping": "^0.3.9"
},
"license": "MIT",
"optional": true,
"os": [
"android"
],
"engines": {
"node": ">=6.0.0"
"node": ">=18"
}
},
"node_modules/@jridgewell/resolve-uri": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz",
"integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==",
"node_modules/@esbuild/darwin-arm64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.5.tgz",
"integrity": "sha512-GtaBgammVvdF7aPIgH2jxMDdivezgFu6iKpmT+48+F8Hhg5J/sfnDieg0aeG/jfSvkYQU2/pceFPDKlqZzwnfQ==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">=6.0.0"
"node": ">=18"
}
},
"node_modules/@jridgewell/set-array": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz",
"integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==",
"node_modules/@esbuild/darwin-x64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.5.tgz",
"integrity": "sha512-1iT4FVL0dJ76/q1wd7XDsXrSW+oLoquptvh4CLR4kITDtqi2e/xwXwdCVH8hVHU43wgJdsq7Gxuzcs6Iq/7bxQ==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">=6.0.0"
"node": ">=18"
}
},
"node_modules/@jridgewell/source-map": {
"version": "0.3.3",
"resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.3.tgz",
"integrity": "sha512-b+fsZXeLYi9fEULmfBrhxn4IrPlINf8fiNarzTof004v3lFdntdwa9PF7vFJqm3mg7s+ScJMxXaE3Acp1irZcg==",
"node_modules/@esbuild/freebsd-arm64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.5.tgz",
"integrity": "sha512-nk4tGP3JThz4La38Uy/gzyXtpkPW8zSAmoUhK9xKKXdBCzKODMc2adkB2+8om9BDYugz+uGV7sLmpTYzvmz6Sw==",
"cpu": [
"arm64"
],
"dev": true,
"dependencies": {
"@jridgewell/gen-mapping": "^0.3.0",
"@jridgewell/trace-mapping": "^0.3.9"
"license": "MIT",
"optional": true,
"os": [
"freebsd"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@jridgewell/sourcemap-codec": {
"version": "1.4.15",
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
"integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==",
"dev": true
},
"node_modules/@jridgewell/trace-mapping": {
"version": "0.3.18",
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz",
"integrity": "sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==",
"node_modules/@esbuild/freebsd-x64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.5.tgz",
"integrity": "sha512-PrikaNjiXdR2laW6OIjlbeuCPrPaAl0IwPIaRv+SMV8CiM8i2LqVUHFC1+8eORgWyY7yhQY+2U2fA55mBzReaw==",
"cpu": [
"x64"
],
"dev": true,
"dependencies": {
"@jridgewell/resolve-uri": "3.1.0",
"@jridgewell/sourcemap-codec": "1.4.14"
"license": "MIT",
"optional": true,
"os": [
"freebsd"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@jridgewell/trace-mapping/node_modules/@jridgewell/sourcemap-codec": {
"version": "1.4.14",
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz",
"integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==",
"dev": true
"node_modules/@esbuild/linux-arm": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.5.tgz",
"integrity": "sha512-cPzojwW2okgh7ZlRpcBEtsX7WBuqbLrNXqLU89GxWbNt6uIg78ET82qifUy3W6OVww6ZWobWub5oqZOVtwolfw==",
"cpu": [
"arm"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-arm64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.5.tgz",
"integrity": "sha512-Z9kfb1v6ZlGbWj8EJk9T6czVEjjq2ntSYLY2cw6pAZl4oKtfgQuS4HOq41M/BcoLPzrUbNd+R4BXFyH//nHxVg==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-ia32": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.5.tgz",
"integrity": "sha512-sQ7l00M8bSv36GLV95BVAdhJ2QsIbCuCjh/uYrWiMQSUuV+LpXwIqhgJDcvMTj+VsQmqAHL2yYaasENvJ7CDKA==",
"cpu": [
"ia32"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-loong64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.5.tgz",
"integrity": "sha512-0ur7ae16hDUC4OL5iEnDb0tZHDxYmuQyhKhsPBV8f99f6Z9KQM02g33f93rNH5A30agMS46u2HP6qTdEt6Q1kg==",
"cpu": [
"loong64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-mips64el": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.5.tgz",
"integrity": "sha512-kB/66P1OsHO5zLz0i6X0RxlQ+3cu0mkxS3TKFvkb5lin6uwZ/ttOkP3Z8lfR9mJOBk14ZwZ9182SIIWFGNmqmg==",
"cpu": [
"mips64el"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-ppc64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.5.tgz",
"integrity": "sha512-UZCmJ7r9X2fe2D6jBmkLBMQetXPXIsZjQJCjgwpVDz+YMcS6oFR27alkgGv3Oqkv07bxdvw7fyB71/olceJhkQ==",
"cpu": [
"ppc64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-riscv64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.5.tgz",
"integrity": "sha512-kTxwu4mLyeOlsVIFPfQo+fQJAV9mh24xL+y+Bm6ej067sYANjyEw1dNHmvoqxJUCMnkBdKpvOn0Ahql6+4VyeA==",
"cpu": [
"riscv64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-s390x": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.5.tgz",
"integrity": "sha512-K2dSKTKfmdh78uJ3NcWFiqyRrimfdinS5ErLSn3vluHNeHVnBAFWC8a4X5N+7FgVE1EjXS1QDZbpqZBjfrqMTQ==",
"cpu": [
"s390x"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-x64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.5.tgz",
"integrity": "sha512-uhj8N2obKTE6pSZ+aMUbqq+1nXxNjZIIjCjGLfsWvVpy7gKCOL6rsY1MhRh9zLtUtAI7vpgLMK6DxjO8Qm9lJw==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/netbsd-arm64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.5.tgz",
"integrity": "sha512-pwHtMP9viAy1oHPvgxtOv+OkduK5ugofNTVDilIzBLpoWAM16r7b/mxBvfpuQDpRQFMfuVr5aLcn4yveGvBZvw==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"netbsd"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/netbsd-x64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.5.tgz",
"integrity": "sha512-WOb5fKrvVTRMfWFNCroYWWklbnXH0Q5rZppjq0vQIdlsQKuw6mdSihwSo4RV/YdQ5UCKKvBy7/0ZZYLBZKIbwQ==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"netbsd"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/openbsd-arm64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.5.tgz",
"integrity": "sha512-7A208+uQKgTxHd0G0uqZO8UjK2R0DDb4fDmERtARjSHWxqMTye4Erz4zZafx7Di9Cv+lNHYuncAkiGFySoD+Mw==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"openbsd"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/openbsd-x64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.5.tgz",
"integrity": "sha512-G4hE405ErTWraiZ8UiSoesH8DaCsMm0Cay4fsFWOOUcz8b8rC6uCvnagr+gnioEjWn0wC+o1/TAHt+It+MpIMg==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"openbsd"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/sunos-x64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.5.tgz",
"integrity": "sha512-l+azKShMy7FxzY0Rj4RCt5VD/q8mG/e+mDivgspo+yL8zW7qEwctQ6YqKX34DTEleFAvCIUviCFX1SDZRSyMQA==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"sunos"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/win32-arm64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.5.tgz",
"integrity": "sha512-O2S7SNZzdcFG7eFKgvwUEZ2VG9D/sn/eIiz8XRZ1Q/DO5a3s76Xv0mdBzVM5j5R639lXQmPmSo0iRpHqUUrsxw==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/win32-ia32": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.5.tgz",
"integrity": "sha512-onOJ02pqs9h1iMJ1PQphR+VZv8qBMQ77Klcsqv9CNW2w6yLqoURLcgERAIurY6QE63bbLuqgP9ATqajFLK5AMQ==",
"cpu": [
"ia32"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/win32-x64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.5.tgz",
"integrity": "sha512-TXv6YnJ8ZMVdX+SXWVBo/0p8LTcrUYngpWjvm91TMjjBQii7Oz11Lw5lbDV5Y0TzuhSJHwiH4hEtC1I42mMS0g==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@types/frida-gum": {
"version": "19.0.0",
@@ -329,177 +445,59 @@
"dev": true,
"license": "MIT"
},
"node_modules/@types/node": {
"version": "17.0.45",
"resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.45.tgz",
"integrity": "sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==",
"dev": true
},
"node_modules/acorn": {
"version": "8.8.2",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz",
"integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==",
"dev": true,
"bin": {
"acorn": "bin/acorn"
},
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/base64-js": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
"dev": true,
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
]
},
"node_modules/buffer-from": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
"dev": true
},
"node_modules/commander": {
"version": "11.1.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz",
"integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==",
"node_modules/esbuild": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.5.tgz",
"integrity": "sha512-P8OtKZRv/5J5hhz0cUAdu/cLuPIKXpQl1R9pZtvmHWQvrAUVd0UNIPT4IB4W3rNOqVO0rlqHmCIbSwxh/c9yUQ==",
"dev": true,
"hasInstallScript": true,
"license": "MIT",
"engines": {
"node": ">=16"
}
},
"node_modules/frida-compile": {
"version": "17.0.0",
"resolved": "https://registry.npmjs.org/frida-compile/-/frida-compile-17.0.0.tgz",
"integrity": "sha512-ixJRj14qLH/Z0ckFWd5fKeDMm0W2+2WDpSGnLRgpn0nuCQAbDHRCqVCWtPnV8uzPJmA6XOX0pujsMpYe9q9RRw==",
"dev": true,
"dependencies": {
"@frida/assert": "^3.0.1",
"@frida/base64-js": "^2.0.3",
"@frida/buffer": "^7.0.4",
"@frida/crosspath": "^3.0.0",
"@frida/crypto": "^1.0.1",
"@frida/diagnostics_channel": "^1.0.0",
"@frida/events": "^4.0.4",
"@frida/http": "^4.0.2",
"@frida/http-parser-js": "^1.0.0",
"@frida/https": "^1.0.0",
"@frida/ieee754": "^2.0.2",
"@frida/net": "^4.0.1",
"@frida/os": "^1.0.0",
"@frida/path": "^2.0.3",
"@frida/process": "^1.2.1",
"@frida/punycode": "^3.0.0",
"@frida/querystring": "^1.0.0",
"@frida/readable-stream": "^4.1.3",
"@frida/reserved-words": "^1.0.0",
"@frida/stream": "^1.0.2",
"@frida/string_decoder": "^2.0.0",
"@frida/terser": "^1.0.0",
"@frida/timers": "^3.0.0",
"@frida/tty": "^1.0.0",
"@frida/url": "^1.0.2",
"@frida/util": "^1.0.3",
"@frida/vm": "^2.0.0",
"commander": "^11.1.0",
"frida-fs": "^6.0.0",
"typed-emitter": "^2.1.0"
},
"bin": {
"frida-compile": "dist/cli.js"
}
},
"node_modules/frida-fs": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/frida-fs/-/frida-fs-6.0.0.tgz",
"integrity": "sha512-I0fnKupZh7fU2ixwCIjJnEqNdhfm/SC1ZYBMy58EmeqOWSbjw1Dpy99mJ7BJdbk2KNXJeaBZGxDYLtn0J9S+UA==",
"dev": true,
"license": "MIT"
},
"node_modules/http-parser-js": {
"version": "0.5.8",
"resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz",
"integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==",
"dev": true
},
"node_modules/ieee754": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
"integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
"dev": true,
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
]
},
"node_modules/rxjs": {
"version": "7.8.1",
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz",
"integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==",
"dev": true,
"optional": true,
"dependencies": {
"tslib": "^2.1.0"
}
},
"node_modules/source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
"dev": true,
"esbuild": "bin/esbuild"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/source-map-support": {
"version": "0.5.21",
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
"integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
"dev": true,
"dependencies": {
"buffer-from": "^1.0.0",
"source-map": "^0.6.0"
}
},
"node_modules/tslib": {
"version": "2.5.2",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.2.tgz",
"integrity": "sha512-5svOrSA2w3iGFDs1HibEVBGbDrAY82bFQ3HZ3ixB+88nsbsWQoKqDRb5UBYAUPEzbBn6dAp5gRNXglySbx1MlA==",
"dev": true,
"optional": true
},
"node_modules/typed-emitter": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/typed-emitter/-/typed-emitter-2.1.0.tgz",
"integrity": "sha512-g/KzbYKbH5C2vPkaXGu8DJlHrGKHLsM25Zg9WuC9pMGfuvT+X25tZQWo5fK1BjBm8+UrVE9LDCvaY0CQk+fXDA==",
"dev": true,
"node": ">=18"
},
"optionalDependencies": {
"rxjs": "*"
"@esbuild/aix-ppc64": "0.25.5",
"@esbuild/android-arm": "0.25.5",
"@esbuild/android-arm64": "0.25.5",
"@esbuild/android-x64": "0.25.5",
"@esbuild/darwin-arm64": "0.25.5",
"@esbuild/darwin-x64": "0.25.5",
"@esbuild/freebsd-arm64": "0.25.5",
"@esbuild/freebsd-x64": "0.25.5",
"@esbuild/linux-arm": "0.25.5",
"@esbuild/linux-arm64": "0.25.5",
"@esbuild/linux-ia32": "0.25.5",
"@esbuild/linux-loong64": "0.25.5",
"@esbuild/linux-mips64el": "0.25.5",
"@esbuild/linux-ppc64": "0.25.5",
"@esbuild/linux-riscv64": "0.25.5",
"@esbuild/linux-s390x": "0.25.5",
"@esbuild/linux-x64": "0.25.5",
"@esbuild/netbsd-arm64": "0.25.5",
"@esbuild/netbsd-x64": "0.25.5",
"@esbuild/openbsd-arm64": "0.25.5",
"@esbuild/openbsd-x64": "0.25.5",
"@esbuild/sunos-x64": "0.25.5",
"@esbuild/win32-arm64": "0.25.5",
"@esbuild/win32-ia32": "0.25.5",
"@esbuild/win32-x64": "0.25.5"
}
},
"node_modules/typescript": {
"version": "5.8.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz",
"integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==",
"dev": true,
"license": "Apache-2.0",
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
},
"engines": {
"node": ">=14.17"
}
}
}
+6 -3
View File
@@ -2,12 +2,15 @@
"name": "frida-barebone-script-runtime",
"version": "1.0.0",
"description": "Script runtime used by Frida's Barebone backend",
"type": "module",
"scripts": {
"prepare": "npm run build",
"build": "frida-compile script-runtime/entrypoint.ts -o script-runtime.js -c"
"build": "esbuild script-runtime/entrypoint.ts --outfile=script-runtime.js --bundle --platform=node --target=es2022 --minify",
"check": "tsc",
"watch": "tsc -w"
},
"devDependencies": {
"@types/frida-gum": "^19.0.0",
"frida-compile": "^17.0.0"
"esbuild": "^0.25.5",
"typescript": "^5.8.3"
}
}
+4 -20
View File
@@ -208,7 +208,10 @@ namespace Frida.Barebone {
}
~CompilationAssets () {
rmtree (workdir);
try {
FS.rmtree (workdir);
} catch (Error e) {
}
}
private static string make_main_rs (string code, Machine machine) {
@@ -428,23 +431,4 @@ namespace Frida.Barebone {
yield file.replace_contents_async (content.data, null, false, FileCreateFlags.NONE, cancellable, null);
return file;
}
private void rmtree (File dir) {
try {
var enumerator = dir.enumerate_children (FileAttribute.STANDARD_NAME, NOFOLLOW_SYMLINKS);
FileInfo? info;
File? child;
while (enumerator.iterate (out info, out child) && info != null) {
if (info == null)
continue;
if (info.get_file_type () == DIRECTORY)
rmtree (child);
else
child.delete ();
}
dir.delete ();
} catch (GLib.Error e) {
}
}
}
-18
View File
@@ -210,24 +210,6 @@ Object.defineProperties(globalThis, {
}
}
},
ObjC: {
enumerable: true,
value: {
available: false
}
},
Swift: {
enumerable: true,
value: {
available: false
}
},
Java: {
enumerable: true,
value: {
available: false
}
},
console: {
enumerable: true,
value: new Console()
+162 -38
View File
@@ -72,7 +72,7 @@ namespace Frida {
private QuickJS.Value int64_func = QuickJS.Undefined;
private QuickJS.Value uint64_func = QuickJS.Undefined;
private Gee.ArrayList<QuickJS.Value?> entrypoints = new Gee.ArrayList<QuickJS.Value?> ();
private Gee.Queue<Entrypoint> entrypoints = new Gee.ArrayQueue<Entrypoint> ();
private Gee.Map<string, Asset> assets = new Gee.HashMap<string, Asset> ();
private Cancellable io_cancellable = new Cancellable ();
@@ -328,6 +328,8 @@ namespace Frida {
foreach (var val in values)
ctx.free_value (val);
entrypoints.clear ();
QuickJS.Atom atoms[] = {
address_key,
base_key,
@@ -376,48 +378,65 @@ namespace Frida {
yield;
}
public void load () {
foreach (QuickJS.Value? entrypoint in entrypoints) {
var result = ctx.eval_function (entrypoint);
if (result.is_exception ())
public async void load (Cancellable? cancellable) throws IOError {
Entrypoint? entrypoint;
while ((entrypoint = entrypoints.poll ()) != null) {
var result = ctx.eval_function (ctx.dup_value (entrypoint.callable));
if (result.is_exception ()) {
catch_and_emit ();
ctx.free_value (result);
if (runtime_obj.is_undefined ()) {
runtime_obj = global.get_property_str (ctx, "$rt");
if (!runtime_obj.is_undefined ()) {
dispatch_exception_func = runtime_obj.get_property_str (ctx, "dispatchException");
assert (!dispatch_exception_func.is_undefined ());
dispatch_message_func = runtime_obj.get_property_str (ctx, "dispatchMessage");
assert (!dispatch_message_func.is_undefined ());
var native_pointer_instance = global.get_property_str (ctx, "NULL");
assert (!native_pointer_instance.is_undefined ());
var native_pointer_proto = native_pointer_instance.get_prototype (ctx);
var ir_proto = ctx.make_object_proto (native_pointer_proto);
add_cfunc (ir_proto, "replace", on_invocation_retval_replace, 1);
ctx.set_class_proto (invocation_retval_class, ir_proto);
ctx.free_value (native_pointer_proto);
ctx.free_value (native_pointer_instance);
ptr_func = global.get_property_str (ctx, "ptr");
assert (!ptr_func.is_undefined ());
int64_func = global.get_property_str (ctx, "int64");
assert (!int64_func.is_undefined ());
uint64_func = global.get_property_str (ctx, "uint64");
assert (!uint64_func.is_undefined ());
}
continue;
}
if (entrypoint.kind == ESM) {
var op = new PromiseWaitOperation (this, result);
var r = yield op.perform (cancellable);
if (!r.error.is_null ())
on_unhandled_exception (r.error);
} else {
ctx.free_value (result);
}
maybe_bind_runtime ();
}
perform_pending_io ();
}
private void maybe_bind_runtime () {
if (!runtime_obj.is_undefined ())
return;
runtime_obj = global.get_property_str (ctx, "$rt");
if (runtime_obj.is_undefined ())
return;
dispatch_exception_func = runtime_obj.get_property_str (ctx, "dispatchException");
assert (!dispatch_exception_func.is_undefined ());
dispatch_message_func = runtime_obj.get_property_str (ctx, "dispatchMessage");
assert (!dispatch_message_func.is_undefined ());
var native_pointer_instance = global.get_property_str (ctx, "NULL");
assert (!native_pointer_instance.is_undefined ());
var native_pointer_proto = native_pointer_instance.get_prototype (ctx);
var ir_proto = ctx.make_object_proto (native_pointer_proto);
add_cfunc (ir_proto, "replace", on_invocation_retval_replace, 1);
ctx.set_class_proto (invocation_retval_class, ir_proto);
ctx.free_value (native_pointer_proto);
ctx.free_value (native_pointer_instance);
ptr_func = global.get_property_str (ctx, "ptr");
assert (!ptr_func.is_undefined ());
int64_func = global.get_property_str (ctx, "int64");
assert (!int64_func.is_undefined ());
uint64_func = global.get_property_str (ctx, "uint64");
assert (!uint64_func.is_undefined ());
}
public void post (string json, Bytes? data) {
var json_val = ctx.make_string (json);
var data_val = (data != null) ? ctx.make_array_buffer (data.get_data ()) : QuickJS.Null;
@@ -495,7 +514,7 @@ namespace Frida {
throw_malformed_package ();
var val = compile_module (entrypoint);
entrypoints.add (val);
entrypoints.offer (new Entrypoint (this, val, ESM));
string rest = raw_assets[assets_offset:];
if (rest.has_prefix (delimiter_marker))
@@ -507,7 +526,7 @@ namespace Frida {
}
} else {
var val = compile_script (source, name);
entrypoints.add (val);
entrypoints.offer (new Entrypoint (this, val, PLAIN));
}
}
@@ -708,6 +727,111 @@ namespace Frida {
}
}
private class Entrypoint {
private weak BareboneScript script;
public QuickJS.Value callable;
public Kind kind;
public enum Kind {
PLAIN,
ESM
}
public Entrypoint (BareboneScript script, QuickJS.Value callable, Kind kind) {
this.script = script;
this.callable = callable;
this.kind = kind;
}
~Entrypoint () {
script.ctx.free_value (callable);
}
}
private class PromiseWaitOperation {
private BareboneScript script;
private QuickJS.Value promise;
private enum Magic {
ON_SUCCESS,
ON_FAILURE,
}
public PromiseWaitOperation (BareboneScript script, QuickJS.Value promise) {
this.script = script;
this.promise = promise;
}
~PromiseWaitOperation () {
script.ctx.free_value (promise);
}
public async Result perform (Cancellable? cancellable) throws IOError {
var res = new Result (script, perform.callback);
unowned QuickJS.Context ctx = script.ctx;
var data = ctx.make_object ();
data.set_opaque (res);
var on_success = ctx.make_cfunction_data (on_settled, 1, Magic.ON_SUCCESS, { data });
var on_failure = ctx.make_cfunction_data (on_settled, 1, Magic.ON_FAILURE, { data });
var then_func = promise.get_property_str (ctx, "then");
var catch_func = promise.get_property_str (ctx, "catch");
ctx.free_value (then_func.call (ctx, promise, { on_success }));
ctx.free_value (catch_func.call (ctx, promise, { on_failure }));
ctx.free_value (catch_func);
ctx.free_value (then_func);
ctx.free_value (on_failure);
ctx.free_value (on_success);
script.perform_pending_io ();
yield;
return res;
}
private static QuickJS.Value on_settled (QuickJS.Context ctx, QuickJS.Value this_val, QuickJS.Value[] argv, int magic,
QuickJS.Value[] data) {
QuickJS.ClassID cid;
unowned Result res = (Result) data[0].get_any_opaque (out cid);
if (magic == Magic.ON_SUCCESS)
res.val = ctx.dup_value (argv[0]);
else
res.error = ctx.dup_value (argv[0]);
var source = new IdleSource ();
source.set_callback ((owned) res.on_complete);
source.attach (MainContext.get_thread_default ());
return QuickJS.Undefined;
}
public class Result {
public BareboneScript script;
public SourceFunc on_complete;
public QuickJS.Value val = QuickJS.Null;
public QuickJS.Value error = QuickJS.Null;
public Result (BareboneScript script, owned SourceFunc on_complete) {
this.script = script;
this.on_complete = (owned) on_complete;
}
~Result () {
unowned QuickJS.Context ctx = script.ctx;
ctx.free_value (val);
ctx.free_value (error);
}
}
}
private class NativeCallbackHandler : Object, Barebone.CallbackHandler {
public uint arity {
get { return _arity; }
+10
View File
@@ -0,0 +1,10 @@
{
"compilerOptions": {
"target": "ES2022",
"lib": ["ES2022"],
"module": "Node16",
"strict": true,
"noEmit": true
},
"include": ["script-runtime/**/*.ts"]
}
-469
View File
@@ -1,469 +0,0 @@
import * as crosspath from "@frida/crosspath";
import type * as backend from "frida-compile";
import {
makeDefaultCompilerOptions,
build as _build,
watch as _watch,
queryDefaultAssets as _queryDefaultAssets,
} from "frida-compile";
import ts from "frida-compile/ext/typescript.js";
import fridaFs from "frida-fs";
import fs from "fs";
const { DiagnosticCategory, FileWatcherEventKind } = ts;
const { S_IFDIR } = fs.constants;
export const compilerRoot = "/frida-compile";
export const compilerNodeModules = compilerRoot + "/node_modules";
export const agentDirectories = new Set<string>(__agentDirectories__);
export const agentFiles = new Map<string, string>(__agentFiles__);
const cachedSourceFiles = new Map<string, ts.SourceFile>();
declare const __agentDirectories__: string[];
declare const __agentFiles__: [string, string][];
const pendingDiagnostics: ts.Diagnostic[] = [];
const fileWatchers = new Map<WatcherId, WatcherCallback>();
let nextWatcherId: WatcherId = 1;
populateSourceFileCache();
function populateSourceFileCache() {
const config = makeDefaultCompilerOptions();
for (const [name, contents] of agentFiles) {
if (name.endsWith(".d.ts")) {
const sf = ts.createSourceFile(name, contents, config.target!);
ts.prebindSourceFile(sf, config);
cachedSourceFiles.set(name, sf);
}
}
}
export function init(): void {
function onChange(message: WatchChangeMessage): void {
const callback = fileWatchers.get(message.id);
callback?.(fileWatcherEventKindFromFileState(message.state));
recv("watch:change", onChange);
}
recv("watch:change", onChange);
const origCreateCompilerHostFromProgramHost = (ts as any).createCompilerHostFromProgramHost;
(ts as any).createCompilerHostFromProgramHost = (...args: any[]): ts.CompilerHost => {
const host = origCreateCompilerHostFromProgramHost(...args);
patchCompilerHost(host);
return host;
};
}
export function build(projectRoot: string, entrypoint: string, sourceMaps: backend.SourceMaps, compression: backend.Compression): string {
const system = new FridaSystem(projectRoot);
const assets = _queryDefaultAssets(projectRoot, system);
try {
return _build({
projectRoot,
entrypoint,
assets,
system,
sourceMaps,
compression,
onDiagnostic,
onCompilerHostCreated: patchCompilerHost,
});
} finally {
flushDiagnostics();
}
}
export function watch(projectRoot: string, entrypoint: string, sourceMaps: backend.SourceMaps, compression: backend.Compression): void {
const system = new FridaSystem(projectRoot);
const assets = _queryDefaultAssets(projectRoot, system);
_watch({
projectRoot,
entrypoint,
assets,
system,
sourceMaps,
compression,
onDiagnostic,
})
.on("compilationStarting", () => {
send(["watch:compilation-starting"]);
})
.on("compilationFinished", () => {
send(["watch:compilation-finished"]);
})
.on("bundleUpdated", bundle => {
send(["watch:bundle-updated", bundle]);
});
}
function patchCompilerHost(host: ts.CompilerHost) {
const origGetSourceFile = host.getSourceFile;
host.getSourceFile = (fileName, ...args) => {
const compilerPath = nativePathToCompilerPath(fileName);
if (compilerPath !== null) {
const sf = cachedSourceFiles.get(compilerPath);
if (sf !== undefined) {
return sf;
}
} else {
const startPos = fileName.indexOf("/node_modules/@types/");
if (startPos !== -1) {
const builtinsPath = fileName.substring(startPos);
const sf = cachedSourceFiles.get(builtinsPath);
if (sf !== undefined) {
let allowCache = true;
if (builtinsPath.startsWith("/node_modules/@types/frida-gum/")) {
try {
const hashOnDisk = Checksum.compute("sha256", File.readAllText(fileName));
const hashInCache = Checksum.compute("sha256", agentFiles.get(sf.fileName)!);
allowCache = hashOnDisk === hashInCache;
} catch (e) {
}
}
if (allowCache) {
return sf;
}
}
}
}
return origGetSourceFile(fileName, ...args);
};
}
export { _build, _watch, _queryDefaultAssets };
type DiagnosticFile = [path: string, line: number, character: number];
function onDiagnostic(diagnostic: ts.Diagnostic): void {
pendingDiagnostics.push(diagnostic);
if (pendingDiagnostics.length === 1) {
Script.nextTick(flushDiagnostics);
}
}
function flushDiagnostics(): void {
const pending = pendingDiagnostics.splice(0, pendingDiagnostics.length);
if (pending.length === 0) {
return;
}
send([
"diagnostics",
pending.map(({
category,
code,
file: tsFile,
start,
messageText
}) => {
let file: DiagnosticFile | null = null;
if (tsFile !== undefined) {
const { line, character } = ts.getLineAndCharacterOfPosition(tsFile, start!);
file = [tsFile.fileName, line, character];
}
return [
diagnosticCategoryToString(category),
code,
file,
ts.flattenDiagnosticMessageText(messageText, "\n")
];
}),
]);
}
function diagnosticCategoryToString(category: ts.DiagnosticCategory): string {
switch (category) {
case DiagnosticCategory.Warning:
return "warning";
case DiagnosticCategory.Error:
return "error";
case DiagnosticCategory.Suggestion:
return "suggestion";
case DiagnosticCategory.Message:
return "message";
}
}
class FridaSystem implements ts.System {
args = [];
newLine = "\n";
useCaseSensitiveFileNames = true;
#projectRoot: string;
#projectNodeModules: string;
constructor(projectRoot: string) {
this.#projectRoot = crosspath.ensurePosix(projectRoot);
this.#projectNodeModules = crosspath.join(this.#projectRoot, "node_modules");
}
write(s: string): void {
}
writeOutputIsTTY(): boolean {
return true;
}
readFile(path: string, encoding?: string): string | undefined {
let result: string | undefined;
if (path.startsWith(this.#projectRoot)) {
try {
result = File.readAllText(path);
} catch (e) {
}
}
if (result === undefined) {
const agentZipPath = this.#nativePathToAgentZipPath(path);
if (agentZipPath !== null) {
result = agentFiles.get(agentZipPath);
}
}
return result;
}
getFileSize(path: string): number {
throw new Error("not implemented");
}
writeFile(path: string, data: string, writeByteOrderMark?: boolean): void {
File.writeAllText(path, data);
}
watchFile(path: string, callback: ts.FileWatcherCallback, pollingInterval?: number, options?: ts.WatchOptions): ts.FileWatcher {
if (path.startsWith(compilerRoot)) {
return makeDummyWatcher();
}
return makeFileWatcher(path, "file", pollingInterval ?? 0, kind => {
callback(path, kind);
});
}
watchDirectory(path: string, callback: ts.DirectoryWatcherCallback, recursive?: boolean, options?: ts.WatchOptions): ts.FileWatcher {
if (path.startsWith(compilerRoot)) {
return makeDummyWatcher();
}
return makeFileWatcher(path, "directory", 0, kind => {
callback(path);
});
}
resolvePath(path: string): string {
return path;
}
fileExists(path: string): boolean {
if (path.startsWith(this.#projectRoot)) {
try {
const st = fs.statSync(path);
return !st.isDirectory();
} catch (e) {
}
}
const agentZipPath = this.#nativePathToAgentZipPath(path);
if (agentZipPath === null) {
return false;
}
return agentFiles.has(agentZipPath);
}
directoryExists(path: string): boolean {
if (path === compilerNodeModules) {
return true;
}
if (path.startsWith(this.#projectRoot)) {
try {
const st = fs.statSync(path);
return st.isDirectory();
} catch (e) {
}
}
const agentZipPath = this.#nativePathToAgentZipPath(path);
if (agentZipPath === null) {
return false;
}
return agentDirectories.has(agentZipPath);
}
createDirectory(path: string): void {
throw new Error("not implemented");
}
getExecutingFilePath(): string {
return [compilerRoot, "ext", "typescript.js"].join("/");
}
getCurrentDirectory(): string {
return this.#projectRoot;
}
getDirectories(path: string): string[] {
const result = new Set<string>();
if (path.startsWith(this.#projectRoot)) {
try {
for (const entry of fridaFs.list(path).filter(entry => entry.type === S_IFDIR)) {
result.add(entry.name);
}
} catch (e) {
}
}
const agentZipPath = this.#nativePathToAgentZipPath(path);
if (agentZipPath !== null) {
for (const dir of agentDirectories) {
const slashIndex = dir.lastIndexOf("/");
const parent = dir.substring(0, slashIndex);
if (parent === agentZipPath) {
const basename = dir.substring(slashIndex + 1);
result.add(basename);
}
}
}
return Array.from(result);
}
readDirectory(path: string, extensions?: readonly string[], exclude?: readonly string[], include?: readonly string[], depth?: number): string[] {
return [];
}
getModifiedTime(path: string): Date | undefined {
return undefined;
}
setModifiedTime(path: string, time: Date): void {
}
deleteFile(path: string): void {
}
createHash(data: string): string {
return this.createSHA256Hash(data);
}
createSHA256Hash(data: string): string {
return Checksum.compute("sha256", data);
}
getMemoryUsage(): number {
return Frida.heapSize;
}
exit(exitCode?: number): void {
}
realpath(path: string): string {
return path;
}
getEnvironmentVariable(name: string): string {
return "";
}
setTimeout(callback: (...args: any[]) => void, ms: number, ...args: any[]): any {
return setTimeout(callback);
}
clearTimeout(timeoutId: any): void {
return clearTimeout(timeoutId);
}
clearScreen(): void {
}
base64decode(input: string): string {
throw new Error("not implemented");
}
base64encode(input: string): string {
throw new Error("not implemented");
}
#nativePathToAgentZipPath(path: string): string | null {
const compilerPath = nativePathToCompilerPath(path);
if (compilerPath !== null) {
return compilerPath;
}
if (path.startsWith(this.#projectNodeModules)) {
return "/node_modules" + path.substring(this.#projectNodeModules.length);
}
return null;
}
}
function nativePathToCompilerPath(path: string): string | null {
if (!path.startsWith(compilerRoot)) {
return null;
}
const subPath = path.substring(compilerRoot.length);
if (subPath.startsWith("/node_modules")) {
return subPath;
}
return "/node_modules/frida-compile" + subPath;
}
type WatcherId = number;
type WatcherCallback = (eventKind: ts.FileWatcherEventKind) => void;
type FileState = "pristine" | "modified" | "deleted";
interface WatchChangeMessage {
id: WatcherId;
state: FileState;
}
function makeFileWatcher(path: string, type: "file" | "directory", pollingInterval: number, callback: WatcherCallback): ts.FileWatcher {
if (nextWatcherId === 0xffffffff) {
nextWatcherId = 1;
}
let id: WatcherId = nextWatcherId++;
while (fileWatchers.has(id)) {
id = nextWatcherId++;
}
fileWatchers.set(id, callback);
send(["watch:add", id, path, type, pollingInterval ?? 0]);
return {
close() {
send(["watch:remove", id]);
fileWatchers.delete(id);
}
};
}
function makeDummyWatcher(): ts.FileWatcher {
return {
close() {
}
};
}
function fileWatcherEventKindFromFileState(state: FileState): ts.FileWatcherEventKind {
switch (state) {
case "pristine": return FileWatcherEventKind.Created;
case "modified": return FileWatcherEventKind.Changed;
case "deleted": return FileWatcherEventKind.Deleted;
}
}
-5
View File
@@ -1,5 +0,0 @@
const { init, build, watch } = FridaCompilerAgentCore;
init();
rpc.exports = { build, watch };
-222
View File
@@ -1,222 +0,0 @@
const {
compilerRoot,
compilerNodeModules,
agentDirectories,
agentFiles,
_build,
_queryDefaultAssets,
} = FridaCompilerAgentCore;
const projectRoot = '/agent';
const projectNodeModules = '/agent/node_modules';
const entrypoint = 'index.ts';
const sourceMaps = 'included';
const compression = 'none';
const hashes = new Map();
let nextHashId = 1;
function main() {
const system = new StubSystem();
const assets = _queryDefaultAssets(projectRoot, system);
_build({
projectRoot,
entrypoint,
assets,
system,
sourceMaps,
compression,
onDiagnostic,
});
}
function onDiagnostic(diagnostic) {
throwNotImplemented('diagnostic', ts.flattenDiagnosticMessageText(diagnostic, '\n'));
}
class StubSystem {
args = [];
newLine = '\n';
useCaseSensitiveFileNames = true;
write(s) {
}
writeOutputIsTTY() {
return true;
}
readFile(path, encoding) {
if (path === '/agent/tsconfig.json')
return '{}';
if (path === '/agent/index.ts')
return 'Interceptor.attach(ptr(1234), { onEnter(args) {} });'
const agentZipPath = this.#nativePathToAgentZipPath(path);
if (agentZipPath !== null) {
return agentFiles.get(agentZipPath);
}
throwNotImplemented('readFile', path);
}
getFileSize(path) {
throwNotImplemented('getFileSize');
}
writeFile(path, data, writeByteOrderMark) {
throwNotImplemented('writeFile');
}
watchFile(path, callback, pollingInterval, options) {
throwNotImplemented('watchFile');
}
watchDirectory(path, callback, recursive, options) {
throwNotImplemented('watchDirectory');
}
resolvePath(path) {
throwNotImplemented('resolvePath');
}
fileExists(path) {
if (path === '/package.json' || path === '/agent/package.json')
return false;
const agentZipPath = this.#nativePathToAgentZipPath(path);
if (agentZipPath !== null)
return agentFiles.has(agentZipPath);
throwNotImplemented('fileExists', path);
}
directoryExists(path) {
if (path === '/' || path === projectRoot || path === compilerNodeModules)
return true;
const agentZipPath = this.#nativePathToAgentZipPath(path);
if (agentZipPath !== null)
return agentDirectories.has(agentZipPath);
if (path === '/node_modules/@types' || path === '/node_modules')
return false;
throwNotImplemented('directoryExists', path);
}
createDirectory(path) {
throwNotImplemented('createDirectory');
}
getExecutingFilePath() {
return [compilerRoot, 'ext', 'typescript.js'].join('/');
}
getCurrentDirectory() {
return '/';
}
getDirectories(path) {
const agentZipPath = this.#nativePathToAgentZipPath(path);
if (agentZipPath !== null) {
const result = [];
for (const dir of agentDirectories) {
const slashIndex = dir.lastIndexOf('/');
const parent = dir.substring(0, slashIndex);
if (parent === agentZipPath) {
const basename = dir.substring(slashIndex + 1);
result.push(basename);
}
}
return result;
}
throwNotImplemented('getDirectories', path);
}
readDirectory(path, extensions, exclude, include, depth) {
if (!extensions.includes('.ts'))
throwNotImplemented('readDirectory', path, extensions);
return ['index.ts'];
}
getModifiedTime(path) {
}
setModifiedTime(path, time) {
}
deleteFile(path) {
}
createHash(data) {
let hash = hashes.get(data);
if (hash === undefined) {
hash = 'hash' + nextHashId++;
hashes.set(data, hash);
}
return hash;
}
createSHA256Hash(data) {
throwNotImplemented('createSHA256Hash');
}
getMemoryUsage() {
throwNotImplemented('getMemoryUsage');
}
exit(exitCode) {
}
realpath(path) {
return path;
}
getEnvironmentVariable(name) {
return '';
}
setTimeout(callback, ms, ...args) {
throwNotImplemented('setTimeout');
}
clearTimeout(timeoutId) {
throwNotImplemented('clearTimeout');
}
clearScreen() {
}
base64decode(input) {
throwNotImplemented('base64decode');
}
base64encode(input) {
throwNotImplemented('base64encode');
}
#nativePathToAgentZipPath(path) {
if (path.startsWith(compilerRoot)) {
const subPath = path.substring(compilerRoot.length);
if (subPath.startsWith('/node_modules')) {
return subPath;
}
return '/node_modules/frida-compile' + subPath;
}
if (path.startsWith(projectNodeModules)) {
return '/node_modules' + path.substring(projectNodeModules.length);
}
return null;
}
}
function throwNotImplemented(operation, ...details) {
throw new Error('not implemented: ' + operation + ((details.length > 0) ? ` (${details.join(' ')})` : ''));
}
main();
+28
View File
@@ -0,0 +1,28 @@
#ifdef _MSC_VER
#include <glib.h>
#ifdef HAVE_ARM64
# define FRIDA_CGO_INIT_FUNC _st0_arm64_windows_lib
#elif GLIB_SIZEOF_VOID_P == 8
# define FRIDA_CGO_INIT_FUNC _st0_amd64_windows_lib
#else
# define FRIDA_CGO_INIT_FUNC st0_386_windows_lib
#endif
extern void FRIDA_CGO_INIT_FUNC ();
void
_frida_compiler_backend_init_go_runtime (void)
{
FRIDA_CGO_INIT_FUNC ();
}
#else
void
_frida_compiler_backend_init_go_runtime (void)
{
}
#endif
+816
View File
@@ -0,0 +1,816 @@
package main
/*
#include <stdint.h>
typedef enum {
FRIDA_OUTPUT_UNESCAPED,
FRIDA_OUTPUT_HEX_BYTES,
FRIDA_OUTPUT_C_STRING,
} FridaOutputFormat;
typedef enum {
FRIDA_BUNDLE_ESM,
FRIDA_BUNDLE_IIFE,
} FridaBundleFormat;
typedef void (* FridaBuildCompleteFunc) (char * bundle, char * error_message, void * user_data);
typedef void (* FridaWatchReadyFunc) (uintptr_t session_handle, char * error_message, void * user_data);
typedef void (* FridaStartingFunc) (void * user_data);
typedef void (* FridaFinishedFunc) (void * user_data);
typedef void (* FridaOutputFunc) (char * bundle, void * user_data);
typedef void (* FridaDiagnosticFunc) (char * category, int code, char * path, int line, int character, char * text,
void * user_data);
typedef void (* FridaDestroyFunc) (void * user_data);
static inline void
invoke_build_complete_func (FridaBuildCompleteFunc fn,
char * bundle,
char * error_message,
void * user_data)
{
fn (bundle, error_message, user_data);
}
static inline void
invoke_watch_ready_func (FridaWatchReadyFunc fn,
uintptr_t session_handle,
char * error_message,
void * user_data)
{
fn (session_handle, error_message, user_data);
}
static inline void
invoke_starting_func (FridaStartingFunc fn,
void * user_data)
{
fn (user_data);
}
static inline void
invoke_finished_func (FridaFinishedFunc fn,
void * user_data)
{
fn (user_data);
}
static inline void
invoke_output_func (FridaOutputFunc fn,
char * bundle,
void * user_data)
{
fn (bundle, user_data);
}
static inline void
invoke_diagnostic_func (FridaDiagnosticFunc fn,
char * category,
int code,
char * path,
int line,
int character,
char * text,
void * user_data)
{
fn (category, code, path, line, character, text, user_data);
}
static inline void
invoke_destroy_func (FridaDestroyFunc fn,
void * user_data)
{
fn (user_data);
}
*/
import "C"
import (
"fmt"
"path"
"path/filepath"
"runtime/cgo"
"strings"
"sync"
"unsafe"
esbuild "github.com/evanw/esbuild/pkg/api"
tsscanner "github.com/frida/typescript-go/pkg/scanner"
)
type BuildOptions struct {
ProjectRoot string
Entrypoint string
OutputFormat OutputFormat
BundleFormat BundleFormat
DisableTypeCheck bool
SourceMap bool
Compress bool
}
type OutputFormat C.FridaOutputFormat
const (
OutputFormatUnescaped OutputFormat = OutputFormat(C.FRIDA_OUTPUT_UNESCAPED)
OutputFormatHexBytes OutputFormat = OutputFormat(C.FRIDA_OUTPUT_HEX_BYTES)
OutputFormatCString OutputFormat = OutputFormat(C.FRIDA_OUTPUT_C_STRING)
)
type BundleFormat C.FridaBundleFormat
const (
BundleFormatESM BundleFormat = BundleFormat(C.FRIDA_BUNDLE_ESM)
BundleFormatIIFE BundleFormat = BundleFormat(C.FRIDA_BUNDLE_IIFE)
)
type Diagnostic struct {
category string
code int
path string
line, character int
text string
}
type BuildEventCallbacks struct {
OnStart BuildStartCallback
OnEnd BuildEndCallback
OnOutput BuildOutputCallback
OnDiagnostic BuildDiagnosticCallback
OnConfigChange ConfigChangeCallback
}
type BuildStartCallback func()
type BuildEndCallback func()
type BuildOutputCallback func(bundle string)
type BuildDiagnosticCallback func(d Diagnostic)
//export _frida_compiler_backend_build
func _frida_compiler_backend_build(cProjectRoot, cEntrypoint *C.char, outputFormat C.FridaOutputFormat, bundleFormat C.FridaBundleFormat,
disableTypeCheck, sourceMap, compress uintptr,
onCompleteFn C.FridaBuildCompleteFunc, onCompleteData unsafe.Pointer, onCompleteDataDestroy C.FridaDestroyFunc,
onDiagnosticFn C.FridaDiagnosticFunc, onDiagnosticData unsafe.Pointer) {
options := BuildOptions{
ProjectRoot: C.GoString(cProjectRoot),
Entrypoint: C.GoString(cEntrypoint),
OutputFormat: OutputFormat(outputFormat),
BundleFormat: BundleFormat(bundleFormat),
DisableTypeCheck: disableTypeCheck != 0,
SourceMap: sourceMap != 0,
Compress: compress != 0,
}
onComplete := NewCDelegate(onCompleteFn, onCompleteData, onCompleteDataDestroy)
onDiagnostic := NewCDelegate(onDiagnosticFn, onDiagnosticData, nil)
go func() {
defer onComplete.Dispose()
defer onDiagnostic.Dispose()
onDiagnostic := makeCBuildDiagnosticCallback(onDiagnostic)
bundle, err := build(options, onDiagnostic)
var cBundle, cErrorMessage *C.char
if err == nil {
cBundle = C.CString(bundle)
} else {
cErrorMessage = C.CString(err.Error())
}
C.invoke_build_complete_func(onComplete.Func, cBundle, cErrorMessage, onComplete.Data)
}()
}
//export _frida_compiler_backend_watch
func _frida_compiler_backend_watch(cProjectRoot, cEntrypoint *C.char, outputFormat C.FridaOutputFormat, bundleFormat C.FridaBundleFormat,
disableTypeCheck, sourceMap, compress uintptr,
onReadyFn C.FridaWatchReadyFunc, onReadyData unsafe.Pointer, onReadyDataDestroy C.FridaDestroyFunc,
onStartingFn C.FridaStartingFunc, onStartingData unsafe.Pointer,
onFinishedFn C.FridaFinishedFunc, onFinishedData unsafe.Pointer,
onOutputFn C.FridaOutputFunc, onOutputData unsafe.Pointer,
onDiagnosticFn C.FridaDiagnosticFunc, onDiagnosticData unsafe.Pointer) {
options := BuildOptions{
ProjectRoot: C.GoString(cProjectRoot),
Entrypoint: C.GoString(cEntrypoint),
OutputFormat: OutputFormat(outputFormat),
BundleFormat: BundleFormat(bundleFormat),
DisableTypeCheck: disableTypeCheck != 0,
SourceMap: sourceMap != 0,
Compress: compress != 0,
}
onReady := NewCDelegate(onReadyFn, onReadyData, onReadyDataDestroy)
onStarting := NewCDelegate(onStartingFn, onStartingData, nil)
onFinished := NewCDelegate(onFinishedFn, onFinishedData, nil)
onOutput := NewCDelegate(onOutputFn, onOutputData, nil)
onDiagnostic := NewCDelegate(onDiagnosticFn, onDiagnosticData, nil)
go func() {
defer onReady.Dispose()
onDispose := func() {
onStarting.Dispose()
onFinished.Dispose()
onOutput.Dispose()
onDiagnostic.Dispose()
}
callbacks := BuildEventCallbacks{
OnStart: func() {
C.invoke_starting_func(onStarting.Func, onStarting.Data)
},
OnEnd: func() {
C.invoke_starting_func(onFinished.Func, onFinished.Data)
},
OnOutput: func(bundle string) {
C.invoke_output_func(onOutput.Func, C.CString(bundle), onOutput.Data)
},
OnDiagnostic: makeCBuildDiagnosticCallback(onDiagnostic),
}
session, err := NewWatchSession(options, onDispose, callbacks)
var cSession C.uintptr_t
var cErrorMessage *C.char
if err == nil {
cSession = C.uintptr_t(cgo.NewHandle(session))
} else {
cErrorMessage = C.CString(err.Error())
}
C.invoke_watch_ready_func(onReady.Func, cSession, cErrorMessage, onReady.Data)
}()
}
//export _frida_compiler_backend_watch_session_dispose
func _frida_compiler_backend_watch_session_dispose(h uintptr) {
handle := cgo.Handle(h)
session := handle.Value().(*WatchSession)
session.Dispose()
handle.Delete()
}
func makeCBuildDiagnosticCallback(onDiagnostic *CDelegate[C.FridaDiagnosticFunc]) BuildDiagnosticCallback {
return func(d Diagnostic) {
var cPath *C.char
if d.path != "" {
cPath = C.CString(d.path)
}
C.invoke_diagnostic_func(onDiagnostic.Func, C.CString(d.category), C.int(d.code), cPath, C.int(d.line),
C.int(d.character), C.CString(d.text), onDiagnostic.Data)
}
}
func build(options BuildOptions, onDiagnostic BuildDiagnosticCallback) (bundle string, err error) {
callbacks := BuildEventCallbacks{
OnOutput: func(b string) {
bundle = b
},
OnDiagnostic: onDiagnostic,
}
ctx, err := makeContext(options, callbacks)
if err != nil {
return
}
defer ctx.Dispose()
result := ctx.Rebuild()
if len(result.Errors) != 0 {
err = fmt.Errorf("Compilation failed")
}
return
}
type WatchSession struct {
mu sync.Mutex
options BuildOptions
callbacks BuildEventCallbacks
ctx esbuild.BuildContext
onDispose SessionDisposeHandler
}
type SessionDisposeHandler func()
func NewWatchSession(opts BuildOptions, onDispose SessionDisposeHandler, callbacks BuildEventCallbacks) (session *WatchSession, err error) {
cbs := BuildEventCallbacks{
OnStart: callbacks.OnStart,
OnEnd: callbacks.OnEnd,
OnOutput: callbacks.OnOutput,
OnDiagnostic: callbacks.OnDiagnostic,
OnConfigChange: func() {
if callbacks.OnConfigChange != nil {
callbacks.OnConfigChange()
}
session.onConfigChange()
},
}
ctx, err := makeContext(opts, cbs)
if err != nil {
return
}
ctx.Watch(esbuild.WatchOptions{})
session = &WatchSession{
options: opts,
callbacks: cbs,
ctx: ctx,
onDispose: onDispose,
}
return
}
func (s *WatchSession) Dispose() {
s.mu.Lock()
defer s.mu.Unlock()
if s.ctx != nil {
s.ctx.Dispose()
s.ctx = nil
}
s.onDispose()
}
func (s *WatchSession) onConfigChange() {
go func() {
s.mu.Lock()
defer s.mu.Unlock()
if s.ctx != nil {
s.ctx.Dispose()
s.ctx = nil
}
ctx, err := makeContext(s.options, s.callbacks)
if err != nil {
return
}
s.ctx = ctx
ctx.Watch(esbuild.WatchOptions{})
}()
}
func makeContext(options BuildOptions, callbacks BuildEventCallbacks) (ctx esbuild.BuildContext, err error) {
var e error
var projectRoot string
if projectRoot, e = filepath.EvalSymlinks(options.ProjectRoot); e != nil {
err = fmt.Errorf("Failed to resolve project root: %w", e)
return
}
var entrypoint string
if filepath.IsAbs(options.Entrypoint) {
entrypoint = options.Entrypoint
} else {
entrypoint = filepath.Join(projectRoot, options.Entrypoint)
}
if entrypoint, e = filepath.EvalSymlinks(entrypoint); e != nil {
err = fmt.Errorf("Failed to resolve entrypoint: %w", e)
return
}
rel, e := filepath.Rel(projectRoot, entrypoint)
if e != nil {
err = fmt.Errorf("Could not compute entrypoint path relative to project root: %w", e)
return
}
if strings.HasPrefix(rel, "..") {
err = fmt.Errorf("Entrypoint must be inside the project root")
return
}
isTS := strings.HasSuffix(entrypoint, ".ts")
var tsconfigCache *TSConfigCache
var tsconfigText string
var tsCompiler *TSCompiler
if isTS {
tsconfigCache = NewTSConfigCache(projectRoot, options.SourceMap, callbacks.OnConfigChange)
tsCompiler = NewTSCompiler(projectRoot, entrypoint, tsconfigCache.GetCompilerOptions)
_, tsconfigText, err = tsconfigCache.GetCompilerOptions(tsCompiler)
if err != nil {
err = fmt.Errorf("Failed to load tsconfig options: %w", err)
return
}
}
sourcemapOption := esbuild.SourceMapNone
if options.SourceMap {
if options.BundleFormat == BundleFormatESM {
sourcemapOption = esbuild.SourceMapExternal
} else {
sourcemapOption = esbuild.SourceMapInline
}
}
minifyWhitespace := false
minifyIdentifiers := false
minifySyntax := false
if options.Compress {
minifyWhitespace = true
minifyIdentifiers = true
minifySyntax = true
}
var format esbuild.Format
if options.BundleFormat == BundleFormatESM {
format = esbuild.FormatESModule
} else {
format = esbuild.FormatIIFE
}
plugins := []esbuild.Plugin{
makeBuildObserverPlugin(projectRoot, entrypoint, options, callbacks),
}
if isTS && !options.DisableTypeCheck {
plugins = append(plugins, makeTypeScriptPlugin(tsCompiler))
}
plugins = append(plugins, makeFridaShimsPlugin())
buildOpts := esbuild.BuildOptions{
Sourcemap: sourcemapOption,
SourcesContent: esbuild.SourcesContentExclude,
Target: esbuild.ES2022,
MinifyWhitespace: minifyWhitespace,
MinifyIdentifiers: minifyIdentifiers,
MinifySyntax: minifySyntax,
LegalComments: esbuild.LegalCommentsNone,
Bundle: true,
Outdir: projectRoot,
AbsWorkingDir: projectRoot,
Platform: esbuild.PlatformNode,
Format: format,
Inject: []string{"frida-builtins:///node-globals.js"},
EntryPoints: []string{entrypoint},
Write: false,
Plugins: plugins,
}
if isTS {
buildOpts.TsconfigRaw = tsconfigText
}
if buildCtx, ctxErr := esbuild.Context(buildOpts); ctxErr == nil {
ctx = buildCtx
} else {
for _, e := range ctxErr.Errors {
emitDiagnostic("error", e, callbacks.OnDiagnostic)
}
err = fmt.Errorf("Failed to create ESBuild context")
}
return
}
func emitDiagnostic(category string, message esbuild.Message, onDiagnostic BuildDiagnosticCallback) {
d := Diagnostic{
category: category,
code: -1,
text: message.Text,
}
l := message.Location
if l != nil {
d.path = l.File
d.line = l.Line
d.character = l.Column
}
if message.PluginName == "frida-custom-ts" && len(message.Notes) == 2 {
d.category = message.Notes[0].Text
fmt.Sscan(message.Notes[1].Text, &d.code)
}
onDiagnostic(d)
}
func changeToJS(p string) string {
ext := path.Ext(p)
base := p[:len(p)-len(ext)]
return base + ".js"
}
func makeBuildObserverPlugin(projectRoot, entrypoint string, options BuildOptions, callbacks BuildEventCallbacks) esbuild.Plugin {
return esbuild.Plugin{
Name: "frida-build-observer",
Setup: func(build esbuild.PluginBuild) {
if callbacks.OnStart != nil {
build.OnStart(func() (esbuild.OnStartResult, error) {
callbacks.OnStart()
return esbuild.OnStartResult{}, nil
})
}
build.OnEnd(func(result *esbuild.BuildResult) (esbuild.OnEndResult, error) {
if len(result.Errors) == 0 {
var output string
if options.BundleFormat == BundleFormatESM {
output = makeESMBundle(result.OutputFiles, projectRoot, entrypoint)
} else {
output = string(result.OutputFiles[0].Contents)
}
switch options.OutputFormat {
case OutputFormatHexBytes:
output = encodeStringToHexBytes(output)
case OutputFormatCString:
output = encodeStringToCString(output)
}
callbacks.OnOutput(output)
} else {
for _, e := range result.Errors {
emitDiagnostic("error", e, callbacks.OnDiagnostic)
}
for _, e := range result.Warnings {
emitDiagnostic("warning", e, callbacks.OnDiagnostic)
}
}
if callbacks.OnEnd != nil {
callbacks.OnEnd()
}
return esbuild.OnEndResult{}, nil
})
},
}
}
func makeESMBundle(files []esbuild.OutputFile, projectRoot, entrypoint string) string {
entrypointJS, entrypointMap := outputForEntrypoint(projectRoot, entrypoint)
relEntryp, err := filepath.Rel(projectRoot, entrypoint)
if err != nil {
panic(fmt.Sprintf("Cannot compute entrypoint relative path: %v", err))
}
entrySubDir := filepath.Dir(relEntryp)
entryIndexJS := -1
entryIndexMap := -1
for i, of := range files {
if of.Path == entrypointJS {
entryIndexJS = i
}
if of.Path == entrypointMap {
entryIndexMap = i
}
}
if entryIndexJS < 0 {
panic(fmt.Sprintf("Entrypoint JS %q not found in files", entrypointJS))
}
orderedFiles := make([]esbuild.OutputFile, 0, len(files))
orderedFiles = append(orderedFiles, files[entryIndexJS])
if entryIndexMap >= 0 {
orderedFiles = append(orderedFiles, files[entryIndexMap])
}
for i, of := range files {
if i == entryIndexJS || i == entryIndexMap {
continue
}
orderedFiles = append(orderedFiles, of)
}
var sb strings.Builder
sb.WriteString("📦\n")
for _, of := range orderedFiles {
size := len(of.Contents)
relPath, _ := filepath.Rel(projectRoot, of.Path)
withSub := filepath.Join(entrySubDir, relPath)
sb.WriteString(fmt.Sprintf("%d /%s\n", size, filepath.ToSlash(withSub)))
}
sb.WriteString("✄\n")
for i, of := range orderedFiles {
sb.Write(of.Contents)
if i < len(orderedFiles)-1 {
sb.WriteString("\n✄\n")
}
}
return sb.String()
}
func outputForEntrypoint(projectRoot, entrypoint string) (jsOut, mapOut string) {
jsOut = filepath.Join(projectRoot, changeToJS(filepath.Base(entrypoint)))
mapOut = jsOut + ".map"
return
}
func encodeStringToHexBytes(s string) string {
n := len(s)
if n == 0 {
return ""
}
totalLen := n*4 + (n-1)*2 + 1
buf := make([]byte, 0, totalLen)
hexDigits := "0123456789abcdef"
for i := 0; i < n; i++ {
b := s[i]
buf = append(buf, '0', 'x')
buf = append(buf,
hexDigits[b>>4],
hexDigits[b&0xF],
)
if i < n-1 {
if (i+1)%12 == 0 {
buf = append(buf, ',', '\n')
} else {
buf = append(buf, ',', ' ')
}
}
}
buf = append(buf, '\n')
return string(buf)
}
func encodeStringToCString(s string) string {
n := len(s)
if n == 0 {
return `""`
}
hexDigits := "0123456789abcdef"
var bldr strings.Builder
openLiteral := func() {
bldr.WriteByte('"')
}
closeLiteral := func() {
bldr.WriteByte('"')
}
inLiteral := false
for i := 0; i < n; i++ {
c := s[i]
if !inLiteral {
openLiteral()
inLiteral = true
}
if c == '\n' {
bldr.WriteByte('\\')
bldr.WriteByte('n')
closeLiteral()
inLiteral = false
if i < n-1 {
bldr.WriteByte('\n')
openLiteral()
inLiteral = true
}
continue
}
switch c {
case '"':
bldr.WriteByte('\\')
bldr.WriteByte('"')
case '\\':
bldr.WriteByte('\\')
bldr.WriteByte('\\')
case '\a':
bldr.WriteByte('\\')
bldr.WriteByte('a')
case '\b':
bldr.WriteByte('\\')
bldr.WriteByte('b')
case '\t':
bldr.WriteByte('\\')
bldr.WriteByte('t')
case '\v':
bldr.WriteByte('\\')
bldr.WriteByte('v')
case '\f':
bldr.WriteByte('\\')
bldr.WriteByte('f')
case '\r':
bldr.WriteByte('\\')
bldr.WriteByte('r')
default:
isPrintableExceptQuoteAndBackslash := c >= 0x20 && c <= 0x7E
if isPrintableExceptQuoteAndBackslash {
bldr.WriteByte(c)
} else {
bldr.WriteByte('\\')
bldr.WriteByte('x')
bldr.WriteByte(hexDigits[c>>4])
bldr.WriteByte(hexDigits[c&0xF])
}
}
}
if inLiteral {
closeLiteral()
}
bldr.WriteByte('\n')
return bldr.String()
}
func makeTypeScriptPlugin(compiler *TSCompiler) esbuild.Plugin {
return esbuild.Plugin{
Name: "frida-custom-ts",
Setup: func(build esbuild.PluginBuild) {
build.OnStart(func() (esbuild.OnStartResult, error) {
compiler.EnsureProgramUpToDate()
return esbuild.OnStartResult{}, nil
})
build.OnEnd(func(result *esbuild.BuildResult) (esbuild.OnEndResult, error) {
if len(result.Errors) == 0 {
compiler.CommitPendingInputs()
} else {
compiler.DropPendingInputs()
}
return esbuild.OnEndResult{}, nil
})
build.OnLoad(esbuild.OnLoadOptions{Filter: "\\.ts$"}, func(args esbuild.OnLoadArgs) (esbuild.OnLoadResult, error) {
compiledJS, tsDiagnostics, err := compiler.Compile(args.Path)
result := esbuild.OnLoadResult{
WatchFiles: compiler.WatchFiles(),
WatchDirs: compiler.WatchDirs(),
}
var esbuildMessages []esbuild.Message
for _, d := range tsDiagnostics {
f := d.File()
pos := d.Pos()
line, column := tsscanner.GetLineAndCharacterOfPosition(f, pos)
esbuildMessages = append(esbuildMessages, esbuild.Message{
Text: d.Message(),
Location: &esbuild.Location{
File: f.FileName(),
Line: line,
Column: column,
Length: d.Len(),
LineText: f.Text()[pos:d.End()],
},
Notes: []esbuild.Note{
{Text: d.Category().Name()},
{Text: fmt.Sprintf("%d", d.Code())},
},
})
}
if err != nil {
mainErr := esbuild.Message{Text: err.Error()}
result.Errors = append([]esbuild.Message{mainErr}, esbuildMessages...)
return result, nil
}
if len(esbuildMessages) > 0 {
result.Errors = esbuildMessages
return result, nil
}
result.Contents = &compiledJS
result.Loader = esbuild.LoaderJS
return result, nil
})
},
}
}
type CDelegate[F any] struct {
Func F
null F
Data unsafe.Pointer
dataDestroy C.FridaDestroyFunc
}
func NewCDelegate[F any](function F, data unsafe.Pointer, dataDestroy C.FridaDestroyFunc) *CDelegate[F] {
return &CDelegate[F]{Func: function, Data: data, dataDestroy: dataDestroy}
}
func (d *CDelegate[F]) Dispose() {
if d.dataDestroy != nil {
C.invoke_destroy_func(d.dataDestroy, d.Data)
}
d.Func = d.null
d.Data = nil
d.dataDestroy = nil
}
func main() {}
+7
View File
@@ -0,0 +1,7 @@
{
global:
_frida_compiler_backend_*;
local:
*;
};
+375
View File
@@ -0,0 +1,375 @@
import base64
import json
import os
import shutil
import struct
import subprocess
import sys
from pathlib import Path
from typing import List
def main(argv):
go_config = json.loads(base64.b64decode(argv[1]).decode("utf-8"))
output_dir, priv_dir, go, npm, *inputs = [Path(d).resolve() for d in argv[2:]]
try:
build_backend(go_config, inputs, output_dir, priv_dir, go, npm)
except subprocess.CalledProcessError as e:
print(e, file=sys.stderr)
print(
"Output:\n\t| " + "\n\t| ".join(e.output.strip().split("\n")),
file=sys.stderr,
)
sys.exit(2)
except Exception as e:
print(e, file=sys.stderr)
sys.exit(1)
def build_backend(
config: dict,
inputs: List[Path],
output_dir: Path,
priv_dir: Path,
go: Path,
npm: Path,
):
base_dir = min(inputs, key=lambda p: len(p.parts)).parent
for f in inputs:
dest = priv_dir / f.relative_to(base_dir)
dest.parent.mkdir(exist_ok=True)
shutil.copy(f, dest)
go_sources = [str(f.relative_to(base_dir)) for f in inputs if f.suffix == ".go"]
def run(*args):
return subprocess.run(
args,
cwd=priv_dir,
env=config["env"],
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
encoding="utf-8",
check=True,
)
run(npm, "install")
# run(npm, "link", "/home/oleavr/src/frida-fs")
mode = config["mode"]
backend_stem = "frida-compiler-backend"
if mode == "c-shared":
backend_stem += "-raw"
backend_a = priv_dir / f"{backend_stem}.a"
backend_shlib = priv_dir / (f"{backend_stem}" + config["shlib_suffix"])
backend_h = priv_dir / f"{backend_stem}.h"
extra_go_args = config["extra_go_args"].copy()
if mode == "c-shared":
version_script = priv_dir / "backend.version"
extra_go_args.append(f"-ldflags=-linkmode=external -extldflags=-Wl,--version-script={version_script}")
run(
go,
"build",
f"-buildmode={mode}",
"-o",
backend_a.name if mode == "c-archive" else backend_shlib.name,
"-buildvcs=false",
*extra_go_args,
*go_sources,
)
if mode == "c-archive":
symbols_to_scramble = detect_conflictful_symbols_in_archive(backend_a, config["nm"])
scramble_symbols_in_archive(backend_a, symbols_to_scramble, config["ranlib"])
if (mingw := config.get("mingw")) is not None and (abi := config["abi"]) in {
"x86",
"x86_64",
}:
prefix = Path(mingw["prefix"])
ar = config["ar"]
libmingwex_a = prefix / "lib" / "libmingwex.a"
if not libmingwex_a.exists():
libmingwex_a = prefix / mingw["triplet"] / "lib" / "libmingwex.a"
libgcc_objects = [
"_chkstk_ms.o",
]
run(*ar, "x", mingw["libcc"], *libgcc_objects)
gwex_objflavor = "64" if abi == "x86_64" else "32"
gwex_objects = [
f"lib{gwex_objflavor}_libmingwex_a-{name}.o"
for name in [
"dmisc",
"gdtoa",
"gmisc",
"mingw_fprintf",
"mingw_pformat",
"misc",
]
]
run(*ar, "x", libmingwex_a, *gwex_objects)
extra_objects = []
if abi == "x86_64":
run(*ar, "x", backend_a.name, "go.o")
sort_pdata_in_object(Path(priv_dir) / "go.o")
extra_objects.append("go.o")
run(*ar, "rs", backend_a.name, *libgcc_objects, *gwex_objects, *extra_objects)
shutil.copy(priv_dir / backend_a.name, output_dir / backend_a.name)
else:
shutil.copy(priv_dir / backend_shlib.name, output_dir / backend_shlib.name)
shutil.copy(priv_dir / backend_h.name, output_dir / backend_h.name)
def detect_conflictful_symbols_in_archive(
archive: Path, nm_cmd_array: List[str]
) -> List[str]:
result = []
for line in subprocess.run(
[*nm_cmd_array, str(archive)], capture_output=True, encoding="utf-8", check=True
).stdout.splitlines():
tokens = line.lstrip().split(" ")
if len(tokens) >= 3 and tokens[1] in {"S", "T"}:
symbol = tokens[2]
if all(sub not in symbol for sub in ("/", ".", ":", "frida")):
result.append(symbol)
return result
def scramble_symbols_in_archive(
archive: Path, symbols: List[str], ranlib_cmd_array: List[str]
):
data = archive.read_bytes()
for old_sym in symbols:
new_sym = roll_first_alpha(old_sym)
data = data.replace(old_sym.encode("ascii"), new_sym.encode("ascii"))
archive.write_bytes(data)
subprocess.run([*ranlib_cmd_array, str(archive)], check=True)
def roll_first_alpha(s: str) -> str:
chars = list(s)
for i, c in enumerate(chars):
if c.isalpha():
if c == "z":
chars[i] = "a"
elif c == "Z":
chars[i] = "A"
else:
chars[i] = chr(ord(c) + 1)
break
return "".join(chars)
# Work around the Go toolchain's almost-MSVC-compatible object files
# until our patch is merged upstream:
# https://go-review.googlesource.com/c/go/+/678795
def sort_pdata_in_object(object_file: Path):
data = bytearray(object_file.read_bytes())
# --- Parse COFF File Header (IMAGE_FILE_HEADER) ---
# Format: WORD Machine; WORD NumberOfSections;
# DWORD TimeDateStamp; DWORD PointerToSymbolTable;
# DWORD NumberOfSymbols; WORD SizeOfOptionalHeader;
# WORD Characteristics;
IMAGE_FILE_HEADER_FMT = "<HHLLLHH"
IMAGE_FILE_HEADER_SIZE = struct.calcsize(IMAGE_FILE_HEADER_FMT)
if len(data) < IMAGE_FILE_HEADER_SIZE:
print("Error: File too small to be a valid COFF object", file=sys.stderr)
return
(
machine,
number_of_sections,
time_date_stamp,
pointer_to_symbol_table,
number_of_symbols,
size_of_optional_header,
characteristics,
) = struct.unpack(IMAGE_FILE_HEADER_FMT, data[0:IMAGE_FILE_HEADER_SIZE])
# --- Parse Section Headers to find .pdata ---
# Each IMAGE_SECTION_HEADER is 40 bytes: Name[8], Misc(VirtualSize), VirtualAddress,
# SizeOfRawData, PointerToRawData, PointerToRelocations, PointerToLinenumbers,
# NumberOfRelocations, NumberOfLinenumbers, Characteristics
SECTION_HEADER_FMT = "<8sLLLLLLHHI"
SECTION_HEADER_SIZE = struct.calcsize(SECTION_HEADER_FMT)
section_table_offset = IMAGE_FILE_HEADER_SIZE + size_of_optional_header
pdata_section_index = None
pdata_pointer_to_raw = None
pdata_size_of_raw = None
pdata_pointer_to_relocs = None
pdata_number_of_relocs = None
# Keep all section headers for rewriting relocation entries later if needed
section_headers = []
for i in range(number_of_sections):
offset = section_table_offset + i * SECTION_HEADER_SIZE
section_data = data[offset : offset + SECTION_HEADER_SIZE]
(
name,
virtual_size,
virtual_address,
size_of_raw_data,
pointer_to_raw_data,
pointer_to_relocations,
pointer_to_linenumbers,
number_of_relocations,
number_of_linenumbers,
sec_characteristics,
) = struct.unpack(SECTION_HEADER_FMT, section_data)
section_name = name.rstrip(b"\x00").decode("utf-8")
section_headers.append(
{
"name": section_name,
"offset": offset,
"virtual_size": virtual_size,
"virtual_address": virtual_address,
"size_of_raw_data": size_of_raw_data,
"pointer_to_raw_data": pointer_to_raw_data,
"pointer_to_relocations": pointer_to_relocations,
"number_of_relocations": number_of_relocations,
}
)
if section_name == ".pdata":
pdata_section_index = i
pdata_pointer_to_raw = pointer_to_raw_data
pdata_size_of_raw = size_of_raw_data
pdata_pointer_to_relocs = pointer_to_relocations
pdata_number_of_relocs = number_of_relocations
if pdata_section_index is None:
print("Error: No .pdata section found in the object file", file=sys.stderr)
return
# --- Parse Symbol Table ---
# Each IMAGE_SYMBOL is 18 bytes: Name[8], Value (4 bytes), SectionNumber (2 bytes),
# Type (2 bytes), StorageClass (1 byte), NumberOfAuxSymbols (1 byte)
SYMBOL_TABLE_ENTRY_SIZE = 18
symbols = []
for sym_index in range(number_of_symbols):
sym_offset = pointer_to_symbol_table + sym_index * SYMBOL_TABLE_ENTRY_SIZE
entry = data[sym_offset : sym_offset + SYMBOL_TABLE_ENTRY_SIZE]
if len(entry) < SYMBOL_TABLE_ENTRY_SIZE:
print("Error: Truncated symbol table entry", file=sys.stderr)
return
# Unpack: Name (8s), Value (L), SectionNumber (h), Type (H), StorageClass (B), NumberOfAuxSymbols (B)
name_bytes, value, section_number, sym_type, storage_class, num_aux = (
struct.unpack("<8sLhHBB", entry)
)
# Decode name: if name_bytes[0:4] are zeros, use string from offset in string table
if name_bytes[:4] == b"\x00\x00\x00\x00":
str_table_offset = struct.unpack("<L", name_bytes[4:])[0]
# String table starts immediately after symbol table: size (4 bytes) + NUL-terminated strings
str_tab_start = (
pointer_to_symbol_table + number_of_symbols * SYMBOL_TABLE_ENTRY_SIZE
)
# Fetch the name from string table
str_offset = str_tab_start + str_table_offset
name_end = data.find(b"\x00", str_offset)
symbol_name = data[str_offset:name_end].decode("utf-8")
else:
symbol_name = name_bytes.partition(b"\x00")[0].decode("utf-8")
symbols.append(
{"name": symbol_name, "value": value, "section_number": section_number}
)
# --- Read original .pdata section raw data ---
pdata_data = data[pdata_pointer_to_raw : pdata_pointer_to_raw + pdata_size_of_raw]
if len(pdata_data) % 12 != 0:
print("Error: .pdata size is not a multiple of 12 bytes", file=sys.stderr)
return
num_entries = len(pdata_data) // 12
# --- Read relocation entries for .pdata ---
# Each IMAGE_RELOCATION is 10 bytes: VirtualAddress (4), SymbolTableIndex (4), Type (2)
RELOC_ENTRY_SIZE = 10
reloc_entries = []
reloc_table_start = pdata_pointer_to_relocs
for rindex in range(pdata_number_of_relocs):
reloff = reloc_table_start + rindex * RELOC_ENTRY_SIZE
entry = data[reloff : reloff + RELOC_ENTRY_SIZE]
if len(entry) < RELOC_ENTRY_SIZE:
print("Error: Truncated relocation entry", file=sys.stderr)
return
va, sym_index, rtype = struct.unpack("<LLH", entry)
reloc_entries.append(
{"virtual_address": va, "symbol_index": sym_index, "type": rtype}
)
# There should be 3 relocations per .pdata entry
if len(reloc_entries) != num_entries * 3:
print(
"Warning: Expected {} relocations but found {}".format(
num_entries * 3, len(reloc_entries)
),
file=sys.stderr,
)
# --- Associate each entry with its relocations and sorting key ---
entries = []
for i in range(num_entries):
entry_bytes = pdata_data[i * 12 : (i + 1) * 12]
entry_relocs = reloc_entries[i * 3 : i * 3 + 3]
# Sorting key: use symbol.Value of first relocation"s symbol index
sym_idx = entry_relocs[0]["symbol_index"]
if sym_idx < 0 or sym_idx >= number_of_symbols:
key = 0
else:
key = symbols[sym_idx]["value"]
entries.append({"entry_bytes": entry_bytes, "relocs": entry_relocs, "key": key})
# --- Sort entries by computed key ---
entries.sort(key=lambda x: x["key"])
# --- Build new .pdata data buffer ---
sorted_pdata = bytearray()
for e in entries:
sorted_pdata.extend(e["entry_bytes"])
# --- Build new relocation table buffer ---
new_reloc_buf = bytearray()
for new_i, e in enumerate(entries):
for reloc in e["relocs"]:
field_offset = reloc["virtual_address"] % 12
new_va = new_i * 12 + field_offset
packed = struct.pack("<LLH", new_va, reloc["symbol_index"], reloc["type"])
new_reloc_buf.extend(packed)
# --- Write back sorted .pdata and new relocations into data buffer ---
# Replace .pdata raw data
data[pdata_pointer_to_raw : pdata_pointer_to_raw + pdata_size_of_raw] = sorted_pdata
# Replace relocation entries
data[pdata_pointer_to_relocs : pdata_pointer_to_relocs + len(new_reloc_buf)] = (
new_reloc_buf
)
# --- Emit the fixed object file ---
object_file.write_bytes(data)
if __name__ == "__main__":
main(sys.argv)
@@ -1,3 +1,2 @@
[resource-compiler]
namespace = Frida.Data.Compiler
compress = *.js:text:7; *.bin:generic:7
-3
View File
@@ -1,3 +0,0 @@
[resource-compiler]
namespace = Frida.Data.Compiler
compress = *.js:text:11; *.bin:generic:11
+288 -338
View File
@@ -5,59 +5,52 @@ namespace Frida {
public signal void output (string bundle);
public signal void diagnostics (Variant diagnostics);
public DeviceManager manager {
get;
construct;
private size_t watch_session_handle = 0;
private Gee.Queue<Diagnostic> pending_diagnostics = new Gee.ArrayQueue<Diagnostic> ();
private MainContext main_context;
// TODO: Remove the DeviceManager parameter.
public Compiler (DeviceManager? manager = null) {
Object ();
}
#if HAVE_COMPILER_BACKEND
private Promise<Agent>? load_request;
private Gee.Map<uint, MonitorEntry> monitors = new Gee.HashMap<uint, MonitorEntry> ();
private Gee.Set<MonitorEntry> dirty_monitors = new Gee.HashSet<MonitorEntry> ();
private TimeoutSource? monitor_flush_timer;
private Cancellable io_cancellable = new Cancellable ();
#endif
public Compiler (DeviceManager manager) {
Object (manager: manager);
static construct {
CompilerBackend.init ();
}
#if HAVE_COMPILER_BACKEND
public override void dispose () {
if (load_request != null)
close.begin ();
base.dispose ();
construct {
main_context = Frida.get_main_context ();
}
private async void close () {
try {
var agent = yield get_agent (null);
yield agent.close (null);
} catch (GLib.Error e) {
}
load_request = null;
if (monitor_flush_timer != null) {
monitor_flush_timer.destroy ();
monitor_flush_timer = null;
}
foreach (var entry in monitors.values)
detach_monitor_entry (entry);
monitors.clear ();
~Compiler () {
cancel_watch ();
}
#endif
public async string build (string entrypoint, BuildOptions? options = null, Cancellable? cancellable = null)
throws Error, IOError {
#if HAVE_COMPILER_BACKEND
var agent = yield get_agent (cancellable);
CompilerBackend.check_available ();
BuildOptions opts = (options != null) ? options : new BuildOptions ();
string project_root = compute_project_root (entrypoint, opts);
starting ();
try {
string bundle = yield agent.build (entrypoint, options, cancellable);
string? bundle = null;
string? error_message = null;
CompilerBackend.BuildCompleteFunc on_complete = (b, e) => {
bundle = b;
error_message = e;
schedule_on_frida_thread (build.callback);
};
CompilerBackend.build (project_root, entrypoint, opts.output_format, opts.bundle_format,
(size_t) (opts.type_check == NONE), (size_t) (opts.source_maps == INCLUDED),
(size_t) (opts.compression == TERSER), (owned) on_complete, on_diagnostic);
yield;
if (error_message != null)
throw new Error.INVALID_ARGUMENT ("%s", error_message);
output (bundle);
@@ -65,9 +58,6 @@ namespace Frida {
} finally {
finished ();
}
#else
throw_not_supported ();
#endif
}
public string build_sync (string entrypoint, BuildOptions? options = null, Cancellable? cancellable = null)
@@ -89,13 +79,38 @@ namespace Frida {
public async void watch (string entrypoint, WatchOptions? options = null, Cancellable? cancellable = null)
throws Error, IOError {
#if HAVE_COMPILER_BACKEND
var agent = yield get_agent (cancellable);
CompilerBackend.check_available ();
yield agent.watch (entrypoint, options, cancellable);
#else
throw_not_supported ();
#endif
WatchOptions opts = (options != null) ? options : new WatchOptions ();
string project_root = compute_project_root (entrypoint, opts);
cancel_watch ();
size_t session_handle = 0;
string? error_message = null;
CompilerBackend.WatchReadyFunc on_ready = (h, e) => {
session_handle = h;
error_message = e;
schedule_on_frida_thread (watch.callback);
};
CompilerBackend.watch (project_root, entrypoint, opts.output_format, opts.bundle_format,
(size_t) (opts.type_check == NONE), (size_t) (opts.source_maps == INCLUDED),
(size_t) (opts.compression == TERSER), (owned) on_ready, on_starting, on_finished,
on_output, on_diagnostic);
yield;
if (error_message != null)
throw new Error.INVALID_ARGUMENT ("%s", error_message);
watch_session_handle = session_handle;
}
private void cancel_watch () {
if (watch_session_handle != 0) {
CompilerBackend.WatchSession.dispose (watch_session_handle);
watch_session_handle = 0;
}
}
public void watch_sync (string entrypoint, WatchOptions? options = null, Cancellable? cancellable = null)
@@ -115,343 +130,238 @@ namespace Frida {
}
}
#if HAVE_COMPILER_BACKEND
private void on_watch_add (uint id, string path, string type, int64 polling_interval) {
var file = File.parse_name (path);
private void on_starting () {
schedule_on_frida_thread (() => {
starting ();
return Source.REMOVE;
});
}
GLib.FileMonitor monitor;
try {
if (type == "file")
monitor = file.monitor_file (FileMonitorFlags.SEND_MOVED, io_cancellable);
else if (type == "directory")
monitor = file.monitor_directory (FileMonitorFlags.NONE, io_cancellable);
else
assert_not_reached ();
} catch (GLib.Error e) {
return;
private void on_finished () {
schedule_on_frida_thread (() => {
finished ();
return Source.REMOVE;
});
}
private void on_output (owned string bundle) {
schedule_on_frida_thread (() => {
output (bundle);
return Source.REMOVE;
});
}
private void on_diagnostic (owned string category, int code, owned string? path, int line, int character,
owned string text) {
var diag = new Diagnostic () {
category = category,
code = code,
path = path,
line = line,
character = character,
text = text,
};
bool schedule_emit = false;
lock (pending_diagnostics) {
schedule_emit = pending_diagnostics.is_empty;
pending_diagnostics.add (diag);
}
if (polling_interval != 0)
monitor.rate_limit = (int) polling_interval;
var entry = new MonitorEntry (id, monitor);
entry.file_changed.connect (on_file_changed);
monitors[id] = entry;
}
private void on_watch_remove (uint id) {
MonitorEntry? entry;
if (monitors.unset (id, out entry))
detach_monitor_entry (entry);
}
private void detach_monitor_entry (MonitorEntry entry) {
dirty_monitors.remove (entry);
entry.file_changed.disconnect (on_file_changed);
entry.destroy ();
}
private void on_file_changed (MonitorEntry entry) {
dirty_monitors.add (entry);
if (monitor_flush_timer == null) {
var source = new TimeoutSource (50);
source.set_callback (on_monitor_flush_tick);
source.attach (MainContext.get_thread_default ());
monitor_flush_timer = source;
if (schedule_emit) {
schedule_on_frida_thread (() => {
emit_pending_diagnostics ();
return Source.REMOVE;
});
}
}
private bool on_monitor_flush_tick () {
var settled = new Gee.ArrayList<MonitorEntry> ();
var now = get_monotonic_time ();
settled.add_all_iterator (dirty_monitors.filter (m => now - m.last_change >= 50000));
Agent agent = load_request.future.value;
foreach (var entry in settled) {
agent.notify_file_changed (entry.id, entry.state, io_cancellable);
dirty_monitors.remove (entry);
private void emit_pending_diagnostics () {
var batch = new Gee.ArrayList<Diagnostic> ();
lock (pending_diagnostics) {
batch.add_all (pending_diagnostics);
pending_diagnostics.clear ();
}
if (!dirty_monitors.is_empty)
return Source.CONTINUE;
var builder = new VariantBuilder (new VariantType.array (VariantType.VARDICT));
monitor_flush_timer = null;
return Source.REMOVE;
}
private async Agent get_agent (Cancellable? cancellable) throws Error, IOError {
Future<Agent> future;
if (load_request != null) {
future = load_request.future;
} else {
load_request = new Promise<Agent> ();
future = load_request.future;
load_agent.begin ();
foreach (var d in batch) {
builder.open (VariantType.VARDICT);
builder.add ("{sv}", "category", new Variant.string (d.category));
builder.add ("{sv}", "code", new Variant.int64 (d.code));
if (d.path != null) {
var b = new VariantBuilder (VariantType.VARDICT);
b.add ("{sv}", "path", new Variant.string (d.path));
b.add ("{sv}", "line", new Variant.int64 (d.line));
b.add ("{sv}", "character", new Variant.int64 (d.character));
builder.add ("{sv}", "file", b.end ());
}
builder.add ("{sv}", "text", new Variant.string (d.text));
builder.close ();
}
return yield future.wait_async (cancellable);
diagnostics (builder.end ());
}
private async void load_agent () {
try {
var device = yield manager.get_device_by_type (LOCAL, 0, io_cancellable);
var session = yield device.get_host_session (io_cancellable);
var agent = new Agent (this, (LocalHostSession) session);
load_request.resolve (agent);
} catch (GLib.Error e) {
if ((e is Error || e is IOError.CANCELLED))
e = new Error.NOT_SUPPORTED ("%s", e.message);
load_request.reject (e);
load_request = null;
}
}
#else
[NoReturn]
private void throw_not_supported () throws Error {
throw new Error.NOT_SUPPORTED ("Compiler backend disabled at build-time");
}
#endif
private T create<T> () {
return Object.new (typeof (T), parent: this);
}
protected void schedule_on_frida_thread (owned SourceFunc function) {
var source = new IdleSource ();
source.set_callback ((owned) function);
source.attach (main_context);
}
private class Diagnostic {
public string category;
public int code;
public string? path;
public int line;
public int character;
public string text;
}
private abstract class CompilerTask<T> : AsyncTask<T> {
public weak Compiler parent {
get;
construct;
}
}
}
namespace CompilerBackend {
private void init () {
#if HAVE_COMPILER_BACKEND
private class Agent : InternalAgent {
public weak Compiler parent {
get;
construct;
}
private Promise<string> source_request = new Promise<string> ();
private Promise<Bytes?> snapshot_request = new Promise<Bytes?> ();
public Agent (Compiler parent, LocalHostSession host_session) {
Object (
parent: parent,
host_session: host_session,
#if HAVE_V8
script_runtime: ScriptRuntime.V8
#if COMPILER_BACKEND_STATIC_COMPILATION
_init_go_runtime ();
build = (BuildFunc) _build;
watch = (WatchFunc) _watch;
WatchSession.dispose = (WatchSession.DisposeFunc) WatchSession._dispose;
#else
script_runtime: ScriptRuntime.DEFAULT
#endif
);
}
unowned uint8[] backend_so = Frida.Data.Compiler.get_frida_compiler_backend_so_blob ().data;
construct {
load_resources ();
}
FileDescriptor fd;
if (MemoryFileDescriptor.is_supported ()) {
fd = MemoryFileDescriptor.from_bytes ("frida-compiler-backend.so", new Bytes.static (backend_so));
} else {
string name_used;
try {
fd = new FileDescriptor (FileUtils.open_tmp ("frida-compiler-backend-XXXXXX.so", out name_used));
FileUtils.unlink (name_used);
private void load_resources () {
new Thread<void> ("compiler-agent-loader", () => {
var agent_js_blob = Data.Compiler.get_agent_js_blob ();
Bytes agent_js_bytes = decompress (agent_js_blob.data, agent_js_blob.uncompressed_size);
source_request.resolve ((string) agent_js_bytes.get_data ());
var output = new UnixOutputStream (fd.handle, false);
output.write_all (backend_so, null);
var snapshot_blob = Data.Compiler.get_snapshot_bin_blob ();
Bytes snapshot = decompress (snapshot_blob.data, snapshot_blob.uncompressed_size);
snapshot_request.resolve ((snapshot.get_size () != 0) ? snapshot : null);
});
}
public async string build (string entrypoint, BuildOptions? options, Cancellable? cancellable)
throws Error, IOError {
BuildOptions opts = (options != null) ? options : new BuildOptions ();
Json.Node bundle = yield call ("build", new Json.Node[] {
new Json.Node.alloc ().init_string (compute_project_root (entrypoint, opts)),
new Json.Node.alloc ().init_string (entrypoint),
new Json.Node.alloc ().init_string (opts.source_maps.to_nick ()),
new Json.Node.alloc ().init_string (opts.compression.to_nick ()),
}, null, cancellable);
return bundle.get_string ();
}
public async void watch (string entrypoint, WatchOptions? options, Cancellable? cancellable)
throws Error, IOError {
WatchOptions opts = (options != null) ? options : new WatchOptions ();
yield call ("watch", new Json.Node[] {
new Json.Node.alloc ().init_string (compute_project_root (entrypoint, opts)),
new Json.Node.alloc ().init_string (entrypoint),
new Json.Node.alloc ().init_string (opts.source_maps.to_nick ()),
new Json.Node.alloc ().init_string (opts.compression.to_nick ()),
}, null, cancellable);
}
private static string compute_project_root (string entrypoint, CompilerOptions options) {
string? project_root = options.project_root;
if (project_root != null)
return project_root;
if (Path.is_absolute (entrypoint))
return Path.get_dirname (entrypoint);
return Environment.get_current_dir ();
}
public void notify_file_changed (uint id, FileState state, Cancellable? cancellable) {
var notification = new Json.Builder ();
notification
.begin_object ()
.set_member_name ("type")
.add_string_value ("watch:change")
.set_member_name ("id")
.add_int_value (id)
.set_member_name ("state")
.add_string_value (Marshal.enum_to_nick<FileState> (state))
.end_object ();
post.begin (notification.get_root (), cancellable);
}
protected override async uint get_target_pid (Cancellable? cancellable) throws Error, IOError {
return 0;
}
protected override async string? load_source (Cancellable? cancellable) throws Error, IOError {
return yield source_request.future.wait_async (cancellable);
}
protected override async Bytes? load_snapshot (Cancellable? cancellable, out SnapshotTransport transport)
throws Error, IOError {
transport = SHARED_MEMORY;
return yield snapshot_request.future.wait_async (cancellable);
}
protected override void on_event (string type, Json.Array event) {
if (type == "diagnostics") {
on_build_diagnostics (event.get_array_element (1));
} else if (type == "watch:compilation-starting") {
parent.starting ();
} else if (type == "watch:compilation-finished") {
parent.finished ();
} else if (type == "watch:bundle-updated") {
on_watch_bundle_updated (event.get_string_element (1));
} else if (type == "watch:add") {
parent.on_watch_add ((uint) event.get_int_element (1), event.get_string_element (2),
event.get_string_element (3), event.get_int_element (4));
} else if (type == "watch:remove") {
parent.on_watch_remove ((uint) event.get_int_element (1));
} else {
Posix.lseek (fd.handle, 0, Posix.SEEK_SET);
} catch (GLib.Error e) {
assert_not_reached ();
}
}
private void on_build_diagnostics (Json.Array diagnostics) {
uint n = diagnostics.get_length ();
var builder = new VariantBuilder (new VariantType.array (VariantType.VARDICT));
for (uint i = 0; i != n; i++) {
var diag = diagnostics.get_array_element (i);
builder.open (VariantType.VARDICT);
builder.add ("{sv}", "category", new Variant.string (diag.get_string_element (0)));
builder.add ("{sv}", "code", new Variant.int64 (diag.get_int_element (1)));
if (!diag.get_null_element (2)) {
var file = diag.get_array_element (2);
var b = new VariantBuilder (VariantType.VARDICT);
b.add ("{sv}", "path", new Variant.string (file.get_string_element (0)));
b.add ("{sv}", "line", new Variant.int64 (file.get_int_element (1)));
b.add ("{sv}", "character", new Variant.int64 (file.get_int_element (2)));
builder.add ("{sv}", "file", b.end ());
}
builder.add ("{sv}", "text", new Variant.string (diag.get_string_element (3)));
builder.close ();
}
parent.diagnostics (builder.end ());
}
private void on_watch_bundle_updated (string bundle) {
parent.output (bundle);
}
private static Bytes decompress (uint8[] data, uint uncompressed_size) {
var decoder = new Brotli.Decoder ();
decoder.set_parameter (LARGE_WINDOW, 1);
uint8[] uncompressed_data = new uint8[uncompressed_size + 1];
size_t available_in = data.length;
size_t available_out = uncompressed_size;
uint8 * next_in = data;
uint8 * next_out = uncompressed_data;
decoder.decompress_stream (&available_in, &next_in, &available_out, &next_out);
uncompressed_data.length = (int) (next_out - (uint8 *) uncompressed_data);
return new Bytes.take ((owned) uncompressed_data);
Module backend;
try {
backend = new Module ("/proc/self/fd/%d".printf (fd.handle), LOCAL);
} catch (ModuleError e) {
assert_not_reached ();
}
build = resolve_symbol (backend, "_frida_compiler_backend_build");
watch = resolve_symbol (backend, "_frida_compiler_backend_watch");
WatchSession.dispose = resolve_symbol (backend, "_frida_compiler_backend_watch_session_dispose");
#endif
#endif
}
private class MonitorEntry : Object {
public signal void file_changed ();
public uint id;
public GLib.FileMonitor monitor;
public FileState state = PRISTINE;
public int64 last_change = -1;
public MonitorEntry (uint id, GLib.FileMonitor monitor) {
this.id = id;
this.monitor = monitor;
monitor.changed.connect (on_file_changed);
}
public void destroy () {
monitor.changed.disconnect (on_file_changed);
monitor.cancel ();
}
private void on_file_changed (File file, File? other_file, FileMonitorEvent event) {
switch (event) {
case CREATED:
state = PRISTINE;
break;
case CHANGED:
if (state != PRISTINE)
state = MODIFIED;
break;
case DELETED:
case MOVED:
state = DELETED;
break;
default:
return;
}
last_change = get_monotonic_time ();
file_changed ();
}
private void check_available () throws Error {
if (build == null)
throw new Error.NOT_SUPPORTED ("Compiler backend disabled at build-time");
}
private enum FileState {
PRISTINE,
MODIFIED,
DELETED,
private BuildFunc? build;
private WatchFunc? watch;
[CCode (has_target = false)]
private delegate void BuildFunc (string project_root, string entrypoint, OutputFormat output_format,
BundleFormat bundle_format, size_t disable_type_check, size_t source_map, size_t compress,
owned BuildCompleteFunc on_complete, DiagnosticFunc on_diagnostic);
[CCode (has_target = false)]
private delegate void WatchFunc (string project_root, string entrypoint, OutputFormat output_format,
BundleFormat bundle_format, size_t disable_type_check, size_t source_map, size_t compress,
owned WatchReadyFunc on_ready, StartingFunc on_starting, FinishedFunc on_finished, OutputFunc on_output,
DiagnosticFunc on_diagnostic);
#if COMPILER_BACKEND_STATIC_COMPILATION
private extern void _init_go_runtime ();
private extern void _build ();
private extern void _watch ();
#endif
namespace WatchSession {
[CCode (has_target = false)]
private delegate void DisposeFunc (size_t handle);
private DisposeFunc? dispose;
#if COMPILER_BACKEND_STATIC_COMPILATION
private extern void _dispose ();
#endif
}
private delegate void BuildCompleteFunc (owned string? bundle, owned string? error_message);
private delegate void WatchReadyFunc (size_t session_handle, owned string? error_message);
private delegate void StartingFunc ();
private delegate void FinishedFunc ();
private delegate void OutputFunc (owned string bundle);
private delegate void DiagnosticFunc (owned string category, int code, owned string? path, int line, int character,
owned string text);
#if HAVE_COMPILER_BACKEND && !COMPILER_BACKEND_STATIC_COMPILATION
private static T resolve_symbol<T> (Module m, string name) {
void * address;
if (!m.symbol (name, out address))
assert_not_reached ();
return (T) address;
}
#endif
}
private string compute_project_root (string entrypoint, CompilerOptions options) {
string? project_root = options.project_root;
if (project_root != null)
return project_root;
if (Path.is_absolute (entrypoint))
return Path.get_dirname (entrypoint);
return Environment.get_current_dir ();
}
public class CompilerOptions : Object {
public string? project_root {
get;
set;
}
public OutputFormat output_format {
get;
set;
default = UNESCAPED;
}
public BundleFormat bundle_format {
get;
set;
default = ESM;
}
public TypeCheckMode type_check {
get;
set;
default = FULL;
}
public SourceMaps source_maps {
get;
set;
@@ -471,6 +381,46 @@ namespace Frida {
public sealed class WatchOptions : CompilerOptions {
}
public enum OutputFormat {
UNESCAPED,
HEX_BYTES,
C_STRING;
public static OutputFormat from_nick (string nick) throws Error {
return Marshal.enum_from_nick<OutputFormat> (nick);
}
public string to_nick () {
return Marshal.enum_to_nick<OutputFormat> (this);
}
}
public enum BundleFormat {
ESM,
IIFE;
public static BundleFormat from_nick (string nick) throws Error {
return Marshal.enum_from_nick<BundleFormat> (nick);
}
public string to_nick () {
return Marshal.enum_to_nick<BundleFormat> (this);
}
}
public enum TypeCheckMode {
FULL,
NONE;
public static TypeCheckMode from_nick (string nick) throws Error {
return Marshal.enum_from_nick<TypeCheckMode> (nick);
}
public string to_nick () {
return Marshal.enum_to_nick<TypeCheckMode> (this);
}
}
public enum SourceMaps {
INCLUDED,
OMITTED;
-91
View File
@@ -1,91 +0,0 @@
from pathlib import Path
import shutil
import subprocess
import sys
INPUTS = [
"agent-entrypoint.js",
"agent-core.ts",
"agent-warmup.js",
"package.json",
"package-lock.json",
"tsconfig.json",
"rollup.config.agent-core.ts",
"rollup.config.typescript.ts",
]
def main(argv):
output_dir, priv_dir, input_dir, npm, v8_mksnapshot = [Path(d).resolve() if d else None for d in argv[1:6]]
host_os_family, host_arch, host_cpu_mode = argv[6:9]
try:
generate_agent(output_dir, priv_dir, input_dir, npm, v8_mksnapshot, host_os_family, host_arch, host_cpu_mode)
except subprocess.CalledProcessError as e:
print(e, file=sys.stderr)
print("Output:\n\t| " + "\n\t| ".join(e.output.strip().split("\n")), file=sys.stderr)
sys.exit(2)
except Exception as e:
print(e, file=sys.stderr)
sys.exit(1)
def generate_agent(output_dir, priv_dir, input_dir, npm, v8_mksnapshot, host_os_family, host_arch, host_cpu_mode):
entrypoint = input_dir / "agent-entrypoint.js"
priv_dir.mkdir(exist_ok=True)
for name in INPUTS:
if name == "agent-entrypoint.js":
continue
shutil.copy(input_dir / name, priv_dir / name)
run_kwargs = {
"cwd": priv_dir,
"stdout": subprocess.PIPE,
"stderr": subprocess.STDOUT,
"encoding": "utf-8",
"check": True,
}
subprocess.run([npm, "install"], **run_kwargs)
#subprocess.run([npm, "link", "/Users/oleavr/src/frida-compile"], **run_kwargs)
components = ["typescript", "agent-core"]
for component in components:
subprocess.run([
npm, "run", "build:" + component,
"--",
"--environment", f"FRIDA_HOST_OS_FAMILY:{host_os_family},FRIDA_HOST_ARCH:{host_arch},FRIDA_HOST_CPU_MODE:{host_cpu_mode}",
"--silent",
],
**run_kwargs)
chunks = []
for component in components:
script = (priv_dir / f"{component}.js").read_text(encoding="utf-8")
chunks.append(script)
components_source = "\n".join(chunks)
agent = output_dir / "agent.js"
snapshot = output_dir / "snapshot.bin"
if v8_mksnapshot is not None:
shutil.copy(entrypoint, agent)
(priv_dir / "embed.js").write_text(components_source, encoding="utf-8")
subprocess.run([
v8_mksnapshot,
"--turbo-instruction-scheduling",
f"--startup-blob={snapshot}",
"embed.js",
input_dir / "agent-warmup.js",
],
**run_kwargs)
else:
agent.write_text("\n".join([
components_source,
entrypoint.read_text(encoding="utf-8"),
]), encoding="utf-8")
snapshot.write_bytes(b"")
if __name__ == "__main__":
main(sys.argv)
+14
View File
@@ -0,0 +1,14 @@
module github.com/frida/frida-core-compiler
go 1.24.3
require (
github.com/evanw/esbuild v0.25.5
github.com/frida/typescript-go v0.0.0-20250601212135-a4721f45f19c
)
require (
github.com/dlclark/regexp2 v1.11.5 // indirect
github.com/go-json-experiment/json v0.0.0-20250517221953-25912455fbc8 // indirect
golang.org/x/sys v0.33.0 // indirect
)
+17
View File
@@ -0,0 +1,17 @@
github.com/dlclark/regexp2 v1.11.5 h1:Q/sSnsKerHeCkc/jSTNq1oCm7KiVgUMZRDUoRu0JQZQ=
github.com/dlclark/regexp2 v1.11.5/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
github.com/evanw/esbuild v0.25.5 h1:E+JpeY5S/1LFmnX1vtuZqUKT7qDVcfXdhzMhM3uIKFs=
github.com/evanw/esbuild v0.25.5/go.mod h1:D2vIQZqV/vIf/VRHtViaUtViZmG7o+kKmlBfVQuRi48=
github.com/frida/typescript-go v0.0.0-20250601212135-a4721f45f19c h1:IWBI9AwSFLWymI4enx1jrAw0E4H2E+qHwsihv+AxSoE=
github.com/frida/typescript-go v0.0.0-20250601212135-a4721f45f19c/go.mod h1:L4RMzD/pFBl7CqIf9XTrX41RO2xcok3OOVVcowv0H4k=
github.com/go-json-experiment/json v0.0.0-20250517221953-25912455fbc8 h1:o8UqXPI6SVwQt04RGsqKp3qqmbOfTNMqDrWsc4O47kk=
github.com/go-json-experiment/json v0.0.0-20250517221953-25912455fbc8/go.mod h1:TiCD2a1pcmjd7YnhGH0f/zKNcCD06B029pHhzV23c2M=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/peter-evans/patience v0.3.0 h1:rX0JdJeepqdQl1Sk9c9uvorjYYzL2TfgLX1adqYm9cA=
github.com/peter-evans/patience v0.3.0/go.mod h1:Kmxu5sY1NmBLFSStvXjX1wS9mIv7wMcP/ubucyMOAu0=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
gotest.tools/v3 v3.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q=
gotest.tools/v3 v3.5.2/go.mod h1:LtdLGcnqToBH83WByAAi/wiwSFCArdFIUV/xxN4pcjA=
+45 -41
View File
@@ -1,61 +1,65 @@
compiler_sources = files(
'compiler.vala',
'backend-glue.c',
)
if have_compiler_backend
compiler_mksnapshot = generate_compiler_snapshot ? v8_mksnapshot : ''
compiler_agent = custom_target('frida-compiler-agent',
compiler_backend = custom_target('frida-compiler-backend',
input: [
'agent-entrypoint.js',
'agent-core.ts',
'agent-warmup.js',
'go.mod',
'go.sum',
'backend.go',
'backend.version',
'tscompiler.go',
'tsconfig.go',
'shims.go',
'package.json',
'package-lock.json',
'tsconfig.json',
'rollup.config.agent-core.ts',
'rollup.config.typescript.ts',
],
output: [
'agent.js',
'snapshot.bin',
'frida-compiler-backend' + (compiler_backend_static_compilation ? '.a' : ('-raw' + shlib_suffix)),
'frida-compiler-backend.h',
],
command: [
python,
files('generate-agent.py'),
files('build-backend.py'),
go_config,
meson.current_build_dir(),
'@PRIVATE_DIR@',
meson.current_source_dir(),
go,
npm,
compiler_mksnapshot,
host_os_family,
host_arch_gumjs,
host_cpu_mode,
'@INPUT@',
],
)
compiler_data = custom_target('frida-data-compiler',
input: [
'compiler.resources.' + frida_profile,
compiler_agent,
],
output: [
'frida-data-compiler.vapi',
'frida-data-compiler.h',
'frida-data-compiler.c',
'frida-data-compiler-blob' + resource_blob_extension,
'frida-data-compiler-agent.js.br',
'frida-data-compiler-snapshot.bin.br',
],
command: [
resource_compiler_cmd_array,
'-c', '@INPUT0@',
'-o', meson.current_build_dir() / 'frida-data-compiler',
'@INPUT1@',
'@INPUT2@',
],
)
compiler_sources += compiler_data
if compiler_backend_static_compilation
backend_libs += compiler_backend[0]
else
filename = 'frida-compiler-backend' + shlib_suffix
identity = (host_os_family == 'darwin') ? 'FridaCompilerBackend' : filename
compiler_backend_shlib = custom_target('frida-compiler-backend-shlib',
input: compiler_backend[0],
output: filename,
command: post_process + ['shared-library', identity, 'elf-cleaner:off'],
)
backend_vala_args_private += '--pkg=libbrotlidec'
backend_deps_private += brotlidec_dep
compiler_data = custom_target('frida-data-compiler',
input: [
'compiler.resources',
compiler_backend_shlib,
],
output: [
'frida-data-compiler.vapi',
'frida-data-compiler.h',
'frida-data-compiler.c',
'frida-data-compiler-blob' + resource_blob_extension,
],
command: [
resource_compiler_cmd_array,
'-c', '@INPUT0@',
'-o', meson.current_build_dir() / 'frida-data-compiler',
'@INPUT1@',
],
)
backend_sources += compiler_data
endif
endif
+99 -1756
View File
File diff suppressed because it is too large. Load diff
+30 -21
View File
@@ -1,27 +1,36 @@
{
"name": "frida-compiler-agent",
"name": "frida-compiler-shims",
"version": "1.0.0",
"description": "Agent used by Frida's compiler",
"main": "agent.ts",
"scripts": {
"build:typescript": "rollup --config rollup.config.typescript.ts --configPlugin typescript",
"build:agent-core": "rollup --config rollup.config.agent-core.ts --configPlugin typescript"
},
"description": "Shims used by Frida's compiler",
"private": true,
"dependencies": {
"@frida/crosspath": "3.0.0",
"frida-compile": "17.0.0",
"frida-fs": "6.0.0"
},
"devDependencies": {
"@frida/rollup-plugin-node-polyfills": "^1.0.3",
"@rollup/plugin-node-resolve": "^14.1.0",
"@rollup/plugin-replace": "^4.0.0",
"@rollup/plugin-typescript": "^8.3.4",
"@frida/assert": "^3.0.2",
"@frida/base64-js": "^2.0.3",
"@frida/buffer": "^7.0.4",
"@frida/crypto": "^1.0.1",
"@frida/diagnostics_channel": "^1.0.0",
"@frida/events": "^4.0.4",
"@frida/http": "^4.0.2",
"@frida/http-parser-js": "^1.0.0",
"@frida/https": "^1.0.0",
"@frida/ieee754": "^2.0.2",
"@frida/net": "^5.0.0",
"@frida/os": "^1.0.2",
"@frida/path": "^2.0.3",
"@frida/process": "^1.2.1",
"@frida/punycode": "^3.0.0",
"@frida/querystring": "^1.0.0",
"@frida/readable-stream": "^4.1.3",
"@frida/reserved-words": "^1.0.0",
"@frida/stream": "^1.0.2",
"@frida/string_decoder": "^2.0.0",
"@frida/timers": "^3.0.0",
"@frida/tty": "^1.0.0",
"@frida/url": "^1.0.2",
"@frida/util": "^1.0.3",
"@frida/vm": "^2.0.0",
"@types/frida-gum": "19.0.0",
"@types/glob": "^8.0.0",
"@types/node": "18.7.23",
"glob": "^8.0.3",
"rollup": "^2.79.1",
"rollup-plugin-terser": "^7.0.2"
"@types/node": "18.19.103",
"frida-fs": "7.0.0"
}
}
-184
View File
@@ -1,184 +0,0 @@
import crosspath from "@frida/crosspath";
import fs from "fs";
import { sync as glob } from "glob";
import replace from "@rollup/plugin-replace";
import resolve from "@rollup/plugin-node-resolve";
import typescript from "@rollup/plugin-typescript";
import polyfills from "@frida/rollup-plugin-node-polyfills";
import { terser } from "rollup-plugin-terser";
import { defineConfig } from "rollup";
import type rollup from "rollup";
export default defineConfig({
input: "agent-core.ts",
output: {
file: "agent-core.js",
format: "umd",
name: "FridaCompilerAgentCore",
generatedCode: {
preset: "es2015",
},
strict: false,
interop: "default",
globals: {
"typescript": "ts",
},
},
plugins: [
typescript(),
replace({
preventAssignment: true,
values: computeSubstitutionValues(),
}),
stubTsImportPlugin(),
polyfills(),
resolve(),
/*
terser({
ecma: 2020,
compress: {
module: true,
global_defs: {
"process.env.FRIDA_COMPILE": true
},
},
mangle: {
module: true,
},
}),
*/
],
});
function computeSubstitutionValues() {
const hostOsFamily = process.env.FRIDA_HOST_OS_FAMILY;
if (hostOsFamily === undefined) {
throw new Error("missing FRIDA_HOST_OS_FAMILY");
}
const hostArch = process.env.FRIDA_HOST_ARCH;
if (hostArch === undefined) {
throw new Error("missing FRIDA_HOST_ARCH");
}
const hostCpuMode = process.env.FRIDA_HOST_CPU_MODE;
if (hostCpuMode === undefined) {
throw new Error("missing FRIDA_HOST_CPU_MODE");
}
const outputDir = __dirname;
const compilerDir = crosspath.join(__dirname, "node_modules", "frida-compile");
let usingLinkedCompiler = false;
try {
usingLinkedCompiler = fs.statSync(crosspath.join(compilerDir, "node_modules")).isDirectory();
} catch (e) {
}
const assetParentDir = usingLinkedCompiler ? compilerDir : outputDir;
const assetModulesDir = crosspath.join(assetParentDir, "node_modules");
const shimDirs = [
["@frida", "assert"],
["@frida", "base64-js"],
["@frida", "buffer"],
["@frida", "crypto"],
["@frida", "diagnostics_channel"],
["@frida", "events"],
["@frida", "http"],
["@frida", "http-parser-js"],
["@frida", "https"],
["@frida", "ieee754"],
["@frida", "net"],
["@frida", "os"],
["@frida", "path"],
["@frida", "process"],
["@frida", "punycode"],
["@frida", "querystring"],
["@frida", "readable-stream"],
["@frida", "stream"],
["@frida", "string_decoder"],
["@frida", "timers"],
["@frida", "tty"],
["@frida", "url"],
["@frida", "util"],
["@frida", "vm"],
["frida-fs"],
];
const typeDirs = [
["@types", "node"],
["@types", "frida-gum"],
];
const assets: string[] = [];
for (const shimDir of shimDirs) {
assets.push(...glob(crosspath.join(assetModulesDir, ...shimDir, "package.json")));
assets.push(...glob(crosspath.join(assetModulesDir, ...shimDir, "**", "*.js")));
}
for (const typeDir of typeDirs) {
assets.push(...glob(crosspath.join(assetModulesDir, ...typeDir, "package.json")));
assets.push(...glob(crosspath.join(assetModulesDir, ...typeDir, "**", "*.d.ts")));
}
assets.push(...glob(crosspath.join(compilerDir, "ext", "lib.es*.d.ts")));
assets.push(...glob(crosspath.join(compilerDir, "ext", "lib.decorators*.d.ts")));
const ignoredAssetFiles = new Set([
"@frida/process/browser.js",
]);
const agentDirectories = new Set<string>();
const agentFiles = new Map<string, string>();
for (const assetPath of assets) {
let assetRelpath = assetPath.substring(assetParentDir.length);
if (usingLinkedCompiler && assetRelpath.startsWith("/ext/")) {
assetRelpath = crosspath.join("/", "node_modules", "frida-compile", assetRelpath.substring(1));
}
const identifier = assetRelpath.split("/").slice(2).join("/");
if (ignoredAssetFiles.has(identifier)) {
continue;
}
let currentDir = crosspath.dirname(assetRelpath);
do {
agentDirectories.add(currentDir);
currentDir = crosspath.dirname(currentDir);
} while (currentDir !== "/");
agentFiles.set(assetRelpath, fs.readFileSync(assetPath, "utf-8"));
}
const orderedAgentDirectories = Array.from(agentDirectories);
orderedAgentDirectories.sort();
const orderedAgentFiles = Array.from(agentFiles);
orderedAgentFiles.sort((a, b) => a[0].localeCompare(b[0]));
return {
"Frida.version": "'0.0.0'",
"Process.id": "1",
"Process.platform": `'${hostOsFamily}'`,
"Process.arch": `'${hostArch}'`,
"Process.pointerSize": (hostCpuMode === "64") ? "8" : "4",
"__agentDirectories__": JSON.stringify(orderedAgentDirectories, null, 4),
"__agentFiles__": JSON.stringify(orderedAgentFiles, null, 4),
};
}
function stubTsImportPlugin(): rollup.Plugin {
return {
name: "stub-ts-import",
async resolveId(source, importer, options) {
if (crosspath.basename(source) === "typescript.js") {
return {
id: "typescript",
external: true,
meta: {},
moduleSideEffects: false,
syntheticNamedExports: false
};
}
return this.resolve(source, importer, { skipSelf: true, ...options });
}
};
}
-15
View File
@@ -1,15 +0,0 @@
import path from "path";
import { defineConfig } from "rollup";
export default defineConfig({
input: path.join("node_modules", "frida-compile", "ext", "typescript.js"),
output: {
file: "typescript.js",
format: "umd",
name: "ts",
generatedCode: {
preset: "es2015",
},
strict: false,
},
});
+196
View File
@@ -0,0 +1,196 @@
package main
import (
"embed"
"encoding/json"
"fmt"
"path/filepath"
"strings"
esbuild "github.com/evanw/esbuild/pkg/api"
)
var nodeGlobals = `
export { Buffer } from 'node:buffer';
export { default as process } from 'node:process';
`
//go:embed node_modules/@frida/*/package.json
//go:embed node_modules/@frida/*/*.js
//go:embed node_modules/@frida/*/*/*.js
//go:embed node_modules/@frida/*/*/*/*.js
//go:embed node_modules/frida-fs/package.json
//go:embed node_modules/frida-fs/*/*.js
var embeddedShims embed.FS
func makeFridaShimsPlugin() esbuild.Plugin {
const (
nsBuiltins = "frida-builtins"
nsShim = "frida-shim"
)
const (
builtinFilter = `^frida-builtins://(.+)$`
shimFilter = `^(assert|base64-js|buffer|crypto|diagnostics_channel|events|fs|http|https|http-parser-js|ieee754|net|os|path|process|punycode|querystring|readable-stream|stream|string_decoder|timers|tty|url|util|vm)$`
shimNodePrefixFilter = `^node:(assert|buffer|crypto|diagnostics_channel|events|fs|http|https|net|os|path|process|punycode|querystring|stream|string_decoder|timers|tty|url|util|vm)$`
)
return esbuild.Plugin{
Name: "frida-custom-shims",
Setup: func(build esbuild.PluginBuild) {
build.OnResolve(esbuild.OnResolveOptions{Filter: builtinFilter},
func(args esbuild.OnResolveArgs) (esbuild.OnResolveResult, error) {
return esbuild.OnResolveResult{
Path: strings.TrimPrefix(args.Path, "frida-builtins://"),
Namespace: nsBuiltins,
SideEffects: esbuild.SideEffectsFalse,
}, nil
})
build.OnLoad(esbuild.OnLoadOptions{Filter: ".*", Namespace: nsBuiltins},
func(args esbuild.OnLoadArgs) (esbuild.OnLoadResult, error) {
if args.Path != "/node-globals.js" {
return esbuild.OnLoadResult{
Errors: []esbuild.Message{{Text: "Unexpected path: " + args.Path}},
}, nil
}
return esbuild.OnLoadResult{
Contents: &nodeGlobals,
Loader: esbuild.LoaderJS,
}, nil
})
registerShimResolve := func(pattern string) {
build.OnResolve(esbuild.OnResolveOptions{Filter: pattern},
func(args esbuild.OnResolveArgs) (esbuild.OnResolveResult, error) {
return makeResolveResult(nsShim, args.Path)
})
}
registerShimResolve(shimFilter)
registerShimResolve(shimNodePrefixFilter)
build.OnResolve(esbuild.OnResolveOptions{Filter: ".*", Namespace: nsShim},
func(args esbuild.OnResolveArgs) (esbuild.OnResolveResult, error) {
if strings.HasPrefix(args.Path, ".") {
abs := filepath.ToSlash(filepath.Join(filepath.Dir(args.Importer), args.Path))
return esbuild.OnResolveResult{
Path: abs,
Namespace: nsShim,
SideEffects: esbuild.SideEffectsFalse,
}, nil
}
return makeResolveResult(nsShim, args.Path)
})
build.OnLoad(esbuild.OnLoadOptions{Filter: ".*", Namespace: nsShim},
func(args esbuild.OnLoadArgs) (esbuild.OnLoadResult, error) {
data, err := embeddedShims.ReadFile(filepath.ToSlash(args.Path))
if err != nil {
return esbuild.OnLoadResult{
Errors: []esbuild.Message{{
Text: fmt.Sprintf("Error reading shim file %q: %v", args.Path, err),
}},
}, nil
}
content := string(data)
return esbuild.OnLoadResult{
Contents: &content,
Loader: loaderFor(args.Path),
}, nil
})
},
}
}
func makeResolveResult(ns string, module string) (esbuild.OnResolveResult, error) {
path, errs := resolveShim(module)
if len(errs) > 0 {
return esbuild.OnResolveResult{Errors: errs}, nil
}
return esbuild.OnResolveResult{
Path: path,
Namespace: ns,
SideEffects: esbuild.SideEffectsFalse,
}, nil
}
func loaderFor(path string) esbuild.Loader {
switch ext := filepath.Ext(path); ext {
case ".js", ".mjs", ".cjs":
return esbuild.LoaderJS
case ".json":
return esbuild.LoaderJSON
default:
panic(fmt.Sprintf("frida-shims: unsupported file type %q", ext))
}
}
var shimMap = map[string]string{
"assert": "@frida/assert",
"base64-js": "@frida/base64-js",
"buffer": "@frida/buffer",
"crypto": "@frida/crypto",
"diagnostics_channel": "@frida/diagnostics_channel",
"events": "@frida/events",
"fs": "frida-fs",
"http": "@frida/http",
"https": "@frida/https",
"http-parser-js": "@frida/http-parser-js",
"ieee754": "@frida/ieee754",
"net": "@frida/net",
"os": "@frida/os",
"path": "@frida/path",
"process": "@frida/process",
"punycode": "@frida/punycode",
"querystring": "@frida/querystring",
"readable-stream": "@frida/readable-stream",
"stream": "@frida/stream",
"string_decoder": "@frida/string_decoder",
"timers": "@frida/timers",
"tty": "@frida/tty",
"url": "@frida/url",
"util": "@frida/util",
"vm": "@frida/vm",
}
type PackageJSON struct {
Main string `json:"main"`
Module string `json:"module"`
}
func resolveShim(shimName string) (string, []esbuild.Message) {
var subDir string
if strings.HasPrefix(shimName, "@frida/") {
subDir = shimName
} else {
actualShimName := strings.TrimPrefix(shimName, "node:")
var ok bool
subDir, ok = shimMap[actualShimName]
if !ok {
return "", []esbuild.Message{{Text: "Unknown shim: " + actualShimName}}
}
}
shimPackageDir := filepath.Join("node_modules", subDir)
packageJSONPath := filepath.Join(shimPackageDir, "package.json")
pkgJSONBytes, _ := embeddedShims.ReadFile(filepath.ToSlash(packageJSONPath))
var pkg PackageJSON
json.Unmarshal(pkgJSONBytes, &pkg)
entryFile := ""
if pkg.Module != "" {
entryFile = pkg.Module
} else if pkg.Main != "" {
entryFile = pkg.Main
} else {
entryFile = "index.js"
}
resolvedEntryPath := filepath.Join(shimPackageDir, entryFile)
return filepath.ToSlash(resolvedEntryPath), nil
}
+448
View File
@@ -0,0 +1,448 @@
package main
import (
"context"
"embed"
"fmt"
"maps"
"os"
"path/filepath"
"slices"
"sort"
"strings"
"sync"
"time"
"github.com/frida/typescript-go/pkg/ast"
"github.com/frida/typescript-go/pkg/bundled"
"github.com/frida/typescript-go/pkg/compiler"
"github.com/frida/typescript-go/pkg/core"
"github.com/frida/typescript-go/pkg/tsoptions"
"github.com/frida/typescript-go/pkg/tspath"
"github.com/frida/typescript-go/pkg/vfs"
"github.com/frida/typescript-go/pkg/vfs/iovfs"
"github.com/frida/typescript-go/pkg/vfs/osvfs"
)
//go:embed node_modules/@types/*/package.json
//go:embed node_modules/@types/*/*.d.ts
//go:embed node_modules/@types/*/*/*.d.ts
var embeddedTypes embed.FS
type TSCompiler struct {
projectRoot string
entrypoint string
loadCompilerOptions LoadCompilerOptionsHandler
fs vfs.FS
captureFs *captureFS
mu sync.Mutex
options *core.CompilerOptions
program *compiler.Program
programErr error
forceFreshProgram bool
mtimes map[tspath.Path]time.Time
inputDirs, inputFiles []string
pendingDirs, pendingFiles []string
}
type LoadCompilerOptionsHandler func(host tsoptions.ParseConfigHost) (*core.CompilerOptions, string, error)
func NewTSCompiler(projectRoot, entrypoint string, loadCompilerOptions LoadCompilerOptionsHandler) *TSCompiler {
captureFs := newCaptureFS(osvfs.FS())
fs := newTypesFS(bundled.WrapFS(captureFs), projectRoot)
return &TSCompiler{
projectRoot: projectRoot,
entrypoint: tspath.NormalizePath(entrypoint),
loadCompilerOptions: loadCompilerOptions,
fs: fs,
captureFs: captureFs,
}
}
func (c *TSCompiler) resetProgramState() {
c.options = nil
c.program = nil
c.programErr = nil
c.forceFreshProgram = false
c.mtimes = nil
}
func (c *TSCompiler) EnsureProgramUpToDate() error {
opts, _, err := c.loadCompilerOptions(c)
if err != nil {
c.resetProgramState()
c.recomputeInputs()
return err
}
var prog *compiler.Program
var progErr error
if c.forceFreshProgram || c.program == nil || opts != c.options {
c.forceFreshProgram = false
prog, progErr = c.createProgram(opts)
} else {
prog, progErr = c.updateProgram(c.program, opts)
}
c.program = prog
c.programErr = progErr
c.options = opts
c.recomputeInputs()
return progErr
}
func (c *TSCompiler) createProgram(options *core.CompilerOptions) (*compiler.Program, error) {
host := compiler.NewCompilerHost(options, c.projectRoot, c.fs, bundled.LibPath())
program := compiler.NewProgram(compiler.ProgramOptions{
RootFiles: []string{c.entrypoint},
Host: host,
Options: options,
})
c.updateMtimes(program)
return program, nil
}
func (c *TSCompiler) updateProgram(old *compiler.Program, options *core.CompilerOptions) (*compiler.Program, error) {
newMtimes, err := c.collectMtimes(old)
if err != nil {
return c.createProgram(options)
}
updated := []tspath.Path{}
newProg := old
for path, mtime := range newMtimes {
if !mtime.Equal(c.mtimes[path]) {
var reused bool
newProg, reused = newProg.UpdateProgram(path)
updated = append(updated, path)
if !reused {
c.updateMtimes(newProg)
return newProg, nil
}
}
}
c.mtimes = newMtimes
return newProg, nil
}
func (c *TSCompiler) updateMtimes(p *compiler.Program) {
mt, _ := c.collectMtimes(p)
c.mtimes = mt
}
func (c *TSCompiler) collectMtimes(p *compiler.Program) (map[tspath.Path]time.Time, error) {
mt := make(map[tspath.Path]time.Time, len(p.SourceFiles()))
for _, sf := range p.SourceFiles() {
name := sf.FileName()
if isBundled(name) {
continue
}
info := c.fs.Stat(name)
if info == nil {
return nil, fmt.Errorf("File %q disappeared", name)
}
mt[sf.Path()] = info.ModTime()
}
return mt, nil
}
func isBundled(name string) bool {
return strings.HasPrefix(name, "bundled://")
}
func (c *TSCompiler) WatchDirs() []string {
if c.inputDirs != nil {
return c.inputDirs
}
return c.pendingDirs
}
func (c *TSCompiler) WatchFiles() []string {
if c.inputFiles != nil {
return c.inputFiles
}
return c.pendingFiles
}
func (c *TSCompiler) CommitPendingInputs() {
c.inputDirs, c.pendingDirs = c.pendingDirs, nil
c.inputFiles, c.pendingFiles = c.pendingFiles, nil
}
func (c *TSCompiler) DropPendingInputs() {
c.pendingDirs, c.pendingFiles = nil, nil
}
func (c *TSCompiler) recomputeInputs() {
var capHint int
if c.program != nil {
capHint = 1 + len(c.program.GetSourceFiles())
} else {
capHint = 1
}
files := make([]string, 0, capHint)
files = append(files, filepath.Join(c.projectRoot, "tsconfig.json"))
if c.program != nil {
for _, sf := range c.program.GetSourceFiles() {
name := sf.FileName()
if !isBundled(name) {
files = append(files, name)
}
}
}
sort.Strings(files)
c.pendingDirs = uniqueDirs(files)
c.pendingFiles = files
}
func (c *TSCompiler) Compile(filePathToCompile string) (string, []*ast.Diagnostic, error) {
c.mu.Lock()
defer c.mu.Unlock()
if c.programErr != nil {
return "", nil, c.programErr
}
program := c.program
var targetSourceFile *ast.SourceFile
normalizedFilePathToCompile := tspath.NormalizePath(filePathToCompile)
for _, sf := range program.GetSourceFiles() {
if sf.FileName() == normalizedFilePathToCompile {
targetSourceFile = sf
break
}
}
if targetSourceFile == nil {
return "", nil, fmt.Errorf("TypeScript source file not found in program: %s", filePathToCompile)
}
c.captureFs.ClearOutputs()
res := program.Emit(compiler.EmitOptions{
TargetSourceFile: targetSourceFile,
})
ctx := context.Background()
diagnostics := program.GetSyntacticDiagnostics(ctx, targetSourceFile)
if len(diagnostics) == 0 {
diagnostics = append(diagnostics, program.GetBindDiagnostics(ctx, targetSourceFile)...)
}
if len(diagnostics) == 0 {
diagnostics = append(diagnostics, program.GetOptionsDiagnostics(ctx)...)
}
if len(diagnostics) == 0 {
diagnostics = append(diagnostics, program.GetGlobalDiagnostics(ctx)...)
}
if len(diagnostics) == 0 {
semanticDiags := program.GetSemanticDiagnostics(ctx, targetSourceFile)
for _, d := range semanticDiags {
switch d.Code() {
case
2305, // Module '{0}' has no exported member '{1}'.
2306, // File '{0}' is not a module.
2307: // Cannot find module '{0}' or its corresponding type declarations.
c.forceFreshProgram = true
}
}
diagnostics = append(diagnostics, semanticDiags...)
}
if res.EmitSkipped {
errMsg := "TypeScript compilation failed and was skipped"
if len(diagnostics) == 0 {
errMsg = fmt.Sprintf("TypeScript compilation failed and was skipped for %s, but no diagnostics reported", filePathToCompile)
}
return "", diagnostics, fmt.Errorf(errMsg)
}
var compiledJS string
var foundJSOutput bool
for path, content := range c.captureFs.GetOutputs() {
ext := filepath.Ext(path)
if ext == ".js" {
compiledJS = content
foundJSOutput = true
break
}
}
if !foundJSOutput {
if len(diagnostics) == 0 {
return "", nil, fmt.Errorf("TypeScript compilation for %s seemed to succeed (emit not skipped, no diagnostics) but no .js output file was captured. Captured outputs: %v", filePathToCompile, c.captureFs.GetOutputs())
}
return "", diagnostics, fmt.Errorf("No .js output file was captured for %s. Captured outputs: %v", filePathToCompile, c.captureFs.GetOutputs())
}
return compiledJS, diagnostics, nil
}
func uniqueDirs(files []string) []string {
m := make(map[string]struct{}, len(files))
for _, f := range files {
m[filepath.Dir(f)] = struct{}{}
}
out := make([]string, 0, len(m))
for d := range m {
out = append(out, d)
}
sort.Strings(out)
return out
}
// FS implements ParseConfigHost.
func (c *TSCompiler) FS() vfs.FS {
return c.fs
}
// GetCurrentDirectory implements ParseConfigHost.
func (c *TSCompiler) GetCurrentDirectory() string {
return c.projectRoot
}
type captureFS struct {
vfs.FS
outputs map[string]string
mutex sync.Mutex
}
var _ vfs.FS = (*captureFS)(nil)
func newCaptureFS(inner vfs.FS) *captureFS {
return &captureFS{
FS: inner,
outputs: make(map[string]string),
}
}
func (c *captureFS) ClearOutputs() {
c.mutex.Lock()
defer c.mutex.Unlock()
c.outputs = make(map[string]string)
}
func (c *captureFS) GetOutputs() map[string]string {
c.mutex.Lock()
defer c.mutex.Unlock()
snap := make(map[string]string, len(c.outputs))
for k, v := range c.outputs {
snap[k] = v
}
return snap
}
func (c *captureFS) WriteFile(path string, data string, writeByteOrderMark bool) error {
c.mutex.Lock()
defer c.mutex.Unlock()
c.outputs[path] = data
return nil
}
func (c *captureFS) Remove(path string) error {
c.mutex.Lock()
defer c.mutex.Unlock()
delete(c.outputs, path)
return nil
}
type typesFS struct {
vfs.FS
projectRoot string
types vfs.FS
}
var _ vfs.FS = (*typesFS)(nil)
func newTypesFS(inner vfs.FS, projectRoot string) *typesFS {
return &typesFS{
FS: inner,
projectRoot: projectRoot,
types: iovfs.From(embeddedTypes, true),
}
}
func (t *typesFS) DirectoryExists(path string) bool {
embeddedPath := t.resolveEmbeddedPath(path)
if embeddedPath != "" {
if t.types.DirectoryExists(embeddedPath) {
return true
}
}
return t.FS.DirectoryExists(path)
}
func (t *typesFS) GetAccessibleEntries(path string) vfs.Entries {
embeddedPath := t.resolveEmbeddedPath(path)
var embeddedEntries vfs.Entries
if embeddedPath != "" {
embeddedEntries = t.types.GetAccessibleEntries(embeddedPath)
}
otherEntries := t.FS.GetAccessibleEntries(path)
return vfs.Entries{
Files: mergeAndSort(embeddedEntries.Files, otherEntries.Files),
Directories: mergeAndSort(embeddedEntries.Directories, otherEntries.Directories),
}
}
func (t *typesFS) FileExists(path string) bool {
embeddedPath := t.resolveEmbeddedPath(path)
if embeddedPath != "" {
if t.types.FileExists(embeddedPath) {
return true
}
}
return t.FS.FileExists(path)
}
func (t *typesFS) ReadFile(path string) (contents string, ok bool) {
contents, ok = t.FS.ReadFile(path)
if ok {
return contents, ok
}
embeddedPath := t.resolveEmbeddedPath(path)
if embeddedPath != "" {
contents, ok = t.types.ReadFile(embeddedPath)
}
return contents, ok
}
func (c *typesFS) resolveEmbeddedPath(path string) string {
rel, err := filepath.Rel(c.projectRoot, path)
if err != nil {
return ""
}
if rel == ".." || strings.HasPrefix(rel, ".."+string(os.PathSeparator)) {
return ""
}
return "/" + filepath.ToSlash(rel)
}
func mergeAndSort(a, b []string) []string {
m := make(map[string]struct{}, len(a)+len(b))
for _, v := range append(a, b...) {
m[v] = struct{}{}
}
return slices.Sorted(maps.Keys(m))
}
+158
View File
@@ -0,0 +1,158 @@
package main
import (
"encoding/json"
"fmt"
"path/filepath"
"reflect"
"strings"
"sync"
"time"
tscore "github.com/frida/typescript-go/pkg/core"
"github.com/frida/typescript-go/pkg/tsoptions"
"github.com/frida/typescript-go/pkg/tspath"
)
type TSConfigCache struct {
projectRoot string
sourceMap bool
tsconfigPath string
onChange ConfigChangeCallback
mu sync.Mutex
lastModTime time.Time
cachedOpts *tscore.CompilerOptions
lastText string
}
type ConfigChangeCallback func()
func NewTSConfigCache(
projectRoot string,
sourceMap bool,
callback ConfigChangeCallback,
) *TSConfigCache {
return &TSConfigCache{
projectRoot: projectRoot,
sourceMap: sourceMap,
tsconfigPath: filepath.Join(projectRoot, "tsconfig.json"),
lastModTime: time.Time{},
cachedOpts: nil,
lastText: "",
onChange: callback,
}
}
func (c *TSConfigCache) GetCompilerOptions(
host tsoptions.ParseConfigHost,
) (*tscore.CompilerOptions, string, error) {
c.mu.Lock()
defer c.mu.Unlock()
fs := host.FS()
info := fs.Stat(c.tsconfigPath)
var currentModTime time.Time
if info != nil {
currentModTime = info.ModTime()
} else {
currentModTime = time.Time{}
}
if c.cachedOpts != nil && currentModTime.Equal(c.lastModTime) {
return c.cachedOpts, c.lastText, nil
}
var tsconfigText string
if info != nil {
data, ok := fs.ReadFile(c.tsconfigPath)
if !ok {
return nil, "", fmt.Errorf("Unable to read %q", c.tsconfigPath)
}
tsconfigText = string(data)
} else {
tsconfigText = "{}"
}
parsedSource := tsoptions.NewTsconfigSourceFileFromFilePath(
tspath.NormalizePath(c.tsconfigPath),
tspath.ToPath(c.tsconfigPath, "", fs.UseCaseSensitiveFileNames()),
tsconfigText,
)
parsedCommandLine := tsoptions.ParseJsonSourceFileConfigFileContent(
parsedSource,
host,
c.projectRoot,
nil,
c.tsconfigPath,
nil, nil, nil,
)
if len(parsedCommandLine.Errors) > 0 {
var msgs []string
for _, diag := range parsedCommandLine.Errors {
msgs = append(msgs, diag.Message())
}
return nil, "", fmt.Errorf(
"Failed to parse %s: %s",
c.tsconfigPath,
strings.Join(msgs, "; "),
)
}
newOpts := parsedCommandLine.CompilerOptions()
newOpts.Module = tscore.ModuleKindNode16
newOpts.ModuleResolution = tscore.ModuleResolutionKindNode16
newOpts.NoEmit = tscore.TSFalse
sourceMapOptVal := boolToTristate(c.sourceMap)
newOpts.SourceMap = sourceMapOptVal
newOpts.InlineSourceMap = sourceMapOptVal
if newOpts.Target == tscore.ScriptTargetNone {
newOpts.Target = tscore.ScriptTargetES2022
}
if newOpts.Lib == nil {
newOpts.Lib = []string{"lib.es2022.d.ts"}
}
if newOpts.SkipLibCheck == tscore.TSUnknown {
newOpts.SkipLibCheck = tscore.TSTrue
}
if newOpts.Strict == tscore.TSUnknown {
newOpts.Strict = tscore.TSTrue
}
tsconfigData, _ := json.Marshal(parsedCommandLine.ParsedConfig)
tsconfigText = string(tsconfigData)
hadPreviousOpts := c.cachedOpts != nil
optsChanged := true
if c.cachedOpts != nil && reflect.DeepEqual(newOpts, c.cachedOpts) {
optsChanged = false
}
if optsChanged {
c.cachedOpts = newOpts
c.lastText = tsconfigText
}
c.lastModTime = currentModTime
c.mu.Unlock()
defer c.mu.Lock()
if hadPreviousOpts && optsChanged {
if c.onChange != nil {
c.onChange()
}
}
return newOpts, tsconfigText, nil
}
func boolToTristate(val bool) tscore.Tristate {
if val {
return tscore.TSTrue
}
return tscore.TSFalse
}
-11
View File
@@ -1,11 +0,0 @@
{
"compilerOptions": {
"target": "es2020",
"lib": ["es2020"],
"module": "ES2020",
"moduleResolution": "node",
"allowSyntheticDefaultImports": true,
"strict": true,
"noEmit": true
}
}
+1 -1
View File
@@ -257,7 +257,7 @@ function findSubstrateLauncher() {
if (Process.arch !== 'arm64')
return null;
const imp = Module.enumerateImports('/sbin/launchd').filter(imp => imp.name === 'posix_spawn')[0];
const imp = Process.mainModule.enumerateImports().find(imp => imp.name === 'posix_spawn');
if (imp === undefined)
return null;
const impl = imp.slot.readPointer().strip();
+424 -487
View File
@@ -8,546 +8,483 @@
"name": "frida-osanalytics-agent",
"version": "1.0.0",
"dependencies": {
"frida-objc-bridge": "^8.0.4"
"frida-objc-bridge": "^8.0.5"
},
"devDependencies": {
"@types/frida-gum": "^19.0.0",
"frida-compile": "^17.0.0"
"esbuild": "^0.25.5"
}
},
"node_modules/@frida/assert": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/@frida/assert/-/assert-3.0.2.tgz",
"integrity": "sha512-JXJq5SbXGrM5EkjrZKfRmB29zOoEOix02NC6A5TSJ+C1GE/X051EinJJsuOO2pEOx7KZwpvAHvS0WXW0+levKg==",
"dev": true,
"license": "MIT"
},
"node_modules/@frida/base64-js": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/@frida/base64-js/-/base64-js-2.0.3.tgz",
"integrity": "sha512-2w0F+1TynOTCZ/v7du9LdHPWwq0lJhazjo2fF9upMyQmA1zHetT14fLuQ1v/6T0qPgyeEGkiSrybstU8EsgeUA==",
"dev": true,
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
"node_modules/@esbuild/aix-ppc64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.5.tgz",
"integrity": "sha512-9o3TMmpmftaCMepOdA5k/yDw8SfInyzWWTjYTFCX3kPSDJMROQTb8jg+h9Cnwnmm1vOzvxN7gIfB5V2ewpjtGA==",
"cpu": [
"ppc64"
],
"license": "MIT"
},
"node_modules/@frida/buffer": {
"version": "7.0.4",
"resolved": "https://registry.npmjs.org/@frida/buffer/-/buffer-7.0.4.tgz",
"integrity": "sha512-RxQ1lZRRiCJj7nhcCiD8xeJx0NsLpGGnjqsmTg7jShGmbnVFMN5W7+J+3gqdPSQhc/IxNBIWc6zRXVp4+qnYHg==",
"dev": true,
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
"license": "MIT",
"optional": true,
"os": [
"aix"
],
"license": "MIT",
"dependencies": {
"base64-js": "^1.5.1",
"ieee754": "^1.2.1"
}
},
"node_modules/@frida/crosspath": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/@frida/crosspath/-/crosspath-3.0.0.tgz",
"integrity": "sha512-bNdO1spIPD2P40XtK89N49oZpJhstdlnkJZcD4yJ17jrdkm9Ctu0sd9MIEX6Z8Tm8ydhVJBAOMEKl9/R27onAQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/node": "^17.0.36"
},
"engines": {
"node": ">=14.9.0"
"node": ">=18"
}
},
"node_modules/@frida/crypto": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@frida/crypto/-/crypto-1.0.1.tgz",
"integrity": "sha512-WXTkVjESvX8TIVXIynJJv9BKSIdQP0Iis04StIXknkDi1ULdMlrypA9p5C4KW1H6GCkNsVnKbybpzsulYCTvag==",
"dev": true,
"license": "MIT"
},
"node_modules/@frida/diagnostics_channel": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@frida/diagnostics_channel/-/diagnostics_channel-1.0.0.tgz",
"integrity": "sha512-mYX1jp/5Bpk24tHArJNx65iCk7qSuV8YJkdU0gFNVtJUXxfV8BG5WuPa4mL+ynxsbWWpsg/cwKZbLAepYKTdQQ==",
"dev": true,
"license": "MIT"
},
"node_modules/@frida/events": {
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/@frida/events/-/events-4.0.4.tgz",
"integrity": "sha512-qJVQ6VWHf9sjUKuiJzoCAC00frbpcwxeYfvQ+PP9LU/d70j+QvjWgYe98Qa3ekLaBU6r/AvWm8ThKCDUCLWrQQ==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=0.8.x"
}
},
"node_modules/@frida/http": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/@frida/http/-/http-4.0.2.tgz",
"integrity": "sha512-cvkc7ex7GmVXVOWqtjXKBWUUbYEBgpNRKZbEEoMeI8KiIs8zejKwg+N7rx7296Ao+EP3+xcUr4wBVr3xLaUVfQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"http-parser-js": "^0.5.3"
}
},
"node_modules/@frida/http-parser-js": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@frida/http-parser-js/-/http-parser-js-1.0.0.tgz",
"integrity": "sha512-2nMrNXt/OeTlWbqnE8AH4Sfz4I2+BGoN206dzKEyC/g2svtn83Xu+zuv/V3TkwrA27s26Mcy84ZwsXeNlqNxUQ==",
"dev": true,
"license": "MIT"
},
"node_modules/@frida/https": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@frida/https/-/https-1.0.0.tgz",
"integrity": "sha512-OiqQ6qsALcWOktRLq07oJ0i6sH8eX6MXb/MdZS1qVKDRf6wchH4Pjn6fiLB+pt/OlYbggk+DOfpHwSdjTwuHMQ==",
"dev": true,
"license": "MIT"
},
"node_modules/@frida/ieee754": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/@frida/ieee754/-/ieee754-2.0.2.tgz",
"integrity": "sha512-wlcUebnne4ENN7GDr5pTH598ZDLMVOsh0FjenxeVOe6u7ewZkz9gGRnLnZKJAm9kl5G6XhdxhI0cSXVQK/rQUw==",
"dev": true,
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
"node_modules/@esbuild/android-arm": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.5.tgz",
"integrity": "sha512-AdJKSPeEHgi7/ZhuIPtcQKr5RQdo6OO2IL87JkianiMYMPbCtot9fxPbrMiBADOWWm3T2si9stAiVsGbTQFkbA==",
"cpu": [
"arm"
],
"license": "BSD-3-Clause"
},
"node_modules/@frida/net": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/@frida/net/-/net-4.0.2.tgz",
"integrity": "sha512-qQRe7hQ+ZfCcG/SE3P1TRqQ9bmuK/T7wPCYaT4z56rBPWAxsaQbQHpX4fR6OrFaSDr7X0xJLsTbdIp9hGhhLZg==",
"dev": true,
"license": "MIT"
},
"node_modules/@frida/os": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@frida/os/-/os-1.0.2.tgz",
"integrity": "sha512-3ISAiGNiyIya3QN2EHBCz1wqP0enTdSxP99wUeroeh8+AQRmgoOr/5TRnrVry8pe378anay3fmV/tdUMMSkehQ==",
"dev": true,
"license": "MIT"
},
"node_modules/@frida/path": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/@frida/path/-/path-2.0.3.tgz",
"integrity": "sha512-2RQy36QatoC846fzBhBhV8sXMsSOBGoYvwTHeaE1zUdz7F4RNScP4QEekTTooBYWYX/XjiF36KQpYAzc9OYFtg==",
"dev": true,
"license": "MIT"
},
"node_modules/@frida/process": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/@frida/process/-/process-1.2.1.tgz",
"integrity": "sha512-nvCu22DstFW2ttGFtOKekHM7vnjbZm+XgtvavOt427GNT6uV7k0JYK9tnMbcLMRWv57DG6udAmuJlWs8Paq1ag==",
"dev": true,
"license": "MIT"
},
"node_modules/@frida/punycode": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/@frida/punycode/-/punycode-3.0.0.tgz",
"integrity": "sha512-XVSDY2KamDs1D5/fTVgHcOSNxdU4kTboxzqJMBbTjcQC7XScIT9c0EfbwKCq7Kci6gWQdsHSCr7lU+9Oc4KAdg==",
"dev": true,
"license": "MIT"
},
"node_modules/@frida/querystring": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@frida/querystring/-/querystring-1.0.0.tgz",
"integrity": "sha512-15m1fOZPmoO/vWlgPJrG/J9/BJDz6a2/JpVGpS8ynNzo+fBhTznaStX5nHxUs24mVTqh/OqLo0EiYJM5WWHXxg==",
"dev": true,
"license": "MIT"
},
"node_modules/@frida/readable-stream": {
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/@frida/readable-stream/-/readable-stream-4.1.3.tgz",
"integrity": "sha512-ntGUFmi+CryRGRJIK13a/VST2Ad19uivbln8Xd92vKPAARq+6vMIASDyZIqyl5BLRccfiyCHdYgrgQ6RI5rUig==",
"dev": true,
"license": "MIT"
},
"node_modules/@frida/reserved-words": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@frida/reserved-words/-/reserved-words-1.0.0.tgz",
"integrity": "sha512-2yG/XxJlsGlk/mm6eZTb4OAaQEhkTI2qaFfZFtAsrA/XuCpuMWkS4y/guyBlsRu4hAuhK2HPmNM8+OLLK1zM9Q==",
"dev": true,
"license": "MIT"
},
"node_modules/@frida/stream": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@frida/stream/-/stream-1.0.2.tgz",
"integrity": "sha512-4OuaC1ztmEKgTq3WeBhsy8Oq+AwW9n9cYnvLklcC9jwD93AEwgbWpecLlxJCVuALvTMdhKPg0nQVfyGYP/i9Bw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@frida/readable-stream": "^4.1.3"
}
},
"node_modules/@frida/string_decoder": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@frida/string_decoder/-/string_decoder-2.0.0.tgz",
"integrity": "sha512-in371tYZMHQiW9HF5MS3JDw6Ao6tyBoq34UWy2rzOswYyMG1rpizh85ofi/yVkxDiaqybEZefxzkVittpPGT6g==",
"dev": true,
"license": "MIT"
},
"node_modules/@frida/terser": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@frida/terser/-/terser-1.0.0.tgz",
"integrity": "sha512-59h9WuNzD1Rx/zwoWqQ/FW/4Y/Q3R91Eng2hEwdHapqiTDvtKbZ08F6CynCR7ZVinrh4tLYsF46AtVPTz1ys9g==",
"dev": true,
"license": "BSD-2-Clause",
"dependencies": {
"@jridgewell/source-map": "^0.3.2",
"acorn": "^8.5.0",
"commander": "^2.20.0",
"source-map-support": "~0.5.20"
},
"bin": {
"terser": "bin/terser"
},
"optional": true,
"os": [
"android"
],
"engines": {
"node": ">=10"
"node": ">=18"
}
},
"node_modules/@frida/terser/node_modules/commander": {
"version": "2.20.3",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
"dev": true,
"license": "MIT"
},
"node_modules/@frida/timers": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/@frida/timers/-/timers-3.0.0.tgz",
"integrity": "sha512-3b+0igv10aT8TMxefrTAd06rActqbxJLY2Xkkq9vYcPBffB/yHszl0NYIp/5ko8WC3ecDYPU6bQiY6fjs72zTA==",
"dev": true,
"license": "MIT"
},
"node_modules/@frida/tty": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@frida/tty/-/tty-1.0.0.tgz",
"integrity": "sha512-p/kjLnKYxEAB1MdYP8+5rKv9CsHzyA+0jg9BcGETzjQVKHHcroHDULRxDYUh+DC7qs6cpX8QdDQh9E+a6ydgsQ==",
"dev": true,
"license": "MIT"
},
"node_modules/@frida/url": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@frida/url/-/url-1.0.2.tgz",
"integrity": "sha512-ZKunbKJHMr8w2Eb/5K1avy0MzK1B998S17wYXNv3RmzBGxMm8S5T0F3qEpRxkU7/72P8m4izyQU87fWl+FjQsQ==",
"node_modules/@esbuild/android-arm64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.5.tgz",
"integrity": "sha512-VGzGhj4lJO+TVGV1v8ntCZWJktV7SGCs3Pn1GRWI1SBFtRALoomm8k5E9Pmwg3HOAal2VDc2F9+PM/rEY6oIDg==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"dependencies": {
"@frida/punycode": "^3.0.0",
"@frida/querystring": "^1.0.0"
}
},
"node_modules/@frida/util": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/@frida/util/-/util-1.0.3.tgz",
"integrity": "sha512-htcG3uDiRXv89ERVNNYhfase39kJ2X75ZARfrYcYEtJLFEsSk0nemM1YnEIR4CjrHvdvkWHrwgKkS+acOyoNEg==",
"dev": true,
"license": "MIT"
},
"node_modules/@frida/vm": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@frida/vm/-/vm-2.0.0.tgz",
"integrity": "sha512-7fsjLWscZT5odNIBtg6qbLNI+vAk1xmii6H5W2kaYkMYt0vRohQEcDSUWacA+eaWlu5SvMjZI82Yibj/3G9pJw==",
"dev": true,
"license": "MIT"
},
"node_modules/@jridgewell/gen-mapping": {
"version": "0.3.8",
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz",
"integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@jridgewell/set-array": "^1.2.1",
"@jridgewell/sourcemap-codec": "^1.4.10",
"@jridgewell/trace-mapping": "^0.3.24"
},
"optional": true,
"os": [
"android"
],
"engines": {
"node": ">=6.0.0"
"node": ">=18"
}
},
"node_modules/@jridgewell/resolve-uri": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
"integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
"node_modules/@esbuild/android-x64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.5.tgz",
"integrity": "sha512-D2GyJT1kjvO//drbRT3Hib9XPwQeWd9vZoBJn+bu/lVsOZ13cqNdDeqIF/xQ5/VmWvMduP6AmXvylO/PIc2isw==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"android"
],
"engines": {
"node": ">=6.0.0"
"node": ">=18"
}
},
"node_modules/@jridgewell/set-array": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz",
"integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==",
"node_modules/@esbuild/darwin-arm64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.5.tgz",
"integrity": "sha512-GtaBgammVvdF7aPIgH2jxMDdivezgFu6iKpmT+48+F8Hhg5J/sfnDieg0aeG/jfSvkYQU2/pceFPDKlqZzwnfQ==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">=6.0.0"
"node": ">=18"
}
},
"node_modules/@jridgewell/source-map": {
"version": "0.3.6",
"resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz",
"integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==",
"node_modules/@esbuild/darwin-x64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.5.tgz",
"integrity": "sha512-1iT4FVL0dJ76/q1wd7XDsXrSW+oLoquptvh4CLR4kITDtqi2e/xwXwdCVH8hVHU43wgJdsq7Gxuzcs6Iq/7bxQ==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"dependencies": {
"@jridgewell/gen-mapping": "^0.3.5",
"@jridgewell/trace-mapping": "^0.3.25"
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@jridgewell/sourcemap-codec": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz",
"integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==",
"dev": true,
"license": "MIT"
},
"node_modules/@jridgewell/trace-mapping": {
"version": "0.3.25",
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz",
"integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==",
"node_modules/@esbuild/freebsd-arm64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.5.tgz",
"integrity": "sha512-nk4tGP3JThz4La38Uy/gzyXtpkPW8zSAmoUhK9xKKXdBCzKODMc2adkB2+8om9BDYugz+uGV7sLmpTYzvmz6Sw==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"dependencies": {
"@jridgewell/resolve-uri": "^3.1.0",
"@jridgewell/sourcemap-codec": "^1.4.14"
"optional": true,
"os": [
"freebsd"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@types/frida-gum": {
"version": "19.0.0",
"resolved": "https://registry.npmjs.org/@types/frida-gum/-/frida-gum-19.0.0.tgz",
"integrity": "sha512-qViK1KwvPEAkajwSUv0wpZvZLiX8xO4JFFCh8dfYZfzSyOEfoE0KliCP/nJSKIKG6N3hXnPowrvPufjs5fLKAA==",
"node_modules/@esbuild/freebsd-x64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.5.tgz",
"integrity": "sha512-PrikaNjiXdR2laW6OIjlbeuCPrPaAl0IwPIaRv+SMV8CiM8i2LqVUHFC1+8eORgWyY7yhQY+2U2fA55mBzReaw==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT"
"license": "MIT",
"optional": true,
"os": [
"freebsd"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@types/node": {
"version": "17.0.45",
"resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.45.tgz",
"integrity": "sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==",
"node_modules/@esbuild/linux-arm": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.5.tgz",
"integrity": "sha512-cPzojwW2okgh7ZlRpcBEtsX7WBuqbLrNXqLU89GxWbNt6uIg78ET82qifUy3W6OVww6ZWobWub5oqZOVtwolfw==",
"cpu": [
"arm"
],
"dev": true,
"license": "MIT"
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/acorn": {
"version": "8.14.1",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz",
"integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==",
"node_modules/@esbuild/linux-arm64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.5.tgz",
"integrity": "sha512-Z9kfb1v6ZlGbWj8EJk9T6czVEjjq2ntSYLY2cw6pAZl4oKtfgQuS4HOq41M/BcoLPzrUbNd+R4BXFyH//nHxVg==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-ia32": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.5.tgz",
"integrity": "sha512-sQ7l00M8bSv36GLV95BVAdhJ2QsIbCuCjh/uYrWiMQSUuV+LpXwIqhgJDcvMTj+VsQmqAHL2yYaasENvJ7CDKA==",
"cpu": [
"ia32"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-loong64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.5.tgz",
"integrity": "sha512-0ur7ae16hDUC4OL5iEnDb0tZHDxYmuQyhKhsPBV8f99f6Z9KQM02g33f93rNH5A30agMS46u2HP6qTdEt6Q1kg==",
"cpu": [
"loong64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-mips64el": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.5.tgz",
"integrity": "sha512-kB/66P1OsHO5zLz0i6X0RxlQ+3cu0mkxS3TKFvkb5lin6uwZ/ttOkP3Z8lfR9mJOBk14ZwZ9182SIIWFGNmqmg==",
"cpu": [
"mips64el"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-ppc64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.5.tgz",
"integrity": "sha512-UZCmJ7r9X2fe2D6jBmkLBMQetXPXIsZjQJCjgwpVDz+YMcS6oFR27alkgGv3Oqkv07bxdvw7fyB71/olceJhkQ==",
"cpu": [
"ppc64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-riscv64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.5.tgz",
"integrity": "sha512-kTxwu4mLyeOlsVIFPfQo+fQJAV9mh24xL+y+Bm6ej067sYANjyEw1dNHmvoqxJUCMnkBdKpvOn0Ahql6+4VyeA==",
"cpu": [
"riscv64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-s390x": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.5.tgz",
"integrity": "sha512-K2dSKTKfmdh78uJ3NcWFiqyRrimfdinS5ErLSn3vluHNeHVnBAFWC8a4X5N+7FgVE1EjXS1QDZbpqZBjfrqMTQ==",
"cpu": [
"s390x"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-x64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.5.tgz",
"integrity": "sha512-uhj8N2obKTE6pSZ+aMUbqq+1nXxNjZIIjCjGLfsWvVpy7gKCOL6rsY1MhRh9zLtUtAI7vpgLMK6DxjO8Qm9lJw==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/netbsd-arm64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.5.tgz",
"integrity": "sha512-pwHtMP9viAy1oHPvgxtOv+OkduK5ugofNTVDilIzBLpoWAM16r7b/mxBvfpuQDpRQFMfuVr5aLcn4yveGvBZvw==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"netbsd"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/netbsd-x64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.5.tgz",
"integrity": "sha512-WOb5fKrvVTRMfWFNCroYWWklbnXH0Q5rZppjq0vQIdlsQKuw6mdSihwSo4RV/YdQ5UCKKvBy7/0ZZYLBZKIbwQ==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"netbsd"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/openbsd-arm64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.5.tgz",
"integrity": "sha512-7A208+uQKgTxHd0G0uqZO8UjK2R0DDb4fDmERtARjSHWxqMTye4Erz4zZafx7Di9Cv+lNHYuncAkiGFySoD+Mw==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"openbsd"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/openbsd-x64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.5.tgz",
"integrity": "sha512-G4hE405ErTWraiZ8UiSoesH8DaCsMm0Cay4fsFWOOUcz8b8rC6uCvnagr+gnioEjWn0wC+o1/TAHt+It+MpIMg==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"openbsd"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/sunos-x64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.5.tgz",
"integrity": "sha512-l+azKShMy7FxzY0Rj4RCt5VD/q8mG/e+mDivgspo+yL8zW7qEwctQ6YqKX34DTEleFAvCIUviCFX1SDZRSyMQA==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"sunos"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/win32-arm64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.5.tgz",
"integrity": "sha512-O2S7SNZzdcFG7eFKgvwUEZ2VG9D/sn/eIiz8XRZ1Q/DO5a3s76Xv0mdBzVM5j5R639lXQmPmSo0iRpHqUUrsxw==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/win32-ia32": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.5.tgz",
"integrity": "sha512-onOJ02pqs9h1iMJ1PQphR+VZv8qBMQ77Klcsqv9CNW2w6yLqoURLcgERAIurY6QE63bbLuqgP9ATqajFLK5AMQ==",
"cpu": [
"ia32"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/win32-x64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.5.tgz",
"integrity": "sha512-TXv6YnJ8ZMVdX+SXWVBo/0p8LTcrUYngpWjvm91TMjjBQii7Oz11Lw5lbDV5Y0TzuhSJHwiH4hEtC1I42mMS0g==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">=18"
}
},
"node_modules/esbuild": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.5.tgz",
"integrity": "sha512-P8OtKZRv/5J5hhz0cUAdu/cLuPIKXpQl1R9pZtvmHWQvrAUVd0UNIPT4IB4W3rNOqVO0rlqHmCIbSwxh/c9yUQ==",
"dev": true,
"hasInstallScript": true,
"license": "MIT",
"bin": {
"acorn": "bin/acorn"
"esbuild": "bin/esbuild"
},
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/base64-js": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
"dev": true,
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
],
"license": "MIT"
},
"node_modules/buffer-from": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
"dev": true,
"license": "MIT"
},
"node_modules/commander": {
"version": "11.1.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz",
"integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=16"
}
},
"node_modules/frida-compile": {
"version": "17.0.0",
"resolved": "https://registry.npmjs.org/frida-compile/-/frida-compile-17.0.0.tgz",
"integrity": "sha512-ixJRj14qLH/Z0ckFWd5fKeDMm0W2+2WDpSGnLRgpn0nuCQAbDHRCqVCWtPnV8uzPJmA6XOX0pujsMpYe9q9RRw==",
"dev": true,
"dependencies": {
"@frida/assert": "^3.0.1",
"@frida/base64-js": "^2.0.3",
"@frida/buffer": "^7.0.4",
"@frida/crosspath": "^3.0.0",
"@frida/crypto": "^1.0.1",
"@frida/diagnostics_channel": "^1.0.0",
"@frida/events": "^4.0.4",
"@frida/http": "^4.0.2",
"@frida/http-parser-js": "^1.0.0",
"@frida/https": "^1.0.0",
"@frida/ieee754": "^2.0.2",
"@frida/net": "^4.0.1",
"@frida/os": "^1.0.0",
"@frida/path": "^2.0.3",
"@frida/process": "^1.2.1",
"@frida/punycode": "^3.0.0",
"@frida/querystring": "^1.0.0",
"@frida/readable-stream": "^4.1.3",
"@frida/reserved-words": "^1.0.0",
"@frida/stream": "^1.0.2",
"@frida/string_decoder": "^2.0.0",
"@frida/terser": "^1.0.0",
"@frida/timers": "^3.0.0",
"@frida/tty": "^1.0.0",
"@frida/url": "^1.0.2",
"@frida/util": "^1.0.3",
"@frida/vm": "^2.0.0",
"commander": "^11.1.0",
"frida-fs": "^6.0.0",
"typed-emitter": "^2.1.0"
"node": ">=18"
},
"bin": {
"frida-compile": "dist/cli.js"
"optionalDependencies": {
"@esbuild/aix-ppc64": "0.25.5",
"@esbuild/android-arm": "0.25.5",
"@esbuild/android-arm64": "0.25.5",
"@esbuild/android-x64": "0.25.5",
"@esbuild/darwin-arm64": "0.25.5",
"@esbuild/darwin-x64": "0.25.5",
"@esbuild/freebsd-arm64": "0.25.5",
"@esbuild/freebsd-x64": "0.25.5",
"@esbuild/linux-arm": "0.25.5",
"@esbuild/linux-arm64": "0.25.5",
"@esbuild/linux-ia32": "0.25.5",
"@esbuild/linux-loong64": "0.25.5",
"@esbuild/linux-mips64el": "0.25.5",
"@esbuild/linux-ppc64": "0.25.5",
"@esbuild/linux-riscv64": "0.25.5",
"@esbuild/linux-s390x": "0.25.5",
"@esbuild/linux-x64": "0.25.5",
"@esbuild/netbsd-arm64": "0.25.5",
"@esbuild/netbsd-x64": "0.25.5",
"@esbuild/openbsd-arm64": "0.25.5",
"@esbuild/openbsd-x64": "0.25.5",
"@esbuild/sunos-x64": "0.25.5",
"@esbuild/win32-arm64": "0.25.5",
"@esbuild/win32-ia32": "0.25.5",
"@esbuild/win32-x64": "0.25.5"
}
},
"node_modules/frida-fs": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/frida-fs/-/frida-fs-6.0.0.tgz",
"integrity": "sha512-I0fnKupZh7fU2ixwCIjJnEqNdhfm/SC1ZYBMy58EmeqOWSbjw1Dpy99mJ7BJdbk2KNXJeaBZGxDYLtn0J9S+UA==",
"dev": true,
"license": "MIT"
},
"node_modules/frida-objc-bridge": {
"version": "8.0.4",
"resolved": "https://registry.npmjs.org/frida-objc-bridge/-/frida-objc-bridge-8.0.4.tgz",
"integrity": "sha512-AUzwq/+TFtblQLTI97UPX22pBcvyG2oUde9380DXbcJ0zXts4n9JDVONHUr03aBowa0Le+bdBoVdCs7jyyjvlg==",
"version": "8.0.5",
"resolved": "https://registry.npmjs.org/frida-objc-bridge/-/frida-objc-bridge-8.0.5.tgz",
"integrity": "sha512-0xnL0VgxSQXgLj3S33S0kdAvLrCHSCIZb9HVraEgEyKnf9wOcu0KZ9fI5xzx0e0y+ry/g2Vl3yw9j3dsn92Ffg==",
"license": "LGPL-2.0 WITH WxWindows-exception-3.1"
},
"node_modules/http-parser-js": {
"version": "0.5.10",
"resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.10.tgz",
"integrity": "sha512-Pysuw9XpUq5dVc/2SMHpuTY01RFl8fttgcyunjL7eEMhGM3cI4eOmiCycJDVCo/7O7ClfQD3SaI6ftDzqOXYMA==",
"dev": true,
"license": "MIT"
},
"node_modules/ieee754": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
"integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
"dev": true,
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
],
"license": "BSD-3-Clause"
},
"node_modules/rxjs": {
"version": "7.8.2",
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz",
"integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==",
"dev": true,
"license": "Apache-2.0",
"optional": true,
"dependencies": {
"tslib": "^2.1.0"
}
},
"node_modules/source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
"dev": true,
"license": "BSD-3-Clause",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/source-map-support": {
"version": "0.5.21",
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
"integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
"dev": true,
"license": "MIT",
"dependencies": {
"buffer-from": "^1.0.0",
"source-map": "^0.6.0"
}
},
"node_modules/tslib": {
"version": "2.8.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
"dev": true,
"license": "0BSD",
"optional": true
},
"node_modules/typed-emitter": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/typed-emitter/-/typed-emitter-2.1.0.tgz",
"integrity": "sha512-g/KzbYKbH5C2vPkaXGu8DJlHrGKHLsM25Zg9WuC9pMGfuvT+X25tZQWo5fK1BjBm8+UrVE9LDCvaY0CQk+fXDA==",
"dev": true,
"license": "MIT",
"optionalDependencies": {
"rxjs": "*"
}
}
}
}
+4 -5
View File
@@ -2,15 +2,14 @@
"name": "frida-osanalytics-agent",
"version": "1.0.0",
"description": "Agent used by Frida's Darwin backend on iOS/iPadOS/tvOS",
"type": "module",
"scripts": {
"prepare": "npm run build",
"build": "frida-compile index.js -o osanalytics.js -S -c"
"build": "esbuild index.js --outfile=osanalytics.js --bundle --platform=node --target=es2022 --minify"
},
"devDependencies": {
"@types/frida-gum": "^19.0.0",
"frida-compile": "^17.0.0"
"esbuild": "^0.25.5"
},
"dependencies": {
"frida-objc-bridge": "^8.0.4"
"frida-objc-bridge": "^8.0.5"
}
}
+424 -487
View File
@@ -8,546 +8,483 @@
"name": "frida-reportcrash-agent",
"version": "1.0.0",
"dependencies": {
"frida-objc-bridge": "^8.0.4"
"frida-objc-bridge": "^8.0.5"
},
"devDependencies": {
"@types/frida-gum": "^19.0.0",
"frida-compile": "^17.0.0"
"esbuild": "^0.25.5"
}
},
"node_modules/@frida/assert": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/@frida/assert/-/assert-3.0.2.tgz",
"integrity": "sha512-JXJq5SbXGrM5EkjrZKfRmB29zOoEOix02NC6A5TSJ+C1GE/X051EinJJsuOO2pEOx7KZwpvAHvS0WXW0+levKg==",
"dev": true,
"license": "MIT"
},
"node_modules/@frida/base64-js": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/@frida/base64-js/-/base64-js-2.0.3.tgz",
"integrity": "sha512-2w0F+1TynOTCZ/v7du9LdHPWwq0lJhazjo2fF9upMyQmA1zHetT14fLuQ1v/6T0qPgyeEGkiSrybstU8EsgeUA==",
"dev": true,
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
"node_modules/@esbuild/aix-ppc64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.5.tgz",
"integrity": "sha512-9o3TMmpmftaCMepOdA5k/yDw8SfInyzWWTjYTFCX3kPSDJMROQTb8jg+h9Cnwnmm1vOzvxN7gIfB5V2ewpjtGA==",
"cpu": [
"ppc64"
],
"license": "MIT"
},
"node_modules/@frida/buffer": {
"version": "7.0.4",
"resolved": "https://registry.npmjs.org/@frida/buffer/-/buffer-7.0.4.tgz",
"integrity": "sha512-RxQ1lZRRiCJj7nhcCiD8xeJx0NsLpGGnjqsmTg7jShGmbnVFMN5W7+J+3gqdPSQhc/IxNBIWc6zRXVp4+qnYHg==",
"dev": true,
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
"license": "MIT",
"optional": true,
"os": [
"aix"
],
"license": "MIT",
"dependencies": {
"base64-js": "^1.5.1",
"ieee754": "^1.2.1"
}
},
"node_modules/@frida/crosspath": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/@frida/crosspath/-/crosspath-3.0.0.tgz",
"integrity": "sha512-bNdO1spIPD2P40XtK89N49oZpJhstdlnkJZcD4yJ17jrdkm9Ctu0sd9MIEX6Z8Tm8ydhVJBAOMEKl9/R27onAQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/node": "^17.0.36"
},
"engines": {
"node": ">=14.9.0"
"node": ">=18"
}
},
"node_modules/@frida/crypto": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@frida/crypto/-/crypto-1.0.1.tgz",
"integrity": "sha512-WXTkVjESvX8TIVXIynJJv9BKSIdQP0Iis04StIXknkDi1ULdMlrypA9p5C4KW1H6GCkNsVnKbybpzsulYCTvag==",
"dev": true,
"license": "MIT"
},
"node_modules/@frida/diagnostics_channel": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@frida/diagnostics_channel/-/diagnostics_channel-1.0.0.tgz",
"integrity": "sha512-mYX1jp/5Bpk24tHArJNx65iCk7qSuV8YJkdU0gFNVtJUXxfV8BG5WuPa4mL+ynxsbWWpsg/cwKZbLAepYKTdQQ==",
"dev": true,
"license": "MIT"
},
"node_modules/@frida/events": {
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/@frida/events/-/events-4.0.4.tgz",
"integrity": "sha512-qJVQ6VWHf9sjUKuiJzoCAC00frbpcwxeYfvQ+PP9LU/d70j+QvjWgYe98Qa3ekLaBU6r/AvWm8ThKCDUCLWrQQ==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=0.8.x"
}
},
"node_modules/@frida/http": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/@frida/http/-/http-4.0.2.tgz",
"integrity": "sha512-cvkc7ex7GmVXVOWqtjXKBWUUbYEBgpNRKZbEEoMeI8KiIs8zejKwg+N7rx7296Ao+EP3+xcUr4wBVr3xLaUVfQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"http-parser-js": "^0.5.3"
}
},
"node_modules/@frida/http-parser-js": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@frida/http-parser-js/-/http-parser-js-1.0.0.tgz",
"integrity": "sha512-2nMrNXt/OeTlWbqnE8AH4Sfz4I2+BGoN206dzKEyC/g2svtn83Xu+zuv/V3TkwrA27s26Mcy84ZwsXeNlqNxUQ==",
"dev": true,
"license": "MIT"
},
"node_modules/@frida/https": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@frida/https/-/https-1.0.0.tgz",
"integrity": "sha512-OiqQ6qsALcWOktRLq07oJ0i6sH8eX6MXb/MdZS1qVKDRf6wchH4Pjn6fiLB+pt/OlYbggk+DOfpHwSdjTwuHMQ==",
"dev": true,
"license": "MIT"
},
"node_modules/@frida/ieee754": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/@frida/ieee754/-/ieee754-2.0.2.tgz",
"integrity": "sha512-wlcUebnne4ENN7GDr5pTH598ZDLMVOsh0FjenxeVOe6u7ewZkz9gGRnLnZKJAm9kl5G6XhdxhI0cSXVQK/rQUw==",
"dev": true,
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
"node_modules/@esbuild/android-arm": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.5.tgz",
"integrity": "sha512-AdJKSPeEHgi7/ZhuIPtcQKr5RQdo6OO2IL87JkianiMYMPbCtot9fxPbrMiBADOWWm3T2si9stAiVsGbTQFkbA==",
"cpu": [
"arm"
],
"license": "BSD-3-Clause"
},
"node_modules/@frida/net": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/@frida/net/-/net-4.0.2.tgz",
"integrity": "sha512-qQRe7hQ+ZfCcG/SE3P1TRqQ9bmuK/T7wPCYaT4z56rBPWAxsaQbQHpX4fR6OrFaSDr7X0xJLsTbdIp9hGhhLZg==",
"dev": true,
"license": "MIT"
},
"node_modules/@frida/os": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@frida/os/-/os-1.0.2.tgz",
"integrity": "sha512-3ISAiGNiyIya3QN2EHBCz1wqP0enTdSxP99wUeroeh8+AQRmgoOr/5TRnrVry8pe378anay3fmV/tdUMMSkehQ==",
"dev": true,
"license": "MIT"
},
"node_modules/@frida/path": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/@frida/path/-/path-2.0.3.tgz",
"integrity": "sha512-2RQy36QatoC846fzBhBhV8sXMsSOBGoYvwTHeaE1zUdz7F4RNScP4QEekTTooBYWYX/XjiF36KQpYAzc9OYFtg==",
"dev": true,
"license": "MIT"
},
"node_modules/@frida/process": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/@frida/process/-/process-1.2.1.tgz",
"integrity": "sha512-nvCu22DstFW2ttGFtOKekHM7vnjbZm+XgtvavOt427GNT6uV7k0JYK9tnMbcLMRWv57DG6udAmuJlWs8Paq1ag==",
"dev": true,
"license": "MIT"
},
"node_modules/@frida/punycode": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/@frida/punycode/-/punycode-3.0.0.tgz",
"integrity": "sha512-XVSDY2KamDs1D5/fTVgHcOSNxdU4kTboxzqJMBbTjcQC7XScIT9c0EfbwKCq7Kci6gWQdsHSCr7lU+9Oc4KAdg==",
"dev": true,
"license": "MIT"
},
"node_modules/@frida/querystring": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@frida/querystring/-/querystring-1.0.0.tgz",
"integrity": "sha512-15m1fOZPmoO/vWlgPJrG/J9/BJDz6a2/JpVGpS8ynNzo+fBhTznaStX5nHxUs24mVTqh/OqLo0EiYJM5WWHXxg==",
"dev": true,
"license": "MIT"
},
"node_modules/@frida/readable-stream": {
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/@frida/readable-stream/-/readable-stream-4.1.3.tgz",
"integrity": "sha512-ntGUFmi+CryRGRJIK13a/VST2Ad19uivbln8Xd92vKPAARq+6vMIASDyZIqyl5BLRccfiyCHdYgrgQ6RI5rUig==",
"dev": true,
"license": "MIT"
},
"node_modules/@frida/reserved-words": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@frida/reserved-words/-/reserved-words-1.0.0.tgz",
"integrity": "sha512-2yG/XxJlsGlk/mm6eZTb4OAaQEhkTI2qaFfZFtAsrA/XuCpuMWkS4y/guyBlsRu4hAuhK2HPmNM8+OLLK1zM9Q==",
"dev": true,
"license": "MIT"
},
"node_modules/@frida/stream": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@frida/stream/-/stream-1.0.2.tgz",
"integrity": "sha512-4OuaC1ztmEKgTq3WeBhsy8Oq+AwW9n9cYnvLklcC9jwD93AEwgbWpecLlxJCVuALvTMdhKPg0nQVfyGYP/i9Bw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@frida/readable-stream": "^4.1.3"
}
},
"node_modules/@frida/string_decoder": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@frida/string_decoder/-/string_decoder-2.0.0.tgz",
"integrity": "sha512-in371tYZMHQiW9HF5MS3JDw6Ao6tyBoq34UWy2rzOswYyMG1rpizh85ofi/yVkxDiaqybEZefxzkVittpPGT6g==",
"dev": true,
"license": "MIT"
},
"node_modules/@frida/terser": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@frida/terser/-/terser-1.0.0.tgz",
"integrity": "sha512-59h9WuNzD1Rx/zwoWqQ/FW/4Y/Q3R91Eng2hEwdHapqiTDvtKbZ08F6CynCR7ZVinrh4tLYsF46AtVPTz1ys9g==",
"dev": true,
"license": "BSD-2-Clause",
"dependencies": {
"@jridgewell/source-map": "^0.3.2",
"acorn": "^8.5.0",
"commander": "^2.20.0",
"source-map-support": "~0.5.20"
},
"bin": {
"terser": "bin/terser"
},
"optional": true,
"os": [
"android"
],
"engines": {
"node": ">=10"
"node": ">=18"
}
},
"node_modules/@frida/terser/node_modules/commander": {
"version": "2.20.3",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
"dev": true,
"license": "MIT"
},
"node_modules/@frida/timers": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/@frida/timers/-/timers-3.0.0.tgz",
"integrity": "sha512-3b+0igv10aT8TMxefrTAd06rActqbxJLY2Xkkq9vYcPBffB/yHszl0NYIp/5ko8WC3ecDYPU6bQiY6fjs72zTA==",
"dev": true,
"license": "MIT"
},
"node_modules/@frida/tty": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@frida/tty/-/tty-1.0.0.tgz",
"integrity": "sha512-p/kjLnKYxEAB1MdYP8+5rKv9CsHzyA+0jg9BcGETzjQVKHHcroHDULRxDYUh+DC7qs6cpX8QdDQh9E+a6ydgsQ==",
"dev": true,
"license": "MIT"
},
"node_modules/@frida/url": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@frida/url/-/url-1.0.2.tgz",
"integrity": "sha512-ZKunbKJHMr8w2Eb/5K1avy0MzK1B998S17wYXNv3RmzBGxMm8S5T0F3qEpRxkU7/72P8m4izyQU87fWl+FjQsQ==",
"node_modules/@esbuild/android-arm64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.5.tgz",
"integrity": "sha512-VGzGhj4lJO+TVGV1v8ntCZWJktV7SGCs3Pn1GRWI1SBFtRALoomm8k5E9Pmwg3HOAal2VDc2F9+PM/rEY6oIDg==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"dependencies": {
"@frida/punycode": "^3.0.0",
"@frida/querystring": "^1.0.0"
}
},
"node_modules/@frida/util": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/@frida/util/-/util-1.0.3.tgz",
"integrity": "sha512-htcG3uDiRXv89ERVNNYhfase39kJ2X75ZARfrYcYEtJLFEsSk0nemM1YnEIR4CjrHvdvkWHrwgKkS+acOyoNEg==",
"dev": true,
"license": "MIT"
},
"node_modules/@frida/vm": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@frida/vm/-/vm-2.0.0.tgz",
"integrity": "sha512-7fsjLWscZT5odNIBtg6qbLNI+vAk1xmii6H5W2kaYkMYt0vRohQEcDSUWacA+eaWlu5SvMjZI82Yibj/3G9pJw==",
"dev": true,
"license": "MIT"
},
"node_modules/@jridgewell/gen-mapping": {
"version": "0.3.8",
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz",
"integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@jridgewell/set-array": "^1.2.1",
"@jridgewell/sourcemap-codec": "^1.4.10",
"@jridgewell/trace-mapping": "^0.3.24"
},
"optional": true,
"os": [
"android"
],
"engines": {
"node": ">=6.0.0"
"node": ">=18"
}
},
"node_modules/@jridgewell/resolve-uri": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
"integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
"node_modules/@esbuild/android-x64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.5.tgz",
"integrity": "sha512-D2GyJT1kjvO//drbRT3Hib9XPwQeWd9vZoBJn+bu/lVsOZ13cqNdDeqIF/xQ5/VmWvMduP6AmXvylO/PIc2isw==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"android"
],
"engines": {
"node": ">=6.0.0"
"node": ">=18"
}
},
"node_modules/@jridgewell/set-array": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz",
"integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==",
"node_modules/@esbuild/darwin-arm64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.5.tgz",
"integrity": "sha512-GtaBgammVvdF7aPIgH2jxMDdivezgFu6iKpmT+48+F8Hhg5J/sfnDieg0aeG/jfSvkYQU2/pceFPDKlqZzwnfQ==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">=6.0.0"
"node": ">=18"
}
},
"node_modules/@jridgewell/source-map": {
"version": "0.3.6",
"resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz",
"integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==",
"node_modules/@esbuild/darwin-x64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.5.tgz",
"integrity": "sha512-1iT4FVL0dJ76/q1wd7XDsXrSW+oLoquptvh4CLR4kITDtqi2e/xwXwdCVH8hVHU43wgJdsq7Gxuzcs6Iq/7bxQ==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"dependencies": {
"@jridgewell/gen-mapping": "^0.3.5",
"@jridgewell/trace-mapping": "^0.3.25"
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@jridgewell/sourcemap-codec": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz",
"integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==",
"dev": true,
"license": "MIT"
},
"node_modules/@jridgewell/trace-mapping": {
"version": "0.3.25",
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz",
"integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==",
"node_modules/@esbuild/freebsd-arm64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.5.tgz",
"integrity": "sha512-nk4tGP3JThz4La38Uy/gzyXtpkPW8zSAmoUhK9xKKXdBCzKODMc2adkB2+8om9BDYugz+uGV7sLmpTYzvmz6Sw==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"dependencies": {
"@jridgewell/resolve-uri": "^3.1.0",
"@jridgewell/sourcemap-codec": "^1.4.14"
"optional": true,
"os": [
"freebsd"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@types/frida-gum": {
"version": "19.0.0",
"resolved": "https://registry.npmjs.org/@types/frida-gum/-/frida-gum-19.0.0.tgz",
"integrity": "sha512-qViK1KwvPEAkajwSUv0wpZvZLiX8xO4JFFCh8dfYZfzSyOEfoE0KliCP/nJSKIKG6N3hXnPowrvPufjs5fLKAA==",
"node_modules/@esbuild/freebsd-x64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.5.tgz",
"integrity": "sha512-PrikaNjiXdR2laW6OIjlbeuCPrPaAl0IwPIaRv+SMV8CiM8i2LqVUHFC1+8eORgWyY7yhQY+2U2fA55mBzReaw==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT"
"license": "MIT",
"optional": true,
"os": [
"freebsd"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@types/node": {
"version": "17.0.45",
"resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.45.tgz",
"integrity": "sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==",
"node_modules/@esbuild/linux-arm": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.5.tgz",
"integrity": "sha512-cPzojwW2okgh7ZlRpcBEtsX7WBuqbLrNXqLU89GxWbNt6uIg78ET82qifUy3W6OVww6ZWobWub5oqZOVtwolfw==",
"cpu": [
"arm"
],
"dev": true,
"license": "MIT"
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/acorn": {
"version": "8.14.1",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz",
"integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==",
"node_modules/@esbuild/linux-arm64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.5.tgz",
"integrity": "sha512-Z9kfb1v6ZlGbWj8EJk9T6czVEjjq2ntSYLY2cw6pAZl4oKtfgQuS4HOq41M/BcoLPzrUbNd+R4BXFyH//nHxVg==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-ia32": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.5.tgz",
"integrity": "sha512-sQ7l00M8bSv36GLV95BVAdhJ2QsIbCuCjh/uYrWiMQSUuV+LpXwIqhgJDcvMTj+VsQmqAHL2yYaasENvJ7CDKA==",
"cpu": [
"ia32"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-loong64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.5.tgz",
"integrity": "sha512-0ur7ae16hDUC4OL5iEnDb0tZHDxYmuQyhKhsPBV8f99f6Z9KQM02g33f93rNH5A30agMS46u2HP6qTdEt6Q1kg==",
"cpu": [
"loong64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-mips64el": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.5.tgz",
"integrity": "sha512-kB/66P1OsHO5zLz0i6X0RxlQ+3cu0mkxS3TKFvkb5lin6uwZ/ttOkP3Z8lfR9mJOBk14ZwZ9182SIIWFGNmqmg==",
"cpu": [
"mips64el"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-ppc64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.5.tgz",
"integrity": "sha512-UZCmJ7r9X2fe2D6jBmkLBMQetXPXIsZjQJCjgwpVDz+YMcS6oFR27alkgGv3Oqkv07bxdvw7fyB71/olceJhkQ==",
"cpu": [
"ppc64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-riscv64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.5.tgz",
"integrity": "sha512-kTxwu4mLyeOlsVIFPfQo+fQJAV9mh24xL+y+Bm6ej067sYANjyEw1dNHmvoqxJUCMnkBdKpvOn0Ahql6+4VyeA==",
"cpu": [
"riscv64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-s390x": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.5.tgz",
"integrity": "sha512-K2dSKTKfmdh78uJ3NcWFiqyRrimfdinS5ErLSn3vluHNeHVnBAFWC8a4X5N+7FgVE1EjXS1QDZbpqZBjfrqMTQ==",
"cpu": [
"s390x"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-x64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.5.tgz",
"integrity": "sha512-uhj8N2obKTE6pSZ+aMUbqq+1nXxNjZIIjCjGLfsWvVpy7gKCOL6rsY1MhRh9zLtUtAI7vpgLMK6DxjO8Qm9lJw==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/netbsd-arm64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.5.tgz",
"integrity": "sha512-pwHtMP9viAy1oHPvgxtOv+OkduK5ugofNTVDilIzBLpoWAM16r7b/mxBvfpuQDpRQFMfuVr5aLcn4yveGvBZvw==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"netbsd"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/netbsd-x64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.5.tgz",
"integrity": "sha512-WOb5fKrvVTRMfWFNCroYWWklbnXH0Q5rZppjq0vQIdlsQKuw6mdSihwSo4RV/YdQ5UCKKvBy7/0ZZYLBZKIbwQ==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"netbsd"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/openbsd-arm64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.5.tgz",
"integrity": "sha512-7A208+uQKgTxHd0G0uqZO8UjK2R0DDb4fDmERtARjSHWxqMTye4Erz4zZafx7Di9Cv+lNHYuncAkiGFySoD+Mw==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"openbsd"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/openbsd-x64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.5.tgz",
"integrity": "sha512-G4hE405ErTWraiZ8UiSoesH8DaCsMm0Cay4fsFWOOUcz8b8rC6uCvnagr+gnioEjWn0wC+o1/TAHt+It+MpIMg==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"openbsd"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/sunos-x64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.5.tgz",
"integrity": "sha512-l+azKShMy7FxzY0Rj4RCt5VD/q8mG/e+mDivgspo+yL8zW7qEwctQ6YqKX34DTEleFAvCIUviCFX1SDZRSyMQA==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"sunos"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/win32-arm64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.5.tgz",
"integrity": "sha512-O2S7SNZzdcFG7eFKgvwUEZ2VG9D/sn/eIiz8XRZ1Q/DO5a3s76Xv0mdBzVM5j5R639lXQmPmSo0iRpHqUUrsxw==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/win32-ia32": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.5.tgz",
"integrity": "sha512-onOJ02pqs9h1iMJ1PQphR+VZv8qBMQ77Klcsqv9CNW2w6yLqoURLcgERAIurY6QE63bbLuqgP9ATqajFLK5AMQ==",
"cpu": [
"ia32"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/win32-x64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.5.tgz",
"integrity": "sha512-TXv6YnJ8ZMVdX+SXWVBo/0p8LTcrUYngpWjvm91TMjjBQii7Oz11Lw5lbDV5Y0TzuhSJHwiH4hEtC1I42mMS0g==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">=18"
}
},
"node_modules/esbuild": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.5.tgz",
"integrity": "sha512-P8OtKZRv/5J5hhz0cUAdu/cLuPIKXpQl1R9pZtvmHWQvrAUVd0UNIPT4IB4W3rNOqVO0rlqHmCIbSwxh/c9yUQ==",
"dev": true,
"hasInstallScript": true,
"license": "MIT",
"bin": {
"acorn": "bin/acorn"
"esbuild": "bin/esbuild"
},
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/base64-js": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
"dev": true,
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
],
"license": "MIT"
},
"node_modules/buffer-from": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
"dev": true,
"license": "MIT"
},
"node_modules/commander": {
"version": "11.1.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz",
"integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=16"
}
},
"node_modules/frida-compile": {
"version": "17.0.0",
"resolved": "https://registry.npmjs.org/frida-compile/-/frida-compile-17.0.0.tgz",
"integrity": "sha512-ixJRj14qLH/Z0ckFWd5fKeDMm0W2+2WDpSGnLRgpn0nuCQAbDHRCqVCWtPnV8uzPJmA6XOX0pujsMpYe9q9RRw==",
"dev": true,
"dependencies": {
"@frida/assert": "^3.0.1",
"@frida/base64-js": "^2.0.3",
"@frida/buffer": "^7.0.4",
"@frida/crosspath": "^3.0.0",
"@frida/crypto": "^1.0.1",
"@frida/diagnostics_channel": "^1.0.0",
"@frida/events": "^4.0.4",
"@frida/http": "^4.0.2",
"@frida/http-parser-js": "^1.0.0",
"@frida/https": "^1.0.0",
"@frida/ieee754": "^2.0.2",
"@frida/net": "^4.0.1",
"@frida/os": "^1.0.0",
"@frida/path": "^2.0.3",
"@frida/process": "^1.2.1",
"@frida/punycode": "^3.0.0",
"@frida/querystring": "^1.0.0",
"@frida/readable-stream": "^4.1.3",
"@frida/reserved-words": "^1.0.0",
"@frida/stream": "^1.0.2",
"@frida/string_decoder": "^2.0.0",
"@frida/terser": "^1.0.0",
"@frida/timers": "^3.0.0",
"@frida/tty": "^1.0.0",
"@frida/url": "^1.0.2",
"@frida/util": "^1.0.3",
"@frida/vm": "^2.0.0",
"commander": "^11.1.0",
"frida-fs": "^6.0.0",
"typed-emitter": "^2.1.0"
"node": ">=18"
},
"bin": {
"frida-compile": "dist/cli.js"
"optionalDependencies": {
"@esbuild/aix-ppc64": "0.25.5",
"@esbuild/android-arm": "0.25.5",
"@esbuild/android-arm64": "0.25.5",
"@esbuild/android-x64": "0.25.5",
"@esbuild/darwin-arm64": "0.25.5",
"@esbuild/darwin-x64": "0.25.5",
"@esbuild/freebsd-arm64": "0.25.5",
"@esbuild/freebsd-x64": "0.25.5",
"@esbuild/linux-arm": "0.25.5",
"@esbuild/linux-arm64": "0.25.5",
"@esbuild/linux-ia32": "0.25.5",
"@esbuild/linux-loong64": "0.25.5",
"@esbuild/linux-mips64el": "0.25.5",
"@esbuild/linux-ppc64": "0.25.5",
"@esbuild/linux-riscv64": "0.25.5",
"@esbuild/linux-s390x": "0.25.5",
"@esbuild/linux-x64": "0.25.5",
"@esbuild/netbsd-arm64": "0.25.5",
"@esbuild/netbsd-x64": "0.25.5",
"@esbuild/openbsd-arm64": "0.25.5",
"@esbuild/openbsd-x64": "0.25.5",
"@esbuild/sunos-x64": "0.25.5",
"@esbuild/win32-arm64": "0.25.5",
"@esbuild/win32-ia32": "0.25.5",
"@esbuild/win32-x64": "0.25.5"
}
},
"node_modules/frida-fs": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/frida-fs/-/frida-fs-6.0.0.tgz",
"integrity": "sha512-I0fnKupZh7fU2ixwCIjJnEqNdhfm/SC1ZYBMy58EmeqOWSbjw1Dpy99mJ7BJdbk2KNXJeaBZGxDYLtn0J9S+UA==",
"dev": true,
"license": "MIT"
},
"node_modules/frida-objc-bridge": {
"version": "8.0.4",
"resolved": "https://registry.npmjs.org/frida-objc-bridge/-/frida-objc-bridge-8.0.4.tgz",
"integrity": "sha512-AUzwq/+TFtblQLTI97UPX22pBcvyG2oUde9380DXbcJ0zXts4n9JDVONHUr03aBowa0Le+bdBoVdCs7jyyjvlg==",
"version": "8.0.5",
"resolved": "https://registry.npmjs.org/frida-objc-bridge/-/frida-objc-bridge-8.0.5.tgz",
"integrity": "sha512-0xnL0VgxSQXgLj3S33S0kdAvLrCHSCIZb9HVraEgEyKnf9wOcu0KZ9fI5xzx0e0y+ry/g2Vl3yw9j3dsn92Ffg==",
"license": "LGPL-2.0 WITH WxWindows-exception-3.1"
},
"node_modules/http-parser-js": {
"version": "0.5.10",
"resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.10.tgz",
"integrity": "sha512-Pysuw9XpUq5dVc/2SMHpuTY01RFl8fttgcyunjL7eEMhGM3cI4eOmiCycJDVCo/7O7ClfQD3SaI6ftDzqOXYMA==",
"dev": true,
"license": "MIT"
},
"node_modules/ieee754": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
"integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
"dev": true,
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
],
"license": "BSD-3-Clause"
},
"node_modules/rxjs": {
"version": "7.8.2",
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz",
"integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==",
"dev": true,
"license": "Apache-2.0",
"optional": true,
"dependencies": {
"tslib": "^2.1.0"
}
},
"node_modules/source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
"dev": true,
"license": "BSD-3-Clause",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/source-map-support": {
"version": "0.5.21",
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
"integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
"dev": true,
"license": "MIT",
"dependencies": {
"buffer-from": "^1.0.0",
"source-map": "^0.6.0"
}
},
"node_modules/tslib": {
"version": "2.8.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
"dev": true,
"license": "0BSD",
"optional": true
},
"node_modules/typed-emitter": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/typed-emitter/-/typed-emitter-2.1.0.tgz",
"integrity": "sha512-g/KzbYKbH5C2vPkaXGu8DJlHrGKHLsM25Zg9WuC9pMGfuvT+X25tZQWo5fK1BjBm8+UrVE9LDCvaY0CQk+fXDA==",
"dev": true,
"license": "MIT",
"optionalDependencies": {
"rxjs": "*"
}
}
}
}
+4 -5
View File
@@ -2,15 +2,14 @@
"name": "frida-reportcrash-agent",
"version": "1.0.0",
"description": "Agent used by Frida's Darwin backend on iOS/iPadOS/tvOS",
"type": "module",
"scripts": {
"prepare": "npm run build",
"build": "frida-compile index.js -o reportcrash.js -S -c"
"build": "esbuild index.js --outfile=reportcrash.js --bundle --platform=node --target=es2022 --minify"
},
"devDependencies": {
"@types/frida-gum": "^19.0.0",
"frida-compile": "^17.0.0"
"esbuild": "^0.25.5"
},
"dependencies": {
"frida-objc-bridge": "^8.0.4"
"frida-objc-bridge": "^8.0.5"
}
}
+2
View File
@@ -109,6 +109,8 @@ _frida_get_springboard_api (void)
gum_interceptor_replace (interceptor, frida_xpc_look_up_endpoint, frida_replacement_xpc_look_up_endpoint, NULL, NULL);
else
g_error ("Unable to locate _xpc_look_up_endpoint(); please file a bug");
g_object_unref (interceptor);
}
#endif
+5 -1
View File
@@ -1459,7 +1459,9 @@ namespace Frida {
break;
}
}
assert (session_id != null);
if (session_id == null)
return;
agent_sessions.unset (session_id);
if (may_block) {
@@ -1483,6 +1485,8 @@ namespace Frida {
Promise<bool> detach_request;
if (pending_detach_requests.unset (id, out detach_request))
detach_request.resolve (true);
else if (session != null)
agent_sessions.unset (id);
}
private void on_spawn_added (HostSpawnInfo info) {
+11 -1
View File
@@ -454,7 +454,7 @@ namespace Frida.Fruity {
write_entry (entry);
size_t offset_table_offset = (size_t) seekable.tell ();
offset_size = compute_offset_size (sorted_entries.last ().offset);
offset_size = compute_offset_size (offset_table_offset);
foreach (var entry in sorted_entries)
write_offset (entry.offset);
@@ -1088,6 +1088,11 @@ namespace Frida.Fruity {
}
public void write_dict (PlistDict dict) {
if (dict.is_empty) {
write_line ("<dict/>");
return;
}
write_line ("<dict>");
level++;
@@ -1114,6 +1119,11 @@ namespace Frida.Fruity {
}
public void write_array (PlistArray array) {
if (array.is_empty) {
write_line ("<array/>");
return;
}
write_line ("<array>");
level++;
+22
View File
@@ -0,0 +1,22 @@
import esbuild from 'esbuild';
import alias from 'esbuild-plugin-alias';
import { createRequire } from 'module';
const require = createRequire(import.meta.url);
const BUFFER_SHIM = require.resolve('@frida/buffer');
esbuild.build({
entryPoints: ['index.js'],
outfile: 'system-server.js',
bundle: true,
platform: 'node',
target: ['es2022'],
legalComments: 'none',
minify: true,
plugins: [
alias({
'buffer': BUFFER_SHIM,
'node:buffer': BUFFER_SHIM,
}),
],
}).catch(() => process.exit(1));
@@ -2,6 +2,7 @@ system_server_js = custom_target('system-server.js',
input: [
'package.json',
'package-lock.json',
'build.js',
'index.js',
],
output: [
+470 -460
View File
@@ -8,46 +8,443 @@
"name": "frida-system-server-agent",
"version": "1.0.0",
"dependencies": {
"frida-java-bridge": "^7.0.1"
"@frida/buffer": "^7.0.4",
"frida-java-bridge": "^7.0.4"
},
"devDependencies": {
"@types/frida-gum": "^19.0.0",
"frida-compile": "^17.0.0"
"esbuild": "^0.25.5",
"esbuild-plugin-alias": "^0.2.1"
}
},
"node_modules/@frida/assert": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/@frida/assert/-/assert-3.0.2.tgz",
"integrity": "sha512-JXJq5SbXGrM5EkjrZKfRmB29zOoEOix02NC6A5TSJ+C1GE/X051EinJJsuOO2pEOx7KZwpvAHvS0WXW0+levKg==",
"dev": true,
"license": "MIT"
},
"node_modules/@frida/base64-js": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/@frida/base64-js/-/base64-js-2.0.3.tgz",
"integrity": "sha512-2w0F+1TynOTCZ/v7du9LdHPWwq0lJhazjo2fF9upMyQmA1zHetT14fLuQ1v/6T0qPgyeEGkiSrybstU8EsgeUA==",
"dev": true,
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
"node_modules/@esbuild/aix-ppc64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.5.tgz",
"integrity": "sha512-9o3TMmpmftaCMepOdA5k/yDw8SfInyzWWTjYTFCX3kPSDJMROQTb8jg+h9Cnwnmm1vOzvxN7gIfB5V2ewpjtGA==",
"cpu": [
"ppc64"
],
"license": "MIT"
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"aix"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/android-arm": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.5.tgz",
"integrity": "sha512-AdJKSPeEHgi7/ZhuIPtcQKr5RQdo6OO2IL87JkianiMYMPbCtot9fxPbrMiBADOWWm3T2si9stAiVsGbTQFkbA==",
"cpu": [
"arm"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"android"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/android-arm64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.5.tgz",
"integrity": "sha512-VGzGhj4lJO+TVGV1v8ntCZWJktV7SGCs3Pn1GRWI1SBFtRALoomm8k5E9Pmwg3HOAal2VDc2F9+PM/rEY6oIDg==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"android"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/android-x64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.5.tgz",
"integrity": "sha512-D2GyJT1kjvO//drbRT3Hib9XPwQeWd9vZoBJn+bu/lVsOZ13cqNdDeqIF/xQ5/VmWvMduP6AmXvylO/PIc2isw==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"android"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/darwin-arm64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.5.tgz",
"integrity": "sha512-GtaBgammVvdF7aPIgH2jxMDdivezgFu6iKpmT+48+F8Hhg5J/sfnDieg0aeG/jfSvkYQU2/pceFPDKlqZzwnfQ==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/darwin-x64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.5.tgz",
"integrity": "sha512-1iT4FVL0dJ76/q1wd7XDsXrSW+oLoquptvh4CLR4kITDtqi2e/xwXwdCVH8hVHU43wgJdsq7Gxuzcs6Iq/7bxQ==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/freebsd-arm64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.5.tgz",
"integrity": "sha512-nk4tGP3JThz4La38Uy/gzyXtpkPW8zSAmoUhK9xKKXdBCzKODMc2adkB2+8om9BDYugz+uGV7sLmpTYzvmz6Sw==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"freebsd"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/freebsd-x64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.5.tgz",
"integrity": "sha512-PrikaNjiXdR2laW6OIjlbeuCPrPaAl0IwPIaRv+SMV8CiM8i2LqVUHFC1+8eORgWyY7yhQY+2U2fA55mBzReaw==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"freebsd"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-arm": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.5.tgz",
"integrity": "sha512-cPzojwW2okgh7ZlRpcBEtsX7WBuqbLrNXqLU89GxWbNt6uIg78ET82qifUy3W6OVww6ZWobWub5oqZOVtwolfw==",
"cpu": [
"arm"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-arm64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.5.tgz",
"integrity": "sha512-Z9kfb1v6ZlGbWj8EJk9T6czVEjjq2ntSYLY2cw6pAZl4oKtfgQuS4HOq41M/BcoLPzrUbNd+R4BXFyH//nHxVg==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-ia32": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.5.tgz",
"integrity": "sha512-sQ7l00M8bSv36GLV95BVAdhJ2QsIbCuCjh/uYrWiMQSUuV+LpXwIqhgJDcvMTj+VsQmqAHL2yYaasENvJ7CDKA==",
"cpu": [
"ia32"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-loong64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.5.tgz",
"integrity": "sha512-0ur7ae16hDUC4OL5iEnDb0tZHDxYmuQyhKhsPBV8f99f6Z9KQM02g33f93rNH5A30agMS46u2HP6qTdEt6Q1kg==",
"cpu": [
"loong64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-mips64el": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.5.tgz",
"integrity": "sha512-kB/66P1OsHO5zLz0i6X0RxlQ+3cu0mkxS3TKFvkb5lin6uwZ/ttOkP3Z8lfR9mJOBk14ZwZ9182SIIWFGNmqmg==",
"cpu": [
"mips64el"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-ppc64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.5.tgz",
"integrity": "sha512-UZCmJ7r9X2fe2D6jBmkLBMQetXPXIsZjQJCjgwpVDz+YMcS6oFR27alkgGv3Oqkv07bxdvw7fyB71/olceJhkQ==",
"cpu": [
"ppc64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-riscv64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.5.tgz",
"integrity": "sha512-kTxwu4mLyeOlsVIFPfQo+fQJAV9mh24xL+y+Bm6ej067sYANjyEw1dNHmvoqxJUCMnkBdKpvOn0Ahql6+4VyeA==",
"cpu": [
"riscv64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-s390x": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.5.tgz",
"integrity": "sha512-K2dSKTKfmdh78uJ3NcWFiqyRrimfdinS5ErLSn3vluHNeHVnBAFWC8a4X5N+7FgVE1EjXS1QDZbpqZBjfrqMTQ==",
"cpu": [
"s390x"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-x64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.5.tgz",
"integrity": "sha512-uhj8N2obKTE6pSZ+aMUbqq+1nXxNjZIIjCjGLfsWvVpy7gKCOL6rsY1MhRh9zLtUtAI7vpgLMK6DxjO8Qm9lJw==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/netbsd-arm64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.5.tgz",
"integrity": "sha512-pwHtMP9viAy1oHPvgxtOv+OkduK5ugofNTVDilIzBLpoWAM16r7b/mxBvfpuQDpRQFMfuVr5aLcn4yveGvBZvw==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"netbsd"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/netbsd-x64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.5.tgz",
"integrity": "sha512-WOb5fKrvVTRMfWFNCroYWWklbnXH0Q5rZppjq0vQIdlsQKuw6mdSihwSo4RV/YdQ5UCKKvBy7/0ZZYLBZKIbwQ==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"netbsd"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/openbsd-arm64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.5.tgz",
"integrity": "sha512-7A208+uQKgTxHd0G0uqZO8UjK2R0DDb4fDmERtARjSHWxqMTye4Erz4zZafx7Di9Cv+lNHYuncAkiGFySoD+Mw==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"openbsd"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/openbsd-x64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.5.tgz",
"integrity": "sha512-G4hE405ErTWraiZ8UiSoesH8DaCsMm0Cay4fsFWOOUcz8b8rC6uCvnagr+gnioEjWn0wC+o1/TAHt+It+MpIMg==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"openbsd"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/sunos-x64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.5.tgz",
"integrity": "sha512-l+azKShMy7FxzY0Rj4RCt5VD/q8mG/e+mDivgspo+yL8zW7qEwctQ6YqKX34DTEleFAvCIUviCFX1SDZRSyMQA==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"sunos"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/win32-arm64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.5.tgz",
"integrity": "sha512-O2S7SNZzdcFG7eFKgvwUEZ2VG9D/sn/eIiz8XRZ1Q/DO5a3s76Xv0mdBzVM5j5R639lXQmPmSo0iRpHqUUrsxw==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/win32-ia32": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.5.tgz",
"integrity": "sha512-onOJ02pqs9h1iMJ1PQphR+VZv8qBMQ77Klcsqv9CNW2w6yLqoURLcgERAIurY6QE63bbLuqgP9ATqajFLK5AMQ==",
"cpu": [
"ia32"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/win32-x64": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.5.tgz",
"integrity": "sha512-TXv6YnJ8ZMVdX+SXWVBo/0p8LTcrUYngpWjvm91TMjjBQii7Oz11Lw5lbDV5Y0TzuhSJHwiH4hEtC1I42mMS0g==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@frida/buffer": {
"version": "7.0.4",
"resolved": "https://registry.npmjs.org/@frida/buffer/-/buffer-7.0.4.tgz",
"integrity": "sha512-RxQ1lZRRiCJj7nhcCiD8xeJx0NsLpGGnjqsmTg7jShGmbnVFMN5W7+J+3gqdPSQhc/IxNBIWc6zRXVp4+qnYHg==",
"dev": true,
"funding": [
{
"type": "github",
@@ -68,322 +465,10 @@
"ieee754": "^1.2.1"
}
},
"node_modules/@frida/crosspath": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/@frida/crosspath/-/crosspath-3.0.0.tgz",
"integrity": "sha512-bNdO1spIPD2P40XtK89N49oZpJhstdlnkJZcD4yJ17jrdkm9Ctu0sd9MIEX6Z8Tm8ydhVJBAOMEKl9/R27onAQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/node": "^17.0.36"
},
"engines": {
"node": ">=14.9.0"
}
},
"node_modules/@frida/crypto": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@frida/crypto/-/crypto-1.0.1.tgz",
"integrity": "sha512-WXTkVjESvX8TIVXIynJJv9BKSIdQP0Iis04StIXknkDi1ULdMlrypA9p5C4KW1H6GCkNsVnKbybpzsulYCTvag==",
"dev": true,
"license": "MIT"
},
"node_modules/@frida/diagnostics_channel": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@frida/diagnostics_channel/-/diagnostics_channel-1.0.0.tgz",
"integrity": "sha512-mYX1jp/5Bpk24tHArJNx65iCk7qSuV8YJkdU0gFNVtJUXxfV8BG5WuPa4mL+ynxsbWWpsg/cwKZbLAepYKTdQQ==",
"dev": true,
"license": "MIT"
},
"node_modules/@frida/events": {
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/@frida/events/-/events-4.0.4.tgz",
"integrity": "sha512-qJVQ6VWHf9sjUKuiJzoCAC00frbpcwxeYfvQ+PP9LU/d70j+QvjWgYe98Qa3ekLaBU6r/AvWm8ThKCDUCLWrQQ==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=0.8.x"
}
},
"node_modules/@frida/http": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/@frida/http/-/http-4.0.2.tgz",
"integrity": "sha512-cvkc7ex7GmVXVOWqtjXKBWUUbYEBgpNRKZbEEoMeI8KiIs8zejKwg+N7rx7296Ao+EP3+xcUr4wBVr3xLaUVfQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"http-parser-js": "^0.5.3"
}
},
"node_modules/@frida/http-parser-js": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@frida/http-parser-js/-/http-parser-js-1.0.0.tgz",
"integrity": "sha512-2nMrNXt/OeTlWbqnE8AH4Sfz4I2+BGoN206dzKEyC/g2svtn83Xu+zuv/V3TkwrA27s26Mcy84ZwsXeNlqNxUQ==",
"dev": true,
"license": "MIT"
},
"node_modules/@frida/https": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@frida/https/-/https-1.0.0.tgz",
"integrity": "sha512-OiqQ6qsALcWOktRLq07oJ0i6sH8eX6MXb/MdZS1qVKDRf6wchH4Pjn6fiLB+pt/OlYbggk+DOfpHwSdjTwuHMQ==",
"dev": true,
"license": "MIT"
},
"node_modules/@frida/ieee754": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/@frida/ieee754/-/ieee754-2.0.2.tgz",
"integrity": "sha512-wlcUebnne4ENN7GDr5pTH598ZDLMVOsh0FjenxeVOe6u7ewZkz9gGRnLnZKJAm9kl5G6XhdxhI0cSXVQK/rQUw==",
"dev": true,
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
],
"license": "BSD-3-Clause"
},
"node_modules/@frida/net": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/@frida/net/-/net-4.0.2.tgz",
"integrity": "sha512-qQRe7hQ+ZfCcG/SE3P1TRqQ9bmuK/T7wPCYaT4z56rBPWAxsaQbQHpX4fR6OrFaSDr7X0xJLsTbdIp9hGhhLZg==",
"dev": true,
"license": "MIT"
},
"node_modules/@frida/os": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@frida/os/-/os-1.0.2.tgz",
"integrity": "sha512-3ISAiGNiyIya3QN2EHBCz1wqP0enTdSxP99wUeroeh8+AQRmgoOr/5TRnrVry8pe378anay3fmV/tdUMMSkehQ==",
"dev": true,
"license": "MIT"
},
"node_modules/@frida/path": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/@frida/path/-/path-2.0.3.tgz",
"integrity": "sha512-2RQy36QatoC846fzBhBhV8sXMsSOBGoYvwTHeaE1zUdz7F4RNScP4QEekTTooBYWYX/XjiF36KQpYAzc9OYFtg==",
"dev": true,
"license": "MIT"
},
"node_modules/@frida/process": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/@frida/process/-/process-1.2.1.tgz",
"integrity": "sha512-nvCu22DstFW2ttGFtOKekHM7vnjbZm+XgtvavOt427GNT6uV7k0JYK9tnMbcLMRWv57DG6udAmuJlWs8Paq1ag==",
"dev": true,
"license": "MIT"
},
"node_modules/@frida/punycode": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/@frida/punycode/-/punycode-3.0.0.tgz",
"integrity": "sha512-XVSDY2KamDs1D5/fTVgHcOSNxdU4kTboxzqJMBbTjcQC7XScIT9c0EfbwKCq7Kci6gWQdsHSCr7lU+9Oc4KAdg==",
"dev": true,
"license": "MIT"
},
"node_modules/@frida/querystring": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@frida/querystring/-/querystring-1.0.0.tgz",
"integrity": "sha512-15m1fOZPmoO/vWlgPJrG/J9/BJDz6a2/JpVGpS8ynNzo+fBhTznaStX5nHxUs24mVTqh/OqLo0EiYJM5WWHXxg==",
"dev": true,
"license": "MIT"
},
"node_modules/@frida/readable-stream": {
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/@frida/readable-stream/-/readable-stream-4.1.3.tgz",
"integrity": "sha512-ntGUFmi+CryRGRJIK13a/VST2Ad19uivbln8Xd92vKPAARq+6vMIASDyZIqyl5BLRccfiyCHdYgrgQ6RI5rUig==",
"dev": true,
"license": "MIT"
},
"node_modules/@frida/reserved-words": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@frida/reserved-words/-/reserved-words-1.0.0.tgz",
"integrity": "sha512-2yG/XxJlsGlk/mm6eZTb4OAaQEhkTI2qaFfZFtAsrA/XuCpuMWkS4y/guyBlsRu4hAuhK2HPmNM8+OLLK1zM9Q==",
"dev": true,
"license": "MIT"
},
"node_modules/@frida/stream": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@frida/stream/-/stream-1.0.2.tgz",
"integrity": "sha512-4OuaC1ztmEKgTq3WeBhsy8Oq+AwW9n9cYnvLklcC9jwD93AEwgbWpecLlxJCVuALvTMdhKPg0nQVfyGYP/i9Bw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@frida/readable-stream": "^4.1.3"
}
},
"node_modules/@frida/string_decoder": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@frida/string_decoder/-/string_decoder-2.0.0.tgz",
"integrity": "sha512-in371tYZMHQiW9HF5MS3JDw6Ao6tyBoq34UWy2rzOswYyMG1rpizh85ofi/yVkxDiaqybEZefxzkVittpPGT6g==",
"dev": true,
"license": "MIT"
},
"node_modules/@frida/terser": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@frida/terser/-/terser-1.0.0.tgz",
"integrity": "sha512-59h9WuNzD1Rx/zwoWqQ/FW/4Y/Q3R91Eng2hEwdHapqiTDvtKbZ08F6CynCR7ZVinrh4tLYsF46AtVPTz1ys9g==",
"dev": true,
"license": "BSD-2-Clause",
"dependencies": {
"@jridgewell/source-map": "^0.3.2",
"acorn": "^8.5.0",
"commander": "^2.20.0",
"source-map-support": "~0.5.20"
},
"bin": {
"terser": "bin/terser"
},
"engines": {
"node": ">=10"
}
},
"node_modules/@frida/terser/node_modules/commander": {
"version": "2.20.3",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
"dev": true,
"license": "MIT"
},
"node_modules/@frida/timers": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/@frida/timers/-/timers-3.0.0.tgz",
"integrity": "sha512-3b+0igv10aT8TMxefrTAd06rActqbxJLY2Xkkq9vYcPBffB/yHszl0NYIp/5ko8WC3ecDYPU6bQiY6fjs72zTA==",
"dev": true,
"license": "MIT"
},
"node_modules/@frida/tty": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@frida/tty/-/tty-1.0.0.tgz",
"integrity": "sha512-p/kjLnKYxEAB1MdYP8+5rKv9CsHzyA+0jg9BcGETzjQVKHHcroHDULRxDYUh+DC7qs6cpX8QdDQh9E+a6ydgsQ==",
"dev": true,
"license": "MIT"
},
"node_modules/@frida/url": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@frida/url/-/url-1.0.2.tgz",
"integrity": "sha512-ZKunbKJHMr8w2Eb/5K1avy0MzK1B998S17wYXNv3RmzBGxMm8S5T0F3qEpRxkU7/72P8m4izyQU87fWl+FjQsQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@frida/punycode": "^3.0.0",
"@frida/querystring": "^1.0.0"
}
},
"node_modules/@frida/util": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/@frida/util/-/util-1.0.3.tgz",
"integrity": "sha512-htcG3uDiRXv89ERVNNYhfase39kJ2X75ZARfrYcYEtJLFEsSk0nemM1YnEIR4CjrHvdvkWHrwgKkS+acOyoNEg==",
"dev": true,
"license": "MIT"
},
"node_modules/@frida/vm": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@frida/vm/-/vm-2.0.0.tgz",
"integrity": "sha512-7fsjLWscZT5odNIBtg6qbLNI+vAk1xmii6H5W2kaYkMYt0vRohQEcDSUWacA+eaWlu5SvMjZI82Yibj/3G9pJw==",
"dev": true,
"license": "MIT"
},
"node_modules/@jridgewell/gen-mapping": {
"version": "0.3.8",
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz",
"integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@jridgewell/set-array": "^1.2.1",
"@jridgewell/sourcemap-codec": "^1.4.10",
"@jridgewell/trace-mapping": "^0.3.24"
},
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/@jridgewell/resolve-uri": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
"integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/@jridgewell/set-array": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz",
"integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/@jridgewell/source-map": {
"version": "0.3.6",
"resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz",
"integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@jridgewell/gen-mapping": "^0.3.5",
"@jridgewell/trace-mapping": "^0.3.25"
}
},
"node_modules/@jridgewell/sourcemap-codec": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz",
"integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==",
"dev": true,
"license": "MIT"
},
"node_modules/@jridgewell/trace-mapping": {
"version": "0.3.25",
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz",
"integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@jridgewell/resolve-uri": "^3.1.0",
"@jridgewell/sourcemap-codec": "^1.4.14"
}
},
"node_modules/@types/frida-gum": {
"version": "19.0.0",
"resolved": "https://registry.npmjs.org/@types/frida-gum/-/frida-gum-19.0.0.tgz",
"integrity": "sha512-qViK1KwvPEAkajwSUv0wpZvZLiX8xO4JFFCh8dfYZfzSyOEfoE0KliCP/nJSKIKG6N3hXnPowrvPufjs5fLKAA==",
"dev": true,
"license": "MIT"
},
"node_modules/@types/node": {
"version": "17.0.45",
"resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.45.tgz",
"integrity": "sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==",
"dev": true,
"license": "MIT"
},
"node_modules/acorn": {
"version": "8.14.1",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz",
"integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==",
"dev": true,
"license": "MIT",
"bin": {
"acorn": "bin/acorn"
},
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/base64-js": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
"dev": true,
"funding": [
{
"type": "github",
@@ -400,89 +485,64 @@
],
"license": "MIT"
},
"node_modules/buffer-from": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
"dev": true,
"license": "MIT"
},
"node_modules/commander": {
"version": "11.1.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz",
"integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==",
"node_modules/esbuild": {
"version": "0.25.5",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.5.tgz",
"integrity": "sha512-P8OtKZRv/5J5hhz0cUAdu/cLuPIKXpQl1R9pZtvmHWQvrAUVd0UNIPT4IB4W3rNOqVO0rlqHmCIbSwxh/c9yUQ==",
"dev": true,
"hasInstallScript": true,
"license": "MIT",
"engines": {
"node": ">=16"
}
},
"node_modules/frida-compile": {
"version": "17.0.0",
"resolved": "https://registry.npmjs.org/frida-compile/-/frida-compile-17.0.0.tgz",
"integrity": "sha512-ixJRj14qLH/Z0ckFWd5fKeDMm0W2+2WDpSGnLRgpn0nuCQAbDHRCqVCWtPnV8uzPJmA6XOX0pujsMpYe9q9RRw==",
"dev": true,
"dependencies": {
"@frida/assert": "^3.0.1",
"@frida/base64-js": "^2.0.3",
"@frida/buffer": "^7.0.4",
"@frida/crosspath": "^3.0.0",
"@frida/crypto": "^1.0.1",
"@frida/diagnostics_channel": "^1.0.0",
"@frida/events": "^4.0.4",
"@frida/http": "^4.0.2",
"@frida/http-parser-js": "^1.0.0",
"@frida/https": "^1.0.0",
"@frida/ieee754": "^2.0.2",
"@frida/net": "^4.0.1",
"@frida/os": "^1.0.0",
"@frida/path": "^2.0.3",
"@frida/process": "^1.2.1",
"@frida/punycode": "^3.0.0",
"@frida/querystring": "^1.0.0",
"@frida/readable-stream": "^4.1.3",
"@frida/reserved-words": "^1.0.0",
"@frida/stream": "^1.0.2",
"@frida/string_decoder": "^2.0.0",
"@frida/terser": "^1.0.0",
"@frida/timers": "^3.0.0",
"@frida/tty": "^1.0.0",
"@frida/url": "^1.0.2",
"@frida/util": "^1.0.3",
"@frida/vm": "^2.0.0",
"commander": "^11.1.0",
"frida-fs": "^6.0.0",
"typed-emitter": "^2.1.0"
},
"bin": {
"frida-compile": "dist/cli.js"
"esbuild": "bin/esbuild"
},
"engines": {
"node": ">=18"
},
"optionalDependencies": {
"@esbuild/aix-ppc64": "0.25.5",
"@esbuild/android-arm": "0.25.5",
"@esbuild/android-arm64": "0.25.5",
"@esbuild/android-x64": "0.25.5",
"@esbuild/darwin-arm64": "0.25.5",
"@esbuild/darwin-x64": "0.25.5",
"@esbuild/freebsd-arm64": "0.25.5",
"@esbuild/freebsd-x64": "0.25.5",
"@esbuild/linux-arm": "0.25.5",
"@esbuild/linux-arm64": "0.25.5",
"@esbuild/linux-ia32": "0.25.5",
"@esbuild/linux-loong64": "0.25.5",
"@esbuild/linux-mips64el": "0.25.5",
"@esbuild/linux-ppc64": "0.25.5",
"@esbuild/linux-riscv64": "0.25.5",
"@esbuild/linux-s390x": "0.25.5",
"@esbuild/linux-x64": "0.25.5",
"@esbuild/netbsd-arm64": "0.25.5",
"@esbuild/netbsd-x64": "0.25.5",
"@esbuild/openbsd-arm64": "0.25.5",
"@esbuild/openbsd-x64": "0.25.5",
"@esbuild/sunos-x64": "0.25.5",
"@esbuild/win32-arm64": "0.25.5",
"@esbuild/win32-ia32": "0.25.5",
"@esbuild/win32-x64": "0.25.5"
}
},
"node_modules/frida-fs": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/frida-fs/-/frida-fs-6.0.0.tgz",
"integrity": "sha512-I0fnKupZh7fU2ixwCIjJnEqNdhfm/SC1ZYBMy58EmeqOWSbjw1Dpy99mJ7BJdbk2KNXJeaBZGxDYLtn0J9S+UA==",
"node_modules/esbuild-plugin-alias": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/esbuild-plugin-alias/-/esbuild-plugin-alias-0.2.1.tgz",
"integrity": "sha512-jyfL/pwPqaFXyKnj8lP8iLk6Z0m099uXR45aSN8Av1XD4vhvQutxxPzgA2bTcAwQpa1zCXDcWOlhFgyP3GKqhQ==",
"dev": true,
"license": "MIT"
},
"node_modules/frida-java-bridge": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/frida-java-bridge/-/frida-java-bridge-7.0.1.tgz",
"integrity": "sha512-pyNv12Y+erFgqdbFMsECh1OfqS77E62GeKHtxaBOZUPSpqcEkL0T2/6q/XD2161S4eGYBn6V7zumH2gbxtXK/Q==",
"version": "7.0.4",
"resolved": "https://registry.npmjs.org/frida-java-bridge/-/frida-java-bridge-7.0.4.tgz",
"integrity": "sha512-dE5XCvasUwA/wiVb5gSwBPf6dortI8VtD0qLlw2T0ryqX/0lg4BEtEkg1oRr9IlHDVBTjPOqe9KRzdPar8U3EQ==",
"license": "LGPL-2.0 WITH WxWindows-exception-3.1"
},
"node_modules/http-parser-js": {
"version": "0.5.10",
"resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.10.tgz",
"integrity": "sha512-Pysuw9XpUq5dVc/2SMHpuTY01RFl8fttgcyunjL7eEMhGM3cI4eOmiCycJDVCo/7O7ClfQD3SaI6ftDzqOXYMA==",
"dev": true,
"license": "MIT"
},
"node_modules/ieee754": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
"integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
"dev": true,
"funding": [
{
"type": "github",
@@ -498,56 +558,6 @@
}
],
"license": "BSD-3-Clause"
},
"node_modules/rxjs": {
"version": "7.8.2",
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz",
"integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==",
"dev": true,
"license": "Apache-2.0",
"optional": true,
"dependencies": {
"tslib": "^2.1.0"
}
},
"node_modules/source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
"dev": true,
"license": "BSD-3-Clause",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/source-map-support": {
"version": "0.5.21",
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
"integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
"dev": true,
"license": "MIT",
"dependencies": {
"buffer-from": "^1.0.0",
"source-map": "^0.6.0"
}
},
"node_modules/tslib": {
"version": "2.8.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
"dev": true,
"license": "0BSD",
"optional": true
},
"node_modules/typed-emitter": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/typed-emitter/-/typed-emitter-2.1.0.tgz",
"integrity": "sha512-g/KzbYKbH5C2vPkaXGu8DJlHrGKHLsM25Zg9WuC9pMGfuvT+X25tZQWo5fK1BjBm8+UrVE9LDCvaY0CQk+fXDA==",
"dev": true,
"license": "MIT",
"optionalDependencies": {
"rxjs": "*"
}
}
}
}
+6 -5
View File
@@ -2,15 +2,16 @@
"name": "frida-system-server-agent",
"version": "1.0.0",
"description": "Agent used by Frida's Linux backend on Android",
"type": "module",
"scripts": {
"prepare": "npm run build",
"build": "frida-compile index.js -o system-server.js -S -c"
"build": "node build.js"
},
"devDependencies": {
"@types/frida-gum": "^19.0.0",
"frida-compile": "^17.0.0"
"esbuild": "^0.25.5",
"esbuild-plugin-alias": "^0.2.1"
},
"dependencies": {
"frida-java-bridge": "^7.0.1"
"@frida/buffer": "^7.0.4",
"frida-java-bridge": "^7.0.4"
}
}
-105
View File
@@ -3167,114 +3167,9 @@ namespace Frida {
return Linux.syscall (SysCall.tgkill, tgid, tid, sig);
}
private uint linux_major = 0;
private uint linux_minor = 0;
public bool check_kernel_version (uint major, uint minor) {
if (linux_major == 0) {
var name = Posix.utsname ();
name.release.scanf ("%u.%u", out linux_major, out linux_minor);
}
return (linux_major == major && linux_minor >= minor) || linux_major > major;
}
public extern bool _syscall_satisfies (int syscall_id, LinuxSyscall mask);
public class FileDescriptor : Object, FileDescriptorBased {
public int handle;
public FileDescriptor (int handle) {
this.handle = handle;
}
~FileDescriptor () {
if (handle != -1)
Posix.close (handle);
}
public int steal () {
int result = handle;
handle = -1;
return result;
}
public int get_fd () {
return handle;
}
}
public sealed class PidFileDescriptor : FileDescriptor {
private uint pid;
private PidFileDescriptor (int fd, uint pid) {
base (fd);
this.pid = pid;
}
public static bool is_supported () {
return check_kernel_version (5, 3);
}
public static bool getfd_is_supported () {
return check_kernel_version (5, 6);
}
public static PidFileDescriptor from_pid (uint pid) throws Error {
int fd = pidfd_open (pid, 0);
if (fd == -1)
throw_pidfd_error (pid, errno);
return new PidFileDescriptor (fd, pid);
}
public FileDescriptor getfd (int targetfd) throws Error {
int fd = pidfd_getfd (handle, targetfd, 0);
if (fd == -1)
throw_pidfd_error (pid, errno);
return new FileDescriptor (fd);
}
private static int pidfd_open (uint pid, uint flags) {
return Linux.syscall (SysCall.pidfd_open, pid, flags);
}
private static int pidfd_getfd (int pidfd, int targetfd, uint flags) {
return Linux.syscall (SysCall.pidfd_getfd, pidfd, targetfd, flags);
}
[NoReturn]
private static void throw_pidfd_error (uint pid, int err) throws Error {
switch (err) {
case Posix.ESRCH:
throw new Error.PROCESS_NOT_FOUND ("Process not found");
case Posix.EPERM:
throw new Error.PERMISSION_DENIED ("Unable to use pidfd for pid %u: %s", pid, strerror (err));
default:
throw new Error.NOT_SUPPORTED ("Unable to use pidfd for pid %u: %s", pid, strerror (err));
}
}
}
namespace MemoryFileDescriptor {
public bool is_supported () {
return check_kernel_version (3, 17);
}
public static FileDescriptor from_bytes (string name, Bytes bytes) {
assert (is_supported ());
var fd = new FileDescriptor (memfd_create (name, 0));
unowned uint8[] data = bytes.get_data ();
ssize_t n = Posix.write (fd.handle, data, data.length);
assert (n == data.length);
return fd;
}
private int memfd_create (string name, uint flags) {
return Linux.syscall (SysCall.memfd_create, name, flags);
}
}
private void make_pty (out FileDescriptor read, out FileDescriptor write) throws Error {
#if HAVE_OPENPTY
int rfd = -1, wfd = -1;
-6
View File
@@ -84,12 +84,6 @@ build_arch () {
export CC="gcc -m32" CXX="g++ -m32" STRIP="strip"
fi
case "$ARCH" in
armbe8 | arm64be | arm64beilp32)
EXTRA_FLAGS+=("--without-prebuilds=sdk:host")
;;
esac
cd "$FRIDA_CORE_DIR"
rm -rf "$BUILD_DIR"
+3 -3
View File
@@ -1,6 +1,7 @@
base_sources = [
'frida.vala',
'frida-glue.c',
'package-manager.vala',
'control-service.vala',
'portal-service.vala',
'host-session-service.vala',
@@ -364,16 +365,14 @@ if have_local_backend
helper_backend_vala_args = [
base_vala_args,
gum_vala_args,
'--pkg=gio-unix-2.0',
'--pkg=posix',
]
helper_backend = static_library('frida-helper-backend', helper_backend_sources,
c_args: frida_component_cflags,
vala_args: [
helper_backend_vala_args,
'--vapidir=' + meson.current_source_dir() / 'linux',
'--pkg=frida-sysapi',
'--pkg=linux',
'--pkg=linux-system',
'--pkg=frida-gum-linux-1.0',
],
dependencies: [gio_dep, gio_unix_dep, gee_dep, gum_dep, base_dep] + helper_backend_extra_deps,
@@ -634,6 +633,7 @@ core = library('frida-core', core_sources,
base_vala_args,
gumjs_inspector_vala_args,
'--pkg=gmodule-2.0',
'--pkg=libsoup-3.0',
],
vala_gir: core_gir_name,
link_args: backend_libs_private,
File diff suppressed because it is too large. Load diff
+1 -1
View File
@@ -1,6 +1,6 @@
[wrap-git]
url = https://github.com/frida/frida-gum.git
revision = 17.0.2
revision = 17.2.4
depth = 1
[provide]
+1 -1
View File
@@ -1,6 +1,6 @@
[wrap-git]
url = https://github.com/frida/ngtcp2.git
revision = cc5cf523615b7fa7a9340234c7eec3c3645ae969
revision = 828dcaed498b40954e1b496664a3309796968db6
depth = 1
[provide]
-6
View File
@@ -77,12 +77,6 @@ build_arch () {
export CC="gcc -m32" CXX="g++ -m32" STRIP="strip"
fi
case "$ARCH" in
armbe8 | arm64be | arm64beilp32)
EXTRA_FLAGS+=("--without-prebuilds=sdk:host")
;;
esac
cd "$FRIDA_CORE_DIR"
rm -rf "$BUILD_DIR"
+4
View File
@@ -9,6 +9,10 @@ test_sources = [
'process-resource-usage.c',
]
if host_os_family == 'darwin'
test_sources += 'test-host-session-darwin-glue.m'
endif
test_vala_args = []
test_depends = []
+1 -1
View File
@@ -2,7 +2,7 @@
tests=$(dirname "$0")
repo=$(dirname "$tests")
builddir=../build/tmp_thin-macos-arm64/frida-core
builddir=build
flamegraph=/Users/oleavr/src/FlameGraph
set -ex
+20 -3
View File
@@ -25,14 +25,31 @@ namespace Frida.CompilerTest {
string project_dir = DirUtils.make_tmp ("compiler-test.XXXXXX");
string agent_ts_path = Path.build_filename (project_dir, "agent.ts");
FileUtils.set_contents (agent_ts_path, "console.log(\"Hello World\");");
FileUtils.set_contents (agent_ts_path, """
import { log } from "./logger.js";
const woot = Buffer.from("w00t").toString("base64");
log("Hello World: " + woot);
log(hexdump(Process.mainModule.base, { ansi: true }));
""");
string logger_ts_path = Path.build_filename (project_dir, "logger.ts");
FileUtils.set_contents (logger_ts_path, """
export function log(...items: any[]) {
const message = items.join("\n");
console.log(`[LOG] ${message}`);
}
""");
var timer = new Timer ();
yield compiler.build (agent_ts_path);
var code = yield compiler.build (agent_ts_path);
uint elapsed_msec = (uint) (timer.elapsed () * 1000.0);
if (GLib.Test.verbose ())
if (GLib.Test.verbose ()) {
print ("Output:\nvvv\n%s^^^\n", code);
print ("Built in %u ms\n", elapsed_msec);
}
unowned string? test_log_path = Environment.get_variable ("FRIDA_TEST_LOG");
if (test_log_path != null) {
+83
View File
@@ -0,0 +1,83 @@
#import <Foundation/Foundation.h>
#include <assert.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
static id frida_parse_plist (const uint8_t * data, int length, char ** error_message);
uint8_t *
frida_host_session_test_fruity_plist_to_binary_using_apple_implementation (const uint8_t * data, int length, char ** error_message,
int * output_length)
{
@autoreleasepool
{
uint8_t * result;
id plist;
NSData * bplist;
size_t len;
*error_message = NULL;
*output_length = 0;
plist = frida_parse_plist (data, length, error_message);
if (plist == nil)
return NULL;
bplist = [NSPropertyListSerialization dataWithPropertyList:plist
format:NSPropertyListBinaryFormat_v1_0
options:0
error:nil];
len = [bplist length];
result = malloc (len);
memcpy (result, [bplist bytes], len);
*output_length = (int) len;
return result;
}
}
char *
frida_host_session_test_fruity_plist_to_xml_using_apple_implementation (const uint8_t * data, int length, char ** error_message)
{
@autoreleasepool
{
id plist;
NSData * xml;
*error_message = NULL;
plist = frida_parse_plist (data, length, error_message);
if (plist == nil)
return NULL;
xml = [NSPropertyListSerialization dataWithPropertyList:plist
format:NSPropertyListXMLFormat_v1_0
options:0
error:nil];
return strndup ([xml bytes], [xml length]);
}
}
static id
frida_parse_plist (const uint8_t * data, int length, char ** error_message)
{
id plist;
NSData * input;
NSPropertyListFormat format;
NSError * error = nil;
input = [NSData dataWithBytes:data length:(NSUInteger) length];
plist = [NSPropertyListSerialization propertyListWithData:input
options:NSPropertyListImmutable
format:&format
error:&error];
if (error != nil)
*error_message = strdup ([[error localizedDescription] UTF8String]);
return plist;
}
+67 -1
View File
@@ -46,6 +46,12 @@ namespace Frida.HostSessionTest {
Fruity.Plist.to_xml_yields_complete_document ();
});
#if DARWIN
GLib.Test.add_func ("/HostSession/Fruity/Plist/output-matches-apple-implementation", () => {
Fruity.Plist.output_matches_apple_implementation ();
});
#endif
GLib.Test.add_func ("/HostSession/Fruity/backend", () => {
var h = new Harness ((h) => Fruity.backend.begin (h as Harness));
h.run ();
@@ -1551,7 +1557,7 @@ namespace Frida.HostSessionTest {
private static async void spawn (Harness h) {
if (!GLib.Test.slow () && (
Frida.Test.os () == Frida.Test.OS.ANDROID ||
Frida.Test.os_arch_suffix () == "-linux-arm" ||
Frida.Test.os_arch_suffix () == "-linux-armbe8" ||
Frida.Test.os_arch_suffix () == "-linux-arm64be"
)) {
stdout.printf ("<skipping, run in slow mode> ");
@@ -4059,6 +4065,66 @@ namespace Frida.HostSessionTest {
assert_true (actual_xml == expected_xml);
}
#if DARWIN
private static void output_matches_apple_implementation () {
var request = new Frida.Fruity.Plist ();
request.set_string ("Command", "Lookup");
var options = new Frida.Fruity.PlistDict ();
request.set_dict ("ClientOptions", options);
var attributes = new Frida.Fruity.PlistArray ();
options.set_array ("ReturnAttributes", attributes);
attributes.add_string ("ApplicationType");
attributes.add_string ("IsAppClip");
attributes.add_string ("SBAppTags");
attributes.add_string ("CFBundleIdentifier");
attributes.add_string ("CFBundleDisplayName");
attributes.add_string ("CFBundleShortVersionString");
attributes.add_string ("CFBundleVersion");
attributes.add_string ("Path");
attributes.add_string ("Container");
attributes.add_string ("GroupContainers");
attributes.add_string ("Entitlements");
var ids = new Frida.Fruity.PlistArray ();
options.set_array ("BundleIDs", ids);
ids.add_string ("UUU");
string? error_message;
string our_xml = request.to_xml ();
uint8[] our_bplist = request.to_binary ();
uint8[]? apple_bplist = to_binary_using_apple_implementation (our_xml.data, out error_message);
if (error_message != null)
printerr ("Oops: %s\n", error_message);
assert_nonnull (apple_bplist);
assert_null (error_message);
/*
try {
var home_dir = Environment.get_home_dir ();
FileUtils.set_data (Path.build_filename (home_dir, "frida-test-apple.plist"), apple_bplist);
FileUtils.set_data (Path.build_filename (home_dir, "frida-test-our.plist"), our_bplist);
} catch (FileError e) {
assert_not_reached ();
}
*/
string? apple_xml = to_xml_using_apple_implementation (our_bplist, out error_message);
if (error_message != null)
printerr ("Oops: %s\n", error_message);
assert_nonnull (apple_xml);
assert_null (error_message);
assert_cmpstr (our_xml, EQ, apple_xml);
assert_cmpstr (Base64.encode (our_bplist), EQ, Base64.encode (apple_bplist));
}
private extern uint8[]? to_binary_using_apple_implementation (uint8[] data, out string? error_message);
private extern string? to_xml_using_apple_implementation (uint8[] data, out string? error_message);
#endif
}
}
+369
View File
@@ -0,0 +1,369 @@
from __future__ import annotations
import base64
import json
import os
import platform
import re
import shlex
import shutil
import subprocess
import sys
from dataclasses import dataclass
from pathlib import Path
from typing import List, Optional, Tuple
if platform.system() == "Windows":
import winreg
FRIDA_OS_TO_GO_OS = {
"macos": "darwin",
}
FRIDA_ABI_TO_GO_ARCH = {
"armbe8": "armbe",
"armhf": "arm",
"mips64el": "mips64le",
"mipsel": "mipsle",
"x86": "386",
"x86_64": "amd64",
}
FRIDA_ABI_TO_MINGW_FLAVOR = {
"arm64": "clangarm64",
"x86": "mingw32",
"x86_64": "mingw64",
}
FRIDA_ABI_TO_MINGW_ARCH = {
"arm64": "aarch64",
"x86": "i686",
"x86_64": "x86_64",
}
MACHINE_FLAG_PATTERN = re.compile(
r"^-m(?:arch|float-abi|fpu|thumb|fpmath|stackrealign|cpu|tune|fp32|abi)(?:=.*)?$"
)
def main(argv: List[str]):
args = argv[1:]
go = Path(args.pop(0))
host_os = args.pop(0)
host_abi = args.pop(0)
shlib_suffix = args.pop(0)
cc_id = args.pop(0)
cc_cmd_array = pop_cmd_array_arg(args)
ar_cmd_array = pop_cmd_array_arg(args)
nm_cmd_array = pop_cmd_array_arg(args)
ranlib_cmd_array = pop_cmd_array_arg(args)
try:
config = detect_config(
go,
host_os,
host_abi,
shlib_suffix,
cc_id,
cc_cmd_array,
ar_cmd_array,
nm_cmd_array,
ranlib_cmd_array,
)
print("ok")
print(config["mode"], base64.b64encode(json.dumps(config).encode("utf-8")).decode("ascii"))
except Exception as e:
print("error")
print(str(e).replace("\n", "\\n"))
def pop_cmd_array_arg(args: List[str]) -> List[str]:
result = []
first = args.pop(0)
assert first == ">>>"
while True:
cur = args.pop(0)
if cur == "<<<":
break
result.append(cur)
if len(result) == 1 and not result[0]:
return None
return result
def detect_config(
go: Path,
host_os: str,
host_abi: str,
shlib_suffix: str,
cc_id: str,
cc_cmd_array: List[str],
ar_cmd_array: Optional[List[str]],
nm_cmd_array: Optional[List[str]],
ranlib_cmd_array: Optional[List[str]],
) -> dict:
source_root = Path(os.environ["MESON_SOURCE_ROOT"])
build_root = Path(os.environ["MESON_BUILD_ROOT"])
subdir = Path(os.environ["MESON_SUBDIR"])
work_dir = build_root / subdir / "tools" / "cgo"
work_dir.mkdir(parents=True, exist_ok=True)
for f in ("go.mod", "main.go"):
shutil.copyfile(source_root / subdir / "tools" / "cgo" / f, work_dir / f)
extra_go_args = []
mingw = None
env = {
**os.environ,
"CGO_ENABLED": "1",
}
if cc_id == "msvc":
toolchain = MinGWToolchain.detect(host_abi)
mingw = {
"triplet": toolchain.triplet,
"prefix": str(toolchain.prefix),
"bindir": str(toolchain.bindir),
"cc": str(toolchain.cc),
"libcc": str(toolchain.libcc),
}
env["CC"] = str(toolchain.cc)
env["PATH"] = str(toolchain.cc.parent) + ";" + env["PATH"]
ar_cmd_array = [str(toolchain.ar)]
nm_cmd_array = [str(toolchain.nm)]
ranlib_cmd_array = [str(toolchain.ranlib)]
else:
env["CC"] = shlex.join(
[arg for arg in cc_cmd_array if MACHINE_FLAG_PATTERN.fullmatch(arg) is None]
)
extra_go_args.append(f"-ldflags=-extar={ar_cmd_array[0]}")
if host_os == "macos":
extra_go_args.append("-ldflags=-extldflags=-mmacosx-version-min=11.0")
env["MACOSX_DEPLOYMENT_TARGET"] = "11.0"
def run(*args):
return subprocess.run(
args,
cwd=work_dir,
env=env,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
encoding="utf-8",
check=True,
)
goos = FRIDA_OS_TO_GO_OS.get(host_os, host_os)
goarch = FRIDA_ABI_TO_GO_ARCH.get(host_abi, host_abi)
needed = f"{goos}/{goarch}"
supported = run("go", "tool", "dist", "list").stdout.splitlines()
if needed not in supported:
raise NotSupportedError(f"Go does not support {needed}")
env["GOOS"] = goos
env["GOARCH"] = goarch
mode = "c-shared" if host_os == "android" else "c-archive"
try:
run(go, "build", f"-buildmode={mode}", "-o", "cgotest.a", "-buildvcs=false")
except subprocess.CalledProcessError as e:
raise BuildError(e.output.strip())
config = {
"mode": mode,
"os": host_os,
"abi": host_abi,
"shlib_suffix": shlib_suffix,
"extra_go_args": extra_go_args,
"env": env,
"ar": ar_cmd_array,
"nm": nm_cmd_array,
"ranlib": ranlib_cmd_array,
}
if mingw is not None:
config["mingw"] = mingw
return config
class BuildError(Exception):
pass
class NotSupportedError(Exception):
pass
@dataclass
class MinGWToolchain:
triplet: str
prefix: Path
bindir: Path
cc: Path
ar: Path
nm: Path
ranlib: Path
libcc: Path
@staticmethod
def detect(host_abi: str) -> MinGWToolchain:
msys_prefix = find_msys2_prefix_from_environment()
if msys_prefix is None:
msys_prefix = find_msys2_prefix_from_registry()
if msys_prefix is None:
msys_prefix = Path(os.environ["SystemDrive"] + r"\msys64")
if not msys_prefix.exists():
msys_prefix = None
if msys_prefix is not None:
flavor = host_abi_to_mingw_flavor(host_abi)
mingw_prefix = msys_prefix / flavor
if not mingw_prefix.exists():
mingw_prefix = None
else:
mingw_prefix = None
mingw_cc = host_abi_to_mingw_cc(host_abi)
if mingw_prefix is not None:
mingw_bindir = mingw_prefix / "bin"
cc_path = mingw_bindir / f"{mingw_cc}.exe"
if not cc_path.exists():
cc_path = None
else:
raw_cc_path = shutil.which(mingw_cc)
cc_path = Path(raw_cc_path) if raw_cc_path is not None else None
if cc_path is not None:
mingw_bindir = cc_path.parent
mingw_prefix = mingw_bindir.parent
if cc_path is None:
raise MinGWNotFoundError(
"could not find an MSYS2/MinGW toolchain under msys64, "
"nor a MinGW-based GCC/Clang on PATH matching the requested host_abi"
)
def query_cc(*args):
return subprocess.run(
[cc_path, *args],
cwd=cc_path.parent,
capture_output=True,
encoding="utf-8",
check=True,
).stdout.rstrip()
try:
triplet = query_cc("-dumpmachine")
except subprocess.CalledProcessError:
raise MinGWNotFoundError(
f"unable to detect the machine triplet of {cc_path}"
)
actual_mingw_arch = triplet.split("-", 1)[0]
expected_mingw_arch = FRIDA_ABI_TO_MINGW_ARCH[host_abi]
if actual_mingw_arch != expected_mingw_arch:
raise MinGWNotFoundError(
f"compiler at {cc_path} is for {actual_mingw_arch}, expected {expected_mingw_arch}"
)
if host_abi != "arm64" and "mingw" not in triplet:
raise MinGWNotFoundError(
f"compiler at {cc_path} does not target MinGW, its triplet is {triplet}"
)
ar_path = cc_path.parent / "ar.exe"
nm_path = cc_path.parent / "nm.exe"
ranlib_path = cc_path.parent / "ranlib.exe"
try:
libcc_name = query_cc("-print-libgcc-file-name")
except subprocess.CalledProcessError:
raise MinGWNotFoundError(
f"unable to detect the libgcc file name of {cc_path}"
)
libcc_path = Path(libcc_name).resolve()
return MinGWToolchain(
triplet,
mingw_prefix,
mingw_bindir,
cc_path,
ar_path,
nm_path,
ranlib_path,
libcc_path,
)
class MinGWNotFoundError(Exception):
pass
def host_abi_to_mingw_flavor(abi: str) -> str:
try:
return FRIDA_ABI_TO_MINGW_FLAVOR[abi]
except KeyError:
raise MinGWNotFoundError(f"unsupported host_abi: {abi}")
def host_abi_to_mingw_cc(abi: str) -> str:
return "clang" if abi == "arm64" else "gcc"
def find_msys2_prefix_from_environment() -> Optional[Path]:
location = os.environ.get("MSYS2_LOCATION")
if location is None:
return None
return Path(location)
def find_msys2_prefix_from_registry() -> Optional[Path]:
UNINSTALL_PATHS = [
(
winreg.HKEY_CURRENT_USER,
r"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall",
),
(
winreg.HKEY_CURRENT_USER,
r"SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall",
),
(
winreg.HKEY_LOCAL_MACHINE,
r"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall",
),
(
winreg.HKEY_LOCAL_MACHINE,
r"SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall",
),
]
for hive, subkey_path in UNINSTALL_PATHS:
try:
with winreg.OpenKey(hive, subkey_path) as uninstall_root:
num_subkeys, _, _ = winreg.QueryInfoKey(uninstall_root)
for i in range(num_subkeys):
try:
subkey_name = winreg.EnumKey(uninstall_root, i)
with winreg.OpenKey(uninstall_root, subkey_name) as app_key:
disp_name, _ = winreg.QueryValueEx(app_key, "DisplayName")
if disp_name.startswith("MSYS2"):
install_loc, _ = winreg.QueryValueEx(
app_key, "InstallLocation"
)
return Path(install_loc)
except FileNotFoundError:
continue
except OSError:
continue
except FileNotFoundError:
continue
except OSError:
continue
return None
if __name__ == "__main__":
main(sys.argv)
+3
View File
@@ -0,0 +1,3 @@
module frida.re/cgotest
go 1.24.3
+13
View File
@@ -0,0 +1,13 @@
package main
/*
#include <stdlib.h>
*/
import "C"
//export frobnicate
func frobnicate() int {
return 42
}
func main() {}
+10 -7
View File
@@ -22,14 +22,17 @@ def compile_js_agent(output_js: Path, inputs: List[Path], priv_dir: Path, npm: P
dest.parent.mkdir(exist_ok=True)
shutil.copy(f, dest)
run_kwargs = {
"cwd": priv_dir,
"stdout": subprocess.PIPE,
"stderr": subprocess.STDOUT,
"encoding": "utf-8",
"check": True,
}
try:
subprocess.run(
[npm, "install"],
capture_output=True,
cwd=priv_dir,
encoding="utf-8",
check=True,
)
subprocess.run([npm, "install"], **run_kwargs)
subprocess.run([npm, "run", "build"], **run_kwargs)
except subprocess.CalledProcessError as e:
print(e, file=sys.stderr)
print(
+2 -1
View File
@@ -23,6 +23,7 @@ def main(argv):
input_entitlements_path = args.pop(0) if args else None
else:
input_entitlements_path = None
flags = set(args.pop(0).split("|") if args else [])
is_apple_os = host_os in {"macos", "ios", "watchos", "tvos"}
@@ -62,7 +63,7 @@ def main(argv):
codesign_args += ["--entitlements", input_entitlements_path]
subprocess.run(codesign + codesign_args + [intermediate_path], **run_kwargs)
if host_os == "android":
if host_os == "android" and "elf-cleaner:off" not in flags:
api_level = 19 if host_abi in {"x86", "arm"} else 21
subprocess.run(termux_elf_cleaner + ["--api-level", str(api_level), "--quiet", intermediate_path],
**run_kwargs)
+10
View File
@@ -163,6 +163,9 @@ namespace QuickJS {
[CCode (cname = "JS_NewCFunction2")]
public Value make_cfunction2 (CFunction func, string name, int length, CFunctionEnum cproto, int magic);
[CCode (cname = "JS_NewCFunctionData")]
public Value make_cfunction_data (CFunctionData func, int length, int magic, [CCode (array_length_pos = 3.1)] Value[] data);
[CCode (cname = "JS_NewPromiseCapability")]
public Value make_promise ([CCode (array_length = false, array_null_terminated = false)] Value[] resolving_funcs);
@@ -201,6 +204,10 @@ namespace QuickJS {
[CCode (has_target = false)]
public delegate Value CFunction (Context ctx, Value this_val, [CCode (array_length_pos = 2.1)] Value[] argv);
[CCode (has_target = false)]
public delegate Value CFunctionData (Context ctx, Value this_val, [CCode (array_length_pos = 2.1)] Value[] argv, int magic,
[CCode (array_length = false, array_null_terminated = false)] Value[] data);
[CCode (cprefix = "JS_CFUNC_", has_type_id = false)]
public enum CFunctionEnum {
generic,
@@ -314,6 +321,9 @@ namespace QuickJS {
[CCode (cname = "JS_GetOpaque")]
public void * get_opaque (ClassID class_id);
[CCode (cname = "JS_GetAnyOpaque")]
public void * get_any_opaque (out ClassID class_id);
[CCode (cname = "JS_SetOpaque")]
public void set_opaque (void * opaque);
}