mirror of
https://github.com/rizinorg/rz-bindgen.git
synced 2026-11-07 23:02:04 -10:00
Compare commits
51
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9bee5c3771 | ||
|
|
dd35844550 | ||
|
|
6e305d6fab | ||
|
|
6444185df7 | ||
|
|
a0b71b09db | ||
|
|
4a31374a3b | ||
|
|
380f6e229c | ||
|
|
b2a1f44b82 | ||
|
|
b378684805 | ||
|
|
8aaf3011bd | ||
|
|
e0ec4912c1 | ||
|
|
f7c5a16028 | ||
|
|
fc409dfa10 | ||
|
|
220d7a8405 | ||
|
|
6a7efaab4e | ||
|
|
69302758c8 | ||
|
|
3885561032 | ||
|
|
6fe53b3f73 | ||
|
|
0215843fa6 | ||
|
|
d856543253 | ||
|
|
ff0cc4a7f8 | ||
|
|
e8070500bf | ||
|
|
114bd35d25 | ||
|
|
68e8cd3ad0 | ||
|
|
f51f476a5d | ||
|
|
b6d4757eba | ||
|
|
dc1add8fc3 | ||
|
|
2610bd4b8e | ||
|
|
f45f5687b1 | ||
|
|
7e7a790d3c | ||
|
|
8b6d71f3fd | ||
|
|
3f898ed6e6 | ||
|
|
7cb30e15d1 | ||
|
|
ae7bf29fbf | ||
|
|
adf1025286 | ||
|
|
e9fdf80685 | ||
|
|
9fdba22e35 | ||
|
|
e4aef7d474 | ||
|
|
a03d1f32f5 | ||
|
|
fc64be188f | ||
|
|
aabbf0df6b | ||
|
|
5740a3770b | ||
|
|
878f562385 | ||
|
|
a71ec49cf0 | ||
|
|
48bc95c67a | ||
|
|
4a15bfe470 | ||
|
|
f9456f670c | ||
|
|
961e34a258 | ||
|
|
ad843b76d1 | ||
|
|
00422160f1 | ||
|
|
fadef06f39 |
No files matched your search
@@ -0,0 +1,7 @@
|
||||
version: 2
|
||||
|
||||
updates:
|
||||
- package-ecosystem: github-actions
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
+20
-16
@@ -1,6 +1,11 @@
|
||||
name: build
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- dev
|
||||
- stable
|
||||
- 'ci-*'
|
||||
pull_request:
|
||||
workflow_dispatch:
|
||||
workflow_call:
|
||||
inputs:
|
||||
@@ -21,7 +26,7 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-24.04, windows-2019, macos-14]
|
||||
os: [ubuntu-24.04, windows-2022, macos-14]
|
||||
|
||||
steps:
|
||||
- name: Install SWIG with Homebrew
|
||||
@@ -29,12 +34,12 @@ jobs:
|
||||
run: brew install swig
|
||||
|
||||
- name: Checkout rz-bindgen
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
|
||||
# runned only from workflow_call
|
||||
- name: Checkout rizin
|
||||
if: ${{ inputs.external_call }}
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
repository: rizinorg/rizin
|
||||
path: rizin
|
||||
@@ -42,7 +47,7 @@ jobs:
|
||||
|
||||
- name: Checkout rizin (stable)
|
||||
if: ${{ !inputs.external_call && ((github.ref_name == 'stable') || (github.base_ref == 'stable')) }}
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
repository: rizinorg/rizin
|
||||
path: rizin
|
||||
@@ -50,23 +55,23 @@ jobs:
|
||||
|
||||
- name: Checkout rizin (dev)
|
||||
if: ${{ !inputs.external_call && ((github.ref_name != 'stable') && (github.base_ref != 'stable')) }}
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
repository: rizinorg/rizin
|
||||
path: rizin
|
||||
ref: dev
|
||||
|
||||
- name: Build rz-bindgen
|
||||
uses: pypa/cibuildwheel@v2.22.0
|
||||
uses: pypa/cibuildwheel@v3.4.1
|
||||
|
||||
- name: Upload sdist
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: sdist-${{ matrix.os }}
|
||||
path: dist/*.tar.gz
|
||||
|
||||
- name: Upload wheels
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: wheels-${{ matrix.os }}
|
||||
path: wheelhouse/*.whl
|
||||
@@ -76,14 +81,14 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout rz-bindgen
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
path: rz-bindgen
|
||||
|
||||
# runned only from workflow_call
|
||||
- name: Checkout rizin
|
||||
if: ${{ inputs.external_call }}
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
repository: rizinorg/rizin
|
||||
path: rizin
|
||||
@@ -91,7 +96,7 @@ jobs:
|
||||
|
||||
- name: Checkout rizin (stable)
|
||||
if: ${{ !inputs.external_call && ((github.ref_name == 'stable') || (github.base_ref == 'stable')) }}
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
repository: rizinorg/rizin
|
||||
path: rizin
|
||||
@@ -99,7 +104,7 @@ jobs:
|
||||
|
||||
- name: Checkout rizin (dev)
|
||||
if: ${{ !inputs.external_call && ((github.ref_name != 'stable') && (github.base_ref != 'stable')) }}
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
repository: rizinorg/rizin
|
||||
path: rizin
|
||||
@@ -127,7 +132,6 @@ jobs:
|
||||
- name: Test python lang plugin
|
||||
run: rizin -qc "Ll" | grep "Python SWIG"
|
||||
|
||||
- name: Test rizin.py
|
||||
run: |
|
||||
echo "import rizin" > testimport.py
|
||||
python3 testimport.py
|
||||
- name: Run rz-test
|
||||
run: rz-test -L tests/
|
||||
working-directory: rz-bindgen
|
||||
@@ -1,19 +1,25 @@
|
||||
name: lint
|
||||
on: push
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- dev
|
||||
- stable
|
||||
- 'ci-*'
|
||||
pull_request:
|
||||
jobs:
|
||||
licenses:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: Checkout rz-bindgen
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v6
|
||||
- name: REUSE compliance check
|
||||
uses: fsfe/reuse-action@v1
|
||||
uses: fsfe/reuse-action@v6
|
||||
|
||||
python:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: Checkout rz-bindgen
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v6
|
||||
- name: Install tools
|
||||
run: |
|
||||
pip install mypy pyflakes pylint black
|
||||
@@ -40,10 +46,10 @@ jobs:
|
||||
security-events: write
|
||||
steps:
|
||||
- name: Checkout rz-bindgen
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v6
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v2
|
||||
uses: github/codeql-action/init@v4
|
||||
with:
|
||||
languages: python
|
||||
- name: Run CodeQL
|
||||
uses: github/codeql-action/analyze@v2
|
||||
uses: github/codeql-action/analyze@v4
|
||||
@@ -25,16 +25,16 @@ jobs:
|
||||
needs: [build]
|
||||
steps:
|
||||
- name: Download artifacts
|
||||
uses: actions/download-artifact@v3
|
||||
uses: actions/download-artifact@v8
|
||||
with:
|
||||
name: wheels
|
||||
path: dist
|
||||
- name: Download sdist
|
||||
uses: actions/download-artifact@v3
|
||||
uses: actions/download-artifact@v8
|
||||
with:
|
||||
name: sdist
|
||||
path: dist
|
||||
- name: Publish wheels
|
||||
uses: pypa/gh-action-pypi-publish@v1.5.1
|
||||
uses: pypa/gh-action-pypi-publish@v1.14.0
|
||||
with:
|
||||
password: ${{ secrets.PYPI_TOKEN }}
|
||||
-32
@@ -1,32 +0,0 @@
|
||||
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
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
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"
|
||||
+1
-1
@@ -43,7 +43,7 @@ else
|
||||
export CFLAGS="-include linux/limits.h"
|
||||
fi
|
||||
meson setup --buildtype=release --libdir=lib build
|
||||
sudo meson install -C build
|
||||
sudo PATH="$PATH" bash -c "meson install -C build"
|
||||
fi
|
||||
|
||||
popd
|
||||
|
||||
+5
-3
@@ -50,6 +50,7 @@ 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]
|
||||
@@ -66,8 +67,8 @@ for i, corefile in enumerate(core.files):
|
||||
for binfile in corefile.binfiles:
|
||||
print(f" * {binfile.file}")
|
||||
|
||||
while True:
|
||||
core.flush(input("rizin> "))
|
||||
while core.flush(input("rizin> ")) != CMD_EXIT:
|
||||
pass
|
||||
```
|
||||
|
||||
Here's an example session:
|
||||
@@ -86,10 +87,11 @@ rizin> aaa
|
||||
[x] Applied 0 FLIRT signatures via sigdb
|
||||
[x] Propagate noreturn information
|
||||
[x] Use -AA or aaaa to perform additional experimental analysis.
|
||||
> afl
|
||||
rizin> afl
|
||||
0x0040233e 1 6 entry0
|
||||
0x00402051 3 49 -> 16 sym.HelloWorld::Main
|
||||
0x0040205f 99 24482 -> 31854 sym.HelloWorld::.ctor
|
||||
rizin> q
|
||||
```
|
||||
|
||||
### Plugins
|
||||
|
||||
@@ -4,6 +4,7 @@ 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]
|
||||
@@ -20,5 +21,5 @@ for i, corefile in enumerate(core.files):
|
||||
for binfile in corefile.binfiles:
|
||||
print(f" * {binfile.file}")
|
||||
|
||||
while True:
|
||||
core.flush(input("rizin> "))
|
||||
while core.flush(input("rizin> ")) != CMD_EXIT:
|
||||
pass
|
||||
@@ -8,11 +8,10 @@ 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__()
|
||||
@@ -23,6 +22,7 @@ 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 True:
|
||||
core.flush(input("> "))
|
||||
while core.flush(input("rizin> ")) != CMD_EXIT:
|
||||
pass
|
||||
@@ -4,6 +4,7 @@ SPDX-License-Identifier: LGPL-3.0-only
|
||||
"""
|
||||
|
||||
import rizin
|
||||
from rizin import RZ_CORE_CMD_EXIT as CMD_EXIT
|
||||
import sys
|
||||
|
||||
|
||||
@@ -26,5 +27,5 @@ core.bin.plugins.append(plugin_struct)
|
||||
core.bin.force_plugin(plugin.name)
|
||||
core.file_open_load(sys.argv[1])
|
||||
|
||||
while True:
|
||||
core.flush(input("> "))
|
||||
while core.flush(input("rizin> ")) != CMD_EXIT:
|
||||
pass
|
||||
@@ -89,6 +89,11 @@ 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(
|
||||
|
||||
@@ -29,6 +29,7 @@ class Generic:
|
||||
|
||||
specializations: Set[str]
|
||||
|
||||
c_methods: OrderedDict[str, List[str]]
|
||||
python_methods: OrderedDict[str, List[str]]
|
||||
specialization_extensions: DefaultDict[str, List[str]]
|
||||
|
||||
@@ -49,6 +50,7 @@ class Generic:
|
||||
self.methods = OrderedDict()
|
||||
self.specializations = set()
|
||||
|
||||
self.c_methods = OrderedDict()
|
||||
self.python_methods = OrderedDict()
|
||||
self.specialization_extensions = DefaultDict(list)
|
||||
|
||||
@@ -131,9 +133,15 @@ 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 function with decl
|
||||
Add python method with decl
|
||||
"""
|
||||
self.python_methods[decl] = [f"def {decl}:"] + [f" {line}" for line in lines]
|
||||
|
||||
|
||||
@@ -42,11 +42,19 @@ 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 cursors[-1].get_children()
|
||||
if cursor.kind == CursorKind.PARM_DECL
|
||||
cursor for cursor in cursor_children if cursor.kind == CursorKind.PARM_DECL
|
||||
]
|
||||
|
||||
assert len(cursor_args) == len(ctype.args)
|
||||
|
||||
+24
-33
@@ -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_iter_get_next", rename="next", generic_ret=True)
|
||||
rz_list_iter.add_method("rz_list_iter_get_data", rename="data", generic_ret=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)
|
||||
|
||||
### 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", rename="first", generic_ret=True)
|
||||
rz_list.add_method("rz_list_last", rename="last", generic_ret=True)
|
||||
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_iterator", rename="iterator", generic_ret=True)
|
||||
|
||||
rz_list.add_method(
|
||||
@@ -150,8 +150,7 @@ def bind_analysis(analysis_h: Header) -> None:
|
||||
rz_analysis = Class(
|
||||
analysis_h,
|
||||
typedef="RzAnalysis",
|
||||
ignore_fields={"leaddrs"},
|
||||
rename_fields={},
|
||||
struct="rz_analysis_t",
|
||||
)
|
||||
|
||||
rz_analysis_function = Class(analysis_h, typedef="RzAnalysisFunction")
|
||||
@@ -159,12 +158,10 @@ 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_prefixed_methods("rz_analysis_")
|
||||
rz_analysis.add_prefixed_funcs("rz_analysis_")
|
||||
rz_analysis.add_constructor("rz_analysis_new")
|
||||
rz_analysis.add_destructor("rz_analysis_free")
|
||||
|
||||
Class(analysis_h, typedef="RzAnalysisBlock")
|
||||
Class(analysis_h, typedef="RzAnalysisEsil")
|
||||
Class(analysis_h, typedef="RzAnalysisEsilInterState")
|
||||
Class(analysis_h, typedef="RzAnalysisBlock", struct="rz_analysis_bb_t")
|
||||
Class(analysis_h, typedef="RzAnalysisPlugin")
|
||||
|
||||
Class(
|
||||
@@ -180,7 +177,13 @@ def bind_asm(asm_h: Header) -> None:
|
||||
"""
|
||||
RzAsm
|
||||
"""
|
||||
Class(asm_h, typedef="RzAsm") # TODO: Add functions
|
||||
|
||||
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="RzAsmPlugin")
|
||||
|
||||
|
||||
@@ -327,29 +330,17 @@ def bind_core(core_h: Header) -> None:
|
||||
|
||||
Class(core_h, typedef="RzCoreFile")
|
||||
|
||||
@threaded_header("rz_util/rz_annotated_code.h")
|
||||
def bind_annotated_code(annotated_code_h: Header) -> None:
|
||||
"""
|
||||
RzAnnotatedCode
|
||||
"""
|
||||
rz_code_annotation = Class(
|
||||
annotated_code_h,
|
||||
typedef="RzCodeAnnotation",
|
||||
struct="rz_code_annotation_t",
|
||||
)
|
||||
rz_code_annotation.add_prefixed_methods("rz_annotation_")
|
||||
rz_code_annotation.add_prefixed_funcs("rz_annotation_")
|
||||
MacroEnum(core_h, prefix="RZ_CORE_CMD_")
|
||||
|
||||
rz_annotated_code = Class(
|
||||
annotated_code_h,
|
||||
typedef="RzAnnotatedCode",
|
||||
struct="rz_annotated_code_t",
|
||||
)
|
||||
rz_annotated_code.add_constructor("rz_annotated_code_new")
|
||||
rz_annotated_code.add_destructor("rz_annotated_code_free")
|
||||
|
||||
rz_annotated_code.add_prefixed_methods("rz_annotated_code_")
|
||||
rz_annotated_code.add_prefixed_funcs("rz_annotated_code_")
|
||||
@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:
|
||||
|
||||
+14
-14
@@ -110,23 +110,23 @@ class Token:
|
||||
extent: SourceRange
|
||||
|
||||
class CursorKind(Enum):
|
||||
INCLUSION_DIRECTIVE: TypeKind
|
||||
MACRO_INSTANTIATION: TypeKind
|
||||
INCLUSION_DIRECTIVE: CursorKind
|
||||
MACRO_INSTANTIATION: CursorKind
|
||||
|
||||
ENUM_DECL: TypeKind
|
||||
MACRO_DEFINITION: TypeKind
|
||||
STRUCT_DECL: TypeKind
|
||||
TYPEDEF_DECL: TypeKind
|
||||
FUNCTION_DECL: TypeKind
|
||||
ENUM_DECL: CursorKind
|
||||
MACRO_DEFINITION: CursorKind
|
||||
STRUCT_DECL: CursorKind
|
||||
TYPEDEF_DECL: CursorKind
|
||||
FUNCTION_DECL: CursorKind
|
||||
|
||||
FIELD_DECL: TypeKind
|
||||
UNION_DECL: TypeKind
|
||||
PARM_DECL: TypeKind
|
||||
ENUM_CONSTANT_DECL: TypeKind
|
||||
FIELD_DECL: CursorKind
|
||||
UNION_DECL: CursorKind
|
||||
PARM_DECL: CursorKind
|
||||
ENUM_CONSTANT_DECL: CursorKind
|
||||
|
||||
ANNOTATE_ATTR: TypeKind
|
||||
TYPE_REF: TypeKind
|
||||
PACKED_ATTR: TypeKind
|
||||
ANNOTATE_ATTR: CursorKind
|
||||
TYPE_REF: CursorKind
|
||||
PACKED_ATTR: CursorKind
|
||||
|
||||
class Cursor:
|
||||
kind: CursorKind
|
||||
|
||||
@@ -76,7 +76,7 @@ class CFunc(AttrCursor):
|
||||
|
||||
|
||||
### Configuration ###
|
||||
rizin_include_path: Optional[str] = None
|
||||
rizin_include_path: Optional[str] = None # pylint: disable=invalid-name
|
||||
clang_args: List[str] = []
|
||||
|
||||
### Headers ###
|
||||
|
||||
@@ -39,7 +39,7 @@ from binding_func import Func
|
||||
|
||||
from writer import Writer
|
||||
|
||||
doxygen_path: Optional[str] = None
|
||||
doxygen_path: Optional[str] = None # pylint: disable=invalid-name
|
||||
|
||||
DoxygenElements = Dict[str, Element]
|
||||
|
||||
|
||||
@@ -114,6 +114,9 @@ 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():
|
||||
|
||||
+103
-4
@@ -30,9 +30,11 @@ 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,
|
||||
@@ -44,6 +46,30 @@ 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()
|
||||
|
||||
@@ -57,6 +83,14 @@ 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
|
||||
@@ -76,7 +110,8 @@ def cursor_get_annotations(cursor: Cursor) -> List[str]:
|
||||
]
|
||||
|
||||
|
||||
generic_types = {"RzList", "RzListIter", "RzPVector", "RzVector", "RzGraph"}
|
||||
generic_types = {"RzList", "RzListIter", "RzPVector", "RzVector", "RzGraph", "HtPP"}
|
||||
skip_files = {"ht_inc.c", "ht_inc.h", "rz_th_ht.h", "thread_hash_table.c"}
|
||||
|
||||
|
||||
def cursor_get_comment(cursor: Cursor, *, packed: bool = False) -> Optional[str]:
|
||||
@@ -136,7 +171,10 @@ 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:
|
||||
if (
|
||||
typeref_spelling in generic_types
|
||||
and location_get_filename(cursor.location) not in skip_files
|
||||
):
|
||||
warn(
|
||||
f"Missing type comment at {stringify_location(cursor.location)} "
|
||||
"(token is not a comment)"
|
||||
@@ -152,7 +190,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", "RzGraph"}:
|
||||
if typeref_spelling in {"RzList", "RzListIter", "RzPVector"}:
|
||||
if comment[-2] != "*":
|
||||
warn(f"Type comment at {stringify_location(cursor.location)} lacks pointer")
|
||||
elif comment[-3] != " ":
|
||||
@@ -164,8 +202,21 @@ 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 {
|
||||
"HtPP",
|
||||
"HtUP",
|
||||
"HtUU",
|
||||
"HtPU",
|
||||
@@ -265,6 +316,51 @@ 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:
|
||||
@@ -309,6 +405,7 @@ def check_translation_unit(
|
||||
CursorKind.STRUCT_DECL,
|
||||
CursorKind.UNION_DECL,
|
||||
CursorKind.ENUM_DECL,
|
||||
CursorKind.ALIGNED_ATTR,
|
||||
]:
|
||||
warn(f"Unknown field cursor kind: {field.kind}")
|
||||
|
||||
@@ -385,6 +482,8 @@ def main() -> int:
|
||||
for include in includes
|
||||
]
|
||||
|
||||
check_doxygen_syntax(abspath, rizin_path)
|
||||
|
||||
try:
|
||||
check_translation_unit(
|
||||
TranslationUnit.from_source(abspath, clang_args),
|
||||
|
||||
@@ -9,16 +9,20 @@ bool rizin_warn_deprecate_instructions = true;
|
||||
%{
|
||||
void rizin_try_warn_deprecate(const char *name, const char *c_name) {
|
||||
if (rizin_warn_deprecate) {
|
||||
printf("Warning: `%s` calls deprecated function `%s`\n", name, c_name);
|
||||
fprintf(stderr, "Warning: `%s` calls deprecated function `%s`\n", name, c_name);
|
||||
if (rizin_warn_deprecate_instructions) {
|
||||
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`");
|
||||
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");
|
||||
}
|
||||
}
|
||||
}
|
||||
%}
|
||||
|
||||
// uint64_t, int64_t etc
|
||||
%include <stdint.i>
|
||||
|
||||
// Buffer typemaps
|
||||
%include <pybuffer.i>
|
||||
%pybuffer_mutable_binary(unsigned char *buf, unsigned long long len);
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
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
|
||||
Reference in new issue
Block a user