2 Commits
Author SHA1 Message Date
Anton Kochkov 7172f6e9ba ci: install pkg-config on macOS worker 2023-08-02 18:01:23 +08:00
Anton Kochkov 66dd4bf9e9 Build multiarch wheels 2023-08-02 17:21:13 +08:00
34 changed files with 190 additions and 569 deletions

No files matched your search

-7
View File
@@ -1,7 +0,0 @@
version: 2
updates:
- package-ecosystem: github-actions
directory: "/"
schedule:
interval: "weekly"
+19 -103
View File
@@ -1,137 +1,53 @@
name: build
name: run-rz-bindgen
on:
push:
branches:
- dev
- stable
- 'ci-*'
pull_request:
workflow_dispatch:
workflow_call:
inputs:
external_call:
description: 'To distinguish workflow_call from regular push'
type: boolean
required: false
default: true
rizin_ref:
required: false
type: string
default: 'dev'
jobs:
pypa-wheels:
run-bindgen:
name: Run bindgen
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-24.04, windows-2022, macos-14]
os: [ubuntu-latest, windows-2019, macos-latest]
steps:
- name: Install SWIG with Homebrew
if: matrix.os == 'macos-14' && matrix.enabled
run: brew install swig
- name: Checkout rz-bindgen
uses: actions/checkout@v6
uses: actions/checkout@v3
# runned only from workflow_call
- name: Checkout rizin
if: ${{ inputs.external_call }}
uses: actions/checkout@v6
uses: actions/checkout@v3
with:
repository: rizinorg/rizin
path: rizin
ref: ${{ inputs.rizin_ref }}
- name: Install pkg-config with Homebrew
if: matrix.os == 'macos-latest'
run: brew install pkg-config
- name: Checkout rizin (stable)
if: ${{ !inputs.external_call && ((github.ref_name == 'stable') || (github.base_ref == 'stable')) }}
uses: actions/checkout@v6
with:
repository: rizinorg/rizin
path: rizin
ref: stable
- name: Checkout rizin (dev)
if: ${{ !inputs.external_call && ((github.ref_name != 'stable') && (github.base_ref != 'stable')) }}
uses: actions/checkout@v6
with:
repository: rizinorg/rizin
path: rizin
ref: dev
- name: Build rz-bindgen
uses: pypa/[email protected]
- name: Run rz-bindgen
uses: pypa/[email protected]
env:
CIBW_ARCHS_MACOS: x86_64 arm64 universal2
CIBW_ARCHS_LINUX: auto aarch64 ppc64le s390x
- name: Upload sdist
uses: actions/upload-artifact@v7
uses: actions/upload-artifact@v3
with:
name: sdist-${{ matrix.os }}
name: sdist
path: dist/*.tar.gz
- name: Upload wheels
uses: actions/upload-artifact@v7
uses: actions/upload-artifact@v3
with:
name: wheels-${{ matrix.os }}
name: wheels
path: wheelhouse/*.whl
ubuntu-default-llvm:
runs-on: ubuntu-24.04
steps:
- name: Checkout rz-bindgen
uses: actions/checkout@v6
with:
path: rz-bindgen
# runned only from workflow_call
- name: Checkout rizin
if: ${{ inputs.external_call }}
uses: actions/checkout@v6
with:
repository: rizinorg/rizin
path: rizin
ref: ${{ inputs.rizin_ref }}
- name: Checkout rizin (stable)
if: ${{ !inputs.external_call && ((github.ref_name == 'stable') || (github.base_ref == 'stable')) }}
uses: actions/checkout@v6
with:
repository: rizinorg/rizin
path: rizin
ref: stable
- name: Checkout rizin (dev)
if: ${{ !inputs.external_call && ((github.ref_name != 'stable') && (github.base_ref != 'stable')) }}
uses: actions/checkout@v6
with:
repository: rizinorg/rizin
path: rizin
ref: dev
- name: Install dependencies
run: |
sudo apt update
sudo apt-get --assume-yes install cmake swig pkg-config clang libclang-dev llvm wget unzip python3-wheel python3-setuptools build-essential python3-pip
sudo pip3 install meson ninja
- name: Install rizin
run: |
export PATH=$PATH:/usr/local/bin
meson setup --prefix=/usr --buildtype=release build && ninja -C build && sudo ninja -C build install
working-directory: rizin
- name: Build rz-bindgen
run: |
meson setup --prefix=/usr -Dplugin=enabled build
meson compile -C build
sudo meson install -C build
working-directory: rz-bindgen
- name: Test python lang plugin
run: rizin -qc "Ll" | grep "Python SWIG"
- name: Run rz-test
run: rz-test -L tests/
working-directory: rz-bindgen
+12 -18
View File
@@ -1,31 +1,25 @@
name: lint
on:
push:
branches:
- dev
- stable
- 'ci-*'
pull_request:
name: linting
on: push
jobs:
licenses:
runs-on: ubuntu-24.04
runs-on: ubuntu-latest
steps:
- name: Checkout rz-bindgen
uses: actions/checkout@v6
uses: actions/checkout@v3
- name: REUSE compliance check
uses: fsfe/reuse-action@v6
uses: fsfe/reuse-action@v1
python:
runs-on: ubuntu-24.04
runs-on: ubuntu-latest
steps:
- name: Checkout rz-bindgen
uses: actions/checkout@v6
uses: actions/checkout@v3
- name: Install tools
run: |
pip install mypy pyflakes pylint black
- name: Run mypy
run: |
mypy --disable-error-code misc src/main.py
mypy src/main.py
if: ${{ always() }}
- name: Run pyflakes
run: |
@@ -41,15 +35,15 @@ jobs:
if: ${{ always() }}
codeql:
runs-on: ubuntu-24.04
runs-on: ubuntu-latest
permissions:
security-events: write
steps:
- name: Checkout rz-bindgen
uses: actions/checkout@v6
uses: actions/checkout@v3
- name: Initialize CodeQL
uses: github/codeql-action/init@v4
uses: github/codeql-action/init@v2
with:
languages: python
- name: Run CodeQL
uses: github/codeql-action/analyze@v4
uses: github/codeql-action/analyze@v2
+9 -8
View File
@@ -1,4 +1,4 @@
name: release
name: release-rz-bindgen
on:
push:
tags:
@@ -7,34 +7,35 @@ on:
jobs:
extract-rizin-version:
runs-on: ubuntu-24.04
runs-on: ubuntu-latest
outputs:
rizin_version: ${{ steps.extract_version.outputs.result }}
steps:
- id: extract_version
run: echo "result=$(echo ${{ github.ref }} | cut -d'_' -f1 | cut -d'-' -f2-)" >> "$GITHUB_OUTPUT"
build:
run-bindgen:
uses: ./.github/workflows/ci.yml
needs: [extract-rizin-version]
with:
rizin_ref: ${{ needs.extract-rizin-version.outputs.rizin_version }}
publish-pypi:
runs-on: ubuntu-24.04
needs: [build]
name: Publish PyPi
runs-on: ubuntu-latest
needs: [run-bindgen]
steps:
- name: Download artifacts
uses: actions/download-artifact@v8
uses: actions/download-artifact@v3
with:
name: wheels
path: dist
- name: Download sdist
uses: actions/download-artifact@v8
uses: actions/download-artifact@v3
with:
name: sdist
path: dist
- name: Publish wheels
uses: pypa/gh-action-pypi-publish@v1.14.0
uses: pypa/gh-action-pypi-publish@v1.5.1
with:
password: ${{ secrets.PYPI_TOKEN }}
+32
View File
@@ -0,0 +1,32 @@
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: rz-bindgen
Upstream-Contact: wingdeans <[email protected]>
Source: https://github.com/rizinorg/rz-bindgen/
Files: src/clang/__init__.py src/clang/cindex.py src/clang/enumerations.py
Copyright: 2022 The LLVM Project
License: Apache-2.0 WITH LLVM-exception
Files: src/snippets_swig/*
Copyright: 2022 wingdeans <[email protected]>
License: LGPL-3.0-only
Files: .github/workflows/* .gitignore README.md src/README.md
Copyright: 2022 wingdeans <[email protected]>
License: LGPL-3.0-only
Files: meson.build plugin/meson.build meson_options.txt
Copyright: 2022 wingdeans <[email protected]>
License: LGPL-3.0-only
Files: pyproject.toml mypy.ini pylintrc
Copyright: 2022 wingdeans <[email protected]>
License: LGPL-3.0-only
Files: cutter/PythonConsole.ui cutter/CMakeLists.txt .clang-format
Copyright: 2022 wingdeans <[email protected]>
License: LGPL-3.0-only
Files: doc/*.md
Copyright: 2022 wingdeans <[email protected]>
License: LGPL-3.0-only
+2 -2
View File
@@ -9,9 +9,9 @@ For usage information, see [the documentation](doc/README.md).
## Building python plugin
Requirements:
- rizin > 0.4.1 (needs commit [59b38e6](https://github.com/rizinorg/rizin/commit/59b38e6efaf00b9b9869e0ec5baba4f1b9605f37))
- meson >= 1.1.0
- meson
- ninja
- python >= 3.10
- python >= 3.7
- libclang
- SWIG
-58
View File
@@ -1,58 +0,0 @@
version = 1
SPDX-PackageName = "rz-bindgen"
SPDX-PackageSupplier = "wingdeans <[email protected]>"
SPDX-PackageDownloadLocation = "https://github.com/rizinorg/rz-bindgen/"
[[annotations]]
path = ["src/clang/__init__.py", "src/clang/cindex.py", "src/clang/enumerations.py"]
precedence = "aggregate"
SPDX-FileCopyrightText = "2022 The LLVM Project"
SPDX-License-Identifier = "Apache-2.0 WITH LLVM-exception"
[[annotations]]
path = "src/snippets_swig/**"
precedence = "aggregate"
SPDX-FileCopyrightText = "2022 wingdeans <[email protected]>"
SPDX-License-Identifier = "LGPL-3.0-only"
[[annotations]]
path = [".github/workflows/**", ".gitignore", "README.md", "src/README.md"]
precedence = "aggregate"
SPDX-FileCopyrightText = "2022 wingdeans <[email protected]>"
SPDX-License-Identifier = "LGPL-3.0-only"
[[annotations]]
path = ["meson.build", "plugin/meson.build", "meson_options.txt"]
precedence = "aggregate"
SPDX-FileCopyrightText = "2022 wingdeans <[email protected]>"
SPDX-License-Identifier = "LGPL-3.0-only"
[[annotations]]
path = ["pyproject.toml", "mypy.ini", "pylintrc"]
precedence = "aggregate"
SPDX-FileCopyrightText = "2022 wingdeans <[email protected]>"
SPDX-License-Identifier = "LGPL-3.0-only"
[[annotations]]
path = ["cutter/PythonConsole.ui", "cutter/CMakeLists.txt", ".clang-format"]
precedence = "aggregate"
SPDX-FileCopyrightText = "2022 wingdeans <[email protected]>"
SPDX-License-Identifier = "LGPL-3.0-only"
[[annotations]]
path = "doc/**.md"
precedence = "aggregate"
SPDX-FileCopyrightText = "2022 wingdeans <[email protected]>"
SPDX-License-Identifier = "LGPL-3.0-only"
[[annotations]]
path = "tests/**"
precedence = "aggregate"
SPDX-FileCopyrightText = "2026 RizinOrg <[email protected]>"
SPDX-License-Identifier = "LGPL-3.0-only"
[[annotations]]
path = ".github/**"
precedence = "aggregate"
SPDX-FileCopyrightText = "2026 RizinOrg <[email protected]>"
SPDX-License-Identifier = "LGPL-3.0-only"
+6 -22
View File
@@ -4,48 +4,32 @@
set -ex
# Install deps
pygt311=$(python3 -c 'import sys; print(0) if sys.version_info.minor > 11 else print(1)' 2>&1)
if [[ $pygt311 == '0' ]]; then
pip3 install --break-system-packages meson ninja meson-python build
else
pip3 install meson ninja meson-python build
fi
pip3 install meson ninja meson-python build
if command -v brew; then
brew install --require-sha swig
elif command -v apt; then
if command -v apt; then
set +e
grep VERSION_CODENAME=stretch /etc/os-release >/dev/null 2>/dev/null
if [[ $? == 0 ]] ; then
# Required because manylinux_2_24 uses Debian Stretch and the repos are not available anymore
# Required because manylinux_2_24 uses Debian Stretch and the repos are not available anymore
echo "deb http://archive.debian.org/debian stretch main" > /etc/apt/sources.list
echo "deb http://archive.debian.org/debian-security stretch/updates main" >> /etc/apt/sources.list
echo "Acquire::Check-Valid-Until no;" > /etc/apt/apt.conf.d/99no-check-valid-until
fi
set -e
apt update && apt install --assume-yes libclang-7-dev clang-7 llvm-7 sudo
apt update && apt install --assume-yes libclang-7-dev clang-7 llvm-7
elif command -v apk; then
apk update && apk add clang-dev sudo
elif command -v yum; then
yum -y install llvm-toolset-7.0 llvm-toolset-7.0-llvm-devel sudo
# (CentOS 7) Uncomment following lines to see required paths in build log:
# yum -y install centos-release-scl
# source scl_source enable llvm-toolset-7.0 || true
apk update && apk add clang-dev
fi
pushd rizin
if [[ "$OSTYPE" =~ msys* ]]; then
meson setup --buildtype=release --prefix='c:/rizin' --vsenv build
meson install -C build
else
if [[ "$OSTYPE" =~ linux* ]]; then
export CFLAGS="-include linux/limits.h"
fi
meson setup --buildtype=release --libdir=lib build
sudo PATH="$PATH" bash -c "meson install -C build"
fi
meson install -C build
popd
if command -v apt; then
+3 -5
View File
@@ -50,7 +50,6 @@ In the SWIG bindings, these functions are mapped to methods of RzCore.
```py
import rizin
from rizin import RZ_CORE_CMD_EXIT as CMD_EXIT
from sys import argv
filename = argv[1]
@@ -67,8 +66,8 @@ for i, corefile in enumerate(core.files):
for binfile in corefile.binfiles:
print(f" * {binfile.file}")
while core.flush(input("rizin> ")) != CMD_EXIT:
pass
while True:
core.flush(input("rizin> "))
```
Here's an example session:
@@ -87,11 +86,10 @@ rizin> aaa
[x] Applied 0 FLIRT signatures via sigdb
[x] Propagate noreturn information
[x] Use -AA or aaaa to perform additional experimental analysis.
rizin> afl
> afl
0x0040233e 1 6 entry0
0x00402051 3 49 -> 16 sym.HelloWorld::Main
0x0040205f 99 24482 -> 31854 sym.HelloWorld::.ctor
rizin> q
```
### Plugins
+2 -3
View File
@@ -4,7 +4,6 @@ SPDX-License-Identifier: LGPL-3.0-only
"""
import rizin
from rizin import RZ_CORE_CMD_EXIT as CMD_EXIT
from sys import argv
filename = argv[1]
@@ -21,5 +20,5 @@ for i, corefile in enumerate(core.files):
for binfile in corefile.binfiles:
print(f" * {binfile.file}")
while core.flush(input("rizin> ")) != CMD_EXIT:
pass
while True:
core.flush(input("rizin> "))
+4 -4
View File
@@ -8,10 +8,11 @@ SPDX-License-Identifier: LGPL-3.0-only
# things, see `2b-rz_bin_plugin.py`
import rizin
from rizin import RZ_CORE_CMD_EXIT as CMD_EXIT
import sys
import rizin
class CustomBinPlugin(rizin.RzBinPluginDirector):
def __init__(self):
super().__init__()
@@ -22,7 +23,6 @@ class CustomBinPlugin(rizin.RzBinPluginDirector):
print("size: ", bf.size)
return True
# Construct the director
builder = rizin.RzBinPluginBuilder()
builder.name = "SWIGCustom"
@@ -36,5 +36,5 @@ core.bin.plugins.append(plugin)
core.bin.force_plugin(plugin.name)
core.file_open_load(sys.argv[1])
while core.flush(input("rizin> ")) != CMD_EXIT:
pass
while True:
core.flush(input("> "))
+2 -3
View File
@@ -4,7 +4,6 @@ SPDX-License-Identifier: LGPL-3.0-only
"""
import rizin
from rizin import RZ_CORE_CMD_EXIT as CMD_EXIT
import sys
@@ -27,5 +26,5 @@ core.bin.plugins.append(plugin_struct)
core.bin.force_plugin(plugin.name)
core.file_open_load(sys.argv[1])
while core.flush(input("rizin> ")) != CMD_EXIT:
pass
while True:
core.flush(input("> "))
+9 -17
View File
@@ -1,7 +1,7 @@
project('rz-bindgen', 'c', 'cpp',
version: '0.6.0',
license: 'LGPL3',
meson_version: '>=0.62.2',
meson_version: '>=0.53.0',
default_options: ['python.install_env=auto'])
pymod = import('python')
@@ -19,9 +19,9 @@ target_sphinx = targets.contains('sphinx')
doxygen_path = get_option('doxygen_path')
if clang_path == ''
llvm_config = find_program('llvm-config', 'llvm-config-7', required: false)
if llvm_config.found()
clang_path = run_command(llvm_config, '--libdir', check: true).stdout().strip()
llvm = dependency('llvm', required: false)
if llvm.found()
clang_path = llvm.get_variable(cmake: 'LLVM_LIBRARY_DIRS', configtool: 'libdir', default_value: 'none')
elif build_machine.system() == 'darwin'
clang_path = '/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/'
elif build_machine.system() == 'windows'
@@ -49,7 +49,7 @@ if clang_args == ''
clang = find_program('clang', 'clang-7', required: false)
if clang.found()
clang_args += ' -resource-dir='
clang_args += '"' + run_command(clang, '-print-resource-dir', check: true).stdout().strip() + '"'
clang_args += run_command(clang, '-print-resource-dir', check: true).stdout().strip()
endif
if build_machine.system() == 'darwin'
clang_args += ' -isysroot /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk'
@@ -89,11 +89,6 @@ if target_swig or target_sphinx
'src/lint.py',
'src/main.py',
'src/writer.py',
'src/snippets_swig/cmd_director.i',
'src/snippets_swig/iterators.py',
'src/snippets_swig/prologue.i',
'src/snippets_swig/register_command.py',
'src/snippets_swig/register_swig_command.cpp',
)
bindgen_outputs = custom_target(
@@ -113,7 +108,6 @@ if target_swig or target_sphinx
endif
if target_swig
wheel = get_option('wheel')
swig_output = custom_target(
'swig_output',
input: bindgen_outputs[swig_source_idx],
@@ -123,7 +117,7 @@ if target_swig
'-python', '-c++',
'-outdir', '@OUTDIR@', '@INPUT@'
],
install: wheel or host_machine.system() == 'windows',
install: true,
install_dir: [py.get_install_dir(), false]
)
swig_py = swig_output[0]
@@ -133,18 +127,15 @@ if target_swig
rz_core = dependency('rz_core')
endif
ext_mod = py.extension_module(
py.extension_module(
'_rizin',
swig_wrap,
dependencies: [
py.dependency(),
rz_core,
],
install: wheel or host_machine.system() == 'windows',
install: true,
)
if host_machine.system() != 'windows'
meson.add_install_script('py_install.py', swig_py.full_path(), ext_mod.full_path())
endif
endif
if target_sphinx
@@ -164,3 +155,4 @@ endif
if get_option('plugin').enabled()
subdir('plugin')
endif
-1
View File
@@ -4,6 +4,5 @@ option('rizin_include_path', type: 'string', value: '')
option('targets', type: 'array', choices: ['SWIG', 'sphinx'], value: ['SWIG'])
option('plugin', type: 'feature', value: 'disabled')
option('wheel', type: 'boolean', value: false, description: 'Set up for pypa wheel build')
option('doxygen_path', type: 'string', value: '')
-7
View File
@@ -2,13 +2,6 @@
// SPDX-License-Identifier: LGPL-3.0-only
#include <Python.h>
/**
* Some defines in rz_userconf.h are conflicting with the ones in python.h
**/
#undef HAVE_EXPLICIT_BZERO
#undef HAVE_SIGACTION
#undef HAVE_REALPATH
#include <rz_core.h>
#include <rz_util/rz_file.h>
#include <swig_runtime.h>
-26
View File
@@ -1,26 +0,0 @@
#!/usr/bin/env python3
"""
SPDX-FileCopyrightText: 2024 kazarmy <[email protected]>
SPDX-License-Identifier: LGPL-3.0-only
"""
import os
import shutil
import sys
import sysconfig
def install_files(scheme):
for file in sys.argv[1:]:
if file.endswith(".py"):
dest_type = 'purelib'
elif file.endswith(".so"):
dest_type = 'platlib'
install_dir = sysconfig.get_path(dest_type, scheme)
shutil.copy(file, install_dir)
print(f"Installing {os.path.basename(file)} to {install_dir}")
try:
install_files(sysconfig.get_default_scheme())
except PermissionError:
print("Installing to user site-packages since normal site-packages is not writeable")
install_files(f"{os.name}_user")
+1 -2
View File
@@ -1,9 +1,8 @@
[MESSAGES CONTROL]
disable=too-many-instance-attributes,
too-few-public-methods,
too-few-public-methods,
too-many-branches,
too-many-return-statements,
too-many-locals,
too-many-arguments,
broad-exception-raised,
fixme
+4 -13
View File
@@ -5,30 +5,21 @@ requires = [
]
build-backend = "mesonpy"
[tool.meson-python.args]
setup = ['-Dwheel=true']
[tool.cibuildwheel]
build-verbosity = 3
before-all = "bash {project}/cibw_before_all.sh"
manylinux-x86_64-image = "manylinux2014"
manylinux-x86_64-image = "manylinux_2_24"
manylinux-i686-image = "manylinux_2_24"
skip = "pp*"
[tool.cibuildwheel.linux]
environment = { PATH="/opt/rh/llvm-toolset-7.0/root/usr/bin:/opt/rh/llvm-toolset-7.0/root/usr/sbin:$PATH", LD_LIBRARY_PATH="/opt/rh/llvm-toolset-7.0/root/usr/lib64:$LD_LIBRARY_PATH" }
archs = ["x86_64"]
[tool.cibuildwheel.windows]
environment = { CMAKE_PREFIX_PATH="C:/rizin" }
environment = { CMAKE_PREFIX_PATH="C:\\rizin" }
archs = ["AMD64"]
[tool.cibuildwheel.macos]
environment = { PATH="/opt/homebrew/bin:$PATH", MACOSX_DEPLOYMENT_TARGET="14.0" }
[project]
name = "rz-bindings"
dynamic = [
'version',
]
requires-python = ">=3.9"
requires-python = ">=3.8"
readme = "README.md"
+4 -2
View File
@@ -54,7 +54,8 @@ class Class:
typedef: str,
ignore_fields: Optional[Set[str]] = ...,
rename_fields: Optional[Dict[str, str]] = ...,
): ...
):
...
@overload
def __init__(
@@ -65,7 +66,8 @@ class Class:
struct: str,
ignore_fields: Optional[Set[str]] = ...,
rename_fields: Optional[Dict[str, str]] = ...,
): ...
):
...
def __init__(
self,
+4 -2
View File
@@ -46,10 +46,12 @@ class MacroEnum:
defines: OrderedDict[str, str]
@overload
def __init__(self, header: Header, *defines: str): ...
def __init__(self, header: Header, *defines: str):
...
@overload
def __init__(self, header: Header, *, prefix: str): ...
def __init__(self, header: Header, *, prefix: str):
...
def __init__(
self,
+4 -2
View File
@@ -28,7 +28,8 @@ class Func:
*,
default_args: Optional[Dict[str, str]] = ...,
typemaps: Optional[List[Typemap]] = ...,
): ...
):
...
@overload
def __init__(
@@ -38,7 +39,8 @@ class Func:
cfunc: "CFunc",
default_args: Optional[Dict[str, str]] = ...,
typemaps: Optional[List[Typemap]] = ...,
): ...
):
...
def __init__(
self,
+1 -9
View File
@@ -29,7 +29,6 @@ class Generic:
specializations: Set[str]
c_methods: OrderedDict[str, List[str]]
python_methods: OrderedDict[str, List[str]]
specialization_extensions: DefaultDict[str, List[str]]
@@ -50,7 +49,6 @@ class Generic:
self.methods = OrderedDict()
self.specializations = set()
self.c_methods = OrderedDict()
self.python_methods = OrderedDict()
self.specialization_extensions = DefaultDict(list)
@@ -133,15 +131,9 @@ class Generic:
return specialization
def add_c_method(self, name: str, *lines: str) -> None:
"""
Add C method for name
"""
self.c_methods[name] = list(lines)
def add_python_method(self, decl: str, *lines: str) -> None:
"""
Add python method with decl
Add python function with decl
"""
self.python_methods[decl] = [f"def {decl}:"] + [f" {line}" for line in lines]
+3 -12
View File
@@ -2,7 +2,6 @@
SPDX-FileCopyrightText: 2022 wingdeans <[email protected]>
SPDX-License-Identifier: LGPL-3.0-only
"""
from typing import List, Dict, TYPE_CHECKING
from clang.cindex import Cursor, CursorKind
@@ -42,19 +41,11 @@ def gen_ctype_specializations(cursors: List[Cursor], ctype: CType) -> None:
# eg. typedef RzVector /*<ut64>*/ (*func)(void)
gen_ctype_specializations(cursors + [ctype.cursor], ctype.canonical)
elif isinstance(ctype, CFunctionType):
cursor_children = list(cursors[-1].get_children())
# Handle typedef of typedef of a function pointer
while (
len(cursor_children) == 1 and cursor_children[0].kind == CursorKind.TYPE_REF
):
cursor_children = list(
cursor_children[0].referenced.get_children() # type: ignore[attr-defined]
)
gen_ctype_specializations(cursors, ctype.result)
cursor_args = [
cursor for cursor in cursor_children if cursor.kind == CursorKind.PARM_DECL
cursor
for cursor in cursors[-1].get_children()
if cursor.kind == CursorKind.PARM_DECL
]
assert len(cursor_args) == len(ctype.args)
+26 -54
View File
@@ -63,15 +63,15 @@ def bind_list(list_h: Header) -> None:
"""
### RzListIter ###
rz_list_iter = Generic(list_h, "RzListIter", pointer=True)
rz_list_iter.add_method("rz_list_next", rename="next", generic_ret=True)
rz_list_iter.add_method("rz_list_val", rename="data", generic_ret=True)
rz_list_iter.add_method("rz_list_iter_get_next", rename="next", generic_ret=True)
rz_list_iter.add_method("rz_list_iter_get_data", rename="data", generic_ret=True)
### RzList ###
rz_list = Generic(list_h, "RzList", dependencies=[rz_list_iter], pointer=True)
rz_list.add_method("rz_list_length", rename="length")
rz_list.add_method("rz_list_first_val", rename="first", generic_ret=True)
rz_list.add_method("rz_list_last_val", rename="last", generic_ret=True)
rz_list.add_method("rz_list_first", rename="first", generic_ret=True)
rz_list.add_method("rz_list_last", rename="last", generic_ret=True)
rz_list.add_method("rz_list_iterator", rename="iterator", generic_ret=True)
rz_list.add_method(
@@ -147,10 +147,13 @@ def bind_analysis(analysis_h: Header) -> None:
"""
RzAnalysis
"""
analysis_h.ignore("rz_analysis_version")
rz_analysis = Class(
analysis_h,
typedef="RzAnalysis",
struct="rz_analysis_t",
ignore_fields={"leaddrs"},
rename_fields={"type_links": "_type_links"},
)
rz_analysis_function = Class(analysis_h, typedef="RzAnalysisFunction")
@@ -158,10 +161,11 @@ def bind_analysis(analysis_h: Header) -> None:
rz_analysis_function.add_prefixed_methods("rz_analysis_function_")
rz_analysis.add_method("rz_analysis_reflines_get", rename="get_reflines")
rz_analysis.add_constructor("rz_analysis_new")
rz_analysis.add_destructor("rz_analysis_free")
rz_analysis.add_prefixed_methods("rz_analysis_")
rz_analysis.add_prefixed_funcs("rz_analysis_")
Class(analysis_h, typedef="RzAnalysisBlock", struct="rz_analysis_bb_t")
Class(analysis_h, typedef="RzAnalysisBlock")
Class(analysis_h, typedef="RzAnalysisEsil")
Class(analysis_h, typedef="RzAnalysisPlugin")
Class(
@@ -177,13 +181,7 @@ def bind_asm(asm_h: Header) -> None:
"""
RzAsm
"""
rz_asm = Class(asm_h, typedef="RzAsm", struct="rz_asm_t") # TODO: Add functions
rz_asm.add_constructor("rz_asm_new")
rz_asm.add_destructor("rz_asm_free")
rz_asm.add_prefixed_methods("rz_asm_")
rz_asm.add_prefixed_funcs("rz_asm_")
Class(asm_h, typedef="RzAsm") # TODO: Add functions
Class(asm_h, typedef="RzAsmPlugin")
@@ -261,6 +259,7 @@ def bind_cons(cons_h: Header) -> None:
typedef="RzCons",
ignore_fields={"term_raw", "term_buf"}, # struct termios
rename_fields={
"lastline": "_lastline",
"echo": "_echo",
"highlight": "_highlight",
"newline": "_newline",
@@ -330,17 +329,6 @@ def bind_core(core_h: Header) -> None:
Class(core_h, typedef="RzCoreFile")
MacroEnum(core_h, prefix="RZ_CORE_CMD_")
@threaded_header("rz_esil/rz_esil.h")
def bind_esil(esil_h: Header) -> None:
"""
RzAnalysisEsil
"""
Class(esil_h, typedef="RzAnalysisEsil")
Class(esil_h, typedef="RzAnalysisEsilInterState")
@threaded_header("rz_flag.h")
def bind_flag(flag_h: Header) -> None:
@@ -429,7 +417,15 @@ def bind_sdb(sdb_h: Header) -> None:
Class(sdb_h, typedef="Sdb", ignore_fields={"db", "m"})
@threaded_header("rz_util/ht_pp.h")
@threaded_header("sdb/ls.h")
def bind_ls(ls_h: Header) -> None:
"""
ls
"""
Class(ls_h, typedef="SdbList")
@threaded_header("sdb/ht_pp.h")
def bind_ht_pp(ht_pp_h: Header) -> None:
"""
ht_pp
@@ -437,7 +433,7 @@ def bind_ht_pp(ht_pp_h: Header) -> None:
Class(ht_pp_h, typedef="HtPP")
@threaded_header("rz_util/ht_pu.h")
@threaded_header("sdb/ht_pu.h")
def bind_ht_pu(ht_pu_h: Header) -> None:
"""
ht_pu
@@ -445,7 +441,7 @@ def bind_ht_pu(ht_pu_h: Header) -> None:
Class(ht_pu_h, typedef="HtPU")
@threaded_header("rz_util/ht_up.h")
@threaded_header("sdb/ht_up.h")
def bind_ht_up(ht_up_h: Header) -> None:
"""
ht_up
@@ -453,33 +449,9 @@ def bind_ht_up(ht_up_h: Header) -> None:
Class(ht_up_h, typedef="HtUP")
@threaded_header("rz_util/ht_uu.h")
@threaded_header("sdb/ht_uu.h")
def bind_ht_uu(ht_uu_h: Header) -> None:
"""
ht_uu
"""
Class(ht_uu_h, typedef="HtUU")
@threaded_header("rz_util/ht_sp.h")
def bind_ht_sp(ht_sp_h: Header) -> None:
"""
ht_sp
"""
Class(ht_sp_h, typedef="HtSP")
@threaded_header("rz_util/ht_ss.h")
def bind_ht_ss(ht_ss_h: Header) -> None:
"""
ht_ss
"""
Class(ht_ss_h, typedef="HtSS")
@threaded_header("rz_util/ht_su.h")
def bind_ht_su(ht_su_h: Header) -> None:
"""
ht_su
"""
Class(ht_su_h, typedef="HtSU")
+2 -2
View File
@@ -2224,7 +2224,7 @@ class Type(Structure):
return result
assert self.kind in (TypeKind.FUNCTIONPROTO, TypeKind.FUNCTIONNOPROTO)
assert self.kind == TypeKind.FUNCTIONPROTO
return ArgumentsIterator(self)
@property
@@ -2320,7 +2320,7 @@ class Type(Structure):
def is_function_variadic(self):
"""Determine whether this function Type is a variadic function type."""
assert self.kind in (TypeKind.FUNCTIONPROTO, TypeKind.FUNCTIONNOPROTO)
assert self.kind == TypeKind.FUNCTIONPROTO
return conf.lib.clang_isFunctionTypeVariadic(self)
+14 -16
View File
@@ -38,7 +38,6 @@ class TypeKind(Enum):
POINTER: TypeKind
CONSTANTARRAY: TypeKind
FUNCTIONPROTO: TypeKind
FUNCTIONNOPROTO: TypeKind
INCOMPLETEARRAY: TypeKind
RECORD: TypeKind
@@ -87,7 +86,6 @@ class Type:
class SourceLocation:
class File:
name: str
file: File
line: int
column: int
@@ -110,23 +108,23 @@ class Token:
extent: SourceRange
class CursorKind(Enum):
INCLUSION_DIRECTIVE: CursorKind
MACRO_INSTANTIATION: CursorKind
INCLUSION_DIRECTIVE: TypeKind
MACRO_INSTANTIATION: TypeKind
ENUM_DECL: CursorKind
MACRO_DEFINITION: CursorKind
STRUCT_DECL: CursorKind
TYPEDEF_DECL: CursorKind
FUNCTION_DECL: CursorKind
ENUM_DECL: TypeKind
MACRO_DEFINITION: TypeKind
STRUCT_DECL: TypeKind
TYPEDEF_DECL: TypeKind
FUNCTION_DECL: TypeKind
FIELD_DECL: CursorKind
UNION_DECL: CursorKind
PARM_DECL: CursorKind
ENUM_CONSTANT_DECL: CursorKind
FIELD_DECL: TypeKind
UNION_DECL: TypeKind
PARM_DECL: TypeKind
ENUM_CONSTANT_DECL: TypeKind
ANNOTATE_ATTR: CursorKind
TYPE_REF: CursorKind
PACKED_ATTR: CursorKind
ANNOTATE_ATTR: TypeKind
TYPE_REF: TypeKind
PACKED_ATTR: TypeKind
class Cursor:
kind: CursorKind
+10 -14
View File
@@ -76,7 +76,7 @@ class CFunc(AttrCursor):
### Configuration ###
rizin_include_path: Optional[str] = None # pylint: disable=invalid-name
rizin_include_path: Optional[str] = None
clang_args: List[str] = []
### Headers ###
@@ -98,20 +98,18 @@ class HeaderBuilder:
assert rizin_include_path
filename = os.path.abspath(os.path.join(rizin_include_path, *name_segments))
assert os.path.exists(filename), f"File {filename} does not exist"
# Fix sdb path if using source librz/include
if name_segments[0] == "sdb" and not os.path.exists(filename):
name_segments = ["..", "util", "sdb", "src"] + name_segments[1:]
filename = os.path.abspath(os.path.join(rizin_include_path, *name_segments))
assert os.path.exists(filename)
self.filename = filename
# Parse ht_inc.h if importing SDB hashtable header
self.extra_filename = None
if name_segments[-1] in [
"ht_pp.h",
"ht_pu.h",
"ht_up.h",
"ht_uu.h",
"ht_sp.h",
"ht_ss.h",
"ht_su.h",
]:
if name_segments[-1] in ["ht_pp.h", "ht_pu.h", "ht_up.h", "ht_uu.h"]:
self.extra_filename = "ht_inc.h"
def translation_unit(self) -> TranslationUnit:
@@ -181,9 +179,7 @@ class Header:
continue
# Check for redefinitions
if (
name in self.cursor_kinds and cursor.kind == self.cursor_kinds[name]
): # Redefinition
if name in self.cursor_kinds: # Redefinition
prev = self.cursors[cursor.kind][name]
if cursor.kind == CursorKind.STRUCT_DECL:
assert prev.kind == CursorKind.STRUCT_DECL
+6 -9
View File
@@ -100,32 +100,29 @@ def wrap_type(type_: Type) -> CType:
"""
Wrap a type
"""
orig_type = type_
while type_.kind == TypeKind.ELABORATED:
type_ = type_.get_named_type()
# Complex types
if type_.kind == TypeKind.POINTER:
return CPointerType(orig_type, pointee=wrap_type(type_.get_pointee()))
return CPointerType(type_, pointee=wrap_type(type_.get_pointee()))
if type_.kind in [TypeKind.CONSTANTARRAY, TypeKind.INCOMPLETEARRAY]:
array_t = CArrayType(
orig_type, element=wrap_type(type_.get_array_element_type())
)
array_t = CArrayType(type_, element=wrap_type(type_.get_array_element_type()))
if type_.kind == TypeKind.CONSTANTARRAY:
array_t.element_count = type_.element_count
return array_t
if type_.kind == TypeKind.TYPEDEF:
return CTypedefType(
orig_type,
type_,
canonical=wrap_type(type_.get_canonical()),
cursor=type_.get_declaration(),
)
if type_.kind in (TypeKind.FUNCTIONPROTO, TypeKind.FUNCTIONNOPROTO):
if type_.kind == TypeKind.FUNCTIONPROTO:
return CFunctionType(
orig_type,
type_,
result=wrap_type(type_.get_result()),
args=[wrap_type(arg) for arg in type_.argument_types()],
)
@@ -135,7 +132,7 @@ def wrap_type(type_: Type) -> CType:
if decl_spelling.startswith("const "):
decl_spelling = decl_spelling[len("const ") :]
return CRecordType(orig_type, decl_spelling=decl_spelling)
return CRecordType(type_, decl_spelling=decl_spelling)
# Primitive types
if type_.kind in [
+1 -1
View File
@@ -39,7 +39,7 @@ from binding_func import Func
from writer import Writer
doxygen_path: Optional[str] = None # pylint: disable=invalid-name
doxygen_path: Optional[str] = None
DoxygenElements = Dict[str, Element]
-8
View File
@@ -114,9 +114,6 @@ def write_generic(writer: Writer, generic: Generic) -> None:
for name, method in generic.methods.items():
write_func(writer, method, name, FuncKind.GENERIC)
for c_lines in generic.c_methods.values():
writer.line(*c_lines)
for python_lines in generic.python_methods.values():
writer.line("%pythoncode %{")
with writer.indent():
@@ -268,11 +265,6 @@ def write_func(writer: Writer, func: Func, name: str, kind: FuncKind) -> None:
if arg_name == "self":
arg_name = "_self"
# if function arg is the same as the function name
# we rename the argument
if arg_name == name:
arg_name += "_arg"
arg_decl = stringify_decl(
arg_name,
arg.ctype,
+4 -114
View File
@@ -23,18 +23,15 @@ and definitions. It also does this for Rizin annotations, such as RZ_OWN. This w
by defining the RZ_BINDINGS preprocessor flag, which sets the annotations to expand to
__attribute__((annotate)), which can be picked up by libclang.
"""
from typing import List, Dict, Set, TypedDict, Optional, cast
import os
import sys
import json
import shlex
import re
from argparse import ArgumentParser
from dataclasses import dataclass
from itertools import zip_longest
from pathlib import Path
from clang.cindex import (
Config,
@@ -46,30 +43,6 @@ from clang.cindex import (
SourceLocation,
)
# Detect /** ... */ or /*! ... */ style Doxygen block comments
_DOXY_BLOCK_RE = re.compile(r"/\*[*!][\s\S]*?\*/")
# Detect consecutive /// or //! style Doxygen line comments
_DOXY_LINE_RE = re.compile(r"(?:(?:\/\/[\/!])[^\n]*\n?)+")
# Match any @-prefixed Doxygen command with word boundary
_DOXY_COMMAND_RE = re.compile(r"@(\w+)\b")
# Map of @-prefixed commands to their correct backslash equivalents
_DOXY_COMMANDS = {
"param": "\\param",
"return": "\\return",
"brief": "\\brief",
"ref": "\\ref",
"p": "\\p",
"see": "\\see",
"file": "\\file",
"ingroup": "\\ingroup",
"post": "\\post",
"sa": "\\sa",
"test": "\\test",
}
warnings = set()
@@ -83,14 +56,6 @@ def warn(warning: str) -> None:
warnings.add(warning)
def location_get_filename(location: SourceLocation) -> str:
"""
Get filename for a SourceLocation
"""
path = Path(os.path.abspath(location.file.name))
return path.name
def stringify_location(location: SourceLocation) -> str:
"""
Get <relpath:filename:line> for a SourceLocation
@@ -110,8 +75,7 @@ def cursor_get_annotations(cursor: Cursor) -> List[str]:
]
generic_types = {"RzList", "RzListIter", "RzPVector", "RzVector", "RzGraph", "HtPP"}
skip_files = {"ht_inc.c", "ht_inc.h", "rz_th_ht.h", "thread_hash_table.c"}
generic_types = {"RzList", "RzListIter", "RzPVector", "RzVector", "RzGraph"}
def cursor_get_comment(cursor: Cursor, *, packed: bool = False) -> Optional[str]:
@@ -171,10 +135,7 @@ def cursor_get_comment(cursor: Cursor, *, packed: bool = False) -> Optional[str]
# Filter out other tokens
comment = token.spelling
if not comment.startswith("/*") or not comment.endswith("*/"):
if (
typeref_spelling in generic_types
and location_get_filename(cursor.location) not in skip_files
):
if typeref_spelling in generic_types:
warn(
f"Missing type comment at {stringify_location(cursor.location)} "
"(token is not a comment)"
@@ -190,7 +151,7 @@ def cursor_get_comment(cursor: Cursor, *, packed: bool = False) -> Optional[str]
return comment
# Check pointer (or lack of) and space between pointer
if typeref_spelling in {"RzList", "RzListIter", "RzPVector"}:
if typeref_spelling in {"RzList", "RzListIter", "RzPVector", "RzGraph"}:
if comment[-2] != "*":
warn(f"Type comment at {stringify_location(cursor.location)} lacks pointer")
elif comment[-3] != " ":
@@ -202,30 +163,7 @@ def cursor_get_comment(cursor: Cursor, *, packed: bool = False) -> Optional[str]
warn(
f"Type comment at {stringify_location(cursor.location)} should not have pointer"
)
elif typeref_spelling in {"RzGraph", "HtPP"}:
if not re.match(
r"<(struct )?[A-Za-z0-9_]+ \*, (struct )?[A-Za-z0-9_]+ \*>", comment
):
if typeref_spelling == "RzGraph":
warn(
f"Type comment at {stringify_location(cursor.location)} must "
f"follow exactly the pattern '/*<NodeType *, EdgeType *>*/'. Is: '{comment}'"
)
elif typeref_spelling == "HtPP":
warn(
f"Type comment at {stringify_location(cursor.location)} must "
f"follow exactly the pattern '/*<KeyType *, ValueType *>*/'. Is: '{comment}'"
)
elif typeref_spelling in {
"HtUP",
"HtUU",
"HtPU",
"HtSP",
"HtSS",
"HtSU",
"RBTree",
"SdbList",
}:
elif typeref_spelling in {"HtPP", "HtUP", "HtUU", "RBTree", "SdbList"}:
pass
else:
warn(
@@ -316,51 +254,6 @@ class Function:
)
def check_doxygen_syntax(file_path: str, rizin_path: str) -> None:
"""
Check for incorrect Doxygen syntax in a file.
Rizin uses backslash syntax (\\param, \\return, etc.)
instead of at-sign syntax (@param, @return, etc.).
This function scans Doxygen comment blocks and reports any @-prefixed command usage.
"""
if not (file_path.endswith(".c") or file_path.endswith(".h")):
return
try:
with open(file_path, "r", encoding="utf-8", errors="ignore") as f:
content = f.read()
except (OSError, IOError):
return
relpath = os.path.relpath(os.path.abspath(file_path), rizin_path)
comment_matches = list(_DOXY_BLOCK_RE.finditer(content)) + list(
_DOXY_LINE_RE.finditer(content)
)
comment_matches.sort(key=lambda m: m.start())
for match in comment_matches:
block_text = match.group(0)
block_start_pos = match.start()
line_offset = content[:block_start_pos].count("\n")
lines = block_text.splitlines()
for line_idx, line in enumerate(lines):
for cmd_match in _DOXY_COMMAND_RE.finditer(line):
command = cmd_match.group(1).lower()
if command in _DOXY_COMMANDS:
line_num = line_offset + line_idx + 1
column = cmd_match.start() + 1
correct_syntax = _DOXY_COMMANDS[command]
warn(
f"<{relpath}:{line_num}:{column}> "
f"Found @{command}, should use {correct_syntax}"
)
def check_translation_unit(
translation_unit: TranslationUnit, *, skipped_paths: Set[str], rizin_path: str
) -> None:
@@ -405,7 +298,6 @@ def check_translation_unit(
CursorKind.STRUCT_DECL,
CursorKind.UNION_DECL,
CursorKind.ENUM_DECL,
CursorKind.ALIGNED_ATTR,
]:
warn(f"Unknown field cursor kind: {field.kind}")
@@ -482,8 +374,6 @@ def main() -> int:
for include in includes
]
check_doxygen_syntax(abspath, rizin_path)
try:
check_translation_unit(
TranslationUnit.from_source(abspath, clang_args),
+4 -8
View File
@@ -9,20 +9,16 @@ bool rizin_warn_deprecate_instructions = true;
%{
void rizin_try_warn_deprecate(const char *name, const char *c_name) {
if (rizin_warn_deprecate) {
fprintf(stderr, "Warning: `%s` calls deprecated function `%s`\n", name, c_name);
printf("Warning: `%s` calls deprecated function `%s`\n", name, c_name);
if (rizin_warn_deprecate_instructions) {
fprintf(stderr,
"To disable this warning, set rizin_warn_deprecate to false\n"
"The way to do this depends on the SWIG language being used\n"
"For python, do `rizin.cvar.rizin_warn_deprecate = False`\n");
puts("To disable this warning, set rizin_warn_deprecate to false");
puts("The way to do this depends on the SWIG language being used");
puts("For python, do `rizin.cvar.rizin_warn_deprecate = False`");
}
}
}
%}
// uint64_t, int64_t etc
%include <stdint.i>
// Buffer typemaps
%include <pybuffer.i>
%pybuffer_mutable_binary(unsigned char *buf, unsigned long long len);
+2 -2
View File
@@ -13,7 +13,7 @@ void register_swig_command(const char *str, CmdDirector *director,
} else {
char *dup = strdup(str);
dup[len - 1] = '\0';
parent = (RzCmdDesc *)ht_sp_find($self->ht_cmds, dup, NULL);
parent = (RzCmdDesc *)ht_pp_find($self->ht_cmds, dup, NULL);
free(dup);
}
@@ -21,7 +21,7 @@ void register_swig_command(const char *str, CmdDirector *director,
throw "Could not get parent RzCmdDesc";
}
RzCmdDesc *prev = (RzCmdDesc *)ht_sp_find($self->ht_cmds, str, NULL);
RzCmdDesc *prev = (RzCmdDesc *)ht_pp_find($self->ht_cmds, str, NULL);
std::string cmd(str);
if (prev) { // Update existing RzCmdDesc
auto it = SWIGCmds.find(cmd);
-15
View File
@@ -1,15 +0,0 @@
NAME=1-rz_core.py =
FILE=--
CMDS=<<EOF
!echo q | python3 examples/1-rz_core.py =
echo
EOF
EXPECT=<<EOF
Loaded 1 file(s)
Corefile #1 has 1 binfile(s)
* malloc://512
rizin>
EOF
EXPECT_ERR=<<EOF
EOF
RUN