mirror of
https://github.com/rizinorg/rz-frida.git
synced 2026-11-10 04:21:25 -10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fbfd751a23 | ||
|
|
330bb3f625 | ||
|
|
30b9e6dac7 | ||
|
|
50ba5be26f |
No files matched your search
@@ -12,7 +12,6 @@ Exit codes: 0 on success (changed or not), 1 when a version check fails.
|
||||
"""
|
||||
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import urllib.request
|
||||
@@ -46,9 +45,6 @@ def latest_release(repo):
|
||||
"User-Agent": "rz-frida-version-bump",
|
||||
},
|
||||
)
|
||||
token = os.environ.get("GITHUB_TOKEN")
|
||||
if token:
|
||||
request.add_header("Authorization", "Bearer %s" % token)
|
||||
with urllib.request.urlopen(request, timeout=30) as response:
|
||||
data = json.load(response)
|
||||
return data["tag_name"]
|
||||
|
||||
@@ -0,0 +1,303 @@
|
||||
# SPDX-FileCopyrightText: 2026 Alok Kumar Mishra <[email protected]>
|
||||
# SPDX-License-Identifier: LGPL-3.0-only
|
||||
|
||||
"""Validate a dependency pin patch before it is uploaded or published.
|
||||
|
||||
The only accepted changes are version rewrites of the pin lines in the
|
||||
workflow env blocks, of the meson frida_version option, and of the Cutter
|
||||
version examples in the README. File creates, deletes, renames, copies,
|
||||
mode or binary changes, non-pin edits, and malformed diffs are rejected.
|
||||
"""
|
||||
|
||||
import re
|
||||
import sys
|
||||
|
||||
ALLOWED_PATHS = (
|
||||
".github/workflows/ci.yml",
|
||||
".github/workflows/release.yml",
|
||||
"meson_options.txt",
|
||||
"README.md",
|
||||
)
|
||||
|
||||
# Pin names that exist in each workflow env block.
|
||||
WORKFLOW_PINS = {
|
||||
".github/workflows/ci.yml": frozenset(("RIZIN_VERSION", "FRIDA_VERSION")),
|
||||
".github/workflows/release.yml": frozenset(
|
||||
("RIZIN_VERSION", "FRIDA_VERSION", "CUTTER_VERSION")
|
||||
),
|
||||
}
|
||||
|
||||
VERSION = r"v?\d+(?:\.\d+)+"
|
||||
|
||||
DIFF_HEADER = re.compile(r"^diff --git a/(\S+) b/(\S+)$")
|
||||
INDEX_LINE = re.compile(r"^index [0-9a-f]{4,64}\.\.[0-9a-f]{4,64} 100644$")
|
||||
HUNK_HEADER = re.compile(r"^@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@(?: .*)?$")
|
||||
|
||||
PIN_LINE = re.compile(
|
||||
r"^ (RIZIN_VERSION|FRIDA_VERSION|CUTTER_VERSION): (" + VERSION + r")$"
|
||||
)
|
||||
MESON_LINE = re.compile(
|
||||
r"^option\('frida_version', type: 'string', value: '("
|
||||
+ VERSION
|
||||
+ r")', description: ('[^']*')\)$"
|
||||
)
|
||||
|
||||
# The Cutter version mentions the bump script rewrites in the README.
|
||||
README_FILENAME = re.compile(r"Cutter-(" + VERSION + r")-(Linux|macOS|Windows)")
|
||||
README_PHRASE = re.compile(r"Cutter (" + VERSION + r") AppImage")
|
||||
|
||||
|
||||
class PatchError(Exception):
|
||||
"""The patch is not a plain dependency version bump."""
|
||||
|
||||
|
||||
def validate_text(text):
|
||||
"""Raise PatchError unless text is a clean version-only pin patch."""
|
||||
if not text.strip():
|
||||
raise PatchError("patch is empty")
|
||||
lines = text.splitlines()
|
||||
paths = set()
|
||||
index = 0
|
||||
while index < len(lines):
|
||||
index = _parse_file(lines, index, paths)
|
||||
if not paths:
|
||||
raise PatchError("patch has no file diffs")
|
||||
|
||||
|
||||
def _parse_file(lines, index, paths):
|
||||
header = DIFF_HEADER.fullmatch(lines[index])
|
||||
if header is None:
|
||||
raise PatchError(
|
||||
"line %d: expected a 'diff --git' header, got %r"
|
||||
% (index + 1, lines[index])
|
||||
)
|
||||
old_path, new_path = header.group(1), header.group(2)
|
||||
if old_path != new_path:
|
||||
raise PatchError(
|
||||
"line %d: diff header renames %s to %s" % (index + 1, old_path, new_path)
|
||||
)
|
||||
if old_path not in ALLOWED_PATHS:
|
||||
raise PatchError(
|
||||
"line %d: %s is not an update target" % (index + 1, old_path)
|
||||
)
|
||||
if old_path in paths:
|
||||
raise PatchError("line %d: duplicate diff for %s" % (index + 1, old_path))
|
||||
paths.add(old_path)
|
||||
index += 1
|
||||
|
||||
if index >= len(lines) or INDEX_LINE.fullmatch(lines[index]) is None:
|
||||
raise PatchError(
|
||||
"line %d: %s: expected an 'index <hash>..<hash> 100644' line"
|
||||
% (index + 1, old_path)
|
||||
)
|
||||
index += 1
|
||||
for marker in ("--- a/" + old_path, "+++ b/" + old_path):
|
||||
if index >= len(lines) or lines[index] != marker:
|
||||
raise PatchError(
|
||||
"line %d: %s: expected %r"
|
||||
% (index + 1, old_path, marker)
|
||||
)
|
||||
index += 1
|
||||
|
||||
blocks = []
|
||||
hunks = 0
|
||||
while index < len(lines) and not lines[index].startswith("diff --git "):
|
||||
hunk = HUNK_HEADER.fullmatch(lines[index])
|
||||
if hunk is None:
|
||||
raise PatchError(
|
||||
"line %d: %s: malformed hunk header %r"
|
||||
% (index + 1, old_path, lines[index])
|
||||
)
|
||||
index += 1
|
||||
index, hunk_blocks = _parse_hunk(lines, index, old_path, hunk)
|
||||
blocks.extend(hunk_blocks)
|
||||
hunks += 1
|
||||
if hunks == 0:
|
||||
raise PatchError("%s: file diff has no hunks" % old_path)
|
||||
|
||||
_validate_blocks(old_path, blocks)
|
||||
return index
|
||||
|
||||
|
||||
def _parse_hunk(lines, index, path, header):
|
||||
old_left = int(header.group(2)) if header.group(2) is not None else 1
|
||||
new_left = int(header.group(4)) if header.group(4) is not None else 1
|
||||
blocks = []
|
||||
minus = []
|
||||
plus = []
|
||||
seen_plus = False
|
||||
|
||||
def flush():
|
||||
nonlocal minus, plus, seen_plus
|
||||
if minus or plus:
|
||||
blocks.append((minus, plus))
|
||||
minus, plus, seen_plus = [], [], False
|
||||
|
||||
while old_left > 0 or new_left > 0:
|
||||
if index >= len(lines):
|
||||
raise PatchError(
|
||||
"line %d: %s: hunk is truncated, missing %d old and %d new lines"
|
||||
% (index + 1, path, old_left, new_left)
|
||||
)
|
||||
line = lines[index]
|
||||
if line.startswith(" "):
|
||||
flush()
|
||||
old_left -= 1
|
||||
new_left -= 1
|
||||
elif line.startswith("-"):
|
||||
if seen_plus:
|
||||
raise PatchError(
|
||||
"line %d: %s: '-' after '+' in a change block"
|
||||
% (index + 1, path)
|
||||
)
|
||||
minus.append(line[1:])
|
||||
old_left -= 1
|
||||
elif line.startswith("+"):
|
||||
plus.append(line[1:])
|
||||
seen_plus = True
|
||||
new_left -= 1
|
||||
else:
|
||||
raise PatchError(
|
||||
"line %d: %s: malformed diff line %r" % (index + 1, path, line)
|
||||
)
|
||||
if old_left < 0 or new_left < 0:
|
||||
raise PatchError(
|
||||
"line %d: %s: hunk has more lines than its header declares"
|
||||
% (index + 1, path)
|
||||
)
|
||||
index += 1
|
||||
flush()
|
||||
if not blocks:
|
||||
raise PatchError("%s: hunk changes no lines" % path)
|
||||
return index, blocks
|
||||
|
||||
|
||||
def _validate_blocks(path, blocks):
|
||||
if path in WORKFLOW_PINS:
|
||||
_validate_workflow_blocks(path, blocks)
|
||||
elif path == "meson_options.txt":
|
||||
_validate_meson_blocks(blocks)
|
||||
else:
|
||||
_validate_readme_blocks(blocks)
|
||||
|
||||
|
||||
def _validate_workflow_blocks(path, blocks):
|
||||
pins = WORKFLOW_PINS[path]
|
||||
for minus, plus in blocks:
|
||||
if len(minus) != len(plus):
|
||||
raise PatchError("%s: pin lines must be edited in place" % path)
|
||||
for old_line, new_line in zip(minus, plus):
|
||||
old = PIN_LINE.fullmatch(old_line)
|
||||
new = PIN_LINE.fullmatch(new_line)
|
||||
if old is None or new is None:
|
||||
raise PatchError(
|
||||
"%s: not a pin line: %r -> %r" % (path, old_line, new_line)
|
||||
)
|
||||
name = old.group(1)
|
||||
if new.group(1) != name:
|
||||
raise PatchError(
|
||||
"%s: pin %s was turned into %s" % (path, name, new.group(1))
|
||||
)
|
||||
if name not in pins:
|
||||
raise PatchError("%s: %s is not pinned in this workflow" % (path, name))
|
||||
if old.group(2) == new.group(2):
|
||||
raise PatchError(
|
||||
"%s: pin %s keeps the version %s" % (path, name, old.group(2))
|
||||
)
|
||||
|
||||
|
||||
def _validate_meson_blocks(blocks):
|
||||
for minus, plus in blocks:
|
||||
if len(minus) != len(plus):
|
||||
raise PatchError("meson_options.txt: option line must be edited in place")
|
||||
pairs = [pair for minus, plus in blocks for pair in zip(minus, plus)]
|
||||
if len(pairs) != 1:
|
||||
raise PatchError(
|
||||
"meson_options.txt: expected exactly one frida_version line edit"
|
||||
)
|
||||
old_line, new_line = pairs[0]
|
||||
old = MESON_LINE.fullmatch(old_line)
|
||||
new = MESON_LINE.fullmatch(new_line)
|
||||
if old is None or new is None:
|
||||
raise PatchError(
|
||||
"meson_options.txt: not the frida_version option: %r -> %r"
|
||||
% (old_line, new_line)
|
||||
)
|
||||
if old.group(2) != new.group(2):
|
||||
raise PatchError(
|
||||
"meson_options.txt: frida_version edit changes more than the version"
|
||||
)
|
||||
if old.group(1) == new.group(1):
|
||||
raise PatchError(
|
||||
"meson_options.txt: frida_version keeps the value %s" % old.group(1)
|
||||
)
|
||||
|
||||
|
||||
def _readme_versions(line):
|
||||
versions = [match.group(1) for match in README_FILENAME.finditer(line)]
|
||||
versions.extend(match.group(1) for match in README_PHRASE.finditer(line))
|
||||
return versions
|
||||
|
||||
|
||||
def _replace_readme_versions(line, version):
|
||||
line = README_FILENAME.sub(
|
||||
lambda match: "Cutter-%s-%s" % (version, match.group(2)), line
|
||||
)
|
||||
return README_PHRASE.sub("Cutter %s AppImage" % version, line)
|
||||
|
||||
|
||||
def _validate_readme_blocks(blocks):
|
||||
old_versions = set()
|
||||
new_versions = set()
|
||||
for minus, plus in blocks:
|
||||
if len(minus) != len(plus):
|
||||
raise PatchError("README.md: version mentions must be edited in place")
|
||||
for old_line, new_line in zip(minus, plus):
|
||||
old_found = _readme_versions(old_line)
|
||||
new_found = _readme_versions(new_line)
|
||||
if not old_found or not new_found:
|
||||
raise PatchError(
|
||||
"README.md: not a Cutter version mention: %r" % old_line
|
||||
)
|
||||
if len(set(old_found)) != 1 or len(set(new_found)) != 1:
|
||||
raise PatchError(
|
||||
"README.md: mixed Cutter versions in %r -> %r"
|
||||
% (old_line, new_line)
|
||||
)
|
||||
old_version = old_found[0]
|
||||
new_version = new_found[0]
|
||||
if old_version == new_version:
|
||||
raise PatchError("README.md: %s keeps the version" % old_version)
|
||||
expected = _replace_readme_versions(old_line, new_version)
|
||||
if expected != new_line:
|
||||
raise PatchError(
|
||||
"README.md: %r is not the expected version substitution of %r"
|
||||
% (new_line, old_line)
|
||||
)
|
||||
old_versions.add(old_version)
|
||||
new_versions.add(new_version)
|
||||
if len(old_versions) != 1 or len(new_versions) != 1:
|
||||
raise PatchError("README.md: inconsistent Cutter versions in the diff")
|
||||
|
||||
|
||||
def main(argv):
|
||||
if len(argv) != 2:
|
||||
print("usage: validate_pins_patch.py <patch>", file=sys.stderr)
|
||||
return 2
|
||||
try:
|
||||
with open(argv[1], encoding="utf-8") as handle:
|
||||
text = handle.read()
|
||||
except OSError as error:
|
||||
print("error: cannot read %s: %s" % (argv[1], error), file=sys.stderr)
|
||||
return 2
|
||||
try:
|
||||
validate_text(text)
|
||||
except PatchError as error:
|
||||
print("::error::pins.patch rejected: %s" % error, file=sys.stderr)
|
||||
return 1
|
||||
print("pins.patch ok")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main(sys.argv))
|
||||
+43
-16
@@ -2,14 +2,19 @@ name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
branches: [dev, stable]
|
||||
pull_request:
|
||||
branches: [main]
|
||||
workflow_dispatch:
|
||||
|
||||
# Dependency pins, bumped by update-deps workflow.
|
||||
# dev builds rizin from its dev branch, stable uses the pinned release.
|
||||
# RIZIN_DEV_REF can be a branch name or a commit sha (just-in-case).
|
||||
# PRs use the base branch, pushes/dispatches use the ref.
|
||||
env:
|
||||
RIZIN_VERSION: v0.9.1
|
||||
RIZIN_DEV_REF: dev
|
||||
FRIDA_VERSION: 17.17.0
|
||||
RIZIN_FLAVOR: ${{ (github.base_ref == 'dev' || github.ref_name == 'dev') && 'dev' || 'release' }}
|
||||
|
||||
jobs:
|
||||
linux-frida:
|
||||
@@ -22,15 +27,26 @@ jobs:
|
||||
with: { node-version: '24' }
|
||||
|
||||
- name: Install rizin
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
pip install meson ninja PyYAML
|
||||
wget -q "https://github.com/rizinorg/rizin/releases/download/${RIZIN_VERSION}/rizin-src-${RIZIN_VERSION}.tar.xz"
|
||||
tar xf rizin-src-${RIZIN_VERSION}.tar.xz
|
||||
cd rizin-${RIZIN_VERSION}
|
||||
meson setup build --prefix=/usr -Dblob=true
|
||||
ninja -C build
|
||||
sudo ninja -C build install
|
||||
cd ..
|
||||
if [ "$RIZIN_FLAVOR" = dev ]; then
|
||||
curl -fsSL "https://github.com/rizinorg/rizin/archive/${RIZIN_DEV_REF}.tar.gz" -o rizin-dev.tar.gz
|
||||
mkdir -p rizin-dev-src
|
||||
tar xf rizin-dev.tar.gz -C rizin-dev-src --strip-components=1
|
||||
src=rizin-dev-src
|
||||
echo "rizin dev ref: ${RIZIN_DEV_REF} ($(gh api "repos/rizinorg/rizin/commits/${RIZIN_DEV_REF}" --jq .sha 2>/dev/null || echo unknown))"
|
||||
else
|
||||
wget -q "https://github.com/rizinorg/rizin/releases/download/${RIZIN_VERSION}/rizin-src-${RIZIN_VERSION}.tar.xz"
|
||||
tar xf "rizin-src-${RIZIN_VERSION}.tar.xz"
|
||||
src="rizin-${RIZIN_VERSION}"
|
||||
echo "rizin release: ${RIZIN_VERSION}"
|
||||
fi
|
||||
meson setup "$src/build" "$src" --prefix=/usr -Dblob=true
|
||||
ninja -C "$src/build"
|
||||
sudo ninja -C "$src/build" install
|
||||
|
||||
- name: Build (with frida-core)
|
||||
run: |
|
||||
@@ -56,15 +72,26 @@ jobs:
|
||||
with: { node-version: '24' }
|
||||
|
||||
- name: Install rizin
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
pip install meson ninja PyYAML
|
||||
wget -q "https://github.com/rizinorg/rizin/releases/download/${RIZIN_VERSION}/rizin-src-${RIZIN_VERSION}.tar.xz"
|
||||
tar xf rizin-src-${RIZIN_VERSION}.tar.xz
|
||||
cd rizin-${RIZIN_VERSION}
|
||||
meson setup build --prefix=/usr -Dblob=true
|
||||
ninja -C build
|
||||
sudo ninja -C build install
|
||||
cd ..
|
||||
if [ "$RIZIN_FLAVOR" = dev ]; then
|
||||
curl -fsSL "https://github.com/rizinorg/rizin/archive/${RIZIN_DEV_REF}.tar.gz" -o rizin-dev.tar.gz
|
||||
mkdir -p rizin-dev-src
|
||||
tar xf rizin-dev.tar.gz -C rizin-dev-src --strip-components=1
|
||||
src=rizin-dev-src
|
||||
echo "rizin dev ref: ${RIZIN_DEV_REF} ($(gh api "repos/rizinorg/rizin/commits/${RIZIN_DEV_REF}" --jq .sha 2>/dev/null || echo unknown))"
|
||||
else
|
||||
wget -q "https://github.com/rizinorg/rizin/releases/download/${RIZIN_VERSION}/rizin-src-${RIZIN_VERSION}.tar.xz"
|
||||
tar xf "rizin-src-${RIZIN_VERSION}.tar.xz"
|
||||
src="rizin-${RIZIN_VERSION}"
|
||||
echo "rizin release: ${RIZIN_VERSION}"
|
||||
fi
|
||||
meson setup "$src/build" "$src" --prefix=/usr -Dblob=true
|
||||
ninja -C "$src/build"
|
||||
sudo ninja -C "$src/build" install
|
||||
|
||||
- name: Build (without frida-core)
|
||||
run: |
|
||||
|
||||
@@ -3,7 +3,7 @@ name: Lint
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches: [main]
|
||||
branches: [dev, stable]
|
||||
|
||||
jobs:
|
||||
changes:
|
||||
|
||||
@@ -2,6 +2,7 @@ name: Release
|
||||
|
||||
# Builds and tests the rizin and cutter plugins
|
||||
# and optionally publishes a GitHub release.
|
||||
# Releases are from the stable branch, dev has no releases.
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
@@ -27,9 +28,11 @@ on:
|
||||
pull_request:
|
||||
branches:
|
||||
- '**release**'
|
||||
- stable
|
||||
push:
|
||||
branches:
|
||||
- '**release**'
|
||||
- stable
|
||||
|
||||
# Dependency pins, bumped by the update-deps workflow.
|
||||
env:
|
||||
@@ -49,6 +52,14 @@ jobs:
|
||||
name: Test gate
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: Require stable branch for publishing
|
||||
if: github.event_name == 'workflow_dispatch' && inputs.publish_release
|
||||
run: |
|
||||
if [ "$GITHUB_REF_NAME" != stable ]; then
|
||||
echo "::error::releases must be dispatched from the stable branch"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- uses: actions/checkout@v7
|
||||
- uses: actions/setup-python@v7
|
||||
with: { python-version: '3.12' }
|
||||
@@ -939,6 +950,13 @@ jobs:
|
||||
- package-checksums
|
||||
if: github.event_name == 'workflow_dispatch' && inputs.publish_release
|
||||
steps:
|
||||
- name: Require stable branch
|
||||
run: |
|
||||
if [ "$GITHUB_REF_NAME" != stable ]; then
|
||||
echo "::error::releases must be dispatched from the stable branch"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- uses: actions/download-artifact@v8
|
||||
with:
|
||||
name: rz-frida-release-assets
|
||||
@@ -985,6 +1003,6 @@ jobs:
|
||||
target_commitish: ${{ steps.meta.outputs.target_commitish }}
|
||||
generate_release_notes: true
|
||||
draft: false
|
||||
prerelease: ${{ inputs.prerelease == 'true' }}
|
||||
prerelease: ${{ inputs.prerelease }}
|
||||
fail_on_unmatched_files: true
|
||||
files: release-assets/*
|
||||
@@ -0,0 +1,171 @@
|
||||
name: Open dependency pin pull request
|
||||
|
||||
# Publisher for the diffs produced by the read-only "Update dependency pins"
|
||||
# collector. It only downloads that run's validated patches, applies them, and
|
||||
# pushes branches / opens the PRs. All patch validation stuff happens in the
|
||||
# collector.
|
||||
|
||||
on:
|
||||
workflow_run:
|
||||
workflows: ["Update dependency pins"]
|
||||
types: [completed]
|
||||
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
open:
|
||||
name: Open pull request (${{ matrix.target }})
|
||||
if: >-
|
||||
github.event.workflow_run.conclusion == 'success' &&
|
||||
github.event.workflow_run.event != 'pull_request' &&
|
||||
(github.event.workflow_run.event == 'schedule' ||
|
||||
github.event.workflow_run.event == 'workflow_dispatch') &&
|
||||
github.event.workflow_run.head_branch == 'dev' &&
|
||||
github.event.workflow_run.head_repository.full_name == github.repository
|
||||
runs-on: ubuntu-latest
|
||||
concurrency:
|
||||
group: update-deps-pr-${{ matrix.target }}
|
||||
cancel-in-progress: false
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
target: [dev, stable]
|
||||
env:
|
||||
BASE_BRANCH: ${{ matrix.target }}
|
||||
ARTIFACT: pins-patch-${{ matrix.target }}
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
with:
|
||||
persist-credentials: false
|
||||
ref: ${{ matrix.target }}
|
||||
|
||||
- name: Download pin diff
|
||||
id: download
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
RUN_ID: ${{ github.event.workflow_run.id }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
case "$BASE_BRANCH" in
|
||||
dev|stable) ;;
|
||||
*)
|
||||
echo "::error::unexpected target branch: $BASE_BRANCH"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
count=$(gh api --paginate \
|
||||
"repos/${GITHUB_REPOSITORY}/actions/runs/${RUN_ID}/artifacts" \
|
||||
--jq ".artifacts[] | select(.name == \"${ARTIFACT}\" and .expired == false) | .id" \
|
||||
| wc -l)
|
||||
case "$count" in
|
||||
0)
|
||||
echo "no pin diff to publish for ${BASE_BRANCH}"
|
||||
exit 0
|
||||
;;
|
||||
1) ;;
|
||||
*)
|
||||
echo "::error::expected one non-expired ${ARTIFACT} artifact, found ${count}"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
dest="${RUNNER_TEMP}/pins-patch"
|
||||
rm -rf "$dest"
|
||||
gh run download "$RUN_ID" --repo "$GITHUB_REPOSITORY" \
|
||||
--name "$ARTIFACT" --dir "$dest"
|
||||
mapfile -d '' patches < <(find "$dest" -type f -name pins.patch -print0)
|
||||
if [ "${#patches[@]}" -ne 1 ]; then
|
||||
echo "::error::expected exactly one pins.patch in the artifact, found ${#patches[@]}"
|
||||
exit 1
|
||||
fi
|
||||
# Fixed copy path, so no artifact-controlled name reaches later steps.
|
||||
cp -- "${patches[0]}" "${RUNNER_TEMP}/pins.patch"
|
||||
echo "found=true" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Apply pin diff
|
||||
if: steps.download.outputs.found == 'true'
|
||||
run: |
|
||||
set -euo pipefail
|
||||
patch="${RUNNER_TEMP}/pins.patch"
|
||||
git apply --check "$patch"
|
||||
git apply "$patch"
|
||||
git add -- .github/workflows/ci.yml .github/workflows/release.yml meson_options.txt README.md
|
||||
status=$(git status --porcelain --untracked-files=all)
|
||||
if [ -z "$status" ]; then
|
||||
echo "::error::pin diff produced no staged changes"
|
||||
exit 1
|
||||
fi
|
||||
unexpected=$(printf '%s\n' "$status" | grep -Ev '^M (\.github/workflows/ci\.yml|\.github/workflows/release\.yml|meson_options\.txt|README\.md)$' || true)
|
||||
if [ -n "$unexpected" ]; then
|
||||
echo "::error::pin diff touched paths outside the four pin files"
|
||||
printf '%s\n' "$unexpected" >&2
|
||||
exit 1
|
||||
fi
|
||||
summary=$(git diff --cached --summary)
|
||||
if [ -n "$summary" ]; then
|
||||
echo "::error::pin diff changes a file type or mode"
|
||||
printf '%s\n' "$summary" >&2
|
||||
exit 1
|
||||
fi
|
||||
git -c user.name='github-actions[bot]' \
|
||||
-c user.email='41898282+github-actions[bot]@users.noreply.github.com' \
|
||||
commit -m "update ${BASE_BRANCH} dependency pins"
|
||||
|
||||
- name: Push branch and open pull request
|
||||
if: steps.download.outputs.found == 'true'
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.DEPENDENCY_PIN_PR_TOKEN }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
if [ -z "${GH_TOKEN:-}" ]; then
|
||||
echo "::error::DEPENDENCY_PIN_PR_TOKEN is not set; cannot publish the pin pr"
|
||||
exit 1
|
||||
fi
|
||||
case "$BASE_BRANCH" in
|
||||
stable)
|
||||
branch=deps/update-release-pins
|
||||
title='update release dependency pins'
|
||||
body=$(printf '%s\n' \
|
||||
'## Summary' \
|
||||
'- bump the rizin / frida / Cutter version pins in the workflows to their latest releases' \
|
||||
'' \
|
||||
'Release prep input: merge once stable code is compatible with the bump.')
|
||||
;;
|
||||
dev)
|
||||
branch=deps/update-dev-pins
|
||||
title='update dev dependency pins'
|
||||
body=$(printf '%s\n' \
|
||||
'## Summary' \
|
||||
'- bump the dependency pins in the workflows to their latest releases' \
|
||||
'' \
|
||||
'dev CI builds rizin from its dev branch, so rizin pin bumps affect release prep only.')
|
||||
;;
|
||||
*)
|
||||
echo "::error::unexpected target branch: $BASE_BRANCH"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
gh auth setup-git
|
||||
if git ls-remote --exit-code origin "refs/heads/${branch}" >/dev/null 2>&1; then
|
||||
git fetch origin "refs/heads/${branch}:refs/remotes/origin/${branch}"
|
||||
git push --force-with-lease="refs/heads/${branch}:refs/remotes/origin/${branch}" \
|
||||
origin "HEAD:refs/heads/${branch}"
|
||||
else
|
||||
git push origin "HEAD:refs/heads/${branch}"
|
||||
fi
|
||||
state=$(gh pr view "$branch" --repo "$GITHUB_REPOSITORY" --json state --jq .state 2>/dev/null || true)
|
||||
case "$state" in
|
||||
OPEN)
|
||||
gh pr edit "$branch" --repo "$GITHUB_REPOSITORY" \
|
||||
--base "$BASE_BRANCH" --title "$title" --body "$body"
|
||||
;;
|
||||
CLOSED)
|
||||
gh pr reopen "$branch" --repo "$GITHUB_REPOSITORY"
|
||||
gh pr edit "$branch" --repo "$GITHUB_REPOSITORY" \
|
||||
--base "$BASE_BRANCH" --title "$title" --body "$body"
|
||||
;;
|
||||
*)
|
||||
gh pr create --repo "$GITHUB_REPOSITORY" --base "$BASE_BRANCH" --head "$branch" --title "$title" --body "$body"
|
||||
;;
|
||||
esac
|
||||
@@ -1,7 +1,8 @@
|
||||
name: Update dependency pins
|
||||
|
||||
# Checks latest rizin / frida / Cutter releases once a week and opens a
|
||||
# pr when a pinned version in the release workflow is outdated.
|
||||
# Read-only collector: reads the latest rizin, frida, and Cutter releases,
|
||||
# rewrites the version pins when they are outdated, validates the diff, and
|
||||
# uploads it. "Open dependency pin pull request" publishes it.
|
||||
|
||||
on:
|
||||
schedule:
|
||||
@@ -9,44 +10,57 @@ on:
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: update-deps
|
||||
group: update-deps-collect
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
bump:
|
||||
name: Check for newer dependency releases
|
||||
collect:
|
||||
name: Check for newer dependency releases (${{ matrix.target }})
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
target: [dev, stable]
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
with:
|
||||
ref: ${{ matrix.target }}
|
||||
persist-credentials: false
|
||||
|
||||
- name: Bump version pins
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
GITHUB_TOKEN: ""
|
||||
GH_TOKEN: ""
|
||||
run: python3 .github/scripts/bump_release_versions.py
|
||||
|
||||
- name: Check for changes
|
||||
- name: Save pin diff
|
||||
id: diff
|
||||
run: |
|
||||
set -euo pipefail
|
||||
if git diff --quiet; then
|
||||
echo "changed=false" >> $GITHUB_OUTPUT
|
||||
else
|
||||
git diff
|
||||
echo "changed=true" >> $GITHUB_OUTPUT
|
||||
echo "changed=false" >> "$GITHUB_OUTPUT"
|
||||
exit 0
|
||||
fi
|
||||
unexpected=$(git diff --name-only | grep -Ev '^(\.github/workflows/ci\.yml|\.github/workflows/release\.yml|meson_options\.txt|README\.md)$' || true)
|
||||
if [ -n "$unexpected" ]; then
|
||||
echo "bump edited a file that is not a pin file" >&2
|
||||
printf '%s\n' "$unexpected" >&2
|
||||
exit 1
|
||||
fi
|
||||
git diff --no-ext-diff -- .github/workflows/ci.yml .github/workflows/release.yml meson_options.txt README.md > pins.patch
|
||||
echo "changed=true" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Create pull request
|
||||
- name: Validate pin diff
|
||||
if: steps.diff.outputs.changed == 'true'
|
||||
run: python3 .github/scripts/validate_pins_patch.py pins.patch
|
||||
|
||||
- uses: actions/upload-artifact@v7
|
||||
if: steps.diff.outputs.changed == 'true'
|
||||
uses: peter-evans/create-pull-request@v8
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
branch: deps/update-release-pins
|
||||
title: 'update release dependency pins'
|
||||
body: |
|
||||
## Summary
|
||||
- bump the rizin / frida / Cutter version pins in the workflows to their latest releases
|
||||
commit-message: 'update release dependency pins'
|
||||
delete-branch: true
|
||||
name: pins-patch-${{ matrix.target }}
|
||||
path: pins.patch
|
||||
retention-days: 5
|
||||
if-no-files-found: error
|
||||
@@ -4,6 +4,16 @@ Frida integration plugin for Rizin and Cutter.
|
||||
|
||||
The Rizin plugin provides the backend and command interface. The Cutter plugin provides a native frontend over the Rizin backend.
|
||||
|
||||
## Branches
|
||||
|
||||
- `dev` (default): development branch. CI builds against rizin `dev`.
|
||||
- `stable`: release branch. Uses the rizin, frida, and Cutter releases
|
||||
pinned in the workflows. Fixes that apply to the released APIs are
|
||||
cherry-picked here, and releases are tagged here.
|
||||
|
||||
Pull requests target `dev` by default. Dependency pin PRs are opened
|
||||
against both branches when a newer release is available.
|
||||
|
||||
## Screenshots
|
||||
|
||||

|
||||
|
||||
@@ -2,12 +2,13 @@
|
||||
|
||||
The plugin is a rizin core plugin: it registers the `Fr` command group
|
||||
inside rizin. It needs rizin v0.9.0 or later (the per-core plugin context
|
||||
from [rizin#6404](https://github.com/rizinorg/rizin/pull/6404)). CI builds
|
||||
against v0.9.1. It also needs rizin's development files. With
|
||||
`-Dfrida_core=enabled` and no manual paths, meson fetches the frida-core
|
||||
devkit for the host (see `frida_version` in `meson_options.txt`). Without
|
||||
frida-core the plugin still builds, and device commands answer with a
|
||||
`frida_unavailable` error.
|
||||
from [rizin#6404](https://github.com/rizinorg/rizin/pull/6404)). The
|
||||
`stable` branch builds against the rizin release pinned in the workflows
|
||||
and the `dev` branch builds against rizin `dev`. It also needs rizin's
|
||||
development files. With `-Dfrida_core=enabled` and no manual paths,
|
||||
meson fetches the frida-core devkit for the host (see `frida_version`
|
||||
in `meson_options.txt`). Without frida-core the plugin still builds,
|
||||
and device commands answer with a `frida_unavailable` error.
|
||||
|
||||
The examples below use a prefix of `$PREFIX`. Replace it with wherever you
|
||||
install rizin (`/usr/local`, `$HOME/.local`, and so on). `rizin -H` prints
|
||||
|
||||
@@ -49,12 +49,12 @@ static RzCmdStatus print_status(RzCore *core, RzCmdStateOutput *state) {
|
||||
|
||||
switch (state->mode) {
|
||||
case RZ_OUTPUT_MODE_STANDARD:
|
||||
rz_cons_printf("active: %s\n", rz_str_bool(active));
|
||||
rz_cons_printf("state: %s\n", state_string);
|
||||
rz_cons_printf(core->cons,"active: %s\n", rz_str_bool(active));
|
||||
rz_cons_printf(core->cons,"state: %s\n", state_string);
|
||||
if (session) {
|
||||
rz_cons_printf("pid: %u\n", rz_frida_session_target_pid(session));
|
||||
rz_cons_printf("action: %s\n", uri->action);
|
||||
rz_cons_printf("target: %s\n", uri->target);
|
||||
rz_cons_printf(core->cons,"pid: %u\n", rz_frida_session_target_pid(session));
|
||||
rz_cons_printf(core->cons,"action: %s\n", uri->action);
|
||||
rz_cons_printf(core->cons,"target: %s\n", uri->target);
|
||||
}
|
||||
return RZ_CMD_STATUS_OK;
|
||||
case RZ_OUTPUT_MODE_JSON:
|
||||
@@ -74,7 +74,7 @@ static RzCmdStatus print_status(RzCore *core, RzCmdStateOutput *state) {
|
||||
}
|
||||
}
|
||||
|
||||
static RzCmdStatus print_uri(const char *uri_string, RzCmdStateOutput *state) {
|
||||
static RzCmdStatus print_uri(const char *uri_string, RzCmdStateOutput *state, RzCons* cons) {
|
||||
rz_return_val_if_fail(state, RZ_CMD_STATUS_ERROR);
|
||||
|
||||
RzFridaUri uri = { 0 };
|
||||
@@ -102,10 +102,10 @@ static RzCmdStatus print_uri(const char *uri_string, RzCmdStateOutput *state) {
|
||||
|
||||
switch (state->mode) {
|
||||
case RZ_OUTPUT_MODE_STANDARD:
|
||||
rz_cons_printf("action: %s\n", uri.action);
|
||||
rz_cons_printf("transport: %s\n", uri.transport);
|
||||
rz_cons_printf("device: %s\n", uri.device);
|
||||
rz_cons_printf("target: %s\n", uri.target);
|
||||
rz_cons_printf(cons,"action: %s\n", uri.action);
|
||||
rz_cons_printf(cons,"transport: %s\n", uri.transport);
|
||||
rz_cons_printf(cons,"device: %s\n", uri.device);
|
||||
rz_cons_printf(cons,"target: %s\n", uri.target);
|
||||
break;
|
||||
case RZ_OUTPUT_MODE_JSON:
|
||||
rz_frida_json_ok_begin(state->d.pj);
|
||||
@@ -132,7 +132,7 @@ RZ_IPI RzCmdStatus rz_cmd_fridas_handler(RZ_NONNULL RzCore *core, RZ_UNUSED int
|
||||
|
||||
RZ_IPI RzCmdStatus rz_cmd_fridau_handler(RZ_NONNULL RzCore *core, RZ_UNUSED int argc, RZ_NONNULL const char **argv, RZ_NONNULL RzCmdStateOutput *state) {
|
||||
rz_return_val_if_fail(core && argv && state, RZ_CMD_STATUS_ERROR);
|
||||
return print_uri(argv[1], state);
|
||||
return print_uri(argv[1], state, core->cons);
|
||||
}
|
||||
|
||||
RZ_IPI RzCmdStatus rz_cmd_fridad_handler(RZ_NONNULL RzCore *core, RZ_UNUSED int argc, RZ_NONNULL const char **argv, RZ_NONNULL RzCmdStateOutput *state) {
|
||||
@@ -246,9 +246,9 @@ RZ_IPI RzCmdStatus rz_cmd_fridao_handler(RZ_NONNULL RzCore *core, RZ_UNUSED int
|
||||
// backend_open writes the envelope either way. only keep the session if it opened.
|
||||
// the cons break hook forwards a Cutter breakTask (or Ctrl-C) into the session's
|
||||
// cancellable, which frida's blocking attach/connect uses.
|
||||
rz_cons_break_push(frida_cancel_on_break, session);
|
||||
rz_interrupt_break_push(core->intr, frida_cancel_on_break, session);
|
||||
bool opened = rz_frida_backend_open(session, pj);
|
||||
rz_cons_break_pop();
|
||||
rz_interrupt_break_pop(core->intr);
|
||||
if (!opened) {
|
||||
rz_frida_session_free(session);
|
||||
return RZ_CMD_STATUS_OK;
|
||||
@@ -314,9 +314,9 @@ RZ_IPI RzCmdStatus rz_cmd_fridae_handler(RZ_NONNULL RzCore *core, RZ_UNUSED int
|
||||
return RZ_CMD_STATUS_OK;
|
||||
}
|
||||
|
||||
rz_cons_break_push(frida_cancel_on_break, ctx->session);
|
||||
rz_interrupt_break_push(core->intr, frida_cancel_on_break, ctx->session);
|
||||
rz_frida_backend_eval(ctx->session, argv[1], pj);
|
||||
rz_cons_break_pop();
|
||||
rz_interrupt_break_pop(core->intr);
|
||||
return RZ_CMD_STATUS_OK;
|
||||
}
|
||||
|
||||
@@ -338,9 +338,9 @@ RZ_IPI RzCmdStatus rz_cmd_fridal_handler(RZ_NONNULL RzCore *core, RZ_UNUSED int
|
||||
rz_frida_json_error(pj, RZ_FRIDA_ERROR_INVALID_TARGET, "cannot read the script file");
|
||||
return RZ_CMD_STATUS_OK;
|
||||
}
|
||||
rz_cons_break_push(frida_cancel_on_break, ctx->session);
|
||||
rz_interrupt_break_push(core->intr, frida_cancel_on_break, ctx->session);
|
||||
rz_frida_backend_eval(ctx->session, source, pj);
|
||||
rz_cons_break_pop();
|
||||
rz_interrupt_break_pop(core->intr);
|
||||
free(source);
|
||||
return RZ_CMD_STATUS_OK;
|
||||
}
|
||||
@@ -358,9 +358,9 @@ RZ_IPI RzCmdStatus rz_cmd_fridai_handler(RZ_NONNULL RzCore *core, RZ_UNUSED int
|
||||
return RZ_CMD_STATUS_OK;
|
||||
}
|
||||
|
||||
rz_cons_break_push(frida_cancel_on_break, ctx->session);
|
||||
rz_interrupt_break_push(core->intr, frida_cancel_on_break, ctx->session);
|
||||
rz_frida_backend_ping(ctx->session, pj);
|
||||
rz_cons_break_pop();
|
||||
rz_interrupt_break_pop(core->intr);
|
||||
return RZ_CMD_STATUS_OK;
|
||||
}
|
||||
|
||||
@@ -401,9 +401,9 @@ RZ_IPI RzCmdStatus rz_cmd_fridax_handler(RZ_NONNULL RzCore *core, RZ_UNUSED int
|
||||
}
|
||||
|
||||
ut64 address = rz_num_math(core->num, argv[1]);
|
||||
rz_cons_break_push(frida_cancel_on_break, ctx->session);
|
||||
rz_interrupt_break_push(core->intr, frida_cancel_on_break, ctx->session);
|
||||
rz_frida_backend_mem_read(ctx->session, address, size, pj);
|
||||
rz_cons_break_pop();
|
||||
rz_interrupt_break_pop(core->intr);
|
||||
return RZ_CMD_STATUS_OK;
|
||||
}
|
||||
|
||||
@@ -478,9 +478,9 @@ RZ_IPI RzCmdStatus rz_cmd_fridaw_handler(RZ_NONNULL RzCore *core, RZ_UNUSED int
|
||||
return RZ_CMD_STATUS_OK;
|
||||
}
|
||||
ut64 address = rz_num_math(core->num, argv[1]);
|
||||
rz_cons_break_push(frida_cancel_on_break, ctx->session);
|
||||
rz_interrupt_break_push(core->intr, frida_cancel_on_break, ctx->session);
|
||||
rz_frida_backend_mem_write(ctx->session, address, bytes, (size_t)len, pj);
|
||||
rz_cons_break_pop();
|
||||
rz_interrupt_break_pop(core->intr);
|
||||
free(bytes);
|
||||
return RZ_CMD_STATUS_OK;
|
||||
}
|
||||
@@ -500,9 +500,9 @@ RZ_IPI RzCmdStatus rz_cmd_fridaR_handler(RZ_NONNULL RzCore *core, int argc, RZ_N
|
||||
|
||||
// any arg forces a fresh enumeration instead of cached ranges.
|
||||
bool refresh = (argc > 1) && RZ_STR_ISNOTEMPTY(argv[1]);
|
||||
rz_cons_break_push(frida_cancel_on_break, ctx->session);
|
||||
rz_interrupt_break_push(core->intr, frida_cancel_on_break, ctx->session);
|
||||
rz_frida_backend_ranges(ctx->session, refresh, pj);
|
||||
rz_cons_break_pop();
|
||||
rz_interrupt_break_pop(core->intr);
|
||||
return RZ_CMD_STATUS_OK;
|
||||
}
|
||||
|
||||
@@ -519,9 +519,9 @@ RZ_IPI RzCmdStatus rz_cmd_fridat_handler(RZ_NONNULL RzCore *core, RZ_UNUSED int
|
||||
return RZ_CMD_STATUS_OK;
|
||||
}
|
||||
|
||||
rz_cons_break_push(frida_cancel_on_break, ctx->session);
|
||||
rz_interrupt_break_push(core->intr, frida_cancel_on_break, ctx->session);
|
||||
rz_frida_backend_threads(ctx->session, pj);
|
||||
rz_cons_break_pop();
|
||||
rz_interrupt_break_pop(core->intr);
|
||||
return RZ_CMD_STATUS_OK;
|
||||
}
|
||||
|
||||
@@ -540,9 +540,9 @@ RZ_IPI RzCmdStatus rz_cmd_fridaM_handler(RZ_NONNULL RzCore *core, int argc, RZ_N
|
||||
|
||||
// any arg forces fresh enum instead of cached modules.
|
||||
bool refresh = (argc > 1) && RZ_STR_ISNOTEMPTY(argv[1]);
|
||||
rz_cons_break_push(frida_cancel_on_break, ctx->session);
|
||||
rz_interrupt_break_push(core->intr, frida_cancel_on_break, ctx->session);
|
||||
rz_frida_backend_modules(ctx->session, refresh, pj);
|
||||
rz_cons_break_pop();
|
||||
rz_interrupt_break_pop(core->intr);
|
||||
return RZ_CMD_STATUS_OK;
|
||||
}
|
||||
|
||||
@@ -559,9 +559,9 @@ RZ_IPI RzCmdStatus rz_cmd_fridaE_handler(RZ_NONNULL RzCore *core, RZ_UNUSED int
|
||||
return RZ_CMD_STATUS_OK;
|
||||
}
|
||||
|
||||
rz_cons_break_push(frida_cancel_on_break, ctx->session);
|
||||
rz_interrupt_break_push(core->intr, frida_cancel_on_break, ctx->session);
|
||||
rz_frida_backend_exports(ctx->session, argv[1], pj);
|
||||
rz_cons_break_pop();
|
||||
rz_interrupt_break_pop(core->intr);
|
||||
return RZ_CMD_STATUS_OK;
|
||||
}
|
||||
|
||||
@@ -578,9 +578,9 @@ RZ_IPI RzCmdStatus rz_cmd_fridaI_handler(RZ_NONNULL RzCore *core, RZ_UNUSED int
|
||||
return RZ_CMD_STATUS_OK;
|
||||
}
|
||||
|
||||
rz_cons_break_push(frida_cancel_on_break, ctx->session);
|
||||
rz_interrupt_break_push(core->intr, frida_cancel_on_break, ctx->session);
|
||||
rz_frida_backend_imports(ctx->session, argv[1], pj);
|
||||
rz_cons_break_pop();
|
||||
rz_interrupt_break_pop(core->intr);
|
||||
return RZ_CMD_STATUS_OK;
|
||||
}
|
||||
|
||||
@@ -597,9 +597,9 @@ RZ_IPI RzCmdStatus rz_cmd_fridaS_handler(RZ_NONNULL RzCore *core, RZ_UNUSED int
|
||||
return RZ_CMD_STATUS_OK;
|
||||
}
|
||||
|
||||
rz_cons_break_push(frida_cancel_on_break, ctx->session);
|
||||
rz_interrupt_break_push(core->intr, frida_cancel_on_break, ctx->session);
|
||||
rz_frida_backend_symbols(ctx->session, argv[1], pj);
|
||||
rz_cons_break_pop();
|
||||
rz_interrupt_break_pop(core->intr);
|
||||
return RZ_CMD_STATUS_OK;
|
||||
}
|
||||
|
||||
@@ -617,14 +617,14 @@ RZ_IPI RzCmdStatus rz_cmd_fridab_handler(RZ_NONNULL RzCore *core, int argc, RZ_N
|
||||
}
|
||||
|
||||
// an addr sets a breakpoint, no arg lists the current breakpoints.
|
||||
rz_cons_break_push(frida_cancel_on_break, ctx->session);
|
||||
rz_interrupt_break_push(core->intr, frida_cancel_on_break, ctx->session);
|
||||
if (argc > 1 && RZ_STR_ISNOTEMPTY(argv[1])) {
|
||||
ut64 address = rz_num_math(core->num, argv[1]);
|
||||
rz_frida_backend_bp_set(ctx->session, address, pj);
|
||||
} else {
|
||||
rz_frida_backend_bp_list(ctx->session, pj);
|
||||
}
|
||||
rz_cons_break_pop();
|
||||
rz_interrupt_break_pop(core->intr);
|
||||
return RZ_CMD_STATUS_OK;
|
||||
}
|
||||
|
||||
@@ -648,9 +648,9 @@ RZ_IPI RzCmdStatus rz_cmd_fridab_minus_handler(RZ_NONNULL RzCore *core, RZ_UNUSE
|
||||
rz_strf(address_str, "0x%" PFMT64x, address);
|
||||
target = address_str;
|
||||
}
|
||||
rz_cons_break_push(frida_cancel_on_break, ctx->session);
|
||||
rz_interrupt_break_push(core->intr, frida_cancel_on_break, ctx->session);
|
||||
rz_frida_backend_bp_remove(ctx->session, target, pj);
|
||||
rz_cons_break_pop();
|
||||
rz_interrupt_break_pop(core->intr);
|
||||
return RZ_CMD_STATUS_OK;
|
||||
}
|
||||
|
||||
@@ -674,9 +674,9 @@ RZ_IPI RzCmdStatus rz_cmd_fridag_handler(RZ_NONNULL RzCore *core, int argc, RZ_N
|
||||
rz_strf(tid, "%" PFMT64u, rz_num_math(core->num, argv[1]));
|
||||
thread_id = tid;
|
||||
}
|
||||
rz_cons_break_push(frida_cancel_on_break, ctx->session);
|
||||
rz_interrupt_break_push(core->intr, frida_cancel_on_break, ctx->session);
|
||||
rz_frida_backend_continue(ctx->session, thread_id, pj);
|
||||
rz_cons_break_pop();
|
||||
rz_interrupt_break_pop(core->intr);
|
||||
return RZ_CMD_STATUS_OK;
|
||||
}
|
||||
|
||||
@@ -694,7 +694,7 @@ RZ_IPI RzCmdStatus rz_cmd_fridaB_handler(RZ_NONNULL RzCore *core, int argc, RZ_N
|
||||
}
|
||||
|
||||
ut64 thread_id = rz_num_math(core->num, argv[1]);
|
||||
rz_cons_break_push(frida_cancel_on_break, ctx->session);
|
||||
rz_interrupt_break_push(core->intr, frida_cancel_on_break, ctx->session);
|
||||
if (argc > 3) {
|
||||
char value_str[32];
|
||||
rz_strf(value_str, "0x%" PFMT64x, rz_num_math(core->num, argv[3]));
|
||||
@@ -704,7 +704,7 @@ RZ_IPI RzCmdStatus rz_cmd_fridaB_handler(RZ_NONNULL RzCore *core, int argc, RZ_N
|
||||
} else {
|
||||
rz_frida_backend_reg_read(ctx->session, thread_id, pj);
|
||||
}
|
||||
rz_cons_break_pop();
|
||||
rz_interrupt_break_pop(core->intr);
|
||||
return RZ_CMD_STATUS_OK;
|
||||
}
|
||||
|
||||
@@ -722,7 +722,7 @@ RZ_IPI RzCmdStatus rz_cmd_fridaW_handler(RZ_NONNULL RzCore *core, int argc, RZ_N
|
||||
}
|
||||
|
||||
// addr sets watchpoint, no arg lists current wps.
|
||||
rz_cons_break_push(frida_cancel_on_break, ctx->session);
|
||||
rz_interrupt_break_push(core->intr, frida_cancel_on_break, ctx->session);
|
||||
if (argc > 1 && RZ_STR_ISNOTEMPTY(argv[1])) {
|
||||
ut64 address = rz_num_math(core->num, argv[1]);
|
||||
ut64 size = (argc > 2) ? rz_num_math(core->num, argv[2]) : 0;
|
||||
@@ -732,7 +732,7 @@ RZ_IPI RzCmdStatus rz_cmd_fridaW_handler(RZ_NONNULL RzCore *core, int argc, RZ_N
|
||||
} else {
|
||||
rz_frida_backend_wp_list(ctx->session, pj);
|
||||
}
|
||||
rz_cons_break_pop();
|
||||
rz_interrupt_break_pop(core->intr);
|
||||
return RZ_CMD_STATUS_OK;
|
||||
}
|
||||
|
||||
@@ -756,9 +756,9 @@ RZ_IPI RzCmdStatus rz_cmd_fridaW_minus_handler(RZ_NONNULL RzCore *core, RZ_UNUSE
|
||||
rz_strf(address_str, "0x%" PFMT64x, address);
|
||||
target = address_str;
|
||||
}
|
||||
rz_cons_break_push(frida_cancel_on_break, ctx->session);
|
||||
rz_interrupt_break_push(core->intr, frida_cancel_on_break, ctx->session);
|
||||
rz_frida_backend_wp_remove(ctx->session, target, pj);
|
||||
rz_cons_break_pop();
|
||||
rz_interrupt_break_pop(core->intr);
|
||||
return RZ_CMD_STATUS_OK;
|
||||
}
|
||||
|
||||
@@ -773,9 +773,9 @@ RZ_IPI RzCmdStatus rz_cmd_fridaJ_handler(RZ_NONNULL RzCore *core, RZ_UNUSED int
|
||||
rz_frida_json_error(pj, RZ_FRIDA_ERROR_INVALID_TARGET, "no session is open");
|
||||
return RZ_CMD_STATUS_OK;
|
||||
}
|
||||
rz_cons_break_push(frida_cancel_on_break, ctx->session);
|
||||
rz_interrupt_break_push(core->intr, frida_cancel_on_break, ctx->session);
|
||||
rz_frida_backend_java_available(ctx->session, pj);
|
||||
rz_cons_break_pop();
|
||||
rz_interrupt_break_pop(core->intr);
|
||||
return RZ_CMD_STATUS_OK;
|
||||
}
|
||||
|
||||
@@ -790,9 +790,9 @@ RZ_IPI RzCmdStatus rz_cmd_fridaL_handler(RZ_NONNULL RzCore *core, RZ_UNUSED int
|
||||
rz_frida_json_error(pj, RZ_FRIDA_ERROR_INVALID_TARGET, "no session is open");
|
||||
return RZ_CMD_STATUS_OK;
|
||||
}
|
||||
rz_cons_break_push(frida_cancel_on_break, ctx->session);
|
||||
rz_interrupt_break_push(core->intr, frida_cancel_on_break, ctx->session);
|
||||
rz_frida_backend_loaders(ctx->session, pj);
|
||||
rz_cons_break_pop();
|
||||
rz_interrupt_break_pop(core->intr);
|
||||
return RZ_CMD_STATUS_OK;
|
||||
}
|
||||
|
||||
@@ -810,9 +810,9 @@ RZ_IPI RzCmdStatus rz_cmd_fridaC_handler(RZ_NONNULL RzCore *core, int argc,
|
||||
}
|
||||
const char *prefix = (argc > 1 && RZ_STR_ISNOTEMPTY(argv[1])) ? argv[1] : NULL;
|
||||
ut64 max = rz_config_get_integer(core->config, "frida.java.max");
|
||||
rz_cons_break_push(frida_cancel_on_break, ctx->session);
|
||||
rz_interrupt_break_push(core->intr, frida_cancel_on_break, ctx->session);
|
||||
rz_frida_backend_classes(ctx->session, prefix, max, pj);
|
||||
rz_cons_break_pop();
|
||||
rz_interrupt_break_pop(core->intr);
|
||||
return RZ_CMD_STATUS_OK;
|
||||
}
|
||||
|
||||
@@ -829,7 +829,7 @@ RZ_IPI RzCmdStatus rz_cmd_fridaN_handler(RZ_NONNULL RzCore *core, int argc,
|
||||
return RZ_CMD_STATUS_OK;
|
||||
}
|
||||
bool enable = true;
|
||||
rz_cons_break_push(frida_cancel_on_break, ctx->session);
|
||||
rz_interrupt_break_push(core->intr, frida_cancel_on_break, ctx->session);
|
||||
if (argc > 1 && RZ_STR_ISNOTEMPTY(argv[1])) {
|
||||
if (RZ_STR_EQ(argv[1], "start")) {
|
||||
enable = true;
|
||||
@@ -838,14 +838,14 @@ RZ_IPI RzCmdStatus rz_cmd_fridaN_handler(RZ_NONNULL RzCore *core, int argc,
|
||||
} else {
|
||||
rz_frida_json_error(pj, RZ_FRIDA_ERROR_INVALID_TARGET,
|
||||
"FrNj expects start, stop, or no arguments to list");
|
||||
rz_cons_break_pop();
|
||||
rz_interrupt_break_pop(core->intr);
|
||||
return RZ_CMD_STATUS_OK;
|
||||
}
|
||||
rz_frida_backend_class_load_monitor(ctx->session, enable, pj);
|
||||
} else {
|
||||
rz_frida_backend_newly_loaded_classes(ctx->session, pj);
|
||||
}
|
||||
rz_cons_break_pop();
|
||||
rz_interrupt_break_pop(core->intr);
|
||||
return RZ_CMD_STATUS_OK;
|
||||
}
|
||||
|
||||
@@ -861,7 +861,7 @@ RZ_IPI RzCmdStatus rz_cmd_fridaRN_handler(RZ_NONNULL RzCore *core, int argc,
|
||||
rz_frida_json_error(pj, RZ_FRIDA_ERROR_INVALID_TARGET, "no session is open");
|
||||
return RZ_CMD_STATUS_OK;
|
||||
}
|
||||
rz_cons_break_push(frida_cancel_on_break, ctx->session);
|
||||
rz_interrupt_break_push(core->intr, frida_cancel_on_break, ctx->session);
|
||||
if (argc > 1 && RZ_STR_ISNOTEMPTY(argv[1])) {
|
||||
if (RZ_STR_EQ(argv[1], "on")) {
|
||||
rz_frida_backend_rn_set(ctx->session, true, pj);
|
||||
@@ -872,13 +872,13 @@ RZ_IPI RzCmdStatus rz_cmd_fridaRN_handler(RZ_NONNULL RzCore *core, int argc,
|
||||
} else {
|
||||
rz_frida_json_error(pj, RZ_FRIDA_ERROR_INVALID_TARGET,
|
||||
"FrRNj expects on, off, import, or no arguments to list");
|
||||
rz_cons_break_pop();
|
||||
rz_interrupt_break_pop(core->intr);
|
||||
return RZ_CMD_STATUS_OK;
|
||||
}
|
||||
} else {
|
||||
rz_frida_backend_rn_list(ctx->session, pj);
|
||||
}
|
||||
rz_cons_break_pop();
|
||||
rz_interrupt_break_pop(core->intr);
|
||||
return RZ_CMD_STATUS_OK;
|
||||
}
|
||||
|
||||
@@ -894,9 +894,9 @@ RZ_IPI RzCmdStatus rz_cmd_fridaf_handler(RZ_NONNULL RzCore *core, RZ_UNUSED int
|
||||
rz_frida_json_error(pj, RZ_FRIDA_ERROR_INVALID_TARGET, "no session is open");
|
||||
return RZ_CMD_STATUS_OK;
|
||||
}
|
||||
rz_cons_break_push(frida_cancel_on_break, ctx->session);
|
||||
rz_interrupt_break_push(core->intr, frida_cancel_on_break, ctx->session);
|
||||
rz_frida_backend_flag_import(ctx->session, core, pj);
|
||||
rz_cons_break_pop();
|
||||
rz_interrupt_break_pop(core->intr);
|
||||
return RZ_CMD_STATUS_OK;
|
||||
}
|
||||
|
||||
@@ -913,9 +913,9 @@ RZ_IPI RzCmdStatus rz_cmd_fridaX_handler(RZ_NONNULL RzCore *core, int argc,
|
||||
return RZ_CMD_STATUS_OK;
|
||||
}
|
||||
const char *prefix = (argc > 1 && RZ_STR_ISNOTEMPTY(argv[1])) ? argv[1] : NULL;
|
||||
rz_cons_break_push(frida_cancel_on_break, ctx->session);
|
||||
rz_interrupt_break_push(core->intr, frida_cancel_on_break, ctx->session);
|
||||
rz_frida_backend_dex_diff(ctx->session, core, prefix, pj);
|
||||
rz_cons_break_pop();
|
||||
rz_interrupt_break_pop(core->intr);
|
||||
return RZ_CMD_STATUS_OK;
|
||||
}
|
||||
|
||||
@@ -940,9 +940,9 @@ RZ_IPI RzCmdStatus rz_cmd_fridaD_handler(RZ_NONNULL RzCore *core, int argc,
|
||||
if (argc > 2 && RZ_STR_ISNOTEMPTY(argv[2])) {
|
||||
loaderId = rz_num_math(core->num, argv[2]);
|
||||
}
|
||||
rz_cons_break_push(frida_cancel_on_break, ctx->session);
|
||||
rz_interrupt_break_push(core->intr, frida_cancel_on_break, ctx->session);
|
||||
rz_frida_backend_class_describe(ctx->session, className, loaderId, pj);
|
||||
rz_cons_break_pop();
|
||||
rz_interrupt_break_pop(core->intr);
|
||||
return RZ_CMD_STATUS_OK;
|
||||
}
|
||||
|
||||
@@ -969,7 +969,7 @@ RZ_IPI RzCmdStatus rz_cmd_fridaIm_handler(RZ_NONNULL RzCore *core, int argc,
|
||||
}
|
||||
|
||||
bool has_dot = (strchr(className, '.') != NULL);
|
||||
rz_cons_break_push(frida_cancel_on_break, ctx->session);
|
||||
rz_interrupt_break_push(core->intr, frida_cancel_on_break, ctx->session);
|
||||
if (has_dot) {
|
||||
rz_frida_backend_import_class(ctx->session, core, className, loaderId, pj);
|
||||
} else {
|
||||
@@ -983,7 +983,7 @@ RZ_IPI RzCmdStatus rz_cmd_fridaIm_handler(RZ_NONNULL RzCore *core, int argc,
|
||||
}
|
||||
rz_frida_json_error(pj, RZ_FRIDA_ERROR_INVALID_TARGET,
|
||||
"no matching classes found for the given prefix");
|
||||
rz_cons_break_pop();
|
||||
rz_interrupt_break_pop(core->intr);
|
||||
return RZ_CMD_STATUS_OK;
|
||||
}
|
||||
|
||||
@@ -1026,7 +1026,7 @@ RZ_IPI RzCmdStatus rz_cmd_fridaIm_handler(RZ_NONNULL RzCore *core, int argc,
|
||||
pj_kn(pj, "constructors", (ut64)total_c);
|
||||
rz_frida_json_ok_end(pj);
|
||||
}
|
||||
rz_cons_break_pop();
|
||||
rz_interrupt_break_pop(core->intr);
|
||||
return RZ_CMD_STATUS_OK;
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user