Skip to content

Commit

Permalink
Merge pull request #22 from quarkslab/relax_dependencies
Browse files Browse the repository at this point in the history
Switch to pyproject.toml and relax dependencies
  • Loading branch information
RobinDavid authored Sep 27, 2023
2 parents 2f1d4cc + e65dfd3 commit b1542d4
Show file tree
Hide file tree
Showing 8 changed files with 132 additions and 90 deletions.
51 changes: 46 additions & 5 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,10 +1,51 @@
build*/
third_party/idasdk*/
quokka.pb.h
ci/ida*/
.eggs/*
site/
.pytest_cache/
dist/
docs/reference/python/
doxygen_current.cfg
doxygen_current.cfg

# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# Distribution / packaging
.Python
build*/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST

# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
.hypothesis/
.pytest_cache/

# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
9 changes: 0 additions & 9 deletions bindings/python/quokka/backends/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,9 @@
get_capstone_context,
capstone_decode_instruction,
)
from quokka.backends.pypcode import (
pypcode_decode_block,
pypcode_decode_instruction,
get_pypcode_context,
)

__all__ = [
# From capstone.py
"get_capstone_context",
"capstone_decode_instruction",
# From pypcode.py
"get_pypcode_context",
"pypcode_decode_instruction",
"pypcode_decode_block",
]
9 changes: 6 additions & 3 deletions bindings/python/quokka/block.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@
import logging
import collections
from functools import cached_property

import pypcode
from typing import TYPE_CHECKING

import quokka
from quokka.types import (
Expand All @@ -35,6 +34,8 @@
Set,
)

if TYPE_CHECKING:
import pypcode

logger: logging.Logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -257,4 +258,6 @@ def pcode_insts(self) -> List[pypcode.PcodeOp]:
A list of PCode instructions
"""
return quokka.backends.pypcode_decode_block(self)
from quokka.backend.pypcode import pypcode_decode_block

return pypcode_decode_block(self)
10 changes: 7 additions & 3 deletions bindings/python/quokka/instruction.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
from collections import defaultdict
from functools import cached_property
import capstone
import pypcode
from typing import TYPE_CHECKING

import quokka
from quokka.types import (
Expand All @@ -38,6 +38,9 @@
Union,
)

if TYPE_CHECKING:
import pypcode

logger: logging.Logger = logging.getLogger(__name__)


Expand Down Expand Up @@ -188,7 +191,9 @@ def pcode_insts(self) -> Sequence[pypcode.PcodeOp]:
Returns:
A sequence of PCode instructions
"""
return quokka.backends.pypcode_decode_instruction(self)
from quokka.backends.pypcode import pypcode_decode_instruction

return pypcode_decode_instruction(self)

@cached_property
def string(self) -> Optional[str]:
Expand Down Expand Up @@ -309,7 +314,6 @@ def constants(self) -> List[int]:
for op_index in self.program.proto.instructions[self.proto_index].operand_index:
operand: quokka.pb.Quokka.Operand = self.program.proto.operands[op_index]
if operand.type == 5:

# FIX: This bug is due to IDA mislabelling operands for some
# operations like ADRP on ARM where the operand points to a
# memory area (2) but the type is CONSTANT (5).
Expand Down
9 changes: 7 additions & 2 deletions bindings/python/quokka/program.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@
import os
import pathlib
import subprocess
from typing import TYPE_CHECKING

import capstone
import pypcode
import networkx

import quokka
Expand All @@ -50,6 +50,9 @@
Union,
)

if TYPE_CHECKING:
import pypcode


