Compare commits

..
Author SHA1 Message Date
Ole André Vadla Ravnås e0ada4a9ff [WIP] Toy around with a potential Softwall feature 2026-02-12 23:13:19 +01:00
181 changed files with 8188 additions and 20295 deletions

No files matched your search

@@ -1,4 +0,0 @@
set(VCPKG_TARGET_ARCHITECTURE arm64)
set(VCPKG_CRT_LINKAGE dynamic)
set(VCPKG_LIBRARY_LINKAGE dynamic)
set(VCPKG_BUILD_TYPE release)
@@ -1,4 +0,0 @@
set(VCPKG_TARGET_ARCHITECTURE x64)
set(VCPKG_CRT_LINKAGE dynamic)
set(VCPKG_LIBRARY_LINKAGE dynamic)
set(VCPKG_BUILD_TYPE release)
+5 -92
View File
@@ -61,17 +61,13 @@ jobs:
run: |
sudo apt-get update
sudo apt-get install gcc-multilib lib32stdc++-13-dev
- name: Install setuptools for distutils shim
if: ${{ startsWith(matrix.id, 'windows-') }}
run: pip install setuptools
- name: Build
if: ${{ startsWith(matrix.id, 'windows-') }}
run: |
.\configure `
--host=${{ matrix.id }} `
--enable-compiler-backend `
${{ env.FRIDA_CORE_OPTIONS }} `
-- --force-fallback-for=openssl
${{ env.FRIDA_CORE_OPTIONS }}
.\make
env:
MSYS2_LOCATION: ${{ steps.msys2.outputs.msys2-location }}
@@ -335,7 +331,7 @@ jobs:
if: startsWith(matrix.id, 'android-')
id: setup-ndk
with:
ndk-version: r29
ndk-version: r25c
- name: Add NDK to env
if: startsWith(matrix.id, 'android-')
run: echo ANDROID_NDK_ROOT=${{ steps.setup-ndk.outputs.ndk-path }} >> $GITHUB_ENV
@@ -432,7 +428,6 @@ jobs:
# in, and we want to ensure that they are up-to-date with respect to the source
# for all architectures.
check-linux-helpers:
if: false
strategy:
matrix:
arch: [x86, x86_64, arm, armbe8, arm64, arm64be, arm64beilp32, mips, mipsel, mips64, mips64el]
@@ -450,7 +445,7 @@ jobs:
- name: Check for unexpected changes
run: |
git config --global --add safe.directory "$(realpath .)"
status_output=$(git status --porcelain src/linux/helpers/artifacts)
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"
@@ -466,7 +461,6 @@ jobs:
# in, and we want to ensure that they are up-to-date with respect to the source
# for all architectures.
check-labrats:
if: false
strategy:
matrix:
arch: [x86, x86_64, arm, armbe8, arm64, arm64be, arm64beilp32, mips, mipsel, mips64, mips64el]
@@ -484,7 +478,7 @@ jobs:
- name: Check for unexpected changes
run: |
git config --global --add safe.directory "$(realpath .)"
status_output=$(git status --porcelain tests/labrats/{resident-agent,simple-agent}-linux-${{ matrix.arch }}.so tests/labrats/{forker,sleeper,spawner}-linux-${{ matrix.arch }})
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"
@@ -497,7 +491,6 @@ jobs:
xcframework:
name: Build FridaCore.xcframework
if: ${{ !cancelled() }}
runs-on: macos-latest
needs:
- native
@@ -590,7 +583,7 @@ jobs:
path: FridaCore.xcframework
publish-xcframework:
if: ${{ !cancelled() && github.ref_type == 'tag' && needs.xcframework.result == 'success' }}
if: github.ref_type == 'tag'
runs-on: macos-latest
needs:
- xcframework
@@ -626,83 +619,3 @@ jobs:
prerelease: ${{ contains(github.ref_name, 'snapshot') }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
windows-shared:
strategy:
matrix:
include:
- { arch: x86_64, runner: windows-latest, msvc-arch: amd64, vcpkg-triplet: x64-windows-release }
- { arch: arm64, runner: windows-11-arm, msvc-arch: arm64, vcpkg-triplet: arm64-windows-release }
fail-fast: false
runs-on: ${{ matrix.runner }}
timeout-minutes: 120
steps:
- name: Check out repo
uses: actions/checkout@v6
with:
submodules: recursive
- uses: ilammy/msvc-dev-cmd@v1
with:
arch: ${{ matrix.msvc-arch }}
- uses: actions/setup-python@v6
with:
python-version: "3.12"
- name: Install build tools
run: |
pip install meson ninja setuptools
choco install pkgconfiglite -y
- name: Restore vcpkg cache
id: vcpkg-cache
uses: actions/cache/restore@v5
with:
path: C:\vcpkg\installed
key: vcpkg-${{ matrix.vcpkg-triplet }}-v5
- name: Install dependencies via vcpkg
if: steps.vcpkg-cache.outputs.cache-hit != 'true'
run: >-
vcpkg install
--overlay-triplets=${{ github.workspace }}/.github/vcpkg-triplets
--triplet ${{ matrix.vcpkg-triplet }}
glib json-glib libsoup
- name: Save vcpkg cache
if: steps.vcpkg-cache.outputs.cache-hit != 'true'
uses: actions/cache/save@v5
with:
path: C:\vcpkg\installed
key: vcpkg-${{ matrix.vcpkg-triplet }}-v5
- name: Set up vcpkg environment
shell: bash
run: |
TRIPLET="${{ matrix.vcpkg-triplet }}"
VCPKG_PREFIX="C:/vcpkg/installed/$TRIPLET"
echo "$VCPKG_PREFIX/tools/pkgconf" >> $GITHUB_PATH
echo "$VCPKG_PREFIX/bin" >> $GITHUB_PATH
echo "$VCPKG_PREFIX/tools" >> $GITHUB_PATH
echo "PKG_CONFIG_PATH=$VCPKG_PREFIX/lib/pkgconfig" >> $GITHUB_ENV
- name: Configure
run: |
python -c "import sys; sys.path.insert(0, '.'); from releng.meson_configure import main; main()" `
. `
--host=windows-${{ matrix.arch }} `
--enable-shared `
--without-prebuilds=sdk `
"--prefix=$env:RUNNER_TEMP\frida-prefix" `
-- --force-fallback-for=openssl,libnghttp2 -Dcompiler_backend=disabled -Dtests=disabled
- name: Compile
run: python releng/meson/meson.py compile -C build
- name: Install
run: python releng/meson/meson.py install -C build --no-rebuild --skip-subprojects
- name: List installed files
shell: bash
run: find "$RUNNER_TEMP/frida-prefix" -type f | sort
-153
View File
@@ -1,153 +0,0 @@
# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code)
when working with code in this repository.
## What This Is
frida-core is the core library of the Frida dynamic
instrumentation toolkit. It packages GumJS into a shared
library, injects JavaScript instrumentation into target
processes, provides bidirectional RPC communication with
injected scripts, and enumerates apps/processes/devices.
Written primarily in Vala with OS-specific glue in
C/Objective-C/asm.
## Build Commands
```bash
# First-time setup (fetches git submodules, configures build):
./configure \
--enable-compiler-backend \
--with-devkits=core \
--enable-tests
# Build:
make
# Run tests:
make test
# Rebuild after code changes
make
```
The `configure` script and `Makefile` are thin wrappers
around `releng/meson_configure.py` and
`releng/meson_make.py`. The actual build system is Meson
(>=1.1.0).
Build artifacts go into `build/`. The triplet is
platform-dependent (e.g. `linux-x86_64`).
## Build Requirements
- **Vala compiler**: Must be the Frida-optimized fork from
https://github.com/frida/vala (checks for `-frida` suffix
in version)
- **C/C++ standards**: gnu99/c99 for C, c++17 for C++
- **Go >= 1.24**: Required for compiler backend
- **Python 3**: Build scripts
## Architecture
### Backend System
The core abstraction is a pluggable backend system. Each
backend implements `HostSessionBackend` and provides a
`HostSessionProvider` to create sessions with target
processes:
- **local** — Injects into processes on the local system
(Linux, macOS, Windows, FreeBSD, QNX)
- **fruity** — iOS/tvOS/xrOS devices via USB/network
(QUIC, lockdown protocols)
- **droidy** — Android devices via ADB/JDWP
- **socket** — Remote devices via TCP (connects to
frida-server, frida-gadget, frida-portal)
- **barebone** — Minimal backend using QuickJS
- **simmy** — macOS Simulator
- **compiler** — TypeScript/ESBuild compilation backend
(Go + TypeScript in `src/compiler/`)
Backends are selected at build time via meson options
(e.g. `-Dlocal_backend=enabled`).
### Key Source Layout
- **`src/frida.vala`** — Public API: `DeviceManager`,
`Device`, `Session`, `Script`
- **`src/host-session-service.vala`** — Backend
orchestration, provider registration
- **`src/control-service.vala`** — the guts of frida-server
- **`src/portal-service.vala`** — the guts of frida-portal,
which looks like a frida-server that surfaces any joined
processes (think aggregator/reverse proxy)
- **`lib/base/`** — Core primitives: Session, RPC, streams,
sockets, P2P, buffers
- **`lib/agent/`** — In-process JavaScript agent runtime
- **`lib/payload/`** — Payload compilation and embedding
- **`lib/gadget/`** — Gadget (preloaded library)
implementation
- **`src/<platform>/`** — Platform-specific injectors and
helpers (`linux/`, `darwin/`, `windows/`, `freebsd/`,
`qnx/`)
- **`src/fruity/`** — iOS device protocol stack (USB, QUIC,
plist, XPC, LLDB)
- **`src/droidy/`** — Android device protocol stack
- **`src/compiler/`** — Go/TypeScript compiler backend
### Injection Flow
Each platform has its own injector (e.g. `Linjector` on
Linux, `Fruitjector` on Darwin, `Winjector` on Windows). A
helper process (`frida-helper`) performs privileged injection
operations out-of-process. Helpers and agents can be embedded
into the library or installed as separate files (controlled
by the `assets` meson option).
### Deliverables
- **frida-server** (`server/`) — Standalone daemon exposing
the full API over the network
- **frida-portal** (`portal/`) — Cluster node for
distributed instrumentation
- **frida-inject** (`inject/`) — CLI tool for one-shot
script injection
- **frida-gadget** (`lib/gadget/`) — Shared library for
preload-based instrumentation
### Resource Embedding
Build artifacts (frida-helper, frida-agent) are compiled
into resource blobs via `tools/resource-compiler.vala` and
embedding scripts (`src/embed-helper.py`,
`src/embed-agent.py`). On non-MSVC toolchains these become
`.S` assembly files; on MSVC they become `.obj` files.
## Tests
Tests are in `tests/` as Vala files using a custom async
test harness (`tests/async-harness.vala`). Test binary is
`tests/frida-tests`. Platform-specific runner scripts exist
(e.g. `tests/run-linux-x86_64.sh`).
Test modules: `test-system`, `test-injector`, `test-agent`,
`test-host-session`, `test-gadget`, `test-compiler`. Test
helper programs ("labrats") are in `tests/labrats/`.
## Code Style
### Function Order
Use newspaper/stepdown order: high-level entry points
first, low-level helpers and constants last. In C,
`main()` is always first. When ordering siblings at the
same level, use the chronological order of first use
within their caller.
## Commit Style
- Subject line: max 50 characters
- Body lines: wrap at 72 characters (use the full width, or
slightly less if it avoids making the next line awkward)
+11 -49
View File
@@ -1,18 +1,15 @@
# frida-core
Frida core library.
Frida core library intended for static linking into bindings.
- Lets you inject your own JavaScript instrumentation code
into other processes, optionally with your own [C code][]
for performance-sensitive bits.
- Acts as a logistics layer that packages up [GumJS][] into
a shared library.
- Provides a two-way communication channel for talking to
your scripts, if needed, and later unload them.
- Also lets you enumerate installed apps, running processes,
and connected devices.
- Written in [Vala][], with OS-specific glue code in
C/Objective-C/asm.
- Lets you inject your own JavaScript instrumentation code into other processes,
optionally with your own [C code][] for performance-sensitive bits.
- Acts as a logistics layer that packages up [GumJS][] into a shared library.
- Provides a two-way communication channel for talking to your scripts,
if needed, and later unload them.
- Also lets you enumerate installed apps, running processes, and connected
devices.
- Written in [Vala][], with OS-specific glue code in C/Objective-C/asm.
## Binaries
@@ -32,43 +29,8 @@ $ pip install frida # Python bindings
$ npm install frida # Node.js bindings
```
Or, for static linking into your own project written in a
C-compatible language, download a devkit from the Frida
[releases][] page.
## Distro Packaging
For building a shared library suitable for distro packaging:
```console
$ ./configure --enable-shared --without-prebuilds=sdk && make
```
This builds `libfrida-core-1.0.so` against system dependencies,
while `frida-agent.so` is built using Frida's SDK (with its GLib
fork, needed for the agent's inject/unload lifecycle).
Prerequisites on Fedora:
```console
$ sudo dnf install libgee-devel json-glib-devel \
libsoup3-devel libunwind-devel libdwarf-devel \
libnice-devel ngtcp2-crypto-ossl-devel
```
Prerequisites on Ubuntu:
```console
$ sudo apt install libgee-0.8-dev libjson-glib-dev \
libsoup-3.0-dev libunwind-dev libdwarf-dev \
libnice-dev libngtcp2-crypto-ossl-dev
```
Prerequisites on macOS:
```console
$ brew install libgee json-glib libsoup libnice capstone
```
Or, for static linking into your own project written in a C-compatible language,
download a devkit from the Frida [releases][] page.
## Internals
+61 -211
View File
@@ -9,7 +9,6 @@ import os
from pathlib import Path
import pickle
import platform
import re
import shlex
import shutil
import subprocess
@@ -36,7 +35,6 @@ def main(argv):
command.add_argument("top_builddir", help="top build directory", type=Path)
command.add_argument("frida_version", help="the Frida version")
command.add_argument("host_os", help="operating system binaries are being built for")
command.add_argument("host_os_family", help="operating system family, e.g. darwin")
command.add_argument("host_arch", help="architecture binaries are being built for")
command.add_argument("host_config", help="configuration binaries are being built for")
command.add_argument("compat", help="support for targets with a different architecture",
@@ -44,20 +42,17 @@ def main(argv):
command.add_argument("assets", help="whether assets are embedded vs installed and loaded at runtime")
command.add_argument("components", help="which components will be built",
type=parse_array_option_value)
command.add_argument("glib_flavor", help="upstream or frida", choices=["upstream", "frida"])
command.add_argument("compilers", help="compiler command arrays", nargs="+")
command.set_defaults(func=lambda args: setup(args.role,
args.builddir,
args.top_builddir,
args.frida_version,
args.host_os,
args.host_os_family,
args.host_arch,
args.host_config if args.host_config else None,
args.compat,
args.assets,
args.components,
args.glib_flavor,
parse_compilers(args.compilers)))
command = subparsers.add_parser("compile", help="compile compatibility assets")
@@ -118,13 +113,11 @@ def setup(role: Role,
top_builddir: Path,
frida_version: str,
host_os: str,
host_os_family: str,
host_arch: str,
host_config: Optional[str],
compat: set[str],
assets: str,
components: set[str],
glib_flavor: str,
compilers: Compilers):
try:
outputs: Mapping[str, Sequence[Output]] = OrderedDict()
@@ -156,20 +149,9 @@ def setup(role: Role,
other_triplet: Optional[str] = None
extra_environ: dict[str, str] = {}
if host_os == "windows" and host_arch in {"x86_64", "x86"}:
if host_arch == "x86_64":
other_label = "x86"
other_kind = "legacy"
else:
other_label = "x86_64"
other_kind = "modern"
if host_config == "mingw":
have_toolchain, other_triplet = detect_mingw_toolchain_for(other_label)
else:
have_toolchain = True
other_triplet = None
if host_os == "windows" and host_arch == "x86_64" and host_config == "mingw":
other_label = "x86"
have_toolchain, other_triplet = detect_mingw_toolchain_for("x86")
elif host_os == "linux" and host_arch == "x86_64" and host_config is None:
other_label = "x86"
other_triplet = "i686-linux-gnu"
@@ -197,26 +179,21 @@ def setup(role: Role,
raise ToolchainNotFoundError(f"unable to locate toolchain for {other_triplet}")
missing.append(MissingFeature(other_label, other_triplet))
if host_os == "windows" and host_arch in {"x86_64", "x86"} and have_toolchain:
group = OutputGroup(other_label, other_triplet, extra_environ)
outputs[group] = []
if "helper" in components:
outputs[group] += [
Output(identifier=f"helper_{other_kind}",
name=HELPER_FILE_WINDOWS.name,
file=HELPER_FILE_WINDOWS,
target=HELPER_TARGET),
]
if "agent" in components:
outputs[group] += [
Output(identifier=f"agent_{other_kind}",
name=AGENT_FILE_WINDOWS.name,
file=AGENT_FILE_WINDOWS,
target=AGENT_TARGET),
]
if host_os == "windows" and host_arch == "x86_64" and have_toolchain:
group = OutputGroup("x86", other_triplet, extra_environ)
outputs[group] = [
Output(identifier="helper_legacy",
name=HELPER_FILE_WINDOWS.name,
file=HELPER_FILE_WINDOWS,
target=HELPER_TARGET),
Output(identifier="agent_legacy",
name=AGENT_FILE_WINDOWS.name,
file=AGENT_FILE_WINDOWS,
target=AGENT_TARGET),
]
if "gadget" in components:
outputs[group] += [
Output(identifier=f"gadget_{other_kind}",
Output(identifier="gadget_legacy",
name=GADGET_FILE_WINDOWS.name,
file=GADGET_FILE_WINDOWS,
target=GADGET_TARGET),
@@ -230,21 +207,16 @@ def setup(role: Role,
other_arch = "arm64e"
kind = "modern"
group = OutputGroup(other_arch)
outputs[group] = []
if "helper" in components:
outputs[group] += [
Output(identifier=f"helper_{kind}",
name=f"frida-helper-{other_arch}",
file=HELPER_FILE_UNIX,
target=HELPER_TARGET),
]
if "agent" in components:
outputs[group] += [
Output(identifier=f"agent_{kind}",
name=f"frida-agent-{other_arch}.dylib",
file=AGENT_FILE_DARWIN,
target=AGENT_TARGET),
]
outputs[group] = [
Output(identifier=f"helper_{kind}",
name=f"frida-helper-{other_arch}",
file=HELPER_FILE_UNIX,
target=HELPER_TARGET),
Output(identifier=f"agent_{kind}",
name=f"frida-agent-{other_arch}.dylib",
file=AGENT_FILE_DARWIN,
target=AGENT_TARGET),
]
if "gadget" in components:
outputs[group] += [
Output(identifier=f"gadget_{kind}",
@@ -262,21 +234,16 @@ def setup(role: Role,
if host_os == "linux" and host_arch == "x86_64" and have_toolchain:
group = OutputGroup("x86", other_triplet, extra_environ)
outputs[group] = []
if "helper" in components:
outputs[group] += [
Output(identifier="helper_legacy",
name=HELPER_FILE_UNIX.name,
file=HELPER_FILE_UNIX,
target=HELPER_TARGET),
]
if "agent" in components:
outputs[group] += [
Output(identifier="agent_legacy",
name=AGENT_FILE_ELF.name,
file=AGENT_FILE_ELF,
target=AGENT_TARGET),
]
outputs[group] = [
Output(identifier="helper_legacy",
name=HELPER_FILE_UNIX.name,
file=HELPER_FILE_UNIX,
target=HELPER_TARGET),
Output(identifier="agent_legacy",
name=AGENT_FILE_ELF.name,
file=AGENT_FILE_ELF,
target=AGENT_TARGET),
]
if "gadget" in components:
outputs[group] += [
Output(identifier="gadget_legacy",
@@ -287,21 +254,16 @@ def setup(role: Role,
if host_os == "android" and host_arch in {"arm64", "x86_64"}:
group = OutputGroup("arm" if host_arch == "arm64" else "x86")
outputs[group] = []
if "helper" in components:
outputs[group] += [
Output(identifier="helper_legacy",
name=HELPER_FILE_UNIX.name,
file=HELPER_FILE_UNIX,
target=HELPER_TARGET),
]
if "agent" in components:
outputs[group] += [
Output(identifier="agent_legacy",
name=AGENT_FILE_ELF.name,
file=AGENT_FILE_ELF,
target=AGENT_TARGET),
]
outputs[group] = [
Output(identifier="helper_legacy",
name=HELPER_FILE_UNIX.name,
file=HELPER_FILE_UNIX,
target=HELPER_TARGET),
Output(identifier="agent_legacy",
name=AGENT_FILE_ELF.name,
file=AGENT_FILE_ELF,
target=AGENT_TARGET),
]
if "gadget" in components:
outputs[group] += [
Output(identifier="gadget_legacy",
@@ -322,24 +284,18 @@ def setup(role: Role,
continue
else:
emulated_triplet = None
group = OutputGroup(emulated_arch, emulated_triplet, extra_environ)
outputs[group] = []
if "helper" in components:
outputs[group] += [
Output(identifier=f"helper_emulated_{kind}",
name=HELPER_FILE_WINDOWS.name.replace(".exe", f"-{emulated_arch}.exe"),
file=HELPER_FILE_WINDOWS,
target=HELPER_TARGET),
]
if "agent" in components:
outputs[group] += [
Output(identifier=f"agent_emulated_{kind}",
name=AGENT_FILE_WINDOWS.name.replace(".dll", f"-{emulated_arch}.dll"),
file=AGENT_FILE_WINDOWS,
target=AGENT_TARGET),
]
outputs[OutputGroup(emulated_arch, emulated_triplet, extra_environ)] = [
Output(identifier=f"helper_emulated_{kind}",
name=HELPER_FILE_WINDOWS.name.replace(".exe", f"-{emulated_arch}.exe"),
file=HELPER_FILE_WINDOWS,
target=HELPER_TARGET),
Output(identifier=f"agent_emulated_{kind}",
name=AGENT_FILE_WINDOWS.name.replace(".dll", f"-{emulated_arch}.dll"),
file=AGENT_FILE_WINDOWS,
target=AGENT_TARGET),
]
if host_os == "android" and host_arch in {"x86_64", "x86"} and "agent" in components:
if host_os == "android" and host_arch in {"x86_64", "x86"}:
outputs[OutputGroup("arm")] = [
Output(identifier="agent_emulated_legacy",
name="frida-agent-arm.so",
@@ -354,35 +310,10 @@ def setup(role: Role,
target=AGENT_TARGET),
]
if glib_flavor == "upstream":
kind = "modern" if arch_is_modern(host_os, host_arch) else "legacy"
_, agent_file, gadget_file = native_file_paths(host_os)
group = OutputGroup(host_arch)
outputs[group] = []
if "agent" in components:
outputs[group] += [
Output(identifier=f"agent_{kind}",
name=arch_suffixed_name(agent_file.name, host_arch),
file=agent_file,
target=AGENT_TARGET),
]
if "gadget" in components:
outputs[group] += [
Output(identifier=f"gadget_{kind}",
name=arch_suffixed_name(gadget_file.name, host_arch),
file=gadget_file,
target=GADGET_TARGET),
]
outputs = OrderedDict((g, items) for g, items in outputs.items() if items)
raw_allowed_prebuilds = os.environ.get("FRIDA_ALLOWED_PREBUILDS")
if raw_allowed_prebuilds is not None:
allowed_prebuilds = set(filter(None, raw_allowed_prebuilds.split(",")))
else:
allowed_prebuilds = None
allowed_prebuilds = set(raw_allowed_prebuilds.split(",")) if raw_allowed_prebuilds is not None else None
state = State(role, builddir, top_builddir, frida_version, host_os, host_os_family, host_config, glib_flavor, allowed_prebuilds, outputs)
state = State(role, builddir, top_builddir, frida_version, host_os, host_config, allowed_prebuilds, outputs)
serialized_state = base64.b64encode(pickle.dumps(state)).decode('ascii')
if missing:
@@ -418,9 +349,7 @@ class State:
top_builddir: Path
frida_version: str
host_os: str
host_os_family: str
host_config: Optional[str]
glib_flavor: str
allowed_prebuilds: Optional[set[str]]
outputs: Mapping[OutputGroup, Sequence[Output]]
@@ -500,33 +429,20 @@ def compile(privdir: Path, state: State):
host_machine = MachineSpec(state.host_os, group.arch, state.host_config, group.triplet)
if state.glib_flavor == "upstream":
allowed = None
else:
allowed = state.allowed_prebuilds
if state.glib_flavor == "upstream":
forwarded_options = [o for o in options if not is_stripped_compat_option(o)]
forwarded_options += ["-Ddefault_library=static"]
else:
forwarded_options = [o for o in options if not is_overridden_compat_option(o)]
configure(sourcedir=REPO_ROOT,
builddir=workdir,
host_machine=host_machine,
environ={**build_env, **group.extra_environ},
allowed_prebuilds=allowed,
apple_min_os=detect_parent_apple_min_os(top_builddir, state.host_os, state.host_os_family),
allowed_prebuilds=state.allowed_prebuilds,
extra_meson_options=[
"-Dcompiler_backend=disabled",
"-Dassets=installed",
"-Dhelper_modern=",
"-Dhelper_legacy=",
"-Dagent_modern=",
"-Dagent_legacy=",
"-Dagent_emulated_modern=",
"-Dagent_emulated_legacy=",
*forwarded_options,
*options,
],
call_meson=call_internal_meson,
on_progress=lambda progress: None)
@@ -557,18 +473,6 @@ def compile(privdir: Path, state: State):
(state.builddir / DEPFILE_FILENAME).write_text("\n".join(depfile_lines), encoding="utf-8")
def is_stripped_compat_option(o: str) -> bool:
if is_overridden_compat_option(o):
return True
name = o.split("=", 1)[0].removeprefix("-D")
return name in STRIPPED_COMPAT_OPTIONS or name.endswith(":default_library")
def is_overridden_compat_option(o: str) -> bool:
name = o.split("=", 1)[0].removeprefix("-D")
return name in OVERRIDDEN_COMPAT_OPTIONS
def load_meson_options(top_builddir: Path,
role: Role,
subprojects: set[str]) -> Sequence[str]:
@@ -678,19 +582,6 @@ def ensure_submodules_checked_out(releng_location: Path):
check=True)
def detect_parent_apple_min_os(top_builddir: Path,
host_os: str,
host_os_family: str) -> Optional[Mapping[str, str]]:
if host_os_family != "darwin":
return None
pattern = re.compile(r"-target['\"],\s*['\"][^-]+-apple-" + re.escape(host_os) + r"([0-9.]+)")
for native_file in top_builddir.glob(f"frida-{host_os}-*.txt"):
match = pattern.search(native_file.read_text(encoding="utf-8"))
if match is not None:
return {host_os: match.group(1)}
return None
def detect_relevant_subprojects(releng_location: Path) -> dict[str, Path]:
subprojects = detect_relevant_subprojects_in(REPO_ROOT, releng_location)
gum_location = subprojects.get("frida-gum")
@@ -741,48 +632,9 @@ def detect_mingw_toolchain_for(arch: str) -> Tuple[bool, Optional[str]]:
return (found, triplet)
def arch_is_modern(host_os: str, host_arch: str) -> bool:
if host_os in {"macos", "ios", "tvos"} and host_arch == "arm64":
return host_arch == "arm64e"
return host_arch in MODERN_ARCHS
def native_file_paths(host_os: str) -> Tuple[Path, Path, Path]:
if host_os == "windows":
return (HELPER_FILE_WINDOWS, AGENT_FILE_WINDOWS, GADGET_FILE_WINDOWS)
elif host_os in {"macos", "ios", "tvos"}:
return (HELPER_FILE_UNIX, AGENT_FILE_DARWIN, GADGET_FILE_DARWIN)
else:
return (HELPER_FILE_UNIX, AGENT_FILE_ELF, GADGET_FILE_ELF)
def arch_suffixed_name(name: str, arch: str) -> str:
stem, _, ext = name.partition(".")
if ext:
return f"{stem}-{arch}.{ext}"
return f"{stem}-{arch}"
STATE_FILENAME = "state.dat"
DEPFILE_FILENAME = "compat.deps"
STRIPPED_COMPAT_OPTIONS = {
"default_library",
"frida-gum:gumjs",
"frida-gum:inspector",
}
OVERRIDDEN_COMPAT_OPTIONS = {
"compiler_backend",
"assets",
"helper_modern",
"helper_legacy",
"agent_modern",
"agent_legacy",
"agent_emulated_modern",
"agent_emulated_legacy",
}
HELPER_TARGET = "frida-helper"
HELPER_FILE_WINDOWS = Path("src") / "frida-helper.exe"
HELPER_FILE_UNIX = Path("src") / "frida-helper"
@@ -807,8 +659,6 @@ MSVS_ENVVARS = {
"LIB",
}
MODERN_ARCHS = {"x86_64", "arm64", "arm64e", "mips64", "riscv64"}
MINGW_ARCHS = {
"x86": "i686",
"arm64": "aarch64",
-15
View File
@@ -1,15 +0,0 @@
import os
import shutil
import sys
src = sys.argv[1]
install_subdir = sys.argv[2]
install_name = sys.argv[3]
destdir_prefix = os.environ["MESON_INSTALL_DESTDIR_PREFIX"]
dst_dir = os.path.join(destdir_prefix, install_subdir)
dst = os.path.join(dst_dir, install_name)
os.makedirs(dst_dir, exist_ok=True)
shutil.copy2(src, dst)
print(f"Installing {os.path.basename(src)} to {dst_dir}/{install_name}")
+2 -40
View File
@@ -28,9 +28,6 @@ if no_overridden_compat_bits
build_py = [python, files('build.py')]
components = []
if have_local_backend
components += ['helper', 'agent']
endif
if build_gadget
components += 'gadget'
endif
@@ -45,13 +42,11 @@ if no_overridden_compat_bits
meson.global_build_root(),
frida_version,
host_os,
host_os_family,
host_abi,
host_config,
','.join(get_option('compat')),
assets_mode,
get_option('assets'),
','.join(components),
have_shared_glib ? 'upstream' : 'frida',
'--',
'>>>', cc.cmd_array(), '<<<',
'>>>', cpp.cmd_array(), '<<<',
@@ -69,27 +64,18 @@ if no_overridden_compat_bits
depfile = lines[4]
state = lines[5]
native_arch_suffix = '-' + host_abi
if host_os_family == 'darwin'
install = false
install_dir = asset_dir
else
install = true
install_dir = []
i = 0
foreach varname : varnames
output_name = outputs[i]
needs_rename = output_name.contains(native_arch_suffix) or varname.contains('_emulated_')
should_install = varname != 'arch_support_bundle' \
and not needs_rename \
and (assets_mode == 'installed' or varname.startswith('gadget_'))
if should_install
if varname != 'arch_support_bundle' and (get_option('assets') == 'installed' or varname.startswith('gadget_'))
install_dir += varname.endswith('_modern') ? asset_dir_modern : asset_dir_legacy
else
install_dir += false
endif
i += 1
endforeach
endif
@@ -110,7 +96,6 @@ if no_overridden_compat_bits
foreach output : arch_support.to_list()
outpath = output.full_path()
varname = varnames[i]
output_name = outputs[i]
set_variable(varname, outpath)
@@ -130,29 +115,6 @@ if no_overridden_compat_bits
assert(false, f'unexpected variable name: @varname@')
endif
if host_os_family != 'darwin'
rename_target_dir = ''
if output_name.contains(native_arch_suffix)
rename_target_dir = asset_dir
elif varname.contains('_emulated_')
emulated_arch = output_name.split('-')[-1].split('.')[0]
rename_target_dir = root_asset_dir / emulated_arch
endif
if rename_target_dir != ''
install_name = output_name.replace(native_arch_suffix, '')
foreach arch_suffix : ['-x86_64', '-x86', '-arm64', '-arm']
install_name = install_name.replace(arch_suffix, '')
endforeach
if assets_mode == 'installed' or varname.startswith('gadget_')
meson.add_install_script(python, files('install-renamed.py'),
outpath,
rename_target_dir,
install_name,
)
endif
endif
endif
i += 1
endforeach
else
File renamed without changes.
File renamed without changes.
+15 -2
View File
@@ -4,14 +4,27 @@ inject_sources = [
]
system_vala_args = []
if host_os_family != 'windows'
system_vala_args += ['--pkg=posix']
endif
extra_link_args = []
extra_link_depends = []
if host_os_family == 'darwin'
symlist = 'frida-inject.symbols'
extra_link_args += ['-Wl,-exported_symbols_list,' + meson.current_source_dir() / symlist]
extra_link_depends += [symlist]
elif host_os_family != 'windows'
symscript = 'frida-inject.version'
extra_link_args += ['-Wl,--version-script,' + meson.current_source_dir() / symscript]
extra_link_depends += [symscript]
endif
raw_inject = executable('frida-inject-raw', inject_sources,
vala_args: [core_vala_args, system_vala_args],
link_args: executable_no_exports_link_args,
link_depends: executable_no_exports_link_depends,
link_args: extra_link_args,
link_depends: extra_link_depends,
dependencies: [json_glib_dep, core_dep],
)
+2 -8
View File
@@ -9,9 +9,7 @@
# include <signal.h>
# endif
#endif
#if defined (HAVE_GIOAPPLE)
# include <gioapple.h>
#elif defined (HAVE_GIOOPENSSL)
#ifdef HAVE_GIOOPENSSL
# include <gioopenssl.h>
#endif
@@ -33,9 +31,7 @@ _frida_agent_environment_init (void)
g_thread_set_garbage_handler (_frida_agent_on_pending_thread_garbage, NULL);
#if defined (HAVE_GIOAPPLE)
g_io_module_apple_register ();
#elif defined (HAVE_GIOOPENSSL)
#ifdef HAVE_GIOOPENSSL
g_io_module_openssl_register ();
#endif
@@ -55,8 +51,6 @@ void
_frida_agent_environment_deinit (void)
{
#ifndef HAVE_MUSL
frida_libc_shim_prepare_to_deinit ();
gum_shutdown ();
gio_shutdown ();
glib_shutdown ();
-14
View File
@@ -1,14 +0,0 @@
FRIDA_1.0 {
global:
frida_agent_main;
local:
*;
};
GLIBC_2.2.5 {
local:
fopen*;
fseeko*;
ftello*;
} FRIDA_1.0;
+3 -9
View File
@@ -28,13 +28,7 @@ if host_os_family == 'windows'
elif host_os_family == 'darwin'
extra_link_args += '-Wl,-exported_symbol,_frida_agent_main'
else
if libc == 'glibc'
symscript = 'frida-agent-glibc.version'
elif host_os == 'android'
symscript = 'frida-agent-android.version'
else
symscript = 'frida-agent.version'
endif
symscript = (host_os == 'android') ? 'frida-agent-android.version' : 'frida-agent.version'
extra_link_args += '-Wl,--version-script,' + meson.current_source_dir() / symscript
extra_link_depends += symscript
endif
@@ -67,7 +61,7 @@ modulated_agent = custom_target('frida-agent-modulated',
)
need_universal_agent = host_os_family == 'darwin' \
and assets_mode == 'installed' \
and get_option('assets') == 'installed' \
and agent_compat != ''
if host_os_family == 'darwin'
@@ -80,7 +74,7 @@ agent = custom_target('frida-agent',
output: need_universal_agent ? f'@agent_name@-@host_abi@' : agent_name,
command: post_process + ['shared-library', identity],
build_by_default: true,
install: assets_mode == 'installed' and not need_universal_agent,
install: get_option('assets') == 'installed' and not need_universal_agent,
install_dir: asset_dir,
)
-50
View File
@@ -1,50 +0,0 @@
namespace Frida {
public class AssetLocation : Object {
public string libdir {
get;
construct;
}
public static AssetLocation detect () {
string? module_path = null;
Gum.Address our_address = Gum.Address.from_pointer (Gum.strip_code_pointer ((void *) detect));
Gum.Process.enumerate_modules ((details) => {
var range = details.range;
if (our_address >= range.base_address && our_address < range.base_address + range.size) {
module_path = details.path;
return false;
}
return true;
});
assert (module_path != null);
string libdir = Path.get_dirname (module_path);
string basename = Path.get_basename (libdir).down ();
if (basename == "bin" || basename == "sbin") {
string parent = Path.get_dirname (libdir);
string candidate = Path.build_filename (parent, Config.FRIDA_LIBDIR);
if (FileUtils.test (candidate, IS_DIR))
libdir = candidate;
}
return new AssetLocation (libdir);
}
private AssetLocation (string libdir) {
Object (libdir: libdir);
}
public string derive_asset_path (string arch, string filename) {
#if DARWIN
return Path.build_filename (libdir, Config.FRIDA_LIBDIR_NAME, filename);
#else
return Path.build_filename (libdir, Config.FRIDA_LIBDIR_NAME, arch, filename);
#endif
}
public string derive_plugin_path (string filename) {
return Path.build_filename (libdir, Config.FRIDA_LIBDIR_NAME, "plugins", filename);
}
}
}
+127 -262
View File
@@ -309,17 +309,8 @@ namespace Frida {
public sealed class Buffer : Object {
public Bytes bytes {
get {
if (_bytes == null)
_bytes = new Bytes.static (_data);
return _bytes;
}
}
public size_t size {
get {
return _data.length;
}
get;
construct;
}
public ByteOrder byte_order {
@@ -332,39 +323,20 @@ namespace Frida {
construct;
}
private Bytes? _bytes;
private unowned uint8[] _data;
private unowned uint8 * data;
private size_t size;
public Buffer (Bytes bytes, ByteOrder byte_order = HOST, uint pointer_size = (uint) sizeof (size_t)) {
Object (
bytes: bytes,
byte_order: byte_order,
pointer_size: pointer_size
);
reset_bytes (bytes);
}
public Buffer.from_data (uint8[] data, ByteOrder byte_order = HOST, uint pointer_size = (uint) sizeof (size_t)) {
Object (
byte_order: byte_order,
pointer_size: pointer_size
);
reset_data (data);
}
public void reset_bytes (Bytes bytes) {
_bytes = bytes;
_data = bytes.get_data ();
}
public void reset_data (uint8[] data) {
_bytes = null;
_data = data;
}
public unowned uint8[] peek_data () {
return _data;
construct {
data = bytes.get_data ();
size = bytes.get_size ();
}
public uint64 read_pointer (size_t offset) {
@@ -498,13 +470,17 @@ namespace Frida {
return *((double *) &bits);
}
public unowned string read_string (size_t offset) throws Error {
public string read_string (size_t offset) throws Error {
string * start = (string *) get_pointer (offset, sizeof (char));
size_t max_length = _data.length - offset;
size_t max_length = size - offset;
string * end = memchr (start, 0, max_length);
if (end == null)
throw new Error.PROTOCOL ("Missing null character");
return start;
size_t size = end - start;
string val = start->substring (0, (long) size);
if (!val.validate ())
throw new Error.PROTOCOL ("Invalid UTF-8 string");
return val;
}
[CCode (cname = "memchr", cheader_filename = "string.h")]
@@ -512,14 +488,17 @@ namespace Frida {
public string read_fixed_string (size_t offset, size_t size) throws Error {
string * start = (string *) get_pointer (offset, size);
size_t max_length = size_t.min (size, _data.length - offset);
size_t max_length = size_t.min (size, this.size - offset);
string * end = memchr (start, 0, max_length);
size_t n;
if (end != null)
n = end - start;
else
n = size;
return start->substring (0, (long) n);
string val = start->substring (0, (long) n);
if (!val.validate ())
throw new Error.PROTOCOL ("Invalid UTF-8 string");
return val;
}
public unowned Buffer write_string (size_t offset, string val) {
@@ -529,14 +508,9 @@ namespace Frida {
}
public Bytes read_bytes (size_t offset, size_t size) {
if (_bytes == null)
return make_bytes_with_owner ((uint8 *) _data + offset, _data.length - size, this);
return _bytes[offset:offset + size];
}
public unowned uint8[] read_data (size_t offset, size_t size) {
unowned uint8 * ptr = get_pointer (offset, size);
return ((uint8[]) ptr)[:size];
var data = new uint8[size + 1];
Memory.copy (data, get_pointer (offset, size), size);
return new Bytes.take ((owned) data);
}
public unowned Buffer write_bytes (size_t offset, Bytes bytes) {
@@ -547,49 +521,129 @@ namespace Frida {
private uint8 * get_pointer (size_t offset, size_t n) {
size_t minimum_size = offset + n;
assert (_data.length >= minimum_size);
return (uint8 *) _data + offset;
assert (size >= minimum_size);
return data + offset;
}
}
public sealed class BufferReader {
public Buffer buffer {
get;
}
public size_t offset {
get;
get {
return _offset;
}
}
public size_t available {
get {
return _size - _offset;
return buffer.bytes.get_size () - _offset;
}
}
private size_t _size;
private Buffer buffer;
private size_t _offset = 0;
public BufferReader (Buffer buffer) {
reset (buffer);
public BufferReader (Buffer buf) {
buffer = buf;
}
public void reset (Buffer buffer) {
_buffer = buffer;
_size = buffer.size;
_offset = 0;
public uint64 read_pointer () throws Error {
var pointer_size = buffer.pointer_size;
check_available (pointer_size);
var ptr = buffer.read_pointer (_offset);
_offset += pointer_size;
return ptr;
}
public void reset_at (Buffer buffer, size_t offset) throws Error {
_buffer = buffer;
_size = buffer.size;
seek (offset);
public int8 read_int8 () throws Error {
check_available (sizeof (int8));
var val = buffer.read_int8 (_offset);
_offset += sizeof (int8);
return val;
}
public unowned BufferReader seek (size_t offset) throws Error {
if (offset > _size)
throw new Error.PROTOCOL ("Malformed buffer: truncated");
_offset = offset;
return this;
public uint8 read_uint8 () throws Error {
check_available (sizeof (uint8));
var val = buffer.read_uint8 (_offset);
_offset += sizeof (uint8);
return val;
}
public int16 read_int16 () throws Error {
check_available (sizeof (int16));
var val = buffer.read_int16 (_offset);
_offset += sizeof (int16);
return val;
}
public uint16 read_uint16 () throws Error {
check_available (sizeof (uint16));
var val = buffer.read_uint16 (_offset);
_offset += sizeof (uint16);
return val;
}
public int32 read_int32 () throws Error {
check_available (sizeof (int32));
var val = buffer.read_int32 (_offset);
_offset += sizeof (int32);
return val;
}
public uint32 read_uint32 () throws Error {
check_available (sizeof (uint32));
var val = buffer.read_uint32 (_offset);
_offset += sizeof (uint32);
return val;
}
public int64 read_int64 () throws Error {
check_available (sizeof (int64));
var val = buffer.read_int64 (_offset);
_offset += sizeof (int64);
return val;
}
public uint64 read_uint64 () throws Error {
check_available (sizeof (uint64));
var val = buffer.read_uint64 (_offset);
_offset += sizeof (uint64);
return val;
}
public float read_float () throws Error {
check_available (sizeof (float));
var val = buffer.read_float (_offset);
_offset += sizeof (float);
return val;
}
public double read_double () throws Error {
check_available (sizeof (double));
var val = buffer.read_double (_offset);
_offset += sizeof (double);
return val;
}
public string read_string () throws Error {
check_available (1);
var val = buffer.read_string (_offset);
_offset += val.length + 1;
return val;
}
public string read_fixed_string (size_t size) throws Error {
check_available (size);
var val = buffer.read_fixed_string (_offset, size);
_offset += size;
return val;
}
public Bytes read_bytes (size_t size) throws Error {
check_available (size);
var val = buffer.bytes[_offset:_offset + size];
_offset += size;
return val;
}
public unowned BufferReader skip (size_t n) throws Error {
@@ -598,195 +652,6 @@ namespace Frida {
return this;
}
public unowned BufferReader align (size_t alignment) throws Error {
size_t mask = alignment - 1;
size_t rem = _offset & mask;
if (rem != 0)
skip (alignment - rem);
return this;
}
public uint64 peek_pointer () throws Error {
var pointer_size = _buffer.pointer_size;
check_available (pointer_size);
return _buffer.read_pointer (_offset);
}
public uint64 read_pointer () throws Error {
var pointer_size = _buffer.pointer_size;
check_available (pointer_size);
var ptr = _buffer.read_pointer (_offset);
_offset += pointer_size;
return ptr;
}
public int8 peek_int8 () throws Error {
check_available (sizeof (int8));
return _buffer.read_int8 (_offset);
}
public int8 read_int8 () throws Error {
check_available (sizeof (int8));
var val = _buffer.read_int8 (_offset);
_offset += sizeof (int8);
return val;
}
public uint8 peek_uint8 () throws Error {
check_available (sizeof (uint8));
return _buffer.read_uint8 (_offset);
}
public uint8 read_uint8 () throws Error {
check_available (sizeof (uint8));
var val = _buffer.read_uint8 (_offset);
_offset += sizeof (uint8);
return val;
}
public int16 peek_int16 () throws Error {
check_available (sizeof (int16));
return _buffer.read_int16 (_offset);
}
public int16 read_int16 () throws Error {
check_available (sizeof (int16));
var val = _buffer.read_int16 (_offset);
_offset += sizeof (int16);
return val;
}
public uint16 peek_uint16 () throws Error {
check_available (sizeof (uint16));
return _buffer.read_uint16 (_offset);
}
public uint16 read_uint16 () throws Error {
check_available (sizeof (uint16));
var val = _buffer.read_uint16 (_offset);
_offset += sizeof (uint16);
return val;
}
public int32 peek_int32 () throws Error {
check_available (sizeof (int32));
return _buffer.read_int32 (_offset);
}
public int32 read_int32 () throws Error {
check_available (sizeof (int32));
var val = _buffer.read_int32 (_offset);
_offset += sizeof (int32);
return val;
}
public uint32 peek_uint32 () throws Error {
check_available (sizeof (uint32));
return _buffer.read_uint32 (_offset);
}
public uint32 read_uint32 () throws Error {
check_available (sizeof (uint32));
var val = _buffer.read_uint32 (_offset);
_offset += sizeof (uint32);
return val;
}
public int64 peek_int64 () throws Error {
check_available (sizeof (int64));
return _buffer.read_int64 (_offset);
}
public int64 read_int64 () throws Error {
check_available (sizeof (int64));
var val = _buffer.read_int64 (_offset);
_offset += sizeof (int64);
return val;
}
public uint64 peek_uint64 () throws Error {
check_available (sizeof (uint64));
return _buffer.read_uint64 (_offset);
}
public uint64 read_uint64 () throws Error {
check_available (sizeof (uint64));
var val = _buffer.read_uint64 (_offset);
_offset += sizeof (uint64);
return val;
}
public float peek_float () throws Error {
check_available (sizeof (float));
return _buffer.read_float (_offset);
}
public float read_float () throws Error {
check_available (sizeof (float));
var val = _buffer.read_float (_offset);
_offset += sizeof (float);
return val;
}
public double peek_double () throws Error {
check_available (sizeof (double));
return _buffer.read_double (_offset);
}
public double read_double () throws Error {
check_available (sizeof (double));
var val = _buffer.read_double (_offset);
_offset += sizeof (double);
return val;
}
public unowned string peek_string () throws Error {
check_available (1);
return _buffer.read_string (_offset);
}
public unowned string read_string () throws Error {
check_available (1);
unowned string val = _buffer.read_string (_offset);
_offset += val.length + 1;
return val;
}
public string peek_fixed_string (size_t size) throws Error {
check_available (size);
return _buffer.read_fixed_string (_offset, size);
}
public string read_fixed_string (size_t size) throws Error {
check_available (size);
var val = _buffer.read_fixed_string (_offset, size);
_offset += size;
return val;
}
public unowned uint8[] peek_data (size_t size) throws Error {
check_available (size);
return _buffer.read_data (_offset, size);
}
public unowned uint8[] read_data (size_t size) throws Error {
check_available (size);
unowned uint8[] slice = _buffer.read_data (_offset, size);
_offset += size;
return slice;
}
public Bytes read_bytes (size_t size) throws Error {
check_available (size);
var val = _buffer.read_bytes (_offset, size);
_offset += size;
return val;
}
public unowned uint8[] read_remaining_data () throws Error {
return read_data (available);
}
private void check_available (size_t n) throws Error {
if (available < n)
throw new Error.PROTOCOL ("Malformed buffer: truncated");
+2 -12
View File
@@ -1,26 +1,18 @@
#ifndef __FRIDA_ATOMICS_H__
#define __FRIDA_ATOMICS_H__
#include <glib.h>
G_BEGIN_DECLS
#ifdef _MSC_VER
/* TODO: Add once needed. */
#else
typedef guint64 FridaAtomicU64 __attribute__ ((aligned (8)));
static inline guint64
frida_atomics_load_u64_acquire (volatile FridaAtomicU64 * p)
static inline guint64 frida_atomics_load_u64_acquire (volatile guint64 * p)
{
return __atomic_load_n (p, __ATOMIC_ACQUIRE);
}
static inline void
frida_atomics_store_u64_release (volatile FridaAtomicU64 * p, guint64 v)
static inline void frida_atomics_store_u64_release (volatile guint64 * p, guint64 v)
{
__atomic_store_n (p, v, __ATOMIC_RELEASE);
}
@@ -32,6 +24,4 @@ static inline guint32 frida_atomics_load_u32_acquire (volatile guint32 * p)
#endif
G_END_DECLS
#endif
+3 -3
View File
@@ -1,6 +1,6 @@
[CCode (cheader_filename = "frida-atomics.h")]
namespace Frida.Atomics {
public static uint64 load_u64_acquire (uint64 * p);
public static void store_u64_release (uint64 * p, uint64 v);
public static uint32 load_u32_acquire (uint32 * p);
public static uint64 load_u64_acquire (void * p);
public static void store_u64_release (void * p, uint64 v);
public static uint32 load_u32_acquire (void * p);
}
-4
View File
@@ -6,8 +6,6 @@
#include <glib.h>
#include <xpc/xpc.h>
G_BEGIN_DECLS
typedef void (* FridaXpcHandler) (xpc_object_t object, gpointer user_data);
typedef gboolean (* FridaXpcDictionaryApplier) (const gchar * key, xpc_object_t val, gpointer user_data);
@@ -19,8 +17,6 @@ void _frida_xpc_connection_send_message_with_reply (xpc_connection_t connection,
gchar * _frida_xpc_object_to_string (xpc_object_t object);
gboolean _frida_xpc_dictionary_apply (xpc_object_t dict, FridaXpcDictionaryApplier applier, gpointer user_data);
G_END_DECLS
#endif
#endif
-41
View File
@@ -1,41 +0,0 @@
#ifndef __FRIDA_JNI_H__
#define __FRIDA_JNI_H__
#include <jni.h>
G_BEGIN_DECLS
typedef jint (* JNIDestroyJavaVMFunc) (JavaVM *);
typedef jint (* JNIAttachCurrentThreadFunc) (JavaVM *, JNIEnv **, void *);
typedef jint (* JNIDetachCurrentThreadFunc) (JavaVM *);
typedef jint (* JNIGetEnvFunc) (JavaVM *, JNIEnv **, jint);
typedef jclass (* JNIFindClassFunc) (JNIEnv *, const char *);
typedef jthrowable (* JNIExceptionOccurredFunc) (JNIEnv *);
typedef void (* JNIExceptionDescribeFunc) (JNIEnv *);
typedef void (* JNIExceptionClearFunc) (JNIEnv *);
typedef jint (* JNIPushLocalFrameFunc) (JNIEnv *, jint);
typedef jobject (* JNIPopLocalFrameFunc) (JNIEnv *, jobject);
typedef jobject (* JNINewGlobalRefFunc) (JNIEnv *, jobject);
typedef void (* JNIDeleteGlobalRefFunc) (JNIEnv *, jobject);
typedef void (* JNIDeleteLocalRefFunc) (JNIEnv *, jobject);
typedef jobject (* JNINewObjectFunc) (JNIEnv *, jclass, jmethodID, ...);
typedef jclass (* JNIGetObjectClassFunc) (JNIEnv *, jobject);
typedef jmethodID (* JNIGetMethodIDFunc) (JNIEnv *, jclass, const char *, const char *);
typedef jobject (* JNICallObjectMethodFunc) (JNIEnv *, jobject, jmethodID, ...);
typedef jstring (* JNINewStringUTFFunc) (JNIEnv *, const char *);
typedef const char * (* JNIGetStringUTFCharsFunc) (JNIEnv *, jstring, jboolean *);
typedef void (* JNIReleaseStringUTFCharsFunc) (JNIEnv *, jstring, const char *);
typedef jboolean (* JNIExceptionCheckFunc) (JNIEnv *);
G_END_DECLS
#endif
+2 -18
View File
@@ -46,7 +46,7 @@ namespace Frida {
public extern unowned LinuxSyscallSignature[]? get_compat32_syscall_signatures ();
public struct LinuxSyscallSignature {
public int nr;
public uint nr;
public string name;
public uint8 nargs;
public LinuxSyscallArg args[6];
@@ -128,7 +128,6 @@ namespace Frida {
}
}
#if HAVE_LOCAL_BACKEND
public sealed class BpfObject {
public Programs programs {
get;
@@ -142,7 +141,7 @@ namespace Frida {
private char[] kernel_log_buf;
public static BpfObject open (string name, uint8[] blob) throws Error {
var log_buf = new char[128 * 1024];
var log_buf = new char[64 * 1024];
var opts = Libbpf.Object.OpenOpts ();
opts.sz = sizeof (Libbpf.Object.OpenOpts);
@@ -349,18 +348,6 @@ namespace Frida {
remove_raw ((uint8[]) &key);
}
public void update_u64_u8 (uint64 key, uint8 val) throws Error {
update_raw ((uint8[]) &key, (uint8[]) &val);
}
public void update_u64_u32 (uint64 key, uint32 val) throws Error {
update_raw ((uint8[]) &key, (uint8[]) &val);
}
public void remove_u64 (uint64 key) throws Error {
remove_raw ((uint8[]) &key);
}
public void foreach_percpu_value<T> (uint8[] key, PercpuValueFunc<T> func) throws Error {
var ncpus = check_libbpf_result (Libbpf.num_possible_cpus ());
var percpu_stride = round_up_8 (value_size);
@@ -523,7 +510,6 @@ namespace Frida {
STOP,
}
}
#endif
namespace PerfEvent {
public FileDescriptor open (PerfEventAttr * attr, int pid, int cpu, int group_fd, uint flags) throws Error {
@@ -538,9 +524,7 @@ namespace Frida {
throw new Error.NOT_SUPPORTED ("%s (errno=%d: %s)".printf (message, Posix.errno, Posix.strerror (Posix.errno)));
}
#if HAVE_LOCAL_BACKEND
private size_t round_up_8 (size_t x) {
return (x + 7) & ~((size_t) 7);
}
#endif
}
+10 -17
View File
@@ -1,5 +1,4 @@
base_sources = [
'asset-location.vala',
'session.vala',
'session-glue.c',
'channel.vala',
@@ -16,8 +15,6 @@ base_sources = [
'buffer.vala',
'buffer-glue.c',
'value.vala',
'xnu-syscalls' / 'xnu-syscalls.vala',
'xnu-syscalls' / 'xnu-syscalls-glue.c',
]
extra_vala_args = []
@@ -48,10 +45,8 @@ if host_os_family == 'linux'
extra_vala_args += [
'--pkg=linux',
'--pkg=frida-atomics',
'--pkg=libbpf',
]
if have_local_backend
extra_vala_args += '--pkg=libbpf'
endif
syscall_arch_from_abi = {
'armbe': 'arm',
@@ -78,7 +73,7 @@ extra_deps = []
if host_os_family != 'windows'
extra_deps += gio_unix_dep
endif
if host_os_family == 'linux' and have_local_backend
if host_os_family == 'linux'
extra_deps += libbpf_dep
endif
@@ -115,7 +110,7 @@ base = static_library('frida-base-' + api_version, base_sources,
vala_gir: base_gir_name,
vala_vapi: f'frida-base-@[email protected]',
dependencies: [glib_dep, gobject_dep, gio_dep, libsoup_dep, nice_dep, usrsctp_dep, gee_dep, json_glib_dep, gum_dep, openssl_dep] + extra_deps,
install: have_in_tree_payloads,
install: true,
install_dir: [true, header_install_dir, true, false],
)
@@ -127,12 +122,10 @@ base_dep = declare_dependency(
base_build_dir = meson.current_build_dir()
if have_in_tree_payloads
pkg = import('pkgconfig')
pkg.generate(base,
filebase: f'frida-base-@api_version@',
name: 'Frida Base Library',
version: frida_version,
description: 'Basic building blocks',
)
endif
pkg = import('pkgconfig')
pkg.generate(base,
filebase: f'frida-base-@api_version@',
name: 'Frida Base Library',
version: frida_version,
description: 'Basic building blocks',
)
+9 -417
View File
@@ -1,432 +1,26 @@
#ifdef HAVE_NICE
#define OPENSSL_SUPPRESS_DEPRECATED
#include "frida-base.h"
#include <errno.h>
#include <openssl/asn1.h>
#include <openssl/bio.h>
#include <openssl/bn.h>
#include <openssl/evp.h>
#include <openssl/pem.h>
#include <openssl/rsa.h>
#include <openssl/x509.h>
#include <usrsctp.h>
#ifdef HAVE_GIOAPPLE
# include <CoreFoundation/CoreFoundation.h>
# include <Security/Security.h>
#else
# define OPENSSL_SUPPRESS_DEPRECATED
# include <openssl/asn1.h>
# include <openssl/bio.h>
# include <openssl/bn.h>
# include <openssl/evp.h>
# include <openssl/pem.h>
# include <openssl/rsa.h>
# include <openssl/x509.h>
#endif
#ifdef HAVE_GIOAPPLE
static SecKeyRef frida_rsa_keypair_generate (void);
static void frida_rsa_export_public_key (SecKeyRef private_key, GByteArray * out);
static void frida_rsa_export_private_key (SecKeyRef private_key, GByteArray * out);
static void frida_rsa_sign_sha256 (SecKeyRef private_key, const guint8 * message, gsize message_length, GByteArray * out);
static void frida_build_tbs_certificate (GByteArray * out, const GByteArray * subject_public_key);
static void frida_build_name (GByteArray * out);
static void frida_build_rdn (GByteArray * out, const guint8 * oid, gsize oid_length, guint8 value_tag, const gchar * value);
static void frida_build_validity (GByteArray * out);
static void frida_build_subject_public_key_info (GByteArray * out, const GByteArray * rsa_public_key);
static void frida_build_signed_certificate (GByteArray * out, const GByteArray * tbs, const GByteArray * signature);
static void frida_build_algorithm_identifier (GByteArray * out, const guint8 * oid, gsize oid_length);
static void frida_build_pkcs8_private_key_info (GByteArray * out, const GByteArray * rsa_private_key);
static gchar * frida_pem_encode (const gchar * type, const guint8 * der, gsize der_length);
static void frida_der_append_tlv (GByteArray * out, guint8 tag, const guint8 * value, gsize length);
static void frida_der_append_length (GByteArray * out, gsize length);
static void frida_der_append_integer_uint (GByteArray * out, guint64 value);
static void frida_der_append_null (GByteArray * out);
static void frida_der_append_oid (GByteArray * out, const guint8 * oid, gsize length);
static void frida_der_append_utctime (GByteArray * out, time_t t);
static void frida_der_append_bit_string (GByteArray * out, const guint8 * bytes, gsize length);
static const guint8 frida_oid_country[] = { 0x55, 0x04, 0x06 };
static const guint8 frida_oid_organization[] = { 0x55, 0x04, 0x0a };
static const guint8 frida_oid_common_name[] = { 0x55, 0x04, 0x03 };
static const guint8 frida_oid_rsa_encryption[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01 };
static const guint8 frida_oid_sha256_with_rsa[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b };
#else
static gchar * frida_steal_bio_to_string (BIO ** bio);
#endif
static int frida_on_connection_output (void * addr, void * buffer, size_t length, uint8_t tos, uint8_t set_df);
static void frida_on_debug_printf (const char * format, ...);
static void frida_on_upcall (struct socket * sock, void * user_data, int flags);
#ifdef HAVE_GIOAPPLE
void
_frida_generate_certificate (guint8 ** cert_der, gint * cert_der_length, gchar ** cert_pem, gchar ** key_pem)
{
SecKeyRef private_key;
GByteArray * rsa_public_key, * rsa_private_key, * subject_public_key, * tbs, * signature, * certificate, * pkcs8;
*cert_der = NULL;
*cert_der_length = 0;
*cert_pem = NULL;
*key_pem = NULL;
private_key = frida_rsa_keypair_generate ();
rsa_public_key = g_byte_array_new ();
frida_rsa_export_public_key (private_key, rsa_public_key);
rsa_private_key = g_byte_array_new ();
frida_rsa_export_private_key (private_key, rsa_private_key);
subject_public_key = g_byte_array_new ();
frida_build_subject_public_key_info (subject_public_key, rsa_public_key);
tbs = g_byte_array_new ();
frida_build_tbs_certificate (tbs, subject_public_key);
signature = g_byte_array_new ();
frida_rsa_sign_sha256 (private_key, tbs->data, tbs->len, signature);
certificate = g_byte_array_new ();
frida_build_signed_certificate (certificate, tbs, signature);
pkcs8 = g_byte_array_new ();
frida_build_pkcs8_private_key_info (pkcs8, rsa_private_key);
*cert_der = g_memdup2 (certificate->data, certificate->len);
*cert_der_length = certificate->len;
*cert_pem = frida_pem_encode ("CERTIFICATE", certificate->data, certificate->len);
*key_pem = frida_pem_encode ("PRIVATE KEY", pkcs8->data, pkcs8->len);
g_byte_array_unref (pkcs8);
g_byte_array_unref (certificate);
g_byte_array_unref (signature);
g_byte_array_unref (tbs);
g_byte_array_unref (subject_public_key);
g_byte_array_unref (rsa_private_key);
g_byte_array_unref (rsa_public_key);
CFRelease (private_key);
}
static SecKeyRef
frida_rsa_keypair_generate (void)
{
SecKeyRef private_key;
CFMutableDictionaryRef attrs;
const int key_size_bits = 2048;
CFNumberRef key_size;
attrs = CFDictionaryCreateMutable (kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
key_size = CFNumberCreate (kCFAllocatorDefault, kCFNumberIntType, &key_size_bits);
CFDictionarySetValue (attrs, kSecAttrKeyType, kSecAttrKeyTypeRSA);
CFDictionarySetValue (attrs, kSecAttrKeySizeInBits, key_size);
CFRelease (key_size);
private_key = SecKeyCreateRandomKey (attrs, NULL);
g_assert (private_key != NULL);
CFRelease (attrs);
return private_key;
}
static void
frida_rsa_export_public_key (SecKeyRef private_key, GByteArray * out)
{
SecKeyRef public_key;
CFDataRef data;
public_key = SecKeyCopyPublicKey (private_key);
g_assert (public_key != NULL);
data = SecKeyCopyExternalRepresentation (public_key, NULL);
g_assert (data != NULL);
g_byte_array_append (out, CFDataGetBytePtr (data), CFDataGetLength (data));
CFRelease (data);
CFRelease (public_key);
}
static void
frida_rsa_export_private_key (SecKeyRef private_key, GByteArray * out)
{
CFDataRef data;
data = SecKeyCopyExternalRepresentation (private_key, NULL);
g_assert (data != NULL);
g_byte_array_append (out, CFDataGetBytePtr (data), (guint) CFDataGetLength (data));
CFRelease (data);
}
static void
frida_rsa_sign_sha256 (SecKeyRef private_key, const guint8 * message, gsize message_length, GByteArray * out)
{
CFDataRef to_sign, signature;
to_sign = CFDataCreate (kCFAllocatorDefault, message, (CFIndex) message_length);
signature = SecKeyCreateSignature (private_key, kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA256, to_sign, NULL);
g_assert (signature != NULL);
g_byte_array_append (out, CFDataGetBytePtr (signature), (guint) CFDataGetLength (signature));
CFRelease (signature);
CFRelease (to_sign);
}
static void
frida_build_tbs_certificate (GByteArray * out, const GByteArray * subject_public_key)
{
GByteArray * inner = g_byte_array_new ();
frida_der_append_integer_uint (inner, 1);
frida_build_algorithm_identifier (inner, frida_oid_sha256_with_rsa, sizeof (frida_oid_sha256_with_rsa));
frida_build_name (inner);
frida_build_validity (inner);
frida_build_name (inner);
g_byte_array_append (inner, subject_public_key->data, subject_public_key->len);
frida_der_append_tlv (out, 0x30, inner->data, inner->len);
g_byte_array_unref (inner);
}
static void
frida_build_name (GByteArray * out)
{
GByteArray * inner = g_byte_array_new ();
frida_build_rdn (inner, frida_oid_country, sizeof (frida_oid_country), 0x13, "CA");
frida_build_rdn (inner, frida_oid_organization, sizeof (frida_oid_organization), 0x0c, "Frida");
frida_build_rdn (inner, frida_oid_common_name, sizeof (frida_oid_common_name), 0x0c, "lolcathost");
frida_der_append_tlv (out, 0x30, inner->data, inner->len);
g_byte_array_unref (inner);
}
static void
frida_build_rdn (GByteArray * out, const guint8 * oid, gsize oid_length, guint8 value_tag, const gchar * value)
{
GByteArray * atv, * rdn;
atv = g_byte_array_new ();
rdn = g_byte_array_new ();
frida_der_append_oid (atv, oid, oid_length);
frida_der_append_tlv (atv, value_tag, (const guint8 *) value, strlen (value));
frida_der_append_tlv (rdn, 0x30, atv->data, atv->len);
frida_der_append_tlv (out, 0x31, rdn->data, rdn->len);
g_byte_array_unref (rdn);
g_byte_array_unref (atv);
}
static void
frida_build_validity (GByteArray * out)
{
const time_t lifetime_seconds = 15780000;
GByteArray * inner;
time_t not_before, not_after;
inner = g_byte_array_new ();
not_before = time (NULL);
not_after = not_before + lifetime_seconds;
frida_der_append_utctime (inner, not_before);
frida_der_append_utctime (inner, not_after);
frida_der_append_tlv (out, 0x30, inner->data, inner->len);
g_byte_array_unref (inner);
}
static void
frida_build_subject_public_key_info (GByteArray * out, const GByteArray * rsa_public_key)
{
GByteArray * inner = g_byte_array_new ();
frida_build_algorithm_identifier (inner, frida_oid_rsa_encryption, sizeof (frida_oid_rsa_encryption));
frida_der_append_bit_string (inner, rsa_public_key->data, rsa_public_key->len);
frida_der_append_tlv (out, 0x30, inner->data, inner->len);
g_byte_array_unref (inner);
}
static void
frida_build_signed_certificate (GByteArray * out, const GByteArray * tbs, const GByteArray * signature)
{
GByteArray * inner = g_byte_array_new ();
g_byte_array_append (inner, tbs->data, tbs->len);
frida_build_algorithm_identifier (inner, frida_oid_sha256_with_rsa, sizeof (frida_oid_sha256_with_rsa));
frida_der_append_bit_string (inner, signature->data, signature->len);
frida_der_append_tlv (out, 0x30, inner->data, inner->len);
g_byte_array_unref (inner);
}
static void
frida_build_algorithm_identifier (GByteArray * out, const guint8 * oid, gsize oid_length)
{
GByteArray * inner = g_byte_array_new ();
frida_der_append_oid (inner, oid, oid_length);
frida_der_append_null (inner);
frida_der_append_tlv (out, 0x30, inner->data, inner->len);
g_byte_array_unref (inner);
}
static void
frida_build_pkcs8_private_key_info (GByteArray * out, const GByteArray * rsa_private_key)
{
GByteArray * inner = g_byte_array_new ();
frida_der_append_integer_uint (inner, 0);
frida_build_algorithm_identifier (inner, frida_oid_rsa_encryption, sizeof (frida_oid_rsa_encryption));
frida_der_append_tlv (inner, 0x04, rsa_private_key->data, rsa_private_key->len);
frida_der_append_tlv (out, 0x30, inner->data, inner->len);
g_byte_array_unref (inner);
}
static gchar *
frida_pem_encode (const gchar * type, const guint8 * der, gsize der_length)
{
GString * pem;
gchar * base64;
gsize length, i;
base64 = g_base64_encode (der, der_length);
length = strlen (base64);
pem = g_string_sized_new (length + 128);
g_string_append_printf (pem, "-----BEGIN %s-----\n", type);
for (i = 0; i < length; i += 64)
{
gsize chunk = MIN (64, length - i);
g_string_append_len (pem, base64 + i, chunk);
g_string_append_c (pem, '\n');
}
g_string_append_printf (pem, "-----END %s-----\n", type);
g_free (base64);
return g_string_free (pem, FALSE);
}
static void
frida_der_append_tlv (GByteArray * out, guint8 tag, const guint8 * value, gsize length)
{
g_byte_array_append (out, &tag, 1);
frida_der_append_length (out, length);
if (length > 0)
g_byte_array_append (out, value, length);
}
static void
frida_der_append_length (GByteArray * out, gsize length)
{
gint i;
guint8 buf[9], header;
if (length < 0x80)
{
guint8 b = (guint8) length;
g_byte_array_append (out, &b, 1);
return;
}
i = 0;
while (length > 0)
{
buf[++i] = (guint8) (length & 0xff);
length >>= 8;
}
header = (guint8) (0x80 | i);
g_byte_array_append (out, &header, 1);
while (i > 0)
{
g_byte_array_append (out, &buf[i], 1);
i--;
}
}
static void
frida_der_append_integer_uint (GByteArray * out, guint64 value)
{
gint i;
guint8 buf[9];
gint start;
for (i = 7; i >= 0; i--)
{
buf[i + 1] = (guint8) (value & 0xff);
value >>= 8;
}
buf[0] = 0;
start = 0;
while (start < 8 && buf[start] == 0 && (buf[start + 1] & 0x80) == 0)
start++;
frida_der_append_tlv (out, 0x02, buf + start, (gsize) (9 - start));
}
static void
frida_der_append_null (GByteArray * out)
{
frida_der_append_tlv (out, 0x05, NULL, 0);
}
static void
frida_der_append_oid (GByteArray * out, const guint8 * oid, gsize length)
{
frida_der_append_tlv (out, 0x06, oid, length);
}
static void
frida_der_append_utctime (GByteArray * out, time_t t)
{
struct tm tm;
gchar buf[16];
gmtime_r (&t, &tm);
g_snprintf (buf, sizeof (buf), "%02d%02d%02d%02d%02d%02dZ",
tm.tm_year % 100, tm.tm_mon + 1, tm.tm_mday,
tm.tm_hour, tm.tm_min, tm.tm_sec);
frida_der_append_tlv (out, 0x17, (const guint8 *) buf, strlen (buf));
}
static void
frida_der_append_bit_string (GByteArray * out, const guint8 * bytes, gsize length)
{
guint8 tag = 0x03;
guint8 unused_bits = 0;
g_byte_array_append (out, &tag, 1);
frida_der_append_length (out, length + 1);
g_byte_array_append (out, &unused_bits, 1);
if (length > 0)
g_byte_array_append (out, bytes, length);
}
#else
void
_frida_generate_certificate (guint8 ** cert_der, gint * cert_der_length, gchar ** cert_pem, gchar ** key_pem)
{
@@ -496,8 +90,6 @@ frida_steal_bio_to_string (BIO ** bio)
return result;
}
#endif
void
_frida_sctp_connection_initialize_sctp_backend (void)
{
+1 -12
View File
@@ -2170,10 +2170,7 @@ namespace Frida {
public static string enum_to_nick<T> (int val) {
var klass = (EnumClass) typeof (T).class_ref ();
unowned EnumValue? v = klass.get_value (val);
if (v == null)
return "unknown-0x%x".printf (val);
return v.value_nick;
return klass.get_value (val).value_nick;
}
}
@@ -2199,13 +2196,5 @@ namespace Frida {
uint64 b = val_b;
return a == b;
}
public uint bytes_hash (Bytes b) {
return b.hash ();
}
public static bool bytes_equal (Bytes a, Bytes b) {
return a.compare (b) == 0;
}
}
}
+10 -150
View File
@@ -128,11 +128,6 @@ namespace Frida {
set;
}
public WebRequestHandler? request_handler {
get;
set;
}
public EndpointParameters (string? address = null, uint16 port = 0, TlsCertificate? certificate = null,
string? origin = null, AuthenticationService? auth_service = null, File? asset_root = null) {
Object (
@@ -146,75 +141,6 @@ namespace Frida {
}
}
public interface WebRequestHandler : Object {
public abstract async WebResponse? handle_request (WebRequest request, Cancellable? cancellable) throws Error, IOError;
}
public sealed class WebRequest : Object {
public string method {
get;
construct;
}
public string path {
get;
construct;
}
public string? query_string {
get;
construct;
}
public Bytes? body {
get;
construct;
}
private Soup.MessageHeaders raw_headers;
internal WebRequest (string method, string path, string? query_string, Soup.MessageHeaders headers, Bytes? body) {
Object (method: method, path: path, query_string: query_string, body: body);
raw_headers = headers;
}
public void foreach_header (WebRequestHeaderFunc func) {
raw_headers.foreach ((name, val) => {
func (name, val);
});
}
}
public delegate void WebRequestHeaderFunc (string name, string val);
public sealed class WebResponse : Object {
public uint status {
get;
construct;
}
public Bytes body {
get;
construct;
}
private Soup.MessageHeaders raw_headers = new Soup.MessageHeaders (RESPONSE);
public WebResponse (uint status, Bytes body) {
Object (status: status, body: body);
}
public void add_header (string name, string val) {
raw_headers.append (name, val);
}
internal void write_headers_to (Soup.MessageHeaders target) {
raw_headers.foreach ((name, val) => {
target.replace (name, val);
});
}
}
public async IOStream negotiate_connection (IOStream stream, WebServiceTransport transport, string host, string? origin,
Cancellable? cancellable) throws Error, IOError {
var input = (DataInputStream) Object.new (typeof (DataInputStream),
@@ -542,14 +468,14 @@ namespace Frida {
server.add_websocket_handler ("/ws", endpoint_params.origin, null, on_websocket_opened);
if (endpoint_params.request_handler != null || endpoint_params.asset_root != null)
server.add_handler (null, on_http_request);
if (endpoint_params.asset_root != null)
server.add_handler (null, on_asset_request);
}
public void close () {
io_cancellable.cancel ();
if (endpoint_params.request_handler != null || endpoint_params.asset_root != null)
if (endpoint_params.asset_root != null)
server.remove_handler ("/");
server.remove_handler ("/ws");
@@ -649,77 +575,20 @@ namespace Frida {
connections.remove (connection);
}
private void on_http_request (Soup.Server server, Soup.ServerMessage msg, string path,
private void on_asset_request (Soup.Server server, Soup.ServerMessage msg, string path,
HashTable<string, string>? query) {
msg.get_response_headers ().replace ("Server", "Frida/" + _version_string ());
msg.pause ();
handle_http_request.begin (msg, path);
}
private async void handle_http_request (Soup.ServerMessage msg, string path) {
WebRequestHandler? handler = endpoint_params.request_handler;
if (handler != null) {
if (yield try_request_handler (handler, msg, path, io_cancellable))
return;
}
File? asset_root = endpoint_params.asset_root;
if (asset_root != null) {
unowned string method = msg.get_method ();
if (method != "GET" && method != "HEAD") {
msg.set_status (Soup.Status.METHOD_NOT_ALLOWED, null);
msg.unpause ();
return;
}
File location = asset_root.resolve_relative_path (path.next_char ());
yield handle_asset_request (path, location, msg);
unowned string method = msg.get_method ();
if (method != "GET" && method != "HEAD") {
msg.set_status (Soup.Status.METHOD_NOT_ALLOWED, null);
return;
}
msg.set_status (Soup.Status.NOT_FOUND, null);
msg.unpause ();
}
File location = endpoint_params.asset_root.resolve_relative_path (path.next_char ());
private static async bool try_request_handler (WebRequestHandler handler, Soup.ServerMessage msg, string path,
Cancellable? cancellable) {
var body = msg.get_request_body ();
Bytes? request_body = (body.length != 0) ? body.flatten () : null;
unowned Uri? uri = msg.get_uri ();
string? query_string = (uri != null) ? uri.get_query () : null;
var request = new WebRequest (msg.get_method (), path, query_string, msg.get_request_headers (),
request_body);
WebResponse? response;
try {
response = yield handler.handle_request (request, cancellable);
} catch (Error e) {
msg.set_status (Soup.Status.INTERNAL_SERVER_ERROR, null);
msg.set_response ("text/plain; charset=utf-8", Soup.MemoryUse.COPY, e.message.data);
msg.unpause ();
return true;
} catch (IOError e) {
msg.unpause ();
return true;
}
if (response == null)
return false;
apply_response (msg, response);
msg.unpause ();
return true;
}
private static void apply_response (Soup.ServerMessage msg, WebResponse response) {
msg.set_status (response.status, null);
response.write_headers_to (msg.get_response_headers ());
Bytes body = response.body;
if (body.length > 0)
msg.get_response_body ().append_bytes (body);
msg.pause ();
handle_asset_request.begin (path, location, msg);
}
private async void handle_asset_request (string path, File file, Soup.ServerMessage msg) {
@@ -1071,12 +940,6 @@ namespace Frida {
Memory.copy (buffer, recv_queue.data, n);
recv_queue.remove_range (0, (uint) n);
if (recv_queue.len == 0) {
#if HAVE_SOUP_WEBSOCKET_BACKPRESSURE
websocket.resume_input ();
#endif
}
update_pending_io ();
} else {
if (state == OPEN)
@@ -1143,9 +1006,6 @@ namespace Frida {
private void on_message (int type, Bytes message) {
with_state_lock (() => {
recv_queue.append (message.get_data ());
#if HAVE_SOUP_WEBSOCKET_BACKPRESSURE
websocket.pause_input ();
#endif
update_pending_io ();
});
}
+1 -26
View File
@@ -288,7 +288,7 @@ namespace Frida {
public JsonObjectReader (string json) throws Error {
try {
reader = make_json_reader (json);
reader = new Json.Reader (Json.from_string (json));
} catch (GLib.Error e) {
throw new Error.INVALID_ARGUMENT ("%s", e.message);
}
@@ -404,29 +404,4 @@ namespace Frida {
throw new Error.PROTOCOL ("%s", e.message);
}
}
/*
* Constructs a Json.Reader for the given JSON string, working around the
* json_node_copy() bug in unpatched json-glib (GNOME bugzilla #774684).
*
* Json.Reader's set_root() copies the supplied node via json_node_copy().
* For object/array nodes that copy is a thin shell that shares the original
* JsonObject/JsonArray via refcount, but the members inside the shared
* container have their parent pointers set to the *original* root, not the
* shell. If the original is then dropped, json_reader_end_member()'s walk
* via json_node_get_parent() touches a freed node — which on builds with
* glib checks enabled (e.g. Fedora) trips JSON_NODE_IS_VALID and aborts.
*
* We keep the original root alive by attaching it to the reader as object
* data; the destroy notify drops our reference when the reader is finalized.
*/
public Json.Reader make_json_reader (string json) throws GLib.Error {
return make_json_reader_from_node (Json.from_string (json));
}
public Json.Reader make_json_reader_from_node (Json.Node root) {
var reader = new Json.Reader (root);
reader.set_data<Json.Node> ("frida-json-root", root);
return reader;
}
}
-860
View File
@@ -1,860 +0,0 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from __future__ import annotations
import argparse
import re
from dataclasses import dataclass
from pathlib import Path
from typing import Dict, List, Optional, Tuple
MAX_ARGS = 9
@dataclass(frozen=True)
class SyscallArg:
type: str
name: str
@dataclass(frozen=True)
class SyscallSignature:
name: str
args: Tuple[SyscallArg, ...]
MACH_TRAP_INDEXED_CALL_RE = re.compile(r"/\*\s*(?P<idx>\d+)\s*\*/\s*MACH_TRAP\s*\(")
MACH_TRAPS_IFNDEF_KERNEL_RE = re.compile(r"^\s*#ifndef\s+KERNEL\b", re.MULTILINE)
MACH_TRAPS_ELSE_KERNEL_RE = re.compile(r"^\s*#else\b.*\bKERNEL\b", re.MULTILINE)
USER_EXTERN_PROTO_RE = re.compile(
r"^\s*extern\s+(?P<ret>.+?)\s+(?P<fn>[A-Za-z_]\w*)\s*\((?P<args>.*?)\)\s*;",
re.MULTILINE | re.DOTALL,
)
KERNEL_STRUCT_RE = re.compile(
r"\bstruct\s+(?P<name>[A-Za-z_]\w*)\s*\{\s*(?P<body>.*?)\s*\}\s*;",
re.DOTALL,
)
KERNEL_TRAP_EXTERN_RE = re.compile(
r"^\s*(?:extern\s+)?(?P<ret>.+?)\s+(?P<fn>[A-Za-z_]\w*)\s*\(\s*struct\s+(?P<args_struct>[A-Za-z_]\w*)\s*\*\s*args\s*\)\s*;",
re.MULTILINE | re.DOTALL,
)
PAD_ARG_RE = re.compile(
r"\bPAD_ARG_\s*\(\s*(?P<ty>[^,]+?)\s*,\s*(?P<name>[^)]+?)\s*\)\s*;",
)
PLAIN_FIELD_RE = re.compile(r"^\s*(?P<ty>.+?)\s+(?P<name>[A-Za-z_]\w*)\s*;\s*$")
BSD_MASTER_ENTRY_RE = re.compile(
r"^\s*(?P<nr>\d+)\s+(?P<audit>\S+)\s+(?P<files>\S+)\s+\{\s*(?P<proto>[^}]+?)\s*\}\s*(?:\{.*\})?\s*$"
)
BSD_MASTER_PROTO_RE = re.compile(
r"^\s*(?P<ret>.+?)\s+(?P<fn>[A-Za-z_]\w*)\s*\((?P<args>.*)\)\s*(?P<attrs>.*)$",
re.DOTALL,
)
LINE_COMMENT_RE = re.compile(r"//.*$")
BLOCK_COMMENT_RE = re.compile(r"/\*[^*]*\*+(?:[^/*][^*]*\*+)*/")
TRAILING_ARRAY_SUFFIX_RE = re.compile(r"\[[^\]]*\]\s*$")
POINTER_SPACING_RE = re.compile(r"\s*\*\s*")
PARAM_NAME_RE = re.compile(r"[A-Za-z_]\w*$")
def main() -> int:
ap = argparse.ArgumentParser()
ap.add_argument("--kernel-tree", required=True)
ap.add_argument("--out-vala", required=True)
ap.add_argument("--out-c", required=True)
args = ap.parse_args()
kernel_tree = Path(args.kernel_tree).resolve()
if not kernel_tree.exists():
raise SystemExit(f"--kernel-tree does not exist: {kernel_tree}")
mach_numbers, mach_sigs = load_mach_traps(kernel_tree)
bsd_numbers, bsd_sigs = load_bsd_syscalls_master(kernel_tree)
vala = render_vala(
mach_numbers=mach_numbers,
bsd_numbers=bsd_numbers,
)
c_src = render_c_source(
mach_numbers=mach_numbers,
bsd_numbers=bsd_numbers,
mach_sigs=mach_sigs,
bsd_sigs=bsd_sigs,
)
out_vala = Path(args.out_vala)
out_c = Path(args.out_c)
out_vala.parent.mkdir(parents=True, exist_ok=True)
out_c.parent.mkdir(parents=True, exist_ok=True)
out_vala.write_text(vala, encoding="utf-8")
out_c.write_text(c_src, encoding="utf-8")
return 0
def load_mach_traps(
kernel_tree: Path,
) -> Tuple[Dict[int, str], Dict[str, SyscallSignature]]:
table_path = kernel_tree / "osfmk" / "kern" / "syscall_sw.c"
if not table_path.exists():
raise RuntimeError(f"Missing Mach trap table source: {table_path}")
header_path = kernel_tree / "osfmk" / "mach" / "mach_traps.h"
if not header_path.exists():
raise RuntimeError(f"Missing Mach traps header: {header_path}")
table_text = table_path.read_text(encoding="utf-8", errors="ignore")
trap_routines = parse_mach_trap_table(table_text, table_path)
header_text = header_path.read_text(encoding="utf-8", errors="ignore")
userspace_text, kernel_text = split_mach_traps_header(header_text, header_path)
userspace_protos = parse_userspace_mach_traps_prototypes(
userspace_text, header_path
)
kernel_argmap = parse_kernel_mach_traps_args(kernel_text, header_path)
numbers: Dict[int, str] = {}
sigs: Dict[str, SyscallSignature] = {}
for index, routine in trap_routines:
if routine == "kern_invalid":
continue
nr = -index
public_name = normalize_mach_name(routine)
if public_name == "":
raise RuntimeError(f"{table_path}: empty normalized name from {routine!r}")
if nr in numbers:
raise RuntimeError(f"{table_path}: duplicate mach trap number {nr}")
if public_name in sigs:
raise RuntimeError(
f"{table_path}: normalized Mach name collision for {public_name!r}"
)
args = resolve_mach_trap_signature(
routine=routine,
userspace_protos=userspace_protos,
kernel_argmap=kernel_argmap,
table_path=table_path,
)
if len(args) > MAX_ARGS:
raise RuntimeError(
f"{table_path}: trap {routine!r} has {len(args)} args; max supported is {MAX_ARGS}"
)
numbers[nr] = public_name
sigs[public_name] = SyscallSignature(name=public_name, args=tuple(args))
return numbers, sigs
def parse_mach_trap_table(text: str, path: Path) -> List[Tuple[int, str]]:
anchor = text.find("mach_trap_table")
if anchor == -1:
raise RuntimeError(f"{path}: mach_trap_table not found")
brace = text.find("{", anchor)
if brace == -1:
raise RuntimeError(f"{path}: mach_trap_table '{{' not found")
payload, _ = extract_brace_payload(text, brace, path)
by_index: Dict[int, str] = {}
off = 0
while True:
m = MACH_TRAP_INDEXED_CALL_RE.search(payload, off)
if m is None:
break
idx = int(m.group("idx"), 10)
open_paren = m.end(0) - 1
args_blob, end_off = extract_parentheses_payload(payload, open_paren, path)
parts = [
a.strip() for a in split_top_level_commas(args_blob) if a.strip() != ""
]
if len(parts) < 1:
raise RuntimeError(f"{path}: bad MACH_TRAP() entry: {args_blob!r}")
routine = parts[0]
prev = by_index.get(idx)
if prev is None:
by_index[idx] = routine
else:
if prev == routine:
pass
elif prev == "kern_invalid" and routine != "kern_invalid":
by_index[idx] = routine
elif routine == "kern_invalid" and prev != "kern_invalid":
pass
else:
raise RuntimeError(
f"{path}: conflicting MACH_TRAP entries for index {idx}: {prev!r} vs {routine!r}"
)
off = end_off
return sorted(by_index.items(), key=lambda kv: kv[0])
def split_mach_traps_header(text: str, path: Path) -> Tuple[str, str]:
m_start = MACH_TRAPS_IFNDEF_KERNEL_RE.search(text)
if m_start is None:
raise RuntimeError(f"{path}: missing '#ifndef KERNEL'")
m_else = MACH_TRAPS_ELSE_KERNEL_RE.search(text, m_start.end())
if m_else is None:
raise RuntimeError(f"{path}: missing '#else ... KERNEL ...'")
userspace = text[m_start.end():m_else.start()]
kernel = text[m_else.end():]
return userspace, kernel
def parse_userspace_mach_traps_prototypes(
userspace_text: str, path: Path
) -> Dict[str, Tuple[SyscallArg, ...]]:
protos: Dict[str, Tuple[SyscallArg, ...]] = {}
for m in USER_EXTERN_PROTO_RE.finditer(userspace_text):
fn = m.group("fn").strip()
args_blob = m.group("args").strip()
ret_blob = strip_c_comments(m.group("ret")).strip()
if ret_blob == "":
raise RuntimeError(f"{path}: empty return type for {fn!r}")
line_no = line_number_at_offset(userspace_text, m.start())
args = parse_c_param_list(args_blob, path, line_no)
cur = tuple(args)
prev = protos.get(fn)
if prev is not None and prev != cur:
raise RuntimeError(f"{path}:{line_no}: conflicting prototype for {fn!r}")
protos[fn] = cur
return protos
def parse_kernel_mach_traps_args(
kernel_text: str, path: Path
) -> Dict[str, Tuple[SyscallArg, ...]]:
text = strip_c_comments(kernel_text)
structs: Dict[str, str] = {}
for m in KERNEL_STRUCT_RE.finditer(text):
name = m.group("name").strip()
body = m.group("body")
structs[name] = body
fn_to_struct: Dict[str, str] = {}
for m in KERNEL_TRAP_EXTERN_RE.finditer(text):
fn = m.group("fn").strip()
args_struct = m.group("args_struct").strip()
fn_to_struct[fn] = args_struct
out: Dict[str, Tuple[SyscallArg, ...]] = {}
for fn, args_struct in fn_to_struct.items():
body = structs.get(args_struct)
if body is None:
continue
args = parse_mach_args_struct_body(body, path)
out[fn] = tuple(args)
return out
def parse_mach_args_struct_body(body: str, path: Path) -> List[SyscallArg]:
args: List[SyscallArg] = []
body = strip_c_comments(body)
for raw_ln in body.splitlines():
ln = raw_ln.strip()
if ln == "" or ln.startswith("#"):
continue
if "PAD_ARG_8" in ln:
continue
m = PAD_ARG_RE.search(ln)
if m is not None:
ty = normalize_whitespace(m.group("ty").strip())
name = normalize_whitespace(m.group("name").strip())
if ty == "" or name == "":
raise RuntimeError(f"{path}: bad PAD_ARG_ in args struct: {raw_ln!r}")
args.append(SyscallArg(type=ty, name=name))
continue
m = PLAIN_FIELD_RE.match(ln)
if m is not None:
ty = normalize_whitespace(m.group("ty").strip())
name = m.group("name").strip()
if ty == "" or name == "":
raise RuntimeError(f"{path}: bad field in args struct: {raw_ln!r}")
args.append(SyscallArg(type=ty, name=name))
continue
if len(args) == 1 and args[0].name == "dummy":
return []
return args
def resolve_mach_trap_signature(
*,
routine: str,
userspace_protos: Dict[str, Tuple[SyscallArg, ...]],
kernel_argmap: Dict[str, Tuple[SyscallArg, ...]],
table_path: Path,
) -> List[SyscallArg]:
def get_userspace(name: str) -> Optional[Tuple[SyscallArg, ...]]:
return userspace_protos.get(name)
def get_kernel(name: str) -> Optional[Tuple[SyscallArg, ...]]:
return kernel_argmap.get(name)
proto_args = get_userspace(routine)
if proto_args is None and routine.endswith("_trap"):
proto_args = get_userspace(routine[: -len("_trap")])
if proto_args is not None:
return list(proto_args)
proto_args = get_kernel(routine)
if proto_args is None and routine.endswith("_trap"):
proto_args = get_kernel(routine[: -len("_trap")])
if proto_args is None:
raise RuntimeError(
f"{table_path}: missing userspace prototype for {routine!r}, and no kernel extern(struct *_args *args) mapping found"
)
return list(proto_args)
def normalize_mach_name(routine: str) -> str:
if routine.startswith("_"):
routine = routine[1:]
if routine.startswith("kernelrpc_"):
routine = routine[len("kernelrpc_"):]
if routine.endswith("_trap"):
routine = routine[: -len("_trap")]
return routine
def load_bsd_syscalls_master(
kernel_tree: Path,
) -> Tuple[Dict[int, str], Dict[str, SyscallSignature]]:
path = kernel_tree / "bsd" / "kern" / "syscalls.master"
if not path.exists():
raise RuntimeError(f"Missing BSD master file: {path}")
numbers: Dict[int, str] = {}
sigs: Dict[str, SyscallSignature] = {}
lines = path.read_text(encoding="utf-8", errors="ignore").splitlines()
stack: List[bool] = []
active = True
for line_no, raw in enumerate(lines, start=1):
line = raw.rstrip("\n")
stripped = line.lstrip()
if (
stripped.startswith("#if ")
or stripped.startswith("#ifdef ")
or stripped.startswith("#ifndef ")
):
stack.append(active)
continue
if stripped.startswith("#else"):
if not stack:
raise RuntimeError(f"{path}:{line_no}: #else without #if")
active = False
continue
if stripped.startswith("#endif"):
if not stack:
raise RuntimeError(f"{path}:{line_no}: #endif without #if")
active = stack.pop()
continue
if not active:
continue
m = BSD_MASTER_ENTRY_RE.match(line)
if m is None:
continue
nr = int(m.group("nr"), 10)
proto_blob = strip_c_comments(m.group("proto")).strip()
mp = BSD_MASTER_PROTO_RE.match(proto_blob)
if mp is None:
raise RuntimeError(
f"{path}:{line_no}: cannot parse prototype: {proto_blob!r}"
)
fn = mp.group("fn").strip()
args_blob = mp.group("args").strip()
if fn in {"nosys", "enosys"}:
continue
public_name = normalize_bsd_name(fn)
if public_name == "":
raise RuntimeError(f"{path}:{line_no}: empty normalized name from {fn!r}")
if nr in numbers:
raise RuntimeError(f"{path}:{line_no}: duplicate syscall number {nr}")
if public_name in sigs:
raise RuntimeError(
f"{path}:{line_no}: duplicate syscall name {public_name!r}"
)
args = parse_c_param_list(args_blob, path, line_no)
if len(args) > MAX_ARGS:
raise RuntimeError(
f"{path}:{line_no}: syscall {public_name!r} has {len(args)} args; max supported is {MAX_ARGS}"
)
numbers[nr] = public_name
sigs[public_name] = SyscallSignature(name=public_name, args=tuple(args))
return numbers, sigs
def normalize_bsd_name(fn: str) -> str:
if fn.startswith("sys_"):
return fn[len("sys_"):]
if fn.startswith("__"):
return fn[2:]
return fn
def strip_c_comments(s: str) -> str:
s = LINE_COMMENT_RE.sub("", s)
while True:
new_s = BLOCK_COMMENT_RE.sub("", s)
if new_s == s:
break
s = new_s
return s
def split_top_level_commas(text: str) -> List[str]:
parts: List[str] = []
buf: List[str] = []
depth = 0
in_string = False
string_quote = ""
cursor = 0
while cursor < len(text):
ch = text[cursor]
if in_string:
buf.append(ch)
if ch == "\\" and cursor + 1 < len(text):
buf.append(text[cursor + 1])
cursor += 2
continue
if ch == string_quote:
in_string = False
cursor += 1
continue
if ch in ("'", '"'):
in_string = True
string_quote = ch
buf.append(ch)
cursor += 1
continue
if ch == "(":
depth += 1
elif ch == ")":
depth = max(0, depth - 1)
if ch == "," and depth == 0:
parts.append("".join(buf).strip())
buf = []
cursor += 1
continue
buf.append(ch)
cursor += 1
parts.append("".join(buf).strip())
return parts
def parse_c_param_list(args_blob: str, path: Path, line_no: int) -> List[SyscallArg]:
raw = strip_c_comments(args_blob).strip()
if raw == "" or raw == "void":
return []
raw_params = [p.strip() for p in split_top_level_commas(raw) if p.strip() != ""]
if len(raw_params) == 1 and raw_params[0] == "void":
return []
args: List[SyscallArg] = []
for idx, p in enumerate(raw_params):
ty, name = split_param_decl(p, path, line_no)
if name is None:
name = f"arg{idx}"
if ty == "user_addr_t" and name in {"attrname", "link", "path"}:
ty = "char *"
args.append(SyscallArg(type=ty, name=name))
return args
def split_param_decl(decl: str, path: Path, line_no: int) -> Tuple[str, Optional[str]]:
d = strip_c_comments(decl).strip()
if d == "" or d == "void":
raise RuntimeError(f"{path}:{line_no}: bad parameter decl: {decl!r}")
tokens = _tokenize_decl(d)
ty_tokens, name = _split_type_and_name(tokens)
ty = _format_type(ty_tokens)
if not ty:
raise RuntimeError(
f"{path}:{line_no}: cannot parse parameter type from {decl!r}"
)
return ty, _camel_to_snake(name) if name else None
def _tokenize_decl(s: str) -> list[str]:
out = []
for c in s:
out.append(" * " if c == "*" else c)
return "".join(out).split()
def _split_type_and_name(tokens: list[str]) -> Tuple[list[str], Optional[str]]:
if not tokens:
return [], None
last = tokens[-1]
if last == "*":
return tokens, None
stars, remainder = _split_leading_stars(last)
if stars:
if _is_identifier(remainder):
return tokens[:-1] + ["*"] * stars, remainder
return tokens, None
if _is_identifier(last):
return tokens[:-1], last
return tokens, None
def _format_type(tokens: list[str]) -> str:
formatted: list[str] = []
i = 0
while i < len(tokens):
if tokens[i] != "*":
formatted.append(tokens[i])
i += 1
continue
j = i
while j < len(tokens) and tokens[j] == "*":
j += 1
formatted.append("*" * (j - i))
i = j
return " ".join(formatted).strip()
def _split_leading_stars(token: str) -> Tuple[int, str]:
i = 0
while i < len(token) and token[i] == "*":
i += 1
return i, token[i:]
def _is_identifier(s: str) -> bool:
if not s:
return False
if not (s[0].isalpha() or s[0] == "_"):
return False
return all(c.isalnum() or c == "_" for c in s)
def _camel_to_snake(name: str) -> str:
out = []
for i, c in enumerate(name):
if (
c.isupper()
and i > 0
and (name[i - 1].islower() or (i + 1 < len(name) and name[i + 1].islower()))
):
out.append("_")
out.append(c.lower())
return "".join(out)
def normalize_whitespace(s: str) -> str:
return " ".join(s.split())
def line_number_at_offset(text: str, offset: int) -> int:
return text.count("\n", 0, offset) + 1
def extract_parentheses_payload(
text: str, open_paren_offset: int, path: Path
) -> Tuple[str, int]:
if (
open_paren_offset < 0
or open_paren_offset >= len(text)
or text[open_paren_offset] != "("
):
raise RuntimeError(f"{path}: expected '(' at offset {open_paren_offset}")
depth = 0
cursor = open_paren_offset
start = open_paren_offset + 1
in_string = False
string_quote = ""
while cursor < len(text):
ch = text[cursor]
if in_string:
if ch == "\\":
cursor += 2
continue
if ch == string_quote:
in_string = False
cursor += 1
continue
if ch in ("'", '"'):
in_string = True
string_quote = ch
cursor += 1
continue
if ch == "(":
depth += 1
elif ch == ")":
depth -= 1
if depth == 0:
return text[start:cursor], cursor + 1
cursor += 1
raise RuntimeError(f"{path}: unterminated parentheses payload")
def extract_brace_payload(
text: str, open_brace_offset: int, path: Path
) -> Tuple[str, int]:
if (
open_brace_offset < 0
or open_brace_offset >= len(text)
or text[open_brace_offset] != "{"
):
raise RuntimeError(f"{path}: expected '{{' at offset {open_brace_offset}")
depth = 0
cursor = open_brace_offset
start = open_brace_offset + 1
in_string = False
string_quote = ""
while cursor < len(text):
ch = text[cursor]
if in_string:
if ch == "\\":
cursor += 2
continue
if ch == string_quote:
in_string = False
cursor += 1
continue
if ch in ("'", '"'):
in_string = True
string_quote = ch
cursor += 1
continue
if ch == "{":
depth += 1
elif ch == "}":
depth -= 1
if depth == 0:
return text[start:cursor], cursor + 1
cursor += 1
raise RuntimeError(f"{path}: unterminated brace payload")
def render_vala(*, mach_numbers: Dict[int, str], bsd_numbers: Dict[int, str]) -> str:
out: List[str] = []
out += [
"// AUTO-GENERATED FILE. DO NOT EDIT.\n",
"\n",
"namespace Frida {\n",
"\tpublic extern unowned XnuSyscallSignature[] get_xnu_mach_traps ();\n",
"\tpublic extern unowned XnuSyscallSignature[] get_xnu_bsd_syscalls ();\n",
"\n",
"\tpublic struct XnuSyscallSignature {\n",
"\t\tpublic int nr;\n",
"\t\tpublic string name;\n",
"\t\tpublic uint8 nargs;\n",
f"\t\tpublic XnuSyscallArg args[{MAX_ARGS}];\n",
"\t}\n",
"\n",
"\tpublic struct XnuSyscallArg {\n",
"\t\tpublic string? type;\n",
"\t\tpublic string? name;\n",
"\t}\n",
"\n",
"\tpublic enum XnuMachTrap {\n",
]
for nr, name in sorted(mach_numbers.items(), key=lambda kv: kv[0], reverse=True):
out += [f"\t\t{name.upper()} = {nr},\n"]
out += [
"\t}\n",
"\n",
"\tpublic enum XnuBsdSyscall {\n",
]
for nr, name in sorted(bsd_numbers.items(), key=lambda kv: kv[0]):
out += [f"\t\t{name.upper()} = {nr},\n"]
out += [
"\t}\n",
"}\n",
]
return "".join(out)
def render_c_source(
*,
mach_numbers: Dict[int, str],
bsd_numbers: Dict[int, str],
mach_sigs: Dict[str, SyscallSignature],
bsd_sigs: Dict[str, SyscallSignature],
) -> str:
out: List[str] = []
out += [
"/* AUTO-GENERATED FILE. DO NOT EDIT. */\n",
"\n",
'#include "frida-base.h"\n',
"\n",
]
emit_c_signature_table(
out,
c_var="frida_xnu_mach_traps",
numbers=mach_numbers,
sigs=mach_sigs,
reverse=True,
)
emit_c_signature_table(
out,
c_var="frida_xnu_bsd_syscalls",
numbers=bsd_numbers,
sigs=bsd_sigs,
)
emit_c_table_getter(
out, c_func="frida_get_xnu_mach_traps", c_var="frida_xnu_mach_traps"
)
out += ["\n"]
emit_c_table_getter(
out, c_func="frida_get_xnu_bsd_syscalls", c_var="frida_xnu_bsd_syscalls"
)
return "".join(out)
def emit_c_signature_table(
out: List[str],
*,
c_var: str,
numbers: Dict[int, str],
sigs: Dict[str, SyscallSignature],
reverse: bool = False,
) -> None:
out += [
f"static const FridaXnuSyscallSignature {c_var}[] =\n",
"{\n",
]
for nr, name in sorted(numbers.items(), key=lambda kv: kv[0], reverse=reverse):
sig = sigs[name]
args_parts: List[str] = []
for a in sig.args:
args_parts += [f"{{ {c_escape(a.type)}, {c_escape(a.name)} }}"]
args_blob = ", ".join(args_parts)
if args_blob != "":
out += [
f" {{ {nr}, {c_escape(name)}, {len(sig.args)}, {{ {args_blob} }} }},\n"
]
else:
out += [f" {{ {nr}, {c_escape(name)}, 0, {{}} }},\n"]
out += [
"};\n",
"\n",
]
def emit_c_table_getter(out: List[str], *, c_func: str, c_var: str) -> None:
out += [
"FridaXnuSyscallSignature *\n",
f"{c_func} (int * len)\n",
"{\n",
" if (len != NULL)\n",
f" *len = G_N_ELEMENTS ({c_var});\n",
f" return (FridaXnuSyscallSignature *) {c_var};\n",
"}\n",
]
def c_escape(s: str) -> str:
return '"' + s.replace("\\", "\\\\").replace('"', '\\"') + '"'
if __name__ == "__main__":
raise SystemExit(main())
-542
View File
@@ -1,542 +0,0 @@
/* AUTO-GENERATED FILE. DO NOT EDIT. */
#include "frida-base.h"
static const FridaXnuSyscallSignature frida_xnu_mach_traps[] =
{
{ -10, "mach_vm_allocate", 4, { { "mach_port_name_t", "target" }, { "mach_vm_offset_t *", "addr" }, { "mach_vm_size_t", "size" }, { "int", "flags" } } },
{ -11, "mach_vm_purgable_control", 4, { { "mach_port_name_t", "target" }, { "mach_vm_offset_t", "address" }, { "vm_purgable_t", "control" }, { "int *", "state" } } },
{ -12, "mach_vm_deallocate", 3, { { "mach_port_name_t", "target" }, { "mach_vm_address_t", "address" }, { "mach_vm_size_t", "size" } } },
{ -13, "task_dyld_process_info_notify_get", 2, { { "mach_port_name_array_t", "names_addr" }, { "natural_t *", "names_count_addr" } } },
{ -14, "mach_vm_protect", 5, { { "mach_port_name_t", "target" }, { "mach_vm_address_t", "address" }, { "mach_vm_size_t", "size" }, { "boolean_t", "set_maximum" }, { "vm_prot_t", "new_protection" } } },
{ -15, "mach_vm_map", 6, { { "mach_port_name_t", "target" }, { "mach_vm_offset_t *", "address" }, { "mach_vm_size_t", "size" }, { "mach_vm_offset_t", "mask" }, { "int", "flags" }, { "vm_prot_t", "cur_protection" } } },
{ -16, "mach_port_allocate", 3, { { "mach_port_name_t", "target" }, { "mach_port_right_t", "right" }, { "mach_port_name_t *", "name" } } },
{ -18, "mach_port_deallocate", 2, { { "mach_port_name_t", "target" }, { "mach_port_name_t", "name" } } },
{ -19, "mach_port_mod_refs", 4, { { "mach_port_name_t", "target" }, { "mach_port_name_t", "name" }, { "mach_port_right_t", "right" }, { "mach_port_delta_t", "delta" } } },
{ -20, "mach_port_move_member", 3, { { "mach_port_name_t", "target" }, { "mach_port_name_t", "member" }, { "mach_port_name_t", "after" } } },
{ -21, "mach_port_insert_right", 4, { { "mach_port_name_t", "target" }, { "mach_port_name_t", "name" }, { "mach_port_name_t", "poly" }, { "mach_msg_type_name_t", "poly_poly" } } },
{ -22, "mach_port_insert_member", 3, { { "mach_port_name_t", "target" }, { "mach_port_name_t", "name" }, { "mach_port_name_t", "pset" } } },
{ -23, "mach_port_extract_member", 3, { { "mach_port_name_t", "target" }, { "mach_port_name_t", "name" }, { "mach_port_name_t", "pset" } } },
{ -24, "mach_port_construct", 4, { { "mach_port_name_t", "target" }, { "mach_port_options_t *", "options" }, { "uint64_t", "context" }, { "mach_port_name_t *", "name" } } },
{ -25, "mach_port_destruct", 4, { { "mach_port_name_t", "target" }, { "mach_port_name_t", "name" }, { "mach_port_delta_t", "srdelta" }, { "uint64_t", "guard" } } },
{ -26, "mach_reply_port", 0, {} },
{ -27, "thread_self", 0, {} },
{ -28, "task_self", 0, {} },
{ -29, "host_self", 0, {} },
{ -31, "mach_msg", 7, { { "mach_msg_header_t *", "msg" }, { "mach_msg_option_t", "option" }, { "mach_msg_size_t", "send_size" }, { "mach_msg_size_t", "rcv_size" }, { "mach_port_name_t", "rcv_name" }, { "mach_msg_timeout_t", "timeout" }, { "mach_port_name_t", "notify" } } },
{ -32, "mach_msg_overwrite", 9, { { "mach_msg_header_t *", "msg" }, { "mach_msg_option_t", "option" }, { "mach_msg_size_t", "send_size" }, { "mach_msg_size_t", "rcv_size" }, { "mach_port_name_t", "rcv_name" }, { "mach_msg_timeout_t", "timeout" }, { "mach_msg_priority_t", "priority" }, { "mach_msg_header_t *", "rcv_msg" }, { "mach_msg_size_t", "rcv_limit" } } },
{ -33, "semaphore_signal", 1, { { "mach_port_name_t", "signal_name" } } },
{ -34, "semaphore_signal_all", 1, { { "mach_port_name_t", "signal_name" } } },
{ -35, "semaphore_signal_thread", 2, { { "mach_port_name_t", "signal_name" }, { "mach_port_name_t", "thread_name" } } },
{ -36, "semaphore_wait", 1, { { "mach_port_name_t", "wait_name" } } },
{ -37, "semaphore_wait_signal", 2, { { "mach_port_name_t", "wait_name" }, { "mach_port_name_t", "signal_name" } } },
{ -38, "semaphore_timedwait", 3, { { "mach_port_name_t", "wait_name" }, { "unsigned int", "sec" }, { "clock_res_t", "nsec" } } },
{ -39, "semaphore_timedwait_signal", 4, { { "mach_port_name_t", "wait_name" }, { "mach_port_name_t", "signal_name" }, { "unsigned int", "sec" }, { "clock_res_t", "nsec" } } },
{ -40, "mach_port_get_attributes", 5, { { "mach_port_name_t", "target" }, { "mach_port_name_t", "name" }, { "mach_port_flavor_t", "flavor" }, { "mach_port_info_t", "port_info_out" }, { "mach_msg_type_number_t *", "port_info_out_cnt" } } },
{ -41, "mach_port_guard", 4, { { "mach_port_name_t", "target" }, { "mach_port_name_t", "name" }, { "uint64_t", "guard" }, { "boolean_t", "strict" } } },
{ -42, "mach_port_unguard", 3, { { "mach_port_name_t", "target" }, { "mach_port_name_t", "name" }, { "uint64_t", "guard" } } },
{ -43, "mach_generate_activity_id", 3, { { "mach_port_name_t", "target" }, { "int", "count" }, { "uint64_t *", "activity_id" } } },
{ -44, "task_name_for_pid", 3, { { "mach_port_name_t", "target_tport" }, { "int", "pid" }, { "mach_port_name_t *", "tn" } } },
{ -45, "task_for_pid", 3, { { "mach_port_name_t", "target_tport" }, { "int", "pid" }, { "mach_port_name_t *", "t" } } },
{ -46, "pid_for_task", 2, { { "mach_port_name_t", "t" }, { "int *", "x" } } },
{ -47, "mach_msg2", 8, { { "void *", "data" }, { "mach_msg_option64_t", "options" }, { "uint64_t", "msgh_bits_and_send_size" }, { "uint64_t", "msgh_remote_and_local_port" }, { "uint64_t", "msgh_voucher_and_id" }, { "uint64_t", "desc_count_and_rcv_name" }, { "uint64_t", "rcv_size_and_priority" }, { "uint64_t", "timeout" } } },
{ -48, "macx_swapon", 4, { { "uint64_t", "filename" }, { "int", "flags" }, { "int", "size" }, { "int", "priority" } } },
{ -49, "macx_swapoff", 2, { { "uint64_t", "filename" }, { "int", "flags" } } },
{ -50, "thread_get_special_reply_port", 0, {} },
{ -51, "macx_triggers", 4, { { "int", "hi_water" }, { "int", "low_water" }, { "int", "flags" }, { "mach_port_t", "alert_port" } } },
{ -52, "macx_backing_store_suspend", 1, { { "boolean_t", "suspend" } } },
{ -53, "macx_backing_store_recovery", 1, { { "int", "pid" } } },
{ -58, "pfz_exit", 0, {} },
{ -59, "swtch_pri", 1, { { "int", "pri" } } },
{ -60, "swtch", 0, {} },
{ -61, "thread_switch", 3, { { "mach_port_name_t", "thread_name" }, { "int", "option" }, { "mach_msg_timeout_t", "option_time" } } },
{ -62, "clock_sleep", 5, { { "mach_port_name_t", "clock_name" }, { "sleep_type_t", "sleep_type" }, { "int", "sleep_sec" }, { "int", "sleep_nsec" }, { "mach_timespec_t *", "wakeup_time" } } },
{ -63, "mach_vm_reclaim_update_kernel_accounting", 2, { { "mach_port_name_t", "target_tport" }, { "uint64_t *", "bytes_reclaimed" } } },
{ -70, "host_create_mach_voucher", 4, { { "mach_port_name_t", "host" }, { "mach_voucher_attr_raw_recipe_array_t", "recipes" }, { "int", "recipes_size" }, { "mach_port_name_t *", "voucher" } } },
{ -72, "mach_voucher_extract_attr_recipe", 4, { { "mach_port_name_t", "voucher_name" }, { "mach_voucher_attr_key_t", "key" }, { "mach_voucher_attr_raw_recipe_t", "recipe" }, { "mach_msg_type_number_t *", "recipe_size" } } },
{ -76, "mach_port_type", 3, { { "ipc_space_t", "task" }, { "mach_port_name_t", "name" }, { "mach_port_type_t *", "ptype" } } },
{ -77, "mach_port_request_notification", 7, { { "ipc_space_t", "task" }, { "mach_port_name_t", "name" }, { "mach_msg_id_t", "msgid" }, { "mach_port_mscount_t", "sync" }, { "mach_port_name_t", "notify" }, { "mach_msg_type_name_t", "notify_poly" }, { "mach_port_name_t *", "previous" } } },
{ -88, "exclaves_ctl", 8, { { "mach_port_name_t", "name" }, { "uint32_t", "operation_and_flags" }, { "uint64_t", "identifier" }, { "mach_vm_address_t", "buffer" }, { "mach_vm_size_t", "size" }, { "mach_vm_size_t", "size2" }, { "mach_vm_size_t", "offset" }, { "mach_vm_address_t", "status" } } },
{ -89, "mach_timebase_info", 1, { { "user_addr_t", "info" } } },
{ -90, "mach_wait_until", 1, { { "uint64_t", "deadline" } } },
{ -91, "mk_timer_create", 0, {} },
{ -92, "mk_timer_destroy", 1, { { "mach_port_name_t", "name" } } },
{ -93, "mk_timer_arm", 2, { { "mach_port_name_t", "name" }, { "uint64_t", "expire_time" } } },
{ -94, "mk_timer_cancel", 2, { { "mach_port_name_t", "name" }, { "user_addr_t", "result_time" } } },
{ -95, "mk_timer_arm_leeway", 4, { { "mach_port_name_t", "name" }, { "uint64_t", "mk_timer_flags" }, { "uint64_t", "expire_time" }, { "uint64_t", "mk_leeway" } } },
{ -96, "debug_control_port_for_pid", 3, { { "mach_port_name_t", "target_tport" }, { "int", "pid" }, { "mach_port_name_t *", "t" } } },
{ -100, "iokit_user_client", 8, { { "void *", "userClientRef" }, { "uint32_t", "index" }, { "void *", "p1" }, { "void *", "p2" }, { "void *", "p3" }, { "void *", "p4" }, { "void *", "p5" }, { "void *", "p6" } } },
};
static const FridaXnuSyscallSignature frida_xnu_bsd_syscalls[] =
{
{ 1, "exit", 1, { { "int", "rval" } } },
{ 2, "fork", 0, {} },
{ 3, "read", 3, { { "int", "fd" }, { "user_addr_t", "cbuf" }, { "user_size_t", "nbyte" } } },
{ 4, "write", 3, { { "int", "fd" }, { "user_addr_t", "cbuf" }, { "user_size_t", "nbyte" } } },
{ 5, "open", 3, { { "char *", "path" }, { "int", "flags" }, { "int", "mode" } } },
{ 6, "close", 1, { { "int", "fd" } } },
{ 7, "wait4", 4, { { "int", "pid" }, { "user_addr_t", "status" }, { "int", "options" }, { "user_addr_t", "rusage" } } },
{ 9, "link", 2, { { "char *", "path" }, { "char *", "link" } } },
{ 10, "unlink", 1, { { "char *", "path" } } },
{ 12, "chdir", 1, { { "char *", "path" } } },
{ 13, "fchdir", 1, { { "int", "fd" } } },
{ 14, "mknod", 3, { { "char *", "path" }, { "int", "mode" }, { "int", "dev" } } },
{ 15, "chmod", 2, { { "char *", "path" }, { "int", "mode" } } },
{ 16, "chown", 3, { { "char *", "path" }, { "int", "uid" }, { "int", "gid" } } },
{ 18, "getfsstat", 3, { { "user_addr_t", "buf" }, { "int", "bufsize" }, { "int", "flags" } } },
{ 20, "getpid", 0, {} },
{ 23, "setuid", 1, { { "uid_t", "uid" } } },
{ 24, "getuid", 0, {} },
{ 25, "geteuid", 0, {} },
{ 26, "ptrace", 4, { { "int", "req" }, { "pid_t", "pid" }, { "caddr_t", "addr" }, { "int", "data" } } },
{ 27, "recvmsg", 3, { { "int", "s" }, { "struct msghdr *", "msg" }, { "int", "flags" } } },
{ 28, "sendmsg", 3, { { "int", "s" }, { "caddr_t", "msg" }, { "int", "flags" } } },
{ 29, "recvfrom", 6, { { "int", "s" }, { "void *", "buf" }, { "size_t", "len" }, { "int", "flags" }, { "struct sockaddr *", "from" }, { "int *", "fromlenaddr" } } },
{ 30, "accept", 3, { { "int", "s" }, { "caddr_t", "name" }, { "socklen_t *", "anamelen" } } },
{ 31, "getpeername", 3, { { "int", "fdes" }, { "caddr_t", "asa" }, { "socklen_t *", "alen" } } },
{ 32, "getsockname", 3, { { "int", "fdes" }, { "caddr_t", "asa" }, { "socklen_t *", "alen" } } },
{ 33, "access", 2, { { "char *", "path" }, { "int", "flags" } } },
{ 34, "chflags", 2, { { "char *", "path" }, { "int", "flags" } } },
{ 35, "fchflags", 2, { { "int", "fd" }, { "int", "flags" } } },
{ 36, "sync", 0, {} },
{ 37, "kill", 3, { { "int", "pid" }, { "int", "signum" }, { "int", "posix" } } },
{ 38, "crossarch_trap", 1, { { "uint32_t", "name" } } },
{ 39, "getppid", 0, {} },
{ 41, "dup", 1, { { "u_int", "fd" } } },
{ 42, "pipe", 0, {} },
{ 43, "getegid", 0, {} },
{ 46, "sigaction", 3, { { "int", "signum" }, { "struct __sigaction *", "nsa" }, { "struct sigaction *", "osa" } } },
{ 47, "getgid", 0, {} },
{ 48, "sigprocmask", 3, { { "int", "how" }, { "user_addr_t", "mask" }, { "user_addr_t", "omask" } } },
{ 49, "getlogin", 2, { { "char *", "namebuf" }, { "u_int", "namelen" } } },
{ 50, "setlogin", 1, { { "char *", "namebuf" } } },
{ 51, "acct", 1, { { "char *", "path" } } },
{ 52, "sigpending", 1, { { "struct sigvec *", "osv" } } },
{ 53, "sigaltstack", 2, { { "struct sigaltstack *", "nss" }, { "struct sigaltstack *", "oss" } } },
{ 54, "ioctl", 3, { { "int", "fd" }, { "u_long", "com" }, { "caddr_t", "data" } } },
{ 55, "reboot", 2, { { "int", "opt" }, { "char *", "msg" } } },
{ 56, "revoke", 1, { { "char *", "path" } } },
{ 57, "symlink", 2, { { "char *", "path" }, { "char *", "link" } } },
{ 58, "readlink", 3, { { "char *", "path" }, { "char *", "buf" }, { "int", "count" } } },
{ 59, "execve", 3, { { "char *", "fname" }, { "char **", "argp" }, { "char **", "envp" } } },
{ 60, "umask", 1, { { "int", "newmask" } } },
{ 61, "chroot", 1, { { "char *", "path" } } },
{ 65, "msync", 3, { { "caddr_ut", "addr" }, { "size_ut", "len" }, { "int", "flags" } } },
{ 66, "vfork", 0, {} },
{ 67, "oslog_coproc_reg", 3, { { "const char *", "uuid" }, { "const char *", "file_path" }, { "size_t", "file_path_len" } } },
{ 68, "oslog_coproc", 7, { { "void *", "buff" }, { "uint64_t", "buff_len" }, { "uint32_t", "type" }, { "const char *", "uuid" }, { "uint64_t", "timestamp" }, { "uint32_t", "offset" }, { "uint32_t", "stream_log" } } },
{ 73, "munmap", 2, { { "caddr_ut", "addr" }, { "size_ut", "len" } } },
{ 74, "mprotect", 3, { { "caddr_ut", "addr" }, { "size_ut", "len" }, { "int", "prot" } } },
{ 75, "madvise", 3, { { "caddr_ut", "addr" }, { "size_ut", "len" }, { "int", "behav" } } },
{ 78, "mincore", 3, { { "caddr_ut", "addr" }, { "size_ut", "len" }, { "user_addr_t", "vec" } } },
{ 79, "getgroups", 2, { { "u_int", "gidsetsize" }, { "gid_t *", "gidset" } } },
{ 80, "setgroups", 2, { { "u_int", "gidsetsize" }, { "gid_t *", "gidset" } } },
{ 81, "getpgrp", 0, {} },
{ 82, "setpgid", 2, { { "int", "pid" }, { "int", "pgid" } } },
{ 83, "setitimer", 3, { { "u_int", "which" }, { "struct itimerval *", "itv" }, { "struct itimerval *", "oitv" } } },
{ 85, "swapon", 0, {} },
{ 86, "getitimer", 2, { { "u_int", "which" }, { "struct itimerval *", "itv" } } },
{ 89, "getdtablesize", 0, {} },
{ 90, "dup2", 2, { { "u_int", "from" }, { "u_int", "to" } } },
{ 92, "fcntl", 3, { { "int", "fd" }, { "int", "cmd" }, { "long", "arg" } } },
{ 93, "select", 5, { { "int", "nd" }, { "u_int32_t *", "in" }, { "u_int32_t *", "ou" }, { "u_int32_t *", "ex" }, { "struct timeval *", "tv" } } },
{ 95, "fsync", 1, { { "int", "fd" } } },
{ 96, "setpriority", 3, { { "int", "which" }, { "id_t", "who" }, { "int", "prio" } } },
{ 97, "socket", 3, { { "int", "domain" }, { "int", "type" }, { "int", "protocol" } } },
{ 98, "connect", 3, { { "int", "s" }, { "caddr_t", "name" }, { "socklen_t", "namelen" } } },
{ 100, "getpriority", 2, { { "int", "which" }, { "id_t", "who" } } },
{ 104, "bind", 3, { { "int", "s" }, { "caddr_t", "name" }, { "socklen_t", "namelen" } } },
{ 105, "setsockopt", 5, { { "int", "s" }, { "int", "level" }, { "int", "name" }, { "caddr_t", "val" }, { "socklen_t", "valsize" } } },
{ 106, "listen", 2, { { "int", "s" }, { "int", "backlog" } } },
{ 111, "sigsuspend", 1, { { "sigset_t", "mask" } } },
{ 116, "gettimeofday", 3, { { "struct timeval *", "tp" }, { "struct timezone *", "tzp" }, { "uint64_t *", "mach_absolute_time" } } },
{ 117, "getrusage", 2, { { "int", "who" }, { "struct rusage *", "rusage" } } },
{ 118, "getsockopt", 5, { { "int", "s" }, { "int", "level" }, { "int", "name" }, { "caddr_t", "val" }, { "socklen_t *", "avalsize" } } },
{ 120, "readv", 3, { { "int", "fd" }, { "struct iovec *", "iovp" }, { "u_int", "iovcnt" } } },
{ 121, "writev", 3, { { "int", "fd" }, { "struct iovec *", "iovp" }, { "u_int", "iovcnt" } } },
{ 122, "settimeofday", 2, { { "struct timeval *", "tv" }, { "struct timezone *", "tzp" } } },
{ 123, "fchown", 3, { { "int", "fd" }, { "int", "uid" }, { "int", "gid" } } },
{ 124, "fchmod", 2, { { "int", "fd" }, { "int", "mode" } } },
{ 126, "setreuid", 2, { { "uid_t", "ruid" }, { "uid_t", "euid" } } },
{ 127, "setregid", 2, { { "gid_t", "rgid" }, { "gid_t", "egid" } } },
{ 128, "rename", 2, { { "char *", "from" }, { "char *", "to" } } },
{ 131, "flock", 2, { { "int", "fd" }, { "int", "how" } } },
{ 132, "mkfifo", 2, { { "char *", "path" }, { "int", "mode" } } },
{ 133, "sendto", 6, { { "int", "s" }, { "caddr_t", "buf" }, { "size_t", "len" }, { "int", "flags" }, { "caddr_t", "to" }, { "socklen_t", "tolen" } } },
{ 134, "shutdown", 2, { { "int", "s" }, { "int", "how" } } },
{ 135, "socketpair", 4, { { "int", "domain" }, { "int", "type" }, { "int", "protocol" }, { "int *", "rsv" } } },
{ 136, "mkdir", 2, { { "char *", "path" }, { "int", "mode" } } },
{ 137, "rmdir", 1, { { "char *", "path" } } },
{ 138, "utimes", 2, { { "char *", "path" }, { "struct timeval *", "tptr" } } },
{ 139, "futimes", 2, { { "int", "fd" }, { "struct timeval *", "tptr" } } },
{ 140, "adjtime", 2, { { "struct timeval *", "delta" }, { "struct timeval *", "olddelta" } } },
{ 142, "gethostuuid", 2, { { "unsigned char *", "uuid_buf" }, { "const struct timespec *", "timeoutp" } } },
{ 147, "setsid", 0, {} },
{ 151, "getpgid", 1, { { "pid_t", "pid" } } },
{ 152, "setprivexec", 1, { { "int", "flag" } } },
{ 153, "pread", 4, { { "int", "fd" }, { "user_addr_t", "buf" }, { "user_size_t", "nbyte" }, { "off_t", "offset" } } },
{ 154, "pwrite", 4, { { "int", "fd" }, { "user_addr_t", "buf" }, { "user_size_t", "nbyte" }, { "off_t", "offset" } } },
{ 155, "nfssvc", 2, { { "int", "flag" }, { "caddr_t", "argp" } } },
{ 157, "statfs", 2, { { "char *", "path" }, { "struct statfs *", "buf" } } },
{ 158, "fstatfs", 2, { { "int", "fd" }, { "struct statfs *", "buf" } } },
{ 159, "unmount", 2, { { "char *", "path" }, { "int", "flags" } } },
{ 161, "getfh", 2, { { "char *", "fname" }, { "fhandle_t *", "fhp" } } },
{ 164, "funmount", 2, { { "int", "fd" }, { "int", "flags" } } },
{ 165, "quotactl", 4, { { "const char *", "path" }, { "int", "cmd" }, { "int", "uid" }, { "caddr_t", "arg" } } },
{ 167, "mount", 4, { { "char *", "type" }, { "char *", "path" }, { "int", "flags" }, { "caddr_t", "data" } } },
{ 169, "csops", 4, { { "pid_t", "pid" }, { "uint32_t", "ops" }, { "user_addr_t", "useraddr" }, { "user_size_t", "usersize" } } },
{ 170, "csops_audittoken", 5, { { "pid_t", "pid" }, { "uint32_t", "ops" }, { "user_addr_t", "useraddr" }, { "user_size_t", "usersize" }, { "user_addr_t", "uaudittoken" } } },
{ 173, "waitid", 4, { { "idtype_t", "idtype" }, { "id_t", "id" }, { "siginfo_t *", "infop" }, { "int", "options" } } },
{ 177, "kdebug_typefilter", 2, { { "void **", "addr" }, { "size_t *", "size" } } },
{ 178, "kdebug_trace_string", 3, { { "uint32_t", "debugid" }, { "uint64_t", "str_id" }, { "const char *", "str" } } },
{ 179, "kdebug_trace64", 5, { { "uint32_t", "code" }, { "uint64_t", "arg1" }, { "uint64_t", "arg2" }, { "uint64_t", "arg3" }, { "uint64_t", "arg4" } } },
{ 180, "kdebug_trace", 5, { { "uint32_t", "code" }, { "u_long", "arg1" }, { "u_long", "arg2" }, { "u_long", "arg3" }, { "u_long", "arg4" } } },
{ 181, "setgid", 1, { { "gid_t", "gid" } } },
{ 182, "setegid", 1, { { "gid_t", "egid" } } },
{ 183, "seteuid", 1, { { "uid_t", "euid" } } },
{ 184, "sigreturn", 3, { { "struct ucontext *", "uctx" }, { "int", "infostyle" }, { "user_addr_t", "token" } } },
{ 185, "panic_with_data", 5, { { "uuid_t", "uuid" }, { "void *", "addr" }, { "uint32_t", "len" }, { "uint32_t", "flags" }, { "const char *", "msg" } } },
{ 186, "thread_selfcounts", 3, { { "uint32_t", "kind" }, { "user_addr_t", "buf" }, { "user_size_t", "size" } } },
{ 187, "fdatasync", 1, { { "int", "fd" } } },
{ 188, "stat", 2, { { "char *", "path" }, { "user_addr_t", "ub" } } },
{ 189, "fstat", 2, { { "int", "fd" }, { "user_addr_t", "ub" } } },
{ 190, "lstat", 2, { { "char *", "path" }, { "user_addr_t", "ub" } } },
{ 191, "pathconf", 2, { { "char *", "path" }, { "int", "name" } } },
{ 192, "fpathconf", 2, { { "int", "fd" }, { "int", "name" } } },
{ 194, "getrlimit", 2, { { "u_int", "which" }, { "struct rlimit *", "rlp" } } },
{ 195, "setrlimit", 2, { { "u_int", "which" }, { "struct rlimit *", "rlp" } } },
{ 196, "getdirentries", 4, { { "int", "fd" }, { "char *", "buf" }, { "u_int", "count" }, { "long *", "basep" } } },
{ 197, "mmap", 6, { { "caddr_ut", "addr" }, { "size_ut", "len" }, { "int", "prot" }, { "int", "flags" }, { "int", "fd" }, { "off_t", "pos" } } },
{ 199, "lseek", 3, { { "int", "fd" }, { "off_t", "offset" }, { "int", "whence" } } },
{ 200, "truncate", 2, { { "char *", "path" }, { "off_t", "length" } } },
{ 201, "ftruncate", 2, { { "int", "fd" }, { "off_t", "length" } } },
{ 202, "sysctl", 6, { { "int *", "name" }, { "u_int", "namelen" }, { "void *", "old" }, { "size_t *", "oldlenp" }, { "void *", "new" }, { "size_t", "newlen" } } },
{ 203, "mlock", 2, { { "caddr_ut", "addr" }, { "size_ut", "len" } } },
{ 204, "munlock", 2, { { "caddr_ut", "addr" }, { "size_ut", "len" } } },
{ 205, "undelete", 1, { { "char *", "path" } } },
{ 216, "open_dprotected_np", 5, { { "char *", "path" }, { "int", "flags" }, { "int", "class" }, { "int", "dpflags" }, { "int", "mode" } } },
{ 217, "fsgetpath_ext", 5, { { "user_addr_t", "buf" }, { "size_t", "bufsize" }, { "user_addr_t", "fsid" }, { "uint64_t", "objid" }, { "uint32_t", "options" } } },
{ 218, "openat_dprotected_np", 7, { { "int", "fd" }, { "char *", "path" }, { "int", "flags" }, { "int", "class" }, { "int", "dpflags" }, { "int", "mode" }, { "int", "authfd" } } },
{ 220, "getattrlist", 5, { { "const char *", "path" }, { "struct attrlist *", "alist" }, { "void *", "attribute_buffer" }, { "size_t", "buffer_size" }, { "u_long", "options" } } },
{ 221, "setattrlist", 5, { { "const char *", "path" }, { "struct attrlist *", "alist" }, { "void *", "attribute_buffer" }, { "size_t", "buffer_size" }, { "u_long", "options" } } },
{ 222, "getdirentriesattr", 8, { { "int", "fd" }, { "struct attrlist *", "alist" }, { "void *", "buffer" }, { "size_t", "buffersize" }, { "u_long *", "count" }, { "u_long *", "basep" }, { "u_long *", "newstate" }, { "u_long", "options" } } },
{ 223, "exchangedata", 3, { { "const char *", "path1" }, { "const char *", "path2" }, { "u_long", "options" } } },
{ 225, "searchfs", 6, { { "const char *", "path" }, { "struct fssearchblock *", "searchblock" }, { "uint32_t *", "nummatches" }, { "uint32_t", "scriptcode" }, { "uint32_t", "options" }, { "struct searchstate *", "state" } } },
{ 226, "delete", 1, { { "char *", "path" } } },
{ 227, "copyfile", 4, { { "char *", "from" }, { "char *", "to" }, { "int", "mode" }, { "int", "flags" } } },
{ 228, "fgetattrlist", 5, { { "int", "fd" }, { "struct attrlist *", "alist" }, { "void *", "attribute_buffer" }, { "size_t", "buffer_size" }, { "u_long", "options" } } },
{ 229, "fsetattrlist", 5, { { "int", "fd" }, { "struct attrlist *", "alist" }, { "void *", "attribute_buffer" }, { "size_t", "buffer_size" }, { "u_long", "options" } } },
{ 230, "poll", 3, { { "struct pollfd *", "fds" }, { "u_int", "nfds" }, { "int", "timeout" } } },
{ 234, "getxattr", 6, { { "char *", "path" }, { "char *", "attrname" }, { "user_addr_t", "value" }, { "size_t", "size" }, { "uint32_t", "position" }, { "int", "options" } } },
{ 235, "fgetxattr", 6, { { "int", "fd" }, { "char *", "attrname" }, { "user_addr_t", "value" }, { "size_t", "size" }, { "uint32_t", "position" }, { "int", "options" } } },
{ 236, "setxattr", 6, { { "char *", "path" }, { "char *", "attrname" }, { "user_addr_t", "value" }, { "size_t", "size" }, { "uint32_t", "position" }, { "int", "options" } } },
{ 237, "fsetxattr", 6, { { "int", "fd" }, { "char *", "attrname" }, { "user_addr_t", "value" }, { "size_t", "size" }, { "uint32_t", "position" }, { "int", "options" } } },
{ 238, "removexattr", 3, { { "char *", "path" }, { "char *", "attrname" }, { "int", "options" } } },
{ 239, "fremovexattr", 3, { { "int", "fd" }, { "char *", "attrname" }, { "int", "options" } } },
{ 240, "listxattr", 4, { { "char *", "path" }, { "user_addr_t", "namebuf" }, { "size_t", "bufsize" }, { "int", "options" } } },
{ 241, "flistxattr", 4, { { "int", "fd" }, { "user_addr_t", "namebuf" }, { "size_t", "bufsize" }, { "int", "options" } } },
{ 242, "fsctl", 4, { { "const char *", "path" }, { "u_long", "cmd" }, { "caddr_t", "data" }, { "u_int", "options" } } },
{ 243, "initgroups", 3, { { "u_int", "gidsetsize" }, { "gid_t *", "gidset" }, { "int", "gmuid" } } },
{ 244, "posix_spawn", 5, { { "pid_t *", "pid" }, { "const char *", "path" }, { "const struct _posix_spawn_args_desc *", "adesc" }, { "char **", "argv" }, { "char **", "envp" } } },
{ 245, "ffsctl", 4, { { "int", "fd" }, { "u_long", "cmd" }, { "caddr_t", "data" }, { "u_int", "options" } } },
{ 248, "fhopen", 2, { { "const struct fhandle *", "u_fhp" }, { "int", "flags" } } },
{ 250, "minherit", 3, { { "caddr_ut", "addr" }, { "size_ut", "len" }, { "int", "inherit" } } },
{ 251, "semsys", 5, { { "u_int", "which" }, { "int", "a2" }, { "int", "a3" }, { "int", "a4" }, { "int", "a5" } } },
{ 252, "msgsys", 5, { { "u_int", "which" }, { "int", "a2" }, { "int", "a3" }, { "int", "a4" }, { "int", "a5" } } },
{ 253, "shmsys", 4, { { "u_int", "which" }, { "int", "a2" }, { "int", "a3" }, { "int", "a4" } } },
{ 254, "semctl", 4, { { "int", "semid" }, { "int", "semnum" }, { "int", "cmd" }, { "semun_t", "arg" } } },
{ 255, "semget", 3, { { "key_t", "key" }, { "int", "nsems" }, { "int", "semflg" } } },
{ 256, "semop", 3, { { "int", "semid" }, { "struct sembuf *", "sops" }, { "int", "nsops" } } },
{ 258, "msgctl", 3, { { "int", "msqid" }, { "int", "cmd" }, { "struct msqid_ds *", "buf" } } },
{ 259, "msgget", 2, { { "key_t", "key" }, { "int", "msgflg" } } },
{ 260, "msgsnd", 4, { { "int", "msqid" }, { "void *", "msgp" }, { "size_t", "msgsz" }, { "int", "msgflg" } } },
{ 261, "msgrcv", 5, { { "int", "msqid" }, { "void *", "msgp" }, { "size_t", "msgsz" }, { "long", "msgtyp" }, { "int", "msgflg" } } },
{ 262, "shmat", 3, { { "int", "shmid" }, { "void *", "shmaddr" }, { "int", "shmflg" } } },
{ 263, "shmctl", 3, { { "int", "shmid" }, { "int", "cmd" }, { "struct shmid_ds *", "buf" } } },
{ 264, "shmdt", 1, { { "void *", "shmaddr" } } },
{ 265, "shmget", 3, { { "key_t", "key" }, { "size_t", "size" }, { "int", "shmflg" } } },
{ 266, "shm_open", 3, { { "const char *", "name" }, { "int", "oflag" }, { "int", "mode" } } },
{ 267, "shm_unlink", 1, { { "const char *", "name" } } },
{ 268, "sem_open", 4, { { "const char *", "name" }, { "int", "oflag" }, { "int", "mode" }, { "int", "value" } } },
{ 269, "sem_close", 1, { { "sem_t *", "sem" } } },
{ 270, "sem_unlink", 1, { { "const char *", "name" } } },
{ 271, "sem_wait", 1, { { "sem_t *", "sem" } } },
{ 272, "sem_trywait", 1, { { "sem_t *", "sem" } } },
{ 273, "sem_post", 1, { { "sem_t *", "sem" } } },
{ 274, "sysctlbyname", 6, { { "const char *", "name" }, { "size_t", "namelen" }, { "void *", "old" }, { "size_t *", "oldlenp" }, { "void *", "new" }, { "size_t", "newlen" } } },
{ 277, "open_extended", 6, { { "char *", "path" }, { "int", "flags" }, { "uid_t", "uid" }, { "gid_t", "gid" }, { "int", "mode" }, { "user_addr_t", "xsecurity" } } },
{ 278, "umask_extended", 2, { { "int", "newmask" }, { "user_addr_t", "xsecurity" } } },
{ 279, "stat_extended", 4, { { "char *", "path" }, { "user_addr_t", "ub" }, { "user_addr_t", "xsecurity" }, { "user_addr_t", "xsecurity_size" } } },
{ 280, "lstat_extended", 4, { { "char *", "path" }, { "user_addr_t", "ub" }, { "user_addr_t", "xsecurity" }, { "user_addr_t", "xsecurity_size" } } },
{ 281, "fstat_extended", 4, { { "int", "fd" }, { "user_addr_t", "ub" }, { "user_addr_t", "xsecurity" }, { "user_addr_t", "xsecurity_size" } } },
{ 282, "chmod_extended", 5, { { "char *", "path" }, { "uid_t", "uid" }, { "gid_t", "gid" }, { "int", "mode" }, { "user_addr_t", "xsecurity" } } },
{ 283, "fchmod_extended", 5, { { "int", "fd" }, { "uid_t", "uid" }, { "gid_t", "gid" }, { "int", "mode" }, { "user_addr_t", "xsecurity" } } },
{ 284, "access_extended", 4, { { "user_addr_t", "entries" }, { "size_t", "size" }, { "user_addr_t", "results" }, { "uid_t", "uid" } } },
{ 285, "settid", 2, { { "uid_t", "uid" }, { "gid_t", "gid" } } },
{ 286, "gettid", 2, { { "uid_t *", "uidp" }, { "gid_t *", "gidp" } } },
{ 287, "setsgroups", 2, { { "int", "setlen" }, { "user_addr_t", "guidset" } } },
{ 288, "getsgroups", 2, { { "user_addr_t", "setlen" }, { "user_addr_t", "guidset" } } },
{ 289, "setwgroups", 2, { { "int", "setlen" }, { "user_addr_t", "guidset" } } },
{ 290, "getwgroups", 2, { { "user_addr_t", "setlen" }, { "user_addr_t", "guidset" } } },
{ 291, "mkfifo_extended", 5, { { "char *", "path" }, { "uid_t", "uid" }, { "gid_t", "gid" }, { "int", "mode" }, { "user_addr_t", "xsecurity" } } },
{ 292, "mkdir_extended", 5, { { "char *", "path" }, { "uid_t", "uid" }, { "gid_t", "gid" }, { "int", "mode" }, { "user_addr_t", "xsecurity" } } },
{ 293, "identitysvc", 2, { { "int", "opcode" }, { "user_addr_t", "message" } } },
{ 294, "shared_region_check_np", 1, { { "uint64_t *", "start_address" } } },
{ 296, "vm_pressure_monitor", 3, { { "int", "wait_for_pressure" }, { "int", "nsecs_monitored" }, { "uint32_t *", "pages_reclaimed" } } },
{ 297, "psynch_rw_longrdlock", 5, { { "user_addr_t", "rwlock" }, { "uint32_t", "lgenval" }, { "uint32_t", "ugenval" }, { "uint32_t", "rw_wc" }, { "int", "flags" } } },
{ 298, "psynch_rw_yieldwrlock", 5, { { "user_addr_t", "rwlock" }, { "uint32_t", "lgenval" }, { "uint32_t", "ugenval" }, { "uint32_t", "rw_wc" }, { "int", "flags" } } },
{ 299, "psynch_rw_downgrade", 5, { { "user_addr_t", "rwlock" }, { "uint32_t", "lgenval" }, { "uint32_t", "ugenval" }, { "uint32_t", "rw_wc" }, { "int", "flags" } } },
{ 300, "psynch_rw_upgrade", 5, { { "user_addr_t", "rwlock" }, { "uint32_t", "lgenval" }, { "uint32_t", "ugenval" }, { "uint32_t", "rw_wc" }, { "int", "flags" } } },
{ 301, "psynch_mutexwait", 5, { { "user_addr_t", "mutex" }, { "uint32_t", "mgen" }, { "uint32_t", "ugen" }, { "uint64_t", "tid" }, { "uint32_t", "flags" } } },
{ 302, "psynch_mutexdrop", 5, { { "user_addr_t", "mutex" }, { "uint32_t", "mgen" }, { "uint32_t", "ugen" }, { "uint64_t", "tid" }, { "uint32_t", "flags" } } },
{ 303, "psynch_cvbroad", 7, { { "user_addr_t", "cv" }, { "uint64_t", "cvlsgen" }, { "uint64_t", "cvudgen" }, { "uint32_t", "flags" }, { "user_addr_t", "mutex" }, { "uint64_t", "mugen" }, { "uint64_t", "tid" } } },
{ 304, "psynch_cvsignal", 8, { { "user_addr_t", "cv" }, { "uint64_t", "cvlsgen" }, { "uint32_t", "cvugen" }, { "int", "thread_port" }, { "user_addr_t", "mutex" }, { "uint64_t", "mugen" }, { "uint64_t", "tid" }, { "uint32_t", "flags" } } },
{ 305, "psynch_cvwait", 8, { { "user_addr_t", "cv" }, { "uint64_t", "cvlsgen" }, { "uint32_t", "cvugen" }, { "user_addr_t", "mutex" }, { "uint64_t", "mugen" }, { "uint32_t", "flags" }, { "int64_t", "sec" }, { "uint32_t", "nsec" } } },
{ 306, "psynch_rw_rdlock", 5, { { "user_addr_t", "rwlock" }, { "uint32_t", "lgenval" }, { "uint32_t", "ugenval" }, { "uint32_t", "rw_wc" }, { "int", "flags" } } },
{ 307, "psynch_rw_wrlock", 5, { { "user_addr_t", "rwlock" }, { "uint32_t", "lgenval" }, { "uint32_t", "ugenval" }, { "uint32_t", "rw_wc" }, { "int", "flags" } } },
{ 308, "psynch_rw_unlock", 5, { { "user_addr_t", "rwlock" }, { "uint32_t", "lgenval" }, { "uint32_t", "ugenval" }, { "uint32_t", "rw_wc" }, { "int", "flags" } } },
{ 309, "psynch_rw_unlock2", 5, { { "user_addr_t", "rwlock" }, { "uint32_t", "lgenval" }, { "uint32_t", "ugenval" }, { "uint32_t", "rw_wc" }, { "int", "flags" } } },
{ 310, "getsid", 1, { { "pid_t", "pid" } } },
{ 311, "settid_with_pid", 2, { { "pid_t", "pid" }, { "int", "assume" } } },
{ 312, "psynch_cvclrprepost", 7, { { "user_addr_t", "cv" }, { "uint32_t", "cvgen" }, { "uint32_t", "cvugen" }, { "uint32_t", "cvsgen" }, { "uint32_t", "prepocnt" }, { "uint32_t", "preposeq" }, { "uint32_t", "flags" } } },
{ 313, "aio_fsync", 2, { { "int", "op" }, { "user_addr_t", "aiocbp" } } },
{ 314, "aio_return", 1, { { "user_addr_t", "aiocbp" } } },
{ 315, "aio_suspend", 3, { { "user_addr_t", "aiocblist" }, { "int", "nent" }, { "user_addr_t", "timeoutp" } } },
{ 316, "aio_cancel", 2, { { "int", "fd" }, { "user_addr_t", "aiocbp" } } },
{ 317, "aio_error", 1, { { "user_addr_t", "aiocbp" } } },
{ 318, "aio_read", 1, { { "user_addr_t", "aiocbp" } } },
{ 319, "aio_write", 1, { { "user_addr_t", "aiocbp" } } },
{ 320, "lio_listio", 4, { { "int", "mode" }, { "user_addr_t", "aiocblist" }, { "int", "nent" }, { "user_addr_t", "sigp" } } },
{ 322, "iopolicysys", 2, { { "int", "cmd" }, { "void *", "arg" } } },
{ 323, "process_policy", 7, { { "int", "scope" }, { "int", "action" }, { "int", "policy" }, { "int", "policy_subtype" }, { "user_addr_t", "attrp" }, { "pid_t", "target_pid" }, { "uint64_t", "target_threadid" } } },
{ 324, "mlockall", 1, { { "int", "how" } } },
{ 325, "munlockall", 1, { { "int", "how" } } },
{ 327, "issetugid", 0, {} },
{ 328, "pthread_kill", 2, { { "int", "thread_port" }, { "int", "sig" } } },
{ 329, "pthread_sigmask", 3, { { "int", "how" }, { "user_addr_t", "set" }, { "user_addr_t", "oset" } } },
{ 330, "sigwait", 2, { { "user_addr_t", "set" }, { "user_addr_t", "sig" } } },
{ 331, "disable_threadsignal", 1, { { "int", "value" } } },
{ 332, "pthread_markcancel", 1, { { "int", "thread_port" } } },
{ 333, "pthread_canceled", 1, { { "int", "action" } } },
{ 334, "semwait_signal", 6, { { "int", "cond_sem" }, { "int", "mutex_sem" }, { "int", "timeout" }, { "int", "relative" }, { "int64_t", "tv_sec" }, { "int32_t", "tv_nsec" } } },
{ 336, "proc_info", 6, { { "int32_t", "callnum" }, { "int32_t", "pid" }, { "uint32_t", "flavor" }, { "uint64_t", "arg" }, { "user_addr_t", "buffer" }, { "int32_t", "buffersize" } } },
{ 337, "sendfile", 6, { { "int", "fd" }, { "int", "s" }, { "off_t", "offset" }, { "off_t *", "nbytes" }, { "struct sf_hdtr *", "hdtr" }, { "int", "flags" } } },
{ 338, "stat64", 2, { { "char *", "path" }, { "user_addr_t", "ub" } } },
{ 339, "fstat64", 2, { { "int", "fd" }, { "user_addr_t", "ub" } } },
{ 340, "lstat64", 2, { { "char *", "path" }, { "user_addr_t", "ub" } } },
{ 341, "stat64_extended", 4, { { "char *", "path" }, { "user_addr_t", "ub" }, { "user_addr_t", "xsecurity" }, { "user_addr_t", "xsecurity_size" } } },
{ 342, "lstat64_extended", 4, { { "char *", "path" }, { "user_addr_t", "ub" }, { "user_addr_t", "xsecurity" }, { "user_addr_t", "xsecurity_size" } } },
{ 343, "fstat64_extended", 4, { { "int", "fd" }, { "user_addr_t", "ub" }, { "user_addr_t", "xsecurity" }, { "user_addr_t", "xsecurity_size" } } },
{ 344, "getdirentries64", 4, { { "int", "fd" }, { "void *", "buf" }, { "user_size_t", "bufsize" }, { "off_t *", "position" } } },
{ 345, "statfs64", 2, { { "char *", "path" }, { "struct statfs64 *", "buf" } } },
{ 346, "fstatfs64", 2, { { "int", "fd" }, { "struct statfs64 *", "buf" } } },
{ 347, "getfsstat64", 3, { { "user_addr_t", "buf" }, { "int", "bufsize" }, { "int", "flags" } } },
{ 348, "pthread_chdir", 1, { { "char *", "path" } } },
{ 349, "pthread_fchdir", 1, { { "int", "fd" } } },
{ 350, "audit", 2, { { "void *", "record" }, { "int", "length" } } },
{ 351, "auditon", 3, { { "int", "cmd" }, { "void *", "data" }, { "int", "length" } } },
{ 353, "getauid", 1, { { "au_id_t *", "auid" } } },
{ 354, "setauid", 1, { { "au_id_t *", "auid" } } },
{ 357, "getaudit_addr", 2, { { "struct auditinfo_addr *", "auditinfo_addr" }, { "int", "length" } } },
{ 358, "setaudit_addr", 2, { { "struct auditinfo_addr *", "auditinfo_addr" }, { "int", "length" } } },
{ 359, "auditctl", 1, { { "char *", "path" } } },
{ 360, "bsdthread_create", 5, { { "user_addr_t", "func" }, { "user_addr_t", "func_arg" }, { "user_addr_t", "stack" }, { "user_addr_t", "pthread" }, { "uint32_t", "flags" } } },
{ 361, "bsdthread_terminate", 4, { { "user_addr_t", "stackaddr" }, { "size_t", "freesize" }, { "uint32_t", "port" }, { "user_addr_t", "sema_or_ulock" } } },
{ 362, "kqueue", 0, {} },
{ 363, "kevent", 6, { { "int", "fd" }, { "const struct kevent *", "changelist" }, { "int", "nchanges" }, { "struct kevent *", "eventlist" }, { "int", "nevents" }, { "const struct timespec *", "timeout" } } },
{ 364, "lchown", 3, { { "char *", "path" }, { "uid_t", "owner" }, { "gid_t", "group" } } },
{ 366, "bsdthread_register", 7, { { "user_addr_t", "threadstart" }, { "user_addr_t", "wqthread" }, { "uint32_t", "flags" }, { "user_addr_t", "stack_addr_hint" }, { "user_addr_t", "targetconc_ptr" }, { "uint32_t", "dispatchqueue_offset" }, { "uint32_t", "tsd_offset" } } },
{ 367, "workq_open", 0, {} },
{ 368, "workq_kernreturn", 4, { { "int", "options" }, { "user_addr_t", "item" }, { "int", "affinity" }, { "int", "prio" } } },
{ 369, "kevent64", 7, { { "int", "fd" }, { "const struct kevent64_s *", "changelist" }, { "int", "nchanges" }, { "struct kevent64_s *", "eventlist" }, { "int", "nevents" }, { "unsigned int", "flags" }, { "const struct timespec *", "timeout" } } },
{ 372, "thread_selfid", 0, {} },
{ 373, "ledger", 4, { { "int", "cmd" }, { "caddr_t", "arg1" }, { "caddr_t", "arg2" }, { "caddr_t", "arg3" } } },
{ 374, "kevent_qos", 8, { { "int", "fd" }, { "const struct kevent_qos_s *", "changelist" }, { "int", "nchanges" }, { "struct kevent_qos_s *", "eventlist" }, { "int", "nevents" }, { "void *", "data_out" }, { "size_t *", "data_available" }, { "unsigned int", "flags" } } },
{ 375, "kevent_id", 8, { { "uint64_t", "id" }, { "const struct kevent_qos_s *", "changelist" }, { "int", "nchanges" }, { "struct kevent_qos_s *", "eventlist" }, { "int", "nevents" }, { "void *", "data_out" }, { "size_t *", "data_available" }, { "unsigned int", "flags" } } },
{ 380, "mac_execve", 4, { { "char *", "fname" }, { "char **", "argp" }, { "char **", "envp" }, { "struct mac *", "mac_p" } } },
{ 381, "mac_syscall", 3, { { "char *", "policy" }, { "int", "call" }, { "user_addr_t", "arg" } } },
{ 382, "mac_get_file", 2, { { "char *", "path_p" }, { "struct mac *", "mac_p" } } },
{ 383, "mac_set_file", 2, { { "char *", "path_p" }, { "struct mac *", "mac_p" } } },
{ 384, "mac_get_link", 2, { { "char *", "path_p" }, { "struct mac *", "mac_p" } } },
{ 385, "mac_set_link", 2, { { "char *", "path_p" }, { "struct mac *", "mac_p" } } },
{ 386, "mac_get_proc", 1, { { "struct mac *", "mac_p" } } },
{ 387, "mac_set_proc", 1, { { "struct mac *", "mac_p" } } },
{ 388, "mac_get_fd", 2, { { "int", "fd" }, { "struct mac *", "mac_p" } } },
{ 389, "mac_set_fd", 2, { { "int", "fd" }, { "struct mac *", "mac_p" } } },
{ 390, "mac_get_pid", 2, { { "pid_t", "pid" }, { "struct mac *", "mac_p" } } },
{ 394, "pselect", 6, { { "int", "nd" }, { "u_int32_t *", "in" }, { "u_int32_t *", "ou" }, { "u_int32_t *", "ex" }, { "const struct timespec *", "ts" }, { "const struct sigset_t *", "mask" } } },
{ 395, "pselect_nocancel", 6, { { "int", "nd" }, { "u_int32_t *", "in" }, { "u_int32_t *", "ou" }, { "u_int32_t *", "ex" }, { "const struct timespec *", "ts" }, { "const struct sigset_t *", "mask" } } },
{ 396, "read_nocancel", 3, { { "int", "fd" }, { "user_addr_t", "cbuf" }, { "user_size_t", "nbyte" } } },
{ 397, "write_nocancel", 3, { { "int", "fd" }, { "user_addr_t", "cbuf" }, { "user_size_t", "nbyte" } } },
{ 398, "open_nocancel", 3, { { "char *", "path" }, { "int", "flags" }, { "int", "mode" } } },
{ 399, "close_nocancel", 1, { { "int", "fd" } } },
{ 400, "wait4_nocancel", 4, { { "int", "pid" }, { "user_addr_t", "status" }, { "int", "options" }, { "user_addr_t", "rusage" } } },
{ 401, "recvmsg_nocancel", 3, { { "int", "s" }, { "struct msghdr *", "msg" }, { "int", "flags" } } },
{ 402, "sendmsg_nocancel", 3, { { "int", "s" }, { "caddr_t", "msg" }, { "int", "flags" } } },
{ 403, "recvfrom_nocancel", 6, { { "int", "s" }, { "void *", "buf" }, { "size_t", "len" }, { "int", "flags" }, { "struct sockaddr *", "from" }, { "int *", "fromlenaddr" } } },
{ 404, "accept_nocancel", 3, { { "int", "s" }, { "caddr_t", "name" }, { "socklen_t *", "anamelen" } } },
{ 405, "msync_nocancel", 3, { { "caddr_ut", "addr" }, { "size_ut", "len" }, { "int", "flags" } } },
{ 406, "fcntl_nocancel", 3, { { "int", "fd" }, { "int", "cmd" }, { "long", "arg" } } },
{ 407, "select_nocancel", 5, { { "int", "nd" }, { "u_int32_t *", "in" }, { "u_int32_t *", "ou" }, { "u_int32_t *", "ex" }, { "struct timeval *", "tv" } } },
{ 408, "fsync_nocancel", 1, { { "int", "fd" } } },
{ 409, "connect_nocancel", 3, { { "int", "s" }, { "caddr_t", "name" }, { "socklen_t", "namelen" } } },
{ 410, "sigsuspend_nocancel", 1, { { "sigset_t", "mask" } } },
{ 411, "readv_nocancel", 3, { { "int", "fd" }, { "struct iovec *", "iovp" }, { "u_int", "iovcnt" } } },
{ 412, "writev_nocancel", 3, { { "int", "fd" }, { "struct iovec *", "iovp" }, { "u_int", "iovcnt" } } },
{ 413, "sendto_nocancel", 6, { { "int", "s" }, { "caddr_t", "buf" }, { "size_t", "len" }, { "int", "flags" }, { "caddr_t", "to" }, { "socklen_t", "tolen" } } },
{ 414, "pread_nocancel", 4, { { "int", "fd" }, { "user_addr_t", "buf" }, { "user_size_t", "nbyte" }, { "off_t", "offset" } } },
{ 415, "pwrite_nocancel", 4, { { "int", "fd" }, { "user_addr_t", "buf" }, { "user_size_t", "nbyte" }, { "off_t", "offset" } } },
{ 416, "waitid_nocancel", 4, { { "idtype_t", "idtype" }, { "id_t", "id" }, { "siginfo_t *", "infop" }, { "int", "options" } } },
{ 417, "poll_nocancel", 3, { { "struct pollfd *", "fds" }, { "u_int", "nfds" }, { "int", "timeout" } } },
{ 418, "msgsnd_nocancel", 4, { { "int", "msqid" }, { "void *", "msgp" }, { "size_t", "msgsz" }, { "int", "msgflg" } } },
{ 419, "msgrcv_nocancel", 5, { { "int", "msqid" }, { "void *", "msgp" }, { "size_t", "msgsz" }, { "long", "msgtyp" }, { "int", "msgflg" } } },
{ 420, "sem_wait_nocancel", 1, { { "sem_t *", "sem" } } },
{ 421, "aio_suspend_nocancel", 3, { { "user_addr_t", "aiocblist" }, { "int", "nent" }, { "user_addr_t", "timeoutp" } } },
{ 422, "sigwait_nocancel", 2, { { "user_addr_t", "set" }, { "user_addr_t", "sig" } } },
{ 423, "semwait_signal_nocancel", 6, { { "int", "cond_sem" }, { "int", "mutex_sem" }, { "int", "timeout" }, { "int", "relative" }, { "int64_t", "tv_sec" }, { "int32_t", "tv_nsec" } } },
{ 424, "mac_mount", 5, { { "char *", "type" }, { "char *", "path" }, { "int", "flags" }, { "caddr_t", "data" }, { "struct mac *", "mac_p" } } },
{ 425, "mac_get_mount", 2, { { "char *", "path" }, { "struct mac *", "mac_p" } } },
{ 426, "mac_getfsstat", 5, { { "user_addr_t", "buf" }, { "int", "bufsize" }, { "user_addr_t", "mac" }, { "int", "macsize" }, { "int", "flags" } } },
{ 427, "fsgetpath", 4, { { "user_addr_t", "buf" }, { "size_t", "bufsize" }, { "user_addr_t", "fsid" }, { "uint64_t", "objid" } } },
{ 428, "audit_session_self", 0, {} },
{ 429, "audit_session_join", 1, { { "mach_port_name_t", "port" } } },
{ 430, "fileport_makeport", 2, { { "int", "fd" }, { "user_addr_t", "portnamep" } } },
{ 431, "fileport_makefd", 1, { { "mach_port_name_t", "port" } } },
{ 432, "audit_session_port", 2, { { "au_asid_t", "asid" }, { "user_addr_t", "portnamep" } } },
{ 433, "pid_suspend", 1, { { "int", "pid" } } },
{ 434, "pid_resume", 1, { { "int", "pid" } } },
{ 435, "pid_hibernate", 1, { { "int", "pid" } } },
{ 436, "pid_shutdown_sockets", 2, { { "int", "pid" }, { "int", "level" } } },
{ 439, "kas_info", 3, { { "int", "selector" }, { "void *", "value" }, { "size_t *", "size" } } },
{ 440, "memorystatus_control", 5, { { "uint32_t", "command" }, { "int32_t", "pid" }, { "uint32_t", "flags" }, { "user_addr_t", "buffer" }, { "size_t", "buffersize" } } },
{ 441, "guarded_open_np", 5, { { "char *", "path" }, { "const guardid_t *", "guard" }, { "u_int", "guardflags" }, { "int", "flags" }, { "int", "mode" } } },
{ 442, "guarded_close_np", 2, { { "int", "fd" }, { "const guardid_t *", "guard" } } },
{ 443, "guarded_kqueue_np", 2, { { "const guardid_t *", "guard" }, { "u_int", "guardflags" } } },
{ 444, "change_fdguard_np", 6, { { "int", "fd" }, { "const guardid_t *", "guard" }, { "u_int", "guardflags" }, { "const guardid_t *", "nguard" }, { "u_int", "nguardflags" }, { "int *", "fdflagsp" } } },
{ 445, "usrctl", 1, { { "uint32_t", "flags" } } },
{ 446, "proc_rlimit_control", 3, { { "pid_t", "pid" }, { "int", "flavor" }, { "void *", "arg" } } },
{ 447, "connectx", 8, { { "int", "socket" }, { "const sa_endpoints_t *", "endpoints" }, { "sae_associd_t", "associd" }, { "unsigned int", "flags" }, { "const struct iovec *", "iov" }, { "unsigned int", "iovcnt" }, { "size_t *", "len" }, { "sae_connid_t *", "connid" } } },
{ 448, "disconnectx", 3, { { "int", "s" }, { "sae_associd_t", "aid" }, { "sae_connid_t", "cid" } } },
{ 449, "peeloff", 2, { { "int", "s" }, { "sae_associd_t", "aid" } } },
{ 450, "socket_delegate", 4, { { "int", "domain" }, { "int", "type" }, { "int", "protocol" }, { "pid_t", "epid" } } },
{ 451, "telemetry", 6, { { "uint64_t", "cmd" }, { "uint64_t", "deadline" }, { "uint64_t", "interval" }, { "uint64_t", "leeway" }, { "uint64_t", "arg4" }, { "uint64_t", "arg5" } } },
{ 452, "proc_uuid_policy", 4, { { "uint32_t", "operation" }, { "uuid_t", "uuid" }, { "size_t", "uuidlen" }, { "uint32_t", "flags" } } },
{ 453, "memorystatus_get_level", 1, { { "user_addr_t", "level" } } },
{ 454, "system_override", 2, { { "uint64_t", "timeout" }, { "uint64_t", "flags" } } },
{ 455, "vfs_purge", 0, {} },
{ 456, "sfi_ctl", 4, { { "uint32_t", "operation" }, { "uint32_t", "sfi_class" }, { "uint64_t", "time" }, { "uint64_t *", "out_time" } } },
{ 457, "sfi_pidctl", 4, { { "uint32_t", "operation" }, { "pid_t", "pid" }, { "uint32_t", "sfi_flags" }, { "uint32_t *", "out_sfi_flags" } } },
{ 458, "coalition", 3, { { "uint32_t", "operation" }, { "uint64_t *", "cid" }, { "uint32_t", "flags" } } },
{ 459, "coalition_info", 4, { { "uint32_t", "flavor" }, { "uint64_t *", "cid" }, { "void *", "buffer" }, { "size_t *", "bufsize" } } },
{ 460, "necp_match_policy", 3, { { "uint8_t *", "parameters" }, { "size_t", "parameters_size" }, { "struct necp_aggregate_result *", "returned_result" } } },
{ 461, "getattrlistbulk", 5, { { "int", "dirfd" }, { "struct attrlist *", "alist" }, { "void *", "attribute_buffer" }, { "size_t", "buffer_size" }, { "uint64_t", "options" } } },
{ 462, "clonefileat", 5, { { "int", "src_dirfd" }, { "user_addr_t", "src" }, { "int", "dst_dirfd" }, { "user_addr_t", "dst" }, { "uint32_t", "flags" } } },
{ 463, "openat", 4, { { "int", "fd" }, { "char *", "path" }, { "int", "flags" }, { "int", "mode" } } },
{ 464, "openat_nocancel", 4, { { "int", "fd" }, { "char *", "path" }, { "int", "flags" }, { "int", "mode" } } },
{ 465, "renameat", 4, { { "int", "fromfd" }, { "char *", "from" }, { "int", "tofd" }, { "char *", "to" } } },
{ 466, "faccessat", 4, { { "int", "fd" }, { "char *", "path" }, { "int", "amode" }, { "int", "flag" } } },
{ 467, "fchmodat", 4, { { "int", "fd" }, { "char *", "path" }, { "int", "mode" }, { "int", "flag" } } },
{ 468, "fchownat", 5, { { "int", "fd" }, { "char *", "path" }, { "uid_t", "uid" }, { "gid_t", "gid" }, { "int", "flag" } } },
{ 469, "fstatat", 4, { { "int", "fd" }, { "char *", "path" }, { "user_addr_t", "ub" }, { "int", "flag" } } },
{ 470, "fstatat64", 4, { { "int", "fd" }, { "char *", "path" }, { "user_addr_t", "ub" }, { "int", "flag" } } },
{ 471, "linkat", 5, { { "int", "fd1" }, { "char *", "path" }, { "int", "fd2" }, { "char *", "link" }, { "int", "flag" } } },
{ 472, "unlinkat", 3, { { "int", "fd" }, { "char *", "path" }, { "int", "flag" } } },
{ 473, "readlinkat", 4, { { "int", "fd" }, { "char *", "path" }, { "user_addr_t", "buf" }, { "size_t", "bufsize" } } },
{ 474, "symlinkat", 3, { { "user_addr_t *", "path1" }, { "int", "fd" }, { "user_addr_t", "path2" } } },
{ 475, "mkdirat", 3, { { "int", "fd" }, { "char *", "path" }, { "int", "mode" } } },
{ 476, "getattrlistat", 6, { { "int", "fd" }, { "const char *", "path" }, { "struct attrlist *", "alist" }, { "void *", "attribute_buffer" }, { "size_t", "buffer_size" }, { "u_long", "options" } } },
{ 477, "proc_trace_log", 2, { { "pid_t", "pid" }, { "uint64_t", "uniqueid" } } },
{ 478, "bsdthread_ctl", 4, { { "user_addr_t", "cmd" }, { "user_addr_t", "arg1" }, { "user_addr_t", "arg2" }, { "user_addr_t", "arg3" } } },
{ 479, "openbyid_np", 3, { { "user_addr_t", "fsid" }, { "user_addr_t", "objid" }, { "int", "oflags" } } },
{ 480, "recvmsg_x", 4, { { "int", "s" }, { "struct msghdr_x *", "msgp" }, { "u_int", "cnt" }, { "int", "flags" } } },
{ 481, "sendmsg_x", 4, { { "int", "s" }, { "struct msghdr_x *", "msgp" }, { "u_int", "cnt" }, { "int", "flags" } } },
{ 482, "thread_selfusage", 0, {} },
{ 483, "csrctl", 3, { { "uint32_t", "op" }, { "user_addr_t", "useraddr" }, { "user_addr_t", "usersize" } } },
{ 484, "guarded_open_dprotected_np", 7, { { "char *", "path" }, { "const guardid_t *", "guard" }, { "u_int", "guardflags" }, { "int", "flags" }, { "int", "dpclass" }, { "int", "dpflags" }, { "int", "mode" } } },
{ 485, "guarded_write_np", 4, { { "int", "fd" }, { "const guardid_t *", "guard" }, { "user_addr_t", "cbuf" }, { "user_size_t", "nbyte" } } },
{ 486, "guarded_pwrite_np", 5, { { "int", "fd" }, { "const guardid_t *", "guard" }, { "user_addr_t", "buf" }, { "user_size_t", "nbyte" }, { "off_t", "offset" } } },
{ 487, "guarded_writev_np", 4, { { "int", "fd" }, { "const guardid_t *", "guard" }, { "struct iovec *", "iovp" }, { "int", "iovcnt" } } },
{ 488, "renameatx_np", 5, { { "int", "fromfd" }, { "char *", "from" }, { "int", "tofd" }, { "char *", "to" }, { "u_int", "flags" } } },
{ 489, "mremap_encrypted", 5, { { "caddr_ut", "addr" }, { "size_ut", "len" }, { "uint32_t", "cryptid" }, { "uint32_t", "cputype" }, { "uint32_t", "cpusubtype" } } },
{ 490, "netagent_trigger", 2, { { "uuid_t", "agent_uuid" }, { "size_t", "agent_uuidlen" } } },
{ 491, "stack_snapshot_with_config", 3, { { "int", "stackshot_config_version" }, { "user_addr_t", "stackshot_config" }, { "size_t", "stackshot_config_size" } } },
{ 492, "microstackshot", 3, { { "user_addr_t", "tracebuf" }, { "uint32_t", "tracebuf_size" }, { "uint32_t", "flags" } } },
{ 493, "grab_pgo_data", 4, { { "user_addr_t", "uuid" }, { "int", "flags" }, { "user_addr_t", "buffer" }, { "user_ssize_t", "size" } } },
{ 494, "persona", 6, { { "uint32_t", "operation" }, { "uint32_t", "flags" }, { "struct kpersona_info *", "info" }, { "uid_t *", "id" }, { "size_t *", "idlen" }, { "char *", "path" } } },
{ 496, "mach_eventlink_signal", 2, { { "mach_port_name_t", "eventlink_port" }, { "uint64_t", "signal_count" } } },
{ 497, "mach_eventlink_wait_until", 5, { { "mach_port_name_t", "eventlink_port" }, { "uint64_t", "wait_count" }, { "uint64_t", "deadline" }, { "uint32_t", "clock_id" }, { "uint32_t", "option" } } },
{ 498, "mach_eventlink_signal_wait_until", 6, { { "mach_port_name_t", "eventlink_port" }, { "uint64_t", "wait_count" }, { "uint64_t", "signal_count" }, { "uint64_t", "deadline" }, { "uint32_t", "clock_id" }, { "uint32_t", "option" } } },
{ 499, "work_interval_ctl", 4, { { "uint32_t", "operation" }, { "uint64_t", "work_interval_id" }, { "void *", "arg" }, { "size_t", "len" } } },
{ 500, "getentropy", 2, { { "void *", "buffer" }, { "size_t", "size" } } },
{ 502, "necp_client_action", 6, { { "int", "necp_fd" }, { "uint32_t", "action" }, { "uuid_t", "client_id" }, { "size_t", "client_id_len" }, { "uint8_t *", "buffer" }, { "size_t", "buffer_size" } } },
{ 503, "nexus_open", 2, { { "struct nxctl_init *", "init" }, { "uint32_t", "init_len" } } },
{ 504, "nexus_register", 5, { { "int", "ctl" }, { "struct nxprov_reg *", "reg" }, { "uint32_t", "reg_len" }, { "uuid_t *", "prov_uuid" }, { "uint32_t", "prov_uuid_len" } } },
{ 505, "nexus_deregister", 3, { { "int", "ctl" }, { "uuid_t", "prov_uuid" }, { "uint32_t", "prov_uuid_len" } } },
{ 506, "nexus_create", 5, { { "int", "ctl" }, { "uuid_t", "prov_uuid" }, { "uint32_t", "prov_uuid_len" }, { "uuid_t *", "nx_uuid" }, { "uint32_t", "nx_uuid_len" } } },
{ 507, "nexus_destroy", 3, { { "int", "ctl" }, { "uuid_t", "nx_uuid" }, { "uint32_t", "nx_uuid_len" } } },
{ 508, "nexus_get_opt", 4, { { "int", "ctl" }, { "uint32_t", "opt" }, { "void *", "aoptval" }, { "uint32_t *", "aoptlen" } } },
{ 509, "nexus_set_opt", 4, { { "int", "ctl" }, { "uint32_t", "opt" }, { "const void *", "aoptval" }, { "uint32_t", "optlen" } } },
{ 510, "channel_open", 2, { { "struct ch_init *", "init" }, { "uint32_t", "init_len" } } },
{ 511, "channel_get_info", 3, { { "int", "c" }, { "struct ch_info *", "cinfo" }, { "uint32_t", "cinfolen" } } },
{ 512, "channel_sync", 3, { { "int", "c" }, { "int", "mode" }, { "int", "flags" } } },
{ 513, "channel_get_opt", 4, { { "int", "c" }, { "uint32_t", "opt" }, { "void *", "aoptval" }, { "uint32_t *", "aoptlen" } } },
{ 514, "channel_set_opt", 4, { { "int", "c" }, { "uint32_t", "opt" }, { "const void *", "aoptval" }, { "uint32_t", "optlen" } } },
{ 515, "ulock_wait", 4, { { "uint32_t", "operation" }, { "void *", "addr" }, { "uint64_t", "value" }, { "uint32_t", "timeout" } } },
{ 516, "ulock_wake", 3, { { "uint32_t", "operation" }, { "void *", "addr" }, { "uint64_t", "wake_value" } } },
{ 517, "fclonefileat", 4, { { "int", "src_fd" }, { "int", "dst_dirfd" }, { "user_addr_t", "dst" }, { "uint32_t", "flags" } } },
{ 518, "fs_snapshot", 6, { { "uint32_t", "op" }, { "int", "dirfd" }, { "user_addr_t", "name1" }, { "user_addr_t", "name2" }, { "user_addr_t", "data" }, { "uint32_t", "flags" } } },
{ 520, "terminate_with_payload", 7, { { "int", "pid" }, { "uint32_t", "reason_namespace" }, { "uint64_t", "reason_code" }, { "void *", "payload" }, { "uint32_t", "payload_size" }, { "const char *", "reason_string" }, { "uint64_t", "reason_flags" } } },
{ 521, "abort_with_payload", 6, { { "uint32_t", "reason_namespace" }, { "uint64_t", "reason_code" }, { "void *", "payload" }, { "uint32_t", "payload_size" }, { "const char *", "reason_string" }, { "uint64_t", "reason_flags" } } },
{ 523, "necp_session_action", 6, { { "int", "necp_fd" }, { "uint32_t", "action" }, { "uint8_t *", "in_buffer" }, { "size_t", "in_buffer_length" }, { "uint8_t *", "out_buffer" }, { "size_t", "out_buffer_length" } } },
{ 524, "setattrlistat", 6, { { "int", "fd" }, { "const char *", "path" }, { "struct attrlist *", "alist" }, { "void *", "attribute_buffer" }, { "size_t", "buffer_size" }, { "uint32_t", "options" } } },
{ 525, "net_qos_guideline", 2, { { "struct net_qos_param *", "param" }, { "uint32_t", "param_len" } } },
{ 526, "fmount", 4, { { "const char *", "type" }, { "int", "fd" }, { "int", "flags" }, { "void *", "data" } } },
{ 527, "ntp_adjtime", 1, { { "struct timex *", "tp" } } },
{ 528, "ntp_gettime", 1, { { "struct ntptimeval *", "ntvp" } } },
{ 529, "os_fault_with_payload", 6, { { "uint32_t", "reason_namespace" }, { "uint64_t", "reason_code" }, { "void *", "payload" }, { "uint32_t", "payload_size" }, { "const char *", "reason_string" }, { "uint64_t", "reason_flags" } } },
{ 530, "kqueue_workloop_ctl", 4, { { "user_addr_t", "cmd" }, { "uint64_t", "options" }, { "user_addr_t", "addr" }, { "size_t", "sz" } } },
{ 531, "mach_bridge_remote_time", 1, { { "uint64_t", "local_timestamp" } } },
{ 532, "coalition_ledger", 4, { { "uint32_t", "operation" }, { "uint64_t *", "cid" }, { "void *", "buffer" }, { "size_t *", "bufsize" } } },
{ 533, "log_data", 4, { { "unsigned int", "tag" }, { "unsigned int", "flags" }, { "void *", "buffer" }, { "unsigned int", "size" } } },
{ 534, "memorystatus_available_memory", 0, {} },
{ 535, "objc_bp_assist_cfg_np", 2, { { "uint64_t", "adr" }, { "uint64_t", "ctl" } } },
{ 536, "shared_region_map_and_slide_2_np", 4, { { "uint32_t", "files_count" }, { "const struct shared_file_np *", "files" }, { "uint32_t", "mappings_count" }, { "const shared_file_mapping_slide_np_ut *", "mappings_u" } } },
{ 537, "pivot_root", 2, { { "const char *", "new_rootfs_path_before" }, { "const char *", "old_rootfs_path_after" } } },
{ 538, "task_inspect_for_pid", 3, { { "mach_port_name_t", "target_tport" }, { "int", "pid" }, { "mach_port_name_t *", "t" } } },
{ 539, "task_read_for_pid", 3, { { "mach_port_name_t", "target_tport" }, { "int", "pid" }, { "mach_port_name_t *", "t" } } },
{ 540, "preadv", 4, { { "int", "fd" }, { "struct iovec *", "iovp" }, { "int", "iovcnt" }, { "off_t", "offset" } } },
{ 541, "pwritev", 4, { { "int", "fd" }, { "struct iovec *", "iovp" }, { "int", "iovcnt" }, { "off_t", "offset" } } },
{ 542, "preadv_nocancel", 4, { { "int", "fd" }, { "struct iovec *", "iovp" }, { "int", "iovcnt" }, { "off_t", "offset" } } },
{ 543, "pwritev_nocancel", 4, { { "int", "fd" }, { "struct iovec *", "iovp" }, { "int", "iovcnt" }, { "off_t", "offset" } } },
{ 544, "ulock_wait2", 5, { { "uint32_t", "operation" }, { "void *", "addr" }, { "uint64_t", "value" }, { "uint64_t", "timeout" }, { "uint64_t", "value2" } } },
{ 545, "proc_info_extended_id", 8, { { "int32_t", "callnum" }, { "int32_t", "pid" }, { "uint32_t", "flavor" }, { "uint32_t", "flags" }, { "uint64_t", "ext_id" }, { "uint64_t", "arg" }, { "user_addr_t", "buffer" }, { "int32_t", "buffersize" } } },
{ 546, "tracker_action", 3, { { "int", "action" }, { "char *", "buffer" }, { "size_t", "buffer_size" } } },
{ 547, "debug_syscall_reject", 1, { { "uint64_t", "packed_selectors" } } },
{ 548, "debug_syscall_reject_config", 3, { { "uint64_t", "packed_selectors1" }, { "uint64_t", "packed_selectors2" }, { "uint64_t", "flags" } } },
{ 549, "graftdmg", 4, { { "int", "dmg_fd" }, { "const char *", "mountdir" }, { "uint32_t", "graft_type" }, { "graftdmg_args_un *", "gda" } } },
{ 550, "map_with_linking_np", 4, { { "void *", "regions" }, { "uint32_t", "region_count" }, { "void *", "link_info" }, { "uint32_t", "link_info_size" } } },
{ 551, "freadlink", 3, { { "int", "fd" }, { "user_addr_t", "buf" }, { "user_size_t", "bufsize" } } },
{ 552, "record_system_event", 4, { { "uint32_t", "type" }, { "uint32_t", "subsystem" }, { "const char *", "event" }, { "const char *", "payload" } } },
{ 553, "mkfifoat", 3, { { "int", "fd" }, { "char *", "path" }, { "int", "mode" } } },
{ 554, "mknodat", 4, { { "int", "fd" }, { "char *", "path" }, { "int", "mode" }, { "int", "dev" } } },
{ 555, "ungraftdmg", 2, { { "const char *", "mountdir" }, { "uint64_t", "flags" } } },
{ 556, "coalition_policy_set", 3, { { "uint64_t", "cid" }, { "uint32_t", "flavor" }, { "uint32_t", "value" } } },
{ 557, "coalition_policy_get", 2, { { "uint64_t", "cid" }, { "uint32_t", "flavor" } } },
};
FridaXnuSyscallSignature *
frida_get_xnu_mach_traps (int * len)
{
if (len != NULL)
*len = G_N_ELEMENTS (frida_xnu_mach_traps);
return (FridaXnuSyscallSignature *) frida_xnu_mach_traps;
}
FridaXnuSyscallSignature *
frida_get_xnu_bsd_syscalls (int * len)
{
if (len != NULL)
*len = G_N_ELEMENTS (frida_xnu_bsd_syscalls);
return (FridaXnuSyscallSignature *) frida_xnu_bsd_syscalls;
}
-539
View File
@@ -1,539 +0,0 @@
// AUTO-GENERATED FILE. DO NOT EDIT.
namespace Frida {
public extern unowned XnuSyscallSignature[] get_xnu_mach_traps ();
public extern unowned XnuSyscallSignature[] get_xnu_bsd_syscalls ();
public struct XnuSyscallSignature {
public int nr;
public string name;
public uint8 nargs;
public XnuSyscallArg args[9];
}
public struct XnuSyscallArg {
public string? type;
public string? name;
}
public enum XnuMachTrap {
MACH_VM_ALLOCATE = -10,
MACH_VM_PURGABLE_CONTROL = -11,
MACH_VM_DEALLOCATE = -12,
TASK_DYLD_PROCESS_INFO_NOTIFY_GET = -13,
MACH_VM_PROTECT = -14,
MACH_VM_MAP = -15,
MACH_PORT_ALLOCATE = -16,
MACH_PORT_DEALLOCATE = -18,
MACH_PORT_MOD_REFS = -19,
MACH_PORT_MOVE_MEMBER = -20,
MACH_PORT_INSERT_RIGHT = -21,
MACH_PORT_INSERT_MEMBER = -22,
MACH_PORT_EXTRACT_MEMBER = -23,
MACH_PORT_CONSTRUCT = -24,
MACH_PORT_DESTRUCT = -25,
MACH_REPLY_PORT = -26,
THREAD_SELF = -27,
TASK_SELF = -28,
HOST_SELF = -29,
MACH_MSG = -31,
MACH_MSG_OVERWRITE = -32,
SEMAPHORE_SIGNAL = -33,
SEMAPHORE_SIGNAL_ALL = -34,
SEMAPHORE_SIGNAL_THREAD = -35,
SEMAPHORE_WAIT = -36,
SEMAPHORE_WAIT_SIGNAL = -37,
SEMAPHORE_TIMEDWAIT = -38,
SEMAPHORE_TIMEDWAIT_SIGNAL = -39,
MACH_PORT_GET_ATTRIBUTES = -40,
MACH_PORT_GUARD = -41,
MACH_PORT_UNGUARD = -42,
MACH_GENERATE_ACTIVITY_ID = -43,
TASK_NAME_FOR_PID = -44,
TASK_FOR_PID = -45,
PID_FOR_TASK = -46,
MACH_MSG2 = -47,
MACX_SWAPON = -48,
MACX_SWAPOFF = -49,
THREAD_GET_SPECIAL_REPLY_PORT = -50,
MACX_TRIGGERS = -51,
MACX_BACKING_STORE_SUSPEND = -52,
MACX_BACKING_STORE_RECOVERY = -53,
PFZ_EXIT = -58,
SWTCH_PRI = -59,
SWTCH = -60,
THREAD_SWITCH = -61,
CLOCK_SLEEP = -62,
MACH_VM_RECLAIM_UPDATE_KERNEL_ACCOUNTING = -63,
HOST_CREATE_MACH_VOUCHER = -70,
MACH_VOUCHER_EXTRACT_ATTR_RECIPE = -72,
MACH_PORT_TYPE = -76,
MACH_PORT_REQUEST_NOTIFICATION = -77,
EXCLAVES_CTL = -88,
MACH_TIMEBASE_INFO = -89,
MACH_WAIT_UNTIL = -90,
MK_TIMER_CREATE = -91,
MK_TIMER_DESTROY = -92,
MK_TIMER_ARM = -93,
MK_TIMER_CANCEL = -94,
MK_TIMER_ARM_LEEWAY = -95,
DEBUG_CONTROL_PORT_FOR_PID = -96,
IOKIT_USER_CLIENT = -100,
}
public enum XnuBsdSyscall {
EXIT = 1,
FORK = 2,
READ = 3,
WRITE = 4,
OPEN = 5,
CLOSE = 6,
WAIT4 = 7,
LINK = 9,
UNLINK = 10,
CHDIR = 12,
FCHDIR = 13,
MKNOD = 14,
CHMOD = 15,
CHOWN = 16,
GETFSSTAT = 18,
GETPID = 20,
SETUID = 23,
GETUID = 24,
GETEUID = 25,
PTRACE = 26,
RECVMSG = 27,
SENDMSG = 28,
RECVFROM = 29,
ACCEPT = 30,
GETPEERNAME = 31,
GETSOCKNAME = 32,
ACCESS = 33,
CHFLAGS = 34,
FCHFLAGS = 35,
SYNC = 36,
KILL = 37,
CROSSARCH_TRAP = 38,
GETPPID = 39,
DUP = 41,
PIPE = 42,
GETEGID = 43,
SIGACTION = 46,
GETGID = 47,
SIGPROCMASK = 48,
GETLOGIN = 49,
SETLOGIN = 50,
ACCT = 51,
SIGPENDING = 52,
SIGALTSTACK = 53,
IOCTL = 54,
REBOOT = 55,
REVOKE = 56,
SYMLINK = 57,
READLINK = 58,
EXECVE = 59,
UMASK = 60,
CHROOT = 61,
MSYNC = 65,
VFORK = 66,
OSLOG_COPROC_REG = 67,
OSLOG_COPROC = 68,
MUNMAP = 73,
MPROTECT = 74,
MADVISE = 75,
MINCORE = 78,
GETGROUPS = 79,
SETGROUPS = 80,
GETPGRP = 81,
SETPGID = 82,
SETITIMER = 83,
SWAPON = 85,
GETITIMER = 86,
GETDTABLESIZE = 89,
DUP2 = 90,
FCNTL = 92,
SELECT = 93,
FSYNC = 95,
SETPRIORITY = 96,
SOCKET = 97,
CONNECT = 98,
GETPRIORITY = 100,
BIND = 104,
SETSOCKOPT = 105,
LISTEN = 106,
SIGSUSPEND = 111,
GETTIMEOFDAY = 116,
GETRUSAGE = 117,
GETSOCKOPT = 118,
READV = 120,
WRITEV = 121,
SETTIMEOFDAY = 122,
FCHOWN = 123,
FCHMOD = 124,
SETREUID = 126,
SETREGID = 127,
RENAME = 128,
FLOCK = 131,
MKFIFO = 132,
SENDTO = 133,
SHUTDOWN = 134,
SOCKETPAIR = 135,
MKDIR = 136,
RMDIR = 137,
UTIMES = 138,
FUTIMES = 139,
ADJTIME = 140,
GETHOSTUUID = 142,
SETSID = 147,
GETPGID = 151,
SETPRIVEXEC = 152,
PREAD = 153,
PWRITE = 154,
NFSSVC = 155,
STATFS = 157,
FSTATFS = 158,
UNMOUNT = 159,
GETFH = 161,
FUNMOUNT = 164,
QUOTACTL = 165,
MOUNT = 167,
CSOPS = 169,
CSOPS_AUDITTOKEN = 170,
WAITID = 173,
KDEBUG_TYPEFILTER = 177,
KDEBUG_TRACE_STRING = 178,
KDEBUG_TRACE64 = 179,
KDEBUG_TRACE = 180,
SETGID = 181,
SETEGID = 182,
SETEUID = 183,
SIGRETURN = 184,
PANIC_WITH_DATA = 185,
THREAD_SELFCOUNTS = 186,
FDATASYNC = 187,
STAT = 188,
FSTAT = 189,
LSTAT = 190,
PATHCONF = 191,
FPATHCONF = 192,
GETRLIMIT = 194,
SETRLIMIT = 195,
GETDIRENTRIES = 196,
MMAP = 197,
LSEEK = 199,
TRUNCATE = 200,
FTRUNCATE = 201,
SYSCTL = 202,
MLOCK = 203,
MUNLOCK = 204,
UNDELETE = 205,
OPEN_DPROTECTED_NP = 216,
FSGETPATH_EXT = 217,
OPENAT_DPROTECTED_NP = 218,
GETATTRLIST = 220,
SETATTRLIST = 221,
GETDIRENTRIESATTR = 222,
EXCHANGEDATA = 223,
SEARCHFS = 225,
DELETE = 226,
COPYFILE = 227,
FGETATTRLIST = 228,
FSETATTRLIST = 229,
POLL = 230,
GETXATTR = 234,
FGETXATTR = 235,
SETXATTR = 236,
FSETXATTR = 237,
REMOVEXATTR = 238,
FREMOVEXATTR = 239,
LISTXATTR = 240,
FLISTXATTR = 241,
FSCTL = 242,
INITGROUPS = 243,
POSIX_SPAWN = 244,
FFSCTL = 245,
FHOPEN = 248,
MINHERIT = 250,
SEMSYS = 251,
MSGSYS = 252,
SHMSYS = 253,
SEMCTL = 254,
SEMGET = 255,
SEMOP = 256,
MSGCTL = 258,
MSGGET = 259,
MSGSND = 260,
MSGRCV = 261,
SHMAT = 262,
SHMCTL = 263,
SHMDT = 264,
SHMGET = 265,
SHM_OPEN = 266,
SHM_UNLINK = 267,
SEM_OPEN = 268,
SEM_CLOSE = 269,
SEM_UNLINK = 270,
SEM_WAIT = 271,
SEM_TRYWAIT = 272,
SEM_POST = 273,
SYSCTLBYNAME = 274,
OPEN_EXTENDED = 277,
UMASK_EXTENDED = 278,
STAT_EXTENDED = 279,
LSTAT_EXTENDED = 280,
FSTAT_EXTENDED = 281,
CHMOD_EXTENDED = 282,
FCHMOD_EXTENDED = 283,
ACCESS_EXTENDED = 284,
SETTID = 285,
GETTID = 286,
SETSGROUPS = 287,
GETSGROUPS = 288,
SETWGROUPS = 289,
GETWGROUPS = 290,
MKFIFO_EXTENDED = 291,
MKDIR_EXTENDED = 292,
IDENTITYSVC = 293,
SHARED_REGION_CHECK_NP = 294,
VM_PRESSURE_MONITOR = 296,
PSYNCH_RW_LONGRDLOCK = 297,
PSYNCH_RW_YIELDWRLOCK = 298,
PSYNCH_RW_DOWNGRADE = 299,
PSYNCH_RW_UPGRADE = 300,
PSYNCH_MUTEXWAIT = 301,
PSYNCH_MUTEXDROP = 302,
PSYNCH_CVBROAD = 303,
PSYNCH_CVSIGNAL = 304,
PSYNCH_CVWAIT = 305,
PSYNCH_RW_RDLOCK = 306,
PSYNCH_RW_WRLOCK = 307,
PSYNCH_RW_UNLOCK = 308,
PSYNCH_RW_UNLOCK2 = 309,
GETSID = 310,
SETTID_WITH_PID = 311,
PSYNCH_CVCLRPREPOST = 312,
AIO_FSYNC = 313,
AIO_RETURN = 314,
AIO_SUSPEND = 315,
AIO_CANCEL = 316,
AIO_ERROR = 317,
AIO_READ = 318,
AIO_WRITE = 319,
LIO_LISTIO = 320,
IOPOLICYSYS = 322,
PROCESS_POLICY = 323,
MLOCKALL = 324,
MUNLOCKALL = 325,
ISSETUGID = 327,
PTHREAD_KILL = 328,
PTHREAD_SIGMASK = 329,
SIGWAIT = 330,
DISABLE_THREADSIGNAL = 331,
PTHREAD_MARKCANCEL = 332,
PTHREAD_CANCELED = 333,
SEMWAIT_SIGNAL = 334,
PROC_INFO = 336,
SENDFILE = 337,
STAT64 = 338,
FSTAT64 = 339,
LSTAT64 = 340,
STAT64_EXTENDED = 341,
LSTAT64_EXTENDED = 342,
FSTAT64_EXTENDED = 343,
GETDIRENTRIES64 = 344,
STATFS64 = 345,
FSTATFS64 = 346,
GETFSSTAT64 = 347,
PTHREAD_CHDIR = 348,
PTHREAD_FCHDIR = 349,
AUDIT = 350,
AUDITON = 351,
GETAUID = 353,
SETAUID = 354,
GETAUDIT_ADDR = 357,
SETAUDIT_ADDR = 358,
AUDITCTL = 359,
BSDTHREAD_CREATE = 360,
BSDTHREAD_TERMINATE = 361,
KQUEUE = 362,
KEVENT = 363,
LCHOWN = 364,
BSDTHREAD_REGISTER = 366,
WORKQ_OPEN = 367,
WORKQ_KERNRETURN = 368,
KEVENT64 = 369,
THREAD_SELFID = 372,
LEDGER = 373,
KEVENT_QOS = 374,
KEVENT_ID = 375,
MAC_EXECVE = 380,
MAC_SYSCALL = 381,
MAC_GET_FILE = 382,
MAC_SET_FILE = 383,
MAC_GET_LINK = 384,
MAC_SET_LINK = 385,
MAC_GET_PROC = 386,
MAC_SET_PROC = 387,
MAC_GET_FD = 388,
MAC_SET_FD = 389,
MAC_GET_PID = 390,
PSELECT = 394,
PSELECT_NOCANCEL = 395,
READ_NOCANCEL = 396,
WRITE_NOCANCEL = 397,
OPEN_NOCANCEL = 398,
CLOSE_NOCANCEL = 399,
WAIT4_NOCANCEL = 400,
RECVMSG_NOCANCEL = 401,
SENDMSG_NOCANCEL = 402,
RECVFROM_NOCANCEL = 403,
ACCEPT_NOCANCEL = 404,
MSYNC_NOCANCEL = 405,
FCNTL_NOCANCEL = 406,
SELECT_NOCANCEL = 407,
FSYNC_NOCANCEL = 408,
CONNECT_NOCANCEL = 409,
SIGSUSPEND_NOCANCEL = 410,
READV_NOCANCEL = 411,
WRITEV_NOCANCEL = 412,
SENDTO_NOCANCEL = 413,
PREAD_NOCANCEL = 414,
PWRITE_NOCANCEL = 415,
WAITID_NOCANCEL = 416,
POLL_NOCANCEL = 417,
MSGSND_NOCANCEL = 418,
MSGRCV_NOCANCEL = 419,
SEM_WAIT_NOCANCEL = 420,
AIO_SUSPEND_NOCANCEL = 421,
SIGWAIT_NOCANCEL = 422,
SEMWAIT_SIGNAL_NOCANCEL = 423,
MAC_MOUNT = 424,
MAC_GET_MOUNT = 425,
MAC_GETFSSTAT = 426,
FSGETPATH = 427,
AUDIT_SESSION_SELF = 428,
AUDIT_SESSION_JOIN = 429,
FILEPORT_MAKEPORT = 430,
FILEPORT_MAKEFD = 431,
AUDIT_SESSION_PORT = 432,
PID_SUSPEND = 433,
PID_RESUME = 434,
PID_HIBERNATE = 435,
PID_SHUTDOWN_SOCKETS = 436,
KAS_INFO = 439,
MEMORYSTATUS_CONTROL = 440,
GUARDED_OPEN_NP = 441,
GUARDED_CLOSE_NP = 442,
GUARDED_KQUEUE_NP = 443,
CHANGE_FDGUARD_NP = 444,
USRCTL = 445,
PROC_RLIMIT_CONTROL = 446,
CONNECTX = 447,
DISCONNECTX = 448,
PEELOFF = 449,
SOCKET_DELEGATE = 450,
TELEMETRY = 451,
PROC_UUID_POLICY = 452,
MEMORYSTATUS_GET_LEVEL = 453,
SYSTEM_OVERRIDE = 454,
VFS_PURGE = 455,
SFI_CTL = 456,
SFI_PIDCTL = 457,
COALITION = 458,
COALITION_INFO = 459,
NECP_MATCH_POLICY = 460,
GETATTRLISTBULK = 461,
CLONEFILEAT = 462,
OPENAT = 463,
OPENAT_NOCANCEL = 464,
RENAMEAT = 465,
FACCESSAT = 466,
FCHMODAT = 467,
FCHOWNAT = 468,
FSTATAT = 469,
FSTATAT64 = 470,
LINKAT = 471,
UNLINKAT = 472,
READLINKAT = 473,
SYMLINKAT = 474,
MKDIRAT = 475,
GETATTRLISTAT = 476,
PROC_TRACE_LOG = 477,
BSDTHREAD_CTL = 478,
OPENBYID_NP = 479,
RECVMSG_X = 480,
SENDMSG_X = 481,
THREAD_SELFUSAGE = 482,
CSRCTL = 483,
GUARDED_OPEN_DPROTECTED_NP = 484,
GUARDED_WRITE_NP = 485,
GUARDED_PWRITE_NP = 486,
GUARDED_WRITEV_NP = 487,
RENAMEATX_NP = 488,
MREMAP_ENCRYPTED = 489,
NETAGENT_TRIGGER = 490,
STACK_SNAPSHOT_WITH_CONFIG = 491,
MICROSTACKSHOT = 492,
GRAB_PGO_DATA = 493,
PERSONA = 494,
MACH_EVENTLINK_SIGNAL = 496,
MACH_EVENTLINK_WAIT_UNTIL = 497,
MACH_EVENTLINK_SIGNAL_WAIT_UNTIL = 498,
WORK_INTERVAL_CTL = 499,
GETENTROPY = 500,
NECP_CLIENT_ACTION = 502,
NEXUS_OPEN = 503,
NEXUS_REGISTER = 504,
NEXUS_DEREGISTER = 505,
NEXUS_CREATE = 506,
NEXUS_DESTROY = 507,
NEXUS_GET_OPT = 508,
NEXUS_SET_OPT = 509,
CHANNEL_OPEN = 510,
CHANNEL_GET_INFO = 511,
CHANNEL_SYNC = 512,
CHANNEL_GET_OPT = 513,
CHANNEL_SET_OPT = 514,
ULOCK_WAIT = 515,
ULOCK_WAKE = 516,
FCLONEFILEAT = 517,
FS_SNAPSHOT = 518,
TERMINATE_WITH_PAYLOAD = 520,
ABORT_WITH_PAYLOAD = 521,
NECP_SESSION_ACTION = 523,
SETATTRLISTAT = 524,
NET_QOS_GUIDELINE = 525,
FMOUNT = 526,
NTP_ADJTIME = 527,
NTP_GETTIME = 528,
OS_FAULT_WITH_PAYLOAD = 529,
KQUEUE_WORKLOOP_CTL = 530,
MACH_BRIDGE_REMOTE_TIME = 531,
COALITION_LEDGER = 532,
LOG_DATA = 533,
MEMORYSTATUS_AVAILABLE_MEMORY = 534,
OBJC_BP_ASSIST_CFG_NP = 535,
SHARED_REGION_MAP_AND_SLIDE_2_NP = 536,
PIVOT_ROOT = 537,
TASK_INSPECT_FOR_PID = 538,
TASK_READ_FOR_PID = 539,
PREADV = 540,
PWRITEV = 541,
PREADV_NOCANCEL = 542,
PWRITEV_NOCANCEL = 543,
ULOCK_WAIT2 = 544,
PROC_INFO_EXTENDED_ID = 545,
TRACKER_ACTION = 546,
DEBUG_SYSCALL_REJECT = 547,
DEBUG_SYSCALL_REJECT_CONFIG = 548,
GRAFTDMG = 549,
MAP_WITH_LINKING_NP = 550,
FREADLINK = 551,
RECORD_SYSTEM_EVENT = 552,
MKFIFOAT = 553,
MKNODAT = 554,
UNGRAFTDMG = 555,
COALITION_POLICY_SET = 556,
COALITION_POLICY_GET = 557,
}
}
-11
View File
@@ -1,11 +0,0 @@
FRIDA_1.0 {
local:
*;
};
GLIBC_2.2.5 {
local:
fopen*;
fseeko*;
ftello*;
} FRIDA_1.0;
+2 -8
View File
@@ -9,9 +9,7 @@
# include <signal.h>
#endif
#include <gumjs/gumscriptbackend.h>
#if defined (HAVE_GIOAPPLE)
# include <gioapple.h>
#elif defined (HAVE_GIOOPENSSL)
#ifdef HAVE_GIOOPENSSL
# include <gioopenssl.h>
#endif
@@ -93,9 +91,7 @@ frida_gadget_environment_init (void)
g_thread_set_garbage_handler (_frida_gadget_on_pending_thread_garbage, NULL);
#if defined (HAVE_GIOAPPLE)
g_io_module_apple_register ();
#elif defined (HAVE_GIOOPENSSL)
#ifdef HAVE_GIOOPENSSL
g_io_module_openssl_register ();
#endif
@@ -122,8 +118,6 @@ frida_gadget_environment_deinit (void)
g_assert (worker_loop != NULL);
frida_libc_shim_prepare_to_deinit ();
source = g_idle_source_new ();
g_source_set_priority (source, G_PRIORITY_LOW);
g_source_set_callback (source, stop_worker_loop, NULL, NULL);
+1 -1
View File
@@ -45,7 +45,7 @@ elif host_os_family == 'darwin'
extra_link_args += '-Wl,-exported_symbols_list,' + meson.current_source_dir() / symlist
extra_link_depends += symlist
else
symscript = (libc == 'glibc') ? 'frida-gadget-glibc.version' : 'frida-gadget.version'
symscript = 'frida-gadget.version'
extra_link_args += '-Wl,--version-script,' + meson.current_source_dir() / symscript
extra_link_depends += symscript
endif
+6 -8
View File
@@ -4,12 +4,10 @@ endif
subdir('base')
subdir('netif')
subdir('pipe')
if have_in_tree_payloads
subdir('payload')
if have_local_backend
subdir('agent')
endif
if build_gadget
subdir('gadget')
endif
subdir('payload')
if have_local_backend
subdir('agent')
endif
if build_gadget
subdir('gadget')
endif
+30 -404
View File
@@ -10,7 +10,6 @@
# include <assert.h>
# include <fcntl.h>
# include <unistd.h>
# include <wchar.h>
#endif
#if defined (HAVE_DARWIN)
# include <sys/attr.h>
@@ -24,50 +23,23 @@
# include <xlocale.h>
#endif
#undef __srget
#undef feof
#undef ferror
#undef fgetwc
#undef fopen
#undef fopen64
#undef fputwc
#undef fseek
#undef fseeko
#undef fseeko64
#undef ftell
#undef ftello
#undef ftello64
#undef getc
#undef getc_unlocked
#undef getwc
#undef memcpy
#undef putc
#undef putchar
#undef putwc
#undef setbuf
#undef setbuffer
#undef setlinebuf
#undef snprintf
#undef sprintf
#undef stderr
#undef stdin
#undef stdout
#undef ungetc
#undef ungetwc
#undef vsnprintf
#ifdef HAVE_MUSL
# define FRIDA_STDIO_OPAQUE_FILE 1
#endif
static gboolean frida_deinit_expected = FALSE;
void
frida_libc_shim_prepare_to_deinit (void)
{
frida_deinit_expected = TRUE;
}
#if defined (HAVE_WINDOWS) || defined (HAVE_ASAN)
void
@@ -98,9 +70,6 @@ __attribute__ ((destructor)) static
void
frida_libc_shim_deinit (void)
{
if (!frida_deinit_expected)
return;
# ifdef HAVE_ASAN
gum_deinit ();
# else
@@ -165,18 +134,16 @@ struct _FridaFile
int err;
guint8 * rbuf;
gboolean owns_rbuf;
size_t rcap;
size_t rpos;
size_t rlen;
guint8 * wbuf;
gboolean owns_wbuf;
size_t wcap;
size_t wlen;
guint8 ungot_buf[8];
guint ungot_len;
int ungot;
gboolean has_ungot;
};
struct _FridaFileHandle
@@ -204,10 +171,6 @@ struct _FridaDir
#endif
static FILE * frida_fopen_impl (const char * pathname, const char * mode);
static int frida_fseek_impl (FILE * stream, off_t offset, int whence);
static off_t frida_ftell_impl (FILE * stream);
static void frida_stdio_register_stream (FILE * stream);
static void frida_stdio_unregister_stream (FILE * stream);
#ifdef HAVE_FRIDA_DIR
@@ -230,8 +193,6 @@ static void frida_parse_fopen_mode (const char * mode, int * oflags);
static int frida_write_formatted_to_fd (int fd, const char * format, va_list args);
static gboolean frida_utf8_expected_len (guint8 first, guint * out_len);
#ifdef HAVE_FRIDA_DIR
static FridaDir * frida_dir_get_impl (DIR * dirp);
static DIR * frida_dir_wrap (FridaDir * impl);
@@ -356,9 +317,6 @@ frida_libc_shim_deinit (void)
fflush (NULL);
if (!frida_deinit_expected)
return;
G_LOCK (frida_stdio);
g_hash_table_iter_init (&iter, frida_streams);
@@ -681,34 +639,8 @@ asprintf_l (char ** ret, locale_t loc, const char * format, ...)
#endif
#ifdef HAVE_GLIBC
G_GNUC_INTERNAL FILE *
frida_fopen_glibc_225 (const char * pathname, const char * mode)
{
return frida_fopen_impl (pathname, mode);
}
__asm__ (".symver frida_fopen_glibc_225,fopen@@GLIBC_2.2.5");
G_GNUC_INTERNAL FILE *
frida_fopen64_glibc_225 (const char * pathname, const char * mode)
{
return frida_fopen_impl (pathname, mode);
}
__asm__ (".symver frida_fopen64_glibc_225,fopen64@@GLIBC_2.2.5");
#else
G_GNUC_INTERNAL FILE *
fopen (const char * pathname, const char * mode)
{
return frida_fopen_impl (pathname, mode);
}
#endif
static FILE *
frida_fopen_impl (const char * pathname, const char * mode)
{
FILE * result;
int oflags, fd;
@@ -782,17 +714,8 @@ setvbuf (FILE * stream, char * buf, int mode, size_t size)
if (mode == _IONBF)
{
if (f->owns_rbuf)
g_clear_pointer (&f->rbuf, g_free);
else
f->rbuf = NULL;
f->owns_rbuf = FALSE;
if (f->owns_wbuf)
g_clear_pointer (&f->wbuf, g_free);
else
f->wbuf = NULL;
f->owns_wbuf = FALSE;
g_clear_pointer (&f->rbuf, g_free);
g_clear_pointer (&f->wbuf, g_free);
f->rcap = 0;
f->wcap = 0;
@@ -804,40 +727,13 @@ setvbuf (FILE * stream, char * buf, int mode, size_t size)
}
if (size == 0)
size = BUFSIZ;
if (!f->owns_rbuf)
{
f->rbuf = NULL;
f->rcap = 0;
}
size = FRIDA_STDIO_BUFSIZE;
f->rbuf = g_realloc (f->rbuf, size);
f->owns_rbuf = TRUE;
f->wbuf = g_realloc (f->wbuf, size);
f->rcap = size;
if (buf != NULL)
{
if (f->owns_wbuf)
g_clear_pointer (&f->wbuf, g_free);
f->wbuf = (guint8 *) buf;
f->owns_wbuf = FALSE;
f->wcap = size;
}
else
{
if (!f->owns_wbuf)
{
f->wbuf = NULL;
f->wcap = 0;
}
f->wbuf = g_realloc (f->wbuf, size);
f->owns_wbuf = TRUE;
f->wcap = size;
}
f->wcap = size;
f->rpos = 0;
f->rlen = 0;
f->wlen = 0;
@@ -845,39 +741,6 @@ setvbuf (FILE * stream, char * buf, int mode, size_t size)
return 0;
}
G_GNUC_INTERNAL void
setbuf (FILE * stream, char * buf)
{
if (buf == NULL)
(void) setvbuf (stream, NULL, _IONBF, 0);
else
(void) setvbuf (stream, buf, _IOFBF, BUFSIZ);
}
#if defined (HAVE_DARWIN) || defined (HAVE_ANDROID) || defined (HAVE_FREEBSD)
G_GNUC_INTERNAL int
setlinebuf (FILE * stream)
{
return setvbuf (stream, NULL, _IOLBF, 0);
}
#else
G_GNUC_INTERNAL void
setlinebuf (FILE * stream)
{
setvbuf (stream, NULL, _IOLBF, 0);
}
#endif
G_GNUC_INTERNAL void
#if defined (HAVE_DARWIN) || defined (HAVE_ANDROID) || defined (HAVE_FREEBSD)
setbuffer (FILE * stream, char * buf, int size)
#else
setbuffer (FILE * stream, char * buf, size_t size)
#endif
{
(void) setvbuf (stream, buf, (buf != NULL) ? _IOFBF : _IONBF, size);
}
G_GNUC_INTERNAL int
fflush (FILE * stream)
{
@@ -938,8 +801,11 @@ getc_unlocked (FILE * stream)
f = frida_file_get_impl (stream);
if (f->ungot_len != 0)
return f->ungot_buf[--f->ungot_len];
if (f->has_ungot)
{
f->has_ungot = FALSE;
return f->ungot;
}
if (f->buf_mode == _IONBF)
{
@@ -980,64 +846,6 @@ getc (FILE * stream)
return getc_unlocked (stream);
}
G_GNUC_INTERNAL int
__srget (FILE * stream)
{
return getc_unlocked (stream);
}
G_GNUC_INTERNAL wint_t
getwc (FILE * stream)
{
return fgetwc (stream);
}
G_GNUC_INTERNAL wint_t
fgetwc (FILE * stream)
{
char bytes[4];
guint need, have;
int c;
gunichar ch;
c = getc_unlocked (stream);
if (c == EOF)
return WEOF;
bytes[0] = c;
if (!frida_utf8_expected_len (bytes[0], &need))
{
errno = EILSEQ;
frida_file_get_impl (stream)->err = errno;
return WEOF;
}
have = 1;
while (have != need)
{
c = getc_unlocked (stream);
if (c == EOF)
{
errno = EILSEQ;
frida_file_get_impl (stream)->err = errno;
return WEOF;
}
bytes[have++] = c;
}
ch = g_utf8_get_char_validated (bytes, (gssize) need);
if (ch == (gunichar) -1 || ch == (gunichar) -2)
{
errno = EILSEQ;
frida_file_get_impl (stream)->err = errno;
return WEOF;
}
return (wint_t) ch;
}
G_GNUC_INTERNAL int
ungetc (int c, FILE * stream)
{
@@ -1048,46 +856,16 @@ ungetc (int c, FILE * stream)
if (c == EOF)
return EOF;
if (f->ungot_len == G_N_ELEMENTS (f->ungot_buf))
if (f->has_ungot)
return EOF;
f->ungot_buf[f->ungot_len++] = c;
f->ungot = c;
f->has_ungot = TRUE;
f->eof = FALSE;
return c;
}
G_GNUC_INTERNAL wint_t
ungetwc (wint_t wc, FILE * stream)
{
FridaFile * f;
char tmp[4];
int len;
int i;
if (wc == WEOF)
return WEOF;
f = frida_file_get_impl (stream);
len = g_unichar_to_utf8 ((gunichar) wc, tmp);
if (len <= 0 || len > 4)
{
errno = EILSEQ;
f->err = errno;
return WEOF;
}
if (f->ungot_len + len > G_N_ELEMENTS (f->ungot_buf))
return WEOF;
for (i = 0; i != len; i++)
f->ungot_buf[f->ungot_len++] = tmp[i];
f->eof = FALSE;
return wc;
}
G_GNUC_INTERNAL size_t
fread (void * ptr, size_t size, size_t nmemb, FILE * stream)
{
@@ -1106,9 +884,10 @@ fread (void * ptr, size_t size, size_t nmemb, FILE * stream)
while (got != want)
{
if (f->ungot_len != 0)
if (f->has_ungot)
{
out[got++] = f->ungot_buf[--f->ungot_len];
out[got++] = (guint8) f->ungot;
f->has_ungot = FALSE;
continue;
}
@@ -1227,12 +1006,6 @@ fwrite (const void * ptr, size_t size, size_t nmemb, FILE * stream)
return off / size;
}
G_GNUC_INTERNAL int
putc (int c, FILE * stream)
{
return fputc (c, stream);
}
G_GNUC_INTERNAL int
fputc (int c, FILE * stream)
{
@@ -1246,37 +1019,6 @@ fputc (int c, FILE * stream)
return ch;
}
G_GNUC_INTERNAL wint_t
putwc (wchar_t wc, FILE * stream)
{
return fputwc (wc, stream);
}
G_GNUC_INTERNAL wint_t
fputwc (wchar_t wc, FILE * stream)
{
char tmp[4];
int len;
size_t n;
if (wc == WEOF)
return WEOF;
len = g_unichar_to_utf8 ((gunichar) wc, tmp);
if (len <= 0 || len > 4)
{
errno = EILSEQ;
frida_file_get_impl (stream)->err = errno;
return WEOF;
}
n = fwrite (tmp, 1, len, stream);
if (n != len)
return WEOF;
return (wint_t) wc;
}
G_GNUC_INTERNAL int
fputs (const char * s, FILE * stream)
{
@@ -1320,84 +1062,6 @@ fgets (char * s, int size, FILE * stream)
G_GNUC_INTERNAL int
fseek (FILE * stream, long offset, int whence)
{
return frida_fseek_impl (stream, (off_t) offset, whence);
}
G_GNUC_INTERNAL long
ftell (FILE * stream)
{
off_t pos = frida_ftell_impl (stream);
if (pos == (off_t) -1)
return -1;
return (long) pos;
}
#ifdef HAVE_GLIBC
G_GNUC_INTERNAL int
frida_fseeko_glibc_225 (FILE * stream, off_t offset, int whence)
{
return frida_fseek_impl (stream, offset, whence);
}
__asm__ (".symver frida_fseeko_glibc_225,fseeko@@GLIBC_2.2.5");
G_GNUC_INTERNAL int
frida_fseeko64_glibc_225 (FILE * stream, off_t offset, int whence)
{
return frida_fseek_impl (stream, offset, whence);
}
__asm__ (".symver frida_fseeko64_glibc_225,fseeko64@@GLIBC_2.2.5");
G_GNUC_INTERNAL off_t
frida_ftello_glibc_225 (FILE * stream)
{
return frida_ftell_impl (stream);
}
__asm__ (".symver frida_ftello_glibc_225,ftello@@GLIBC_2.2.5");
G_GNUC_INTERNAL off_t
frida_ftello64_glibc_225 (FILE * stream)
{
return frida_ftell_impl (stream);
}
__asm__ (".symver frida_ftello64_glibc_225,ftello64@@GLIBC_2.2.5");
#else
G_GNUC_INTERNAL int
fseeko (FILE * stream, off_t offset, int whence)
{
return frida_fseek_impl (stream, offset, whence);
}
G_GNUC_INTERNAL off_t
ftello (FILE * stream)
{
return frida_ftell_impl (stream);
}
# ifndef HAVE_QNX
G_GNUC_INTERNAL int
fseeko64 (FILE * stream, off_t offset, int whence)
{
return frida_fseek_impl (stream, offset, whence);
}
G_GNUC_INTERNAL off_t
ftello64 (FILE * stream)
{
return frida_ftell_impl (stream);
}
# endif
#endif
static int
frida_fseek_impl (FILE * stream, off_t offset, int whence)
{
FridaFile * f;
off_t r;
@@ -1409,10 +1073,10 @@ frida_fseek_impl (FILE * stream, off_t offset, int whence)
f->rpos = 0;
f->rlen = 0;
f->ungot_len = 0;
f->has_ungot = FALSE;
f->eof = FALSE;
r = frida_lseek_nointr (f->fd, offset, whence);
r = frida_lseek_nointr (f->fd, (off_t) offset, whence);
if (r == (off_t) -1)
{
f->err = errno;
@@ -1422,8 +1086,8 @@ frida_fseek_impl (FILE * stream, off_t offset, int whence)
return 0;
}
static off_t
frida_ftell_impl (FILE * stream)
G_GNUC_INTERNAL long
ftell (FILE * stream)
{
FridaFile * f;
off_t pos;
@@ -1440,9 +1104,10 @@ frida_ftell_impl (FILE * stream)
if (f->buf_mode != _IONBF)
pos -= (off_t) (f->rlen - f->rpos);
pos -= f->ungot_len;
if (f->has_ungot)
pos -= 1;
return pos;
return (long) pos;
}
G_GNUC_INTERNAL void
@@ -2053,12 +1718,10 @@ frida_file_new (int fd, gboolean close_fd, int buf_mode)
if (buf_mode != _IONBF)
{
f->rcap = FRIDA_STDIO_BUFSIZE;
f->rbuf = g_malloc (f->rcap);
f->owns_rbuf = TRUE;
f->wcap = FRIDA_STDIO_BUFSIZE;
f->rbuf = g_malloc (f->rcap);
f->wbuf = g_malloc (f->wcap);
f->owns_wbuf = TRUE;
}
return f;
@@ -2070,15 +1733,8 @@ frida_file_free (FridaFile * f)
if (f == NULL)
return;
if (f->owns_rbuf)
g_clear_pointer (&f->rbuf, g_free);
else
f->rbuf = NULL;
if (f->owns_wbuf)
g_clear_pointer (&f->wbuf, g_free);
else
f->wbuf = NULL;
g_clear_pointer (&f->rbuf, g_free);
g_clear_pointer (&f->wbuf, g_free);
g_free (f);
}
@@ -2210,36 +1866,6 @@ beach:
}
}
static gboolean
frida_utf8_expected_len (guint8 first, guint * out_len)
{
if (first < 0x80)
{
*out_len = 1;
return TRUE;
}
if ((first & 0xe0) == 0xc0)
{
*out_len = 2;
return TRUE;
}
if ((first & 0xf0) == 0xe0)
{
*out_len = 3;
return TRUE;
}
if ((first & 0xf8) == 0xf0)
{
*out_len = 4;
return TRUE;
}
return FALSE;
}
#ifdef HAVE_FRIDA_DIR
static FridaDir *
-1
View File
@@ -1,5 +1,4 @@
namespace Frida {
public extern void libc_shim_prepare_to_deinit ();
#if DARWIN
public extern void libc_shim_deinit ();
#endif
+73 -285
View File
@@ -224,21 +224,15 @@ helper_name = 'frida-helper' + exe_suffix
agent_name = 'frida-agent' + shlib_suffix
gadget_name = 'frida-gadget' + shlib_suffix
frida_libdir_name = f'frida-@api_version@'
root_asset_dir = get_option('libdir') / frida_libdir_name
root_asset_dir = get_option('libdir') / 'frida'
if host_os_family == 'darwin'
asset_dir = root_asset_dir
default_asset_path_template = get_option('prefix') / get_option('libdir') / frida_libdir_name
elif host_os_family == 'windows'
asset_dir = root_asset_dir / host_abi
asset_dir_modern = root_asset_dir / 'x86_64'
asset_dir_legacy = root_asset_dir / 'x86'
default_asset_path_template = get_option('prefix') / get_option('libdir') / frida_libdir_name / '<arch>'
default_asset_path_template = get_option('prefix') / get_option('libdir') / 'frida'
else
asset_dir = root_asset_dir / host_cpu_mode
asset_dir_modern = root_asset_dir / '64'
asset_dir_legacy = root_asset_dir / '32'
default_asset_path_template = get_option('prefix') / get_option('libdir') / frida_libdir_name / '<arch>'
default_asset_path_template = get_option('prefix') / get_option('libdir') / 'frida' / '<arch>'
endif
asset_path_template = get_option('asset_path_template')
@@ -246,22 +240,11 @@ if asset_path_template == ''
asset_path_template = default_asset_path_template
endif
is_shared = get_option('default_library') == 'shared'
assets_mode = get_option('assets')
if assets_mode == 'auto'
assets_mode = is_shared ? 'installed' : 'embedded'
endif
cdata.set_quoted('FRIDA_LIBDIR', get_option('libdir'))
cdata.set_quoted('FRIDA_LIBDIR_NAME', frida_libdir_name)
if assets_mode == 'embedded'
cdata.set('HAVE_EMBEDDED_ASSETS', 1)
if get_option('assets') == 'embedded'
vala_flags += '--define=HAVE_EMBEDDED_ASSETS'
else
cdata.set_quoted('FRIDA_HELPER_NAME', helper_name)
cdata.set_quoted('FRIDA_AGENT_NAME', agent_name)
cdata.set_quoted('FRIDA_HELPER_PATH', asset_path_template / helper_name)
cdata.set_quoted('FRIDA_AGENT_PATH', asset_path_template / agent_name)
endif
cdata.set('HAVE_' + host_os_family.to_upper(), 1)
@@ -319,31 +302,21 @@ if host_os == 'linux'
endif
cdata.set('HAVE_' + libc.to_upper(), 1)
vala_flags += '--define=' + libc.to_upper()
elif host_os == 'android'
libc = 'bionic'
else
libc = 'other'
endif
if get_option('b_sanitize') == 'address'
cdata.set('HAVE_ASAN', 1)
endif
have_in_tree_payloads = get_option('default_library') != 'shared'
gum_dep = dependency('frida-gum-1.0', default_options: [
'default_library=static',
f'frida_version=@frida_version@',
'gumjs=' + (have_in_tree_payloads ? 'enabled' : 'disabled'),
'inspector=enabled',
'gumjs=enabled',
])
if have_in_tree_payloads
gumjs_dep = dependency('frida-gumjs-1.0', default_options: ['default_library=static'])
endif
gumjs_inspector_dep = dependency('frida-gumjs-inspector-1.0', default_options: ['default_library=static'])
gumjs_dep = dependency('frida-gumjs-1.0')
gumjs_inspector_dep = dependency('frida-gumjs-inspector-1.0')
glib_version_req = '>=2.74'
glib_options = [
'default_library=static',
'cocoa=disabled',
'selinux=disabled',
'xattr=false',
@@ -360,7 +333,6 @@ if optimize_for_prod
endif
gee_options = [
'default_library=static',
'disable-introspection=true',
]
if optimize_for_prod
@@ -368,36 +340,16 @@ if optimize_for_prod
endif
glib_dep = dependency('glib-2.0', version: glib_version_req, default_options: glib_options)
if glib_dep.type_name() == 'internal'
have_shared_glib = get_option('default_library') != 'static'
else
glib_flavor_src = '''
#include <glib.h>
#ifdef GLIB_STATIC_COMPILATION
# error GLib is static
#endif
'''
have_shared_glib = cc.compiles(glib_flavor_src, name: 'compiling with shared GLib', dependencies: [glib_dep])
endif
have_frida_glib = glib_dep.type_name() == 'internal' or cc.has_function('g_thread_set_callbacks', dependencies: [glib_dep])
if have_frida_glib
cdata.set('HAVE_FRIDA_GLIB', 1)
vala_flags += '--define=HAVE_FRIDA_GLIB'
endif
gobject_dep = dependency('gobject-2.0')
gmodule_dep = dependency('gmodule-2.0')
gio_dep = dependency('gio-2.0')
gee_dep = dependency('gee-0.8', default_options: gee_options)
json_glib_dep = dependency('json-glib-1.0', version: '>=1.8', default_options: [
'default_library=static',
'introspection=disabled',
'gtk_doc=disabled',
'tests=false',
])
libsoup_dep = dependency('libsoup-3.0', default_options: [
'default_library=static',
'sqlite:default_library=static',
'gssapi=disabled',
'ntlm=disabled',
'brotli=disabled',
@@ -409,48 +361,19 @@ libsoup_dep = dependency('libsoup-3.0', default_options: [
'tests=false',
'sysprof=disabled',
])
if libsoup_dep.type_name() == 'internal' \
or cc.has_function('soup_websocket_connection_pause_input', dependencies: [libsoup_dep])
vala_flags += '--define=HAVE_SOUP_WEBSOCKET_BACKPRESSURE'
endif
brotlidec_dep = dependency('libbrotlidec', default_options: ['default_library=static'])
capstone_dep = dependency('capstone', default_options: ['default_library=static'])
if capstone_dep.type_name() != 'internal' \
and not cc.has_function('cs_arch_register_x86', dependencies: [capstone_dep])
add_project_arguments(
'-Dcs_arch_register_x86()=',
'-Dcs_arch_register_arm()=',
'-Dcs_arch_register_arm64()=',
'-Dcs_arch_register_mips()=',
language: ['c', 'objc'],
)
endif
brotlidec_dep = dependency('libbrotlidec')
quickjs_dep = dependency('quickjs', required: get_option('barebone_backend'), default_options: [
'default_library=static',
'libc=false',
'bignum=true',
'atomics=disabled',
'stack_check=disabled',
])
lzfse_dep = dependency('lzfse', required: false, default_options: ['default_library=static'])
lzfse_from_system = false
if not lzfse_dep.found() and not meson.is_cross_build()
if cc.has_header_symbol('lzfse.h', 'lzfse_decode_buffer')
lzfse_lib = cc.find_library('lzfse', required: false)
if lzfse_lib.found()
lzfse_dep = declare_dependency(dependencies: lzfse_lib)
lzfse_from_system = true
endif
endif
endif
if not lzfse_dep.found()
lzfse_dep = dependency('lzfse', required: get_option('barebone_backend'), default_options: ['default_library=static'])
endif
lzfse_dep = dependency('lzfse', required: get_option('barebone_backend'))
native_glib_dep = dependency('glib-2.0', version: glib_version_req, native: true, default_options: glib_options)
native_gio_dep = dependency('gio-2.0', native: true)
native_gee_dep = dependency('gee-0.8', native: true, default_options: gee_options)
native_brotlienc_dep = dependency('libbrotlienc', native: true, default_options: ['default_library=static'])
native_brotlienc_dep = dependency('libbrotlienc', native: true)
if host_os_family == 'windows'
gio_windows_dep = dependency('gio-windows-2.0')
@@ -458,10 +381,8 @@ else
gio_unix_dep = dependency('gio-unix-2.0')
endif
have_local_backend = get_option('local_backend').allowed()
if host_os_family == 'linux' and have_local_backend
libbpf_dep = dependency('libbpf', default_options: ['default_library=static'])
if host_os_family == 'linux'
libbpf_dep = dependency('libbpf')
endif
if host_os == 'android'
@@ -509,6 +430,7 @@ else
codesign = ''
endif
have_local_backend = get_option('local_backend').allowed()
have_simmy_backend = get_option('simmy_backend') \
.disable_auto_if(host_os != 'macos') \
.require(host_os == 'macos', error_message: 'Simmy backend is only available on macOS') \
@@ -527,7 +449,6 @@ have_barebone_backend = get_option('barebone_backend') \
compiler_backend_opt = get_option('compiler_backend') \
.disable_auto_if(host_os == 'watchos')
have_compiler_backend = false
compiler_backend_mode = ''
if compiler_backend_opt.allowed()
go = find_program('go', native: true, required: false)
if go.found()
@@ -538,13 +459,9 @@ if compiler_backend_opt.allowed()
files('tools' / 'cgo' / 'detect.py'),
go,
host_os,
host_os_family,
host_abi,
libc,
exe_suffix,
shlib_suffix,
cc.get_id(),
assets_mode,
'>>>', cc.cmd_array(), '<<<',
'>>>', ar, '<<<',
'>>>', nm, '<<<',
@@ -557,29 +474,12 @@ if compiler_backend_opt.allowed()
status = lines[0]
if status == 'ok'
have_compiler_backend = true
cdata.set('HAVE_COMPILER_BACKEND', 1)
compiler_backend_mode = lines[1]
go_config = lines[2]
if compiler_backend_mode == 'c-archive'
vala_flags += '--define=COMPILER_BACKEND_LINKED'
cdata.set('HAVE_COMPILER_BACKEND_LINKED', 1)
elif compiler_backend_mode == 'c-shared'
if assets_mode == 'installed'
vala_flags += '--define=COMPILER_BACKEND_INSTALLED_LIBRARY'
cdata.set_quoted('FRIDA_COMPILER_BACKEND_NAME', 'frida-compiler-backend' + shlib_suffix)
else
vala_flags += '--define=COMPILER_BACKEND_EMBEDDED_LIBRARY'
endif
elif compiler_backend_mode == 'pie'
if assets_mode == 'installed'
vala_flags += '--define=COMPILER_BACKEND_INSTALLED_EXECUTABLE'
cdata.set_quoted('FRIDA_COMPILER_BACKEND_NAME', 'frida-compiler-backend' + exe_suffix)
else
vala_flags += '--define=COMPILER_BACKEND_EMBEDDED_EXECUTABLE'
endif
else
error('Unsupported compiler backend mode: ' + compiler_backend_mode)
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]
@@ -648,10 +548,8 @@ endif
gi_dep = dependency('gobject-introspection-1.0', required: false)
if gi_dep.found()
girdir = gi_dep.get_variable('girdir')
typelibdir = gi_dep.get_variable('typelibdir')
else
girdir = get_option('prefix') / get_option('datadir') / 'gir-1.0'
typelibdir = get_option('prefix') / get_option('libdir') / 'girepository-1.0'
endif
vapidir = get_option('prefix') / get_option('datadir') / 'vala' / 'vapi'
@@ -660,15 +558,12 @@ gum_vala_args = [
'--pkg=frida-gum-1.0',
'--vapidir=' + gum_dep.get_variable('frida_vapidir'),
]
gumjs_vala_args = ['--pkg=frida-gumjs-1.0', '--pkg=gio-2.0', gum_vala_args]
gumjs_inspector_vala_args = ['--pkg=frida-gumjs-inspector-1.0', gum_vala_args]
if have_in_tree_payloads
gumjs_vala_args = ['--pkg=frida-gumjs-1.0', '--pkg=gio-2.0', gum_vala_args]
have_v8 = gumjs_dep.get_variable('gumjs_v8') == 'enabled'
if have_v8
vala_flags += ['--define=HAVE_V8']
endif
have_v8 = gumjs_dep.get_variable('gumjs_v8') == 'enabled'
if have_v8
vala_flags += ['--define=HAVE_V8']
endif
backend_deps_private = []
@@ -676,7 +571,6 @@ backend_reqs_private = []
backend_libs_private = []
openssl_options = [
'default_library=static',
'cli=disabled',
]
if host_os_family == 'windows' and cc.get_argument_syntax() != 'msvc'
@@ -689,48 +583,25 @@ openssl_dep = dependency('openssl',
)
if have_fruity_backend
backend_deps_private += dependency('libnghttp2', default_options: ['default_library=static'])
backend_reqs_private += 'libnghttp2'
foreach dep : ['libnghttp2', 'libngtcp2', 'libngtcp2_crypto_quictls', 'libusb-1.0']
backend_deps_private += dependency(dep)
backend_reqs_private += dep
endforeach
if host_os != 'macos'
backend_deps_private += dependency('libngtcp2', default_options: ['default_library=static'])
backend_reqs_private += 'libngtcp2'
ngtcp2_crypto_quictls_dep = dependency('libngtcp2_crypto_quictls', required: false, default_options: ['default_library=static'])
if ngtcp2_crypto_quictls_dep.found()
backend_deps_private += ngtcp2_crypto_quictls_dep
backend_reqs_private += 'libngtcp2_crypto_quictls'
else
backend_deps_private += dependency('libngtcp2_crypto_ossl', default_options: ['default_library=static'])
backend_reqs_private += 'libngtcp2_crypto_ossl'
vala_flags += '--define=HAVE_NGTCP2_CRYPTO_OSSL'
endif
if have_frida_glib
libusb_dep = dependency('libusb-1.0', default_options: ['default_library=static'])
else
subproject('libusb', default_options: ['default_library=static'])
libusb_dep = dependency('libusb-1.0', default_options: ['default_library=static'])
endif
backend_deps_private += libusb_dep
backend_reqs_private += 'libusb-1.0'
lwip_options = [
'default_library=static',
'ipv4=disabled',
'ipv6=enabled',
'dns=disabled',
'arp=disabled',
'ethernet=enabled',
]
if optimize_for_prod
lwip_options += 'lwip_debug=disabled'
else
lwip_options += 'lwip_debug=enabled'
endif
backend_deps_private += dependency('lwip', default_options: lwip_options)
backend_reqs_private += 'lwip'
lwip_options = [
'ipv4=disabled',
'ipv6=enabled',
'dns=disabled',
'arp=disabled',
'ethernet=enabled',
]
if optimize_for_prod
lwip_options += 'lwip_debug=disabled'
else
lwip_options += 'lwip_debug=enabled'
endif
backend_deps_private += dependency('lwip', default_options: lwip_options)
backend_reqs_private += 'lwip'
endif
if quickjs_dep.found()
@@ -740,14 +611,10 @@ endif
if lzfse_dep.found()
backend_deps_private += lzfse_dep
if lzfse_from_system
backend_libs_private += '-llzfse'
else
backend_reqs_private += 'lzfse'
endif
backend_reqs_private += 'lzfse'
endif
if host_os_family == 'linux' and have_local_backend
if host_os_family == 'linux'
backend_deps_private += libbpf_dep
backend_reqs_private += 'libbpf'
endif
@@ -758,87 +625,43 @@ endif
if host_os == 'android'
termux_elf_cleaner = find_program('termux-elf-cleaner', native: true)
libselinux_dep = dependency('libselinux', version: '>=3.0', default_options: ['default_library=static'])
libsepol_dep = dependency('libsepol', version: '>=3.0', default_options: ['default_library=static'])
libselinux_dep = dependency('libselinux', version: '>=3.0')
libsepol_dep = dependency('libsepol', version: '>=3.0')
backend_deps_private += [libselinux_dep, libsepol_dep]
backend_reqs_private += ['libselinux', 'libsepol']
else
termux_elf_cleaner = []
endif
tls_provider_dep = dependency('gioopenssl', required: get_option('connectivity'), default_options: [
'gnutls=disabled',
'openssl=enabled',
'libproxy=disabled',
'gnome_proxy=disabled',
'tests=false',
])
tls_provider_vala_args = []
if have_shared_glib
tls_provider_dep = gio_dep
else
use_apple_tls = false
if host_os_family == 'darwin'
apple_tls_deployment_check = '''
#include <Availability.h>
#if defined (__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 150000
# error macOS deployment target below 15.0
#endif
#if defined (__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 180000
# error iOS deployment target below 18.0
#endif
#if defined (__TV_OS_VERSION_MIN_REQUIRED) && __TV_OS_VERSION_MIN_REQUIRED < 180000
# error tvOS deployment target below 18.0
#endif
#if defined (__WATCH_OS_VERSION_MIN_REQUIRED) && __WATCH_OS_VERSION_MIN_REQUIRED < 110000
# error watchOS deployment target below 11.0
#endif
'''
use_apple_tls = cc.compiles(apple_tls_deployment_check, name: 'Apple TLS backend deployment target')
endif
if use_apple_tls
tls_provider_name = 'gioapple'
tls_provider_define_name = 'HAVE_GIOAPPLE'
tls_provider_backend_options = [
'gnutls=disabled',
'openssl=disabled',
'apple=enabled',
]
else
tls_provider_name = 'gioopenssl'
tls_provider_define_name = 'HAVE_GIOOPENSSL'
tls_provider_backend_options = [
'gnutls=disabled',
'openssl=enabled',
'apple=disabled',
]
endif
tls_provider_dep = dependency(tls_provider_name,
required: get_option('connectivity'),
default_options: tls_provider_backend_options + [
'libproxy=disabled',
'gnome_proxy=disabled',
'tests=false',
],
)
if tls_provider_dep.found()
tls_provider_vala_args += [
'--pkg=' + tls_provider_name,
'--vapidir=' + tls_provider_dep.get_variable('vapidir'),
]
cdata.set(tls_provider_define_name, 1)
vala_flags += ['--define=' + tls_provider_define_name]
backend_deps_private += tls_provider_dep
backend_reqs_private += tls_provider_name
endif
if tls_provider_dep.found()
tls_provider_vala_args += [
'--pkg=gioopenssl',
'--vapidir=' + tls_provider_dep.get_variable('vapidir'),
]
cdata.set('HAVE_GIOOPENSSL', 1)
vala_flags += ['--define=HAVE_GIOOPENSSL']
backend_deps_private += tls_provider_dep
backend_reqs_private += 'gioopenssl'
endif
nice_dep = dependency('nice', required: get_option('connectivity'), default_options: [
'default_library=static',
'gupnp=disabled',
'gstreamer=disabled',
'crypto-library=auto',
'crypto-library=openssl',
'examples=disabled',
'tests=disabled',
'introspection=disabled',
])
if nice_dep.found()
usrsctp_dep = dependency('usrsctp', default_options: [
'default_library=static',
'sctp_inet=false',
'sctp_inet6=false',
'sctp_build_programs=false',
@@ -846,12 +669,8 @@ if nice_dep.found()
cdata.set('HAVE_NICE', 1)
vala_flags += ['--define=HAVE_NICE']
backend_deps_private += [nice_dep, usrsctp_dep]
backend_reqs_private += ['nice', 'usrsctp']
if host_os != 'macos'
backend_deps_private += openssl_dep
backend_reqs_private += 'openssl'
endif
backend_deps_private += [nice_dep, openssl_dep, usrsctp_dep]
backend_reqs_private += ['nice', 'openssl', 'usrsctp']
if host_os_family in ['darwin', 'freebsd', 'qnx']
cdata.set('HAVE_SCONN_LEN', 1)
@@ -861,10 +680,10 @@ else
endif
if host_os_family == 'windows'
backend_libs_private += ['-lsetupapi', '-lshlwapi']
backend_libs_private += ['-lsetupapi']
endif
if host_os_family == 'darwin'
backend_libs_private += ['-Wl,-framework,Foundation', '-Wl,-framework,CoreFoundation', '-lbsm']
backend_libs_private += ['-Wl,-framework,Foundation', '-lbsm']
endif
if host_os == 'macos'
backend_libs_private += ['-Wl,-framework,AppKit']
@@ -934,19 +753,6 @@ post_process = [
'@INPUT0@',
]
executable_no_exports_link_args = []
executable_no_exports_link_depends = []
if host_os_family == 'darwin'
script = meson.project_source_root() / 'tools' / 'executable-no-exports.symbols'
executable_no_exports_link_args = ['-Wl,-exported_symbols_list,' + script]
executable_no_exports_link_depends = [script]
elif host_os_family != 'windows'
script_name = (host_os == 'freebsd') ? 'executable-no-exports-freebsd.version' : 'executable-no-exports.version'
script = meson.project_source_root() / 'tools' / script_name
executable_no_exports_link_args = ['-Wl,--version-script,' + script]
executable_no_exports_link_depends = [script]
endif
compile_js_agent = files('tools' / 'compile-js-agent.py')
mapper_opt = get_option('mapper')
@@ -977,20 +783,11 @@ if cc.get_id() == 'gcc' and cc.compiles('#if __GNUC__ >= 5\n#error NOTNEEDED\n#e
add_project_arguments('-w', language: 'c')
endif
local_vapidir = meson.current_source_dir() / 'vapi'
vapidir = meson.current_source_dir() / 'vapi'
vala_flags += [
'--vapidir=' + local_vapidir,
'--vapidir=' + vapidir,
'--pkg', 'config',
]
if gee_dep.type_name() not in ['internal', 'cmake']
gee_prefix = gee_dep.get_variable('prefix', default_value: '')
if gee_prefix != ''
gee_vapidir = gee_prefix / 'share' / 'vala' / 'vapi'
if fs.is_dir(gee_vapidir)
vala_flags += '--vapidir=' + gee_vapidir
endif
endif
endif
vala_flags += '--define=' + host_os_family.to_upper()
if host_os != host_os_family
@@ -1002,22 +799,13 @@ if host_abi != host_arch
endif
vala_flags += '--define=' + host_machine.endian().to_upper() + '_ENDIAN'
add_project_arguments(vala_flags, language: 'vala')
add_project_arguments('-I' + local_vapidir, language: 'c')
add_project_arguments('-I' + vapidir, language: 'c')
native_vala_flags = [
'--vapidir=' + local_vapidir,
'--vapidir=' + meson.current_source_dir() / 'vapi',
]
if native_gee_dep.type_name() not in ['internal', 'cmake']
native_gee_prefix = native_gee_dep.get_variable('prefix', default_value: '')
if native_gee_prefix != ''
native_gee_vapidir = native_gee_prefix / 'share' / 'vala' / 'vapi'
if fs.is_dir(native_gee_vapidir)
native_vala_flags += '--vapidir=' + native_gee_vapidir
endif
endif
endif
add_project_arguments(native_vala_flags, language: 'vala', native: true)
add_project_arguments('-I' + local_vapidir, language: 'c', native: true)
add_project_arguments('-I' + vapidir, language: 'c', native: true)
subdir('compat')
subdir('tools')
@@ -1052,7 +840,7 @@ summary(
summary(
{
'compat': compat_summary,
'assets': assets_mode,
'assets': get_option('assets'),
'mapper': have_mapper,
'connectivity': tls_provider_dep.found(),
'gadget': build_gadget,
+2 -2
View File
@@ -48,8 +48,8 @@ option('compiler_backend',
option('assets',
type: 'combo',
choices: ['auto', 'embedded', 'installed'],
value: 'auto',
choices: ['embedded', 'installed'],
value: 'embedded',
description: 'Whether assets such as frida-agent should be embedded vs installed and loaded at runtime'
)
+1
View File
@@ -0,0 +1 @@
# No exported symbols.
+9
View File
@@ -0,0 +1,9 @@
{
global:
# FreeBSD needs these two:
__progname;
environ;
local:
*;
};
+14 -2
View File
@@ -2,6 +2,18 @@ portal_sources = [
'portal.vala',
]
extra_link_args = []
extra_link_depends = []
if host_os_family == 'darwin'
symlist = 'frida-portal.symbols'
extra_link_args += ['-Wl,-exported_symbols_list,' + meson.current_source_dir() / symlist]
extra_link_depends += [symlist]
elif host_os_family != 'windows'
symscript = 'frida-portal.version'
extra_link_args += ['-Wl,--version-script,' + meson.current_source_dir() / symscript]
extra_link_depends += [symscript]
endif
extra_deps = []
if tls_provider_dep.found()
extra_deps += tls_provider_dep
@@ -9,8 +21,8 @@ endif
raw_portal = executable('frida-portal-raw', portal_sources,
vala_args: [core_vala_args, tls_provider_vala_args, '--pkg=posix'],
link_args: executable_no_exports_link_args,
link_depends: executable_no_exports_link_depends,
link_args: extra_link_args,
link_depends: extra_link_depends,
dependencies: [core_dep] + extra_deps,
)
+1 -3
View File
@@ -39,9 +39,7 @@ namespace Frida.Portal {
};
private static int main (string[] args) {
#if HAVE_GIOAPPLE
GIOApple.register ();
#elif HAVE_GIOOPENSSL
#if HAVE_GIOOPENSSL
GIOOpenSSL.register ();
#endif
+1 -1
Submodule releng updated: c1c778ea2d...7ed66fe687.
-11
View File
@@ -1,11 +0,0 @@
{
global:
# FreeBSD needs these two:
__progname;
environ;
# Allow users to load the server as a shared library with dlopen() and call main() directly
main;
local:
*;
};
+1 -2
View File
@@ -1,2 +1 @@
# Allow users to load the server as a shared library with dlopen() and call main() directly
_main
# No exported symbols.
+3
View File
@@ -1,5 +1,8 @@
{
global:
# FreeBSD needs these two:
__progname;
environ;
# Allow users to load the server as a shared library with dlopen() and call main() directly
main;
+3 -8
View File
@@ -19,7 +19,7 @@ if host_os_family == 'darwin'
extra_link_args += ['-Wl,-exported_symbols_list,' + meson.current_source_dir() / symlist]
extra_link_depends += [symlist]
elif host_os_family != 'windows'
symscript = (host_os == 'freebsd') ? 'frida-server-freebsd.version' : 'frida-server.version'
symscript = 'frida-server.version'
extra_link_args += ['-Wl,--version-script,' + meson.current_source_dir() / symscript]
extra_link_depends += [symscript]
endif
@@ -29,20 +29,15 @@ if host_os == 'macos'
extra_link_depends += [server_plist]
endif
server_deps = [core_dep]
if host_os_family == 'darwin'
server_deps += dependency('appleframeworks', modules: ['CoreFoundation'])
endif
raw_server = executable('frida-server-raw', server_sources,
vala_args: [core_vala_args, '--pkg=posix'],
link_args: extra_link_args,
link_depends: extra_link_depends,
dependencies: server_deps,
dependencies: [core_dep],
)
server_name = 'frida-server' + exe_suffix
need_universal_server = assets_mode == 'installed' and server_compat != ''
need_universal_server = get_option('assets') == 'installed' and server_compat != ''
server = custom_target('frida-server',
input: [raw_server, 'frida-server.xcent'],
+1 -1
View File
@@ -11,7 +11,7 @@ helper.dex: build/frida-helper.jar
$<
mv build/classes.dex $@
build/frida-helper.jar: re/frida/Helper.java re/frida/HelperBackend.java
build/frida-helper.jar: re/frida/Helper.java
javac \
-cp .:$(android_jar) \
-bootclasspath $(android_jar) \
+77 -93
View File
@@ -1,12 +1,66 @@
namespace Frida {
public sealed class AndroidHelperClient : Object {
public AndroidHelperTransport transport {
public sealed class AndroidHelperClient : Object, AsyncInitable {
public signal void closed ();
public IOStream stream {
get;
construct;
}
public AndroidHelperClient (AndroidHelperTransport transport) {
Object (transport: transport);
private BufferedInputStream input;
private OutputStream output;
private Cancellable io_cancellable = new Cancellable ();
private State state = CLOSED;
private Gee.Queue<Request> pending_requests = new Gee.ArrayQueue<Request> ();
private ByteArray pending_output = new ByteArray ();
private bool writing = false;
private enum State {
CLOSED,
OPEN
}
private const uint32 MAX_RESPONSE_SIZE = 100 * 1024 * 1024;
public AndroidHelperClient (IOStream stream) {
Object (stream: stream);
}
construct {
input = (BufferedInputStream) Object.new (typeof (BufferedInputStream),
"base-stream", stream.get_input_stream (),
"close-base-stream", false,
"buffer-size", 128 * 1024);
output = stream.get_output_stream ();
state = OPEN;
process_incoming_responses.begin ();
}
public async void close (Cancellable? cancellable) throws IOError {
io_cancellable.cancel ();
var source = new IdleSource ();
source.set_callback (close.callback);
source.attach (MainContext.get_thread_default ());
yield;
try {
yield stream.close_async (Priority.DEFAULT, cancellable);
} catch (IOError e) {
}
ensure_closed ();
}
private void ensure_closed () {
if (state == CLOSED)
return;
state = CLOSED;
closed ();
}
public async HostApplicationInfo get_frontmost_application (FrontmostQueryOptions options,
@@ -18,12 +72,12 @@ namespace Frida {
.add_string_value (options.scope.to_nick ())
.end_array ();
Json.Node response = yield transport.request (stanza.get_root (), cancellable);
Json.Node response = yield request (stanza.get_root (), cancellable);
if (response.is_null ())
return HostApplicationInfo.empty ();
Json.Reader reader = make_json_reader_from_node (response);
Json.Reader reader = new Json.Reader (response);
string? identifier = null;
string? name = null;
@@ -73,9 +127,9 @@ namespace Frida {
.add_string_value (options.scope.to_nick ())
.end_array ();
Json.Node response = yield transport.request (stanza.get_root (), cancellable);
Json.Node response = yield request (stanza.get_root (), cancellable);
Json.Reader reader = make_json_reader_from_node (response);
Json.Reader reader = new Json.Reader (response);
int num_apps = reader.count_elements ();
if (num_apps == -1)
@@ -139,9 +193,9 @@ namespace Frida {
.add_string_value (options.scope.to_nick ())
.end_array ();
Json.Node response = yield transport.request (stanza.get_root (), cancellable);
Json.Node response = yield request (stanza.get_root (), cancellable);
Json.Reader reader = make_json_reader_from_node (response);
Json.Reader reader = new Json.Reader (response);
int num_processes = reader.count_elements ();
if (num_processes == -1)
@@ -193,9 +247,9 @@ namespace Frida {
.add_int_value (uid)
.end_array ();
Json.Node response = yield transport.request (stanza.get_root (), cancellable);
Json.Node response = yield request (stanza.get_root (), cancellable);
var r = make_json_reader_from_node (response);
var r = new Json.Reader (response);
parse_envelope_or_throw (r);
r.read_element (1);
@@ -263,9 +317,9 @@ namespace Frida {
.add_int_value (uid)
.end_array ();
Json.Node response = yield transport.request (stanza.get_root (), cancellable);
Json.Node response = yield request (stanza.get_root (), cancellable);
var r = make_json_reader_from_node (response);
var r = new Json.Reader (response);
parse_envelope_or_throw (r);
}
@@ -277,9 +331,9 @@ namespace Frida {
.add_int_value ((int) pid)
.end_array ();
Json.Node response = yield transport.request (stanza.get_root (), cancellable);
Json.Node response = yield request (stanza.get_root (), cancellable);
var r = make_json_reader_from_node (response);
var r = new Json.Reader (response);
parse_envelope_or_throw (r);
r.read_element (1);
@@ -289,13 +343,6 @@ namespace Frida {
return r.get_boolean_value ();
}
private async void request_ok (Json.Builder stanza, Cancellable? cancellable) throws Error, IOError {
Json.Node response = yield transport.request (stanza.get_root (), cancellable);
var r = make_json_reader_from_node (response);
parse_envelope_or_throw (r);
}
private void parse_envelope_or_throw (Json.Reader r) throws Error {
r.read_element (0);
string? kind = r.get_string_value ();
@@ -405,76 +452,6 @@ namespace Frida {
throw new Error.PROTOCOL ("Unexpected JSON type: %s", type.name ());
}
}
public interface AndroidHelperTransport : Object {
public abstract async void close (Cancellable? cancellable) throws IOError;
public abstract async Json.Node request (Json.Node stanza, Cancellable? cancellable) throws Error, IOError;
}
public sealed class AndroidHelperStreamTransport : Object, AndroidHelperTransport {
public signal void closed ();
public IOStream stream {
get;
construct;
}
private BufferedInputStream input;
private OutputStream output;
private Cancellable io_cancellable = new Cancellable ();
private State state = CLOSED;
private Gee.Queue<Request> pending_requests = new Gee.ArrayQueue<Request> ();
private ByteArray pending_output = new ByteArray ();
private bool writing = false;
private enum State {
CLOSED,
OPEN
}
private const uint32 MAX_RESPONSE_SIZE = 100 * 1024 * 1024;
public AndroidHelperStreamTransport (IOStream stream) {
Object (stream: stream);
}
construct {
input = (BufferedInputStream) Object.new (typeof (BufferedInputStream),
"base-stream", stream.get_input_stream (),
"close-base-stream", false,
"buffer-size", 128 * 1024);
output = stream.get_output_stream ();
state = OPEN;
process_incoming_responses.begin ();
}
public async void close (Cancellable? cancellable) throws IOError {
io_cancellable.cancel ();
var source = new IdleSource ();
source.set_callback (close.callback);
source.attach (MainContext.get_thread_default ());
yield;
try {
yield stream.close_async (Priority.DEFAULT, cancellable);
} catch (IOError e) {
}
ensure_closed ();
}
private void ensure_closed () {
if (state == CLOSED)
return;
state = CLOSED;
closed ();
}
public async Json.Node request (Json.Node stanza, Cancellable? cancellable) throws Error, IOError {
if (state == CLOSED)
@@ -510,6 +487,13 @@ namespace Frida {
return r.response;
}
private async void request_ok (Json.Builder stanza, Cancellable? cancellable) throws Error, IOError {
Json.Node response = yield request (stanza.get_root (), cancellable);
var r = new Json.Reader (response);
parse_envelope_or_throw (r);
}
private void write_request (Json.Node request) {
string request_str = Json.to_string (request, false);
uint8[] request_data = request_str.data;
Binary file not shown.
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+37 -70
View File
@@ -23,49 +23,57 @@ CORE_TAG_METHOD = f"{{{CORE_NAMESPACE}}}method"
OBJECT_TYPE_PATTERN = re.compile(r"\bpublic\s+(sealed )?(class|interface)\s+(\w+)\b")
TOPLEVEL_NAMES = [
"frida.vala",
"package-manager.vala",
"control-service.vala",
"portal-service.vala",
"file-monitor.vala",
Path("compiler") / "compiler.vala",
]
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', 'symbol-maps'], default='bundle')
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'))
parser.add_argument('core_vapi', metavar='/path/to/frida-core.vapi', type=argparse.FileType('r', encoding='utf-8'))
parser.add_argument('base_header', metavar='/path/to/frida-base.h', type=argparse.FileType('r', encoding='utf-8'))
parser.add_argument('base_gir', metavar='/path/to/FridaBase-x.y.gir', type=argparse.FileType('r', encoding='utf-8'))
parser.add_argument('base_vapi', metavar='/path/to/frida-base.vapi', type=argparse.FileType('r', encoding='utf-8'))
parser.add_argument('output_dir', metavar='/output/dir')
parser.add_argument('extra_args', nargs='*')
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()
core_vapi = args.core_vapi.read()
base_header = args.base_header.read()
base_gir = args.base_gir.read()
base_vapi = args.base_vapi.read()
output_dir = Path(args.output_dir)
if output_type == 'symbol-maps':
emit_symbol_maps_from_source(output_dir)
return
extra = args.extra_args
frida_version = extra[0]
frida_version_components = tuple(extra[1:5])
api_version = extra[5]
if output_type == 'vapi-stamp':
(output_dir / f"frida-core-{api_version}.vapi.stamp").write_bytes(b"")
return
core_header = Path(extra[6]).read_text(encoding='utf-8')
core_gir = Path(extra[7]).read_text(encoding='utf-8')
core_vapi = Path(extra[8]).read_text(encoding='utf-8')
base_header = Path(extra[9]).read_text(encoding='utf-8')
base_gir = Path(extra[10]).read_text(encoding='utf-8')
base_vapi = Path(extra[11]).read_text(encoding='utf-8')
toplevel_names = [
"frida.vala",
"package-manager.vala",
"control-service.vala",
"portal-service.vala",
"file-monitor.vala",
Path("compiler") / "compiler.vala",
]
toplevel_sources = []
src_dir = Path(__file__).parent.parent.resolve()
for name in TOPLEVEL_NAMES:
for name in toplevel_names:
toplevel_sources.append((src_dir / name).read_text(encoding='utf-8'))
toplevel_code = "\n".join(toplevel_sources)
@@ -241,29 +249,6 @@ def emit_gir(api: ApiSpec, core_gir: str, base_gir: str, output_dir: Path) -> st
merge_and_transform_elements("interface", object_type_names)
merge_and_transform_elements("enumeration", enum_type_names | error_type_names)
for source_root in [core_root, base_root]:
for record in source_root.findall(".//record", GIR_NAMESPACES):
owner = record.get(f"{{{GLIB_NAMESPACE}}}is-gtype-struct-for")
if owner is not None and owner in object_type_names:
merged_namespace.append(record)
known_names = object_type_names | enum_type_names | error_type_names
referenced_names = set()
for elem in merged_namespace.iter():
type_name = elem.get("name")
if type_name is None:
continue
for prefix in ("Frida.", "FridaBase."):
if type_name.startswith(prefix):
referenced_names.add(type_name[len(prefix):])
break
needed_names = referenced_names - known_names
for source_root in [core_root, base_root]:
source_namespace = source_root.find("namespace", GIR_NAMESPACES)
for callback in source_namespace.findall("callback", GIR_NAMESPACES):
if callback.get("name") in needed_names:
merged_namespace.append(callback)
ET.indent(merged_root, space=" ")
result = ET.tostring(merged_root,
encoding="unicode",
@@ -319,17 +304,6 @@ def emit_vapi(api, output_dir):
output_deps_file.write("gobject-2.0\n")
output_deps_file.write("gio-2.0\n")
def emit_symbol_maps_from_source(output_dir: Path):
with OutputFile(output_dir / 'frida-core.version') as f:
f.write("{\n")
f.write(" global:\n")
f.write(" frida_*;\n")
f.write(" _frida_*;\n")
f.write("\n")
f.write(" local:\n")
f.write(" *;\n")
f.write("};\n")
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
@@ -351,9 +325,6 @@ def parse_api(frida_version, frida_version_components, api_version, toplevel_cod
"EndpointParameters": "PortalService",
"AuthenticationService": "EndpointParameters",
"StaticAuthenticationService": "AuthenticationService",
"WebRequestHandler": "StaticAuthenticationService",
"WebRequest": "WebRequestHandler",
"WebResponse": "WebRequest",
}
internal_type_prefixes = [
"AgentMessageKind",
@@ -448,7 +419,7 @@ def parse_api(frida_version, frida_version_components, api_version, toplevel_cod
object_type.c_method_prototypes.append(method_cprototype)
elif method_name == 'get_type':
object_type.c_get_type = method_cprototype.replace("G_GNUC_CONST ;", "G_GNUC_CONST;")
for d in re.finditer(r"^typedef.+?\(\*(" + object_type.c_name + r".+?)\) \(.+\);$", all_headers, re.MULTILINE):
for d in re.finditer(r"^typedef.+?\(\*(" + object_type.c_name + r".+?)\) \(.+\);$", core_header, re.MULTILINE):
delegate_cname = d.group(1)
if delegate_cname not in seen_cdelegates:
seen_cdelegates.add(delegate_cname)
@@ -539,8 +510,6 @@ def function_is_public(name):
"generate_certificate",
"get_dbus_context",
"invalidate_dbus_context",
"make_json_reader",
"make_json_reader_from_node",
"make_parameters_dict",
"compute_system_parameters",
"parse_control_address",
@@ -550,8 +519,6 @@ def function_is_public(name):
"check_kernel_version",
"get_syscall_signatures",
"get_compat32_syscall_signatures",
"get_xnu_mach_traps",
"get_xnu_bsd_syscalls",
"make_stdio_pipes",
"make_stdio_pipe",
}
+39 -75
View File
@@ -3,7 +3,6 @@ fs = import('fs')
generate_api = [python, files('generate.py')]
generate_api_args = [
meson.current_build_dir(),
frida_version,
frida_major_version.to_string(),
frida_minor_version.to_string(),
@@ -16,6 +15,7 @@ generate_api_args = [
base_build_dir / 'frida-base.h',
base_build_dir / base_gir_name,
base_build_dir / f'frida-base-@[email protected]',
meson.current_build_dir(),
]
core_api = custom_target('frida-core-api',
@@ -44,24 +44,6 @@ glib_gir = fs.copyfile('GLib-2.0.gir', install: install_glib_girs, install_dir:
gobject_gir = fs.copyfile('GObject-2.0.gir', install: install_glib_girs, install_dir: girdir)
gio_gir = fs.copyfile('Gio-2.0.gir', install: install_glib_girs, install_dir: girdir)
g_ir_compiler = find_program('g-ir-compiler', required: false)
if g_ir_compiler.found()
custom_target('frida-core-typelib',
command: [
g_ir_compiler,
'--output', '@OUTPUT@',
'--includedir=' + girdir,
'--includedir=' + meson.current_source_dir(),
'@INPUT@',
],
input: core_public_gir,
output: f'Frida-@[email protected]',
depends: core,
install: true,
install_dir: typelibdir,
)
endif
core_public_vapi_stamp = custom_target('frida-core-vapi-stamp',
input: core_public_vapi,
output: f'frida-core-@[email protected]',
@@ -72,26 +54,22 @@ core_public_vapi_stamp = custom_target('frida-core-vapi-stamp',
],
)
if is_shared
core_public_lib = core
else
core_public_lib = custom_target('frida-core-library',
input: [core] + internal_libs,
output: f'libfrida-core-@[email protected]',
command: [
python,
files('merge.py'),
lib,
libtool,
ar,
meson.current_build_dir(),
'@OUTPUT@',
'@INPUT@'
],
install: true,
install_dir: get_option('libdir'),
)
endif
core_public_lib = custom_target('frida-core-library',
input: [core] + internal_libs,
output: f'libfrida-core-@[email protected]',
command: [
python,
files('merge.py'),
lib,
libtool,
ar,
meson.current_build_dir(),
'@OUTPUT@',
'@INPUT@'
],
install: true,
install_dir: get_option('libdir'),
)
core_public_extra_headers = []
if host_os == 'android'
@@ -118,43 +96,29 @@ installed_variables = {
'frida_vapidir': vapidir,
}
core_public_dep_kwargs = {
'sources': [core_public_h, core_public_gir, glib_gir, gobject_gir, gio_gir, core_public_vapi_stamp] + core_public_extra_headers,
'include_directories': include_directories('.'),
'link_with': core_public_lib,
'dependencies': core_deps,
'variables': uninstalled_variables,
}
if not is_shared
core_public_dep_kwargs += {
'link_args': backend_libs_private,
}
endif
core_public_dep = declare_dependency(kwargs: core_public_dep_kwargs)
core_public_dep = declare_dependency(
sources: [core_public_h, core_public_gir, glib_gir, gobject_gir, gio_gir, core_public_vapi_stamp, core_public_extra_headers],
include_directories: include_directories('.'),
link_args: backend_libs_private,
link_with: core_public_lib,
dependencies: core_deps,
variables: uninstalled_variables,
)
pkg = import('pkgconfig')
pkg_kwargs = {
'filebase': f'frida-core-@api_version@',
'name': 'Frida Core Library',
'version': frida_version,
'description': 'Instrumentation toolkit for developers, reverse-engineers, and security researchers',
'requires': ['glib-2.0', 'gobject-2.0', 'gio-2.0', 'json-glib-1.0'],
'subdirs': f'frida-@api_version@',
'extra_cflags': ['-I${frida_includedir}'],
'variables': installed_variables,
'uninstalled_variables': uninstalled_variables,
}
if is_shared
pkg_kwargs += {
'libraries': ['-L${libdir}', f'-lfrida-core-@api_version@'],
}
else
pkg_kwargs += {
'libraries': core_public_lib,
'requires_private': ['gmodule-2.0', 'gee-0.8', 'libsoup-3.0', 'frida-gum-1.0', 'frida-gumjs-inspector-1.0', 'libbrotlidec'] + backend_reqs_private,
'libraries_private': backend_libs_private,
}
endif
pkg.generate(kwargs: pkg_kwargs)
pkg.generate(
filebase: f'frida-core-@api_version@',
name: 'Frida Core Library',
version: frida_version,
description: 'Instrumentation toolkit for developers, reverse-engineers, and security researchers',
requires: ['glib-2.0', 'gobject-2.0', 'gio-2.0', 'json-glib-1.0'],
requires_private: ['gmodule-2.0', 'gee-0.8', 'libsoup-3.0', 'frida-gum-1.0', 'frida-gumjs-inspector-1.0', 'libbrotlidec'] + backend_reqs_private,
subdirs: f'frida-@api_version@',
libraries: core_public_lib,
libraries_private: backend_libs_private,
extra_cflags: ['-I${frida_includedir}'],
variables: installed_variables,
uninstalled_variables: uninstalled_variables,
)
meson.override_dependency(f'frida-core-@api_version@', core_public_dep)
+3 -14
View File
@@ -14,21 +14,15 @@ namespace Frida {
public sealed class BareboneHostSessionProvider : Object, HostSessionProvider {
public string id {
get {
return "barebone";
}
get { return "barebone"; }
}
public string name {
get {
return "GDB Remote Stub";
}
get { return "GDB Remote Stub"; }
}
public Variant? icon {
get {
return _icon;
}
get { return null; }
}
public HostSessionProviderKind kind {
@@ -37,13 +31,8 @@ namespace Frida {
}
}
private static Variant _icon;
private BareboneHostSession? host_session;
static construct {
_icon = make_provider_icon (Frida.Data.Icons.get_barebone_png_blob ().data);
}
public async void close (Cancellable? cancellable) throws IOError {
if (host_session != null) {
yield host_session.close (cancellable);
+1 -1
View File
@@ -401,7 +401,7 @@ namespace Frida.Barebone {
}
private void handle_message (Json.Node message) throws Error {
var r = make_json_reader_from_node (message);
var r = new Json.Reader (message);
bool is_response = r.read_member ("id");
uint id = 0;
+1 -1
View File
@@ -1,4 +1,4 @@
#if defined (_MSC_VER) && defined (HAVE_COMPILER_BACKEND_LINKED)
#ifdef _MSC_VER
#include <glib.h>
+271
View File
@@ -1,11 +1,98 @@
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"
@@ -23,6 +110,21 @@ type BuildOptions struct {
Externals []string
}
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
@@ -44,6 +146,153 @@ 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, cPlatform *C.char, cExternals **C.char, numExternals C.int,
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,
Platform: platformFromFrida(C.GoString(cPlatform)),
Externals: parseCExternals(cExternals, numExternals),
}
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, cPlatform *C.char, cExternals **C.char, numExternals C.int,
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,
Platform: platformFromFrida(C.GoString(cPlatform)),
Externals: parseCExternals(cExternals, numExternals),
}
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 platformFromFrida(s string) esbuild.Platform {
switch s {
case "gum":
return esbuild.PlatformNode
case "browser":
return esbuild.PlatformBrowser
case "neutral":
return esbuild.PlatformNeutral
default:
panic(fmt.Sprintf("Unknown platform: %q", s))
}
}
func parseCExternals(cExternals **C.char, numExternals C.int) []string {
if numExternals == 0 {
return nil
}
n := int(numExternals)
cArray := (*[1 << 20]*C.char)(unsafe.Pointer(cExternals))[:n:n]
externals := make([]string, n)
for i := 0; i < n; i++ {
externals[i] = C.GoString(cArray[i])
}
return externals
}
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) {
@@ -579,3 +828,25 @@ func makeTypeScriptPlugin(compiler *TSCompiler) esbuild.Plugin {
},
}
}
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() {}
-1
View File
@@ -1 +0,0 @@
__frida_compiler_backend_*
+16 -22
View File
@@ -1,3 +1,4 @@
import base64
import json
import os
import shutil
@@ -9,7 +10,7 @@ from typing import List
def main(argv):
go_config = json.loads(Path(argv[1]).read_text(encoding="utf-8"))
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:
@@ -59,36 +60,28 @@ def build_backend(
mode = config["mode"]
backend_stem = "frida-compiler-backend"
if mode != "c-archive":
if mode == "c-shared":
backend_stem += "-raw"
if mode == "c-archive":
backend_binary = priv_dir / f"{backend_stem}.a"
elif mode == "c-shared":
backend_binary = priv_dir / (f"{backend_stem}" + config["shlib_suffix"])
else:
backend_binary = priv_dir / (f"{backend_stem}" + config["exe_suffix"])
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":
if config["os_family"] == "darwin":
symbols_list = priv_dir / "backend.symbols"
extra_go_args.append(f"-ldflags=-linkmode=external -extldflags=-Wl,-exported_symbols_list,{symbols_list}")
elif config["os_family"] != "windows":
version_script = priv_dir / "backend.version"
extra_go_args.append(f"-ldflags=-linkmode=external -extldflags=-Wl,--version-script={version_script}")
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_binary.name,
backend_a.name if mode == "c-archive" else backend_shlib.name,
"-buildvcs=false",
*extra_go_args,
".",
*go_sources,
)
if mode == "c-archive":
@@ -116,7 +109,7 @@ def build_backend(
)
run(priv_dir / "symbol-replacer" / symbol_replacer_name,
backend_binary.name, *config["nm"], *config["ranlib"], config["env"]["CC"])
backend_a.name, *config["nm"], *config["ranlib"], config["env"]["CC"])
if (mingw := config.get("mingw")) is not None and (abi := config["abi"]) in {
"x86",
@@ -150,16 +143,17 @@ def build_backend(
extra_objects = []
if abi == "x86_64":
run(*ar, "x", backend_binary.name, "go.o")
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_binary.name, *libgcc_objects, *gwex_objects, *extra_objects)
run(*ar, "rs", backend_a.name, *libgcc_objects, *gwex_objects, *extra_objects)
shutil.copy(priv_dir / backend_binary.name, output_dir / backend_binary.name)
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)
if mode in {"c-archive", "c-shared"}:
shutil.copy(priv_dir / backend_h.name, output_dir / backend_h.name)
shutil.copy(priv_dir / backend_h.name, output_dir / backend_h.name)
# Work around the Go toolchain's almost-MSVC-compatible object files
+14 -646
View File
@@ -47,7 +47,7 @@ namespace Frida {
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), opts.platform.to_nick (),
opts.externals.to_array (), on_diagnostic, (owned) on_complete);
opts.externals.to_array (), (owned) on_complete, on_diagnostic);
yield;
if (error_message != null)
@@ -98,8 +98,8 @@ namespace Frida {
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), opts.platform.to_nick (),
opts.externals.to_array (), on_starting, on_finished, on_output, on_diagnostic,
(owned) on_ready);
opts.externals.to_array (), (owned) on_ready, on_starting, on_finished,
on_output, on_diagnostic);
yield;
if (error_message != null)
@@ -235,24 +235,12 @@ namespace Frida {
namespace CompilerBackend {
private void init () {
#if HAVE_COMPILER_BACKEND
#if COMPILER_BACKEND_LINKED
#if COMPILER_BACKEND_STATIC_COMPILATION
_init_go_runtime ();
build = (BuildFunc) _build;
watch = (WatchFunc) _watch;
WatchSession.dispose = (WatchSession.DisposeFunc) WatchSession._dispose;
#elif COMPILER_BACKEND_INSTALLED_LIBRARY
Module? backend = null;
try {
backend = new Module (Frida.compiler_backend_path, LOCAL);
} catch (ModuleError e) {
return;
}
backend.make_resident ();
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");
#elif COMPILER_BACKEND_EMBEDDED_LIBRARY
#else
unowned uint8[] backend_so = Frida.Data.Compiler.get_frida_compiler_backend_so_blob ().data;
Module? backend = null;
@@ -284,31 +272,17 @@ namespace Frida {
assert_not_reached ();
}
}
backend.make_resident ();
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");
#elif COMPILER_BACKEND_EMBEDDED_EXECUTABLE || COMPILER_BACKEND_INSTALLED_EXECUTABLE
backend_process = new BackendProcess ();
build = executable_build;
watch = executable_watch;
WatchSession.dispose = executable_watch_session_dispose;
#endif
#endif
}
private void check_available () throws Error {
if (build == null) {
#if COMPILER_BACKEND_INSTALLED_LIBRARY || COMPILER_BACKEND_INSTALLED_EXECUTABLE
throw new Error.NOT_SUPPORTED (
"Compiler backend plugin not installed; expected at: %s",
Frida.compiler_backend_path);
#else
if (build == null)
throw new Error.NOT_SUPPORTED ("Compiler backend disabled at build-time");
#endif
}
}
private BuildFunc? build;
@@ -317,15 +291,16 @@ namespace Frida {
[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,
string platform, string[] externals, DiagnosticFunc on_diagnostic, owned BuildCompleteFunc on_complete);
string platform, string[] externals, 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,
string platform, string[] externals, StartingFunc on_starting, FinishedFunc on_finished,
OutputFunc on_output, DiagnosticFunc on_diagnostic, owned WatchReadyFunc on_ready);
string platform, string[] externals, owned WatchReadyFunc on_ready, StartingFunc on_starting,
FinishedFunc on_finished, OutputFunc on_output, DiagnosticFunc on_diagnostic);
#if COMPILER_BACKEND_LINKED
#if COMPILER_BACKEND_STATIC_COMPILATION
private extern void _init_go_runtime ();
private extern void _build ();
private extern void _watch ();
@@ -337,7 +312,7 @@ namespace Frida {
private DisposeFunc? dispose;
#if COMPILER_BACKEND_LINKED
#if COMPILER_BACKEND_STATIC_COMPILATION
private extern void _dispose ();
#endif
}
@@ -350,621 +325,14 @@ namespace Frida {
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_EMBEDDED_LIBRARY || COMPILER_BACKEND_INSTALLED_LIBRARY)
private T resolve_symbol<T> (Module m, string name) {
#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
#if COMPILER_BACKEND_EMBEDDED_EXECUTABLE || COMPILER_BACKEND_INSTALLED_EXECUTABLE
private BackendProcess? backend_process;
private static void executable_build (string project_root, string entrypoint, OutputFormat output_format,
BundleFormat bundle_format, size_t disable_type_check, size_t source_map, size_t compress,
string platform, string[] externals, DiagnosticFunc on_diagnostic, owned BuildCompleteFunc on_complete) {
backend_process.build (project_root, entrypoint, output_format, bundle_format, disable_type_check, source_map,
compress, platform, externals, on_diagnostic, (owned) on_complete);
}
private static void executable_watch (string project_root, string entrypoint, OutputFormat output_format,
BundleFormat bundle_format, size_t disable_type_check, size_t source_map, size_t compress,
string platform, string[] externals, StartingFunc on_starting, FinishedFunc on_finished,
OutputFunc on_output, DiagnosticFunc on_diagnostic, owned WatchReadyFunc on_ready) {
backend_process.watch (project_root, entrypoint, output_format, bundle_format, disable_type_check, source_map,
compress, platform, externals, on_starting, on_finished, on_output, on_diagnostic, (owned) on_ready);
}
private static void executable_watch_session_dispose (size_t handle) {
backend_process.dispose_watch_session (handle);
}
private class BackendProcess : Object {
private Subprocess? process;
private BufferedInputStream? input;
private OutputStream? output;
private DataInputStream? errput;
private ByteArray pending_output = new ByteArray ();
private bool writing = false;
private uint next_request_id = 1;
private uint next_session_id = 1;
private Gee.Map<uint, PendingBuild> pending_builds = new Gee.HashMap<uint, PendingBuild> ();
private Gee.Map<uint, WatchEntry> watches = new Gee.HashMap<uint, WatchEntry> ();
private Cancellable io_cancellable = new Cancellable ();
construct {
try_start ();
}
private void try_start () {
try {
ensure_started ();
} catch (GLib.Error e) {
}
}
private void ensure_started () throws GLib.Error {
if (process != null)
return;
#if COMPILER_BACKEND_INSTALLED_EXECUTABLE
unowned string path = Frida.compiler_backend_path;
bool unlink_after = false;
#else
string path = extract_backend_executable ();
bool unlink_after = true;
#endif
try {
var p = new Subprocess (STDIN_PIPE | STDOUT_PIPE | STDERR_PIPE, path);
process = p;
input = (BufferedInputStream) Object.new (typeof (BufferedInputStream),
"base-stream", p.get_stdout_pipe (),
"close-base-stream", false,
"buffer-size", 128 * 1024);
output = p.get_stdin_pipe ();
errput = new DataInputStream (p.get_stderr_pipe ());
process_incoming_messages.begin ();
process_stderr_stream.begin (errput);
} finally {
if (unlink_after)
FileUtils.unlink (path);
}
}
#if COMPILER_BACKEND_EMBEDDED_EXECUTABLE
private static string extract_backend_executable () throws GLib.Error {
unowned uint8[] blob = Frida.Data.Compiler.get_frida_compiler_backend_blob ().data;
string path;
{
var fd = new FileDescriptor (FileUtils.open_tmp ("frida-compiler-backend-XXXXXX", out path));
fd.pwrite_all (blob, 0);
}
FileUtils.chmod (path, 0700);
return path;
}
#endif
private void handle_process_failure (string message) {
io_cancellable.cancel ();
io_cancellable = new Cancellable ();
if (process != null) {
if (!process.get_if_exited ())
process.force_exit ();
}
process = null;
input = null;
output = null;
errput = null;
foreach (var e in pending_builds.entries)
e.value.on_complete (null, message);
pending_builds.clear ();
foreach (var e in watches.entries) {
var entry = e.value;
if (entry.on_ready != null)
entry.on_ready (0, message);
}
watches.clear ();
pending_output = new ByteArray ();
writing = false;
}
public void build (string project_root, string entrypoint, OutputFormat output_format, BundleFormat bundle_format,
size_t disable_type_check, size_t source_map, size_t compress, string platform, string[] externals,
DiagnosticFunc on_diagnostic, owned BuildCompleteFunc on_complete) {
try {
ensure_started ();
} catch (GLib.Error e) {
on_complete (null, e.message);
return;
}
uint request_id = allocate_request_id ();
pending_builds[request_id] = new PendingBuild ((owned) on_complete, on_diagnostic);
post_message (make_build_request (
request_id,
project_root,
entrypoint,
output_format,
bundle_format,
disable_type_check != 0,
source_map != 0,
compress != 0,
platform,
externals
));
}
private class PendingBuild {
public BuildCompleteFunc on_complete;
public unowned DiagnosticFunc on_diagnostic;
public PendingBuild (owned BuildCompleteFunc on_complete, DiagnosticFunc on_diagnostic) {
this.on_complete = (owned) on_complete;
this.on_diagnostic = on_diagnostic;
}
}
public void watch (string project_root, string entrypoint, OutputFormat output_format, BundleFormat bundle_format,
size_t disable_type_check, size_t source_map, size_t compress, string platform, string[] externals,
StartingFunc on_starting, FinishedFunc on_finished, OutputFunc on_output,
DiagnosticFunc on_diagnostic, owned WatchReadyFunc on_ready) {
try {
ensure_started ();
} catch (GLib.Error e) {
on_ready (0, e.message);
return;
}
uint session_id = allocate_session_id ();
watches[session_id] = new WatchEntry ((owned) on_ready, on_starting, on_finished, on_output, on_diagnostic);
post_message (make_watch_request (
session_id,
project_root,
entrypoint,
output_format,
bundle_format,
disable_type_check != 0,
source_map != 0,
compress != 0,
platform,
externals
));
}
private class WatchEntry {
public WatchReadyFunc? on_ready;
public unowned StartingFunc on_starting;
public unowned FinishedFunc on_finished;
public unowned OutputFunc on_output;
public unowned DiagnosticFunc on_diagnostic;
public WatchEntry (owned WatchReadyFunc on_ready, StartingFunc on_starting, FinishedFunc on_finished,
OutputFunc on_output, DiagnosticFunc on_diagnostic) {
this.on_ready = (owned) on_ready;
this.on_starting = on_starting;
this.on_finished = on_finished;
this.on_output = on_output;
this.on_diagnostic = on_diagnostic;
}
}
public void dispose_watch_session (size_t handle) {
uint session_id = (uint) handle;
WatchEntry entry;
if (!watches.unset (session_id, out entry))
return;
if (process != null)
post_message (make_dispose_request (session_id));
}
private static string make_build_request (uint id, string project_root, string entrypoint,
OutputFormat output_format, BundleFormat bundle_format, bool disable_type_check,
bool source_map, bool compress, string platform, string[] externals) {
return make_request ("build", "id", id, project_root, entrypoint, output_format, bundle_format,
disable_type_check, source_map, compress, platform, externals);
}
private static string make_watch_request (uint session_id, string project_root, string entrypoint,
OutputFormat output_format, BundleFormat bundle_format, bool disable_type_check,
bool source_map, bool compress, string platform, string[] externals) {
return make_request ("watch", "session_id", session_id, project_root, entrypoint, output_format,
bundle_format, disable_type_check, source_map, compress, platform, externals);
}
private static string make_request (string type, string id_name, uint id, string project_root, string entrypoint,
OutputFormat output_format, BundleFormat bundle_format, bool disable_type_check,
bool source_map, bool compress, string platform, string[] externals) {
var builder = new Json.Builder ();
builder
.begin_object ()
.set_member_name ("type")
.add_string_value (type)
.set_member_name (id_name)
.add_int_value (id)
.set_member_name ("project_root")
.add_string_value (project_root)
.set_member_name ("entrypoint")
.add_string_value (entrypoint)
.set_member_name ("output_format")
.add_string_value (output_format.to_nick ())
.set_member_name ("bundle_format")
.add_string_value (bundle_format.to_nick ())
.set_member_name ("disable_type_check")
.add_boolean_value (disable_type_check)
.set_member_name ("source_map")
.add_boolean_value (source_map)
.set_member_name ("compress")
.add_boolean_value (compress)
.set_member_name ("platform")
.add_string_value (platform)
.set_member_name ("externals")
.begin_array ();
foreach (unowned string e in externals)
builder.add_string_value (e);
builder
.end_array ()
.end_object ();
return Json.to_string (builder.get_root (), false);
}
private static string make_dispose_request (uint session_id) {
var builder = new Json.Builder ();
builder
.begin_object ()
.set_member_name ("type")
.add_string_value ("dispose")
.set_member_name ("session_id")
.add_int_value (session_id)
.end_object ();
return Json.to_string (builder.get_root (), false);
}
private uint allocate_request_id () {
uint start = next_request_id;
do {
uint id = next_request_id++;
if (next_request_id == 0)
next_request_id = 1;
if (!pending_builds.has_key (id))
return id;
} while (next_request_id != start);
assert_not_reached ();
}
private uint allocate_session_id () {
uint start = next_session_id;
do {
uint id = next_session_id++;
if (next_session_id == 0)
next_session_id = 1;
if (!watches.has_key (id))
return id;
} while (next_session_id != start);
assert_not_reached ();
}
private void post_message (string json) {
unowned uint8[] raw_json = json.data;
uint32 size = ((uint32) raw_json.length).to_big_endian ();
pending_output.append ((uint8[]) &size);
pending_output.append (raw_json);
if (!writing) {
writing = true;
var source = new IdleSource ();
source.set_callback (() => {
process_pending_output.begin ();
return false;
});
source.attach (MainContext.get_thread_default ());
}
}
private async void process_pending_output () {
while (pending_output.len > 0) {
uint8[] batch = pending_output.steal ();
size_t bytes_written;
try {
yield output.write_all_async (batch, Priority.DEFAULT, io_cancellable, out bytes_written);
} catch (GLib.Error e) {
handle_process_failure ("Compiler backend process terminated unexpectedly");
return;
}
}
writing = false;
}
private async void process_incoming_messages () {
try {
while (true) {
size_t header_size = 4;
if (input.get_available () < header_size)
yield fill_until_n_bytes_available (header_size);
uint32 body_size = 0;
unowned uint8[] size_buf = ((uint8[]) &body_size)[:4];
input.peek (size_buf);
body_size = uint32.from_big_endian (body_size);
size_t full_size = header_size + body_size;
if (input.get_available () < full_size)
yield fill_until_n_bytes_available (full_size);
var raw_json = new uint8[body_size + 1];
input.peek (raw_json[:body_size], header_size);
unowned string json = (string) raw_json;
handle_message (json);
input.skip (full_size, io_cancellable);
}
} catch (GLib.Error e) {
handle_process_failure (e.message);
}
}
private void handle_message (string json) throws Error {
Json.Reader reader;
try {
reader = make_json_reader (json);
} catch (GLib.Error e) {
throw new Error.PROTOCOL ("%s", e.message);
}
reader.read_member ("type");
unowned string? type = reader.get_string_value ();
if (type == null)
throw new Error.PROTOCOL ("Missing or invalid 'type' value");
reader.end_member ();
var tokens = type.split (":", 2);
if (tokens.length != 2)
throw new Error.PROTOCOL ("Invalid 'type' value");
unowned string scope = tokens[0];
unowned string subtype = tokens[1];
if (scope == "build")
handle_build_message (subtype, reader);
else if (scope == "watch")
handle_watch_message (subtype, reader);
else
throw new Error.PROTOCOL ("Unknown 'type' scope");
}
private void handle_build_message (string type, Json.Reader reader) throws Error {
if (type == "complete")
handle_build_complete_message (reader);
else if (type == "diagnostic")
handle_build_diagnostic_message (reader);
else
throw new Error.PROTOCOL ("Unknown build message type: %s", type);
}
private void handle_watch_message (string type, Json.Reader reader) throws Error {
if (type == "ready")
handle_watch_ready_message (reader);
else if (type == "starting" || type == "finished" || type == "output" || type == "diagnostic")
handle_watch_event_message (reader, type);
else
throw new Error.PROTOCOL ("Unknown watch message type: %s", type);
}
private void handle_build_complete_message (Json.Reader reader) throws Error {
reader.read_member ("id");
uint id = (uint) reader.get_int_value ();
reader.end_member ();
PendingBuild pending;
if (!pending_builds.unset (id, out pending))
throw new Error.PROTOCOL ("Invalid pending build ID: %u", id);
if (reader.read_member ("error")) {
unowned string? error = reader.get_string_value ();
if (error == null)
throw new Error.PROTOCOL ("Missing or invalid 'error' value");
reader.end_member ();
pending.on_complete (null, error);
return;
}
reader.end_member ();
reader.read_member ("bundle");
unowned string? bundle = reader.get_string_value ();
if (bundle == null)
throw new Error.PROTOCOL ("Missing or invalid 'bundle' value");
reader.end_member ();
pending.on_complete (bundle, null);
}
private void handle_build_diagnostic_message (Json.Reader reader) throws Error {
reader.read_member ("id");
uint id = (uint) reader.get_int_value ();
reader.end_member ();
var pending = pending_builds[id];
if (pending == null)
throw new Error.PROTOCOL ("Invalid pending build ID: %u", id);
emit_diagnostic_from_json (reader, pending.on_diagnostic);
}
private void handle_watch_ready_message (Json.Reader reader) throws Error {
reader.read_member ("session_id");
uint session_id = (uint) reader.get_int_value ();
reader.end_member ();
var watch = watches[session_id];
if (watch == null)
throw new Error.PROTOCOL ("Invalid watch session ID: %u", session_id);
if (reader.read_member ("error")) {
unowned string? error = reader.get_string_value ();
if (error == null)
throw new Error.PROTOCOL ("Missing or invalid 'error' value");
reader.end_member ();
watches.unset (session_id);
watch.on_ready (0, error);
return;
}
reader.end_member ();
var on_ready = (owned) watch.on_ready;
if (on_ready == null)
throw new Error.PROTOCOL ("Duplicate watch:ready for session ID: %u", session_id);
watch.on_ready = null;
on_ready (session_id, null);
}
private void handle_watch_event_message (Json.Reader reader, string type) throws Error {
reader.read_member ("session_id");
var session_id = (uint) reader.get_int_value ();
reader.end_member ();
var watch = watches[session_id];
if (watch == null)
throw new Error.PROTOCOL ("Invalid watch session ID: %u", session_id);
if (type == "starting") {
watch.on_starting ();
return;
}
if (type == "finished") {
watch.on_finished ();
return;
}
if (type == "output") {
reader.read_member ("bundle");
unowned string? bundle = reader.get_string_value ();
if (bundle == null)
throw new Error.PROTOCOL ("Missing or invalid 'bundle' value");
reader.end_member ();
watch.on_output (bundle);
return;
}
emit_diagnostic_from_json (reader, watch.on_diagnostic);
}
private static void emit_diagnostic_from_json (Json.Reader reader, DiagnosticFunc on_diagnostic) throws Error {
reader.read_member ("category");
unowned string? category = reader.get_string_value ();
if (category == null)
throw new Error.PROTOCOL ("Missing or invalid 'category' value");
reader.end_member ();
reader.read_member ("code");
int code = (int) reader.get_int_value ();
reader.end_member ();
string? path = null;
int line = 0;
int character = 0;
if (reader.read_member ("path")) {
path = reader.get_string_value ();
reader.end_member ();
reader.read_member ("line");
line = (int) reader.get_int_value ();
reader.end_member ();
reader.read_member ("character");
character = (int) reader.get_int_value ();
reader.end_member ();
} else {
reader.end_member ();
}
reader.read_member ("text");
unowned string? text = reader.get_string_value ();
if (text == null)
throw new Error.PROTOCOL ("Missing or invalid 'text' value");
reader.end_member ();
on_diagnostic (category, code, path, line, character, text);
}
private async void process_stderr_stream (DataInputStream stream) {
try {
while (true) {
string? line = yield stream.read_line_utf8_async (Priority.DEFAULT, io_cancellable);
if (line == null)
break;
printerr ("[frida-compiler-backend stderr] %s\n", line);
}
} catch (GLib.Error e) {
}
}
private async void fill_until_n_bytes_available (size_t minimum) throws Error, IOError {
size_t available = input.get_available ();
while (available < minimum) {
if (input.get_buffer_size () < minimum)
input.set_buffer_size (minimum);
ssize_t n;
try {
n = yield input.fill_async ((ssize_t) (input.get_buffer_size () - available),
Priority.DEFAULT, io_cancellable);
} catch (GLib.Error e) {
throw new Error.TRANSPORT ("Compiler backend process terminated unexpectedly");
}
if (n == 0)
throw new Error.TRANSPORT ("Compiler backend process terminated unexpectedly");
available += n;
}
}
}
#endif
}
private string compute_project_root (string entrypoint, CompilerOptions options) {
-249
View File
@@ -1,249 +0,0 @@
//go:build !frida_compiler_backend_executable
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 (
"runtime/cgo"
"unsafe"
)
//export _frida_compiler_backend_build
func _frida_compiler_backend_build(cProjectRoot, cEntrypoint *C.char, outputFormat C.FridaOutputFormat, bundleFormat C.FridaBundleFormat,
disableTypeCheck, sourceMap, compress uintptr, cPlatform *C.char, cExternals **C.char, numExternals C.int,
onDiagnosticFn C.FridaDiagnosticFunc, onDiagnosticData unsafe.Pointer, onCompleteFn C.FridaBuildCompleteFunc,
onCompleteData unsafe.Pointer, onCompleteDataDestroy C.FridaDestroyFunc) {
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,
Platform: platformFromFrida(C.GoString(cPlatform)),
Externals: parseCExternals(cExternals, numExternals),
}
onDiagnostic := NewCDelegate(onDiagnosticFn, onDiagnosticData, nil)
onComplete := NewCDelegate(onCompleteFn, onCompleteData, onCompleteDataDestroy)
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, cPlatform *C.char, cExternals **C.char, numExternals C.int,
onStartingFn C.FridaStartingFunc, onStartingData unsafe.Pointer,
onFinishedFn C.FridaFinishedFunc, onFinishedData unsafe.Pointer,
onOutputFn C.FridaOutputFunc, onOutputData unsafe.Pointer,
onDiagnosticFn C.FridaDiagnosticFunc, onDiagnosticData unsafe.Pointer,
onReadyFn C.FridaWatchReadyFunc, onReadyData unsafe.Pointer, onReadyDataDestroy C.FridaDestroyFunc) {
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,
Platform: platformFromFrida(C.GoString(cPlatform)),
Externals: parseCExternals(cExternals, numExternals),
}
onStarting := NewCDelegate(onStartingFn, onStartingData, nil)
onFinished := NewCDelegate(onFinishedFn, onFinishedData, nil)
onOutput := NewCDelegate(onOutputFn, onOutputData, nil)
onDiagnostic := NewCDelegate(onDiagnosticFn, onDiagnosticData, nil)
onReady := NewCDelegate(onReadyFn, onReadyData, onReadyDataDestroy)
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_finished_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 parseCExternals(cExternals **C.char, numExternals C.int) []string {
if numExternals == 0 {
return nil
}
n := int(numExternals)
cArray := (*[1 << 20]*C.char)(unsafe.Pointer(cExternals))[:n:n]
externals := make([]string, n)
for i := 0; i < n; i++ {
externals[i] = C.GoString(cArray[i])
}
return externals
}
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)
}
}
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() {}
-263
View File
@@ -1,263 +0,0 @@
//go:build frida_compiler_backend_executable
package main
import (
"bufio"
"encoding/binary"
"encoding/json"
"errors"
"fmt"
"io"
"os"
"sync"
)
type BackendRequest struct {
Type string `json:"type"`
ID uint `json:"id,omitempty"`
SessionID uint `json:"session_id,omitempty"`
ProjectRoot string `json:"project_root,omitempty"`
Entrypoint string `json:"entrypoint,omitempty"`
OutputFormat string `json:"output_format,omitempty"`
BundleFormat string `json:"bundle_format,omitempty"`
DisableTypeCheck bool `json:"disable_type_check,omitempty"`
SourceMap bool `json:"source_map,omitempty"`
Compress bool `json:"compress,omitempty"`
Platform string `json:"platform,omitempty"`
Externals []string `json:"externals,omitempty"`
}
type BackendEvent struct {
Type string `json:"type"`
ID uint `json:"id,omitempty"`
SessionID uint `json:"session_id,omitempty"`
Bundle string `json:"bundle,omitempty"`
Error string `json:"error,omitempty"`
Category string `json:"category,omitempty"`
Code int `json:"code,omitempty"`
Path string `json:"path,omitempty"`
Line int `json:"line,omitempty"`
Character int `json:"character,omitempty"`
Text string `json:"text,omitempty"`
}
func main() {
if err := run(); err != nil {
fmt.Fprintln(os.Stderr, err.Error())
os.Exit(1)
}
}
func run() error {
reader := bufio.NewReaderSize(os.Stdin, 128*1024)
writer := bufio.NewWriterSize(os.Stdout, 128*1024)
var outputMu sync.Mutex
var sessionsMu sync.Mutex
sessions := make(map[uint]*WatchSession)
emit := func(ev BackendEvent) {
outputMu.Lock()
defer outputMu.Unlock()
if err := writeMessage(writer, ev); err != nil {
fmt.Fprintln(os.Stderr, err.Error())
}
}
for {
var req BackendRequest
if err := readMessage(reader, &req); err != nil {
if errors.Is(err, io.EOF) {
return nil
}
return err
}
switch req.Type {
case "build":
go func(req BackendRequest) {
options, err := buildOptionsFromRequest(req)
if err != nil {
emit(BackendEvent{
Type: "build:complete",
ID: req.ID,
Error: err.Error(),
})
return
}
onDiagnostic := func(d Diagnostic) {
ev := BackendEvent{
Type: "build:diagnostic",
ID: req.ID,
Category: d.category,
Code: d.code,
Path: d.path,
Line: d.line,
Character: d.character,
Text: d.text,
}
emit(ev)
}
bundle, err := build(options, onDiagnostic)
ev := BackendEvent{
Type: "build:complete",
ID: req.ID,
}
if err != nil {
ev.Error = err.Error()
} else {
ev.Bundle = bundle
}
emit(ev)
}(req)
case "watch":
go func(req BackendRequest) {
options, err := buildOptionsFromRequest(req)
if err != nil {
emit(BackendEvent{
Type: "watch:ready",
SessionID: req.SessionID,
Error: err.Error(),
})
return
}
callbacks := BuildEventCallbacks{
OnStart: func() {
emit(BackendEvent{
Type: "watch:starting",
SessionID: req.SessionID,
})
},
OnEnd: func() {
emit(BackendEvent{
Type: "watch:finished",
SessionID: req.SessionID,
})
},
OnOutput: func(bundle string) {
emit(BackendEvent{
Type: "watch:output",
SessionID: req.SessionID,
Bundle: bundle,
})
},
OnDiagnostic: func(d Diagnostic) {
emit(BackendEvent{
Type: "watch:diagnostic",
SessionID: req.SessionID,
Category: d.category,
Code: d.code,
Path: d.path,
Line: d.line,
Character: d.character,
Text: d.text,
})
},
}
var session *WatchSession
onDispose := func() {
sessionsMu.Lock()
delete(sessions, req.SessionID)
sessionsMu.Unlock()
}
session, err = NewWatchSession(options, onDispose, callbacks)
if err != nil {
emit(BackendEvent{
Type: "watch:ready",
SessionID: req.SessionID,
Error: err.Error(),
})
return
}
sessionsMu.Lock()
sessions[req.SessionID] = session
sessionsMu.Unlock()
emit(BackendEvent{
Type: "watch:ready",
SessionID: req.SessionID,
})
}(req)
case "dispose":
sessionsMu.Lock()
session := sessions[req.SessionID]
delete(sessions, req.SessionID)
sessionsMu.Unlock()
if session != nil {
session.Dispose()
}
default:
return fmt.Errorf("unsupported request type: %q", req.Type)
}
}
}
func buildOptionsFromRequest(req BackendRequest) (BuildOptions, error) {
outputFormat, err := outputFormatFromNick(req.OutputFormat)
if err != nil {
return BuildOptions{}, err
}
bundleFormat, err := bundleFormatFromNick(req.BundleFormat)
if err != nil {
return BuildOptions{}, err
}
return BuildOptions{
ProjectRoot: req.ProjectRoot,
Entrypoint: req.Entrypoint,
OutputFormat: outputFormat,
BundleFormat: bundleFormat,
DisableTypeCheck: req.DisableTypeCheck,
SourceMap: req.SourceMap,
Compress: req.Compress,
Platform: platformFromFrida(req.Platform),
Externals: req.Externals,
}, nil
}
func readMessage(r io.Reader, out any) error {
var size uint32
if err := binary.Read(r, binary.BigEndian, &size); err != nil {
return err
}
buf := make([]byte, size)
if _, err := io.ReadFull(r, buf); err != nil {
return err
}
return json.Unmarshal(buf, out)
}
func writeMessage(w *bufio.Writer, msg any) error {
buf, err := json.Marshal(msg)
if err != nil {
return err
}
if err := binary.Write(w, binary.BigEndian, uint32(len(buf))); err != nil {
return err
}
if _, err := w.Write(buf); err != nil {
return err
}
return w.Flush()
}
+32 -67
View File
@@ -4,40 +4,23 @@ compiler_sources = files(
)
if have_compiler_backend
if compiler_backend_mode == 'c-archive'
output_files = [
'frida-compiler-backend.a',
'frida-compiler-backend.h',
]
elif compiler_backend_mode == 'c-shared'
output_files = [
'frida-compiler-backend-raw' + shlib_suffix,
'frida-compiler-backend-raw.h',
]
elif compiler_backend_mode == 'pie'
output_files = [
'frida-compiler-backend-raw' + exe_suffix,
]
endif
output_suffix = compiler_backend_static_compilation ? '' : '-raw'
compiler_backend = custom_target('frida-compiler-backend',
input: [
'go.mod',
'go.sum',
'frontend_capi.go',
'frontend_stdio.go',
'backend.go',
'protocol_types.go',
'backend.version',
'backend.symbols',
'tscompiler.go',
'tsconfig.go',
'shims.go',
'package.json',
'package-lock.json',
],
output: output_files,
depend_files: go_config,
output: [
'frida-compiler-backend' + output_suffix + (compiler_backend_static_compilation ? '.a' : shlib_suffix),
'frida-compiler-backend' + output_suffix + '.h',
],
command: [
python,
files('build-backend.py'),
@@ -49,53 +32,35 @@ if have_compiler_backend
'@INPUT@',
],
)
if compiler_backend_mode == 'c-archive'
if compiler_backend_static_compilation
backend_libs += compiler_backend[0]
else
if compiler_backend_mode == 'c-shared'
processed_filename = 'frida-compiler-backend' + shlib_suffix
identity = (host_os_family == 'darwin') ? 'FridaCompilerBackend' : processed_filename
compiler_backend_binary = custom_target('frida-compiler-backend-binary',
input: compiler_backend[0],
output: processed_filename,
command: post_process + ['shared-library', identity, 'elf-cleaner:off'],
install: assets_mode == 'installed',
install_dir: get_option('libdir') / frida_libdir_name / 'plugins',
)
elif compiler_backend_mode == 'pie'
processed_filename = 'frida-compiler-backend' + exe_suffix
compiler_backend_binary = custom_target('frida-compiler-backend-binary',
input: compiler_backend[0],
output: processed_filename,
command: post_process + ['executable', processed_filename],
install: assets_mode == 'installed',
install_dir: get_option('libdir') / frida_libdir_name / 'plugins',
)
endif
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'],
)
if assets_mode == 'installed'
core_extra_link_depends += compiler_backend_binary
else
compiler_data = custom_target('frida-data-compiler',
input: [
'compiler.resources',
compiler_backend_binary,
],
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
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
+4 -4
View File
@@ -33,7 +33,7 @@
"@frida/url": "^1.0.2",
"@frida/util": "^1.0.3",
"@frida/vm": "^2.0.0",
"@types/frida-gum": "19.0.2",
"@types/frida-gum": "19.0.1",
"@types/node": "18.19.103",
"frida-fs": "7.0.0"
}
@@ -248,9 +248,9 @@
"license": "MIT"
},
"node_modules/@types/frida-gum": {
"version": "19.0.2",
"resolved": "https://registry.npmjs.org/@types/frida-gum/-/frida-gum-19.0.2.tgz",
"integrity": "sha512-oh/f1r8dIMDWBoziXP3geIJ8ga/siU32MuifBztGsDglOKbHrhS0E3z0Dab0MIe3UFzC4Bvz/GRHfin2LDE8BQ==",
"version": "19.0.1",
"resolved": "https://registry.npmjs.org/@types/frida-gum/-/frida-gum-19.0.1.tgz",
"integrity": "sha512-mp8BpWWkQFJH86ZN5uXZuDiA7KY/+jDknrw0a06x0/+F5ucPwctHrCuV6iT+LLCp/GyICc36ssedF33B1WoLsw==",
"license": "MIT"
},
"node_modules/@types/node": {
+1 -1
View File
@@ -29,7 +29,7 @@
"@frida/url": "^1.0.2",
"@frida/util": "^1.0.3",
"@frida/vm": "^2.0.0",
"@types/frida-gum": "19.0.2",
"@types/frida-gum": "19.0.1",
"@types/node": "18.19.103",
"frida-fs": "7.0.0"
}
-59
View File
@@ -1,59 +0,0 @@
package main
import (
"fmt"
esbuild "github.com/evanw/esbuild/pkg/api"
)
type OutputFormat int
const (
OutputFormatUnescaped OutputFormat = iota
OutputFormatHexBytes
OutputFormatCString
)
func outputFormatFromNick(s string) (OutputFormat, error) {
switch s {
case "unescaped":
return OutputFormatUnescaped, nil
case "hex-bytes":
return OutputFormatHexBytes, nil
case "c-string":
return OutputFormatCString, nil
default:
return 0, fmt.Errorf("unknown output format: %q", s)
}
}
type BundleFormat int
const (
BundleFormatESM BundleFormat = iota
BundleFormatIIFE
)
func bundleFormatFromNick(s string) (BundleFormat, error) {
switch s {
case "esm":
return BundleFormatESM, nil
case "iife":
return BundleFormatIIFE, nil
default:
return 0, fmt.Errorf("unknown bundle format: %q", s)
}
}
func platformFromFrida(s string) esbuild.Platform {
switch s {
case "gum":
return esbuild.PlatformNode
case "browser":
return esbuild.PlatformBrowser
case "neutral":
return esbuild.PlatformNeutral
default:
panic(fmt.Sprintf("Unknown platform: %q", s))
}
}
+2 -2
View File
@@ -44,7 +44,7 @@ namespace Frida {
#if HAVE_EMBEDDED_ASSETS
return null;
#else
unowned string path = Frida.agent_path;
unowned string path = Config.FRIDA_AGENT_PATH;
# if IOS || TVOS
unowned string? cryptex_path = Environment.get_variable ("CRYPTEX_MOUNT_PATH");
if (cryptex_path != null)
@@ -1053,7 +1053,7 @@ namespace Frida {
var parameters = make_parameters_dict ();
try {
var header = make_json_reader (raw_header);
var header = new Json.Reader (Json.from_string (raw_header));
foreach (string member in header.list_members ()) {
header.read_member (member);
+12 -16
View File
@@ -444,7 +444,6 @@ static void frida_set_nth_hardware_breakpoint (gpointer state, guint n, GumAddre
static void frida_set_hardware_single_step (gpointer debug_state, GumDarwinUnifiedThreadState * thread_state, gboolean enabled, GumCpuType cpu_type);
static gboolean frida_is_hardware_breakpoint_support_working (void);
static gboolean frida_find_restart_with_dyld_in_cache (const GumDarwinSymbolDetails * details, gpointer user_data);
static GumAddress frida_find_run_initializers_call (mach_port_t task, GumCpuType cpu_type, GumAddress start);
static GHashTable * frida_find_modinit_strcmp_checks (mach_port_t task, GumDarwinModule * dyld);
static GumAddress frida_find_function_end (mach_port_t task, GumCpuType cpu_type, GumAddress start, gsize max_size);
@@ -2108,8 +2107,18 @@ _frida_darwin_helper_backend_prepare_spawn_instance_for_injection (FridaDarwinHe
frida_spawn_instance_set_nth_breakpoint (instance, i++, sim_notify_address, FRIDA_BREAKPOINT_REPEAT_ALWAYS);
if (instance->dyld_flavor == FRIDA_DYLD_V4_PLUS)
{
GumAddress restart_with_dyld_in_cache = 0;
gum_darwin_module_enumerate_symbols (dyld, frida_find_restart_with_dyld_in_cache, &restart_with_dyld_in_cache);
GumAddress restart_with_dyld_in_cache = gum_darwin_module_resolve_symbol_address (dyld,
"__ZN5dyld422restartWithDyldInCacheEPKNS_10KernelArgsEPKN6mach_o6HeaderEPK15DyldSharedCachePv");
if (restart_with_dyld_in_cache == 0)
{
restart_with_dyld_in_cache = gum_darwin_module_resolve_symbol_address (dyld,
"__ZN5dyld422restartWithDyldInCacheEPKNS_10KernelArgsEPKN5dyld39MachOFileEPK15DyldSharedCachePv");
}
if (restart_with_dyld_in_cache == 0)
{
restart_with_dyld_in_cache = gum_darwin_module_resolve_symbol_address (dyld,
"__ZN5dyld422restartWithDyldInCacheEPKNS_10KernelArgsEPKN5dyld39MachOFileEPv");
}
if (restart_with_dyld_in_cache != 0)
frida_spawn_instance_set_nth_breakpoint (instance, i++, restart_with_dyld_in_cache, FRIDA_BREAKPOINT_REPEAT_NEVER);
}
@@ -5433,19 +5442,6 @@ frida_is_hardware_breakpoint_support_working (void)
#endif
}
static gboolean
frida_find_restart_with_dyld_in_cache (const GumDarwinSymbolDetails * details, gpointer user_data)
{
if (strstr (details->name, "restartWithDyldInCache") != NULL)
{
GumAddress * restart_with_dyld_in_cache = user_data;
*restart_with_dyld_in_cache = details->address;
return FALSE;
}
return TRUE;
}
static GumAddress
frida_find_run_initializers_call (mach_port_t task, GumCpuType cpu_type, GumAddress start)
{
+1 -1
View File
@@ -512,7 +512,7 @@ namespace Frida {
tempdir));
FileUtils.chmod (helper.path, 0700);
#else
helper = new InstalledHelperFile.for_path (Frida.helper_path);
helper = new InstalledHelperFile.for_path (Config.FRIDA_HELPER_PATH);
#endif
}
+1 -1
View File
@@ -23,5 +23,5 @@ custom_target('core-devkit',
meson.current_build_dir(),
] + devkit_options,
install: true,
install_dir: get_option('libdir') / frida_libdir_name / 'devkits' / 'core'
install_dir: get_option('libdir') / 'frida' / 'devkits' / 'core'
)
+19 -32
View File
@@ -118,7 +118,13 @@ namespace Frida {
}
construct {
_icon = make_provider_icon (Frida.Data.Icons.get_droidy_png_blob ().data);
var builder = new VariantBuilder (VariantType.VARDICT);
builder.add ("{sv}", "format", new Variant.string ("rgba"));
builder.add ("{sv}", "width", new Variant.uint16 (16));
builder.add ("{sv}", "height", new Variant.uint16 (16));
var image = new Bytes (Base64.decode ("AAAAAAAAAAAAAAAAAAAAAP///0DS4pz/////MP///0D///9A////MNflqP////9AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8QzN6Q/7vTa/+vy1L/r8tS/7vTa//O4JXv////EAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1eSkz6TEOf+kxDn/pMQ5/6TEOf+kxDn/pMQ5/9XkpM8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8vfjcKrIRf+kxDn/pMQ5/6TEOf+kxDn/pMQ5/6TEOf+qyEX/8PXeYAAAAAAAAAAAAAAAAAAAAAAAAAAA////QNLinL+kxDn/pMQ5/6TEOf+kxDn/pMQ5/6TEOf+kxDn/pMQ5/97qt6////9AAAAAAAAAAAAAAAAA2eatv7vTa//G2oP/pMQ5/6TEOf+kxDn/pMQ5/6TEOf+kxDn/pMQ5/6TEOf/M3pD/u9Nr/9nmrb8AAAAAAAAAANLinP+kxDn/u9Nr/6TEOf+kxDn/pMQ5/6TEOf+kxDn/pMQ5/6TEOf+kxDn/u9Nr/6TEOf/S4pz/AAAAAAAAAADS4pz/pMQ5/7vTa/+kxDn/pMQ5/6TEOf+kxDn/pMQ5/6TEOf+kxDn/pMQ5/7vTa/+kxDn/0uKc/wAAAAAAAAAA0uKc/6TEOf+702v/pMQ5/6TEOf+kxDn/pMQ5/6TEOf+kxDn/pMQ5/6TEOf+702v/pMQ5/9LinP8AAAAAAAAAANLinP+kxDn/u9Nr/6TEOf+kxDn/pMQ5/6TEOf+kxDn/pMQ5/6TEOf+kxDn/u9Nr/6TEOf/S4pz/AAAAAAAAAADO4JXvpMQ5/8DWd/+kxDn/pMQ5/6TEOf+kxDn/pMQ5/6TEOf+kxDn/pMQ5/8DWd/+kxDn/zuCV7wAAAAAAAAAA7fPXUNLinIDl7sbfpMQ5/6TEOf+kxDn/pMQ5/6TEOf+kxDn/pMQ5/6TEOf/l7sbf0uKcgO3z11AAAAAAAAAAAAAAAAAAAAAA8PXeYMDWd/+qyEX/pMQ5/6/LUv+vy1L/pMQ5/6rIRf/A1nf/7fPXUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAu9Nr/6TEOf/C2Hu/wth7v6TEOf+702v/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALvTa/+kxDn/wth7v8LYe7+kxDn/u9Nr/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADc6LPPu9Nr/+HrvY/h672Pu9Nr/9nmrb8AAAAAAAAAAAAAAAAAAAAAAAAAAA=="));
builder.add ("{sv}", "image", Variant.new_from_data (new VariantType ("ay"), image.get_data (), true, image));
_icon = builder.end ();
}
public async void close (Cancellable? cancellable) throws IOError {
@@ -129,18 +135,7 @@ namespace Frida {
if (host_session != null)
throw new Error.INVALID_ARGUMENT ("Already created");
string control_endpoint = ("tcp:%" + uint16.FORMAT_MODIFIER + "u").printf (DEFAULT_CONTROL_PORT);
if (options != null) {
Value? control_endpoint_val = options.map["control-endpoint"];
if (control_endpoint_val != null) {
if (!control_endpoint_val.holds (typeof (string)))
throw new Error.INVALID_ARGUMENT ("The control-endpoint option must be a string");
control_endpoint = control_endpoint_val.get_string ();
}
}
host_session = new DroidyHostSession (device_details, this, control_endpoint);
host_session = new DroidyHostSession (device_details, this);
host_session.agent_session_detached.connect (on_agent_session_detached);
return host_session;
@@ -236,11 +231,6 @@ namespace Frida {
construct;
}
public string control_endpoint {
get;
construct;
}
private Promise<AndroidHelperClient>? helper_client_request;
private Droidy.ShellSession? helper_shell;
@@ -268,12 +258,10 @@ namespace Frida {
private const double MIN_SERVER_CHECK_INTERVAL = 5.0;
private const string GADGET_APP_ID = "re.frida.Gadget";
public DroidyHostSession (Droidy.DeviceDetails device_details, HostChannelProvider channel_provider,
string control_endpoint) {
public DroidyHostSession (Droidy.DeviceDetails device_details, HostChannelProvider channel_provider) {
Object (
device_details: device_details,
channel_provider: channel_provider,
control_endpoint: control_endpoint
channel_provider: channel_provider
);
}
@@ -302,9 +290,8 @@ namespace Frida {
if (helper_client_request != null) {
AndroidHelperClient? helper = yield try_get_helper_client (cancellable);
if (helper != null) {
var transport = (AndroidHelperStreamTransport) helper.transport;
on_helper_stream_transport_closed (transport);
yield transport.close (cancellable);
on_helper_client_closed (helper);
yield helper.close (cancellable);
}
}
@@ -850,7 +837,9 @@ namespace Frida {
DBusConnection? connection = null;
try {
var stream = yield channel_provider.open_channel (control_endpoint, cancellable);
var stream = yield channel_provider.open_channel (
("tcp:%" + uint16.FORMAT_MODIFIER + "u").printf (DEFAULT_CONTROL_PORT),
cancellable);
WebServiceTransport transport = PLAIN;
string? origin = null;
@@ -1071,10 +1060,8 @@ namespace Frida {
throw e;
}
var transport = new AndroidHelperStreamTransport (client.stream);
transport.closed.connect (on_helper_stream_transport_closed);
var helper = new AndroidHelperClient (transport);
var helper = new AndroidHelperClient (client.stream);
helper.closed.connect (on_helper_client_closed);
helper_shell = shell;
@@ -1093,8 +1080,8 @@ namespace Frida {
}
}
private void on_helper_stream_transport_closed (AndroidHelperStreamTransport transport) {
transport.closed.disconnect (on_helper_stream_transport_closed);
private void on_helper_client_closed (AndroidHelperClient helper) {
helper.closed.disconnect (on_helper_client_closed);
helper_client_request = null;
if (helper_shell != null) {
+4 -28
View File
@@ -1,9 +1,7 @@
#include "frida-core.h"
#include <gum/gum.h>
#if defined (HAVE_GIOAPPLE)
# include <gioapple.h>
#elif defined (HAVE_GIOOPENSSL)
#ifdef HAVE_GIOOPENSSL
# include <gioopenssl.h>
#endif
@@ -12,11 +10,6 @@ static GThread * main_thread;
static GMainLoop * main_loop;
static GMainContext * main_context;
#ifndef HAVE_EMBEDDED_ASSETS
extern void _frida_init_asset_paths (void);
extern void _frida_deinit_asset_paths (void);
#endif
static gpointer run_main_loop (gpointer data);
static gboolean dummy_callback (gpointer data);
static gboolean stop_main_loop (gpointer data);
@@ -32,27 +25,18 @@ frida_init_with_runtime (FridaRuntime rt)
{
static gsize frida_initialized = FALSE;
#ifdef HAVE_FRIDA_GLIB
runtime = rt;
g_thread_set_garbage_handler (frida_on_pending_garbage, NULL);
glib_init ();
#endif
if (g_once_init_enter (&frida_initialized))
{
runtime = rt;
#ifdef HAVE_FRIDA_GLIB
gio_init ();
#endif
gum_init ();
#ifndef HAVE_EMBEDDED_ASSETS
_frida_init_asset_paths ();
#endif
frida_error_quark (); /* Initialize early so GDBus will pick it up */
#if defined (HAVE_GIOAPPLE)
g_io_module_apple_register ();
#elif defined (HAVE_GIOOPENSSL)
#ifdef HAVE_GIOOPENSSL
g_io_module_openssl_register ();
#endif
@@ -125,20 +109,12 @@ frida_deinit (void)
frida_invalidate_dbus_context ();
gum_shutdown ();
#ifdef HAVE_FRIDA_GLIB
gio_shutdown ();
glib_shutdown ();
#endif
#ifndef HAVE_EMBEDDED_ASSETS
_frida_deinit_asset_paths ();
#endif
gum_deinit ();
#ifdef HAVE_FRIDA_GLIB
gio_deinit ();
glib_deinit ();
#endif
}
GMainContext *
+1 -68
View File
@@ -581,40 +581,6 @@ namespace Frida {
return close_request != null;
}
public void override_option (string name, Variant val) throws Error {
Value v;
switch (val.classify ()) {
case BOOLEAN:
v = Value (typeof (bool));
v.set_boolean (val.get_boolean ());
break;
case INT64:
v = Value (typeof (int64));
v.set_int64 (val.get_int64 ());
break;
case UINT64:
v = Value (typeof (uint64));
v.set_uint64 (val.get_uint64 ());
break;
case DOUBLE:
v = Value (typeof (double));
v.set_double (val.get_double ());
break;
case STRING:
v = Value (typeof (string));
v.set_string (val.get_string ());
break;
default:
throw new Error.INVALID_ARGUMENT ("Unsupported option type");
}
lock (host_session_options) {
if (host_session_options == null)
host_session_options = new HostSessionOptions ();
host_session_options.map[name] = v;
}
}
public async HashTable<string, Variant> query_system_parameters (Cancellable? cancellable = null) throws Error, IOError {
check_open ();
@@ -1366,11 +1332,7 @@ namespace Frida {
host_session_request = new Promise<HostSession> ();
try {
HostSessionOptions? opts;
lock (host_session_options)
opts = (host_session_options != null) ? host_session_options.copy () : null;
var session = yield provider.create (manager, opts, cancellable);
var session = yield provider.create (manager, host_session_options, cancellable);
attach_host_session (session);
current_host_session = session;
@@ -3621,39 +3583,11 @@ namespace Frida {
}
}
#if !HAVE_EMBEDDED_ASSETS
internal string helper_path;
internal string agent_path;
#if COMPILER_BACKEND_INSTALLED_LIBRARY || COMPILER_BACKEND_INSTALLED_EXECUTABLE
internal string compiler_backend_path;
#endif
public void _init_asset_paths () {
var location = AssetLocation.detect ();
helper_path = location.derive_asset_path ("<arch>", Config.FRIDA_HELPER_NAME);
agent_path = location.derive_asset_path ("<arch>", Config.FRIDA_AGENT_NAME);
#if COMPILER_BACKEND_INSTALLED_LIBRARY || COMPILER_BACKEND_INSTALLED_EXECUTABLE
compiler_backend_path = location.derive_plugin_path (Config.FRIDA_COMPILER_BACKEND_NAME);
#endif
}
public void _deinit_asset_paths () {
helper_path = null;
agent_path = null;
#if COMPILER_BACKEND_INSTALLED_LIBRARY || COMPILER_BACKEND_INSTALLED_EXECUTABLE
compiler_backend_path = null;
#endif
}
#endif
#if HAVE_FRIDA_GLIB
private Mutex gc_mutex;
private uint gc_generation = 0;
private bool gc_scheduled = false;
#endif
public void on_pending_garbage (void * data) {
#if HAVE_FRIDA_GLIB
gc_mutex.lock ();
gc_generation++;
bool already_scheduled = gc_scheduled;
@@ -3679,6 +3613,5 @@ namespace Frida {
return repeat;
});
#endif
}
}
-401
View File
@@ -1,401 +0,0 @@
[CCode (gir_namespace = "FridaFruity", gir_version = "1.0")]
namespace Frida.Fruity {
public class CsSignature : Object {
public uint32 version;
public uint32 pid;
public uint32 stuff;
public uint32 flags;
public Gee.List<CsSigOwner> owners = new Gee.ArrayList<CsSigOwner> ();
private CsSegIndexEntry[]? seg_index = null;
private uint32 seg_index_gen = 0;
private struct CsSegIndexEntry {
public uint64 start;
public uint64 end;
public unowned CsSigOwner owner;
}
public void apply_refresh (CsSignature fresh, uint32 gen) {
foreach (var cur in owners) {
if (cur.mapped_gen_end != 0)
continue;
bool still_present = false;
foreach (var f in fresh.owners) {
if (cur.uuid.compare (f.uuid) == 0) {
still_present = true;
break;
}
}
if (!still_present)
cur.mapped_gen_end = gen;
}
foreach (var f in fresh.owners) {
CsSigOwner? cur = null;
foreach (var existing in owners) {
if (existing.uuid.compare (f.uuid) == 0) {
cur = existing;
break;
}
}
if (cur == null) {
f.mapped_gen_start = gen;
f.mapped_gen_end = 0;
owners.add (f);
} else {
uint32 start = cur.mapped_gen_start;
uint32 end = cur.mapped_gen_end;
cur.path = f.path;
cur.image_base = f.image_base;
cur.image_end = f.image_end;
cur.segments = f.segments;
cur.version = f.version;
cur.mapped_gen_start = start;
cur.mapped_gen_end = end;
}
}
invalidate_index ();
}
public void note_unmapped_uuid (Bytes uuid, uint32 gen) {
foreach (var o in owners) {
if (o.mapped_gen_end != 0)
continue;
if (o.uuid.compare (uuid) == 0) {
o.mapped_gen_end = gen;
invalidate_index ();
return;
}
}
}
public void resolve_addresses (uint32 gen, uint64[] addrs, AddressResolved on_symbol, ModulesReady on_modules) {
ensure_index (gen);
var used_owner_to_mod = new Gee.HashMap<CsSigOwner, uint32> ();
var module_list = new Gee.ArrayList<CsSigOwner> ();
foreach (var addr in addrs) {
CsSigOwner? owner;
uint32 rel;
if (!try_resolve (addr, out owner, out rel)) {
on_symbol (addr, uint32.MAX, 0);
continue;
}
uint32 mod_idx;
if (!used_owner_to_mod.has_key (owner)) {
mod_idx = (uint32) module_list.size;
used_owner_to_mod[owner] = mod_idx;
module_list.add (owner);
} else {
mod_idx = used_owner_to_mod[owner];
}
on_symbol (addr, mod_idx, rel);
}
on_modules (module_list);
}
public delegate void AddressResolved (uint64 addr, uint32 module_index, uint32 rel);
public delegate void ModulesReady (Gee.List<CsSigOwner> modules);
private void ensure_index (uint32 gen) {
if (seg_index != null && seg_index_gen == gen)
return;
var tmp = new Array<CsSegIndexEntry> (false, false);
foreach (var owner in owners) {
if (!owner_is_mapped_at (owner, gen))
continue;
foreach (var seg in owner.segments) {
if (seg.name == "__PAGEZERO")
continue;
tmp.append_val (CsSegIndexEntry () {
start = seg.vmaddr,
end = seg.vmaddr + seg.vmsize,
owner = owner,
});
}
}
tmp.sort ((a, b) => {
if (a.start < b.start)
return -1;
if (a.start > b.start)
return 1;
return 0;
});
seg_index = tmp.steal ();
seg_index_gen = gen;
}
private void invalidate_index () {
seg_index = null;
seg_index_gen = 0;
}
private bool try_resolve (uint64 addr, out CsSigOwner? owner, out uint32 rel) {
owner = null;
rel = 0;
int n = seg_index.length;
if (n == 0)
return false;
int lo = 0;
int hi = n - 1;
int best = -1;
while (lo <= hi) {
int mid = lo + ((hi - lo) / 2);
if (seg_index[mid].start <= addr) {
best = mid;
lo = mid + 1;
} else {
hi = mid - 1;
}
}
if (best == -1)
return false;
for (int i = best; i >= 0; i--) {
var e = seg_index[i];
if (e.start > addr)
continue;
if (addr < e.end) {
owner = e.owner;
rel = (uint32) (addr - owner.image_base);
return true;
}
}
return false;
}
private static bool owner_is_mapped_at (CsSigOwner owner, uint32 gen) {
if (gen < owner.mapped_gen_start)
return false;
uint32 end = owner.mapped_gen_end;
if (end == 0)
return true;
return gen < end;
}
}
public class CsSigOwner : Object {
public Bytes uuid;
public uint32 a;
public uint32 flags;
public uint64 load_timestamp;
public uint64 unload_timestamp;
public uint32 cpu_type;
public uint32 cpu_subtype;
public string path;
public uint64 image_base;
public uint64 image_end;
public Gee.List<CsSigSegment> segments = new Gee.ArrayList<CsSigSegment> ();
public string? version;
public uint32 mapped_gen_start = 1;
public uint32 mapped_gen_end = 0;
}
public class CsSigSegment {
public string name;
public uint64 vmaddr;
public uint64 vmsize;
}
public sealed class CsSignatureParser : Object {
private Buffer buf;
private BufferReader r;
public CsSignatureParser (Bytes blob) {
buf = new Buffer (blob, LITTLE_ENDIAN, 8);
r = new BufferReader (buf);
}
public CsSignature parse () throws Error {
uint32 magic = r.read_uint32 ();
uint32 version = r.read_uint32 ();
uint32 pid = r.read_uint32 ();
uint32 stuff = r.read_uint32 ();
uint32 flags = r.read_uint32 ();
uint32 owner_count = r.read_uint32 ();
if (magic != 0xff01ff02u)
throw new Error.PROTOCOL ("Bad signature magic 0x%08x", magic);
var sig = new CsSignature ();
sig.version = version;
sig.pid = pid;
sig.stuff = stuff;
sig.flags = flags;
for (uint32 i = 0; i != owner_count; i++)
sig.owners.add (parse_owner ());
decode_optional_data (sig);
return sig;
}
private CsSigOwner parse_owner () throws Error {
var o = new CsSigOwner ();
o.uuid = r.read_bytes (16);
o.a = r.read_uint32 ();
o.flags = r.read_uint32 () & 0x7fffffff;
o.load_timestamp = r.read_uint64 ();
o.unload_timestamp = r.read_uint64 ();
o.cpu_type = r.read_uint32 ();
o.cpu_subtype = r.read_uint32 ();
uint32 nsegs = r.read_uint32 ();
uint32 str_len = r.read_uint32 ();
o.path = r.read_fixed_string (str_len);
for (uint32 i = 0; i != nsegs; i++) {
var s = new CsSigSegment ();
s.name = r.read_fixed_string (16);
s.vmaddr = r.read_uint64 ();
s.vmsize = r.read_uint64 ();
o.segments.add (s);
}
o.segments.sort ((a, b) => {
if (a.vmaddr < b.vmaddr)
return -1;
if (a.vmaddr > b.vmaddr)
return 1;
return 0;
});
uint64 image_base = uint64.MAX;
uint64 image_end = 0;
foreach (var seg in o.segments) {
if (seg.name != "__PAGEZERO" && seg.vmaddr < image_base)
image_base = seg.vmaddr;
uint64 seg_end = seg.vmaddr + seg.vmsize;
if (seg_end > image_end)
image_end = seg_end;
}
o.image_base = image_base;
o.image_end = image_end;
return o;
}
private void decode_optional_data (CsSignature sig) throws Error {
if (r.available < 8)
return;
size_t start = r.offset;
uint64 hdr = r.read_uint64 ();
uint32 magic = (uint32) (hdr & 0xffffffffu);
uint32 sel = (uint32) (hdr >> 32);
if (magic != 0x00c0ffeeu) {
r.seek (start);
return;
}
if (sel == 2) {
if (r.available < 0x18)
throw new Error.PROTOCOL ("Optional v2 truncated");
r.skip (0x18);
return;
}
if (sel == 3) {
skip_optional_v3 ();
return;
}
if (sel != 4)
return;
size_t v3_start = r.offset;
uint32 count = skip_optional_v3 ();
size_t table_end = v3_start + 0x38 + (size_t) count * 0x60;
if (table_end + 4 > buf.size)
throw new Error.PROTOCOL ("Optional v4 truncated");
r.seek (table_end);
uint32 strings_size = r.read_uint32 ();
size_t strings_start = r.offset;
size_t strings_end = strings_start + (size_t) strings_size;
if (strings_end > buf.size)
throw new Error.PROTOCOL ("Optional v4 strings overrun");
r.seek (strings_start);
for (int i = 0; i < sig.owners.size; i++) {
if (r.offset >= strings_end)
throw new Error.PROTOCOL ("Optional v4 strings truncated");
sig.owners[i].version = r.read_string ();
}
r.seek (v3_start + 0x3c + (size_t) count * 0x60 + (size_t) strings_size);
}
private uint32 skip_optional_v3 () throws Error {
if (r.available < 0x38)
throw new Error.PROTOCOL ("Optional v3 truncated");
size_t base_offset = r.offset;
r.skip (0x30);
r.read_uint8 ();
r.skip (3);
uint32 count = r.read_uint32 ();
size_t total = 0x38 + (size_t) count * 0x60;
if (base_offset + total > buf.size)
throw new Error.PROTOCOL ("Optional v3 overrun");
r.seek (base_offset + total);
return count;
}
}
}
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+2 -2
View File
@@ -50,8 +50,8 @@ namespace Frida.Fruity {
if (rr.key.klass != IN)
throw new Error.PROTOCOL ("Expected an AAAA record of class IN");
var subreader = new DnsPacketReader (rr.data);
unowned uint8[] raw_address = subreader.reader.read_data (16);
var address = new InetAddress.from_bytes (raw_address, IPV6);
var raw_address = subreader.reader.read_bytes (16);
var address = new InetAddress.from_bytes (raw_address.get_data (), IPV6);
return new DnsAaaaRecord () {
key = rr.key,
ttl = rr.ttl,
+30 -787
View File
@@ -69,20 +69,6 @@ namespace Frida.Fruity {
return result;
}
public async CsSignature query_symbolicator_signature (uint pid, Cancellable? cancellable = null) throws Error, IOError {
var args = new DTXArgumentListBuilder ()
.append_object (new NSNumber.from_integer (pid))
.append_object (new NSString (""));
var response = yield channel.invoke ("symbolicatorSignatureForPid:trackingSelector:", args, cancellable);
NSData? data = response as NSData;
if (data == null)
throw new Error.PROTOCOL ("Malformed response");
var parser = new CsSignatureParser (data.bytes);
return parser.parse ();
}
private static string resolve_real_app_name (string name) {
if (name.has_prefix ("/var/"))
return "/private" + name;
@@ -321,8 +307,6 @@ namespace Frida.Fruity {
}
public sealed class ProcessControlService : Object, AsyncInitable {
public signal void process_terminated (uint pid, int exit_code, int crashing_signal);
public HostChannelProvider channel_provider {
get;
construct;
@@ -351,746 +335,15 @@ namespace Frida.Fruity {
var connection = yield DTXConnection.obtain (channel_provider, cancellable);
channel = connection.make_channel ("com.apple.instruments.server.services.processcontrol");
channel.invocation.connect (on_invocation);
return true;
}
public async uint process_identifier_for_bundle_identifier (string bundle_id, Cancellable? cancellable = null)
throws Error, IOError {
var args = new DTXArgumentListBuilder ()
.append_object (new NSString (bundle_id));
var response = yield channel.invoke ("processIdentifierForBundleIdentifier:", args, cancellable);
NSNumber? pid = response as NSNumber;
if (pid == null)
throw new Error.PROTOCOL ("Malformed response");
return (uint) pid.integer;
}
public async bool is_pid_debuggable (uint pid, Cancellable? cancellable = null) throws Error, IOError {
var args = new DTXArgumentListBuilder ()
.append_object (new NSNumber.from_integer (pid));
var response = yield channel.invoke ("isPidDebuggable:", args, cancellable);
NSNumber? is_debuggable = response as NSNumber;
if (is_debuggable == null)
throw new Error.PROTOCOL ("Malformed response");
return is_debuggable.boolean;
}
public async void start_observing_pid (uint pid, Cancellable? cancellable = null) throws Error, IOError {
var args = new DTXArgumentListBuilder ()
.append_object (new NSNumber.from_integer (pid));
yield channel.invoke ("startObservingPid:", args, cancellable);
}
public async void stop_observing_pid (uint pid, Cancellable? cancellable = null) throws Error, IOError {
var args = new DTXArgumentListBuilder ()
.append_object (new NSNumber.from_integer (pid));
yield channel.invoke ("stopObservingPid:", args, cancellable);
}
public async uint launch (string bundle_id, LaunchOptions? options = null, Cancellable? cancellable = null)
throws Error, IOError {
var opts = options;
if (opts == null)
opts = new LaunchOptions ();
var args_val = new NSArray ();
foreach (unowned string arg in opts.arguments)
args_val.add_object (new NSString (arg));
var env_val = new NSDictionary ();
foreach (unowned string entry in opts.environment) {
string[] tokens = entry.split ("=", 2);
if (tokens.length != 2)
throw new Error.INVALID_ARGUMENT ("Invalid environment variable entry: %s", entry);
env_val.set_value (tokens[0], new NSString (tokens[1]));
}
var opts_val = new NSDictionary ();
opts_val.set_value ("StartSuspendedKey", new NSNumber.from_boolean (opts.launch_mode == SUSPENDED));
opts_val.set_value ("KillExisting", new NSNumber.from_boolean (opts.existing_instance_policy == KILL));
// TODO: Support CaptureOutput + iODestinationKey
var dtx_args = new DTXArgumentListBuilder ()
.append_object (new NSString (""))
.append_object (new NSString (bundle_id))
.append_object (env_val)
.append_object (args_val)
.append_object (opts_val);
var response = yield channel.invoke (
"launchSuspendedProcessWithDevicePath:bundleIdentifier:environment:arguments:options:",
dtx_args, cancellable);
NSNumber? pid = response as NSNumber;
if (pid == null)
throw new Error.PROTOCOL ("Malformed response");
return (uint) pid.integer;
}
public async void kill (uint pid, Cancellable? cancellable = null) throws Error, IOError {
var args = new DTXArgumentListBuilder ()
.append_object (new NSNumber.from_integer (pid));
yield channel.invoke ("killPid:", args, cancellable);
}
public async void send_signal (uint pid, uint sig, Cancellable? cancellable = null) throws Error, IOError {
var args = new DTXArgumentListBuilder ()
.append_object (new NSNumber.from_integer (sig))
.append_object (new NSNumber.from_integer (pid));
yield channel.invoke ("sendSignal:toPid:", args, cancellable);
}
private void on_invocation (string method_name, DTXArgumentList args, DTXMessageTransportFlags transport_flags) {
if (method_name == "processWithPID:terminatedWithExitCode:orCrashingSignal:") {
if (args.elements.length != 3)
return;
uint pid;
if (!try_parse_int (args.elements[0], out pid))
return;
int exit_code = -1;
int crashing_signal = -1;
if (!try_parse_int (args.elements[1], out exit_code)) {
if (!try_parse_int (args.elements[2], out crashing_signal))
return;
}
process_terminated (pid, exit_code, crashing_signal);
}
}
private bool try_parse_int (Value v, out int i) {
i = -1;
if (!v.holds (typeof (NSNumber)))
return false;
i = (int) ((NSNumber) v.get_object ()).integer;
return true;
}
}
public sealed class LaunchOptions : Object {
public string[] arguments {
get;
set;
default = {};
}
public string[] environment {
get;
set;
default = {};
}
public LaunchMode launch_mode {
get;
set;
default = LaunchMode.NORMAL;
}
public ExistingInstancePolicy existing_instance_policy {
get;
set;
default = ExistingInstancePolicy.KEEP;
}
}
public enum LaunchMode {
NORMAL,
SUSPENDED
}
public enum ExistingInstancePolicy {
KEEP,
KILL
}
public sealed class CoreProfileService : Object, AsyncInitable {
public signal void stackshot (Bytes blob);
public signal void kperfdata (Bytes blob);
public HostChannelProvider channel_provider {
get;
construct;
}
private DTXChannel channel;
private CoreProfileService (HostChannelProvider channel_provider) {
Object (channel_provider: channel_provider);
}
public static async CoreProfileService open (HostChannelProvider channel_provider, Cancellable? cancellable = null)
throws Error, IOError {
var service = new CoreProfileService (channel_provider);
try {
yield service.init_async (Priority.DEFAULT, cancellable);
} catch (GLib.Error e) {
throw_api_error (e);
}
return service;
}
private async bool init_async (int io_priority, Cancellable? cancellable) throws Error, IOError {
var connection = yield DTXConnection.obtain (channel_provider, cancellable);
channel = connection.make_channel ("com.apple.instruments.server.services.coreprofilesessiontap");
channel.notification.connect (on_notification);
channel.data.connect (on_data);
return true;
}
public async void set_config (KtraceConfig config, Cancellable? cancellable = null) throws Error, IOError {
var args = new DTXArgumentListBuilder ()
.append_object (config.encode ());
yield channel.invoke ("setConfig:", args, cancellable);
}
public async void start (Cancellable? cancellable = null) throws Error, IOError {
yield channel.invoke ("start", null, cancellable);
}
public async void stop (Cancellable? cancellable = null) throws Error, IOError {
yield channel.invoke ("stop", null, cancellable);
}
private void on_notification (NSObject obj) {
// printerr ("on_notification(): %s\n", obj.to_string ());
}
private void on_data (Bytes blob) {
if (Kcdata.is_stackshot (blob))
stackshot (blob);
else
kperfdata (blob);
}
}
public abstract class TapConfig : Object {
public TapRecordingMode buffer_mode {
get {
return _buffer_mode;
}
set {
_buffer_mode = value;
if (value != POLLED)
_polling_interval = 0;
}
}
public uint64 polling_interval {
get;
set;
default = 500;
}
public uint64 window_size {
get;
set;
default = 0;
}
public bool spool_to_disk_when_possible {
get;
set;
default = false;
}
public bool discard_heartbeats_when_possible {
get;
set;
default = false;
}
private TapRecordingMode _buffer_mode = POLLED;
internal virtual NSDictionary encode () {
var dict = new NSDictionary ();
dict.set_value ("bm", new NSNumber.from_integer (_buffer_mode));
if (_polling_interval != 0)
dict.set_value ("ur", new NSNumber.from_integer ((int64) _polling_interval));
if (_window_size != 0)
dict.set_value ("ws", new NSNumber.from_integer ((int64) _window_size));
if (_spool_to_disk_when_possible)
dict.set_value ("s2d", new NSNumber.from_boolean (true));
if (_discard_heartbeats_when_possible)
dict.set_value ("nohb", new NSNumber.from_boolean (true));
return dict;
}
}
public enum TapRecordingMode {
POLLED,
IMMEDIATE,
WINDOWED,
}
public sealed class KtraceConfig : TapConfig {
public bool can_use_raw_ktrace_file {
get;
set;
default = false;
}
public KtraceRecordingPriority recording_priority {
get;
set;
default = FOREGROUND;
}
public uint collection_interval {
get;
set;
default = 0;
}
public uint64 buffer_size_override {
get;
set;
default = 0;
}
public uint64 buffer_size_override_clamping {
get;
set;
default = 0;
}
public NSDictionary? provider_options {
get;
set;
default = null;
}
private Gee.List<KtraceTapTriggerConfig> trigger_configs = new Gee.ArrayList<KtraceTapTriggerConfig> ();
public void add_trigger_config (KtraceTapTriggerConfig tc) {
trigger_configs.add (tc);
}
internal override NSDictionary encode () {
var dict = base.encode ();
if (can_use_raw_ktrace_file)
dict.set_value ("curkt", new NSNumber.from_boolean (true));
dict.set_value ("rp", new NSNumber.from_integer (_recording_priority));
if (_collection_interval != 0)
dict.set_value ("kco", new NSNumber.from_integer (_collection_interval));
if (_buffer_size_override != 0)
dict.set_value ("bso", new NSNumber.from_integer ((int64) _buffer_size_override));
if (_buffer_size_override_clamping != 0)
dict.set_value ("bsoc", new NSNumber.from_integer ((int64) _buffer_size_override_clamping));
if (_provider_options != null)
dict.set_value ("po", _provider_options);
var tc = new NSArray ();
foreach (var cfg in trigger_configs)
tc.add_object (cfg.encode ());
dict.set_value ("tc", tc);
return dict;
}
}
public enum KtraceRecordingPriority {
BACKGROUND = 10,
FOREGROUND = 100,
}
public sealed class KtraceTapTriggerConfig : Object {
public KtraceTapTriggerKind kind {
get;
construct;
}
public KdebugCodeSet? filter {
get;
set;
}
public bool is_all_processes {
get {
return included_pids == null;
}
set {
if (value)
included_pids = null;
else
ensure_included_pids ();
}
}
public uint callstack_frame_depth {
get;
set;
default = 0;
}
public KtraceTapActions actions {
get;
default = new KtraceTapActions ();
}
private Gee.Set<uint>? included_pids = null;
public KtraceTapTriggerConfig (KtraceTapTriggerKind kind) {
Object (kind: kind);
}
public void include_pid (uint pid) {
ensure_included_pids ().add (pid);
}
private unowned Gee.Set<uint> ensure_included_pids () {
if (included_pids == null)
included_pids = new Gee.HashSet<uint> ();
return included_pids;
}
internal NSDictionary encode () {
var dict = new NSDictionary ();
dict.set_value ("uuid", new NSString (Uuid.string_random ().up ()));
dict.set_value ("tk", new NSNumber.from_integer (_kind));
if (_filter != null) {
dict.set_value ("kdf", new NSString (_filter.legacy_xml));
dict.set_value ("kdf2", _filter.kdebug_codes);
}
if (included_pids != null) {
var pf = new NSArray ();
foreach (var pid in included_pids)
pf.add_object (new NSNumber.from_integer (pid));
dict.set_value ("pf", pf);
}
if (_callstack_frame_depth != 0)
dict.set_value ("csd", new NSNumber.from_integer (_callstack_frame_depth));
var actions = _actions.items;
if (!actions.is_empty) {
var arr = new NSArray ();
foreach (var action in actions)
arr.add_object (action.encode ());
dict.set_value ("ta", arr);
}
return dict;
}
}
public enum KtraceTapTriggerKind {
TIME = 1,
PMI,
KDEBUG,
}
public sealed class KtraceTapActions : Object {
internal Gee.List<KtraceTapAction> items = new Gee.ArrayList<KtraceTapAction> ();
public unowned KtraceTapActions add (KtraceTapAction action) {
items.add (action);
return this;
}
public unowned KtraceTapActions add_stack_collection (KtraceTapStackCollectionMode mode) {
items.add (new KtraceTapStackCollectionAction (mode));
return this;
}
public unowned KtraceTapActions add_baseline () {
items.add (new KtraceTapAction0 ());
items.add (new KtraceTapAction2 ());
return this;
}
public unowned KtraceTapActions add_pmc_event (string event_name, string counter_name, uint32 extra = 0) {
items.add (new KtraceTapAddPmcEventAction (event_name, counter_name, extra));
return this;
}
public unowned KtraceTapActions add_kdebug_codeset (KdebugCodeSet codeset) {
items.add (new KtraceTapAddKdebugCodeSetAction (codeset.kdebug_codes));
return this;
}
public unowned KtraceTapActions add_kdebug_legacy_backtrace_filter () {
items.add (new KtraceTapKdebugBacktraceFilterAction ());
return this;
}
}
public enum KtraceTapActionKind {
ACTION0,
STACK_COLLECTION,
ACTION2,
KDEBUG_BACKTRACE_FILTER,
ADD_PMC_EVENT,
ADD_KDEBUG_CODESET,
}
public abstract class KtraceTapAction : Object {
public abstract KtraceTapActionKind kind {
get;
}
internal abstract NSArray encode ();
}
public sealed class KtraceTapAction0 : KtraceTapAction {
public override KtraceTapActionKind kind {
get {
return ACTION0;
}
}
internal override NSArray encode () {
var a = new NSArray ();
a.add_object (new NSNumber.from_integer (kind));
return a;
}
}
public sealed class KtraceTapAction2 : KtraceTapAction {
public override KtraceTapActionKind kind {
get {
return ACTION2;
}
}
internal override NSArray encode () {
var a = new NSArray ();
a.add_object (new NSNumber.from_integer (kind));
return a;
}
}
public sealed class KtraceTapStackCollectionAction : KtraceTapAction {
public KtraceTapStackCollectionMode mode {
get {
return _mode;
}
set {
_mode = value;
}
}
private KtraceTapStackCollectionMode _mode;
public KtraceTapStackCollectionAction (KtraceTapStackCollectionMode mode) {
_mode = mode;
}
public override KtraceTapActionKind kind {
get {
return STACK_COLLECTION;
}
}
internal override NSArray encode () {
var a = new NSArray ();
a.add_object (new NSNumber.from_integer (kind));
a.add_object (new NSNumber.from_boolean ((_mode & KtraceTapStackCollectionMode.USER) != 0));
a.add_object (new NSNumber.from_boolean ((_mode & KtraceTapStackCollectionMode.KERNEL) != 0));
return a;
}
}
[Flags]
public enum KtraceTapStackCollectionMode {
NONE = 0,
USER = (1 << 0),
KERNEL = (1 << 1),
}
public sealed class KtraceTapKdebugBacktraceFilterAction : KtraceTapAction {
public override KtraceTapActionKind kind {
get {
return KDEBUG_BACKTRACE_FILTER;
}
}
internal override NSArray encode () {
var a = new NSArray ();
a.add_object (new NSNumber.from_integer (kind));
return a;
}
}
public sealed class KtraceTapAddPmcEventAction : KtraceTapAction {
public string event_name {
get {
return _event_name;
}
set {
_event_name = value;
}
}
public string counter_name {
get {
return _counter_name;
}
set {
_counter_name = value;
}
}
public uint32 extra {
get {
return _extra;
}
set {
_extra = value;
}
}
private string _event_name;
private string _counter_name;
private uint32 _extra;
public KtraceTapAddPmcEventAction (string event_name, string counter_name, uint32 extra = 0) {
_event_name = event_name;
_counter_name = counter_name;
_extra = extra;
}
public override KtraceTapActionKind kind {
get {
return ADD_PMC_EVENT;
}
}
internal override NSArray encode () {
var a = new NSArray ();
a.add_object (new NSNumber.from_integer (kind));
a.add_object (new NSString (_event_name));
a.add_object (new NSString (_counter_name));
a.add_object (new NSNumber.from_integer (_extra));
return a;
}
}
public sealed class KtraceTapAddKdebugCodeSetAction : KtraceTapAction {
public NSSet codes {
get {
return _codes;
}
set {
_codes = value;
}
}
private NSSet _codes;
public KtraceTapAddKdebugCodeSetAction (NSSet codes) {
_codes = codes;
}
public override KtraceTapActionKind kind {
get {
return ADD_KDEBUG_CODESET;
}
}
internal override NSArray encode () {
var a = new NSArray ();
a.add_object (new NSNumber.from_integer (kind));
a.add_object (_codes);
return a;
}
}
public sealed class KdebugCodeSet : Object {
public string legacy_xml {
owned get {
var xml = new StringBuilder.sized (256);
xml.append ("<events>");
foreach (var c in codes) {
var kc = KdebugCode (c);
xml.append ("<event type=\"KDebug\" class=\"");
var klass = kc.klass;
if (klass == ANY)
xml.append_c ('*');
else
xml.append_printf ("%u", klass);
xml.append ("\" subclass=\"");
var subclass = kc.subclass;
if (subclass == KDEBUG_SUBCLASS_ANY)
xml.append_c ('*');
else
xml.append_printf ("%u", subclass);
xml.append ("\" code=\"");
uint code = kc.code;
if (code == KDEBUG_CODE_ANY)
xml.append_c ('*');
else
xml.append_printf ("%u", code);
xml.append ("\"/>");
}
xml.append ("</events>");
return xml.str;
}
}
public NSSet kdebug_codes {
get {
if (_kdebug_codes == null) {
_kdebug_codes = new NSSet ();
foreach (var c in codes)
_kdebug_codes.add_object (new NSNumber.from_integer (c));
}
return _kdebug_codes;
}
}
private Gee.Set<uint> codes = new Gee.HashSet<uint> ();
private NSSet _kdebug_codes = null;
public KdebugCodeSet copy () {
var s = new KdebugCodeSet ();
s.codes.add_all (codes);
s._kdebug_codes = _kdebug_codes;
return s;
}
public unowned KdebugCodeSet add (KdebugCode code) {
codes.add (code.raw);
_kdebug_codes = null;
return this;
}
}
public sealed class DTXConnection : Object, DTXTransport {
@@ -1120,6 +373,7 @@ namespace Frida.Fruity {
private Gee.HashMap<uint32, Gee.ArrayList<Fragment>> fragments = new Gee.HashMap<uint32, Gee.ArrayList<Fragment>> ();
private uint32 next_fragment_identifier = 1;
private size_t total_buffered = 0;
private Gee.ArrayQueue<Bytes> pending_writes = new Gee.ArrayQueue<Bytes> ();
private DTXControlChannel control_channel;
@@ -1127,6 +381,8 @@ namespace Frida.Fruity {
private int32 next_channel_code = 1;
private const uint32 DTX_FRAGMENT_MAGIC = 0x1f3d5b79U;
private const uint MAX_BUFFERED_COUNT = 100;
private const size_t MAX_BUFFERED_SIZE = 30 * 1024 * 1024;
private const size_t MAX_MESSAGE_SIZE = 128 * 1024 * 1024;
private const size_t MAX_FRAGMENT_SIZE = 128 * 1024;
private const string REMOTESERVER_ENDPOINT_17PLUS = "lockdown:com.apple.instruments.dtservicehub";
@@ -1310,6 +566,8 @@ namespace Frida.Fruity {
Gee.ArrayList<Fragment> entries = fragments[fragment.identifier];
if (entries == null) {
if (fragments.size == MAX_BUFFERED_COUNT)
throw new Error.PROTOCOL ("Total buffered count exceeds maximum");
if (fragment.index != 0)
throw new Error.PROTOCOL ("Expected first fragment to have index of zero");
fragment.data_size = 0;
@@ -1327,6 +585,10 @@ namespace Frida.Fruity {
first_fragment.data_size += (uint32) size;
if (first_fragment.data_size > MAX_MESSAGE_SIZE)
throw new Error.PROTOCOL ("Message size exceeds maximum");
total_buffered += size;
if (total_buffered > MAX_BUFFERED_SIZE)
throw new Error.PROTOCOL ("Total buffered size exceeds maximum");
}
if (entries.size == fragment.count) {
@@ -1352,6 +614,7 @@ namespace Frida.Fruity {
}
fragments.unset (fragment.identifier);
total_buffered -= message.length;
process_message (message, first_fragment);
}
@@ -1451,37 +714,33 @@ namespace Frida.Fruity {
message.payload_data = raw_message[payload_start_offset:payload_end_offset];
int32 channel_code = message.channel_code;
if ((message.conversation_index % 2) == 0)
bool is_notification = false;
if (message.type == INVOKE) {
channel_code = -channel_code;
bool is_notification = message.conversation_index == 0;
} else if (message.type == RESULT && channel_code < 0) {
channel_code = -channel_code;
is_notification = true;
}
var channel = channels[channel_code];
if (channel == null)
return;
switch (message.type) {
case DISPATCH:
channel.handle_dispatch (message);
case INVOKE:
channel.handle_invoke (message);
break;
case OK:
case OBJECT:
case RESULT:
case ERROR:
if (is_notification)
channel.handle_notification (message);
else
channel.handle_response (message);
break;
case DATA:
channel.handle_data (message);
break;
case BARRIER:
channel.handle_barrier (message);
break;
case PRIMITIVE:
case COMPRESSED:
case PROXIED_MESSAGE:
throw new Error.PROTOCOL ("Unsupported message type: %s", message.type.to_string ());
}
}
@@ -1596,8 +855,7 @@ namespace Frida.Fruity {
public void notify_of_published_capabilities () throws Error {
var capabilities = new NSDictionary ();
capabilities.set_value ("com.apple.private.DTXConnection", new NSNumber.from_integer (1));
capabilities.set_value ("com.apple.instruments.client.processcontrol.capability.terminationCallback",
new NSNumber.from_integer (1));
capabilities.set_value ("com.apple.private.DTXBlockCompression", new NSNumber.from_integer (2));
var args = new DTXArgumentListBuilder ()
.append_object (capabilities);
@@ -1621,7 +879,6 @@ namespace Frida.Fruity {
public class DTXChannel : Object {
public signal void invocation (string method_name, DTXArgumentList args, DTXMessageTransportFlags transport_flags);
public signal void notification (NSObject obj);
public signal void data (Bytes blob);
public signal void barrier ();
public int32 code {
@@ -1678,7 +935,7 @@ namespace Frida.Fruity {
check_open ();
var message = DTXMessage ();
message.type = DISPATCH;
message.type = INVOKE;
message.channel_code = code;
message.transport_flags = EXPECTS_REPLY;
@@ -1708,7 +965,7 @@ namespace Frida.Fruity {
check_open ();
var message = DTXMessage ();
message.type = DISPATCH;
message.type = INVOKE;
message.channel_code = code;
message.transport_flags = NONE;
@@ -1725,10 +982,10 @@ namespace Frida.Fruity {
transport.send_message (message, out identifier);
}
internal void handle_dispatch (DTXMessage message) throws Error {
internal void handle_invoke (DTXMessage message) throws Error {
NSString? method_name = NSKeyedArchive.decode (message.payload_data) as NSString;
if (method_name == null)
throw new Error.PROTOCOL ("Malformed dispatch payload");
throw new Error.PROTOCOL ("Malformed invocation payload");
var args = DTXArgumentList.parse (message.aux_data);
@@ -1742,7 +999,7 @@ namespace Frida.Fruity {
case OK:
request.resolve (null);
break;
case OBJECT:
case RESULT:
request.resolve (NSKeyedArchive.decode (message.payload_data));
break;
case ERROR: {
@@ -1780,10 +1037,6 @@ namespace Frida.Fruity {
notification (payload);
}
internal void handle_data (DTXMessage message) throws Error {
data (new Bytes (message.payload_data));
}
internal void handle_barrier (DTXMessage message) throws Error {
barrier ();
}
@@ -1800,15 +1053,11 @@ namespace Frida.Fruity {
}
public enum DTXMessageType {
OK,
DATA,
DISPATCH,
OBJECT,
ERROR,
BARRIER,
PRIMITIVE,
COMPRESSED,
PROXIED_MESSAGE,
OK = 0,
INVOKE = 2,
RESULT = 3,
ERROR = 4,
BARRIER = 5
}
public struct DTXMessage {
@@ -1862,12 +1111,6 @@ namespace Frida.Fruity {
}
case BUFFER: {
size_t size = reader.read_uint32 ();
if (size == 0) {
var gval = Value (typeof (NSObject));
elements += (owned) gval;
break;
}
unowned uint8[] buf = reader.read_byte_array (size);
NSObject? obj = NSKeyedArchive.decode (buf);
File diff suppressed because it is too large. Load diff
+9 -22
View File
@@ -186,14 +186,8 @@ namespace Frida.Fruity.Injector {
}
private async void teardown (Cancellable? cancellable) throws GLib.Error {
try {
yield lldb.deallocate (scratch_page, cancellable);
} catch (Error e) {
}
try {
yield lldb.deallocate (jit_page, cancellable);
} catch (Error e) {
}
yield lldb.deallocate (scratch_page, cancellable);
yield lldb.deallocate (jit_page, cancellable);
yield restore_main_thread_state (cancellable);
}
@@ -899,14 +893,11 @@ namespace Frida.Fruity.Injector {
uint64 initializer = (notify_objc_init != null) ? notify_objc_init : libdyld_initialize;
GDB.Breakpoint init_breakpoint = yield lldb.add_breakpoint (SOFT, initializer, 4, cancellable);
GDB.Breakpoint? restart_breakpoint = null;
uint64? restart_with_dyld_in_cache = null;
foreach (var e in dyld_symbols.entries) {
if (e.key.contains ("restartWithDyldInCache")) {
restart_with_dyld_in_cache = e.value;
break;
}
}
uint64? restart_with_dyld_in_cache = dyld_symbols["__ZN5dyld422restartWithDyldInCacheEPKNS_10KernelArgsEPKN6mach_o6HeaderEPK15DyldSharedCachePv"];
if (restart_with_dyld_in_cache == null)
restart_with_dyld_in_cache = dyld_symbols["__ZN5dyld422restartWithDyldInCacheEPKNS_10KernelArgsEPKN5dyld39MachOFileEPK15DyldSharedCachePv"];
if (restart_with_dyld_in_cache == null)
restart_with_dyld_in_cache = dyld_symbols["__ZN5dyld422restartWithDyldInCacheEPKNS_10KernelArgsEPKN5dyld39MachOFileEPv"];
if (restart_with_dyld_in_cache != null)
restart_breakpoint = yield lldb.add_breakpoint (SOFT, restart_with_dyld_in_cache, 4, cancellable);
@@ -1383,12 +1374,8 @@ namespace Frida.Fruity.Injector {
}
}
if (state != scratch_page) {
try {
yield lldb.deallocate (state, cancellable);
} catch (Error e) {
}
}
if (state != scratch_page)
yield lldb.deallocate (state, cancellable);
return new SymbolSet (symbols);
}
-558
View File
@@ -1,558 +0,0 @@
[CCode (gir_namespace = "FridaFruity", gir_version = "1.0")]
namespace Frida.Fruity.Kcdata {
public struct ItemHeader {
public ItemType type;
public uint32 size;
public uint64 flags;
}
public enum ItemType {
INVALID = 0x000u,
STRING_DESC = 0x001u,
UINT32_DESC = 0x002u,
UINT64_DESC = 0x003u,
INT32_DESC = 0x004u,
INT64_DESC = 0x005u,
BINDATA_DESC = 0x006u,
ARRAY = 0x011u,
TYPEDEFINTION = 0x012u,
CONTAINER_BEGIN = 0x013u,
CONTAINER_END = 0x014u,
ARRAY_PAD0 = 0x020u,
ARRAY_PAD1 = 0x021u,
ARRAY_PAD2 = 0x022u,
ARRAY_PAD3 = 0x023u,
ARRAY_PAD4 = 0x024u,
ARRAY_PAD5 = 0x025u,
ARRAY_PAD6 = 0x026u,
ARRAY_PAD7 = 0x027u,
ARRAY_PAD8 = 0x028u,
ARRAY_PAD9 = 0x029u,
ARRAY_PADa = 0x02au,
ARRAY_PADb = 0x02bu,
ARRAY_PADc = 0x02cu,
ARRAY_PADd = 0x02du,
ARRAY_PADe = 0x02eu,
ARRAY_PADf = 0x02fu,
LIBRARY_LOADINFO = 0x030u,
LIBRARY_LOADINFO64 = 0x031u,
TIMEBASE = 0x032u,
MACH_ABSOLUTE_TIME = 0x033u,
TIMEVAL = 0x034u,
USECS_SINCE_EPOCH = 0x035u,
PID = 0x036u,
PROCNAME = 0x037u,
NESTED_KCDATA = 0x038u,
LIBRARY_AOTINFO = 0x039u,
TASK_CRASHINFO_EXTMODINFO = 0x801u,
TASK_CRASHINFO_BSDINFOWITHUNIQID = 0x802u,
TASK_CRASHINFO_TASKDYLD_INFO = 0x803u,
TASK_CRASHINFO_UUID = 0x804u,
TASK_CRASHINFO_PID = 0x805u,
TASK_CRASHINFO_PPID = 0x806u,
TASK_CRASHINFO_RUSAGE = 0x807u,
TASK_CRASHINFO_RUSAGE_INFO = 0x808u,
TASK_CRASHINFO_PROC_NAME = 0x809u,
TASK_CRASHINFO_PROC_STARTTIME = 0x80Bu,
TASK_CRASHINFO_USERSTACK = 0x80Cu,
TASK_CRASHINFO_ARGSLEN = 0x80Du,
TASK_CRASHINFO_EXCEPTION_CODES = 0x80Eu,
TASK_CRASHINFO_PROC_PATH = 0x80Fu,
TASK_CRASHINFO_PROC_CSFLAGS = 0x810u,
TASK_CRASHINFO_PROC_STATUS = 0x811u,
TASK_CRASHINFO_UID = 0x812u,
TASK_CRASHINFO_GID = 0x813u,
TASK_CRASHINFO_PROC_ARGC = 0x814u,
TASK_CRASHINFO_PROC_FLAGS = 0x815u,
TASK_CRASHINFO_CPUTYPE = 0x816u,
TASK_CRASHINFO_WORKQUEUEINFO = 0x817u,
TASK_CRASHINFO_RESPONSIBLE_PID = 0x818u,
TASK_CRASHINFO_DIRTY_FLAGS = 0x819u,
TASK_CRASHINFO_CRASHED_THREADID = 0x81Au,
TASK_CRASHINFO_COALITION_ID = 0x81Bu,
TASK_CRASHINFO_UDATA_PTRS = 0x81Cu,
TASK_CRASHINFO_MEMORY_LIMIT = 0x81Du,
TASK_CRASHINFO_LEDGER_INTERNAL = 0x81Eu,
TASK_CRASHINFO_LEDGER_INTERNAL_COMPRESSED = 0x81Fu,
TASK_CRASHINFO_LEDGER_IOKIT_MAPPED = 0x820u,
TASK_CRASHINFO_LEDGER_ALTERNATE_ACCOUNTING = 0x821u,
TASK_CRASHINFO_LEDGER_ALTERNATE_ACCOUNTING_COMPRESSED = 0x822u,
TASK_CRASHINFO_LEDGER_PURGEABLE_NONVOLATILE = 0x823u,
TASK_CRASHINFO_LEDGER_PURGEABLE_NONVOLATILE_COMPRESSED = 0x824u,
TASK_CRASHINFO_LEDGER_PAGE_TABLE = 0x825u,
TASK_CRASHINFO_LEDGER_PHYS_FOOTPRINT = 0x826u,
TASK_CRASHINFO_LEDGER_PHYS_FOOTPRINT_LIFETIME_MAX = 0x827u,
TASK_CRASHINFO_LEDGER_NETWORK_NONVOLATILE = 0x828u,
TASK_CRASHINFO_LEDGER_NETWORK_NONVOLATILE_COMPRESSED = 0x829u,
TASK_CRASHINFO_LEDGER_WIRED_MEM = 0x82Au,
TASK_CRASHINFO_PROC_PERSONA_ID = 0x82Bu,
TASK_CRASHINFO_MEMORY_LIMIT_INCREASE = 0x82Cu,
TASK_CRASHINFO_LEDGER_TAGGED_FOOTPRINT = 0x82Du,
TASK_CRASHINFO_LEDGER_TAGGED_FOOTPRINT_COMPRESSED = 0x82Eu,
TASK_CRASHINFO_LEDGER_MEDIA_FOOTPRINT = 0x82Fu,
TASK_CRASHINFO_LEDGER_MEDIA_FOOTPRINT_COMPRESSED = 0x830u,
TASK_CRASHINFO_LEDGER_GRAPHICS_FOOTPRINT = 0x831u,
TASK_CRASHINFO_LEDGER_GRAPHICS_FOOTPRINT_COMPRESSED = 0x832u,
TASK_CRASHINFO_LEDGER_NEURAL_FOOTPRINT = 0x833u,
TASK_CRASHINFO_LEDGER_NEURAL_FOOTPRINT_COMPRESSED = 0x834u,
TASK_CRASHINFO_MEMORYSTATUS_EFFECTIVE_PRIORITY = 0x835u,
TASK_CRASHINFO_KERNEL_TRIAGE_INFO_V1 = 0x836u,
TASK_CRASHINFO_TASK_IS_CORPSE_FORK = 0x837u,
TASK_CRASHINFO_EXCEPTION_TYPE = 0x838u,
TASK_CRASHINFO_CRASH_COUNT = 0x839u,
TASK_CRASHINFO_THROTTLE_TIMEOUT = 0x83Au,
TASK_CRASHINFO_CS_SIGNING_ID = 0x83Bu,
TASK_CRASHINFO_CS_TEAM_ID = 0x83Cu,
TASK_CRASHINFO_CS_VALIDATION_CATEGORY = 0x83Du,
TASK_CRASHINFO_CS_TRUST_LEVEL = 0x83Eu,
TASK_CRASHINFO_PROC_CPUTYPE = 0x83Fu,
TASK_CRASHINFO_JIT_ADDRESS_RANGE = 0x840u,
TASK_CRASHINFO_MB = 0x841u,
TASK_CRASHINFO_CS_AUXILIARY_INFO = 0x842u,
TASK_CRASHINFO_RLIM_CORE = 0x843u,
TASK_CRASHINFO_CORE_ALLOWED = 0x844u,
TASK_CRASHINFO_TASK_SECURITY_CONFIG = 0x845u,
STACKSHOT_IOSTATS = 0x901u,
STACKSHOT_GLOBAL_MEM_STATS = 0x902u,
STACKSHOT_CONTAINER_TASK = 0x903u,
STACKSHOT_CONTAINER_THREAD = 0x904u,
STACKSHOT_TASK_SNAPSHOT = 0x905u,
STACKSHOT_THREAD_SNAPSHOT = 0x906u,
STACKSHOT_DONATING_PIDS = 0x907u,
STACKSHOT_SHAREDCACHE_LOADINFO = 0x908u,
STACKSHOT_THREAD_NAME = 0x909u,
STACKSHOT_KERN_STACKFRAME = 0x90Au,
STACKSHOT_KERN_STACKFRAME64 = 0x90Bu,
STACKSHOT_USER_STACKFRAME = 0x90Cu,
STACKSHOT_USER_STACKFRAME64 = 0x90Du,
STACKSHOT_BOOTARGS = 0x90Eu,
STACKSHOT_OSVERSION = 0x90Fu,
STACKSHOT_KERN_PAGE_SIZE = 0x910u,
STACKSHOT_JETSAM_LEVEL = 0x911u,
STACKSHOT_DELTA_SINCE_TIMESTAMP = 0x912u,
STACKSHOT_KERN_STACKLR = 0x913u,
STACKSHOT_KERN_STACKLR64 = 0x914u,
STACKSHOT_USER_STACKLR = 0x915u,
STACKSHOT_USER_STACKLR64 = 0x916u,
STACKSHOT_NONRUNNABLE_TIDS = 0x917u,
STACKSHOT_NONRUNNABLE_TASKS = 0x918u,
STACKSHOT_CPU_TIMES = 0x919u,
STACKSHOT_STACKSHOT_DURATION = 0x91au,
STACKSHOT_STACKSHOT_FAULT_STATS = 0x91bu,
STACKSHOT_KERNELCACHE_LOADINFO = 0x91cu,
STACKSHOT_THREAD_WAITINFO = 0x91du,
STACKSHOT_THREAD_GROUP_SNAPSHOT = 0x91eu,
STACKSHOT_THREAD_GROUP = 0x91fu,
STACKSHOT_JETSAM_COALITION_SNAPSHOT = 0x920u,
STACKSHOT_JETSAM_COALITION = 0x921u,
STACKSHOT_THREAD_POLICY_VERSION = 0x922u,
STACKSHOT_INSTRS_CYCLES = 0x923u,
STACKSHOT_USER_STACKTOP = 0x924u,
STACKSHOT_ASID = 0x925u,
STACKSHOT_PAGE_TABLES = 0x926u,
STACKSHOT_SYS_SHAREDCACHE_LAYOUT = 0x927u,
STACKSHOT_THREAD_DISPATCH_QUEUE_LABEL = 0x928u,
STACKSHOT_THREAD_TURNSTILEINFO = 0x929u,
STACKSHOT_TASK_CPU_ARCHITECTURE = 0x92au,
STACKSHOT_LATENCY_INFO = 0x92bu,
STACKSHOT_LATENCY_INFO_TASK = 0x92cu,
STACKSHOT_LATENCY_INFO_THREAD = 0x92du,
STACKSHOT_LOADINFO64_TEXT_EXEC = 0x92eu,
STACKSHOT_AOTCACHE_LOADINFO = 0x92fu,
STACKSHOT_TRANSITIONING_TASK_SNAPSHOT = 0x930u,
STACKSHOT_CONTAINER_TRANSITIONING_TASK = 0x931u,
STACKSHOT_USER_ASYNC_START_INDEX = 0x932u,
STACKSHOT_USER_ASYNC_STACKLR64 = 0x933u,
STACKSHOT_CONTAINER_PORTLABEL = 0x934u,
STACKSHOT_PORTLABEL = 0x935u,
STACKSHOT_PORTLABEL_NAME = 0x936u,
STACKSHOT_DYLD_COMPACTINFO = 0x937u,
STACKSHOT_SUSPENSION_INFO = 0x938u,
STACKSHOT_SUSPENSION_SOURCE = 0x939u,
STACKSHOT_TASK_DELTA_SNAPSHOT = 0x940u,
STACKSHOT_THREAD_DELTA_SNAPSHOT = 0x941u,
STACKSHOT_CONTAINER_SHAREDCACHE = 0x942u,
STACKSHOT_SHAREDCACHE_INFO = 0x943u,
STACKSHOT_SHAREDCACHE_AOTINFO = 0x944u,
STACKSHOT_SHAREDCACHE_ID = 0x945u,
STACKSHOT_CODESIGNING_INFO = 0x946u,
STACKSHOT_OS_BUILD_VERSION = 0x947u,
STACKSHOT_KERN_EXCLAVES_THREADINFO = 0x948u,
STACKSHOT_CONTAINER_EXCLAVES = 0x949u,
STACKSHOT_CONTAINER_EXCLAVE_SCRESULT = 0x94au,
STACKSHOT_EXCLAVE_SCRESULT_INFO = 0x94bu,
STACKSHOT_CONTAINER_EXCLAVE_IPCSTACKENTRY = 0x94cu,
STACKSHOT_EXCLAVE_IPCSTACKENTRY_INFO = 0x94du,
STACKSHOT_EXCLAVE_IPCSTACKENTRY_ECSTACK = 0x94eu,
STACKSHOT_CONTAINER_EXCLAVE_ADDRESSSPACE = 0x94fu,
STACKSHOT_EXCLAVE_ADDRESSSPACE_INFO = 0x950u,
STACKSHOT_EXCLAVE_ADDRESSSPACE_NAME = 0x951u,
STACKSHOT_CONTAINER_EXCLAVE_TEXTLAYOUT = 0x952u,
STACKSHOT_EXCLAVE_TEXTLAYOUT_INFO = 0x953u,
STACKSHOT_EXCLAVE_TEXTLAYOUT_SEGMENTS = 0x954u,
STACKSHOT_KERN_EXCLAVES_CRASH_THREADINFO = 0x955u,
STACKSHOT_LATENCY_INFO_CPU = 0x956u,
STACKSHOT_TASK_EXEC_META = 0x957u,
STACKSHOT_TASK_MEMORYSTATUS = 0x958u,
STACKSHOT_LATENCY_INFO_BUFFER = 0x95au,
TASK_BTINFO_PID = 0xA01u,
TASK_BTINFO_PPID = 0xA02u,
TASK_BTINFO_PROC_NAME = 0xA03u,
TASK_BTINFO_PROC_PATH = 0xA04u,
TASK_BTINFO_UID = 0xA05u,
TASK_BTINFO_GID = 0xA06u,
TASK_BTINFO_PROC_FLAGS = 0xA07u,
TASK_BTINFO_CPUTYPE = 0xA08u,
TASK_BTINFO_EXCEPTION_CODES = 0xA09u,
TASK_BTINFO_EXCEPTION_TYPE = 0xA0Au,
TASK_BTINFO_RUSAGE_INFO = 0xA0Bu,
TASK_BTINFO_COALITION_ID = 0xA0Cu,
TASK_BTINFO_CRASH_COUNT = 0xA0Du,
TASK_BTINFO_THROTTLE_TIMEOUT = 0xA0Eu,
TASK_BTINFO_THREAD_ID = 0xA20u,
TASK_BTINFO_THREAD_NAME = 0xA21u,
TASK_BTINFO_THREAD_STATE = 0xA22u,
TASK_BTINFO_THREAD_EXCEPTION_STATE = 0xA23u,
TASK_BTINFO_BACKTRACE = 0xA24u,
TASK_BTINFO_BACKTRACE64 = 0xA25u,
TASK_BTINFO_ASYNC_BACKTRACE64 = 0xA26u,
TASK_BTINFO_ASYNC_START_INDEX = 0xA27u,
TASK_BTINFO_PLATFORM = 0xA28u,
TASK_BTINFO_SC_LOADINFO = 0xA29u,
TASK_BTINFO_SC_LOADINFO64 = 0xA2Au,
TASK_BTINFO_FLAGS = 0xAFFu,
BUFFER_BEGIN_XNUPOST_CONFIG = 0x1e21c09fu,
BUFFER_BEGIN_COMPRESSED = 0x434f4d50u,
BUFFER_BEGIN_BTINFO = 0x46414E47u,
BUFFER_BEGIN_STACKSHOT = 0x59a25807u,
BUFFER_BEGIN_OS_REASON = 0x53A20900u,
BUFFER_BEGIN_DELTA_STACKSHOT = 0xDE17A59Au,
BUFFER_BEGIN_CRASHINFO = 0xDEADF157u,
BUFFER_END = 0xF19158EDu;
public string to_nick () {
return Marshal.enum_to_nick<ItemType> (this);
}
}
[Flags]
public enum StackshotFlagsLow {
GET_DQ = (1U << 0),
SAVE_LOADINFO = (1U << 1),
GET_GLOBAL_MEM_STATS = (1U << 2),
SAVE_KEXT_LOADINFO = (1U << 3),
ACTIVE_KERNEL_THREADS_ONLY = (1U << 8),
GET_BOOT_PROFILE = (1U << 9),
DO_COMPRESS = (1U << 10),
SAVE_IMP_DONATION_PIDS = (1U << 13),
SAVE_IN_KERNEL_BUFFER = (1U << 14),
RETRIEVE_EXISTING_BUFFER = (1U << 15),
KCDATA_FORMAT = (1U << 16),
ENABLE_BT_FAULTING = (1U << 17),
COLLECT_DELTA_SNAPSHOT = (1U << 18),
COLLECT_SHAREDCACHE_LAYOUT = (1U << 19),
TRYLOCK = (1U << 20),
ENABLE_UUID_FAULTING = (1U << 21),
FROM_PANIC = (1U << 22),
NO_IO_STATS = (1U << 23),
THREAD_WAITINFO = (1U << 24),
THREAD_GROUP = (1U << 25),
SAVE_JETSAM_COALITIONS = (1U << 26),
INSTRS_CYCLES = (1U << 27),
ASID = (1U << 28),
PAGE_TABLES = (1U << 29),
DISABLE_LATENCY_INFO = (1U << 30),
SAVE_DYLD_COMPACTINFO = (1U << 31)
}
[Flags]
public enum StackshotFlagsHigh {
INCLUDE_DRIVER_THREADS_IN_KERNEL = (1U << 0),
EXCLAVES = (1U << 1),
SKIP_EXCLAVES = (1U << 2),
}
public const size_t TASK_SNAPSHOT_PID_OFFSET = 84;
public static bool is_stackshot (Bytes bytes) {
if (bytes.get_size () < 16)
return false;
var type = (ItemType) uint32.from_little_endian (*((uint32 *) bytes.get_data ()));
switch (type) {
case ItemType.BUFFER_BEGIN_STACKSHOT:
case ItemType.BUFFER_BEGIN_DELTA_STACKSHOT:
case ItemType.BUFFER_BEGIN_COMPRESSED:
return true;
default:
return false;
}
}
public sealed class Reader : Object {
private Buffer buf;
private BufferReader r;
private Buffer payload_buf;
private BufferReader payload_r;
private BufferReader scan_r;
private Array<uint64> scan_container_ids = new Array<uint64> ();
[Compact]
private struct Scope {
public size_t end_item_offset;
public uint64 end_id;
}
private Array<Scope> scopes = new Array<Scope> ();
private size_t current_end_item_offset;
private const size_t HEADER_SIZE = 16;
private const size_t ALIGNMENT_SIZE = 16;
public Reader (Bytes bytes) {
buf = new Buffer (bytes, LITTLE_ENDIAN);
r = new BufferReader (buf);
payload_buf = new Buffer.from_data ((uint8[]) null, buf.byte_order, buf.pointer_size);
payload_r = new BufferReader (payload_buf);
scan_r = new BufferReader (buf);
current_end_item_offset = buf.bytes.get_size ();
}
public enum VisitResult {
CONTINUE,
STOP
}
public VisitResult for_each (ItemVisitor visitor) throws Error {
ItemHeader h;
unowned BufferReader p;
while (read_item (out h, out p)) {
if (visitor (h, p) == VisitResult.STOP)
return VisitResult.STOP;
}
return VisitResult.CONTINUE;
}
public delegate VisitResult ItemVisitor (ItemHeader h, BufferReader payload) throws Error;
public VisitResult for_each_container (ItemType want_container_type, ScopeVisitor visitor) throws Error {
ItemHeader h;
unowned BufferReader p;
while (read_item (out h, out p)) {
if (h.type != ItemType.CONTAINER_BEGIN)
continue;
var ctype = (ItemType) p.read_uint32 ();
var id = h.flags;
if (ctype != want_container_type) {
skip_container_body (id);
continue;
}
enter_container_body (id);
var result = visitor (this);
leave_container ();
if (result == VisitResult.STOP)
return VisitResult.STOP;
}
return VisitResult.CONTINUE;
}
public delegate VisitResult ScopeVisitor (Reader r) throws Error;
public unowned BufferReader get_first (ItemType type) throws Error {
unowned BufferReader result = null;
for_each ((h, p) => {
if (h.type != type)
return VisitResult.CONTINUE;
result = p;
return VisitResult.STOP;
});
if (result == null)
throw new Error.PROTOCOL ("Missing item: %s", type.to_nick ());
return result;
}
private bool read_item (out ItemHeader h, out unowned BufferReader payload) throws Error {
if (r.available == 0 || r.offset == current_end_item_offset) {
h = ItemHeader ();
payload = null;
return false;
}
h = read_header ();
payload = read_payload (h);
return true;
}
private ItemHeader read_header () throws Error {
if (r.available < HEADER_SIZE)
throw new Error.PROTOCOL ("KCDATA truncated at %zu (need header, avail=%zu)", r.offset, r.available);
var item_start = r.offset;
var h = read_item_header_fields (r);
var avail_payload = current_end_item_offset - r.offset;
var avail = size_t.min (r.available, avail_payload);
if (h.size > avail) {
throw new Error.PROTOCOL ("KCDATA truncated at %zu (type=0x%x size=%u avail=%zu)", item_start,
(uint32) h.type, h.size, avail);
}
return h;
}
private unowned BufferReader read_payload (ItemHeader h) throws Error {
unowned uint8[] payload = r.read_data (h.size);
payload_buf.reset_data (payload);
payload_r.reset (payload_buf);
r.align (ALIGNMENT_SIZE);
return payload_r;
}
private void enter_container_body (uint64 id) throws Error {
var body_start = r.offset;
size_t end_item_offset;
find_container_end (body_start, id, out end_item_offset);
var s = Scope ();
s.end_item_offset = end_item_offset;
s.end_id = id;
scopes.append_val (s);
current_end_item_offset = end_item_offset;
}
private void leave_container () throws Error {
var s = scopes.index (scopes.length - 1);
scopes.set_size (scopes.length - 1);
consume_container_end_at (s.end_item_offset, s.end_id);
if (scopes.length == 0)
current_end_item_offset = buf.bytes.get_size ();
else {
var parent = scopes.index (scopes.length - 1);
current_end_item_offset = parent.end_item_offset;
}
}
private void skip_container_body (uint64 id) throws Error {
var body_start = r.offset;
size_t end_item_offset;
find_container_end (body_start, id, out end_item_offset);
consume_container_end_at (end_item_offset, id);
}
private void consume_container_end_at (size_t end_item_offset, uint64 id) throws Error {
if (r.offset != end_item_offset)
r.seek (end_item_offset);
if (r.available < HEADER_SIZE)
throw new Error.PROTOCOL ("KCDATA truncated at %zu (need header, avail=%zu)", r.offset, r.available);
var item_start = r.offset;
var h = read_item_header_fields (r);
if (h.type != ItemType.CONTAINER_END || h.flags != id) {
throw new Error.PROTOCOL ("Malformed container end at %zu (want id=0x%016" + uint64.FORMAT_MODIFIER + "x)",
item_start, id);
}
if (h.size > r.available) {
throw new Error.PROTOCOL ("KCDATA truncated at %zu (type=0x%x size=%u avail=%zu)", item_start,
(uint32) h.type, h.size, r.available);
}
r.skip (h.size);
r.align (ALIGNMENT_SIZE);
}
private void find_container_end (size_t body_start, uint64 id, out size_t end_item_offset) throws Error {
scan_container_ids.set_size (0);
scan_r.seek (body_start);
while (true) {
if (scan_r.available < HEADER_SIZE) {
throw new Error.PROTOCOL ("KCDATA truncated at %zu (need header, avail=%zu)",
scan_r.offset, scan_r.available);
}
var item_start = scan_r.offset;
var h = read_item_header_fields (scan_r);
if (h.size > scan_r.available) {
throw new Error.PROTOCOL ("KCDATA truncated at %zu (type=0x%x size=%u avail=%zu)", item_start,
(uint32) h.type, h.size, scan_r.available);
}
scan_r.skip (h.size);
scan_r.align (ALIGNMENT_SIZE);
if (h.type == ItemType.CONTAINER_BEGIN) {
scan_container_ids.append_val (h.flags);
continue;
}
if (h.type == ItemType.CONTAINER_END) {
if (scan_container_ids.length != 0) {
var top = scan_container_ids.remove_index (scan_container_ids.length - 1);
if (top != h.flags) {
throw new Error.PROTOCOL ("Malformed container nesting at %zu (id=0x%016" +
uint64.FORMAT_MODIFIER + "x)", item_start, h.flags);
}
} else {
if (h.flags != id) {
throw new Error.PROTOCOL ("Malformed container end at %zu (id=0x%016" +
uint64.FORMAT_MODIFIER + "x)", item_start, h.flags);
}
end_item_offset = item_start;
return;
}
}
}
}
private ItemHeader read_item_header_fields (BufferReader r) throws Error {
var h = ItemHeader ();
h.type = (ItemType) r.read_uint32 ();
h.size = r.read_uint32 ();
h.flags = r.read_uint64 ();
return h;
}
}
}
-220
View File
@@ -1,220 +0,0 @@
[CCode (gir_namespace = "FridaFruity", gir_version = "1.0")]
namespace Frida.Fruity {
public enum KdebugClass {
MACH = 1,
FSYSTEM = 3,
BSD = 4,
TRACE = 7,
DYLD = 31,
PERF = 37,
ANY = 0xff;
public string to_nick () {
return Marshal.enum_to_nick<KdebugClass> (this);
}
}
public enum KdebugMachSubclass {
EXCP_SC = 12,
}
public enum KdebugFsystemSubclass {
FSRW = 1,
DKRW,
FSVN,
FSLOOOKUP,
JOURNAL,
IOCTL,
BOOTCACHE,
HFS,
APFS,
SMB,
MOUNT,
EXFAT = 14,
MSDOS,
ACFS,
THROTTLE,
DECMP,
VFS,
LIVEFS,
NFS;
public string to_nick () {
return Marshal.enum_to_nick<KdebugFsystemSubclass> (this);
}
}
public enum KdebugFsystemFsrwEvent {
LOOKUP = 36,
LOOKUP_DONE = 39;
public string to_nick () {
return Marshal.enum_to_nick<KdebugFsystemFsrwEvent> (this);
}
}
public enum KdebugBsdSubclass {
EXCP_SC = 12,
}
public enum KdebugTraceSubclass {
DATA,
STRING,
INFO;
public string to_nick () {
return Marshal.enum_to_nick<KdebugTraceSubclass> (this);
}
}
public enum KdebugTraceDataEvent {
NEWTHREAD = 1,
EXEC,
THREAD_TERMINATE,
THREAD_TERMINATE_PID;
public string to_nick () {
return Marshal.enum_to_nick<KdebugTraceDataEvent> (this);
}
}
public enum KdebugTraceStringEvent {
GLOBAL,
NEWTHREAD,
EXEC,
PROC_EXIT,
THREADNAME,
THREADNAME_PREV;
public string to_nick () {
return Marshal.enum_to_nick<KdebugTraceStringEvent> (this);
}
}
public enum KdebugDyldSubclass {
UUID = 5,
}
public enum KdebugDyldUuidEvent {
MAP_A,
MAP_B,
MAP_32_A,
MAP_32_B,
MAP_32_C,
UNMAP_A,
UNMAP_B,
UNMAP_32_A,
UNMAP_32_B,
UNMAP_32_C,
SHARED_CACHE_A,
SHARED_CACHE_B,
SHARED_CACHE_32_A,
SHARED_CACHE_32_B,
SHARED_CACHE_32_C,
AOT_MAP_A,
AOT_MAP_B;
public string to_nick () {
return Marshal.enum_to_nick<KdebugDyldUuidEvent> (this);
}
}
public enum KdebugPerfSubclass {
GENERIC,
THREADINFO,
CALLSTACK,
TIMER,
PET,
AST,
KPC,
KDBG,
TASK,
LAZY,
MEMINFO;
public string to_nick () {
return Marshal.enum_to_nick<KdebugPerfSubclass> (this);
}
}
public enum KdebugPerfCallstackEvent {
KSAMPLE,
UPEND,
USAMPLE,
KDATA,
UDATA,
KHDR,
UHDR,
ERROR,
BACKTRACE,
LOG,
EXHDR,
EXDATA,
EXSTACKHDR,
EXSTACK,
KEXOFFSET;
public string to_nick () {
return Marshal.enum_to_nick<KdebugPerfCallstackEvent> (this);
}
}
public const uint8 KDEBUG_SUBCLASS_ANY = 0xff;
public const uint16 KDEBUG_CODE_ANY = 0x3fff;
public enum KdebugFunctionQualifier {
NONE,
START,
END;
public string to_nick () {
return Marshal.enum_to_nick<KdebugFunctionQualifier> (this);
}
}
public struct KdebugCode {
public uint32 raw;
public KdebugCode (uint32 raw) {
this.raw = raw;
}
public KdebugCode.from_parts (
KdebugClass klass,
uint8 subclass = KDEBUG_SUBCLASS_ANY,
uint16 code = KDEBUG_CODE_ANY,
KdebugFunctionQualifier func_qual = NONE) {
raw =
(((uint32) klass & 0xff) << 24) |
(((uint32) subclass & 0xff) << 16) |
(((uint32) code & 0x3fff) << 2) |
((uint32) func_qual & 0x3);
}
public KdebugClass klass {
get {
return (KdebugClass) ((raw >> 24) & 0xff);
}
}
public uint8 subclass {
get {
return (uint8) ((raw >> 16) & 0xff);
}
}
public uint16 code {
get {
return (uint16) ((raw >> 2) & 0x3fff);
}
}
public KdebugFunctionQualifier func_qual {
get {
return (KdebugFunctionQualifier) (raw & 0x3);
}
}
}
}
+8 -190
View File
@@ -9,20 +9,8 @@ namespace Frida.Fruity {
return other == this;
}
public string to_string (uint level = 0) {
var s = new StringBuilder.sized (256);
append_indent (s, level);
append_content (s, level);
return s.str;
}
protected virtual void append_content (StringBuilder s, uint level) {
s.append ("NSObject {}");
}
protected void append_indent (StringBuilder s, uint level) {
for (uint i = 0; i != level; i++)
s.append (" ");
public virtual string to_string () {
return "NSObject";
}
public static uint hash_func (NSObject val) {
@@ -115,19 +103,8 @@ namespace Frida.Fruity {
return false;
}
protected override void append_content (StringBuilder s, uint level) {
switch (kind) {
case BOOLEAN:
s.append (boolean ? "true" : "false");
break;
case INTEGER:
s.append_printf ("%" + int64.FORMAT, integer);
break;
case FLOAT:
case DOUBLE:
s.append_printf ("%f", number);
break;
}
public override string to_string () {
return integer.to_string ();
}
}
@@ -152,11 +129,8 @@ namespace Frida.Fruity {
return other_string.str == str;
}
protected override void append_content (StringBuilder s, uint level) {
s
.append_c ('"')
.append (str.replace ("\"", "\\\""))
.append_c ('"');
public override string to_string () {
return str;
}
}
@@ -181,8 +155,8 @@ namespace Frida.Fruity {
return other_data.bytes.compare (bytes) == 0;
}
protected override void append_content (StringBuilder s, uint level) {
s.append_printf ("NSData { size = %" + size_t.FORMAT + " }", bytes.get_size ());
public override string to_string () {
return "NSData";
}
}
@@ -245,25 +219,6 @@ namespace Frida.Fruity {
public void set_value (string key, NSObject val) {
storage[key] = val;
}
protected override void append_content (StringBuilder s, uint level) {
if (storage.size == 0) {
s.append ("{}");
return;
}
s.append ("{\n");
foreach (var e in entries) {
append_indent (s, level + 1);
s
.append (e.key)
.append (": ");
e.value.append_content (s, level + 1);
s.append (",\n");
}
append_indent (s, level);
s.append_c ('}');
}
}
public sealed class NSDictionaryRaw : NSObject {
@@ -298,24 +253,6 @@ namespace Frida.Fruity {
? storage
: new Gee.HashMap<NSObject, NSObject> (NSObject.hash_func, NSObject.equal_func);
}
protected override void append_content (StringBuilder s, uint level) {
if (storage.size == 0) {
s.append ("{}");
return;
}
s.append ("{\n");
foreach (var e in entries) {
append_indent (s, level + 1);
e.key.append_content (s, level + 1);
s.append (": ");
e.value.append_content (s, level + 1);
s.append (",\n");
}
append_indent (s, level);
s.append_c ('}');
}
}
public sealed class NSArray : NSObject {
@@ -340,56 +277,6 @@ namespace Frida.Fruity {
public void add_object (NSObject obj) {
storage.add (obj);
}
protected override void append_content (StringBuilder s, uint level) {
if (storage.size == 0) {
s.append ("[]");
return;
}
s.append ("[\n");
foreach (var e in elements) {
append_indent (s, level + 1);
e.append_content (s, level + 1);
s.append (",\n");
}
append_indent (s, level);
s.append_c (']');
}
}
public sealed class NSSet : NSObject {
public Gee.Iterable<NSObject> items {
owned get {
return storage;
}
}
private Gee.HashSet<NSObject> storage;
public NSSet (Gee.HashSet<NSObject>? storage = null) {
this.storage = (storage != null) ? storage : new Gee.HashSet<NSObject> (NSObject.hash_func);
}
public void add_object (NSObject obj) {
storage.add (obj);
}
protected override void append_content (StringBuilder s, uint level) {
if (storage.size == 0) {
s.append ("{}");
return;
}
s.append ("{\n");
foreach (var e in items) {
append_indent (s, level + 1);
e.append_content (s, level + 1);
s.append (",\n");
}
append_indent (s, level);
s.append_c ('}');
}
}
public sealed class NSDate : NSObject {
@@ -409,10 +296,6 @@ namespace Frida.Fruity {
return new DateTime.from_unix_utc (MAC_EPOCH_DELTA_FROM_UNIX + whole_seconds)
.add_seconds (time - (double) whole_seconds);
}
protected override void append_content (StringBuilder s, uint level) {
s.append_printf ("NSDate { time = %f }", time);
}
}
public sealed class NSError : NSObject {
@@ -436,35 +319,6 @@ namespace Frida.Fruity {
this.code = code;
this.user_info = user_info;
}
protected override void append_content (StringBuilder s, uint level) {
s.append ("NSError { domain = ");
domain.append_content (s, level);
s.append_printf (", code = %" + uint64.FORMAT_MODIFIER + "d, user_info = ", code);
if (user_info.size == 0) {
user_info.append_content (s, level);
s.append (" }");
return;
}
s.append ("{\n");
append_indent (s, level + 1);
s.append ("domain: ");
domain.append_content (s, level + 1);
s.append (",\n");
append_indent (s, level + 1);
s.append_printf ("code: %" + uint64.FORMAT_MODIFIER + "d,\n", code);
append_indent (s, level + 1);
s.append ("user_info: ");
user_info.append_content (s, level + 1);
s.append_c ('\n');
append_indent (s, level);
s.append_c ('}');
}
}
public sealed class DTTapMessage : NSObject {
@@ -476,25 +330,6 @@ namespace Frida.Fruity {
public DTTapMessage (NSDictionary plist) {
this.plist = plist;
}
protected override void append_content (StringBuilder s, uint level) {
if (plist.size == 0) {
s.append ("DTTapMessage { plist: ");
plist.append_content (s, level);
s.append (" }");
return;
}
s.append ("DTTapMessage {\n");
append_indent (s, level + 1);
s.append ("plist: ");
plist.append_content (s, level + 1);
s.append_c ('\n');
append_indent (s, level);
s.append_c ('}');
}
}
namespace NSKeyedArchive {
@@ -503,7 +338,6 @@ namespace Frida.Fruity {
private const string[] DICTIONARY_CLASS = { "NSDictionary", "NSObject" };
private const string[] ARRAY_CLASS = { "NSArray", "NSObject" };
private const string[] SET_CLASS = { "NSSet", "NSObject" };
[CCode (has_target = false)]
private delegate PlistUid EncodeFunc (NSObject instance, EncodingContext ctx);
@@ -621,7 +455,6 @@ namespace Frida.Fruity {
encoders[typeof (NSString)] = encode_string;
encoders[typeof (NSDictionary)] = encode_dictionary;
encoders[typeof (NSArray)] = encode_array;
encoders[typeof (NSSet)] = encode_set;
}
private static void ensure_decoders_registered () {
@@ -786,21 +619,6 @@ namespace Frida.Fruity {
return uid;
}
private static PlistUid encode_set (NSObject instance, EncodingContext ctx) {
NSSet set = (NSSet) instance;
var object = new PlistDict ();
var uid = ctx.add_object (object);
var objs = new PlistArray ();
foreach (var element in set.items)
objs.add_uid (encode_value (element, ctx));
object.set_array ("NS.objects", objs);
object.set_uid ("$class", ctx.get_class (SET_CLASS));
return uid;
}
private static NSObject decode_array (PlistDict instance, DecodingContext ctx) throws Error, PlistError {
var objs = instance.get_array ("NS.objects");
-180
View File
@@ -1,180 +0,0 @@
[CCode (gir_namespace = "FridaFruity", gir_version = "1.0")]
namespace Frida.Fruity {
public delegate void KperfdataRecordVisitor (KdBuf rec) throws Error;
public sealed class KperfdataStreamParser : Object {
private ByteArray stash = new ByteArray ();
private size_t cursor = 0;
private bool have_header = false;
private uint32 thread_count = 0;
private size_t records_offset = 0;
private const uint32 RAW_VERSION2 = 0x55aa0200u;
private const size_t HEADER_FIXED_SIZE = 0x120;
private const size_t THREADMAP_ENTRY_SIZE = 0x20;
private const size_t PAGE_SIZE = 0x1000;
private const size_t KD_BUF_SIZE = 0x40;
public void reset () {
stash.set_size (0);
cursor = 0;
have_header = false;
thread_count = 0;
records_offset = 0;
}
public void push (Bytes chunk, KperfdataRecordVisitor visitor) throws Error {
stash.append (chunk.get_data ());
var stash_bytes = new Bytes.static (stash.data);
parse_bytes (stash_bytes, visitor);
compact ();
}
private void parse_bytes (Bytes bytes, KperfdataRecordVisitor visitor) throws Error {
var buf = new Frida.Buffer (bytes, LITTLE_ENDIAN);
var r = new Frida.BufferReader (buf);
while (true) {
if (!have_header) {
if (r.available < 8)
return;
size_t header_start = r.offset;
uint32 magic = r.read_uint32 ();
if (magic != RAW_VERSION2)
throw new Error.PROTOCOL ("Unknown kperfdata magic 0x%x", magic);
thread_count = r.read_uint32 ();
uint64 threadmaps_size_64 = thread_count * THREADMAP_ENTRY_SIZE;
size_t header_size = (size_t) (HEADER_FIXED_SIZE + threadmaps_size_64);
size_t aligned = align_up (header_size, PAGE_SIZE);
records_offset = aligned;
if ((r.offset - 8) != header_start)
throw new Error.PROTOCOL ("Internal offset bookkeeping error");
if ((stash.len - header_start) < records_offset) {
r.skip (header_start - r.offset);
return;
}
cursor = header_start + records_offset;
have_header = true;
r.skip (cursor - r.offset);
continue;
}
if (r.offset < cursor) {
if ((cursor - r.offset) > r.available)
return;
r.skip (cursor - r.offset);
}
if (r.available < KD_BUF_SIZE)
return;
KdBuf rec = KdBuf ();
rec.timestamp = r.read_uint64 ();
rec.arg1 = r.read_uint64 ();
rec.arg2 = r.read_uint64 ();
rec.arg3 = r.read_uint64 ();
rec.arg4 = r.read_uint64 ();
rec.arg5 = r.read_uint64 ();
rec.debugid = r.read_uint32 ();
rec.cpuid = r.read_uint32 ();
rec.unused = r.read_uint64 ();
visitor (rec);
cursor = r.offset;
}
}
private void compact () {
if (cursor == 0)
return;
if (cursor >= stash.len) {
stash.set_size (0);
cursor = 0;
return;
}
size_t remaining = stash.len - cursor;
Memory.move (stash.data, (uint8 *) stash.data + cursor, remaining);
stash.set_size ((uint) remaining);
cursor = 0;
}
private static size_t align_up (size_t val, size_t alignment) {
size_t mask = alignment - 1;
return (val + mask) & ~mask;
}
}
public struct KdBuf {
public uint64 timestamp;
public uint64 arg1;
public uint64 arg2;
public uint64 arg3;
public uint64 arg4;
public uint64 arg5;
public uint32 debugid;
public uint32 cpuid;
public uint64 unused;
public KdebugCode kcode {
get {
return KdebugCode (debugid);
}
}
public string to_string () {
var kc = kcode;
return (
"ts=0x%" + uint64.FORMAT_MODIFIER + "x "
+ "arg1=0x%" + uint64.FORMAT_MODIFIER + "x "
+ "arg2=0x%" + uint64.FORMAT_MODIFIER + "x "
+ "arg3=0x%" + uint64.FORMAT_MODIFIER + "x "
+ "arg4=0x%" + uint64.FORMAT_MODIFIER + "x "
+ "arg5=0x%" + uint64.FORMAT_MODIFIER + "x "
+ "debugid=0x%08x "
+ "klass=%s subclass=%u code=%u func=%s "
+ "cpuid=%u "
+ "unused=0x%" + uint64.FORMAT_MODIFIER + "x"
).printf (
timestamp,
arg1,
arg2,
arg3,
arg4,
arg5,
debugid,
kc.klass.to_nick (),
kc.subclass,
kc.code,
kc.func_qual.to_nick (),
cpuid,
unused
);
}
}
}
+2 -2
View File
@@ -151,7 +151,7 @@ namespace Frida.LLDB {
Json.Reader reader;
try {
reader = make_json_reader (response.payload);
reader = new Json.Reader (Json.from_string (response.payload));
} catch (GLib.Error e) {
throw new Error.PROTOCOL ("Invalid response");
}
@@ -194,7 +194,7 @@ namespace Frida.LLDB {
Json.Reader reader;
try {
reader = make_json_reader (response.payload);
reader = new Json.Reader (Json.from_string (response.payload));
} catch (GLib.Error e) {
throw new Error.PROTOCOL ("Invalid response");
}
+29 -19
View File
@@ -36,6 +36,8 @@ namespace Frida.Fruity {
private uint16 ndp_fixed_header_size;
private VirtualNetworkStack? _netstack;
private Gee.Queue<Bytes> pending_input = new Gee.ArrayQueue<Bytes> ();
private bool input_flush_scheduled = false;
private Gee.Queue<Bytes> pending_output = new Gee.ArrayQueue<Bytes> ();
private size_t out_in_flight_count = 0;
private size_t out_in_flight_bytes = 0;
@@ -182,20 +184,8 @@ namespace Frida.Fruity {
}
try {
var datagrams = new Gee.ArrayList<Bytes> ();
while (true) {
var request = pending.peek ();
if (request == null)
break;
if (!datagrams.is_empty && !request.future.ready)
break;
var frame = yield pending.poll ().future.wait_async (io_cancellable);
datagrams.add_all (handle_ncm_frame (frame));
}
yield _netstack.handle_incoming_datagrams (datagrams);
var frame = yield pending.poll ().future.wait_async (io_cancellable);
handle_ncm_frame (frame);
} catch (GLib.Error e) {
return;
}
@@ -218,7 +208,7 @@ namespace Frida.Fruity {
}
}
private Gee.List<Bytes> handle_ncm_frame (Bytes frame) throws GLib.Error {
private void handle_ncm_frame (Bytes frame) throws GLib.Error {
var input = new DataInputStream (new MemoryInputStream.from_bytes (frame));
input.byte_order = LITTLE_ENDIAN;
@@ -232,8 +222,6 @@ namespace Frida.Fruity {
input.skip (6);
var ndp_index = input.read_uint16 ();
var datagrams = new Gee.ArrayList<Bytes> ();
do {
input.seek (ndp_index, SET);
input.read_all (raw_signature[:4], out bytes_read);
@@ -262,13 +250,35 @@ namespace Frida.Fruity {
notify_property ("remote-ipv6-address");
}
datagrams.add (datagram);
on_incoming_datagram (datagram);
}
ndp_index = next_ndp_index;
} while (ndp_index != 0);
}
return datagrams;
private void on_incoming_datagram (Bytes datagram) {
pending_input.offer (datagram);
if (!input_flush_scheduled) {
var source = new IdleSource ();
source.set_callback (() => {
input_flush_scheduled = false;
flush_pending_input ();
return Source.REMOVE;
});
source.attach (MainContext.get_thread_default ());
input_flush_scheduled = true;
}
}
private void flush_pending_input () {
var datagrams = pending_input;
pending_input = new Gee.ArrayQueue<Bytes> ();
try {
_netstack.handle_incoming_datagrams (datagrams);
} catch (Error e) {
}
}
private void on_netif_outgoing_datagrams (Gee.Collection<Bytes> datagrams) {
+6 -21
View File
@@ -283,14 +283,14 @@ namespace Frida.Fruity {
return new Ipv6UdpSocket (this);
}
public async void handle_incoming_datagrams (Gee.Collection<Bytes> datagrams) throws Error {
LWIP.ErrorCode err = OK;
public void handle_incoming_datagrams (Gee.Collection<Bytes> datagrams) throws Error {
check_started ();
schedule_on_lwip_thread (() => {
check (perform_on_lwip_thread (() => {
begin_output ();
LWIP.ErrorCode err = OK;
foreach (var d in datagrams) {
var pbuf = LWIP.PacketBuffer.alloc (RAW, (uint16) d.get_size (), POOL);
pbuf.take (d.get_data ());
@@ -304,14 +304,8 @@ namespace Frida.Fruity {
end_output ();
schedule_on_frida_thread (handle_incoming_datagrams.callback);
return err;
});
yield;
check (err);
}));
}
private static LWIP.ErrorCode on_netif_link_output (LWIP.NetworkInterface handle, LWIP.PacketBuffer pbuf) {
@@ -365,15 +359,6 @@ namespace Frida.Fruity {
}
internal LWIP.ErrorCode perform_on_lwip_thread (owned WorkFunc work) {
var req = submit_work ((owned) work);
return req.join ();
}
internal void schedule_on_lwip_thread (owned WorkFunc work) {
submit_work ((owned) work);
}
private Request submit_work (owned WorkFunc work) {
var req = new Request ((owned) work);
if (Thread.self<bool> () == lwip_thread) {
@@ -384,7 +369,7 @@ namespace Frida.Fruity {
LWIP.Runtime.schedule (perform_next_request);
}
return req;
return req.join ();
}
private void perform_next_request () {
File diff suppressed because it is too large. Load diff
+3 -9
View File
@@ -1592,11 +1592,8 @@ namespace Frida.Fruity {
if (t == typeof (string))
return str_hash (v.get_string ());
if (t == typeof (Bytes))
return ((Bytes) v.get_boxed ()).hash ();
if (t == typeof (PlistDict) || t == typeof (PlistArray))
return (uint) (size_t) v.get_object ();
if (t == typeof (Bytes) || t == typeof (PlistDict) || t == typeof (PlistArray))
return (uint) v.get_object ();
if (t == typeof (PlistUid))
return (uint) ((PlistUid) v.get_object ()).uid;
@@ -1626,10 +1623,7 @@ namespace Frida.Fruity {
if (t == typeof (string))
return a.get_string () == b.get_string ();
if (t == typeof (Bytes))
return ((Bytes) a.get_boxed ()).compare ((Bytes) b.get_boxed ()) == 0;
if (t == typeof (PlistDict) || t == typeof (PlistArray))
if (t == typeof (Bytes) || t == typeof (PlistDict) || t == typeof (PlistArray))
return a.get_object () == b.get_object ();
if (t == typeof (PlistNull))
-356
View File
@@ -1,356 +0,0 @@
[CCode (gir_namespace = "FridaFruity", gir_version = "1.0")]
namespace Frida.Fruity {
public sealed class TlsPskClientStream : IOStream, AsyncInitable {
public IOStream base_stream {
get;
construct;
}
public string psk_identity {
get;
construct;
}
public Bytes psk {
get;
construct;
}
public override InputStream input_stream {
get {
return _input_stream;
}
}
public override OutputStream output_stream {
get {
return _output_stream;
}
}
private OpenSSL.SSLContext ssl_ctx;
private OpenSSL.SSL ssl;
private void * rbio;
private void * wbio;
private PollableInputStream base_pollable_input;
private PollableOutputStream base_pollable_output;
private TlsPskInputStream _input_stream;
private TlsPskOutputStream _output_stream;
private const int IO_CHUNK_SIZE = 64 * 1024;
private const string CIPHER_LIST =
"PSK-AES128-GCM-SHA256:PSK-AES256-GCM-SHA384:PSK-AES256-CBC-SHA384:PSK-AES128-CBC-SHA256";
public static async TlsPskClientStream open (IOStream base_stream, string psk_identity, Bytes psk,
Cancellable? cancellable) throws Error, IOError {
var stream = new TlsPskClientStream (base_stream, psk_identity, psk);
try {
yield stream.init_async (Priority.DEFAULT, cancellable);
} catch (GLib.Error e) {
throw_api_error (e);
}
return stream;
}
private TlsPskClientStream (IOStream base_stream, string psk_identity, Bytes psk) {
Object (base_stream: base_stream, psk_identity: psk_identity, psk: psk);
}
construct {
var raw_input = base_stream.get_input_stream ();
var raw_output = base_stream.get_output_stream ();
assert (raw_input is PollableInputStream && raw_output is PollableOutputStream);
base_pollable_input = (PollableInputStream) raw_input;
base_pollable_output = (PollableOutputStream) raw_output;
_input_stream = new TlsPskInputStream (this);
_output_stream = new TlsPskOutputStream (this);
ssl_ctx = new OpenSSL.SSLContext (OpenSSL.SSLMethod.tls_client ());
ssl = new OpenSSL.SSL (ssl_ctx);
ssl.set_app_data (this);
ssl.set_connect_state ();
ssl.set_cipher_list (CIPHER_LIST);
ssl.set_psk_client_callback ((ssl, hint, identity, psk) => {
TlsPskClientStream * self = ssl.get_app_data ();
unowned uint8[] ident_bytes = self->psk_identity.data;
Memory.copy (identity, ident_bytes, ident_bytes.length);
unowned uint8[] key = self->psk.get_data ();
Memory.copy (psk, key, key.length);
return key.length;
});
rbio = OpenSSL.BasicIO.raw_new (OpenSSL.BasicIOMethod.memory ());
wbio = OpenSSL.BasicIO.raw_new (OpenSSL.BasicIOMethod.memory ());
ssl.set_bio (rbio, wbio);
}
private async bool init_async (int io_priority, Cancellable? cancellable) throws Error, IOError {
while (true) {
int ret = ssl.do_handshake ();
yield handshake_drain_wbio (cancellable);
if (ret == 1)
return true;
int err = ssl.get_error (ret);
if (err == OpenSSL.SSLErrorCode.WANT_READ) {
if (!yield handshake_feed_rbio (cancellable))
throw new Error.TRANSPORT ("Connection closed during TLS handshake");
} else if (err != OpenSSL.SSLErrorCode.WANT_WRITE) {
throw new Error.PROTOCOL ("TLS handshake failed: %s", openssl_error_string ());
}
}
}
private async void handshake_drain_wbio (Cancellable? cancellable) throws Error, IOError {
while (OpenSSL.BasicIO.raw_ctrl_pending (wbio) > 0) {
var buf = new uint8[IO_CHUNK_SIZE];
int n = OpenSSL.BasicIO.raw_read (wbio, buf);
try {
yield ((OutputStream) base_pollable_output).write_all_async (buf[0:n], Priority.DEFAULT,
cancellable, null);
} catch (GLib.Error e) {
throw new Error.TRANSPORT ("%s", e.message);
}
}
}
private async bool handshake_feed_rbio (Cancellable? cancellable) throws Error, IOError {
var buf = new uint8[IO_CHUNK_SIZE];
ssize_t n;
try {
n = yield ((InputStream) base_pollable_input).read_async (buf, Priority.DEFAULT, cancellable);
} catch (GLib.Error e) {
throw new Error.TRANSPORT ("%s", e.message);
}
if (n == 0)
return false;
OpenSSL.BasicIO.raw_write (rbio, buf[:n]);
return true;
}
internal ssize_t do_read_nonblocking (uint8[] buffer) throws GLib.Error {
while (true) {
int n = ssl.read (buffer);
if (n > 0)
return n;
int err = ssl.get_error (n);
if (err == OpenSSL.SSLErrorCode.ZERO_RETURN)
return 0;
if (err != OpenSSL.SSLErrorCode.WANT_READ)
throw new IOError.FAILED ("TLS read error: %s", openssl_error_string ());
var tmp = new uint8[IO_CHUNK_SIZE];
ssize_t r = base_pollable_input.read_nonblocking (tmp);
if (r == 0)
return 0;
OpenSSL.BasicIO.raw_write (rbio, tmp[:r]);
}
}
internal ssize_t do_read_blocking (uint8[] buffer, Cancellable? cancellable) throws IOError {
while (true) {
int n = ssl.read (buffer);
if (n > 0)
return n;
int err = ssl.get_error (n);
if (err == OpenSSL.SSLErrorCode.ZERO_RETURN)
return 0;
if (err != OpenSSL.SSLErrorCode.WANT_READ)
throw new IOError.FAILED ("TLS read error: %s", openssl_error_string ());
var tmp = new uint8[IO_CHUNK_SIZE];
ssize_t r = ((InputStream) base_pollable_input).read (tmp, cancellable);
if (r == 0)
return 0;
OpenSSL.BasicIO.raw_write (rbio, tmp[:r]);
}
}
internal bool do_is_readable () {
return ssl.pending () > 0 || base_pollable_input.is_readable ();
}
internal PollableSource do_create_input_source (Cancellable? cancellable) {
return new PollableSource.full (_input_stream,
base_pollable_input.create_source (cancellable), cancellable);
}
internal ssize_t do_write_nonblocking (uint8[] buffer) throws GLib.Error {
if (!flush_wbio_nonblocking ())
throw new IOError.WOULD_BLOCK ("Resource temporarily unavailable");
int n = ssl.write (buffer);
if (n <= 0) {
int err = ssl.get_error (n);
if (err == OpenSSL.SSLErrorCode.WANT_WRITE || err == OpenSSL.SSLErrorCode.WANT_READ)
throw new IOError.WOULD_BLOCK ("Resource temporarily unavailable");
throw new IOError.FAILED ("TLS write error: %s", openssl_error_string ());
}
flush_wbio_nonblocking ();
return n;
}
internal ssize_t do_write_blocking (uint8[] buffer, Cancellable? cancellable) throws IOError {
try {
flush_wbio_blocking (cancellable);
} catch (GLib.Error e) {
throw new IOError.FAILED ("%s", e.message);
}
int n = ssl.write (buffer);
if (n <= 0)
throw new IOError.FAILED ("TLS write error: %s", openssl_error_string ());
try {
flush_wbio_blocking (cancellable);
} catch (GLib.Error e) {
throw new IOError.FAILED ("%s", e.message);
}
return n;
}
internal bool do_is_writable () {
return base_pollable_output.is_writable ();
}
internal PollableSource do_create_output_source (Cancellable? cancellable) {
return new PollableSource.full (_output_stream, base_pollable_output.create_source (cancellable), cancellable);
}
private bool flush_wbio_nonblocking () throws GLib.Error {
while (true) {
unowned uint8[] data;
long len = OpenSSL.BasicIO.raw_get_mem_data (wbio, out data);
if (len == 0)
return true;
data.length = (int) len;
ssize_t written;
try {
written = base_pollable_output.write_nonblocking (data);
} catch (IOError.WOULD_BLOCK e) {
return false;
}
var scratch = new uint8[written];
OpenSSL.BasicIO.raw_read (wbio, scratch);
}
}
private void flush_wbio_blocking (Cancellable? cancellable) throws GLib.Error {
while (true) {
unowned uint8[] data;
long len = OpenSSL.BasicIO.raw_get_mem_data (wbio, out data);
if (len == 0)
return;
data.length = (int) len;
size_t written;
((OutputStream) base_pollable_output).write_all (data, out written, cancellable);
var scratch = new uint8[written];
OpenSSL.BasicIO.raw_read (wbio, scratch);
}
}
private static string openssl_error_string () {
var buf = new char[256];
OpenSSL.Error.error_string_n (OpenSSL.Error.get_error (), buf);
return (string) buf;
}
private class TlsPskInputStream : InputStream, PollableInputStream {
public weak TlsPskClientStream parent {
get;
construct;
}
public TlsPskInputStream (TlsPskClientStream parent) {
Object (parent: parent);
}
public override ssize_t read (uint8[] buffer, Cancellable? cancellable = null) throws IOError {
return parent.do_read_blocking (buffer, cancellable);
}
public override bool close (Cancellable? cancellable = null) throws IOError {
return true;
}
public bool can_poll () {
return true;
}
public bool is_readable () {
return parent.do_is_readable ();
}
public PollableSource create_source (Cancellable? cancellable) {
return parent.do_create_input_source (cancellable);
}
public ssize_t read_nonblocking_fn (uint8[] buffer) throws GLib.Error {
return parent.do_read_nonblocking (buffer);
}
}
private class TlsPskOutputStream : OutputStream, PollableOutputStream {
public weak TlsPskClientStream parent {
get;
construct;
}
public TlsPskOutputStream (TlsPskClientStream parent) {
Object (parent: parent);
}
public override ssize_t write (uint8[] buffer, Cancellable? cancellable = null) throws IOError {
return parent.do_write_blocking (buffer, cancellable);
}
public override bool close (Cancellable? cancellable = null) throws IOError {
return true;
}
public override bool flush (Cancellable? cancellable = null) throws GLib.Error {
return true;
}
public bool can_poll () {
return true;
}
public bool is_writable () {
return parent.do_is_writable ();
}
public PollableSource create_source (Cancellable? cancellable) {
return parent.do_create_output_source (cancellable);
}
public ssize_t write_nonblocking_fn (uint8[]? buffer) throws GLib.Error {
return parent.do_write_nonblocking (buffer);
}
public PollableReturn writev_nonblocking_fn (OutputVector[] vectors, out size_t bytes_written) throws GLib.Error {
assert_not_reached ();
}
}
}
}
File diff suppressed because it is too large. Load diff
+2873 -10
View File
File diff suppressed because it is too large. Load diff
+1 -20
View File
@@ -183,19 +183,6 @@ namespace Frida {
public abstract void unlink_service_session (HostSession host_session, ServiceSessionId id);
}
private const uint16 PROVIDER_ICON_SIZE = 96;
internal Variant make_provider_icon (uint8[] png) {
var image = new Bytes.static (png);
var builder = new VariantBuilder (VariantType.VARDICT);
builder.add ("{sv}", "format", new Variant.string ("png"));
builder.add ("{sv}", "width", new Variant.uint16 (PROVIDER_ICON_SIZE));
builder.add ("{sv}", "height", new Variant.uint16 (PROVIDER_ICON_SIZE));
builder.add ("{sv}", "image", Variant.new_from_data (new VariantType ("ay"),
image.get_data (), true, image));
return builder.end ();
}
public interface HostSessionConnection : Object {
public abstract HostSession host_session {
get;
@@ -244,12 +231,6 @@ namespace Frida {
set;
default = new Gee.HashMap<string, Value?> ();
}
public HostSessionOptions copy () {
var opts = new HostSessionOptions ();
opts.map.set_all (map);
return opts;
}
}
public interface HostChannelProvider : Object {
@@ -322,7 +303,7 @@ namespace Frida {
}
protected virtual Variant? load_icon () {
return make_provider_icon (Frida.Data.Icons.get_local_png_blob ().data);
return null;
}
public async void close (Cancellable? cancellable) throws IOError {
-2
View File
@@ -1,2 +0,0 @@
[resource-compiler]
namespace = Frida.Data.Icons
Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

Loaded 100 of 181 files, more files were not shown because too many files have changed in this diff. Show more