Repository: frida/frida
Branch: main
Commit: 6d77ff009fb3
Files: 31
Total size: 144.1 KB
Directory structure:
gitextract_t62922vv/
├── .cirrus.yml
├── .github/
│ ├── CODEOWNERS
│ ├── FUNDING.yml
│ ├── actions/
│ │ ├── package-artifact-file/
│ │ │ └── action.yml
│ │ ├── package-artifact-files-as-sfx/
│ │ │ └── action.yml
│ │ ├── package-artifact-files-as-tarball/
│ │ │ └── action.yml
│ │ ├── package-ios-assets/
│ │ │ └── action.yml
│ │ ├── package-tvos-assets/
│ │ │ └── action.yml
│ │ ├── prepare-python-packages/
│ │ │ └── action.yml
│ │ ├── publish-debs/
│ │ │ └── action.yml
│ │ ├── setup-freebsd-env/
│ │ │ └── action.yml
│ │ ├── setup-linux-env/
│ │ │ └── action.yml
│ │ ├── setup-macos-env/
│ │ │ └── action.yml
│ │ └── setup-windows-env/
│ │ └── action.yml
│ ├── scripts/
│ │ ├── package-cirrus-ci-artifacts.sh
│ │ ├── rename-release-assets.sh
│ │ └── repo.py
│ └── workflows/
│ └── ci.yml
├── .gitignore
├── .gitmodules
├── BSDmakefile
├── CONTRIBUTING.md
├── COPYING
├── Makefile
├── README.md
├── configure
├── configure.bat
├── make.bat
├── meson.build
├── meson.options
└── tools/
└── ensure-submodules.py
================================================
FILE CONTENTS
================================================
================================================
FILE: .cirrus.yml
================================================
task:
name: freebsd-x86_64
freebsd_instance:
image_family: freebsd-15-0-amd64-ufs
environment:
S3_ACCESS_KEY: ENCRYPTED[2f368bef589e43779394e459191eaad2fc4cc50dc36c6f03168a1e8e43897476e8bf596fd4dd0d988bcbab8fa8e171f8]
S3_SECRET_KEY: ENCRYPTED[45f352473433a1053622a662ce8d57bc7421bce5772c9c5caf4a0e54f63944bd420f71101e014876e038f0c66c134ac2]
CF_EMAIL: ENCRYPTED[a9f0dcd0ee83fa111c36f092f34b3d5660acafe0d07804d6b6a89bfa70a127ef8305f21089408959c51e23ecd2fd3622]
CF_TOKEN: ENCRYPTED[4f9f3f7c8603fd32978b825d65f34b06fce8e51bedb4303744c799d21fc38266173a6be5a7a46b5e616573d27c9f6e91]
PYTHON: /usr/local/bin/python3.11
PYTHON3: /usr/local/bin/python3.11
timeout_in: 2h
install_dependencies_script: |
pkg install -y \
bash \
bison \
git \
go \
npm \
py311-pip \
py311-setuptools
echo "CIRRUS_SHELL=$(which bash)" >> $CIRRUS_ENV
pip install awscli typing-extensions
npm install -g cloudflare-cli@5.0.5
clone_script: |
if [ -z "$CIRRUS_PR" ]; then
git clone --branch=$CIRRUS_BRANCH https://x-access-token:${CIRRUS_REPO_CLONE_TOKEN}@github.com/${CIRRUS_REPO_FULL_NAME}.git $CIRRUS_WORKING_DIR
else
git clone https://x-access-token:${CIRRUS_REPO_CLONE_TOKEN}@github.com/${CIRRUS_REPO_FULL_NAME}.git $CIRRUS_WORKING_DIR
git fetch origin pull/$CIRRUS_PR/head:pull/$CIRRUS_PR
fi
git reset --hard $CIRRUS_CHANGE_IN_REPO
$PYTHON tools/ensure-submodules.py
setup_environment_script: |
echo "FRIDA_PREFIX=$CIRRUS_WORKING_DIR/dist" >> $CIRRUS_ENV
echo "FRIDA_VERSION=$(python releng/frida_version.py)" >> $CIRRUS_ENV
mkdir -p ~/.aws
(
echo "[default]"
echo "region = us-east-1"
) > ~/.aws/config
(
echo "[default]"
echo "aws_access_key_id = $S3_ACCESS_KEY"
echo "aws_secret_access_key = $S3_SECRET_KEY"
) > ~/.aws/credentials
(
echo "defaults:"
echo " domain: frida.re"
echo " email: $CF_EMAIL"
echo " token: $CF_TOKEN"
) > ~/.cfcli.yml
roll_toolchain_script: $PYTHON releng/deps.py roll toolchain freebsd-x86_64 --activate
roll_sdk_script: $PYTHON releng/deps.py roll sdk freebsd-x86_64
configure_script: >-
./configure
"--prefix=$FRIDA_PREFIX"
--enable-gadget
--enable-server
--enable-portal
--enable-inject
--disable-frida-tools
--
-Dfrida-gum:devkits=gum,gumjs
-Dfrida-core:compiler_backend=enabled
-Dfrida-core:devkits=core
compile_script: make
install_script: make install
frida_gum_devkit_freebsd_x86_64_artifacts:
path: "$FRIDA_PREFIX/lib/frida/devkits/gum/*"
frida_gumjs_devkit_freebsd_x86_64_artifacts:
path: "$FRIDA_PREFIX/lib/frida/devkits/gumjs/*"
frida_core_devkit_freebsd_x86_64_artifacts:
path: "$FRIDA_PREFIX/lib/frida/devkits/core/*"
frida_server_freebsd_x86_64_artifacts:
path: "$FRIDA_PREFIX/bin/frida-server"
frida_portal_freebsd_x86_64_artifacts:
path: "$FRIDA_PREFIX/bin/frida-portal"
frida_inject_freebsd_x86_64_artifacts:
path: "$FRIDA_PREFIX/bin/frida-inject"
frida_gadget_freebsd_x86_64_artifacts:
path: "$FRIDA_PREFIX/lib/frida/64/frida-gadget.so"
package_python_script: |
export FRIDA_EXTENSION=$(find "$FRIDA_PREFIX" -name _frida.abi3.so)
cd subprojects/frida-python
pip wheel -w "$FRIDA_PREFIX/wheels" --no-deps .
frida_python_freebsd_x86_64_artifacts:
path: "$FRIDA_PREFIX/wheels/*.whl"
build_node_script: |
installdir=$FRIDA_PREFIX/prebuilds
export FRIDA_DEPS=$PWD/deps
export PKG_CONFIG_PATH=$FRIDA_PREFIX/libdata/pkgconfig
python tools/ensure-submodules.py frida-node
cd subprojects/frida-node
npm version $FRIDA_VERSION
./configure "--prefix=$FRIDA_PREFIX"
make prebuild
mkdir "$installdir"
cp build/*.tar.gz "$installdir"
frida_node_freebsd_x86_64_artifacts:
path: "$FRIDA_PREFIX/prebuilds/*"
================================================
FILE: .github/CODEOWNERS
================================================
/.github/workflows/ @oleavr
================================================
FILE: .github/FUNDING.yml
================================================
github: frida
================================================
FILE: .github/actions/package-artifact-file/action.yml
================================================
name: Package single-file artifact
description: Downloads an artifact and uploads a compressed version of its file
inputs:
name:
required: true
description: Artifact name
runs:
using: composite
steps:
- name: Download
uses: actions/download-artifact@v4
with:
name: ${{ inputs.name }}
path: ${{ inputs.name }}
- name: Compress
run: |
readarray -t files < <(ls -1 ${{ inputs.name }})
n=${#files[@]}
if [ $n -ne 1 ]; then
echo "Artifact may only contain a single file" > /dev/stderr
exit 1
fi
file=${files[0]}
if echo $file | grep -q '\.'; then
extension=".$(echo $file | cut -d'.' -f2-).xz"
else
extension=".xz"
fi
xz -c -T 0 ${{ inputs.name }}/$file > ${{ inputs.name }}/${{ inputs.name }}$extension
rm ${{ inputs.name }}/$file
shell: bash
- name: Upload
uses: actions/upload-artifact@v4
with:
name: release-asset-${{ inputs.name }}
path: ${{ inputs.name }}/*
================================================
FILE: .github/actions/package-artifact-files-as-sfx/action.yml
================================================
name: Package artifact files as SFX
description: Downloads a specific artifact and uploads a packaged version of it
inputs:
name:
required: true
description: Artifact name
runs:
using: composite
steps:
- name: Download
uses: actions/download-artifact@v4
with:
name: ${{ inputs.name }}
path: ${{ inputs.name }}
- name: Compress
run: |
cd ${{ inputs.name }}
7z a -sfx -r ..\${{ inputs.name }}.exe .
shell: pwsh
- name: Upload
uses: actions/upload-artifact@v4
with:
name: release-asset-${{ inputs.name }}-sfx
path: ${{ inputs.name }}.exe
================================================
FILE: .github/actions/package-artifact-files-as-tarball/action.yml
================================================
name: Package artifact files as tarball
description: Downloads a specific artifact and uploads a packaged version of it
inputs:
name:
required: true
description: Artifact name
runs:
using: composite
steps:
- name: Download
uses: actions/download-artifact@v4
with:
name: ${{ inputs.name }}
path: ${{ inputs.name }}
- name: Compress
run: tar -C ${{ inputs.name }} -cJf ${{ inputs.name }}.tar.xz .
env:
XZ_OPT: "-T 0"
shell: bash
- name: Upload
uses: actions/upload-artifact@v4
with:
name: release-asset-${{ inputs.name }}-tarball
path: ${{ inputs.name }}.tar.xz
================================================
FILE: .github/actions/package-ios-assets/action.yml
================================================
name: Package iOS assets
description: Downloads iOS assets and packages them
runs:
using: composite
steps:
- name: Download iOS assets
uses: actions/download-artifact@v4
with:
name: ios-assets
path: build/ios-assets/
- name: Create frida-server iOS .deb
run: |
cd build
mkdir -p release-assets
for arch in arm arm64; do
../subprojects/frida-core/tools/package-server-fruity.sh \
iphoneos-$arch \
ios-assets \
release-assets/frida_${FRIDA_VERSION}_iphoneos-$arch.deb
done
shell: bash
================================================
FILE: .github/actions/package-tvos-assets/action.yml
================================================
name: Package tvOS assets
description: Downloads tvOS assets and packages them
runs:
using: composite
steps:
- name: Download tvOS assets
uses: actions/download-artifact@v4
with:
name: tvos-assets
path: build/tvos-assets/
- name: Create frida-server tvOS .deb
run: |
cd build
mkdir -p release-assets
../subprojects/frida-core/tools/package-server-fruity.sh \
appletvos-arm64 \
tvos-assets \
release-assets/frida_${FRIDA_VERSION}_appletvos-arm64.deb
shell: bash
================================================
FILE: .github/actions/prepare-python-packages/action.yml
================================================
name: Prepare Python packages for publishing
description: Prepares Python source distribution and wheels to be published
runs:
using: composite
steps:
- name: Create source distribution
run: |
cd subprojects/frida-python
git submodule update --init --recursive
python setup.py sdist --dist-dir ../../build/python-packages
shell: bash
- name: Download wheel for Windows/x86
uses: actions/download-artifact@v4
with:
name: frida-python-windows-x86
path: build/python-packages/
- name: Download wheel for Windows/x86_64
uses: actions/download-artifact@v4
with:
name: frida-python-windows-x86_64
path: build/python-packages/
- name: Download wheel for Windows/arm64
uses: actions/download-artifact@v4
with:
name: frida-python-windows-arm64
path: build/python-packages/
- name: Download wheel for macOS/x86_64
uses: actions/download-artifact@v4
with:
name: frida-python-macos-x86_64
path: build/python-packages/
- name: Download wheel for macOS/arm64
uses: actions/download-artifact@v4
with:
name: frida-python-macos-arm64
path: build/python-packages/
- name: Download wheel for Linux/x86
uses: actions/download-artifact@v4
with:
name: frida-python-linux-x86
path: build/python-packages/
- name: Download wheel for Linux/x86_64
uses: actions/download-artifact@v4
with:
name: frida-python-linux-x86_64
path: build/python-packages/
- name: Download wheel for Linux/armhf
uses: actions/download-artifact@v4
with:
name: frida-python-linux-armhf
path: build/python-packages/
- name: Download wheel for Linux/arm64
uses: actions/download-artifact@v4
with:
name: frida-python-linux-arm64
path: build/python-packages/
================================================
FILE: .github/actions/publish-debs/action.yml
================================================
name: Publish .deb packages
description: Publishes already packaged debs
inputs:
site:
required: true
path: Where to publish; set to either “production” or “development”
runs:
using: composite
steps:
- name: Create repo metadata
run: |
archs="iphoneos-arm iphoneos-arm64 appletvos-arm64"
cd build
rm -rf deb-repo-config
mkdir deb-repo-config
(
echo "Origin: Cydia/Frida"
echo "Label: frida"
echo "Suite: stable"
echo "Version: 1.0"
echo "Codename: stable"
echo "Architectures: $archs"
echo "Components: main"
echo "Description: Frida for iOS/tvOS"
) > deb-repo-config/distributions
rm -rf deb-repo
mkdir -p deb-repo/debs
cd deb-repo
(
echo "Origin: Frida"
echo "Label: Frida"
echo "Suite: stable"
echo "Version: 1.0"
echo "Codename: ios"
echo "Architectures: $archs"
echo "Components: main"
echo "Description: Official Frida Repo"
) > Release
for arch in $archs; do
file=frida_${FRIDA_VERSION}_$arch.deb
cp $GITHUB_WORKSPACE/build/release-assets/$file debs/
reprepro \
-Vb . \
--confdir $GITHUB_WORKSPACE/build/deb-repo-config \
--ignore=forbiddenchar \
includedeb \
stable \
debs/$file
done
(
for arch in $archs; do
zcat < dists/stable/main/binary-$arch/Packages.gz
done
) > Packages
gzip -9k Packages
shell: bash
- name: Upload package and repo metadata
run: |
cd build/deb-repo
case ${{ inputs.site }} in
production)
prefix=
;;
development)
prefix=/dev
;;
*)
echo "Invalid repo specified" > /dev/stderr
exit 1
esac
aws s3 sync --delete pool/ s3://build.frida.re${prefix}/pool/
for file in Release Packages Packages.gz; do
aws s3 cp $file s3://build.frida.re${prefix}/
done
for file in Release Packages Packages.gz; do
aws s3 cp $file s3://build.frida.re${prefix}/./
done
urls_to_invalidate=()
for file in Release Packages Packages.gz ./Release ./Packages ./Packages.gz; do
urls_to_invalidate+=("https://build.frida.re${prefix}/${file}")
done
cfcli purge ${urls_to_invalidate[@]}
shell: bash
================================================
FILE: .github/actions/setup-freebsd-env/action.yml
================================================
name: Set up FreeBSD environment
description: Set up everything needed to build and release things on FreeBSD
inputs:
aws-access-key-id:
required: true
description: The aws-access-key-id used to authenticate with AWS
aws-secret-access-key:
required: true
description: The aws-secret-access-key used to authenticate with AWS
cloudflare-email:
required: true
description: The email used to authenticate with Cloudflare
cloudflare-token:
required: true
description: The token used to authenticate with Cloudflare
runs:
using: composite
steps:
- name: Configure git
run: |
git config --global user.name "Frida Developers"
git config --global user.email "oleavr@frida.re"
git config --global --add safe.directory $GITHUB_WORKSPACE
shell: bash
- name: Check out releng
run: |
git submodule update --init --depth 1 releng
cd releng
git submodule update --init --depth 1
shell: bash
- name: Add convenience environment variables
run: |
(
echo "FRIDA_PREFIX=$RUNNER_WORKSPACE/dist"
echo "FRIDA_VERSION=$(releng/frida_version.py)"
) >> $GITHUB_ENV
shell: bash
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ inputs.aws-access-key-id }}
aws-secret-access-key: ${{ inputs.aws-secret-access-key }}
aws-region: us-east-1
- name: Configure Cloudflare credentials
run: |
(
echo "defaults:"
echo " domain: frida.re"
echo " email: ${{ inputs.cloudflare-email }}"
echo " token: ${{ inputs.cloudflare-token }}"
) > ~/.cfcli.yml
shell: bash
================================================
FILE: .github/actions/setup-linux-env/action.yml
================================================
name: Set up Linux environment
description: Set up everything needed to build and release things on Linux
inputs:
aws-access-key-id:
required: true
description: The aws-access-key-id used to authenticate with AWS
aws-secret-access-key:
required: true
description: The aws-secret-access-key used to authenticate with AWS
cloudflare-email:
required: true
description: The email used to authenticate with Cloudflare
cloudflare-token:
required: true
description: The token used to authenticate with Cloudflare
runs:
using: composite
steps:
- name: Configure git
run: |
git config --global user.name "Frida Developers"
git config --global user.email "oleavr@frida.re"
git config --global --add safe.directory $GITHUB_WORKSPACE
shell: bash
- name: Check out releng
run: |
git submodule update --init --depth 1 releng
cd releng
git submodule update --init --depth 1
shell: bash
- name: Add convenience environment variables
run: |
(
echo "FRIDA_PREFIX=$RUNNER_WORKSPACE/dist"
echo "FRIDA_VERSION=$(releng/frida_version.py)"
) >> $GITHUB_ENV
shell: bash
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ inputs.aws-access-key-id }}
aws-secret-access-key: ${{ inputs.aws-secret-access-key }}
aws-region: us-east-1
- name: Configure Cloudflare credentials
run: |
(
echo "defaults:"
echo " domain: frida.re"
echo " email: ${{ inputs.cloudflare-email }}"
echo " token: ${{ inputs.cloudflare-token }}"
) > ~/.cfcli.yml
shell: bash
================================================
FILE: .github/actions/setup-macos-env/action.yml
================================================
name: Set up macOS environment
description: Set up everything needed to build and release things on macOS
inputs:
certificates-p12:
required: true
description: The certificates to use for codesigning, as a base64-encoded .p12
certificates-password:
required: true
description: The password for the .p12
keychain-password:
required: true
description: The keychain password to use
aws-access-key-id:
required: true
description: The aws-access-key-id used to authenticate with AWS
aws-secret-access-key:
required: true
description: The aws-secret-access-key used to authenticate with AWS
cloudflare-email:
required: true
description: The email used to authenticate with Cloudflare
cloudflare-token:
required: true
description: The token used to authenticate with Cloudflare
runs:
using: composite
steps:
- name: Install the Apple certificates
env:
CERTIFICATES_P12: ${{ inputs.certificates-p12 }}
CERTIFICATES_PASSWORD: ${{ inputs.certificates-password }}
KEYCHAIN_PASSWORD: ${{ inputs.keychain-password }}
run: |
CERTIFICATE_PATH=$RUNNER_TEMP/apple-certificates.p12
KEYCHAIN_PATH=$RUNNER_TEMP/frida-signing.keychain-db
echo -n "$CERTIFICATES_P12" | base64 --decode --output $CERTIFICATE_PATH
security create-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
security set-keychain-settings -lut 21600 $KEYCHAIN_PATH
security unlock-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
security import $CERTIFICATE_PATH -P "$CERTIFICATES_PASSWORD" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH
security list-keychain -d user -s $KEYCHAIN_PATH
rm $CERTIFICATE_PATH
(
MACOS_CERTID=$(security find-identity -v -p codesigning | grep "Developer ID Application: " | awk '{ print $2 }')
IOS_CERTID=$(security find-identity -v -p codesigning | grep "Apple Development: " | awk '{ print $2 }')
echo MACOS_CERTID=$MACOS_CERTID
echo IOS_CERTID=$IOS_CERTID
echo WATCHOS_CERTID=$IOS_CERTID
echo TVOS_CERTID=$IOS_CERTID
) >> $GITHUB_ENV
shell: bash
- name: Configure git
run: |
git config --global user.name "Frida Developers"
git config --global user.email "oleavr@frida.re"
shell: bash
- name: Check out releng
run: |
git submodule update --init --depth 1 releng
cd releng
git submodule update --init --depth 1
shell: bash
- name: Add convenience environment variables
run: |
(
echo "FRIDA_PREFIX=$RUNNER_WORKSPACE/dist"
echo "FRIDA_VERSION=$(releng/frida_version.py)"
) >> $GITHUB_ENV
shell: bash
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ inputs.aws-access-key-id }}
aws-secret-access-key: ${{ inputs.aws-secret-access-key }}
aws-region: us-east-1
- name: Configure Cloudflare credentials
run: |
(
echo "defaults:"
echo " domain: frida.re"
echo " email: ${{ inputs.cloudflare-email }}"
echo " token: ${{ inputs.cloudflare-token }}"
) > ~/.cfcli.yml
shell: bash
- name: Install Python
uses: actions/setup-python@v6
with:
python-version: '3.12'
- name: Install setuptools
run: pip install setuptools
shell: bash
- name: Install cloudflare-cli
run: npm install -g cloudflare-cli@5.0.5
shell: bash
================================================
FILE: .github/actions/setup-windows-env/action.yml
================================================
name: Set up Windows environment
description: Set up everything needed to build and release things on Windows
inputs:
aws-access-key-id:
required: true
description: The aws-access-key-id used to authenticate with AWS
aws-secret-access-key:
required: true
description: The aws-secret-access-key used to authenticate with AWS
cloudflare-email:
required: true
description: The email used to authenticate with Cloudflare
cloudflare-token:
required: true
description: The token used to authenticate with Cloudflare
architecture:
description: The target architecture
default: x64
runs:
using: composite
steps:
- name: Configure git
run: |
git config --global user.name "Frida Developers"
git config --global user.email "oleavr@frida.re"
shell: pwsh
- name: Check out releng
run: |
git submodule update --init --depth 1 releng
cd releng
git submodule update --init --depth 1
shell: pwsh
- name: Add convenience environment variables
run: |
echo "FRIDA_PREFIX=$Env:RUNNER_WORKSPACE\dist" >> $Env:GITHUB_ENV
echo "FRIDA_VERSION=$(python releng/frida_version.py)" >> $Env:GITHUB_ENV
shell: pwsh
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ inputs.aws-access-key-id }}
aws-secret-access-key: ${{ inputs.aws-secret-access-key }}
aws-region: us-east-1
- name: Configure Cloudflare credentials
run: |
@"
defaults:
domain: frida.re
email: ${{ inputs.cloudflare-email }}
token: ${{ inputs.cloudflare-token }}
"@ | Set-Content -Path $HOME\.cfcli.yml -NoNewline
shell: pwsh
- name: Install Python
uses: actions/setup-python@v6
with:
python-version: '3.12'
architecture: ${{ inputs.architecture }}
- name: Install setuptools
run: pip install setuptools
shell: pwsh
- name: Install cloudflare-cli
run: npm install -g cloudflare-cli@5.0.5
shell: pwsh
================================================
FILE: .github/scripts/package-cirrus-ci-artifacts.sh
================================================
#!/bin/bash
sha=$1
if [ -z "$sha" ]; then
echo "Usage: $0 <sha>" > /dev/stderr
exit 1
fi
set -e
build_id=""
while [ -z "$build_id" ]; do
response=$(curl https://api.cirrus-ci.com/graphql --silent --data \
'{
"query": "query BuildBySHAQuery($owner: String!, $name: String!, $SHA: String) { searchBuilds(repositoryOwner: $owner, repositoryName: $name, SHA: $SHA) { id, status } }",
"variables": {
"owner": "frida",
"name": "frida",
"SHA": "'$sha'"
}
}'
);
pending=0
errors=0
for build in $(echo $response | jq -r '.data.searchBuilds[] | { id, status } | join("|")'); do
id=$(echo $build | cut -d'|' -f1)
status=$(echo $build | cut -d'|' -f2)
case $status in
COMPLETED)
build_id=$id
;;
FAILED|ABORTED|ERRORED)
errors=$((errors+1))
;;
*)
pending=$((pending+1))
;;
esac
done
if [ -z "$build_id" ]; then
if [ $errors -gt 0 ] && [ $pending -eq 0 ]; then
echo "Cirrus CI build failed :(" > /dev/stderr
exit 1
else
echo "Cirrus CI build not yet completed. Checking back in 5 minutes."
sleep 300
fi
fi
done
output_dir=$PWD/build/release-assets
mkdir -p "$output_dir"
export XZ_OPT="-T 0"
for task in freebsd_x86_64; do
host=$(echo $task | sed -e 's,_,-,')
enter_artifact ()
{
local name=$1
rm -rf build/pkg
mkdir -p build/pkg
pushd build/pkg > /dev/null
local url=https://api.cirrus-ci.com/v1/artifact/build/$build_id/${name}_${task}.zip
echo "Processing $url"
curl $url -sLo artifact.zip
unzip -qq artifact.zip
rm artifact.zip
}
leave_artifact ()
{
popd > /dev/null
rm -rf build/pkg
}
for component in gum gumjs core; do
enter_artifact frida_${component}_devkit
mv dist/lib/frida/devkits/$component/* .
rm -rf build
tar -cJf "$output_dir/frida-$component-devkit-$host.tar.xz" .
leave_artifact
done
for component in server portal inject gadget; do
enter_artifact frida_${component}
readarray -t files < <(find . -type f)
n=${#files[@]}
if [ $n -ne 1 ]; then
echo "The frida-$component artifact should only contain a single file" > /dev/stderr
exit 1
fi
file=${files[0]}
name=$(basename $file)
if echo $name | grep -q '\.'; then
extension=".$(echo $name | cut -d'.' -f2-).xz"
else
extension=".xz"
fi
xz -c -T 0 "$file" > "$output_dir/frida-$component-$host$extension"
leave_artifact
done
enter_artifact frida_python
mv dist/wheels/* "$output_dir"
leave_artifact
enter_artifact frida_node
mv dist/prebuilds/* "$output_dir"
leave_artifact
done
================================================
FILE: .github/scripts/rename-release-assets.sh
================================================
#!/bin/bash
if [ -z "$FRIDA_VERSION" ]; then
echo "FRIDA_VERSION must be set" > /dev/stderr
exit 1
fi
set -e
cd build/release-assets
for name in *; do
if echo $name | grep -q $FRIDA_VERSION; then
continue
fi
case $name in
frida-*-devkit-*)
new_name=$(echo $name | sed -e "s,devkit-,devkit-$FRIDA_VERSION-,")
;;
frida-server-*|frida-portal-*|frida-inject-*|frida-gadget-*|frida-swift-*|frida-clr-*|frida-qml-*|gum-graft-*)
new_name=$(echo $name | sed -E -e "s,^(frida|gum)-([^-]+),\\1-\\2-$FRIDA_VERSION,")
;;
*)
new_name=""
;;
esac
if [ -n "$new_name" ]; then
mv -v $name $new_name
fi
done
================================================
FILE: .github/scripts/repo.py
================================================
#!/usr/bin/env python3
import argparse
from configparser import ConfigParser
from pathlib import Path
import subprocess
import sys
from typing import Iterator
ROOT_DIR = Path(__file__).parent.parent.parent.resolve()
RELENG_DIR = ROOT_DIR / "releng"
if not (RELENG_DIR / "meson" / "meson.py").exists():
subprocess.run(["git", "submodule", "update", "--init", "--depth", "1", "--recursive", "releng"],
cwd=ROOT_DIR)
sys.path.insert(0, str(ROOT_DIR))
from releng.deps import load_dependency_parameters, query_repo_commits
PROJECT_NAMES_IN_RELEASE_CYCLE = [
"frida-gum",
"frida-core",
"frida-clr",
"frida-node",
"frida-python",
"frida-qml",
"frida-swift",
]
def main(argv: list[str]):
parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers()
command = subparsers.add_parser("bump", help="bump all the things")
command.set_defaults(func=lambda args: bump())
command = subparsers.add_parser("tag", help="tag a new release")
command.add_argument("version")
command.set_defaults(func=lambda args: tag(args.version))
command = subparsers.add_parser("backtag", help="retroactively tag an old release")
command.add_argument("version")
command.set_defaults(func=lambda args: backtag(args.version))
args = parser.parse_args()
if "func" in args:
try:
args.func(args)
except Exception as e:
print(e, file=sys.stderr)
if isinstance(e, subprocess.CalledProcessError):
for label, data in [("Output", e.output),
("Stderr", e.stderr)]:
if data:
print(f"{label}:\n\t| " + "\n\t| ".join(data.strip().split("\n")), file=sys.stderr)
sys.exit(1)
else:
parser.print_usage(file=sys.stderr)
sys.exit(1)
def bump():
projects = list(enumerate_projects_in_release_cycle())
projects.append(("frida-tools", ROOT_DIR / "subprojects" / "frida-tools"))
assert_no_local_changes(ROOT_DIR)
for _, repo in projects:
assert_no_local_changes(repo)
print("# releng")
bump_releng(ROOT_DIR / "releng")
if query_local_changes(ROOT_DIR):
print("\tbumped")
else:
print("\tup-to-date")
for name, repo in projects:
bump_subproject(name, repo)
if bump_submodules():
push_changes("frida", ROOT_DIR)
def bump_subproject(name: str, repo: Path):
print(f"# {name}")
if not (repo / "meson.build").exists():
run(["git", "submodule", "update", "--init", "--depth", "1", Path("subprojects") / repo], cwd=ROOT_DIR)
run(["git", "checkout", "main"], cwd=repo)
run(["git", "pull"], cwd=repo)
releng = repo / "releng"
bump_releng(releng)
if query_local_changes(repo):
run(["git", "submodule", "update"], cwd=releng)
run(["git", "add", "releng"], cwd=repo)
run(["git", "commit", "-m", "submodules: Bump releng"], cwd=repo)
print("\treleng: bumped")
else:
print("\treleng: up-to-date")
bumped_files: list[Path] = []
dep_packages = load_dependency_parameters().packages
for identifier, config, wrapfile in enumerate_git_wraps_in_repo(repo):
if identifier == "nan":
continue
source = config["wrap-git"]
pkg = dep_packages.get(identifier)
if pkg is not None:
current_revision = pkg.version
else:
other_repo = ROOT_DIR / "subprojects" / identifier
if other_repo.exists():
current_revision = run(["git", "rev-parse", "HEAD"], cwd=other_repo).stdout.strip()
else:
url = source["url"]
assert url.startswith("https://github.com/"), f"{url}: unhandled repo URL"
assert url.endswith(".git")
tokens = url[19:-4].split("/")
assert len(tokens) == 2
current_revision = query_repo_commits(organization=tokens[0], repo=tokens[1])["sha"]
if source["revision"] != current_revision:
source["revision"] = current_revision
with wrapfile.open("w") as f:
config.write(f)
bumped_files.append(wrapfile)
if bumped_files:
run(["git", "add", *bumped_files], cwd=repo)
run(["git", "commit", "-m", "subprojects: Bump outdated"], cwd=repo)
print(f"\tsubprojects: bumped {', '.join([f.stem for f in bumped_files])}")
else:
print("\tsubprojects: up-to-date")
push_changes(name, repo)
def bump_releng(releng: Path):
if not (releng / "meson" / "meson.py").exists():
run(["git", "submodule", "update", "--init", "--depth", "1", "--recursive", "releng"], cwd=releng.parent)
run(["git", "checkout", "main"], cwd=releng)
run(["git", "pull"], cwd=releng)
def bump_submodules() -> list[str]:
print("# submodules")
changes = query_local_changes(ROOT_DIR)
relevant_changes = [relpath for kind, relpath in changes
if kind == "M" and (relpath == "releng" or relpath.startswith("subprojects/"))]
assert len(changes) == len(relevant_changes), "frida: expected clean repo"
if relevant_changes:
run(["git", "add", *relevant_changes], cwd=ROOT_DIR)
run(["git", "commit", "-m", "submodules: Bump outdated"], cwd=ROOT_DIR)
print(f"\tbumped {', '.join([Path(relpath).name for relpath in relevant_changes])}")
else:
print("\tup-to-date")
return relevant_changes
def tag(version: str):
for _, repo in enumerate_projects_in_release_cycle():
assert_no_local_changes(repo)
for name, repo in enumerate_projects_in_release_cycle():
prepublish(name, version, repo)
bump_submodules()
prepublish("frida", version, ROOT_DIR)
def prepublish(name: str, version: str, repo: Path):
print("Prepublishing:", name)
modified_wrapfiles: list[Path] = []
for identifier, config, wrapfile in enumerate_git_wraps_in_repo(repo):
if identifier in PROJECT_NAMES_IN_RELEASE_CYCLE:
config["wrap-git"]["revision"] = version
with wrapfile.open("w") as f:
config.write(f)
modified_wrapfiles.append(wrapfile)
if modified_wrapfiles:
run(["git", "add", *modified_wrapfiles], cwd=repo)
run(["git", "commit", "-m", "subprojects: Prepare for release"], cwd=repo)
print(f"\tsubprojects: prepared {', '.join([f.stem for f in modified_wrapfiles])}")
else:
print("\tsubprojects: no changes needed")
run(["git", "tag", version], cwd=repo)
run(["git", "push", "--atomic", "origin", "main", version], cwd=repo)
print("\tpushed")
def backtag(version: str):
run(["git", "checkout", version], cwd=ROOT_DIR)
run(["git", "submodule", "update"], cwd=ROOT_DIR)
for name, repo in enumerate_projects_in_release_cycle():
if not run(["git", "tag", "-l", version], cwd=repo).stdout.strip():
run(["git", "tag", version], cwd=repo)
ensure_remote_origin_writable(name, repo)
run(["git", "push", "origin", version], cwd=repo)
def enumerate_projects_in_release_cycle() -> Iterator[tuple[str, Path]]:
for name in PROJECT_NAMES_IN_RELEASE_CYCLE:
yield name, ROOT_DIR / "subprojects" / name
def enumerate_git_wraps_in_repo(repo: Path) -> Iterator[tuple[str, ConfigParser, Path]]:
for wrapfile in (repo / "subprojects").glob("*.wrap"):
identifier = wrapfile.stem
config = ConfigParser()
config.read(wrapfile)
if "wrap-git" not in config:
continue
yield identifier, config, wrapfile
def assert_no_local_changes(repo: Path):
assert not query_local_changes(repo), f"{repo.name}: expected clean repo"
def query_local_changes(repo: Path) -> list[str]:
output = run(["git", "status", "--porcelain=v1"], cwd=repo).stdout.strip()
if not output:
return []
return [tuple(line.strip().split(" ", maxsplit=1)) for line in output.split("\n")]
def push_changes(name: str, repo: Path):
ensure_remote_origin_writable(name, repo)
run(["git", "push", "-u", "origin", "main"], cwd=repo)
def ensure_remote_origin_writable(name: str, repo: Path):
if "https:" in run(["git", "remote", "show", "origin", "-n"], cwd=repo).stdout:
run(["git", "remote", "rm", "origin"], cwd=repo)
run(["git", "remote", "add", "origin", f"git@github.com:frida/{name}.git"], cwd=repo)
run(["git", "fetch", "origin"], cwd=repo)
def run(argv: list[str], **kwargs) -> subprocess.CompletedProcess:
return subprocess.run(argv,
capture_output=True,
encoding="utf-8",
check=True,
**kwargs)
if __name__ == "__main__":
main(sys.argv)
================================================
FILE: .github/workflows/ci.yml
================================================
name: CI
on: push
env:
FRIDA_COMPILER_MOD: subprojects/frida-core/src/compiler/go.mod
ANDROID_NDK_VERSION: r29
jobs:
publish-prod:
if: startsWith(github.ref, 'refs/tags/')
runs-on: ubuntu-latest
needs:
- package-windows
- package-windows-sfx
- package-macos
- package-linux
- package-ios
- package-watchos
- package-tvos
- package-android
- package-qnx
- package-apple-universal
- assemble-ios-assets
- assemble-tvos-assets
permissions:
contents: write
id-token: write
steps:
- name: Check out repo
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up environment
uses: ./.github/actions/setup-linux-env
with:
aws-access-key-id: ${{ secrets.S3_ACCESS_KEY }}
aws-secret-access-key: ${{ secrets.S3_SECRET_KEY }}
cloudflare-email: ${{ secrets.CF_EMAIL }}
cloudflare-token: ${{ secrets.CF_TOKEN }}
- name: Grab needed submodules
run: python tools/ensure-submodules.py frida-gum frida-core frida-python frida-node
- name: Install tools
run: |
sudo apt-get update
sudo apt-get install -y reprepro
sudo npm install -g cloudflare-cli@5.0.5
- name: Download release assets
uses: actions/download-artifact@v4
with:
pattern: release-asset-*
merge-multiple: true
path: build/release-assets/
- name: Download Node-API prebuilds for Windows/x86_64
uses: actions/download-artifact@v4
with:
name: frida-node-windows-x86_64
path: build/release-assets/
- name: Download Node-API prebuilds for Windows/arm64
uses: actions/download-artifact@v4
with:
name: frida-node-windows-arm64
path: build/release-assets/
- name: Download Node-API prebuilds for macOS/x86_64
uses: actions/download-artifact@v4
with:
name: frida-node-macos-x86_64
path: build/release-assets/
- name: Download Node-API prebuilds for macOS/arm64
uses: actions/download-artifact@v4
with:
name: frida-node-macos-arm64
path: build/release-assets/
- name: Download Node-API prebuilds for Linux/x86
uses: actions/download-artifact@v4
with:
name: frida-node-linux-x86
path: build/release-assets/
- name: Download Node-API prebuilds for Linux/x86_64
uses: actions/download-artifact@v4
with:
name: frida-node-linux-x86_64
path: build/release-assets/
- name: Download Node-API prebuilds for Linux/armhf
uses: actions/download-artifact@v4
with:
name: frida-node-linux-armhf
path: build/release-assets/
- name: Download Node-API prebuilds for Linux/arm64
uses: actions/download-artifact@v4
with:
name: frida-node-linux-arm64
path: build/release-assets/
- name: Package iOS assets
uses: ./.github/actions/package-ios-assets
- name: Package tvOS assets
uses: ./.github/actions/package-tvos-assets
- name: Rename release assets
run: .github/scripts/rename-release-assets.sh
- name: Publish release to GitHub
uses: softprops/action-gh-release@v1
with:
name: "Frida ${{ env.FRIDA_VERSION }}"
body: "See https://frida.re/news/ for details."
files: build/release-assets/*
- name: Prepare Python packages
uses: ./.github/actions/prepare-python-packages
- name: Publish Python bindings to pypi.org
uses: pypa/gh-action-pypi-publish@release/v1
with:
packages-dir: build/python-packages/
- name: Publish .deb packages
uses: ./.github/actions/publish-debs
with:
site: production
- name: Trigger frida-node publish
env:
GH_TOKEN: ${{ secrets.FRIDA_NODE_BOT_PAT }}
FRIDA_VERSION: ${{ env.FRIDA_VERSION }}
run: |
gh api repos/frida/frida-node/dispatches \
-f event_type=publish-prod-started \
-f client_payload[frida_version]="${FRIDA_VERSION}"
- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version: 24
- name: Publish frida-gadget-ios to npm
run: |
cd releng/modules/frida-gadget-ios
npm version $FRIDA_VERSION
npm publish
- name: Trigger magisk-frida CI
run: |
curl \
-X POST \
-H "Accept: application/vnd.github.v3+json" \
-H "Authorization: token ${{ secrets.MAGISK_FRIDA_TOKEN }}" \
https://api.github.com/repos/ViRb3/magisk-frida/dispatches \
-d '{"event_type":"build"}'
publish-dev:
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
needs:
- frida-windows
- frida-macos
- frida-linux
- assemble-ios-assets
- assemble-tvos-assets
permissions:
id-token: write
steps:
- name: Check out repo
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up environment
uses: ./.github/actions/setup-linux-env
with:
aws-access-key-id: ${{ secrets.S3_ACCESS_KEY }}
aws-secret-access-key: ${{ secrets.S3_SECRET_KEY }}
cloudflare-email: ${{ secrets.CF_EMAIL }}
cloudflare-token: ${{ secrets.CF_TOKEN }}
- name: Grab needed submodules
run: python tools/ensure-submodules.py frida-core frida-python
- name: Install tools
run: |
sudo apt-get update
sudo apt-get install -y reprepro
sudo npm install -g cloudflare-cli@5.0.5
- name: Package iOS assets
uses: ./.github/actions/package-ios-assets
- name: Package tvOS assets
uses: ./.github/actions/package-tvos-assets
- name: Prepare Python packages
uses: ./.github/actions/prepare-python-packages
- name: Publish Python bindings to TestPyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
packages-dir: build/python-packages/
repository-url: https://test.pypi.org/legacy/
- name: Publish .deb packages
uses: ./.github/actions/publish-debs
with:
site: development
assemble-ios-assets:
runs-on: macos-latest
needs: frida-ios
steps:
- name: Check out repo
uses: actions/checkout@v4
- name: Set up environment
uses: ./.github/actions/setup-macos-env
with:
certificates-p12: ${{ secrets.APPLE_CERTIFICATES_P12 }}
certificates-password: ${{ secrets.APPLE_CERTIFICATES_PASSWORD }}
keychain-password: ${{ secrets.APPLE_KEYCHAIN_PASSWORD }}
aws-access-key-id: ${{ secrets.S3_ACCESS_KEY }}
aws-secret-access-key: ${{ secrets.S3_SECRET_KEY }}
cloudflare-email: ${{ secrets.CF_EMAIL }}
cloudflare-token: ${{ secrets.CF_TOKEN }}
- name: Download universal frida-server for iOS/arm64(e)
uses: actions/download-artifact@v4
with:
name: frida-server-ios-arm64e
path: ios-arm64e/
- name: Create universal frida-server for iOS
run: |
lipo ios-arm64e/frida-server -thin arm64 -output frida-server-arm64
lipo ios-arm64e/frida-server -thin arm64e -output frida-server-arm64e
for arch in arm64 arm64e; do
codesign -f -s "-" --preserve-metadata=entitlements frida-server-$arch
done
./releng/mkfatmacho.py \
frida-server-ios-universal \
frida-server-arm64 \
frida-server-arm64e
- name: Download universal frida-agent for iOS/arm64(e)
uses: actions/download-artifact@v4
with:
name: frida-agent-ios-arm64e
path: ios-arm64e/
- name: Sign universal frida-agent for iOS/arm64(e)
run: codesign -f -s "-" ios-arm64e/frida-agent.dylib
- name: Assemble iOS assets
run: |
mkdir -p ios-assets/usr/bin ios-assets/usr/lib/frida
mv frida-server-ios-universal ios-assets/usr/bin/frida-server
mv ios-arm64e/frida-agent.dylib ios-assets/usr/lib/frida/frida-agent.dylib
- name: Upload iOS assets
uses: actions/upload-artifact@v4
with:
name: ios-assets
path: ios-assets/*
assemble-tvos-assets:
runs-on: macos-latest
needs: frida-tvos
steps:
- name: Check out repo
uses: actions/checkout@v4
- name: Set up environment
uses: ./.github/actions/setup-macos-env
with:
certificates-p12: ${{ secrets.APPLE_CERTIFICATES_P12 }}
certificates-password: ${{ secrets.APPLE_CERTIFICATES_PASSWORD }}
keychain-password: ${{ secrets.APPLE_KEYCHAIN_PASSWORD }}
aws-access-key-id: ${{ secrets.S3_ACCESS_KEY }}
aws-secret-access-key: ${{ secrets.S3_SECRET_KEY }}
cloudflare-email: ${{ secrets.CF_EMAIL }}
cloudflare-token: ${{ secrets.CF_TOKEN }}
- name: Download frida-server for tvOS/arm64
uses: actions/download-artifact@v4
with:
name: frida-server-tvos-arm64
path: tvos-arm64/
- name: Prepare frida-server for tvOS/arm64
run: codesign -f -s "-" --preserve-metadata=entitlements tvos-arm64/frida-server
- name: Download frida-agent for tvOS/arm64
uses: actions/download-artifact@v4
with:
name: frida-agent-tvos-arm64
path: tvos-arm64/
- name: Prepare frida-agent for tvOS/arm64
run: codesign -f -s "-" tvos-arm64/frida-agent.dylib
- name: Assemble tvOS assets
run: |
mkdir -p tvos-assets/usr/bin tvos-assets/usr/lib/frida
mv tvos-arm64/frida-server tvos-assets/usr/bin/frida-server
mv tvos-arm64/frida-agent.dylib tvos-assets/usr/lib/frida/frida-agent.dylib
- name: Upload tvOS assets
uses: actions/upload-artifact@v4
with:
name: tvos-assets
path: tvos-assets/*
package-apple-universal:
if: startsWith(github.ref, 'refs/tags/')
runs-on: macos-latest
needs: [frida-macos, frida-ios, frida-watchos, frida-tvos]
steps:
- name: Check out repo
uses: actions/checkout@v4
- name: Set up environment
uses: ./.github/actions/setup-macos-env
with:
certificates-p12: ${{ secrets.APPLE_CERTIFICATES_P12 }}
certificates-password: ${{ secrets.APPLE_CERTIFICATES_PASSWORD }}
keychain-password: ${{ secrets.APPLE_KEYCHAIN_PASSWORD }}
aws-access-key-id: ${{ secrets.S3_ACCESS_KEY }}
aws-secret-access-key: ${{ secrets.S3_SECRET_KEY }}
cloudflare-email: ${{ secrets.CF_EMAIL }}
cloudflare-token: ${{ secrets.CF_TOKEN }}
- name: Download frida-gadget for macOS/x86_64
uses: actions/download-artifact@v4
with:
name: frida-gadget-macos-x86_64
path: macos-x86_64/
- name: Download frida-gadget for macOS/arm64(e)
uses: actions/download-artifact@v4
with:
name: frida-gadget-macos-arm64e
path: macos-arm64e/
- name: Create universal frida-gadget for macOS
run: |
lipo \
macos-x86_64/frida-gadget.dylib \
macos-arm64e/frida-gadget.dylib \
-create -output frida-gadget-macos-universal.dylib
install_name_tool \
-id @executable_path/../Frameworks/FridaGadget.dylib \
frida-gadget-macos-universal.dylib
codesign \
-f -s "$MACOS_CERTID" \
frida-gadget-macos-universal.dylib
- name: Compress universal frida-gadget for macOS
run: xz -T 0 frida-gadget-macos-universal.dylib
- name: Upload universal frida-gadget for macOS
uses: actions/upload-artifact@v4
with:
name: release-asset-frida-gadget-macos-universal
path: frida-gadget-macos-universal.dylib.xz
- name: Download frida-gadget for iOS/arm64(e)
uses: actions/download-artifact@v4
with:
name: frida-gadget-ios-arm64e
path: ios-arm64e/
- name: Create universal frida-gadget for iOS
run: |
mv ios-arm64e/frida-gadget.dylib frida-gadget-ios-universal.dylib
install_name_tool \
-id @executable_path/Frameworks/FridaGadget.dylib \
frida-gadget-ios-universal.dylib
codesign \
-f -s "$IOS_CERTID" \
frida-gadget-ios-universal.dylib
- name: Compress universal frida-gadget for iOS
run: |
gzip -k frida-gadget-ios-universal.dylib
xz -T 0 frida-gadget-ios-universal.dylib
- name: Upload universal frida-gadget for iOS (gz)
uses: actions/upload-artifact@v4
with:
name: release-asset-frida-gadget-ios-universal-gz
path: frida-gadget-ios-universal.dylib.gz
- name: Upload universal frida-gadget for iOS (xz)
uses: actions/upload-artifact@v4
with:
name: release-asset-frida-gadget-ios-universal-xz
path: frida-gadget-ios-universal.dylib.xz
- name: Download frida-gadget for iOS/x86_64-simulator
uses: actions/download-artifact@v4
with:
name: frida-gadget-ios-x86_64-simulator
path: ios-x86_64-simulator/
- name: Download frida-gadget for iOS/arm64-simulator
uses: actions/download-artifact@v4
with:
name: frida-gadget-ios-arm64-simulator
path: ios-arm64-simulator/
- name: Create universal frida-gadget for iOS Simulator
run: |
lipo \
ios-x86_64-simulator/frida-gadget.dylib \
ios-arm64-simulator/frida-gadget.dylib \
-create -output frida-gadget-ios-simulator-universal.dylib
install_name_tool \
-id @executable_path/Frameworks/FridaGadget.dylib \
frida-gadget-ios-simulator-universal.dylib
codesign \
-f -s "$IOS_CERTID" \
frida-gadget-ios-simulator-universal.dylib
- name: Compress universal frida-gadget for iOS Simulator
run: xz -T 0 frida-gadget-ios-simulator-universal.dylib
- name: Upload universal frida-gadget for iOS Simulator
uses: actions/upload-artifact@v4
with:
name: release-asset-frida-gadget-ios-simulator-universal
path: frida-gadget-ios-simulator-universal.dylib.xz
- name: Download frida-gadget for watchOS/arm64
uses: actions/download-artifact@v4
with:
name: frida-gadget-watchos-arm64
path: watchos-arm64/
- name: Download frida-gadget for watchOS/arm64-simulator
uses: actions/download-artifact@v4
with:
name: frida-gadget-watchos-arm64-simulator
path: watchos-arm64-simulator/
- name: Package frida-gadget for watchOS
run: |
for arch in arm64 arm64-simulator; do
cp watchos-$arch/frida-gadget.dylib frida-gadget-watchos-$arch.dylib
install_name_tool \
-id @executable_path/Frameworks/FridaGadget.dylib \
frida-gadget-watchos-$arch.dylib
codesign \
-f -s "$WATCHOS_CERTID" \
frida-gadget-watchos-$arch.dylib
xz -T 0 frida-gadget-watchos-$arch.dylib
done
- name: Upload frida-gadget for watchOS/arm64
uses: actions/upload-artifact@v4
with:
name: release-asset-frida-gadget-watchos-arm64
path: frida-gadget-watchos-arm64.dylib.xz
- name: Upload frida-gadget for watchOS/arm64-simulator
uses: actions/upload-artifact@v4
with:
name: release-asset-frida-gadget-watchos-arm64-simulator
path: frida-gadget-watchos-arm64-simulator.dylib.xz
- name: Download frida-gadget for tvOS/arm64
uses: actions/download-artifact@v4
with:
name: frida-gadget-tvos-arm64
path: tvos-arm64/
- name: Download frida-gadget for tvOS/arm64-simulator
uses: actions/download-artifact@v4
with:
name: frida-gadget-tvos-arm64-simulator
path: tvos-arm64-simulator/
- name: Package frida-gadget for tvOS
run: |
for arch in arm64 arm64-simulator; do
cp tvos-$arch/frida-gadget.dylib frida-gadget-tvos-$arch.dylib
install_name_tool \
-id @executable_path/Frameworks/FridaGadget.dylib \
frida-gadget-tvos-$arch.dylib
codesign \
-f -s "$TVOS_CERTID" \
frida-gadget-tvos-$arch.dylib
xz -T 0 frida-gadget-tvos-$arch.dylib
done
- name: Upload frida-gadget for tvOS/arm64
uses: actions/upload-artifact@v4
with:
name: release-asset-frida-gadget-tvos-arm64
path: frida-gadget-tvos-arm64.dylib.xz
- name: Upload frida-gadget for tvOS/arm64-simulator
uses: actions/upload-artifact@v4
with:
name: release-asset-frida-gadget-tvos-arm64-simulator
path: frida-gadget-tvos-arm64-simulator.dylib.xz
package-windows:
if: startsWith(github.ref, 'refs/tags/')
needs: frida-windows
strategy:
matrix:
arch: [x86, x86_64, arm64]
runs-on: ubuntu-latest
steps:
- name: Check out repo
uses: actions/checkout@v4
- name: Package Gum devkit
uses: ./.github/actions/package-artifact-files-as-tarball
with:
name: frida-gum-devkit-windows-${{ matrix.arch }}
- name: Package GumJS devkit
uses: ./.github/actions/package-artifact-files-as-tarball
with:
name: frida-gumjs-devkit-windows-${{ matrix.arch }}
- name: Package Core devkit
uses: ./.github/actions/package-artifact-files-as-tarball
with:
name: frida-core-devkit-windows-${{ matrix.arch }}
- name: Package frida-server
uses: ./.github/actions/package-artifact-file
with:
name: frida-server-windows-${{ matrix.arch }}
- name: Package frida-portal
uses: ./.github/actions/package-artifact-file
with:
name: frida-portal-windows-${{ matrix.arch }}
- name: Package frida-inject
uses: ./.github/actions/package-artifact-file
with:
name: frida-inject-windows-${{ matrix.arch }}
- name: Package frida-gadget
uses: ./.github/actions/package-artifact-file
with:
name: frida-gadget-windows-${{ matrix.arch }}
- name: Package .NET bindings
if: matrix.arch != 'arm64'
uses: ./.github/actions/package-artifact-file
with:
name: frida-clr-windows-${{ matrix.arch }}
- name: Package QML bindings
if: matrix.arch == 'x86_64'
uses: ./.github/actions/package-artifact-files-as-tarball
with:
name: frida-qml-windows-${{ matrix.arch }}
package-windows-sfx:
if: startsWith(github.ref, 'refs/tags/')
needs: frida-windows
strategy:
matrix:
arch: [x86, x86_64]
runs-on: windows-latest
steps:
- name: Check out repo
uses: actions/checkout@v4
- name: Package Gum devkit
uses: ./.github/actions/package-artifact-files-as-sfx
with:
name: frida-gum-devkit-windows-${{ matrix.arch }}
- name: Package GumJS devkit
uses: ./.github/actions/package-artifact-files-as-sfx
with:
name: frida-gumjs-devkit-windows-${{ matrix.arch }}
- name: Package Core devkit
uses: ./.github/actions/package-artifact-files-as-sfx
with:
name: frida-core-devkit-windows-${{ matrix.arch }}
package-macos:
if: startsWith(github.ref, 'refs/tags/')
needs: frida-macos
strategy:
matrix:
arch: [x86_64, arm64, arm64e]
runs-on: ubuntu-latest
steps:
- name: Check out repo
uses: actions/checkout@v4
- name: Package Gum devkit
uses: ./.github/actions/package-artifact-files-as-tarball
with:
name: frida-gum-devkit-macos-${{ matrix.arch }}
- name: Package gum-graft
if: matrix.arch != 'arm64e'
uses: ./.github/actions/package-artifact-file
with:
name: gum-graft-macos-${{ matrix.arch }}
- name: Package GumJS devkit
uses: ./.github/actions/package-artifact-files-as-tarball
with:
name: frida-gumjs-devkit-macos-${{ matrix.arch }}
- name: Package Core devkit
uses: ./.github/actions/package-artifact-files-as-tarball
with:
name: frida-core-devkit-macos-${{ matrix.arch }}
- name: Package frida-server
uses: ./.github/actions/package-artifact-file
with:
name: frida-server-macos-${{ matrix.arch }}
- name: Package frida-portal
uses: ./.github/actions/package-artifact-file
with:
name: frida-portal-macos-${{ matrix.arch }}
- name: Package frida-inject
uses: ./.github/actions/package-artifact-file
with:
name: frida-inject-macos-${{ matrix.arch }}
- name: Package QML bindings
if: matrix.arch == 'x86_64'
uses: ./.github/actions/package-artifact-files-as-tarball
with:
name: frida-qml-macos-${{ matrix.arch }}
package-linux:
if: startsWith(github.ref, 'refs/tags/')
needs: frida-linux
strategy:
matrix:
arch: [x86, x86_64, x86_64-musl, armhf, armhf-musl, armbe8, arm64, arm64be, arm64-musl, mips, mipsel, mips64, mips64el]
runs-on: ubuntu-latest
steps:
- name: Check out repo
uses: actions/checkout@v4
- name: Package Gum devkit
uses: ./.github/actions/package-artifact-files-as-tarball
with:
name: frida-gum-devkit-linux-${{ matrix.arch }}
- name: Package GumJS devkit
uses: ./.github/actions/package-artifact-files-as-tarball
with:
name: frida-gumjs-devkit-linux-${{ matrix.arch }}
- name: Package Core devkit
uses: ./.github/actions/package-artifact-files-as-tarball
with:
name: frida-core-devkit-linux-${{ matrix.arch }}
- name: Package frida-server
uses: ./.github/actions/package-artifact-file
with:
name: frida-server-linux-${{ matrix.arch }}
- name: Package frida-portal
uses: ./.github/actions/package-artifact-file
with:
name: frida-portal-linux-${{ matrix.arch }}
- name: Package frida-gadget
uses: ./.github/actions/package-artifact-file
with:
name: frida-gadget-linux-${{ matrix.arch }}
- name: Package frida-inject
uses: ./.github/actions/package-artifact-file
with:
name: frida-inject-linux-${{ matrix.arch }}
- name: Package QML bindings
if: matrix.arch == 'x86_64'
uses: ./.github/actions/package-artifact-files-as-tarball
with:
name: frida-qml-linux-${{ matrix.arch }}
package-ios:
if: startsWith(github.ref, 'refs/tags/')
needs: frida-ios
strategy:
matrix:
arch: [arm64, arm64e, x86_64-simulator, arm64-simulator]
runs-on: ubuntu-latest
steps:
- name: Check out repo
uses: actions/checkout@v4
- name: Package Gum devkit
uses: ./.github/actions/package-artifact-files-as-tarball
with:
name: frida-gum-devkit-ios-${{ matrix.arch }}
- name: Package GumJS devkit
uses: ./.github/actions/package-artifact-files-as-tarball
with:
name: frida-gumjs-devkit-ios-${{ matrix.arch }}
- name: Package Core devkit
uses: ./.github/actions/package-artifact-files-as-tarball
with:
name: frida-core-devkit-ios-${{ matrix.arch }}
- name: Package frida-portal
if: ${{ !endsWith(matrix.arch, '-simulator') }}
uses: ./.github/actions/package-artifact-file
with:
name: frida-portal-ios-${{ matrix.arch }}
package-watchos:
if: startsWith(github.ref, 'refs/tags/')
needs: frida-watchos
strategy:
matrix:
arch: [arm64, arm64-simulator]
runs-on: ubuntu-latest
steps:
- name: Check out repo
uses: actions/checkout@v4
- name: Package Gum devkit
uses: ./.github/actions/package-artifact-files-as-tarball
with:
name: frida-gum-devkit-watchos-${{ matrix.arch }}
- name: Package GumJS devkit
uses: ./.github/actions/package-artifact-files-as-tarball
with:
name: frida-gumjs-devkit-watchos-${{ matrix.arch }}
- name: Package Core devkit
uses: ./.github/actions/package-artifact-files-as-tarball
with:
name: frida-core-devkit-watchos-${{ matrix.arch }}
package-tvos:
if: startsWith(github.ref, 'refs/tags/')
needs: frida-tvos
strategy:
matrix:
arch: [arm64, arm64-simulator]
runs-on: ubuntu-latest
steps:
- name: Check out repo
uses: actions/checkout@v4
- name: Package Gum devkit
uses: ./.github/actions/package-artifact-files-as-tarball
with:
name: frida-gum-devkit-tvos-${{ matrix.arch }}
- name: Package GumJS devkit
uses: ./.github/actions/package-artifact-files-as-tarball
with:
name: frida-gumjs-devkit-tvos-${{ matrix.arch }}
- name: Package Core devkit
uses: ./.github/actions/package-artifact-files-as-tarball
with:
name: frida-core-devkit-tvos-${{ matrix.arch }}
package-android:
if: startsWith(github.ref, 'refs/tags/')
needs: frida-android
strategy:
matrix:
arch: [x86, x86_64, arm, arm64]
runs-on: ubuntu-latest
steps:
- name: Check out repo
uses: actions/checkout@v4
- name: Package Gum devkit
uses: ./.github/actions/package-artifact-files-as-tarball
with:
name: frida-gum-devkit-android-${{ matrix.arch }}
- name: Package GumJS devkit
uses: ./.github/actions/package-artifact-files-as-tarball
with:
name: frida-gumjs-devkit-android-${{ matrix.arch }}
- name: Package Core devkit
uses: ./.github/actions/package-artifact-files-as-tarball
with:
name: frida-core-devkit-android-${{ matrix.arch }}
- name: Package frida-server
uses: ./.github/actions/package-artifact-file
with:
name: frida-server-android-${{ matrix.arch }}
- name: Package frida-portal
uses: ./.github/actions/package-artifact-file
with:
name: frida-portal-android-${{ matrix.arch }}
- name: Package frida-gadget
uses: ./.github/actions/package-artifact-file
with:
name: frida-gadget-android-${{ matrix.arch }}
- name: Package frida-inject
uses: ./.github/actions/package-artifact-file
with:
name: frida-inject-android-${{ matrix.arch }}
package-qnx:
if: startsWith(github.ref, 'refs/tags/')
needs: frida-qnx
strategy:
matrix:
arch: [armeabi]
runs-on: ubuntu-latest
steps:
- name: Check out repo
uses: actions/checkout@v4
- name: Package Gum devkit
uses: ./.github/actions/package-artifact-files-as-tarball
with:
name: frida-gum-devkit-qnx-${{ matrix.arch }}
- name: Package GumJS devkit
uses: ./.github/actions/package-artifact-files-as-tarball
with:
name: frida-gumjs-devkit-qnx-${{ matrix.arch }}
- name: Package Core devkit
uses: ./.github/actions/package-artifact-files-as-tarball
with:
name: frida-core-devkit-qnx-${{ matrix.arch }}
- name: Package frida-server
uses: ./.github/actions/package-artifact-file
with:
name: frida-server-qnx-${{ matrix.arch }}
- name: Package frida-portal
uses: ./.github/actions/package-artifact-file
with:
name: frida-portal-qnx-${{ matrix.arch }}
- name: Package frida-gadget
uses: ./.github/actions/package-artifact-file
with:
name: frida-gadget-qnx-${{ matrix.arch }}
- name: Package frida-inject
uses: ./.github/actions/package-artifact-file
with:
name: frida-inject-qnx-${{ matrix.arch }}
frida-windows-intel:
needs: sdk-windows
strategy:
matrix:
include:
- { arch: x86, sys: MINGW32, pkg: 'mingw-w64-i686-gcc' }
- { arch: x86_64, sys: MINGW64, pkg: 'mingw-w64-x86_64-gcc' }
fail-fast: false
runs-on: windows-latest
steps:
- name: Check out repo
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up environment
uses: ./.github/actions/setup-windows-env
with:
aws-access-key-id: ${{ secrets.S3_ACCESS_KEY }}
aws-secret-access-key: ${{ secrets.S3_SECRET_KEY }}
cloudflare-email: ${{ secrets.CF_EMAIL }}
cloudflare-token: ${{ secrets.CF_TOKEN }}
architecture: ${{ matrix.arch == 'x86_64' && 'x64' || matrix.arch }}
- name: Install MinGW toolchain for cgo support
id: msys2
uses: msys2/setup-msys2@v2
with:
msystem: ${{ matrix.sys }}
install: ${{ matrix.pkg }}
- name: Grab frida-core
run: python tools/ensure-submodules.py frida-core
- name: Install Go toolchain
uses: actions/setup-go@v5
with:
go-version-file: ${{ env.FRIDA_COMPILER_MOD }}
cache-dependency-path: ${{ env.FRIDA_COMPILER_MOD }}
- name: Install Qt
if: matrix.arch == 'x86_64'
uses: jurplel/install-qt-action@v4
with:
version: '6.7.0'
cache: true
setup-python: false
- name: Configure
run: >-
.\configure
--prefix=$Env:FRIDA_PREFIX
--host=windows-${{ matrix.arch }}
--enable-gadget
--enable-server
--enable-portal
--enable-inject
--
"-Dfrida_qml=auto"
"-Dfrida-gum:devkits=gum,gumjs"
"-Dfrida-core:compiler_backend=enabled"
"-Dfrida-core:devkits=core"
env:
MSYS2_LOCATION: ${{ steps.msys2.outputs.msys2-location }}
- name: Compile
run: .\make
- name: Install
run: .\make install
- name: Upload components needed for emulation on arm64
if: matrix.arch == 'x86_64'
uses: actions/upload-artifact@v4
with:
name: frida-core-emulation-windows
path: |
build/subprojects/frida-core/src/frida-helper.exe
build/subprojects/frida-core/lib/agent/frida-agent.dll
build/subprojects/frida-core/compat/frida-helper.exe
build/subprojects/frida-core/compat/frida-agent.dll
- name: Upload Gum devkit
uses: actions/upload-artifact@v4
with:
name: frida-gum-devkit-windows-${{ matrix.arch }}
path: ${{ env.FRIDA_PREFIX }}/lib/frida/devkits/gum/
- name: Upload GumJS devkit
uses: actions/upload-artifact@v4
with:
name: frida-gumjs-devkit-windows-${{ matrix.arch }}
path: ${{ env.FRIDA_PREFIX }}/lib/frida/devkits/gumjs/
- name: Upload Core devkit
uses: actions/upload-artifact@v4
with:
name: frida-core-devkit-windows-${{ matrix.arch }}
path: ${{ env.FRIDA_PREFIX }}/lib/frida/devkits/core/
- name: Upload frida-server
uses: actions/upload-artifact@v4
with:
name: frida-server-windows-${{ matrix.arch }}
path: ${{ env.FRIDA_PREFIX }}/bin/frida-server.exe
- name: Upload frida-portal
uses: actions/upload-artifact@v4
with:
name: frida-portal-windows-${{ matrix.arch }}
path: ${{ env.FRIDA_PREFIX }}/bin/frida-portal.exe
- name: Upload frida-inject
uses: actions/upload-artifact@v4
with:
name: frida-inject-windows-${{ matrix.arch }}
path: ${{ env.FRIDA_PREFIX }}/bin/frida-inject.exe
- name: Upload 32-bit frida-gadget
if: matrix.arch != 'x86_64'
uses: actions/upload-artifact@v4
with:
name: frida-gadget-windows-${{ matrix.arch }}
path: ${{ env.FRIDA_PREFIX }}/lib/frida/32/frida-gadget.dll
- name: Upload 64-bit frida-gadget
if: matrix.arch == 'x86_64'
uses: actions/upload-artifact@v4
with:
name: frida-gadget-windows-${{ matrix.arch }}
path: ${{ env.FRIDA_PREFIX }}/lib/frida/64/frida-gadget.dll
- name: Package Python bindings
run: |
$Env:FRIDA_EXTENSION = "$Env:FRIDA_PREFIX\lib\site-packages\frida\_frida.pyd"
cd subprojects\frida-python
pip wheel -w "$Env:FRIDA_PREFIX\wheels" --no-deps .
- name: Upload Python bindings
uses: actions/upload-artifact@v4
with:
name: frida-python-windows-${{ matrix.arch }}
path: ${{ env.FRIDA_PREFIX }}/wheels/*.whl
- name: Build Node.js bindings
if: matrix.arch == 'x86_64'
run: |
$installdir = "$Env:FRIDA_PREFIX\prebuilds"
$Env:FRIDA_DEPS = "$pwd\deps"
$Env:PKG_CONFIG_PATH = "$Env:FRIDA_PREFIX\lib\pkgconfig"
function Run {
param(
[Parameter(Mandatory)]
[string] $FilePath,
[Parameter(ValueFromRemainingArguments = $true)]
[string[]] $Argv
)
$p = Start-Process -FilePath $FilePath -ArgumentList $Argv -NoNewWindow -Wait -PassThru
if ($p.ExitCode -ne 0) {
throw "'$FilePath $($Argv -join ' ')' failed with exit status $($p.ExitCode)"
}
}
Run python .\tools\ensure-submodules.py frida-node
cd subprojects\frida-node
Run npm.cmd version $Env:FRIDA_VERSION
Run .\configure `
--prefix=$Env:FRIDA_PREFIX `
--host=windows-${{ matrix.arch }}
Run .\make prebuild
New-Item -ItemType Directory -Path $installdir
Copy-Item .\build\*.tar.gz -Destination $installdir
- name: Upload Node.js bindings
if: matrix.arch == 'x86_64'
uses: actions/upload-artifact@v4
with:
name: frida-node-windows-${{ matrix.arch }}
path: ${{ env.FRIDA_PREFIX }}/prebuilds/*.tar.gz
- name: Build .NET bindings
run: >-
Remove-Item build -Recurse
&& .\configure
--prefix=$Env:FRIDA_PREFIX
--host=windows-${{ matrix.arch }}-md
--enable-frida-clr
--disable-frida-python
--disable-frida-tools
--
"-Dfrida-core:compiler_backend=disabled"
&& .\make install
- name: Upload .NET bindings
uses: actions/upload-artifact@v4
with:
name: frida-clr-windows-${{ matrix.arch }}
path: ${{ env.FRIDA_PREFIX }}/bin/Frida.dll
- name: Upload QML bindings
if: matrix.arch == 'x86_64'
uses: actions/upload-artifact@v4
with:
name: frida-qml-windows-${{ matrix.arch }}
path: |
${{ env.FRIDA_PREFIX }}/lib/qml/
!*.lib
!*.pdb
frida-windows:
needs: frida-windows-intel
runs-on: windows-11-arm
steps:
- name: Check out repo
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up environment
uses: ./.github/actions/setup-windows-env
with:
aws-access-key-id: ${{ secrets.S3_ACCESS_KEY }}
aws-secret-access-key: ${{ secrets.S3_SECRET_KEY }}
cloudflare-email: ${{ secrets.CF_EMAIL }}
cloudflare-token: ${{ secrets.CF_TOKEN }}
architecture: arm64
- name: Install MinGW toolchain for cgo support
id: msys2
uses: msys2/setup-msys2@v2
with:
msystem: CLANGARM64
install: mingw-w64-clang-aarch64-clang
- name: Grab frida-core
run: python tools/ensure-submodules.py frida-core
- name: Install Go toolchain
uses: actions/setup-go@v5
with:
go-version-file: ${{ env.FRIDA_COMPILER_MOD }}
cache-dependency-path: ${{ env.FRIDA_COMPILER_MOD }}
- name: Download emulation components
uses: actions/download-artifact@v4
with:
name: frida-core-emulation-windows
path: emulation/
- name: Configure
run: |
$helperModern = (Resolve-Path "emulation/src/frida-helper.exe").Path
$agentModern = (Resolve-Path "emulation/lib/agent/frida-agent.dll").Path
$helperLegacy = (Resolve-Path "emulation/compat/frida-helper.exe").Path
$agentLegacy = (Resolve-Path "emulation/compat/frida-agent.dll").Path
.\configure `
--prefix=$Env:FRIDA_PREFIX `
--host=windows-arm64 `
--enable-gadget `
--enable-server `
--enable-portal `
--enable-inject `
-- `
"-Dfrida_qml=auto" `
"-Dfrida-gum:devkits=gum,gumjs" `
"-Dfrida-core:compiler_backend=enabled" `
"-Dfrida-core:devkits=core" `
"-Dfrida-core:helper_emulated_modern=$helperModern" `
"-Dfrida-core:agent_emulated_modern=$agentModern" `
"-Dfrida-core:helper_emulated_legacy=$helperLegacy" `
"-Dfrida-core:agent_emulated_legacy=$agentLegacy"
env:
MSYS2_LOCATION: ${{ steps.msys2.outputs.msys2-location }}
- name: Compile
run: .\make
- name: Install
run: .\make install
- name: Upload Gum devkit
uses: actions/upload-artifact@v4
with:
name: frida-gum-devkit-windows-arm64
path: ${{ env.FRIDA_PREFIX }}/lib/frida/devkits/gum/
- name: Upload GumJS devkit
uses: actions/upload-artifact@v4
with:
name: frida-gumjs-devkit-windows-arm64
path: ${{ env.FRIDA_PREFIX }}/lib/frida/devkits/gumjs/
- name: Upload Core devkit
uses: actions/upload-artifact@v4
with:
name: frida-core-devkit-windows-arm64
path: ${{ env.FRIDA_PREFIX }}/lib/frida/devkits/core/
- name: Upload frida-server
uses: actions/upload-artifact@v4
with:
name: frida-server-windows-arm64
path: ${{ env.FRIDA_PREFIX }}/bin/frida-server.exe
- name: Upload frida-portal
uses: actions/upload-artifact@v4
with:
name: frida-portal-windows-arm64
path: ${{ env.FRIDA_PREFIX }}/bin/frida-portal.exe
- name: Upload frida-inject
uses: actions/upload-artifact@v4
with:
name: frida-inject-windows-arm64
path: ${{ env.FRIDA_PREFIX }}/bin/frida-inject.exe
- name: Upload frida-gadget
uses: actions/upload-artifact@v4
with:
name: frida-gadget-windows-arm64
path: ${{ env.FRIDA_PREFIX }}/lib/frida/64/frida-gadget.dll
- name: Package Python bindings
run: |
$Env:FRIDA_EXTENSION = "$Env:FRIDA_PREFIX\lib\site-packages\frida\_frida.pyd"
cd subprojects\frida-python
pip wheel -w "$Env:FRIDA_PREFIX\wheels" --no-deps .
- name: Upload Python bindings
uses: actions/upload-artifact@v4
with:
name: frida-python-windows-arm64
path: ${{ env.FRIDA_PREFIX }}/wheels/*.whl
- name: Build Node.js bindings
run: |
$installdir = "$Env:FRIDA_PREFIX\prebuilds"
$Env:FRIDA_DEPS = "$pwd\deps"
$Env:PKG_CONFIG_PATH = "$Env:FRIDA_PREFIX\lib\pkgconfig"
function Run {
param(
[Parameter(Mandatory)]
[string] $FilePath,
[Parameter(ValueFromRemainingArguments = $true)]
[string[]] $Argv
)
$p = Start-Process -FilePath $FilePath -ArgumentList $Argv -NoNewWindow -Wait -PassThru
if ($p.ExitCode -ne 0) {
throw "'$FilePath $($Argv -join ' ')' failed with exit status $($p.ExitCode)"
}
}
Run python .\tools\ensure-submodules.py frida-node
cd subprojects\frida-node
Run npm.cmd version $Env:FRIDA_VERSION
Run .\configure `
--prefix=$Env:FRIDA_PREFIX `
--host=windows-arm64
Run .\make prebuild
New-Item -ItemType Directory -Path $installdir
Copy-Item .\build\*.tar.gz -Destination $installdir
- name: Upload Node.js bindings
uses: actions/upload-artifact@v4
with:
name: frida-node-windows-arm64
path: ${{ env.FRIDA_PREFIX }}/prebuilds/*.tar.gz
frida-macos:
needs: sdk-macos
strategy:
matrix:
arch: [x86_64, arm64, arm64e]
fail-fast: false
runs-on: macos-latest
steps:
- name: Check out repo
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up environment
uses: ./.github/actions/setup-macos-env
with:
certificates-p12: ${{ secrets.APPLE_CERTIFICATES_P12 }}
certificates-password: ${{ secrets.APPLE_CERTIFICATES_PASSWORD }}
keychain-password: ${{ secrets.APPLE_KEYCHAIN_PASSWORD }}
aws-access-key-id: ${{ secrets.S3_ACCESS_KEY }}
aws-secret-access-key: ${{ secrets.S3_SECRET_KEY }}
cloudflare-email: ${{ secrets.CF_EMAIL }}
cloudflare-token: ${{ secrets.CF_TOKEN }}
- name: Grab frida-core
run: python tools/ensure-submodules.py frida-core
- name: Install Go toolchain
uses: actions/setup-go@v5
with:
go-version-file: ${{ env.FRIDA_COMPILER_MOD }}
cache-dependency-path: ${{ env.FRIDA_COMPILER_MOD }}
- name: Install Qt
if: matrix.arch != 'arm64e'
uses: jurplel/install-qt-action@v4
with:
version: '6.7.0'
cache: true
setup-python: false
- name: Configure
run: >-
./configure
"--prefix=$FRIDA_PREFIX"
--host=macos-${{ matrix.arch }}
--enable-gadget
--enable-server
--enable-portal
--enable-inject
--enable-frida-python
--
-Dfrida_qml=${{ matrix.arch != 'arm64e' && 'enabled' || 'disabled' }}
-Dfrida-gum:graft_tool=enabled
-Dfrida-gum:devkits=gum,gumjs
-Dfrida-core:compiler_backend=${{ matrix.arch != 'arm64e' && 'enabled' || 'disabled' }}
-Dfrida-core:devkits=core
- name: Compile
run: make
- name: Install
run: make install
- name: Upload Gum devkit
uses: actions/upload-artifact@v4
with:
name: frida-gum-devkit-macos-${{ matrix.arch }}
path: ${{ env.FRIDA_PREFIX }}/lib/frida/devkits/gum/
- name: Upload gum-graft
if: matrix.arch != 'arm64e'
uses: actions/upload-artifact@v4
with:
name: gum-graft-macos-${{ matrix.arch }}
path: ${{ env.FRIDA_PREFIX }}/bin/gum-graft
- name: Upload GumJS devkit
uses: actions/upload-artifact@v4
with:
name: frida-gumjs-devkit-macos-${{ matrix.arch }}
path: ${{ env.FRIDA_PREFIX }}/lib/frida/devkits/gumjs/
- name: Upload Core devkit
uses: actions/upload-artifact@v4
with:
name: frida-core-devkit-macos-${{ matrix.arch }}
path: ${{ env.FRIDA_PREFIX }}/lib/frida/devkits/core/
- name: Upload frida-server
uses: actions/upload-artifact@v4
with:
name: frida-server-macos-${{ matrix.arch }}
path: ${{ env.FRIDA_PREFIX }}/bin/frida-server
- name: Upload frida-portal
uses: actions/upload-artifact@v4
with:
name: frida-portal-macos-${{ matrix.arch }}
path: ${{ env.FRIDA_PREFIX }}/bin/frida-portal
- name: Upload frida-inject
uses: actions/upload-artifact@v4
with:
name: frida-inject-macos-${{ matrix.arch }}
path: ${{ env.FRIDA_PREFIX }}/bin/frida-inject
- name: Upload frida-gadget
if: matrix.arch != 'arm64'
uses: actions/upload-artifact@v4
with:
name: frida-gadget-macos-${{ matrix.arch }}
path: ${{ env.FRIDA_PREFIX }}/lib/frida/frida-gadget.dylib
- name: Package Python bindings
run: |
export FRIDA_EXTENSION=$(find "$FRIDA_PREFIX" -name _frida.abi3.so)
case ${{ matrix.arch }} in
x86_64)
platform=macosx-10.13-x86_64
;;
arm64*)
platform=macosx-11.0-arm64
;;
esac
export _PYTHON_HOST_PLATFORM=$platform
cd subprojects/frida-python
pip wheel -w "$FRIDA_PREFIX/wheels" --no-deps .
- name: Upload Python bindings
uses: actions/upload-artifact@v4
with:
name: frida-python-macos-${{ matrix.arch }}
path: ${{ env.FRIDA_PREFIX }}/wheels/*.whl
- name: Build Node.js bindings
if: matrix.arch != 'arm64e'
run: |
installdir=$FRIDA_PREFIX/prebuilds
export FRIDA_DEPS=$PWD/deps
export PKG_CONFIG_PATH=$FRIDA_PREFIX/lib/pkgconfig
python tools/ensure-submodules.py frida-node
cd subprojects/frida-node
npm version $FRIDA_VERSION
./configure \
"--prefix=$FRIDA_PREFIX" \
--host=macos-${{ matrix.arch }}
make prebuild
mkdir "$installdir"
cp build/*.tar.gz "$installdir"
shell: zsh {0}
- name: Upload Node.js bindings
if: matrix.arch != 'arm64e'
uses: actions/upload-artifact@v4
with:
name: frida-node-macos-${{ matrix.arch }}
path: ${{ env.FRIDA_PREFIX }}/prebuilds/*.tar.gz
- name: Upload QML bindings
if: matrix.arch != 'arm64e'
uses: actions/upload-artifact@v4
with:
name: frida-qml-macos-${{ matrix.arch }}
path: ${{ env.FRIDA_PREFIX }}/lib/qml/
frida-linux:
needs: sdk-linux
strategy:
matrix:
arch: [x86, x86_64, x86_64-musl, armhf, armhf-musl, armbe8, arm64, arm64be, arm64-musl, mips, mipsel, mips64, mips64el]
fail-fast: false
runs-on: ubuntu-latest
container: ghcr.io/frida/x-tools-linux-${{ matrix.arch }}:latest
steps:
- name: Check out repo
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up environment
uses: ./.github/actions/setup-linux-env
with:
aws-access-key-id: ${{ secrets.S3_ACCESS_KEY }}
aws-secret-access-key: ${{ secrets.S3_SECRET_KEY }}
cloudflare-email: ${{ secrets.CF_EMAIL }}
cloudflare-token: ${{ secrets.CF_TOKEN }}
- name: Grab frida-core
run: python tools/ensure-submodules.py frida-core
- name: Install Go toolchain
uses: actions/setup-go@v5
with:
go-version-file: ${{ env.FRIDA_COMPILER_MOD }}
cache-dependency-path: ${{ env.FRIDA_COMPILER_MOD }}
- name: Configure qemu-user
if: ${{ !startsWith(matrix.arch, 'x86') }}
run: echo "FRIDA_QEMU_SYSROOT=/opt/x-tools/$XTOOLS_HOST/$XTOOLS_HOST/sysroot" >> $GITHUB_ENV
- name: Prepare environment for installing Qt
if: matrix.arch == 'x86_64'
run: |
apt-get update
apt-get install -y sudo
echo "PIP_BREAK_SYSTEM_PACKAGES=1" >> $GITHUB_ENV
- name: Install Qt
if: matrix.arch == 'x86_64'
uses: jurplel/install-qt-action@v4
with:
version: '6.7.0'
cache: true
setup-python: false
- name: Configure
run: >-
./configure
"--prefix=$FRIDA_PREFIX"
--host=$XTOOLS_HOST
--enable-gadget
--enable-server
--enable-portal
--enable-inject
--enable-frida-python
--
-Dlibdir=lib
-Dfrida_qml=${{ matrix.arch == 'x86_64' && 'enabled' || 'disabled' }}
-Dfrida-gum:devkits=gum,gumjs
-Dfrida-core:compiler_backend=${{ !(startsWith(matrix.arch, 'mips') || matrix.arch == 'armbe8' || matrix.arch == 'arm64be') && 'enabled' || 'disabled' }}
-Dfrida-core:devkits=core
- name: Compile
run: make
- name: Install
run: make install
- name: Upload Gum devkit
uses: actions/upload-artifact@v4
with:
name: frida-gum-devkit-linux-${{ matrix.arch }}
path: ${{ env.FRIDA_PREFIX }}/lib/frida/devkits/gum/
- name: Upload GumJS devkit
uses: actions/upload-artifact@v4
with:
name: frida-gumjs-devkit-linux-${{ matrix.arch }}
path: ${{ env.FRIDA_PREFIX }}/lib/frida/devkits/gumjs/
- name: Upload Core devkit
uses: actions/upload-artifact@v4
with:
name: frida-core-devkit-linux-${{ matrix.arch }}
path: ${{ env.FRIDA_PREFIX }}/lib/frida/devkits/core/
- name: Upload frida-server
uses: actions/upload-artifact@v4
with:
name: frida-server-linux-${{ matrix.arch }}
path: ${{ env.FRIDA_PREFIX }}/bin/frida-server
- name: Upload frida-portal
uses: actions/upload-artifact@v4
with:
name: frida-portal-linux-${{ matrix.arch }}
path: ${{ env.FRIDA_PREFIX }}/bin/frida-portal
- name: Upload frida-inject
uses: actions/upload-artifact@v4
with:
name: frida-inject-linux-${{ matrix.arch }}
path: ${{ env.FRIDA_PREFIX }}/bin/frida-inject
- name: Upload 32-bit frida-gadget
if: ${{ !contains(matrix.arch, '64') }}
uses: actions/upload-artifact@v4
with:
name: frida-gadget-linux-${{ matrix.arch }}
path: ${{ env.FRIDA_PREFIX }}/lib/frida/32/frida-gadget.so
- name: Upload 64-bit frida-gadget
if: ${{ contains(matrix.arch, '64') }}
uses: actions/upload-artifact@v4
with:
name: frida-gadget-linux-${{ matrix.arch }}
path: ${{ env.FRIDA_PREFIX }}/lib/frida/64/frida-gadget.so
- name: Package Python bindings
run: |
export FRIDA_EXTENSION=$(find "$FRIDA_PREFIX" -name _frida.abi3.so)
case ${{ matrix.arch }} in
*-musl)
py_oses=(musllinux_1_1)
;;
x86*)
py_oses=(manylinux_2_5 manylinux1)
;;
arm*|ppc*|s390x)
py_oses=(manylinux_2_17 manylinux2014)
;;
*)
py_oses=(manylinux_2_5)
;;
esac
frida_arch=$(echo "${{ matrix.arch }}" | cut -f1 -d"-")
case $frida_arch in
x86)
py_arch=i686
;;
armhf)
py_arch=armv7l
;;
arm64)
py_arch=aarch64
;;
*)
py_arch=$frida_arch
;;
esac
cd subprojects/frida-python
export _PYTHON_HOST_PLATFORM=linux-$py_arch
for py_os in "${py_oses[@]}"; do
echo "plat_name = ${py_os}_${py_arch}" >> setup.cfg
pip wheel -w "$FRIDA_PREFIX/wheels" --no-deps .
git checkout setup.cfg
done
shell: bash
- name: Upload Python bindings
uses: actions/upload-artifact@v4
with:
name: frida-python-linux-${{ matrix.arch }}
path: ${{ env.FRIDA_PREFIX }}/wheels/*.whl
- name: Build Node.js bindings
if: ${{ !(startsWith(matrix.arch, 'mips') || endsWith(matrix.arch, '-musl') || matrix.arch == 'armbe8' || matrix.arch == 'arm64be') }}
run: |
installdir=$FRIDA_PREFIX/prebuilds
export FRIDA_DEPS=$PWD/deps
export PKG_CONFIG_PATH=$FRIDA_PREFIX/lib/pkgconfig
python tools/ensure-submodules.py frida-node
cd subprojects/frida-node
npm version $FRIDA_VERSION
./configure \
"--prefix=$FRIDA_PREFIX" \
--host=$XTOOLS_HOST
make prebuild
mkdir "$installdir"
cp build/*.tar.gz "$installdir"
shell: bash
- name: Upload Node.js bindings
if: ${{ !(startsWith(matrix.arch, 'mips') || endsWith(matrix.arch, '-musl') || matrix.arch == 'armbe8' || matrix.arch == 'arm64be') }}
uses: actions/upload-artifact@v4
with:
name: frida-node-linux-${{ matrix.arch }}
path: ${{ env.FRIDA_PREFIX }}/prebuilds/*.tar.gz
- name: Upload QML bindings
if: matrix.arch == 'x86_64'
uses: actions/upload-artifact@v4
with:
name: frida-qml-linux-${{ matrix.arch }}
path: ${{ env.FRIDA_PREFIX }}/lib/qml/
frida-ios:
needs: [sdk-macos, sdk-ios]
strategy:
matrix:
arch: [arm64, arm64e, x86_64-simulator, arm64-simulator]
fail-fast: false
runs-on: macos-latest
env:
XCODE11: /Applications/Xcode_11.7.app
steps:
- name: Check out repo
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up environment
uses: ./.github/actions/setup-macos-env
with:
certificates-p12: ${{ secrets.APPLE_CERTIFICATES_P12 }}
certificates-password: ${{ secrets.APPLE_CERTIFICATES_PASSWORD }}
keychain-password: ${{ secrets.APPLE_KEYCHAIN_PASSWORD }}
aws-access-key-id: ${{ secrets.S3_ACCESS_KEY }}
aws-secret-access-key: ${{ secrets.S3_SECRET_KEY }}
cloudflare-email: ${{ secrets.CF_EMAIL }}
cloudflare-token: ${{ secrets.CF_TOKEN }}
- name: Grab frida-core
run: python tools/ensure-submodules.py frida-core
- name: Install Go toolchain
uses: actions/setup-go@v5
with:
go-version-file: ${{ env.FRIDA_COMPILER_MOD }}
cache-dependency-path: ${{ env.FRIDA_COMPILER_MOD }}
- name: Configure
run: >-
./configure
--prefix=/usr
--host=ios-${{ matrix.arch }}
--enable-portal
--
-Dfrida-gum:devkits=gum,gumjs
-Dfrida-core:compiler_backend=${{ matrix.arch != 'arm64e' && 'enabled' || 'disabled' }}
-Dfrida-core:assets=installed
-Dfrida-core:devkits=core
- name: Compile
run: make
- name: Install
run: DESTDIR="$FRIDA_PREFIX" make install
- name: Upload Gum devkit
uses: actions/upload-artifact@v4
with:
name: frida-gum-devkit-ios-${{ matrix.arch }}
path: ${{ env.FRIDA_PREFIX }}/usr/lib/frida/devkits/gum/
- name: Upload GumJS devkit
uses: actions/upload-artifact@v4
with:
name: frida-gumjs-devkit-ios-${{ matrix.arch }}
path: ${{ env.FRIDA_PREFIX }}/usr/lib/frida/devkits/gumjs/
- name: Upload Core devkit
uses: actions/upload-artifact@v4
with:
name: frida-core-devkit-ios-${{ matrix.arch }}
path: ${{ env.FRIDA_PREFIX }}/usr/lib/frida/devkits/core/
- name: Upload frida-server
if: ${{ matrix.arch != 'arm64' && !endsWith(matrix.arch, '-simulator') }}
uses: actions/upload-artifact@v4
with:
name: frida-server-ios-${{ matrix.arch }}
path: ${{ env.FRIDA_PREFIX }}/usr/bin/frida-server
- name: Upload frida-portal
if: ${{ !endsWith(matrix.arch, '-simulator') }}
uses: actions/upload-artifact@v4
with:
name: frida-portal-ios-${{ matrix.arch }}
path: ${{ env.FRIDA_PREFIX }}/usr/bin/frida-portal
- name: Upload frida-inject
if: ${{ !endsWith(matrix.arch, '-simulator') }}
uses: actions/upload-artifact@v4
with:
name: frida-inject-ios-${{ matrix.arch }}
path: ${{ env.FRIDA_PREFIX }}/usr/bin/frida-inject
- name: Upload frida-helper
if: ${{ matrix.arch != 'arm64' && !endsWith(matrix.arch, '-simulator') }}
uses: actions/upload-artifact@v4
with:
name: frida-helper-ios-${{ matrix.arch }}
path: ${{ env.FRIDA_PREFIX }}/usr/lib/frida/frida-helper
- name: Upload frida-agent
if: ${{ matrix.arch != 'arm64' && !endsWith(matrix.arch, '-simulator') }}
uses: actions/upload-artifact@v4
with:
name: frida-agent-ios-${{ matrix.arch }}
path: ${{ env.FRIDA_PREFIX }}/usr/lib/frida/frida-agent.dylib
- name: Upload frida-gadget
if: matrix.arch != 'arm64'
uses: actions/upload-artifact@v4
with:
name: frida-gadget-ios-${{ matrix.arch }}
path: ${{ env.FRIDA_PREFIX }}/usr/lib/frida/frida-gadget.dylib
frida-watchos:
needs: [sdk-macos, sdk-watchos]
strategy:
matrix:
arch: [arm64, arm64-simulator]
fail-fast: false
runs-on: macos-latest
steps:
- name: Check out repo
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up environment
uses: ./.github/actions/setup-macos-env
with:
certificates-p12: ${{ secrets.APPLE_CERTIFICATES_P12 }}
certificates-password: ${{ secrets.APPLE_CERTIFICATES_PASSWORD }}
keychain-password: ${{ secrets.APPLE_KEYCHAIN_PASSWORD }}
aws-access-key-id: ${{ secrets.S3_ACCESS_KEY }}
aws-secret-access-key: ${{ secrets.S3_SECRET_KEY }}
cloudflare-email: ${{ secrets.CF_EMAIL }}
cloudflare-token: ${{ secrets.CF_TOKEN }}
- name: Configure
run: >-
./configure
"--prefix=$FRIDA_PREFIX"
--host=watchos-${{ matrix.arch }}
--
-Dfrida-gum:devkits=gum,gumjs
-Dfrida-core:devkits=core
- name: Compile
run: make
- name: Install
run: make install
- name: Upload Gum devkit
uses: actions/upload-artifact@v4
with:
name: frida-gum-devkit-watchos-${{ matrix.arch }}
path: ${{ env.FRIDA_PREFIX }}/lib/frida/devkits/gum/
- name: Upload GumJS devkit
uses: actions/upload-artifact@v4
with:
name: frida-gumjs-devkit-watchos-${{ matrix.arch }}
path: ${{ env.FRIDA_PREFIX }}/lib/frida/devkits/gumjs/
- name: Upload Core devkit
uses: actions/upload-artifact@v4
with:
name: frida-core-devkit-watchos-${{ matrix.arch }}
path: ${{ env.FRIDA_PREFIX }}/lib/frida/devkits/core/
- name: Upload frida-gadget
uses: actions/upload-artifact@v4
with:
name: frida-gadget-watchos-${{ matrix.arch }}
path: ${{ env.FRIDA_PREFIX }}/lib/frida/frida-gadget.dylib
frida-tvos:
needs: [sdk-macos, sdk-tvos]
strategy:
matrix:
arch: [arm64, arm64-simulator]
fail-fast: false
runs-on: macos-latest
steps:
- name: Check out repo
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up environment
uses: ./.github/actions/setup-macos-env
with:
certificates-p12: ${{ secrets.APPLE_CERTIFICATES_P12 }}
certificates-password: ${{ secrets.APPLE_CERTIFICATES_PASSWORD }}
keychain-password: ${{ secrets.APPLE_KEYCHAIN_PASSWORD }}
aws-access-key-id: ${{ secrets.S3_ACCESS_KEY }}
aws-secret-access-key: ${{ secrets.S3_SECRET_KEY }}
cloudflare-email: ${{ secrets.CF_EMAIL }}
cloudflare-token: ${{ secrets.CF_TOKEN }}
- name: Grab frida-core
run: python tools/ensure-submodules.py frida-core
- name: Configure
run: >-
./configure
--prefix=/usr
--host=tvos-${{ matrix.arch }}
--enable-portal
--
-Dfrida-gum:devkits=gum,gumjs
-Dfrida-core:assets=installed
-Dfrida-core:devkits=core
- name: Compile
run: make
- name: Install
run: DESTDIR="$FRIDA_PREFIX" make install
- name: Upload Gum devkit
uses: actions/upload-artifact@v4
with:
name: frida-gum-devkit-tvos-${{ matrix.arch }}
path: ${{ env.FRIDA_PREFIX }}/usr/lib/frida/devkits/gum/
- name: Upload GumJS devkit
uses: actions/upload-artifact@v4
with:
name: frida-gumjs-devkit-tvos-${{ matrix.arch }}
path: ${{ env.FRIDA_PREFIX }}/usr/lib/frida/devkits/gumjs/
- name: Upload Core devkit
uses: actions/upload-artifact@v4
with:
name: frida-core-devkit-tvos-${{ matrix.arch }}
path: ${{ env.FRIDA_PREFIX }}/usr/lib/frida/devkits/core/
- name: Upload frida-server
if: ${{ !endsWith(matrix.arch, '-simulator') }}
uses: actions/upload-artifact@v4
with:
name: frida-server-tvos-${{ matrix.arch }}
path: ${{ env.FRIDA_PREFIX }}/usr/bin/frida-server
- name: Upload frida-portal
if: ${{ !endsWith(matrix.arch, '-simulator') }}
uses: actions/upload-artifact@v4
with:
name: frida-portal-tvos-${{ matrix.arch }}
path: ${{ env.FRIDA_PREFIX }}/usr/bin/frida-portal
- name: Upload frida-inject
if: ${{ !endsWith(matrix.arch, '-simulator') }}
uses: actions/upload-artifact@v4
with:
name: frida-inject-tvos-${{ matrix.arch }}
path: ${{ env.FRIDA_PREFIX }}/usr/bin/frida-inject
- name: Upload frida-helper
if: ${{ !endsWith(matrix.arch, '-simulator') }}
uses: actions/upload-artifact@v4
with:
name: frida-helper-tvos-${{ matrix.arch }}
path: ${{ env.FRIDA_PREFIX }}/usr/lib/frida/frida-helper
- name: Upload frida-agent
if: ${{ !endsWith(matrix.arch, '-simulator') }}
uses: actions/upload-artifact@v4
with:
name: frida-agent-tvos-${{ matrix.arch }}
path: ${{ env.FRIDA_PREFIX }}/usr/lib/frida/frida-agent.dylib
- name: Upload frida-gadget
uses: actions/upload-artifact@v4
with:
name: frida-gadget-tvos-${{ matrix.arch }}
path: ${{ env.FRIDA_PREFIX }}/usr/lib/frida/frida-gadget.dylib
frida-android:
needs: [sdk-linux, sdk-android-32, sdk-android-64]
strategy:
matrix:
arch: [x86, x86_64, arm, arm64]
fail-fast: false
runs-on: ubuntu-latest
steps:
- name: Check out repo
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up environment
uses: ./.github/actions/setup-linux-env
with:
aws-access-key-id: ${{ secrets.S3_ACCESS_KEY }}
aws-secret-access-key: ${{ secrets.S3_SECRET_KEY }}
cloudflare-email: ${{ secrets.CF_EMAIL }}
cloudflare-token: ${{ secrets.CF_TOKEN }}
- name: Grab frida-core
run: python tools/ensure-submodules.py frida-core
- name: Install Go toolchain
uses: actions/setup-go@v5
with:
go-version-file: ${{ env.FRIDA_COMPILER_MOD }}
cache-dependency-path: ${{ env.FRIDA_COMPILER_MOD }}
- name: Set up NDK
id: setup-ndk
uses: nttld/setup-ndk@v1
with:
ndk-version: ${{ env.ANDROID_NDK_VERSION }}
add-to-path: false
- name: Add ANDROID_NDK_ROOT to environment
run: echo "ANDROID_NDK_ROOT=${{ steps.setup-ndk.outputs.ndk-path }}" >> $GITHUB_ENV
- name: Configure
run: >-
./configure
"--prefix=$FRIDA_PREFIX"
--host=android-${{ matrix.arch }}
--enable-portal
--
-Dfrida-gum:devkits=gum,gumjs
-Dfrida-core:compiler_backend=enabled
-Dfrida-core:devkits=core
- name: Compile
run: make
- name: Install
run: make install
- name: Upload Gum devkit
uses: actions/upload-artifact@v4
with:
name: frida-gum-devkit-android-${{ matrix.arch }}
path: ${{ env.FRIDA_PREFIX }}/lib/frida/devkits/gum/
- name: Upload GumJS devkit
uses: actions/upload-artifact@v4
with:
name: frida-gumjs-devkit-android-${{ matrix.arch }}
path: ${{ env.FRIDA_PREFIX }}/lib/frida/devkits/gumjs/
- name: Upload Core devkit
uses: actions/upload-artifact@v4
with:
name: frida-core-devkit-android-${{ matrix.arch }}
path: ${{ env.FRIDA_PREFIX }}/lib/frida/devkits/core/
- name: Upload frida-server
uses: actions/upload-artifact@v4
with:
name: frida-server-android-${{ matrix.arch }}
path: ${{ env.FRIDA_PREFIX }}/bin/frida-server
- name: Upload frida-portal
uses: actions/upload-artifact@v4
with:
name: frida-portal-android-${{ matrix.arch }}
path: ${{ env.FRIDA_PREFIX }}/bin/frida-portal
- name: Upload frida-inject
uses: actions/upload-artifact@v4
with:
name: frida-inject-android-${{ matrix.arch }}
path: ${{ env.FRIDA_PREFIX }}/bin/frida-inject
- name: Upload 32-bit frida-gadget
if: ${{ !contains(matrix.arch, '64') }}
uses: actions/upload-artifact@v4
with:
name: frida-gadget-android-${{ matrix.arch }}
path: ${{ env.FRIDA_PREFIX }}/lib/frida/32/frida-gadget.so
- name: Upload 64-bit frida-gadget
if: ${{ contains(matrix.arch, '64') }}
uses: actions/upload-artifact@v4
with:
name: frida-gadget-android-${{ matrix.arch }}
path: ${{ env.FRIDA_PREFIX }}/lib/frida/64/frida-gadget.so
frida-qnx:
runs-on: ubuntu-latest
needs: sdk-linux
container: ghcr.io/frida/qnx-tools:latest
steps:
- name: Check out repo
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up environment
uses: ./.github/actions/setup-linux-env
with:
aws-access-key-id: ${{ secrets.S3_ACCESS_KEY }}
aws-secret-access-key: ${{ secrets.S3_SECRET_KEY }}
cloudflare-email: ${{ secrets.CF_EMAIL }}
cloudflare-token: ${{ secrets.CF_TOKEN }}
- name: Add CFLAGS to environment
run: echo "CFLAGS=\"--sysroot=$QNX_TARGET/armle-v7\"" >> $GITHUB_ENV
- name: Roll SDK
run: releng/deps.py roll sdk arm-unknown-nto-qnx6.5.0eabi
- name: Configure
run: >-
./configure
"--prefix=$FRIDA_PREFIX"
--host=arm-unknown-nto-qnx6.5.0eabi
--enable-portal
--
-Dfrida-gum:devkits=gum,gumjs
-Dfrida-core:devkits=core
- name: Compile
run: make
- name: Install
run: make install
- name: Upload Gum devkit
uses: actions/upload-artifact@v4
with:
name: frida-gum-devkit-qnx-armeabi
path: ${{ env.FRIDA_PREFIX }}/lib/frida/devkits/gum/
- name: Upload GumJS devkit
uses: actions/upload-artifact@v4
with:
name: frida-gumjs-devkit-qnx-armeabi
path: ${{ env.FRIDA_PREFIX }}/lib/frida/devkits/gumjs/
- name: Upload Core devkit
uses: actions/upload-artifact@v4
with:
name: frida-core-devkit-qnx-armeabi
path: ${{ env.FRIDA_PREFIX }}/lib/frida/devkits/core/
- name: Upload frida-server
uses: actions/upload-artifact@v4
with:
name: frida-server-qnx-armeabi
path: ${{ env.FRIDA_PREFIX }}/bin/frida-server
- name: Upload frida-portal
uses: actions/upload-artifact@v4
with:
name: frida-portal-qnx-armeabi
path: ${{ env.FRIDA_PREFIX }}/bin/frida-portal
- name: Upload frida-inject
uses: actions/upload-artifact@v4
with:
name: frida-inject-qnx-armeabi
path: ${{ env.FRIDA_PREFIX }}/bin/frida-inject
- name: Upload frida-gadget
uses: actions/upload-artifact@v4
with:
name: frida-gadget-qnx-armeabi
path: ${{ env.FRIDA_PREFIX }}/lib/frida/32/frida-gadget.so
toolchain-windows:
strategy:
matrix:
arch: [x86, arm64]
fail-fast: false
runs-on: ${{ matrix.arch == 'arm64' && 'windows-11-arm' || 'windows-latest' }}
steps:
- name: Check out repo
uses: actions/checkout@v4
- name: Set up environment
uses: ./.github/actions/setup-windows-env
with:
aws-access-key-id: ${{ secrets.S3_ACCESS_KEY }}
aws-secret-access-key: ${{ secrets.S3_SECRET_KEY }}
cloudflare-email: ${{ secrets.CF_EMAIL }}
cloudflare-token: ${{ secrets.CF_TOKEN }}
- name: Roll toolchain
run: python releng\deps.py roll toolchain windows-${{ matrix.arch }}
sdk-windows:
needs: toolchain-windows
strategy:
matrix:
arch: [x86, x86_64, arm64]
config: [md, mdd, mt, mtd]
fail-fast: false
runs-on: ${{ matrix.arch == 'arm64' && 'windows-11-arm' || 'windows-latest' }}
steps:
- name: Check out repo
uses: actions/checkout@v4
- name: Set up environment
uses: ./.github/actions/setup-windows-env
with:
aws-access-key-id: ${{ secrets.S3_ACCESS_KEY }}
aws-secret-access-key: ${{ secrets.S3_SECRET_KEY }}
cloudflare-email: ${{ secrets.CF_EMAIL }}
cloudflare-token: ${{ secrets.CF_TOKEN }}
- name: Roll SDK
run: python releng\deps.py roll sdk windows-${{ matrix.arch }}-${{ matrix.config }} --activate
toolchain-macos:
strategy:
matrix:
arch: [x86_64, arm64]
fail-fast: false
runs-on: macos-latest
steps:
- name: Check out repo
uses: actions/checkout@v4
- name: Set up environment
uses: ./.github/actions/setup-macos-env
with:
certificates-p12: ${{ secrets.APPLE_CERTIFICATES_P12 }}
certificates-password: ${{ secrets.APPLE_CERTIFICATES_PASSWORD }}
keychain-password: ${{ secrets.APPLE_KEYCHAIN_PASSWORD }}
aws-access-key-id: ${{ secrets.S3_ACCESS_KEY }}
aws-secret-access-key: ${{ secrets.S3_SECRET_KEY }}
cloudflare-email: ${{ secrets.CF_EMAIL }}
cloudflare-token: ${{ secrets.CF_TOKEN }}
- name: Roll toolchain
run: releng/deps.py roll toolchain macos-${{ matrix.arch }}
sdk-macos:
needs: toolchain-macos
strategy:
matrix:
arch: [x86_64, arm64, arm64e]
fail-fast: false
runs-on: macos-latest
steps:
- name: Check out repo
uses: actions/checkout@v4
- name: Set up environment
uses: ./.github/actions/setup-macos-env
with:
certificates-p12: ${{ secrets.APPLE_CERTIFICATES_P12 }}
certificates-password: ${{ secrets.APPLE_CERTIFICATES_PASSWORD }}
keychain-password: ${{ secrets.APPLE_KEYCHAIN_PASSWORD }}
aws-access-key-id: ${{ secrets.S3_ACCESS_KEY }}
aws-secret-access-key: ${{ secrets.S3_SECRET_KEY }}
cloudflare-email: ${{ secrets.CF_EMAIL }}
cloudflare-token: ${{ secrets.CF_TOKEN }}
- name: Roll SDK
run: releng/deps.py roll sdk macos-${{ matrix.arch }} --activate
sdk-ios:
needs: toolchain-macos
strategy:
matrix:
arch: [arm64, arm64e, x86_64-simulator, arm64-simulator]
fail-fast: false
runs-on: macos-latest
steps:
- name: Check out repo
uses: actions/checkout@v4
- name: Set up environment
uses: ./.github/actions/setup-macos-env
with:
certificates-p12: ${{ secrets.APPLE_CERTIFICATES_P12 }}
certificates-password: ${{ secrets.APPLE_CERTIFICATES_PASSWORD }}
aws-access-key-id: ${{ secrets.S3_ACCESS_KEY }}
aws-secret-access-key: ${{ secrets.S3_SECRET_KEY }}
cloudflare-email: ${{ secrets.CF_EMAIL }}
cloudflare-token: ${{ secrets.CF_TOKEN }}
- name: Roll SDK
run: releng/deps.py roll sdk ios-${{ matrix.arch }} --activate
sdk-watchos:
needs: toolchain-macos
strategy:
matrix:
arch: [arm64, arm64-simulator]
fail-fast: false
runs-on: macos-latest
steps:
- name: Check out repo
uses: actions/checkout@v4
- name: Set up environment
uses: ./.github/actions/setup-macos-env
with:
certificates-p12: ${{ secrets.APPLE_CERTIFICATES_P12 }}
certificates-password: ${{ secrets.APPLE_CERTIFICATES_PASSWORD }}
aws-access-key-id: ${{ secrets.S3_ACCESS_KEY }}
aws-secret-access-key: ${{ secrets.S3_SECRET_KEY }}
cloudflare-email: ${{ secrets.CF_EMAIL }}
cloudflare-token: ${{ secrets.CF_TOKEN }}
- name: Roll SDK
run: releng/deps.py roll sdk watchos-${{ matrix.arch }} --activate
sdk-tvos:
needs: toolchain-macos
strategy:
matrix:
arch: [arm64, arm64-simulator]
fail-fast: false
runs-on: macos-latest
steps:
- name: Check out repo
uses: actions/checkout@v4
- name: Set up environment
uses: ./.github/actions/setup-macos-env
with:
certificates-p12: ${{ secrets.APPLE_CERTIFICATES_P12 }}
certificates-password: ${{ secrets.APPLE_CERTIFICATES_PASSWORD }}
aws-access-key-id: ${{ secrets.S3_ACCESS_KEY }}
aws-secret-access-key: ${{ secrets.S3_SECRET_KEY }}
cloudflare-email: ${{ secrets.CF_EMAIL }}
cloudflare-token: ${{ secrets.CF_TOKEN }}
- name: Roll SDK
run: releng/deps.py roll sdk tvos-${{ matrix.arch }} --activate
toolchain-linux:
strategy:
matrix:
arch: [x86, x86_64, x86_64-musl, armhf, armhf-musl, armbe8, arm64, arm64be, arm64beilp32, arm64-musl]
fail-fast: false
runs-on: ubuntu-latest
container: ghcr.io/frida/x-tools-linux-${{ matrix.arch }}:latest
steps:
- name: Check out repo
uses: actions/checkout@v4
- name: Set up environment
uses: ./.github/actions/setup-linux-env
with:
aws-access-key-id: ${{ secrets.S3_ACCESS_KEY }}
aws-secret-access-key: ${{ secrets.S3_SECRET_KEY }}
cloudflare-email: ${{ secrets.CF_EMAIL }}
cloudflare-token: ${{ secrets.CF_TOKEN }}
- name: Roll toolchain
run: releng/deps.py roll toolchain $XTOOLS_HOST
sdk-linux:
needs: toolchain-linux
strategy:
matrix:
arch: [x86, x86_64, x86_64-musl, armhf, armhf-musl, armbe8, arm64, arm64be, arm64beilp32, arm64-musl, mips, mipsel, mips64, mips64el]
fail-fast: false
runs-on: ubuntu-latest
container: ghcr.io/frida/x-tools-linux-${{ matrix.arch }}:latest
steps:
- name: Check out repo
uses: actions/checkout@v4
- name: Set up environment
uses: ./.github/actions/setup-linux-env
with:
aws-access-key-id: ${{ secrets.S3_ACCESS_KEY }}
aws-secret-access-key: ${{ secrets.S3_SECRET_KEY }}
cloudflare-email: ${{ secrets.CF_EMAIL }}
cloudflare-token: ${{ secrets.CF_TOKEN }}
- name: Set FRIDA_CAN_RUN_HOST_BINARIES
if: ${{ matrix.arch == 'x86' }}
run: echo "FRIDA_CAN_RUN_HOST_BINARIES=yes" >> $GITHUB_ENV
- name: Configure qemu-user
if: ${{ !startsWith(matrix.arch, 'x86') }}
run: echo "FRIDA_QEMU_SYSROOT=/opt/x-tools/$XTOOLS_HOST/$XTOOLS_HOST/sysroot" >> $GITHUB_ENV
- name: Roll SDK
run: releng/deps.py roll sdk $XTOOLS_HOST --activate
sdk-android-32:
needs: toolchain-linux
strategy:
matrix:
arch: [x86, arm]
fail-fast: false
runs-on: ubuntu-latest
container: ghcr.io/frida/x-tools-linux-x86:latest
steps:
- name: Check out repo
uses: actions/checkout@v4
- name: Set up environment
uses: ./.github/actions/setup-linux-env
with:
aws-access-key-id: ${{ secrets.S3_ACCESS_KEY }}
aws-secret-access-key: ${{ secrets.S3_SECRET_KEY }}
cloudflare-email: ${{ secrets.CF_EMAIL }}
cloudflare-token: ${{ secrets.CF_TOKEN }}
- name: Set up NDK
id: setup-ndk
uses: nttld/setup-ndk@v1
with:
ndk-version: ${{ env.ANDROID_NDK_VERSION }}
add-to-path: false
- name: Roll SDK
run: releng/deps.py roll sdk android-${{ matrix.arch }} --build=$XTOOLS_HOST --activate
env:
ANDROID_NDK_ROOT: ${{ steps.setup-ndk.outputs.ndk-path }}
sdk-android-64:
needs: toolchain-linux
strategy:
matrix:
arch: [x86_64, arm64]
fail-fast: false
runs-on: ubuntu-latest
container: ghcr.io/frida/x-tools-linux-x86_64:latest
steps:
- name: Check out repo
uses: actions/checkout@v4
- name: Set up environment
uses: ./.github/actions/setup-linux-env
with:
aws-access-key-id: ${{ secrets.S3_ACCESS_KEY }}
aws-secret-access-key: ${{ secrets.S3_SECRET_KEY }}
cloudflare-email: ${{ secrets.CF_EMAIL }}
cloudflare-token: ${{ secrets.CF_TOKEN }}
- name: Set up NDK
id: setup-ndk
uses: nttld/setup-ndk@v1
with:
ndk-version: ${{ env.ANDROID_NDK_VERSION }}
add-to-path: false
- name: Roll SDK
run: releng/deps.py roll sdk android-${{ matrix.arch }} --build=$XTOOLS_HOST --activate
env:
ANDROID_NDK_ROOT: ${{ steps.setup-ndk.outputs.ndk-path }}
================================================
FILE: .gitignore
================================================
/build/
/deps/
/releng/__pycache__/
/releng/modules/frida-gadget-ios/*.dylib
/releng/modules/frida-gadget-ios/node_modules
/subprojects/*
================================================
FILE: .gitmodules
================================================
[submodule "frida-gum"]
path = subprojects/frida-gum
url = https://github.com/frida/frida-gum.git
[submodule "frida-core"]
path = subprojects/frida-core
url = https://github.com/frida/frida-core.git
[submodule "frida-python"]
path = subprojects/frida-python
url = https://github.com/frida/frida-python.git
[submodule "frida-node"]
path = subprojects/frida-node
url = https://github.com/frida/frida-node.git
[submodule "frida-swift"]
path = subprojects/frida-swift
url = https://github.com/frida/frida-swift.git
[submodule "frida-clr"]
path = subprojects/frida-clr
url = https://github.com/frida/frida-clr.git
[submodule "frida-qml"]
path = subprojects/frida-qml
url = https://github.com/frida/frida-qml.git
[submodule "frida-tools"]
path = subprojects/frida-tools
url = https://github.com/frida/frida-tools.git
[submodule "frida-go"]
path = subprojects/frida-go
url = https://github.com/frida/frida-go
[submodule "releng"]
path = releng
url = https://github.com/frida/releng.git
================================================
FILE: BSDmakefile
================================================
all: .DEFAULT
.DEFAULT:
@gmake ${.MAKEFLAGS} ${.TARGETS}
.PHONY: all
================================================
FILE: CONTRIBUTING.md
================================================
# Intro
Frida is composed of many sub-projects and its code spans across many
different languages, such as C, C++, Vala, JavaScript, TypeScript,
Python, assembly, etc., and the coding conventions may vary across any
combination of project/language.
The rules presented here are not there because of @oleavr's OCD: they're
about keeping the codebase readable and maintainable, and give the code
a consistent structure as it grows. That helps every contributor to
easily orientate in it.
Moreover, reading this doc helps save everyone's time when it comes to
get a PR reviewed.
# General rules
Rules in this section apply in all cases, regardless of the programming
language or the project owning the code. Examples are in
pseudo-javascript for brevity (with some exceptions).
## Comments vs. naming
### Rule
Only use comments for communicating what cannot be conveyed by the code
itself through meaningful variable and function names, and splitting out
logic into separate functions.
**NOTE**: names should be long enough to be meaningful, but not
ridiculously long.
#### Wrong
```c
// Init the dyld start address with current program counter
a = (instance->cpu_type == GUM_CPU_ARM64) ? __darwin_arm_thread_state64_get_pc (state.ts_64) : state.ts_32.__pc;
// dyld header is initially zero
b = 0;
// set the search granularity to 4k
c = 4096;
for (dyld_chunk = (a & (c - 1)) == 0 ? (a - c) : (a & ~(c - 1));
b == 0;
dyld_chunk -= c)
{
...
}
```
#### Correct
```c
dyld_start = (instance->cpu_type == GUM_CPU_ARM64) ? __darwin_arm_thread_state64_get_pc (state.ts_64) : state.ts_32.__pc;
dyld_header = 0;
dyld_granularity = 4096;
for (dyld_chunk = (dyld_start & (dyld_granularity - 1)) == 0 ? (dyld_start - dyld_granularity) : (dyld_start & ~(dyld_granularity - 1));
dyld_header == 0;
dyld_chunk -= dyld_granularity)
{
...
}
```
#### Example
Here's a **really useful** comment.
```vala
/* Compiled from helpers/upload-listener.c */
private const uint8[] UPLOAD_LISTENER_CODE = {
0xff, 0x43, 0x01, 0xd1, 0xf6, 0x57, 0x02, 0xa9, 0xf4, 0x4f, 0x03, 0xa9, 0xfd, 0x7b, 0x04, 0xa9, 0xfd, 0x03, 0x01,
0x91, 0xf3, 0x03, 0x01, 0xaa, 0xe0, 0x1f, 0x00, 0xb9, 0x28, 0x00, 0x40, 0xf9, 0xe0, 0x03, 0x1f, 0x32, 0xe1, 0x03,
0x00, 0x32, 0x02, 0x00, 0x80, 0x52, 0x00, 0x01, 0x3f, 0xd6, 0x1f, 0x04, 0x00, 0x31, 0x80, 0x05, 0x00, 0x54, 0xf4,
...
0xb2, 0x04, 0x00, 0x00, 0x14, 0xf5, 0x03, 0x46, 0xb2, 0x02, 0x00, 0x00, 0x14, 0x15, 0xa0, 0xe0, 0xd2, 0x68, 0x2a,
0x40, 0xf9, 0xe0, 0x03, 0x14, 0xaa, 0x00, 0x01, 0x3f, 0xd6, 0xe0, 0x03, 0x15, 0xaa, 0xfd, 0x7b, 0x44, 0xa9, 0xf4,
0x4f, 0x43, 0xa9, 0xf6, 0x57, 0x42, 0xa9, 0xff, 0x43, 0x01, 0x91, 0xc0, 0x03, 0x5f, 0xd6
};
```
### Rule
The variable name shouldn't be more verbose than its type name.
#### Wrong
```vala
private void schedule_idle (owned ScheduledFunc function) { ... }
```
#### Correct
```vala
private void schedule_idle (owned ScheduledFunc func) { ... }
```
## Order of functions in a file
### Rule
Higher level functions must be placed before lower level functions, and
Should be sorted chronologically.
In case of C code the corresponding forward declarations must follow
the same order.
#### Wrong
```javascript
function getInfoAboutA() {
/* complex code */
return allInfoAboutA;
}
function getInfoAboutB() {
/* more complex code */
return allInfoAboutB;
}
function getInfo() {
return {
infoAboutA: getInfoAboutA(),
infoAboutB: getInfoAboutB()
};
}
```
#### Correct
```javascript
function getInfo() {
return {
infoAboutA: getInfoAboutA(),
infoAboutB: getInfoAboutB()
};
}
function getInfoAboutA() {
/* complex code */
return allInfoAboutA;
}
function getInfoAboutB() {
/* more complex code */
return allInfoAboutB;
}
```
### Rule
For exported functions / public methods:
functions that work in all cases come before functions which work
only under certain conditions.
#### Wrong
```javascript
function getPrivilegedInfo() {
if (!amIRoot()) {
throw new Error("You must be root");
}
...
return privilegedInfo;
}
function getHarmlessInfo() {
return harmlessInfo;
}
```
#### Correct
```javascript
function getHarmlessInfo() {
return harmlessInfo;
}
function getPrivilegedInfo() {
if (!amIRoot()) {
throw new Error("You must be root");
}
...
return privilegedInfo;
}
```
## Don't repeat yourself
### Rule
Instead of repeating chunks of code, extract it to a function and
call it multiple times.
#### Example
There's no fixed recipe to define what a "repeated chunk of code is", it
really depends on the context. For example, even a couple of lines may
be worth refactoring into a function, especially if they require some
fairly complex error-handling logic.
```vala
private async LLDB.Client start_lldb_service (Fruity.LockdownClient lockdown, Cancellable? cancellable)
throws Error, LLDB.Error, IOError {
try {
var lldb_stream = yield lockdown.start_service (DEBUGSERVER_SERVICE_NAME + "?tls=handshake-only", cancellable);
return yield LLDB.Client.open (lldb_stream, cancellable);
} catch (Fruity.LockdownError e) {
if (e is Fruity.LockdownError.INVALID_SERVICE) {
throw new Error.NOT_SUPPORTED ("This feature requires an iOS Developer Disk Image to be mounted; " +
"run Xcode briefly or use ideviceimagemounter to mount one manually");
}
throw new Error.NOT_SUPPORTED ("%s", e.message);
}
}
```
## Indentation
### Rule
Minimize nesting when possible.
#### Wrong
```javascript
function doSomethingMaybe() {
if (condition) {
/* do something here */
}
}
```
#### Correct
```javascript
function doSomethingMaybe() {
if (!condition) {
return;
}
/* do something here */
}
```
### Rule
Hanging indent – when breaking a long line of code – should be *twice*
the regular indent, regardless of the indentation rules.
#### Wrong
```c
recursive_init_address = gum_darwin_module_resolve_symbol_address (dyld,
"__ZN11ImageLoader23recursiveInitializationERKNS_11LinkContextEjRNS_21InitializerTimingListERNS_15UninitedUpwardsE");
```
#### Correct
```c
recursive_init_address = gum_darwin_module_resolve_symbol_address (dyld,
"__ZN11ImageLoader23recursiveInitializationERKNS_11LinkContextEjRNS_21InitializerTimingListERNS_15UninitedUpwardsE");
```
## Spaces
### Rule
No trailing spaces.
## Indexed loops
### Rule
Prefer strict inequality for loop conditions.
#### Wrong
```javascript
for (let i = 0; i < len; i++) {
...
}
```
#### Correct
```javascript
for (let i = 0; i !== len; i++) {
...
}
```
## Comparisons
### Rule
Use explicit comparisons, even with `0`, `NULL`, and `undefined`,
instead of relying on language-specific coercion. Only use implicit
for booleans.
#### Wrong
```javascript
if (value) {
...
}
```
#### Correct
```javascript
if (value !== 0) {
...
}
```
## Argument validation
### Rule
Internal APIs should assume the API contract is not violated – i.e.
that the function is passed everything it needs – and omit any check
on the arguments.
#### Wrong
```javascript
function doSomethingInternallyWithDevice(device) {
if (device === null || device === undefined) {
throw new Error('Pass a valid device');
}
/* do the thing with device */
}
```
#### Correct
```javascript
function doSomethingInternallyWithDevice(device) {
/* do the thing with device */
}
```
# Rules for C
This set of rules applies to C code, regardless of the project owning it.
## File structure
### Rule
Every C file must follow the following structure, in this order:
* Own header includes
* Internal header includes
* System/dependency includes
* typedefs
* enum and struct definitions
* Forward declarations / prototypes
* Global state / static variables
* Implementation code
Each such group should be separated by a blank line, and includes should
be listed in alphabetical order.
## Spaces
### Rule
In function calls and function definitions, put a space before
the parenthesis.
#### Wrong
```c
ret = thread_create(task, &instance->thread);
```
#### Correct
```c
ret = thread_create (task, &instance->thread);
```
### Rule
When declaring pointers, put a space before and after `*`.
#### Wrong
```c
GumModuleDetails *details;
```
#### Correct
```c
GumModuleDetails * details;
```
### Rule
When casting pointers, put a space before `*`.
#### Wrong
```c
init_func = (guint32*) gum_darwin_read (task, addr, sizeof (guint32), NULL);
```
#### Correct
```c
init_func = (guint32 *) gum_darwin_read (task, addr, sizeof (guint32), NULL);
```
### Rule
Space before and after binary operators, no spaces around unary
operators.
#### Wrong
```c
for (port_index=0; port_index!=previous_ports->count; port_index ++)
{
...
}
* count ++;
```
#### Correct
```c
for (port_index = 0; port_index != previous_ports->count; port_index++)
{
...
}
*count++;
```
### Rule
Never use more than one space (when not used for indentation).
#### Wrong
```c
gint i;
```
#### Correct
```c
gint i;
```
## Blank Lines
### Rule
It's encouraged to leave **one** blank line when needing to separate
semantically distinct blocks of code or improve readability
(some examples later). Just don't abuse that and never leave more
than one blank line. (Except for Python code, which should follow the
recommendations in PEP-8.)
#### Wrong
```
static void
function_one (void)
{
...
}
static void
function_two (void)
{
...
}
```
#### Correct
```
static void
function_one (void)
{
...
}
static void
function_two (void)
{
...
}
```
## Function definitions
### Rule
Function names must be lowercase, e.g. `find_libsystem`
**NOTE**: this is true also for arguments, variable names, and
labels.
#### Wrong
```c
static gboolean
frida_find_libSystem (const GumModuleDetails * details, gpointer user_data)
{
...
}
```
#### Correct
```c
static gboolean
frida_find_libsystem (const GumModuleDetails * details, gpointer user_data)
{
...
}
```
### Rule
Functions which take no arguments should be declared `(void)`, as `()`
means that no information about the number or types of the arguments
is supplied. (Unlike C++, where `()` means "no arguments".)
#### Wrong
```c
static gboolean
function_without_args ()
{
...
}
```
#### Correct
```c
static gboolean
function_without_args (void)
{
...
}
```
## Local variables
### Rule
Local variables are all declared at the beginning of the block
they're used in, a blank line is usually left right after.
#### Wrong
```c
if (is_uninitialized_clone)
{
mach_port_mod_refs (self_task, task, MACH_PORT_RIGHT_SEND, 1);
instance->task = task;
mach_vm_address_t data_address = instance->remote_agent_context;
...
}
```
#### Correct
```c
if (is_uninitialized_clone)
{
mach_vm_address_t data_address;
mach_port_mod_refs (self_task, task, MACH_PORT_RIGHT_SEND, 1);
instance->task = task;
data_address = instance->remote_agent_context;
...
}
```
### Rule
Local variables are listed in chronological order of usage.
**Exception 1**: the variable which holds the return value of a
function should be the first in the list, preceded by any variable
holding argument values.
**Exception 2**: related variables of the same type can be grouped in
one line, in relative chronological order.
#### Example 1
Variables in chronological order of usage.
```c
case FRIDA_BREAKPOINT_CLEANUP:
{
task_t self_task;
gsize page_size;
FridaExceptionPortSet * previous_ports;
mach_msg_type_number_t port_index;
guint i;
self_task = mach_task_self ();
page_size = getpagesize ();
previous_ports = &self->previous_ports;
for (port_index = 0; port_index != previous_ports->count; port_index++)
{
...
}
...
for (i = 0; i != FRIDA_MAX_BREAKPOINTS; i++)
frida_spawn_instance_unset_nth_breakpoint (self, i);
}
```
#### Example 2
The variable holding the return value comes first.
```c
static csh
frida_create_capstone (GumCpuType cpu_type, GumAddress start)
{
csh capstone;
cs_err err;
switch (cpu_type)
{
case GUM_CPU_ARM64:
err = cs_open (CS_ARCH_ARM64, CS_MODE_LITTLE_ENDIAN, &capstone);
break;
...
}
g_assert (err == CS_ERR_OK);
return capstone;
}
```
#### Example 3
Argument helper variable before return value.
```c
guint
_frida_darwin_helper_backend_demonitor_and_clone_injectee_state (FridaDarwinHelperBackend * self, void * raw_instance)
{
FridaInjectInstance * instance = raw_instance;
FridaInjectInstance * clone;
...
return clone->id;
}
```
### Rule
Avoid redundant initialization.
#### Wrong
```c
cs_insn * insn = NULL;
...
insn = cs_malloc (capstone);
```
#### Correct
```c
cs_insn * insn;
...
insn = cs_malloc (capstone);
```
## Indentation and {}
### Rule
In function definitions, the return type goes on its own line (not
for the prototype).
#### Wrong
```c
static gboolean frida_find_libsystem (const GumModuleDetails * details, gpointer user_data)
{
...
}
```
#### Correct
```c
static gboolean
frida_find_libsystem (const GumModuleDetails * details, gpointer user_data)
{
...
}
```
### Rule
Curly braces go on a new line, in all cases.
#### Wrong
```c
if (cached_address_for_breakpoint[instance->cpu_type] == 0) {
...
}
```
#### Correct
```c
if (cached_address_for_breakpoint[instance->cpu_type] == 0)
{
...
}
```
### Rule
Code in a block is indented by 2 spaces.
#### Wrong
```c
if (magic == NULL)
goto handle_probe_dyld_error;
```
#### Correct
```c
if (magic == NULL)
goto handle_probe_dyld_error;
```
### Rule
Simple `if` statements in which the code is only one line should not
have curly braces.
#### Wrong
```c
if (magic == NULL)
{
goto handle_probe_dyld_error;
}
```
#### Correct
```c
if (magic == NULL)
goto handle_probe_dyld_error;
```
### Rule
If the `if` statement has curly braces, then also the `else` should
have it (and vice-versa).
#### Wrong
```c
if (error == nil)
[service cleanupClientPort:client_port];
else
{
g_clear_object (&pipes);
frida_error = g_error_new (
FRIDA_ERROR,
FRIDA_ERROR_NOT_SUPPORTED,
"Unable to launch iOS app: %s",
[[error localizedDescription] UTF8String]);
}
```
#### Correct
```c
if (error == nil)
{
[service cleanupClientPort:client_port];
}
else
{
g_clear_object (&pipes);
frida_error = g_error_new (
FRIDA_ERROR,
FRIDA_ERROR_NOT_SUPPORTED,
"Unable to launch iOS app: %s",
[[error localizedDescription] UTF8String]);
}
```
### Rule
When an `if` statement has single-statement bodies but any of them
exceed the maximum line length, curly braces must be used.
#### Wrong
```c
if (_frida_get_springboard_api ()->fbs != NULL)
frida_darwin_helper_backend_launch_using_fbs (identifier_value, url_value, options, aux_options, on_complete,
on_complete_target);
else
frida_darwin_helper_backend_launch_using_sbs (identifier_value, url_value, options, aux_options, on_complete,
on_complete_target);
```
#### Correct
```c
if (_frida_get_springboard_api ()->fbs != NULL)
{
frida_darwin_helper_backend_launch_using_fbs (identifier_value, url_value, options, aux_options, on_complete,
on_complete_target);
}
else
{
frida_darwin_helper_backend_launch_using_sbs (identifier_value, url_value, options, aux_options, on_complete,
on_complete_target);
}
```
### Rule
If the condition of an `if` statement has been broken up into multiple
lines, then use braces regardless.
#### Wrong
```c
if ((ctx->sink_mask & GUM_BLOCK) != 0 &&
gum_x86_relocator_eob (rl) &&
insn.ci->id != X86_INS_CALL)
gum_exec_block_write_block_event_code (block, &gc, GUM_CODE_INTERRUPTIBLE);
```
#### Correct
```c
if ((ctx->sink_mask & GUM_BLOCK) != 0 &&
gum_x86_relocator_eob (rl) &&
insn.ci->id != X86_INS_CALL)
{
gum_exec_block_write_block_event_code (block, &gc, GUM_CODE_INTERRUPTIBLE);
}
```
## Switch statements
### Rule
If a case needs curly braces, the `break` goes inside, usually
preceded by a blank line.
#### Wrong
```c
switch (cpu_type)
{
case GUM_CPU_ARM:
{
/* case implementation*/
}
break;
...
}
```
#### Correct
```c
switch (cpu_type)
{
case GUM_CPU_ARM:
{
/* case implementation*/
break;
}
...
}
```
# Rules for JavaScript
This set of rules apply to JavaScript code, regardless of the project owning it.
## String constants
### Rule
Don't use double quotes.
#### Wrong
```javascript
throw new Error("Invalid argument");
```
#### Correct
```javascript
throw new Error('Invalid argument');
```
## Indentation
### Rule
Indent with 2 spaces.
### Rule
Curly braces go on the same line of the statement.
#### Wrong
```javascript
if (condition)
{
...
}
else
{
...
}
```
#### Correct
```javascript
if (condition) {
...
} else {
...
}
```
## Semicolons
### Rule
Treat semicolons as mandatory.
#### Wrong
```javascript
console.log('hello world')
```
#### Correct
```javascript
console.log('hello world');
```
## Comparisons
### Rule
Use strict comparisons.
#### Wrong
```javascript
if (methodName == '- init') {
...
}
```
#### Correct
```javascript
if (methodName === '- init') {
...
}
```
### Rule
Put parenthesis around the ternary comparison condition unless it's
simply referencing a boolean variable.
#### Wrong
```javascript
m = res[0] === '' ? '*' : res[0];
```
#### Correct
```javascript
m = (res[0] === '') ? '*' : res[0];
```
## Spaces
### Rule
Unless the specific project follows the semistandard conventions, put no
spaces between function name and argument list.
#### Wrong
```javascript
function parseExportsFunctionPattern (pattern) {
var res = pattern.split ('!');
...
}
```
#### Correct
```javascript
function parseExportsFunctionPattern(pattern) {
var res = pattern.split('!');
...
}
```
## Object properties
### Rule
Reference object properties without quotes when possible.
#### Wrong
```javascript
enumerateMatches('exports:' + obj['module'] + '!' + obj['function']);
```
#### Correct
```javascript
enumerateMatches('exports:' + obj.module + '!' + obj.function);
```
## Internal agents
### Rule
Stick to `ES5` syntax, so it can be consumed by the Duktape runtime
without having to first `frida-compile` the code.
### Rule
In `rpc.exports`, `dispose()` comes first, or right after `init()`.
# Rules for TypeScript
This set of rules apply to TypeScript code, regardless of the project
owning it. Rules for JavaScript also apply to TypeScript, if not
explicitly overridden.
## Indentation
### Rule
Indent with 4 spaces.
## Spaces
### Rule
Never put spaces between function name and argument list, neither in
calls nor definitions.
## String constants
### Rule
Don't use single quotes.
## Enums
### Rule
The TypeScript convention is pascal-case for enum values,
e.g. `FooBarBaz`.
#### Wrong
```typescript
enum PlistType {
NONE,
BINARY,
XML
}
```
#### Correct
```typescript
enum PlistType {
None,
Binary,
Xml
}
```
### Rule
Usage of `const enum` is discouraged portability-wise.
#### Wrong
```typescript
export const enum GrassColor {
Yellow = "YELLOW",
LightGreen = "LIGHTGREEN",
Green = "GREEN",
DarkGreen = "DARKGREEN"
}
```
#### Correct
```typescript
export type GrassColor =
| "YELLOW"
| "LIGHTGREEN"
| "GREEN"
| "DARKGREEN"
;
```
## Constants
### Rule
Constants should be uppercase, e.g. `FOO_BAR_BAZ`.
#### Wrong
```typescript
const lockdownPort = 62078;
```
#### Correct
```typescript
const LOCKDOWN_PORT = 62078;
```
## Types
### Rule
Use `interface` when possible.
#### Wrong
```typescript
export type StringDict = {
[name: string]: string;
}
```
#### Correct
```typescript
export interface StringDict {
[name: string]: string;
}
```
# Rules for Vala
This set of rules apply to Vala code, regardless of the project
owning it.
## Order of class properties
### Rule
* Public properties should precede private ones.
* Higher level properties should precede lower level ones.
## Indentation, spaces and {}
### Rule
Indent only with tabs.
### Rule
Rules for spaces are the same as C.
### Rule
Curly braces go on the same line of the statement. Follow the same
rules as C for whether to omit them or not.
#### Wrong
```vala
if (condition)
{
...
}
else
{
...
}
```
#### Correct
```vala
if (condition) {
...
} else {
...
}
```
## Usage of `var` type
### Rule
Declare variables as `var`, especially when the type is obvious.
#### Wrong
```vala
Json.Node parameters = new Json.Node (Json.NodeType.OBJECT);
```
#### Correct
```vala
var parameters = new Json.Node (Json.NodeType.OBJECT);
```
# Generic rules for Python
This set of rules apply to all python code, regardless of the project
it belongs to.
## Formatting
### Rule
Python formatting should follow the
[PEP-8](https://www.python.org/dev/peps/pep-0008/) guidelines.
## String quotes
### Rule
Use double quotes for regular strings, single quotes for enum-like
values.
#### Wrong
```python
if os.environ.get("TERM", '') == "dumb":
```
#### Correct
```python
if os.environ.get("TERM", "") == 'dumb':
```
## Imports
### Rule
Imports go in alphabetical order.
## Comments
### Rule
Comments should use a capital letter at the start of each sentence,
and each should end in a full stop.
# Generic rules in frida-gum
This set of rules apply to all code in frida-gum, regardless of the
language.
## Max line length
### Rule
Lines should not exceed 80 characters.
# Rules for C code in frida-gum
## Function definitions
### Rule
When defining a function implementation each argument must go on
its own line, vertically aligned (not for the prototype).
#### Wrong
```c
static void
gum_exec_block_write_block_event_code (GumExecBlock * block, GumGeneratorContext * gc,
GumCodeContext cc)
{
...
}
```
#### Correct
```c
static void
gum_exec_block_write_block_event_code (GumExecBlock * block,
GumGeneratorContext * gc,
GumCodeContext cc)
{
...
}
```
# Generic rules in frida-core
This set of rules apply to all code in frida-core, regardless of the
language.
## Max line length
### Rule
Lines should not exceed 140 characters.
# Rules for C code in frida-core
This set of rules apply to C code belonging to frida-core.
## Function definitions
### Rule
Function names should be “namespaced” by having a `frida_` prefix,
even if static.
#### Wrong
```c
static gboolean
find_libsystem (const GumModuleDetails * details, gpointer user_data)
{
...
}
```
#### Correct
```c
static gboolean
frida_find_libsystem (const GumModuleDetails * details, gpointer user_data)
{
...
}
```
================================================
FILE: COPYING
================================================
wxWindows Library Licence, Version 3.1
======================================
Copyright (c) 1998-2005 Julian Smart, Robert Roebling et al
Everyone is permitted to copy and distribute verbatim copies
of this licence document, but changing it is not allowed.
WXWINDOWS LIBRARY LICENCE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
This library is free software; you can redistribute it and/or modify it
under the terms of the GNU Library General Public Licence as published by
the Free Software Foundation; either version 2 of the Licence, or (at your
option) any later version.
This library is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
Licence for more details.
You should have received a copy of the GNU Library General Public Licence
along with this software, usually in a file named COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
Floor, Boston, MA 02110-1301 USA.
EXCEPTION NOTICE
1. As a special exception, the copyright holders of this library give
permission for additional uses of the text contained in this release of the
library as licenced under the wxWindows Library Licence, applying either
version 3.1 of the Licence, or (at your option) any later version of the
Licence as published by the copyright holders of version 3.1 of the Licence
document.
2. The exception is that you may use, copy, link, modify and distribute
under your own terms, binary object code versions of works based on the
Library.
3. If you copy code from files distributed under the terms of the GNU
General Public Licence or the GNU Library General Public Licence into a
copy of this library, as this licence permits, the exception does not apply
to the code that you add in this way. To avoid misleading anyone as to the
status of such modified files, you must delete this exception notice from
such code and/or adjust the licensing conditions notice accordingly.
4. If you write modifications of your own for this library, it is your
choice whether to permit this exception to apply to your modifications. If
you do not wish that, you must delete the exception notice from such code
and/or adjust the licensing conditions notice accordingly.
================================================
FILE: Makefile
================================================
PYTHON ?= $(shell which python3 >/dev/null && echo python3 || echo python)
all $(MAKECMDGOALS):
@$(PYTHON) \
-c "import sys; sys.path.insert(0, sys.argv[1]); from releng.meson_make import main; main()" \
"$(shell pwd)" \
./build \
$(MAKECMDGOALS)
git-submodules:
@[ ! -f releng/meson/meson.py ] && $(PYTHON) tools/ensure-submodules.py
-include git-submodules
.PHONY: all $(MAKECMDGOALS)
================================================
FILE: README.md
================================================
# Frida
Dynamic instrumentation toolkit for developers, reverse-engineers, and security
researchers. Learn more at [frida.re](https://frida.re/).
Two ways to install
===================
## 1. Install from prebuilt binaries
This is the recommended way to get started. All you need to do is:
pip install frida-tools # CLI tools
pip install frida # Python bindings
npm install frida # Node.js bindings
You may also download pre-built binaries for various operating systems from
Frida's [releases](https://github.com/frida/frida/releases) page on GitHub.
## 2. Build your own binaries
Run:
make
You may also invoke `./configure` first if you want to specify a `--prefix`, or
any other options.
### CLI tools
For running the Frida CLI tools, e.g. `frida`, `frida-ls-devices`, `frida-ps`,
`frida-kill`, `frida-trace`, `frida-discover`, etc., you need a few packages:
pip install colorama prompt-toolkit pygments
### Apple OSes
First make a trusted code-signing certificate. If you have already used Xcode
before, chances are you already have an Apple development certificate.
You can check it with the following command:
security find-identity -v -p codesigning
Which will return the certificate in the following format:
1) XXXXX "Apple Development: user@mail.com (XXXXX)"
If you do not have a certificate, follow this guide:
https://help.apple.com/xcode/mac/current/#/dev154b28f09.
Next export the name of your certificate to relevant environment
variables, and run `make`:
export MACOS_CERTID="Apple Development: user@mail.com (XXXXXXXXXX)"
export IOS_CERTID="Apple Development: user@mail.com (XXXXXXXXXX)"
export WATCHOS_CERTID="Apple Development: user@mail.com (XXXXXXXXXX)"
export TVOS_CERTID="Apple Development: user@mail.com (XXXXXXXXXX)"
make
## Learn more
Have a look at our [documentation](https://frida.re/docs/home/).
================================================
FILE: configure
================================================
#!/bin/sh
[ -z "$PYTHON" ] && PYTHON=$(which python3 >/dev/null && echo python3 || echo python)
cd $(dirname $0)
srcroot=$(pwd)
[ ! -f releng/meson/meson.py ] && "$PYTHON" tools/ensure-submodules.py
cd - >/dev/null
exec "$PYTHON" \
-c "import sys; sys.path.insert(0, sys.argv[1]); from releng.meson_configure import main; main()" \
"$srcroot" \
"$@"
================================================
FILE: configure.bat
================================================
@setlocal
@echo off
rem:: Based on: https://github.com/microsoft/terminal/issues/217#issuecomment-737594785
goto :_start_
:set_real_dp0
set dp0=%~dp0
set "dp0=%dp0:~0,-1%"
goto :eof
:_start_
call :set_real_dp0
if not exist "%dp0%\releng\meson\meson.py" (
python "%dp0%\tools\ensure-submodules.py"
if %errorlevel% neq 0 exit /b %errorlevel%
)
endlocal & goto #_undefined_# 2>nul || title %COMSPEC% & python ^
-c "import sys; sys.path.insert(0, sys.argv[1]); from releng.meson_configure import main; main()" ^
"%dp0%" ^
%*
================================================
FILE: make.bat
================================================
@setlocal
@echo off
rem:: Based on: https://github.com/microsoft/terminal/issues/217#issuecomment-737594785
goto :_start_
:set_real_dp0
set dp0=%~dp0
set "dp0=%dp0:~0,-1%"
goto :eof
:_start_
call :set_real_dp0
if not exist "%dp0%\releng\meson\meson.py" (
python "%dp0%\tools\ensure-submodules.py"
if %errorlevel% neq 0 exit /b %errorlevel%
)
endlocal & goto #_undefined_# 2>nul || title %COMSPEC% & python ^
-c "import sys; sys.path.insert(0, sys.argv[1]); from releng.meson_make import main; main()" ^
"%dp0%" ^
.\build ^
%*
================================================
FILE: meson.build
================================================
project('frida', 'c',
version: run_command('releng' / 'frida_version.py', check: true).stdout().strip(),
meson_version: '>=1.1.0',
)
python = import('python').find_installation()
is_cross_build = meson.is_cross_build()
is_watchos = host_machine.subsystem().split('-')[0] == 'watchos'
gum_options = [
'frida_version=' + meson.project_version(),
'graft_tool=' + (get_option('graft_tool').disable_auto_if(is_cross_build).allowed() ? 'enabled' : 'disabled'),
'gumjs=enabled',
]
subproject('frida-gum', default_options: gum_options)
core_options = [
'frida_version=' + meson.project_version(),
]
core_options += 'gadget=' + (get_option('gadget').disable_auto_if(not is_cross_build).allowed() ? 'enabled' : 'disabled')
foreach component : ['server', 'portal', 'inject']
core_options += component + '=' + (get_option(component)
.disable_auto_if(not is_cross_build)
.disable_auto_if(is_watchos)
.allowed() ? 'enabled' : 'disabled')
endforeach
subproject('frida-core', default_options: core_options)
ensure_submodules = [python, files('tools' / 'ensure-submodules.py')]
if get_option('frida_clr') \
.disable_auto_if(is_cross_build) \
.disable_auto_if(build_machine.system() != 'windows') \
.disable_auto_if(get_option('b_vscrt').startswith('mt')) \
.allowed()
run_command(ensure_submodules, 'frida-clr', check: true)
if get_option('frida_clr').auto()
detect_result = run_command(python, 'subprojects' / 'frida-clr' / 'detect-netfx.py', check: false)
build_clr_bindings = detect_result.returncode() == 0
else
build_clr_bindings = true
endif
if build_clr_bindings
subproject('frida-clr')
endif
endif
if get_option('frida_node') \
.disable_auto_if(is_cross_build) \
.allowed()
run_command(ensure_submodules, 'frida-node', check: true)
subproject('frida-node')
endif
if get_option('frida_python') \
.disable_auto_if(is_cross_build) \
.allowed()
run_command(ensure_submodules, 'frida-python', check: true)
subproject('frida-python')
endif
if get_option('frida_swift') \
.disable_auto_if(is_cross_build) \
.disable_auto_if(build_machine.system() != 'macos') \
.allowed()
run_command(ensure_submodules, 'frida-swift', check: true)
subproject('frida-swift')
endif
if get_option('frida_qml') \
.disable_auto_if(is_cross_build) \
.allowed()
qt6_dep = dependency('qt6', modules: ['Core'], required: false)
if get_option('frida_qml') \
.disable_auto_if(not qt6_dep.found()) \
.allowed()
run_command(ensure_submodules, 'frida-qml', check: true)
subproject('frida-qml')
endif
endif
if get_option('frida_tools') \
.disable_auto_if(is_cross_build) \
.allowed()
run_command(ensure_submodules, 'frida-tools', check: true)
subproject('frida-tools')
endif
================================================
FILE: meson.options
================================================
option('frida_tools',
type: 'feature',
value: 'auto',
description: 'Build CLI tools, like frida, frida-trace, etc.',
)
option('graft_tool',
type: 'feature',
value: 'auto',
description: 'Build gum-graft tool',
)
option('gadget',
type: 'feature',
value: 'auto',
description: 'Build frida-gadget',
)
option('server',
type: 'feature',
value: 'auto',
description: 'Build frida-server',
)
option('portal',
type: 'feature',
value: 'disabled',
description: 'Build frida-portal',
)
option('inject',
type: 'feature',
value: 'auto',
description: 'Build frida-inject',
)
option('frida_clr',
type: 'feature',
value: 'disabled',
description: 'Build .NET bindings',
)
option('frida_node',
type: 'feature',
value: 'disabled',
description: 'Build Node.js bindings',
)
option('frida_python',
type: 'feature',
value: 'auto',
description: 'Build Python bindings',
)
option('frida_swift',
type: 'feature',
value: 'disabled',
description: 'Build Swift bindings',
)
option('frida_qml',
type: 'feature',
value: 'disabled',
description: 'Build QML bindings',
)
================================================
FILE: tools/ensure-submodules.py
================================================
#!/usr/bin/env python3
import subprocess
import sys
from pathlib import Path
SOURCE_ROOT = Path(__file__).resolve().parent.parent
UPDATE_FLAGS = ["--init", "--depth", "1"]
def main(argv: list[str]):
names = argv[1:]
if not names:
names = ["frida-gum", "frida-core"]
paths_to_check = [Path("subprojects") / name for name in names]
try:
releng = SOURCE_ROOT / "releng"
if not (releng / "meson" / "meson.py").exists():
print(f"Fetching releng...", flush=True)
run(["git", "submodule", "update", *UPDATE_FLAGS, releng.name], cwd=SOURCE_ROOT)
run(["git", "submodule", "update", *UPDATE_FLAGS], cwd=releng)
for relpath in paths_to_check:
if not (SOURCE_ROOT / relpath / "meson.build").exists():
print(f"Fetching {relpath.name}...", flush=True)
run(["git", "submodule", "update", *UPDATE_FLAGS, relpath], cwd=SOURCE_ROOT)
except Exception as e:
print(e, file=sys.stderr)
if isinstance(e, subprocess.CalledProcessError):
for label, data in [("Output", e.output), ("Stderr", e.stderr)]:
if data:
print(f"{label}:\n\t| " + "\n\t| ".join(data.strip().split("\n")), file=sys.stderr)
sys.exit(1)
def run(argv: list[str], **kwargs) -> subprocess.CompletedProcess:
return subprocess.run(argv, capture_output=True, encoding="utf-8", check=True, **kwargs)
if __name__ == "__main__":
main(sys.argv)
gitextract_t62922vv/
├── .cirrus.yml
├── .github/
│ ├── CODEOWNERS
│ ├── FUNDING.yml
│ ├── actions/
│ │ ├── package-artifact-file/
│ │ │ └── action.yml
│ │ ├── package-artifact-files-as-sfx/
│ │ │ └── action.yml
│ │ ├── package-artifact-files-as-tarball/
│ │ │ └── action.yml
│ │ ├── package-ios-assets/
│ │ │ └── action.yml
│ │ ├── package-tvos-assets/
│ │ │ └── action.yml
│ │ ├── prepare-python-packages/
│ │ │ └── action.yml
│ │ ├── publish-debs/
│ │ │ └── action.yml
│ │ ├── setup-freebsd-env/
│ │ │ └── action.yml
│ │ ├── setup-linux-env/
│ │ │ └── action.yml
│ │ ├── setup-macos-env/
│ │ │ └── action.yml
│ │ └── setup-windows-env/
│ │ └── action.yml
│ ├── scripts/
│ │ ├── package-cirrus-ci-artifacts.sh
│ │ ├── rename-release-assets.sh
│ │ └── repo.py
│ └── workflows/
│ └── ci.yml
├── .gitignore
├── .gitmodules
├── BSDmakefile
├── CONTRIBUTING.md
├── COPYING
├── Makefile
├── README.md
├── configure
├── configure.bat
├── make.bat
├── meson.build
├── meson.options
└── tools/
└── ensure-submodules.py
SYMBOL INDEX (17 symbols across 2 files) FILE: .github/scripts/repo.py function main (line 30) | def main(argv: list[str]): function bump (line 62) | def bump(): function bump_subproject (line 84) | def bump_subproject(name: str, repo: Path): function bump_releng (line 141) | def bump_releng(releng: Path): function bump_submodules (line 148) | def bump_submodules() -> list[str]: function tag (line 163) | def tag(version: str): function prepublish (line 174) | def prepublish(name: str, version: str, repo: Path): function backtag (line 197) | def backtag(version: str): function enumerate_projects_in_release_cycle (line 207) | def enumerate_projects_in_release_cycle() -> Iterator[tuple[str, Path]]: function enumerate_git_wraps_in_repo (line 212) | def enumerate_git_wraps_in_repo(repo: Path) -> Iterator[tuple[str, Confi... function assert_no_local_changes (line 225) | def assert_no_local_changes(repo: Path): function query_local_changes (line 229) | def query_local_changes(repo: Path) -> list[str]: function push_changes (line 236) | def push_changes(name: str, repo: Path): function ensure_remote_origin_writable (line 241) | def ensure_remote_origin_writable(name: str, repo: Path): function run (line 248) | def run(argv: list[str], **kwargs) -> subprocess.CompletedProcess: FILE: tools/ensure-submodules.py function main (line 11) | def main(argv: list[str]): function run (line 37) | def run(argv: list[str], **kwargs) -> subprocess.CompletedProcess:
Condensed preview — 31 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (155K chars).
[
{
"path": ".cirrus.yml",
"chars": 3910,
"preview": "task:\n name: freebsd-x86_64\n freebsd_instance:\n image_family: freebsd-15-0-amd64-ufs\n environment:\n S3_ACCESS_K"
},
{
"path": ".github/CODEOWNERS",
"chars": 28,
"preview": "/.github/workflows/ @oleavr\n"
},
{
"path": ".github/FUNDING.yml",
"chars": 14,
"preview": "github: frida\n"
},
{
"path": ".github/actions/package-artifact-file/action.yml",
"chars": 1073,
"preview": "name: Package single-file artifact\ndescription: Downloads an artifact and uploads a compressed version of its file\ninput"
},
{
"path": ".github/actions/package-artifact-files-as-sfx/action.yml",
"chars": 645,
"preview": "name: Package artifact files as SFX\ndescription: Downloads a specific artifact and uploads a packaged version of it\ninpu"
},
{
"path": ".github/actions/package-artifact-files-as-tarball/action.yml",
"chars": 668,
"preview": "name: Package artifact files as tarball\ndescription: Downloads a specific artifact and uploads a packaged version of it\n"
},
{
"path": ".github/actions/package-ios-assets/action.yml",
"chars": 619,
"preview": "name: Package iOS assets\ndescription: Downloads iOS assets and packages them\nruns:\n using: composite\n steps:\n - nam"
},
{
"path": ".github/actions/package-tvos-assets/action.yml",
"chars": 573,
"preview": "name: Package tvOS assets\ndescription: Downloads tvOS assets and packages them\nruns:\n using: composite\n steps:\n - n"
},
{
"path": ".github/actions/prepare-python-packages/action.yml",
"chars": 1936,
"preview": "name: Prepare Python packages for publishing\ndescription: Prepares Python source distribution and wheels to be published"
},
{
"path": ".github/actions/publish-debs/action.yml",
"chars": 2601,
"preview": "name: Publish .deb packages\ndescription: Publishes already packaged debs\ninputs:\n site:\n required: true\n path: Wh"
},
{
"path": ".github/actions/setup-freebsd-env/action.yml",
"chars": 1779,
"preview": "name: Set up FreeBSD environment\ndescription: Set up everything needed to build and release things on FreeBSD\ninputs:\n "
},
{
"path": ".github/actions/setup-linux-env/action.yml",
"chars": 1775,
"preview": "name: Set up Linux environment\ndescription: Set up everything needed to build and release things on Linux\ninputs:\n aws-"
},
{
"path": ".github/actions/setup-macos-env/action.yml",
"chars": 3602,
"preview": "name: Set up macOS environment\ndescription: Set up everything needed to build and release things on macOS\ninputs:\n cert"
},
{
"path": ".github/actions/setup-windows-env/action.yml",
"chars": 2133,
"preview": "name: Set up Windows environment\ndescription: Set up everything needed to build and release things on Windows\ninputs:\n "
},
{
"path": ".github/scripts/package-cirrus-ci-artifacts.sh",
"chars": 2741,
"preview": "#!/bin/bash\n\nsha=$1\nif [ -z \"$sha\" ]; then\n echo \"Usage: $0 <sha>\" > /dev/stderr\n exit 1\nfi\n\nset -e\n\nbuild_id=\"\"\nwhile"
},
{
"path": ".github/scripts/rename-release-assets.sh",
"chars": 665,
"preview": "#!/bin/bash\n\nif [ -z \"$FRIDA_VERSION\" ]; then\n echo \"FRIDA_VERSION must be set\" > /dev/stderr\n exit 1\nfi\n\nset -e\n\ncd b"
},
{
"path": ".github/scripts/repo.py",
"chars": 8893,
"preview": "#!/usr/bin/env python3\n\nimport argparse\nfrom configparser import ConfigParser\nfrom pathlib import Path\nimport subprocess"
},
{
"path": ".github/workflows/ci.yml",
"chars": 77993,
"preview": "name: CI\n\non: push\n\nenv:\n FRIDA_COMPILER_MOD: subprojects/frida-core/src/compiler/go.mod\n ANDROID_NDK_VERSION: r29\n\njo"
},
{
"path": ".gitignore",
"chars": 138,
"preview": "/build/\n/deps/\n/releng/__pycache__/\n/releng/modules/frida-gadget-ios/*.dylib\n/releng/modules/frida-gadget-ios/node_modul"
},
{
"path": ".gitmodules",
"chars": 999,
"preview": "[submodule \"frida-gum\"]\n\tpath = subprojects/frida-gum\n\turl = https://github.com/frida/frida-gum.git\n[submodule \"frida-co"
},
{
"path": "BSDmakefile",
"chars": 72,
"preview": "all: .DEFAULT\n\n.DEFAULT:\n\t@gmake ${.MAKEFLAGS} ${.TARGETS}\n\n.PHONY: all\n"
},
{
"path": "CONTRIBUTING.md",
"chars": 23070,
"preview": "# Intro\n\nFrida is composed of many sub-projects and its code spans across many\ndifferent languages, such as C, C++, Vala"
},
{
"path": "COPYING",
"chars": 2416,
"preview": " wxWindows Library Licence, Version 3.1\n ======================================\n\nCopyright (c)"
},
{
"path": "Makefile",
"chars": 400,
"preview": "PYTHON ?= $(shell which python3 >/dev/null && echo python3 || echo python)\n\nall $(MAKECMDGOALS):\n\t@$(PYTHON) \\\n\t\t-c \"imp"
},
{
"path": "README.md",
"chars": 1908,
"preview": "# Frida\n\nDynamic instrumentation toolkit for developers, reverse-engineers, and security\nresearchers. Learn more at [fri"
},
{
"path": "configure",
"chars": 365,
"preview": "#!/bin/sh\n\n[ -z \"$PYTHON\" ] && PYTHON=$(which python3 >/dev/null && echo python3 || echo python)\n\ncd $(dirname $0)\nsrcro"
},
{
"path": "configure.bat",
"chars": 563,
"preview": "@setlocal\r\n@echo off\r\nrem:: Based on: https://github.com/microsoft/terminal/issues/217#issuecomment-737594785\r\ngoto :_st"
},
{
"path": "make.bat",
"chars": 573,
"preview": "@setlocal\r\n@echo off\r\nrem:: Based on: https://github.com/microsoft/terminal/issues/217#issuecomment-737594785\r\ngoto :_st"
},
{
"path": "meson.build",
"chars": 2794,
"preview": "project('frida', 'c',\n version: run_command('releng' / 'frida_version.py', check: true).stdout().strip(),\n meson_versi"
},
{
"path": "meson.options",
"chars": 1112,
"preview": "option('frida_tools',\n type: 'feature',\n value: 'auto',\n description: 'Build CLI tools, like frida, frida-trace, etc."
},
{
"path": "tools/ensure-submodules.py",
"chars": 1503,
"preview": "#!/usr/bin/env python3\n\nimport subprocess\nimport sys\nfrom pathlib import Path\n\nSOURCE_ROOT = Path(__file__).resolve().pa"
}
]
About this extraction
This page contains the full source code of the frida/frida GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 31 files (144.1 KB), approximately 40.3k tokens, and a symbol index with 17 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.