class Program(dict):
"""Program
Expand Down Expand Up @@ -209,7 +212,9 @@ def call_graph(self) -> networkx.DiGraph:
@cached_property
def pypcode(self) -> pypcode.Context:
"""Generate the Pypcode context."""
return quokka.backends.get_pypcode_context(self.arch, self.endianness)
from quokka.backends.pypcode import get_pypcode_context

return get_pypcode_context(self.arch, self.endianness)

@cached_property
def structures(self) -> List[quokka.Structure]:
Expand Down
54 changes: 54 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
[build-system]
requires = ["setuptools", "protobuf_distutils"]
build-backend = "setuptools.build_meta"

[project]
name = "quokka-project"
description = "Quokka: A Fast and Accurate Binary Exporter"
authors = [{ name = "Quarkslab", email = "[email protected]" }]
license = { text = "Apache Software License (Apache License, Version 2)" }
readme = { file = "README.md", content-type = "text/markdown" }
requires-python = ">=3.8"
dependencies = ["capstone>=4.0.2", "networkx>=2.4", "protobuf>=3.12.2"]
dynamic = ["version"]

[project.urls]
Homepage = "https://github.com/quarkslab/quokka/"
Repository = "https://github.com/quarkslab/quokka/"
Documentation = "https://quarkslab.github.io/quokka/"
"Bug Tracker" = "https://github.com/quarkslab/quokka/issues"

[project.optional-dependencies]
test = [
"pytest",
"pytest-mock",
"pytest-cov",
"coverage[toml]",
"pypcode>=1.1.1",
]
pypcode = ["pypcode>=1.1.1"]
doc = [
"mkdocs",
"mkdocs-material",
"mkdocstrings",
"mkdocstrings-python",
"mkdocs-literate-nav",
"mkdocs-git-revision-date-localized-plugin",
"mkdocs-gen-files",
"mkdocs-simple-hooks",
]
dev = [
"black",
"ipython",
"flake8",
"flake8-black",
"mypy",
"mypy-protobuf",
"nox",
"pypcode>=1.1.1",
]

[tool.setuptools]
packages = ["quokka", "quokka.analysis", "quokka.backends"]
package-dir = { "" = "bindings/python/" }
package-data = { "quokka" = ["*.pyi", "*.typed"] }
60 changes: 2 additions & 58 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,73 +17,17 @@
from setuptools import setup
from os.path import normpath

with open("README.md", "r") as fd:
readme = fd.read()

main_ns = {}
ver_path = normpath('bindings/python/quokka/version.py')
ver_path = normpath("bindings/python/quokka/version.py")
with open(ver_path) as ver_file:
exec(ver_file.read(), main_ns)

setup(
name="quokka-project",
version=main_ns['__version__'],
author="Alexis <dm> Challande",
author_email="[email protected]",
url="https://github.com/quarkslab/quokka",
project_urls={
"Documentation": "https://quarkslab.github.io/quokka/",
"Bug Tracker": "https://github.com/quarkslab/quokka/issues",
"Source": "https://github.com/quarkslab/quokka/",
},
description="Quokka : A Fast and Accurate Binary Exporter",
long_description=readme,
long_description_content_type="text/markdown",
python_requires=">=3.8",
packages=["quokka", "quokka.analysis", "quokka.backends"],
package_dir={"": "bindings/python/"},
package_data={"quokka": ["*.pyi", "*.typed"]},
setup_requires=[
"protobuf_distutils",
],
license="Apache-2",
version=main_ns["__version__"],
options={
"generate_py_protobufs": {
"source_dir": "proto",
"output_dir": "bindings/python/quokka",
},
},
install_requires=[
"capstone>=4.0.2,<5",
"networkx>=2.4,<3",
"protobuf>=3.12.2,<4",
"pypcode>=1.1.1,<2",
],
extras_require={
"test": [
"pytest",
"pytest-mock",
"pytest-cov",
"coverage[toml]",
],
"doc": [
"mkdocs",
"mkdocs-material",
"mkdocstrings",
"mkdocstrings-python",
"mkdocs-literate-nav",
"mkdocs-git-revision-date-localized-plugin",
"mkdocs-gen-files",
"mkdocs-simple-hooks",
],
"dev": [
"black",
"ipython",
"flake8",
"flake8-black",
"mypy",
"mypy-protobuf",
"nox",
],
},
)
20 changes: 10 additions & 10 deletions tests/python/tests/backends/test_pypcode.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,37 +2,37 @@
import pytest

import quokka
import quokka.backends
import quokka.backends.pypcode as pypcode_backend


def test_pypcode_context():

context = quokka.backends.get_pypcode_context(quokka.analysis.ArchX86)
context = pypcode_backend.get_pypcode_context(quokka.analysis.ArchX86)
assert context.lang.id == "x86:LE:32:default"

context = quokka.backends.get_pypcode_context(quokka.analysis.ArchX64)
context = pypcode_backend.get_pypcode_context(quokka.analysis.ArchX64)
assert context.lang.id == "x86:LE:64:default"

context = quokka.backends.get_pypcode_context(quokka.analysis.ArchARM64)
context = pypcode_backend.get_pypcode_context(quokka.analysis.ArchARM64)
assert context.lang.id == "AARCH64:LE:64:v8A"

context = quokka.backends.get_pypcode_context(quokka.analysis.ArchARM)
context = pypcode_backend.get_pypcode_context(quokka.analysis.ArchARM)
assert context.lang.id == "ARM:LE:32:v8"

with pytest.raises(quokka.PypcodeError):
quokka.backends.get_pypcode_context(quokka.analysis.QuokkaArch)
pypcode_backend.get_pypcode_context(quokka.analysis.QuokkaArch)


def test_pypcode_decode_instruction(mocker):

inst = mocker.MagicMock()
inst.bytes = b"\x55" # push rbp
inst.address = 0x1000
inst.program.pypcode = quokka.backends.get_pypcode_context(
inst.program.pypcode = pypcode_backend.get_pypcode_context(
quokka.analysis.ArchX64
)

inst_decoded = quokka.backends.pypcode_decode_instruction(inst)
inst_decoded = pypcode_backend.pypcode_decode_instruction(inst)
assert len(inst_decoded) == 3
assert isinstance(inst_decoded[0], pypcode.PcodeOp)

Expand All @@ -49,9 +49,9 @@ def test_pypcode_decode_block(mocker):

instructions = [mocker.MagicMock(size=len(inst_bytes)) for inst_bytes in block_bytes]
block.instructions = instructions
block.program.pypcode = quokka.backends.get_pypcode_context(
block.program.pypcode = pypcode_backend.get_pypcode_context(
quokka.analysis.ArchX64
)

decoded_block = quokka.backends.pypcode_decode_block(block)
decoded_block = pypcode_backend.pypcode_decode_block(block)
assert len(decoded_block) > 0

0 comments on commit b1542d4

Please sign in to comment.