Switch the bindings to nanobind (and update the CI)

This commit is contained in:
Romain Thomas
2023-07-09 21:33:43 +02:00
parent 7e387675ac
commit e37ffa9ec8
377 changed files with 12538 additions and 15728 deletions
+10
View File
@@ -0,0 +1,10 @@
<!DOCTYPE html>
<html>
<title>Links for lief</title>
<body>
<h1>Links for lief</h1>
% for path, filename in files:
<a href="/${path}">${filename}</a><br />
% endfor
</body>
</html>
+9
View File
@@ -0,0 +1,9 @@
[lief.s3]
region = "fr-par"
bucket = "lief"
endpoint = "https://s3.fr-par.scw.cloud"
[lief.deploy]
branches = ["master", "deploy", "devel", "nb/ci"]
main-branches = ["master", "main"]
default-dir = "latest"
+258 -242
View File
@@ -1,282 +1,298 @@
#!/usr/bin/env python3
import sys
import os
import re
import logging
import pathlib
import subprocess
import shutil
import json
import itertools
from collections import defaultdict
from datetime import datetime
from mako.template import Template
from enum import Enum, auto
import tempfile
import boto3
from botocore.exceptions import ClientError
from mako.template import Template
from pathlib import Path
from typing import Any, Optional
class CI(Enum):
UNKNOWN = auto()
TRAVIS = auto()
APPVEYOR = auto()
GITLAB_CI = auto()
CIRCLE_CI = auto()
GITHUB_ACTIONS = auto()
AZURE = auto()
LOCAL = auto()
def pretty_ci_name(ci):
return str(ci).split(".")[-1].replace("_", "-").lower()
def is_pr(ci):
if ci == CI.TRAVIS:
cond1 = os.getenv("TRAVIS_EVENT_TYPE", "pull_request") == "pull_request"
cond2 = not (os.getenv("TRAVIS_REPO_SLUG", "").startswith("lief-project/") or os.getenv("TRAVIS_REPO_SLUG", "").startswith("romainthomas/LIEF"))
return cond1 or cond2
elif ci == CI.APPVEYOR:
logger.info("%s - %s", os.getenv("APPVEYOR_PULL_REQUEST_NUMBER", -1), os.getenv("APPVEYOR_REPO_NAME", ""))
pr_number = os.getenv("APPVEYOR_PULL_REQUEST_NUMBER", "")
cond1 = len(pr_number) != 0 and int(pr_number) >= 0
cond2 = not (os.getenv("APPVEYOR_REPO_NAME", "").startswith("lief-project/") or os.getenv("APPVEYOR_REPO_NAME", "").startswith("romainthomas/"))
return cond1 or cond2
elif ci == CI.CIRCLE_CI:
cond1 = int(os.getenv("CIRCLE_PR_NUMBER", -1)) >= 0
cond2 = os.getenv("CIRCLE_PROJECT_USERNAME", "") != "lief-project" and os.getenv("CIRCLE_PROJECT_USERNAME", "") != "romainthomas"
return cond1 or cond2
elif ci == CI.GITHUB_ACTIONS:
cond1 = os.getenv("GITHUB_HEAD_REF", "") != ""
cond2 = not (os.getenv("GITHUB_REPOSITORY", "").startswith("lief-project/") or os.getenv("GITHUB_REPOSITORY", "").startswith("romainthomas/LIEF"))
return cond1 or cond2
elif ci == CI.LOCAL:
return False
return True
def get_branch(ci):
if ci == CI.TRAVIS:
return os.getenv("TRAVIS_BRANCH")
elif ci == CI.APPVEYOR:
return os.getenv("APPVEYOR_REPO_BRANCH")
elif ci == CI.CIRCLE_CI:
return os.getenv("CIRCLE_BRANCH")
elif ci == CI.GITHUB_ACTIONS:
return os.getenv("GITHUB_REF").replace("refs/heads/", "")
elif ci == CI.LOCAL:
return os.getenv("CI_BRANCH")
return None
def get_ci_workdir(ci):
if ci == CI.CIRCLE_CI:
return os.getenv("CIRCLE_WORKING_DIRECTORY")
elif ci == CI.TRAVIS:
return os.getenv("TRAVIS_BUILD_DIR")
elif ci == CI.APPVEYOR:
return os.getenv("APPVEYOR_BUILD_FOLDER")
elif ci == CI.GITHUB_ACTIONS:
return os.getenv("GITHUB_WORKSPACE")
elif ci == CI.LOCAL:
return os.getenv("CI_WORKING_DIR")
else:
logger.critical("Unsupported CI to resolve working directory")
sys.exit(1)
def get_tag(ci):
if ci == CI.CIRCLE_CI:
return os.getenv("CIRCLE_TAG", "")
elif ci == CI.TRAVIS:
return os.getenv("TRAVIS_TAG", "")
elif ci == CI.APPVEYOR:
if "APPVEYOR_REPO_TAG_NAME" in os.environ:
return os.getenv("APPVEYOR_REPO_TAG_NAME", "")
return ""
elif ci == CI.GITHUB_ACTIONS:
ref = os.getenv("GITHUB_REF", "")
logger.info("Github Action tag: {}".format(ref))
if ref.startswith("refs/tags/"):
return ref.replace("refs/tags/", "")
return ""
elif ci == CI.LOCAL:
return os.getenv("CI_TAG")
else:
logger.critical("Unsupported CI to resolve working directory")
sys.exit(1)
import argparse
import boto3
import functools
import logging
import os
import sys
import tempfile
import tomli
LOG_LEVEL = logging.INFO
CURRENTDIR = Path(__file__).resolve().parent
REPODIR = CURRENTDIR.parent
ASSET_DIR = CURRENTDIR / "assets"
CONFIG_DIR = CURRENTDIR / "config"
LIEF_S3_KEY = os.getenv("LIEF_S3_KEY", None)
LIEF_S3_SECRET = os.getenv("LIEF_S3_SECRET", None)
OWNED_ORGS = ["lief-project/", "romainthomas/"]
RELEASE_KEYWRD = "release-"
DEFAULT_CONFIG = CONFIG_DIR / "gh-ci.toml"
DEFAULT_TEMPLATE = (ASSET_DIR / "index.j2").read_text()
logging.getLogger().addHandler(logging.StreamHandler(stream=sys.stdout))
logging.getLogger().setLevel(LOG_LEVEL)
logger = logging.getLogger(__name__)
CURRENT_CI = CI.UNKNOWN
# Detect CI
# ===========================================
if os.getenv("TRAVIS", None) is not None:
CURRENT_CI = CI.TRAVIS
elif os.getenv("APPVEYOR", None) is not None:
CURRENT_CI = CI.APPVEYOR
elif os.getenv("GITHUB_ACTIONS", None) is not None:
CURRENT_CI = CI.GITHUB_ACTIONS
elif os.getenv("GITLAB_CI", None) is not None:
CURRENT_CI = CI.GITLAB_CI
elif os.getenv("CI_LOCAL", "") == "true":
CURRENT_CI = CI.LOCAL
else:
logger.error("Can't detect CI!")
sys.exit(1)
CI_PRETTY_NAME = pretty_ci_name(CURRENT_CI)
logger.info("CI: %s", CI_PRETTY_NAME)
ALLOWED_BRANCHES = {"master", "deploy", "devel"}
BRANCH_NAME = get_branch(CURRENT_CI)
TAG_NAME = get_tag(CURRENT_CI)
IS_TAGGED = TAG_NAME is not None and len(TAG_NAME) > 0
logger.info("Branch: %s", BRANCH_NAME)
logger.info("Tag: %s", TAG_NAME)
if BRANCH_NAME.startswith("release-"):
logger.info("Branch release")
elif BRANCH_NAME not in ALLOWED_BRANCHES and not IS_TAGGED:
logger.info("Skip deployment for branch '%s'", BRANCH_NAME)
sys.exit(0)
if is_pr(CURRENT_CI):
logger.info("Skip pull request")
sys.exit(0)
CURRENTDIR = pathlib.Path(__file__).resolve().parent
REPODIR = CURRENTDIR.parent
# According to Scaleway S3 documentation, the endpoint
# should starts with '<bucket>'.s3.<region>.scw.cloud
# Nevertheless boto3 uses /{Bucket} endpoints suffix
# which create issues (see: https://stackoverflow.com/a/70383653)
LIEF_S3_REGION = "fr-par"
LIEF_S3_ENDPOINT = "https://s3.{region}.scw.cloud".format(region=LIEF_S3_REGION)
LIEF_S3_BUCKET = "lief"
LIEF_S3_KEY = os.getenv("LIEF_S3_KEY", None)
LIEF_S3_SECRET = os.getenv("LIEF_S3_SECRET", None)
if LIEF_S3_KEY is None or len(LIEF_S3_KEY) == 0:
logger.error("LIEF_S3_KEY is not set!")
sys.exit(1)
if LIEF_S3_SECRET is None or len(LIEF_S3_SECRET) == 0:
logger.error("LIEF_S3_SECRET is not set!")
sys.exit(1)
CI_CWD = pathlib.Path(get_ci_workdir(CURRENT_CI))
class S3Manager:
def __init__(self, dirname: str, bucket: str,
region: str, endpoint: str,
dry_run: bool = False):
self._s3_dirname: str = dirname
self._s3_bucket: str = bucket
self._s3_region: str = region
self._s3_endpoint: str = endpoint
self._dry_run: bool = dry_run
if CI_CWD is None:
logger.error("Can't resolve CI working dir")
sys.exit(1)
logger.info("[S3] Bucket : %s", self._s3_bucket)
logger.info("[S3] Region : %s", self._s3_region)
logger.info("[S3] Endpoint: %s", self._s3_endpoint)
logger.info("[S3] Dir : %s", self._s3_dirname)
DIST_DIR = REPODIR / "dist"
BUILD_DIR = REPODIR / "build"
def change_dir(self, dirname: str):
self._s3_dirname = dirname
logger.info("Working directory: %s", CI_CWD)
@property
def s3_lief_sdk(self) -> str:
return f"{self._s3_dirname}/sdk"
INDEX_TEMPLATE = r"""
<!DOCTYPE html>
<html>
<title>Links for lief</title>
<body>
<h1>Links for lief</h1>
% for path, filename in files:
<a href="/${path}">${filename}</a><br />
% endfor
</body>
</html>
"""
@property
def s3_lief_wheel(self) -> str:
return f"{self._s3_dirname}/lief"
SKIP_LIST = ["index.html"]
@property
def url(self):
return f"https://{self._s3_bucket}.s3-website.{self._s3_region}.scw.cloud/{self._s3_dirname}"
s3 = boto3.resource(
's3',
region_name=LIEF_S3_REGION,
use_ssl=True,
endpoint_url=LIEF_S3_ENDPOINT,
aws_access_key_id=LIEF_S3_KEY,
aws_secret_access_key=LIEF_S3_SECRET
)
@functools.lru_cache(maxsize=1)
def s3(self) -> boto3.Session:
s3_res = boto3.resource(
's3',
region_name=self._s3_region,
use_ssl=True,
endpoint_url=self._s3_endpoint,
aws_access_key_id=LIEF_S3_KEY,
aws_secret_access_key=LIEF_S3_SECRET
)
return s3_res
@classmethod
def from_config(cls, config):
pass
def _s3_push(self, file: Path, dst: str):
logger.info("Uploading %s to %s", file, dst)
try:
obj = self.s3().Object(self._s3_bucket, dst)
if not self._dry_run:
obj.put(Body=file.read_bytes())
else:
logger.info("[--] put: %s/%s - %s", self._s3_bucket, dst, file.as_posix())
return 0
except ClientError as e:
logger.error("S3 push failed: %s", e)
return 1
def push_wheel(self, file: str):
wheel_file = Path(file)
if not wheel_file.is_file():
logger.error("'%s' is not a valid file!", wheel_file)
return
dst = f"{self.s3_lief_wheel}/{wheel_file.name}"
self._s3_push(wheel_file, dst)
def push_sdk(self, file: str):
sdk_path = Path(file)
if not sdk_path.is_file():
logger.error("'%s' is not a valid file!", sdk_path)
return
dst = f"{self.s3_lief_sdk}/{sdk_path.name}"
self._s3_push(sdk_path, dst)
def push_content(self, content: str, dst: str):
with tempfile.TemporaryDirectory() as tmp:
tmp_path = Path(tmp)
index = tmp_path / "index.html"
index.write_text(content)
self._s3_push(index, dst)
def process_sdk_wheels(self, directory: Path, maxdepth: int = 0,
depth: int = 0, recurse: bool = True):
logger.info("Processing directory: %s", directory)
for item in directory.iterdir():
if item.is_dir() and recurse:
if maxdepth > 0 and depth > maxdepth:
logger.debug("Maximum iteration depth reached")
else:
self.process_sdk_wheels(item, maxdepth, depth + 1, recurse)
elif item.is_file():
extension = item.suffix
if extension in (".zip", ".gz"):
logger.info("[SDK ] Uploading '%s'", item.as_posix())
self.push_sdk(item.as_posix())
elif extension in (".whl", ):
logger.info("[WHEEL] Uploading '%s'", item.as_posix())
self.push_wheel(item.as_posix())
def push_wheel(file: str, dir_name: str):
wheel_file = pathlib.Path(file)
dst = f"{dir_name}/lief/{wheel_file.name}"
logger.info("Uploading %s to %s", file, dst)
try:
obj = s3.Object(LIEF_S3_BUCKET, dst)
obj.put(Body=wheel_file.read_bytes())
return 0
except ClientError as e:
logger.error("S3 push failed: %s", e)
return 1
def upload_wheels_sdk(self, src_dir: Path, maxdepth: int):
logger.info("Looking for wheels and sdk from: %s", src_dir)
self.process_sdk_wheels(src_dir, maxdepth=maxdepth, recurse=True)
wheels_index = self.generate_index(self.s3_lief_wheel,
DEFAULT_TEMPLATE,
skiplist=("index.html", ))
sdk_index = self.generate_index(self.s3_lief_sdk, DEFAULT_TEMPLATE,
skiplist=("index.html", ))
self.push_content(wheels_index, f"{self.s3_lief_wheel}/index.html")
self.push_content(sdk_index, f"{self.s3_lief_sdk}/index.html")
logger.info("Done!")
logger.info("URL: %s/%s", self.url, "sdk")
logger.info("URL: %s/%s", self.url, "lief")
def s3_list(self, dirname: str) -> list[Any]:
if self._dry_run:
return []
return self.s3().Bucket(self._s3_bucket).objects.filter(Prefix=dirname)
def generate_index(self, dirname: str, template: str, skiplist = None):
files = self.s3_list(dirname)
selected_files = []
for s3_object in files:
filename = Path(s3_object.key).name
if skiplist is not None and filename in skiplist:
continue
selected_files.append((s3_object.key, filename))
return Template(template).render(files=selected_files)
class GithubDeploy:
def __init__(self, branches: list[str],
main_branches: list[str],
default_dir: str,
s3_manager: S3Manager):
self.s3_manager: S3Manager = s3_manager
self._branches: list[str] = branches
self._main_branches: list[str] = main_branches
self._default_dir: str = default_dir
def push_sdk(file: str, dir_name: str):
sdk_file = pathlib.Path(file)
dst = f"{dir_name}/sdk/{sdk_file.name}"
logger.info("Uploading %s to %s", file, dst)
try:
obj = s3.Object(LIEF_S3_BUCKET, dst)
obj.put(Body=sdk_file.read_bytes())
return 0
except ClientError as e:
logger.error("S3 push failed: %s", e)
return 1
@classmethod
def from_config(cls, config_file: Path):
with open(config_file, "rb") as f:
toml_config = tomli.load(f)
def filename(object):
return pathlib.Path(object.key).name
if not "lief" in toml_config:
logger.warning("Missing lief entries in '%s'", config_file)
return None
lief_conf = toml_config["lief"]
def generate_sdk_index(dir_name: str):
files = s3.Bucket(LIEF_S3_BUCKET).objects.filter(Prefix=f'{dir_name}/sdk')
tmpl_info = [(object.key, filename(object)) for object in files if filename(object) not in SKIP_LIST]
html = Template(INDEX_TEMPLATE).render(files=tmpl_info)
return html
if not "s3" in lief_conf:
logger.warning("Missing lief.s3 entries in '%s'", config_file)
return None
def generate_pypi_index(dir_name: str):
files = s3.Bucket(LIEF_S3_BUCKET).objects.filter(Prefix=f'{dir_name}/lief')
tmpl_info = [(object.key, filename(object)) for object in files if filename(object) not in SKIP_LIST]
html = Template(INDEX_TEMPLATE).render(files=tmpl_info)
return html
if not "deploy" in lief_conf:
logger.warning("Missing lief.deploy entries in '%s'", config_file)
return None
dir_name = "latest"
branches = lief_conf["deploy"]["branches"]
main_branches = lief_conf["deploy"]["main-branches"]
default_dir = lief_conf["deploy"]["default-dir"]
s3_config = lief_conf["s3"]
s3_region = s3_config["region"]
s3_bucket = s3_config["bucket"]
s3_endpoint = s3_config["endpoint"]
if BRANCH_NAME != "master":
dir_name = "{}".format(BRANCH_NAME.replace("/", "-").replace("_", "-"))
s3_manager = S3Manager(default_dir, s3_bucket, s3_region, s3_endpoint)
return cls(branches, main_branches, default_dir, s3_manager)
if BRANCH_NAME.startswith("release-"):
_, dir_name = BRANCH_NAME.split("release-")
@staticmethod
def branch() -> Optional[str]:
ref = os.getenv("GITHUB_REF")
if ref is None:
return None
return ref.replace("refs/heads/", "")
if IS_TAGGED:
dir_name = str(TAG_NAME)
@staticmethod
def is_pr() -> bool:
head_ref = os.getenv("GITHUB_HEAD_REF", "")
repo_path = os.getenv("GITHUB_REPOSITORY", "")
is_owned_repo = any(repo_path.startswith(org) for org in OWNED_ORGS)
return head_ref != "" or not is_owned_repo
logger.info("Destination directory: %s", dir_name)
@staticmethod
def is_tagged() -> bool:
tag = GithubDeploy.tag_name()
return tag is not None and len(tag) > 0
for file in DIST_DIR.glob("*.whl"):
logger.info("[WHEEL] Uploading '%s'", file.as_posix())
push_wheel(file.as_posix(), dir_name)
@staticmethod
def tag_name() -> Optional[str]:
ref = os.getenv("GITHUB_REF", "")
logger.info("Github Action tag: %s", ref)
if ref.startswith("refs/tags/"):
return ref.replace("refs/tags/", "")
return ""
for file in itertools.chain(BUILD_DIR.glob("*.zip"), BUILD_DIR.glob("*.tar.gz")):
logger.info("[SDK ] Uploading '%s'", file.as_posix())
push_sdk(file.as_posix(), dir_name)
@staticmethod
def workspace() -> str:
return os.getenv("GITHUB_WORKSPACE", "")
sdk_index = generate_sdk_index(dir_name)
with tempfile.TemporaryDirectory() as tmp:
tmp = pathlib.Path(tmp)
index = (tmp / "index.html")
index.write_text(sdk_index)
push_sdk(index.as_posix(), dir_name)
def is_main_branch(self, name: str) -> bool:
return False
pypi_index = generate_pypi_index(dir_name)
with tempfile.TemporaryDirectory() as tmp:
tmp = pathlib.Path(tmp)
index = (tmp / "index.html")
index.write_text(pypi_index)
push_wheel(index.as_posix(), dir_name)
def deploy(self, directories: list[str]):
s3dir = None
if GithubDeploy.is_tagged():
s3dir = GithubDeploy.tag_name()
else:
branch = GithubDeploy.branch()
if branch is None:
logger.warning("Can't resolve the branch name")
sys.exit(1)
logger.info("Done!")
if branch.startswith(RELEASE_KEYWRD):
_, s3dir = branch.split(RELEASE_KEYWRD)
elif self.is_main_branch(branch):
s3dir = self._default_dir
else:
s3dir = branch.replace("/", "-").replace("_", "-")
if s3dir is None:
logger.error("Target directory is not set")
sys.exit(1)
logger.info("s3dir: %s", s3dir)
self.s3_manager.change_dir(s3dir)
for dirname in directories:
dirpath = Path(dirname).resolve().absolute().expanduser()
self.s3_manager.upload_wheels_sdk(dirpath, maxdepth=1)
def main():
parser = argparse.ArgumentParser()
parser.add_argument("--config", "-c")
parser.add_argument("--dry-run", "-n", action="store_true", default=False)
parser.add_argument("directories", nargs="+")
args = parser.parse_args()
config_path = None
if args.config is not None:
config_path = Path(args.config)
else:
config_path = DEFAULT_CONFIG
if not config_path.is_file():
logger.error("'%s' is not a valid config path")
sys.exit(1)
gh_deploy = GithubDeploy.from_config(config_path)
gh_deploy.deploy(args.directories)
if __name__ == "__main__":
main()
sys.exit(0)
+42 -32
View File
@@ -2,8 +2,12 @@ name: 'Android'
on: push
jobs:
build-and-deploy:
build-sdk:
runs-on: ubuntu-latest
strategy:
matrix:
arch: ['arm', 'arm64']
fail-fast: false
steps:
- uses: actions/checkout@v3
with:
@@ -17,53 +21,59 @@ jobs:
uses: actions/cache@v3
with:
path: ~/.ccache
key: android-${{ runner.os }}-${{ steps.get-date.outputs.date }}
key: android-${{ runner.os }}-${{ matrix.arch }}-${{ steps.get-date.outputs.date }}
restore-keys: |
android-${{ runner.os }}-
- name: Build ARM SDK
android-${{ runner.os }}-${{ matrix.arch }}
- name: Build SDK [${{ matrix.arch }}]
shell: bash
env:
ARCH: ${{ matrix.arch }}
run: |
docker run \
-e CCACHE_COMPRESS=1 \
-e CCACHE_MAXSIZE=10.0G \
-e CCACHE_CPP2=1 \
-e CCACHE_DIR=/ccache \
docker run \
-e CCACHE_COMPRESS=1 \
-e CCACHE_MAXSIZE=10.0G \
-e CCACHE_CPP2=1 \
-e CCACHE_DIR=/ccache \
-v $GITHUB_WORKSPACE:/work \
-v $HOME/.ccache:/ccache \
--rm liefproject/android-arm bash /work/scripts/docker/android-arm.sh
- name: Build AArch64 SDK
shell: bash
run: |
docker run \
-e CCACHE_COMPRESS=1 \
-e CCACHE_MAXSIZE=10.0G \
-e CCACHE_CPP2=1 \
-e CCACHE_DIR=/ccache \
-v $GITHUB_WORKSPACE:/work \
-v $HOME/.ccache:/ccache \
--rm liefproject/android-arm64 bash /work/scripts/docker/android-aarch64.sh
-v $HOME/.ccache:/ccache \
--rm liefproject/android-${ARCH} bash /work/scripts/docker/android-${ARCH}.sh
- name: 'Upload Artifact'
uses: actions/upload-artifact@v3
with:
name: android-sdk
name: android-sdk-${{ matrix.arch }}
path: build/*.tar.gz
retention-days: 3
deploy:
if: ${{ always() }}
runs-on: ubuntu-latest
needs: build-sdk
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Download artifacts
uses: actions/download-artifact@v3
with:
path: ${{ runner.temp }}/artifacts
- name: Display artifacts
run: ls -R
working-directory: ${{ runner.temp }}/artifacts
- name: Deploy
env:
LIEF_S3_KEY: ${{ secrets.LIEF_S3_KEY }}
LIEF_S3_SECRET: ${{ secrets.LIEF_S3_SECRET }}
shell: bash
run: |
docker run \
-v $GITHUB_WORKSPACE:/src \
-e GITHUB_ACTIONS="true" \
-e GITHUB_WORKSPACE=$GITHUB_WORKSPACE \
-e GITHUB_REF=$GITHUB_REF \
docker run --rm \
-v $GITHUB_WORKSPACE:/src \
-v $RUNNER_TEMP:/runner_tmp \
-e GITHUB_ACTIONS="true" \
-e GITHUB_WORKSPACE=$GITHUB_WORKSPACE \
-e GITHUB_REF=$GITHUB_REF \
-e GITHUB_REPOSITORY=$GITHUB_REPOSITORY \
-e LIEF_S3_KEY=$LIEF_S3_KEY \
-e LIEF_S3_SECRET=$LIEF_S3_SECRET \
--rm \
liefproject/deploy python3 /src/.github/deploy.py
-e LIEF_S3_KEY=$LIEF_S3_KEY \
-e LIEF_S3_SECRET=$LIEF_S3_SECRET \
liefproject/deploy python3 /src/.github/deploy.py /runner_tmp/artifacts
+7 -4
View File
@@ -1,6 +1,9 @@
name: 'iOS'
on: push
env:
python-version: '3.10'
jobs:
osx-sdk:
runs-on: macos-11.0
@@ -8,10 +11,10 @@ jobs:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Set up Python 3.9
- name: Set up Python ${{ env.python-version }}
uses: actions/setup-python@v3
with:
python-version: 3.9
python-version: ${{ env.python-version }}
- name: Install system dependencies
run: |
brew install cmake ninja ccache
@@ -53,8 +56,8 @@ jobs:
LIEF_S3_SECRET: ${{ secrets.LIEF_S3_SECRET }}
shell: bash
run: |
python -m pip install --upgrade requests mako boto3
python .github/deploy.py
python -m pip install --upgrade requests mako boto3 tomli
python .github/deploy.py build/
+83 -38
View File
@@ -4,6 +4,49 @@ on: push
jobs:
linux-sdk:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Get Date
id: get-date
run: |
echo "date=$(/bin/date -u "+%Y-%m-%d-%H;%M;%S")" >> $GITHUB_OUTPUT
shell: bash
- name: ccache cache files
uses: actions/cache@v3
with:
path: ~/.ccache
key: linux-aarch64-${{ runner.os }}-sdk-${{ steps.get-date.outputs.date }}
restore-keys: |
linux-aarch64-${{ runner.os }}-sdk
- name: Build SDK
shell: bash
run: |
mkdir -p $RUNNER_TEMP/lief-install
docker run --name lief_sdk --rm \
-e CCACHE_COMPRESS=1 \
-e CCACHE_MAXSIZE=10.0G \
-e CCACHE_DIR=/ccache \
-v $GITHUB_WORKSPACE:/work \
-v $RUNNER_TEMP/lief-install:/install \
-v $HOME/.ccache:/ccache \
liefproject/manylinux2014-aarch64 bash /work/scripts/docker/linux-aarch64.sh
- name: 'Upload SDK Artifact'
uses: actions/upload-artifact@v3
with:
name: linux-aarch64-sdk
path: build/*.tar.gz
retention-days: 3
- name: 'Upload Install Artifact'
uses: actions/upload-artifact@v3
with:
name: linux-aarch64-install
path: ${{ runner.temp }}/lief-install
retention-days: 1
wheels:
runs-on: ubuntu-latest
needs: linux-sdk
strategy:
matrix:
python-version: [3.8, 3.9, '3.10', '3.11']
@@ -20,65 +63,67 @@ jobs:
uses: actions/cache@v3
with:
path: ~/.ccache
key: linux-aarch64-${{ runner.os }}-${{ steps.get-date.outputs.date }}
key: linux-aarch64-${{ runner.os }}-${{ matrix.python-version }}-${{ steps.get-date.outputs.date }}
restore-keys: |
linux-aarch64-${{ runner.os }}-
- name: Build SDK
if: matrix.python-version == '3.9'
shell: bash
run: |
docker run \
-e CCACHE_COMPRESS=1 \
-e CCACHE_MAXSIZE=10.0G \
-e CCACHE_CPP2=1 \
-e CCACHE_DIR=/ccache \
-v $GITHUB_WORKSPACE:/work \
-v $HOME/.ccache:/ccache \
--rm liefproject/manylinux2014-aarch64 bash /work/scripts/docker/linux-aarch64.sh
- name: Build Python ${{ matrix.python-version }} wheel
linux-aarch64-${{ runner.os }}-${{ matrix.python-version }}
- name: Download LIEF install dir
uses: actions/download-artifact@v3
with:
name: linux-aarch64-install
path: ${{ runner.temp }}/lief-install
- name: Python ${{ matrix.python-version }} -- Wheel
shell: bash
env:
PYTHON_VERSION: ${{ matrix.python-version }}
run: |
PYTHON_VERSION2=$(echo "${PYTHON_VERSION}" | sed 's/\.//') # Transform 3.8 -> 38
docker run \
-e CCACHE_COMPRESS=1 \
-e CCACHE_MAXSIZE=10.0G \
-e CCACHE_CPP2=1 \
-e CCACHE_DIR=/ccache \
-e PYTHON_BINARY=/opt/python/cp${PYTHON_VERSION2}-cp${PYTHON_VERSION2}/bin/python${PYTHON_VERSION} \
-v $GITHUB_WORKSPACE:/work \
-v $HOME/.ccache:/ccache \
--rm liefproject/manylinux2014-aarch64 bash /work/scripts/docker/manylinux2014-aarch64.sh
- name: 'Upload SDK Artifact'
if: matrix.python-version == '3.9'
PYTHON_VERSION_ALT=$(echo "${PYTHON_VERSION}" | sed 's/\.//') # Transform 3.8 -> 38
docker run --rm \
-e CCACHE_COMPRESS=1 \
-e CCACHE_MAXSIZE=10.0G \
-e CCACHE_CPP2=1 \
-e CCACHE_DIR=/ccache \
-e PYTHON_VERSION=$PYTHON_VERSION_ALT \
-e PYTHON_BINARY=/opt/python/cp${PYTHON_VERSION_ALT}-cp${PYTHON_VERSION_ALT}/bin/python${PYTHON_VERSION} \
-v $GITHUB_WORKSPACE:/work \
-v $HOME/.ccache:/ccache \
-v $RUNNER_TEMP/lief-install:/install \
liefproject/manylinux2014-aarch64 bash /work/scripts/docker/manylinux2014-aarch64.sh
- name: 'Artifact'
uses: actions/upload-artifact@v3
with:
name: linux-aarch64-sdk
path: build/*.tar.gz
retention-days: 3
- name: 'Upload Python Wheel Artifact - ${{ matrix.python-version }}'
uses: actions/upload-artifact@v3
with:
name: linux-aarch64-wheel-${{ matrix.python-version }}
name: linux-aarch64-python${{ matrix.python-version }}-wheel
path: dist/*.whl
retention-days: 3
deploy:
runs-on: ubuntu-latest
if: ${{ always() }}
needs: [linux-sdk, wheels]
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Download artifacts
uses: actions/download-artifact@v3
with:
path: ${{ runner.temp }}/artifacts
- name: Display artifacts
run: ls -R
working-directory: ${{ runner.temp }}/artifacts
- name: Deploy
env:
LIEF_S3_KEY: ${{ secrets.LIEF_S3_KEY }}
LIEF_S3_SECRET: ${{ secrets.LIEF_S3_SECRET }}
shell: bash
run: |
docker run \
docker run --rm \
-v $GITHUB_WORKSPACE:/src \
-v $RUNNER_TEMP:/runner_tmp \
-e GITHUB_ACTIONS="true" \
-e GITHUB_WORKSPACE=$GITHUB_WORKSPACE \
-e GITHUB_REF=$GITHUB_REF \
-e GITHUB_REPOSITORY=$GITHUB_REPOSITORY \
-e LIEF_S3_KEY=$LIEF_S3_KEY \
-e LIEF_S3_SECRET=$LIEF_S3_SECRET \
--rm \
liefproject/deploy python3 /src/.github/deploy.py
liefproject/deploy python3 /src/.github/deploy.py /runner_tmp/artifacts
+128 -109
View File
@@ -17,102 +17,20 @@ jobs:
uses: actions/cache@v3
with:
path: ~/.ccache
key: linux-x86-64-${{ runner.os }}-${{ steps.get-date.outputs.date }}
key: linux-x86-64-${{ runner.os }}-sdk-${{ steps.get-date.outputs.date }}
restore-keys: |
linux-x86-64-${{ runner.os }}-
- name: Build Python 3.8 wheel & test
shell: bash
env:
PYTHON_VERSION: 38
run: |
docker run --rm \
-e CCACHE_COMPRESS=1 \
-e CCACHE_MAXSIZE=10.0G \
-e CCACHE_CPP2=1 \
-e CCACHE_DIR=/ccache \
-e PYTHON_VERSION=$PYTHON_VERSION \
-e PYTHON_BINARY=/opt/python/cp38-cp38/bin/python3.8 \
-v $GITHUB_WORKSPACE:/src \
-v $HOME/.ccache:/ccache \
liefproject/manylinux_2_28_x86_64 bash /src/scripts/docker/run_linux_test.sh
- name: Build Python 3.9 wheel
shell: bash
env:
PYTHON_VERSION: 39
run: |
docker run --rm \
-e CCACHE_COMPRESS=1 \
-e CCACHE_MAXSIZE=10.0G \
-e CCACHE_CPP2=1 \
-e CCACHE_DIR=/ccache \
-e PYTHON_VERSION=$PYTHON_VERSION \
-e PYTHON_BINARY=/opt/python/cp39-cp39/bin/python3.9 \
-v $GITHUB_WORKSPACE:/src \
-v $HOME/.ccache:/ccache \
liefproject/manylinux_2_28_x86_64 bash /src/scripts/docker/run_linux.sh
- name: Build Python 3.10 wheel
shell: bash
env:
PYTHON_VERSION: 310
run: |
docker run --rm \
-e CCACHE_COMPRESS=1 \
-e CCACHE_MAXSIZE=10.0G \
-e CCACHE_CPP2=1 \
-e CCACHE_DIR=/ccache \
-e PYTHON_VERSION=$PYTHON_VERSION \
-e PYTHON_BINARY=/opt/python/cp310-cp310/bin/python3.10 \
-v $GITHUB_WORKSPACE:/src \
-v $HOME/.ccache:/ccache \
liefproject/manylinux_2_28_x86_64 bash /src/scripts/docker/run_linux.sh
- name: Test LIEF on Archlinux
shell: bash
env:
PYTHON_VERSION: 310
run: |
docker run --rm \
-v $GITHUB_WORKSPACE:/src \
liefproject/archlinux bash /src/scripts/docker/run_archlinux.sh
- name: Build Python 3.11 wheel
shell: bash
env:
PYTHON_VERSION: 311
run: |
docker run --rm \
-e CCACHE_COMPRESS=1 \
-e CCACHE_MAXSIZE=10.0G \
-e CCACHE_CPP2=1 \
-e CCACHE_DIR=/ccache \
-e PYTHON_VERSION=$PYTHON_VERSION \
-e PYTHON_BINARY=/opt/python/cp311-cp311/bin/python3.11 \
-v $GITHUB_WORKSPACE:/src \
-v $HOME/.ccache:/ccache \
liefproject/manylinux_2_28_x86_64 bash /src/scripts/docker/run_linux.sh
- name: Build Python 3.12 wheel
shell: bash
env:
PYTHON_VERSION: 312
run: |
docker run --rm \
-e CCACHE_COMPRESS=1 \
-e CCACHE_MAXSIZE=10.0G \
-e CCACHE_CPP2=1 \
-e CCACHE_DIR=/ccache \
-e PYTHON_VERSION=$PYTHON_VERSION \
-e PYTHON_BINARY=/opt/python/cp312-cp312/bin/python3.12 \
-v $GITHUB_WORKSPACE:/src \
-v $HOME/.ccache:/ccache \
liefproject/manylinux_2_28_x86_64 bash /src/scripts/docker/run_linux.sh
linux-x86-64-${{ runner.os }}-sdk
- name: Build SDK
shell: bash
run: |
docker run --name lief_sdk --rm \
-e PYTHON_BINARY=/opt/python/cp39-cp39/bin/python3.9 \
-e CCACHE_COMPRESS=1 \
-e CCACHE_MAXSIZE=10.0G \
-e CCACHE_DIR=/ccache \
-v $GITHUB_WORKSPACE:/src \
-v $HOME/.ccache:/ccache \
mkdir -p $RUNNER_TEMP/lief-install
docker run --name lief_sdk --rm \
-e CCACHE_COMPRESS=1 \
-e CCACHE_MAXSIZE=10.0G \
-e CCACHE_DIR=/ccache \
-v $GITHUB_WORKSPACE:/src \
-v $RUNNER_TEMP/lief-install:/install \
-v $HOME/.ccache:/ccache \
liefproject/manylinux_2_28_x86_64 bash /src/scripts/docker/run_linux_sdk.sh
- name: 'Upload SDK Artifact'
uses: actions/upload-artifact@v3
@@ -120,40 +38,141 @@ jobs:
name: linux-x86-64-sdk
path: build/*.tar.gz
retention-days: 3
- name: 'Upload SDK Artifact'
- name: 'Upload Install Artifact'
uses: actions/upload-artifact@v3
with:
name: linux-x86-64-python-wheel
name: linux-x86-64-install
path: ${{ runner.temp }}/lief-install
retention-days: 1
testing:
if: "!contains(github.event.commits[0].message, '[skip-test]')"
runs-on: ubuntu-latest
needs: linux-sdk
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Get Date
id: get-date
run: |
echo "date=$(/bin/date -u "+%Y-%m-%d-%H;%M;%S")" >> $GITHUB_OUTPUT
shell: bash
- name: ccache cache files
uses: actions/cache@v3
with:
path: ~/.ccache
key: linux-x86-64-${{ runner.os }}-test-${{ steps.get-date.outputs.date }}
restore-keys: |
linux-x86-64-${{ runner.os }}-test
- name: Python 3.8 -- Wheel & Test
shell: bash
env:
PYTHON_VERSION: 38
run: |
docker run --rm \
-e CCACHE_COMPRESS=1 \
-e CCACHE_MAXSIZE=10.0G \
-e CCACHE_CPP2=1 \
-e CCACHE_DIR=/ccache \
-e PYTHON_VERSION=$PYTHON_VERSION \
-e PYTHON_BINARY=/opt/python/cp38-cp38/bin/python3.8 \
-v $GITHUB_WORKSPACE:/src \
-v $HOME/.ccache:/ccache \
liefproject/manylinux_2_28_x86_64 bash /src/scripts/docker/run_linux_test.sh
pywheels:
runs-on: ubuntu-latest
needs: linux-sdk
strategy:
matrix:
python-version: ['3.8', '3.9', '3.10', '3.11', '3.12']
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Get Date
id: get-date
run: |
echo "date=$(/bin/date -u "+%Y-%m-%d-%H;%M;%S")" >> $GITHUB_OUTPUT
shell: bash
- name: ccache cache files
uses: actions/cache@v3
with:
path: ~/.ccache
key: linux-x86-64-${{ runner.os }}-${{ matrix.python-version }}-${{ steps.get-date.outputs.date }}
restore-keys: |
linux-x86-64-${{ runner.os }}-${{ matrix.python-version }}
- name: Download LIEF install dir
uses: actions/download-artifact@v3
with:
name: linux-x86-64-install
path: ${{ runner.temp }}/lief-install
- name: Python ${{ matrix.python-version }} -- Wheel
shell: bash
env:
PYTHON_VERSION: ${{ matrix.python-version }}
run: |
PYTHON_VERSION_ALT=$(echo "${PYTHON_VERSION}" | sed 's/\.//') # Transform 3.8 -> 38
docker run --rm \
-e CCACHE_COMPRESS=1 \
-e CCACHE_MAXSIZE=10.0G \
-e CCACHE_CPP2=1 \
-e CCACHE_DIR=/ccache \
-e PYTHON_VERSION=$PYTHON_VERSION_ALT \
-e PYTHON_BINARY=/opt/python/cp${PYTHON_VERSION_ALT}-cp${PYTHON_VERSION_ALT}/bin/python${PYTHON_VERSION} \
-v $GITHUB_WORKSPACE:/src \
-v $HOME/.ccache:/ccache \
-v $RUNNER_TEMP/lief-install:/install \
liefproject/manylinux_2_28_x86_64 bash /src/scripts/docker/run_linux.sh
- name: 'Artifact'
uses: actions/upload-artifact@v3
with:
name: linux-x86-64-python${{ matrix.python-version }}-wheel
path: dist/*.whl
retention-days: 3
deploy:
runs-on: ubuntu-latest
if: ${{ always() }}
needs: [linux-sdk, pywheels]
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Download artifacts
uses: actions/download-artifact@v3
with:
path: ${{ runner.temp }}/artifacts
- name: Display artifacts
run: ls -R
working-directory: ${{ runner.temp }}/artifacts
- name: Deploy
env:
LIEF_S3_KEY: ${{ secrets.LIEF_S3_KEY }}
LIEF_S3_SECRET: ${{ secrets.LIEF_S3_SECRET }}
shell: bash
run: |
docker run \
docker run --rm \
-v $GITHUB_WORKSPACE:/src \
-v $RUNNER_TEMP:/runner_tmp \
-e GITHUB_ACTIONS="true" \
-e GITHUB_WORKSPACE=$GITHUB_WORKSPACE \
-e GITHUB_REF=$GITHUB_REF \
-e GITHUB_REPOSITORY=$GITHUB_REPOSITORY \
-e LIEF_S3_KEY=$LIEF_S3_KEY \
-e LIEF_S3_SECRET=$LIEF_S3_SECRET \
--rm \
liefproject/deploy python3 /src/.github/deploy.py
liefproject/deploy python3 /src/.github/deploy.py /runner_tmp/artifacts
documentation:
needs: [deploy]
runs-on: ubuntu-latest
container:
image: liefproject/manylinux_2_28_x86_64
env:
CIRCLE_CI_URL: "https://circleci.com/api/v2/project/gh/lief-project/doc/pipeline"
CIRCLE_CI_TOKEN: ${{ secrets.CIRCLE_CI_TOKEN }}
steps:
- name: Trigger documentation
if: github.ref == 'refs/heads/master'
env:
CIRCLE_CI_TOKEN: ${{ secrets.CIRCLE_CI_TOKEN }}
shell: bash
run: |
docker run --rm \
-e CIRCLE_CI_TOKEN=$CIRCLE_CI_TOKEN \
liefproject/manylinux_2_28_x86_64 \
bash -c "curl --request POST --url https://circleci.com/api/v2/project/gh/lief-project/doc/pipeline --header 'Circle-Token: ${CIRCLE_CI_TOKEN}' --header 'content-type: application/json'";
curl --request POST --url ${CIRCLE_CI_URL} \
--header "Circle-Token: ${CIRCLE_CI_TOKEN}" \
--header 'content-type: application/json' \
--data '{"parameters":{"lief-branch":"master"}}'
-66
View File
@@ -1,66 +0,0 @@
name: 'macOS-arm64'
on:
push:
tags:
- '**'
workflow_dispatch:
jobs:
osx-sdk:
runs-on: macos-11.0
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Set up Python 3.10
uses: actions/setup-python@v4
with:
python-version: "3.10"
- name: Install system dependencies
run: |
brew install cmake ninja ccache
python -m pip install --upgrade pip setuptools wheel
- name: Get Date
id: get-date
run: |
echo "date=$(/bin/date -u "+%Y-%m-%d-%H;%M;%S")" >> $GITHUB_OUTPUT
shell: bash
- name: Setup cache dir
shell: bash
run: |
mkdir -p ~/.ccache
- name: ccache cache files
uses: actions/cache@v3
with:
path: ~/.ccache
key: osx-${{ runner.os }}-${{ steps.get-date.outputs.date }}
restore-keys: |
osx-${{ runner.os }}-
- name: Upgrade pip
shell: bash
run: |
python -m pip install --upgrade pip setuptools
- name: Build SDK
shell: bash
env:
MACOSX_DEPLOYMENT_TARGET: "11.0"
CCACHE_DIR: ~/.ccache
CCACHE_MAXSIZE: 10.0G
CCACHE_CPP2: 1
CCACHE_COMPRESS: 1
run: |
bash scripts/osx/package_sdk_aarch64.sh
- name: 'Upload SDK Artifact'
uses: actions/upload-artifact@v3
with:
name: osx-sdk
path: build/*.tar.gz
retention-days: 3
- name: Deploy
env:
LIEF_S3_KEY: ${{ secrets.LIEF_S3_KEY }}
LIEF_S3_SECRET: ${{ secrets.LIEF_S3_SECRET }}
shell: bash
run: |
python -m pip install --upgrade requests mako boto3
python .github/deploy.py
+160 -72
View File
@@ -1,12 +1,130 @@
name: 'macOS'
on: push
env:
python-test-version: '3.10'
jobs:
osx-sdk:
runs-on: macos-11.0
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Install system dependencies
run: |
brew install cmake ninja ccache
- name: Get Date
id: get-date
run: |
echo "date=$(/bin/date -u "+%Y-%m-%d-%H;%M;%S")" >> $GITHUB_OUTPUT
shell: bash
- name: Setup cache dir
shell: bash
run: |
mkdir -p $RUNNER_TEMP/.ccache
- name: ccache cache files
uses: actions/cache@v3
with:
path: ${{ runner.temp }}/.ccache
key: osx-${{ runner.os }}-sdk-${{ steps.get-date.outputs.date }}
restore-keys: |
osx-${{ runner.os }}-sdk
- name: Build SDK
shell: bash
env:
MACOSX_DEPLOYMENT_TARGET: "11.0"
CCACHE_DIR: ${{ runner.temp }}/.ccache
CCACHE_MAXSIZE: 10.0G
CCACHE_CPP2: 1
CCACHE_COMPRESS: 1
run: |
bash scripts/osx/package_sdk.sh
- name: 'Upload SDK Artifact'
uses: actions/upload-artifact@v3
with:
name: osx-sdk
path: build/*.tar.gz
retention-days: 3
- name: 'Upload install artifact [arm64]'
uses: actions/upload-artifact@v3
with:
name: osx-arm64-install
path: install/arm64
retention-days: 1
- name: 'Upload install artifact [x64]'
uses: actions/upload-artifact@v3
with:
name: osx-x64-install
path: install/x64
retention-days: 1
osx-testing:
runs-on: macos-11.0
if: "!contains(github.event.commits[0].message, '[skip-test]')"
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Set up Python ${{ env.python-test-version }}
uses: actions/setup-python@v4
with:
python-version: ${{ env.python-test-version }}
- name: Install system dependencies
run: |
brew install cmake ninja ccache
python -m pip install --upgrade pip setuptools wheel
- name: Get Date
id: get-date
run: |
echo "date=$(/bin/date -u "+%Y-%m-%d-%H;%M;%S")" >> $GITHUB_OUTPUT
shell: bash
- name: Setup cache dir
shell: bash
run: |
mkdir -p $RUNNER_TEMP/.ccache
- name: ccache cache files
uses: actions/cache@v3
with:
path: ${{ runner.temp }}/.ccache
key: osx-${{ runner.os }}-test-${{ steps.get-date.outputs.date }}
restore-keys: |
osx-${{ runner.os }}-test
- name: Upgrade pip
shell: bash
run: |
python -m pip install --upgrade pip setuptools
- name: Build Python 3.10 with tests
shell: bash
env:
LIEF_SAMPLES_DIR: "/tmp/samples"
BUILD_DIR: "/tmp/lief-build"
MACOSX_TARGET: "11.7"
MACOSX_DEPLOYMENT_TARGET: "11.0"
CCACHE_DIR: ${{ runner.temp }}/.ccache
CCACHE_MAXSIZE: 10.0G
CCACHE_CPP2: 1
CCACHE_COMPRESS: 1
run: |
python -m pip install pytest requests
python tests/dl_samples.py ${LIEF_SAMPLES_DIR}
cd api/python
PYLIEF_CONF=${GITHUB_WORKSPACE}/scripts/osx/osx-testing-x64.toml \
python ./setup.py build \
--build-base=${BUILD_DIR}/base \
--build-temp=${BUILD_DIR}/temp \
install --user
cd ${GITHUB_WORKSPACE}
python tests/run_pytest.py
python tests/run_tools_check.py ${BUILD_DIR}/temp
ctest --output-on-failure --test-dir ${BUILD_DIR}/temp
wheels:
runs-on: macos-11.0
needs: osx-sdk
strategy:
matrix:
python-version: [3.8, 3.9, '3.10', '3.11', '3.12-dev']
python-version: [3.8, 3.9, '3.10', '3.11']
arch: ['x64', 'arm64']
fail-fast: false
steps:
- uses: actions/checkout@v3
with:
@@ -27,100 +145,70 @@ jobs:
- name: Setup cache dir
shell: bash
run: |
mkdir -p ~/.ccache
mkdir -p $RUNNER_TEMP/.ccache
- name: ccache cache files
uses: actions/cache@v3
with:
path: ~/.ccache
key: osx-${{ runner.os }}-${{ steps.get-date.outputs.date }}
path: ${{ runner.temp }}/.ccache
key: osx-${{ runner.os }}-${{ matrix.arch }}-${{ matrix.python-version }}-${{ steps.get-date.outputs.date }}
restore-keys: |
osx-${{ runner.os }}-
osx-${{ runner.os }}-${{ matrix.arch }}-${{ matrix.python-version }}
- name: Upgrade pip
shell: bash
run: |
python -m pip install --upgrade pip setuptools
#
# Run LIEF tests on Python 3.8 (only)
# ========================================
- name: Build Python ${{ matrix.python-version }} wheel & test
- name: Download LIEF install dir
uses: actions/download-artifact@v3
with:
name: osx-${{ matrix.arch }}-install
path: ~/lief-${{ matrix.arch }}-install
- name: Build Python ${{ matrix.python-version }} [${{ matrix.arch }}]
shell: bash
if: matrix.python-version == '3.8'
env:
LIEF_SAMPLES_DIR: "/tmp/samples"
MACOSX_TARGET: "11.7"
MACOSX_DEPLOYMENT_TARGET: "10.14"
CCACHE_DIR: ~/.ccache
CCACHE_MAXSIZE: 10.0G
CCACHE_CPP2: 1
CCACHE_COMPRESS: 1
run: |
python -m pip install pytest requests
python tests/dl_samples.py ${LIEF_SAMPLES_DIR}
python -m pip -vv wheel --wheel-dir=dist/ api/python
python -m pip -vv install api/python
python ./tests/run_pytest.py
cmake -S . -B ./api/python/build/temp.macosx-${MACOSX_TARGET}-x86_64-cpython-38 -DLIEF_TESTS=on
ninja -C ./api/python/build/temp.macosx-${MACOSX_TARGET}-x86_64-cpython-38
python ./tests/run_tools_check.py ./api/python/build/temp.macosx-${MACOSX_TARGET}-x86_64-cpython-38
ctest --output-on-failure --test-dir ./api/python/build/temp.macosx-${MACOSX_TARGET}-x86_64-cpython-38
- name: Build Python ${{ matrix.python-version }} wheel (x86-64)
shell: bash
if: matrix.python-version != '3.8'
env:
MACOSX_DEPLOYMENT_TARGET: "10.14"
CCACHE_DIR: ~/.ccache
CCACHE_MAXSIZE: 10.0G
CCACHE_CPP2: 1
CCACHE_COMPRESS: 1
run: |
python -m pip wheel --wheel-dir=dist/ api/python
#
# cross-compile for Apple M1 for Python >= 3.9
# ============================================
- name: Build Python ${{ matrix.python-version }} wheel (arm64)
shell: bash
if: matrix.python-version != '3.8'
env:
MACOSX_DEPLOYMENT_TARGET: "11.0"
CCACHE_DIR: ~/.ccache
CCACHE_DIR: ${{ runner.temp }}/.ccache
CCACHE_MAXSIZE: 10.0G
CCACHE_CPP2: 1
CCACHE_COMPRESS: 1
PYLIEF_CONF: "${{ github.workspace }}/scripts/osx/py-${{ matrix.arch }}.toml"
run: |
PYLIEF_CONF="$(pwd)/scripts/osx/config-xcompile-arm64.toml" \
python -m pip -vv wheel --wheel-dir=dist/ api/python
#
# Build the SDK while running with Python 3.9 (only once)
# =======================================================
- name: Build SDK
shell: bash
if: matrix.python-version == '3.9' # Build the SDD only with Python 3.9
env:
MACOSX_DEPLOYMENT_TARGET: "10.14"
CCACHE_DIR: ~/.ccache
CCACHE_MAXSIZE: 10.0G
CCACHE_CPP2: 1
CCACHE_COMPRESS: 1
run: |
bash scripts/osx/package_sdk.sh
- name: 'Upload SDK Artifact'
if: matrix.python-version == '3.9' # Build the SDk only with Python 3.9
- name: 'Upload Python wheel artifact - ${{ matrix.python-version }}'
uses: actions/upload-artifact@v3
with:
name: osx-sdk
path: build/*.tar.gz
retention-days: 3
- name: 'Upload Python Wheel Artifact - ${{ matrix.python-version }}'
uses: actions/upload-artifact@v3
with:
name: osx-wheel-${{ matrix.python-version }}
name: osx-wheel-${{ matrix.arch }}-${{ matrix.python-version }}
path: dist/*.whl
retention-days: 3
deploy:
runs-on: ubuntu-latest
if: ${{ always() }}
needs: [osx-sdk, wheels]
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Download artifacts
uses: actions/download-artifact@v3
with:
path: ${{ runner.temp }}/artifacts
- name: Display artifacts
run: ls -R
working-directory: ${{ runner.temp }}/artifacts
- name: Deploy
env:
LIEF_S3_KEY: ${{ secrets.LIEF_S3_KEY }}
LIEF_S3_SECRET: ${{ secrets.LIEF_S3_SECRET }}
shell: bash
run: |
python -m pip install --upgrade requests mako boto3
python .github/deploy.py
docker run --rm \
-v $GITHUB_WORKSPACE:/src \
-v $RUNNER_TEMP:/runner_tmp \
-e GITHUB_ACTIONS="true" \
-e GITHUB_WORKSPACE=$GITHUB_WORKSPACE \
-e GITHUB_REF=$GITHUB_REF \
-e GITHUB_REPOSITORY=$GITHUB_REPOSITORY \
-e LIEF_S3_KEY=$LIEF_S3_KEY \
-e LIEF_S3_SECRET=$LIEF_S3_SECRET \
liefproject/deploy python3 /src/.github/deploy.py /runner_tmp/artifacts
+33 -17
View File
@@ -1,13 +1,13 @@
name: LIEF PR
on: [pull_request, workflow_dispatch]
env:
python-osx-version: '3.10'
python-win-version: '3.10'
jobs:
osx:
runs-on: macos-11.0
strategy:
matrix:
python-version: ["3.10"]
steps:
- uses: actions/checkout@v2
with:
@@ -15,20 +15,29 @@ jobs:
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
python-version: ${{ env.python-osx-version }}
- name: Install system dependencies
run: |
brew install cmake ninja ccache
python -m pip install --upgrade pip setuptools wheel
- name: Build with Python ${{ matrix.python-version }} & Test
- name: Build with Python ${{ env.python-osx-version }} & Test
shell: bash
env:
LIEF_SAMPLES_DIR: "/tmp/samples"
BUILD_DIR: "/tmp/lief-build"
run: |
python -m pip install pytest requests
python tests/dl_samples.py ${LIEF_SAMPLES_DIR}
python -m pip -vv install api/python
python ./tests/run_pytest.py
cd api/python
PYLIEF_CONF=${GITHUB_WORKSPACE}/scripts/osx/osx-testing-x64.toml \
python ./setup.py build \
--build-base=${BUILD_DIR}/base \
--build-temp=${BUILD_DIR}/temp \
install --user
cd ${GITHUB_WORKSPACE}
python tests/run_pytest.py
python tests/run_tools_check.py ${BUILD_DIR}/temp
ctest --output-on-failure --test-dir ${BUILD_DIR}/temp
linux:
runs-on: ubuntu-latest
steps:
@@ -47,21 +56,17 @@ jobs:
liefproject/manylinux_2_28_x86_64 bash /src/scripts/docker/run_linux_test.sh
windows:
runs-on: windows-latest
strategy:
matrix:
python-version: [3.9]
steps:
- uses: actions/checkout@v2
- name: Set up Python ${{ matrix.python-version }}
- name: Set up Python ${{ env.python-win-version }}
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
python-version: ${{ env.python-win-version }}
architecture: x64
- name: Install system dependencies
run: |
choco install ninja
python -m pip install --upgrade pip setuptools
python -m pip install wheel mako
- uses: ilammy/msvc-dev-cmd@v1
with:
toolset: "14.16"
@@ -69,12 +74,23 @@ jobs:
run: |
chcp 65001 #set code page to utf-8
echo ("LIEF_SAMPLES_DIR=" + $env:RUNNER_TEMP + "/samples") >> $env:GITHUB_ENV
- name: Build and Test
echo ("BUILD_DIR=" + $env:RUNNER_TEMP + "/lief-build") >> $env:GITHUB_ENV
echo ("PYLIEF_CONF=" + $env:GITHUB_WORKSPACE + "/scripts/windows/py-x64-test.toml") >> $env:GITHUB_ENV
- name: Build Python ${{ env.python-win-version }}
run: |
python -m pip install pytest requests
python tests/dl_samples.py %LIEF_SAMPLES_DIR%
python -m pip -vv install api/python
python ./tests/run_pytest.py
cd api/python
python ./setup.py build ^
--build-base=%BUILD_DIR%/base ^
--build-temp=%BUILD_DIR%/temp ^
install --user
shell: cmd
- name: Run tests
run: |
cd %GITHUB_WORKSPACE%
python tests/run_pytest.py
ctest --output-on-failure --test-dir %BUILD_DIR%/temp/Release
shell: cmd
+1 -7
View File
@@ -1,11 +1,5 @@
name: 'sanitize'
on:
push:
tags:
- '**'
schedule:
- cron: '0 0 * * 1'
workflow_dispatch:
on: workflow_dispatch
jobs:
gcc:
+256
View File
@@ -0,0 +1,256 @@
name: LIEF Windows
on:
push:
branches:
- 'master'
- 'release-**'
tags:
- '**'
env:
python-test-version: '3.10'
python-version: '3.9'
jobs:
build-sdk:
runs-on: windows-2019
strategy:
matrix:
arch: ['x64', 'x86']
fail-fast: false
env:
SCCACHE_CACHE_SIZE: 2G
SCCACHE_DIR: ${{ vars.SCCACHE_DIR }}
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: ${{ env.python-version }}
architecture: ${{ matrix.arch }}
- name: Install system dependencies
run: |
choco install ninja
choco install sccache
- uses: ilammy/msvc-dev-cmd@v1
with:
toolset: "14.16"
- name: Get Date
id: get-date
run: |
echo "date=$(/bin/date -u "+%Y-%m-%d-%H;%M;%S")" >> $GITHUB_OUTPUT
shell: bash
- name: Setup sccache
uses: actions/cache@v3
continue-on-error: false
with:
path: ${{ vars.SCCACHE_DIR }}
key: ${{ runner.os }}-${{ matrix.arch }}-sccache-sdk-${{ steps.get-date.outputs.date }}
restore-keys: |
${{ runner.os }}-${{ matrix.arch }}-sccache-sdk
- name: Start sccache server
run: sccache --start-server
- name: Build SDK
run: |
python ./scripts/windows/package_sdk.py
- name: 'Upload SDK artifact'
uses: actions/upload-artifact@v3
with:
name: windows-${{ matrix.arch }}-sdk
path: build/*.zip
retention-days: 3
- name: 'Upload install artifact'
uses: actions/upload-artifact@v3
with:
name: windows-${{ matrix.arch }}-install
path: ${{ runner.temp }}/lief-install
retention-days: 1
- name: sccache stats
run: sccache --show-stats
- name: stop sccache server
run: sccache --stop-server || true
tests:
runs-on: windows-2019
if: "!contains(github.event.commits[0].message, '[skip-test]')"
strategy:
matrix:
arch: ['x64']
fail-fast: false
env:
SCCACHE_CACHE_SIZE: 2G
SCCACHE_DIR: ${{ vars.SCCACHE_DIR }}
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Set up Python ${{ env.python-test-version }}
uses: actions/setup-python@v4
with:
python-version: ${{ env.python-test-version }}
architecture: ${{ matrix.arch }}
- name: Install system dependencies
run: |
choco install ninja
choco install sccache
- uses: ilammy/msvc-dev-cmd@v1
with:
toolset: "14.16"
- name: Get Date
id: get-date
run: |
echo "date=$(/bin/date -u "+%Y-%m-%d-%H;%M;%S")" >> $GITHUB_OUTPUT
shell: bash
- name: Setup sccache
uses: actions/cache@v3
continue-on-error: false
with:
path: ${{ vars.SCCACHE_DIR }}
key: ${{ runner.os }}-${{ matrix.arch }}-sccache-test-${{ steps.get-date.outputs.date }}
restore-keys: |
${{ runner.os }}-${{ matrix.arch }}-sccache-test
- name: Start sccache server
run: sccache --start-server
- name: Set arch specific env
if: matrix.arch == 'x64'
run: |
echo "ARCH=x64" >> $env:GITHUB_ENV
- name: Set arch specific env
if: matrix.arch == 'x86'
run: |
echo "ARCH=x86" >> $env:GITHUB_ENV
- name: Set Python config (${{ matrix.arch }})
run: |
echo ("PYLIEF_CONF=" + $env:GITHUB_WORKSPACE + "/scripts/windows/py-" + $env:ARCH + "-test.toml") >> $env:GITHUB_ENV
- name: Set env variables
run: |
chcp 65001 #set code page to utf-8
echo ("LIEF_SAMPLES_DIR=" + $env:RUNNER_TEMP + "/samples") >> $env:GITHUB_ENV
echo ("BUILD_DIR=" + $env:RUNNER_TEMP + "/lief-build") >> $env:GITHUB_ENV
- name: Build Python ${{ env.python-test-version }}
run: |
python -m pip install pytest requests
python tests/dl_samples.py %LIEF_SAMPLES_DIR%
cd api/python
python ./setup.py build ^
--build-base=%BUILD_DIR%/base ^
--build-temp=%BUILD_DIR%/temp ^
install --user
shell: cmd
- name: Run tests
run: |
cd %GITHUB_WORKSPACE%
python tests/run_pytest.py
ctest --output-on-failure --test-dir %BUILD_DIR%/temp/Release
shell: cmd
- name: sccache stats
run: sccache --show-stats
- name: stop sccache server
run: sccache --stop-server || true
wheels:
runs-on: windows-2019
needs: build-sdk
strategy:
matrix:
python-version: [3.8, 3.9, '3.10', '3.11', '3.12-dev']
arch: ['x86', 'x64']
fail-fast: false
env:
SCCACHE_CACHE_SIZE: 2G
SCCACHE_DIR: ${{ vars.SCCACHE_DIR }}
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
architecture: ${{ matrix.arch }}
- name: Install system dependencies
run: |
choco install ninja
choco install sccache
python -m pip install --upgrade pip setuptools
python -m pip install wheel mako
- uses: ilammy/msvc-dev-cmd@v1
with:
toolset: "14.16"
- name: Get Date
id: get-date
run: |
echo "date=$(/bin/date -u "+%Y-%m-%d-%H;%M;%S")" >> $GITHUB_OUTPUT
shell: bash
- name: Save sccache
uses: actions/cache@v3
continue-on-error: false
with:
path: ${{ vars.SCCACHE_DIR }}
key: ${{ runner.os }}-${{ matrix.arch }}-sccache-${{ matrix.python-version }}-${{ steps.get-date.outputs.date }}
restore-keys: |
${{ runner.os }}-${{ matrix.arch }}-sccache-${{ matrix.python-version }}
- name: Download LIEF install dir
uses: actions/download-artifact@v3
with:
name: windows-${{ matrix.arch }}-install
path: ~/lief-${{ matrix.arch }}-install
- name: Start sccache server
run: sccache --start-server
- name: Upgrade pip
run: |
python -m pip install --upgrade pip
shell: cmd
- name: Set arch specific env
if: matrix.arch == 'x64'
run: |
echo "ARCH=x64" >> $env:GITHUB_ENV
- name: Set arch specific env
if: matrix.arch == 'x86'
run: |
echo "ARCH=x86" >> $env:GITHUB_ENV
- name: Set Python config (${{ matrix.arch }})
run: |
echo ("PYLIEF_CONF=" + $env:GITHUB_WORKSPACE + "/scripts/windows/py-" + $env:ARCH + ".toml") >> $env:GITHUB_ENV
- name: Set env variables
run: |
chcp 65001 #set code page to utf-8
- name: Build Python ${{ matrix.python-version }}
run: |
python -m pip -vv wheel --wheel-dir=dist/ api/python
shell: cmd
- name: 'Upload Python artifacts [${{ matrix.python-version }}]'
uses: actions/upload-artifact@v3
with:
name: windows-${{ matrix.arch }}-wheel-${{ matrix.python-version }}
path: dist/*.whl
retention-days: 3
deploy:
if: ${{ always() }}
runs-on: ubuntu-latest
needs: [build-sdk, wheels]
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Download artifacts
uses: actions/download-artifact@v3
with:
path: ${{ runner.temp }}/artifacts
- name: Deploy
env:
LIEF_S3_KEY: ${{ secrets.LIEF_S3_KEY }}
LIEF_S3_SECRET: ${{ secrets.LIEF_S3_SECRET }}
shell: bash
run: |
docker run --rm \
-v $GITHUB_WORKSPACE:/src \
-v $RUNNER_TEMP:/runner_tmp \
-e GITHUB_ACTIONS="true" \
-e GITHUB_WORKSPACE=$GITHUB_WORKSPACE \
-e GITHUB_REF=$GITHUB_REF \
-e GITHUB_REPOSITORY=$GITHUB_REPOSITORY \
-e LIEF_S3_KEY=$LIEF_S3_KEY \
-e LIEF_S3_SECRET=$LIEF_S3_SECRET \
liefproject/deploy python3 /src/.github/deploy.py /runner_tmp/artifacts
@@ -1,6 +1,4 @@
name: LIEF Windows x64 Quick
name: LIEF Windows Quick
on:
push:
branches:
@@ -10,24 +8,28 @@ on:
tags-ignore:
- "**"
env:
python-version: '3.9'
jobs:
build:
quick-test:
runs-on: windows-2019
strategy:
matrix:
python-version: [3.9]
arch: [x64, x86]
fail-fast: false
env:
SCCACHE_CACHE_SIZE: 2G
SCCACHE_DIR: "C:\\Users\\runner\\AppData\\Local\\Mozilla\\sccache"
SCCACHE_DIR: ${{ vars.SCCACHE_DIR }}
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
- name: Set up Python ${{ env.python-version }}
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
architecture: x64
python-version: ${{ env.python-version }}
architecture: ${{ matrix.python-version }}
- name: Install system dependencies
run: |
choco install ninja
@@ -46,10 +48,10 @@ jobs:
uses: actions/cache@v3
continue-on-error: false
with:
path: "C:\\Users\\runner\\AppData\\Local\\Mozilla\\sccache"
key: ${{ runner.os }}-x64-sccache-${{ steps.get-date.outputs.date }}
path: ${{ vars.SCCACHE_DIR }}
key: ${{ runner.os }}-${{ matrix.arch }}-quick-${{ steps.get-date.outputs.date }}
restore-keys: |
${{ runner.os }}-x64-sccache-
${{ runner.os }}-${{ matrix.arch }}-quick
- name: Start sccache server
run: sccache --start-server
- name: Set env variables
@@ -60,14 +62,17 @@ jobs:
run: |
python -m pip install --upgrade pip
shell: cmd
- name: ⛓ Build Python ${{ matrix.python-version }} & Test
- name: Build Python ${{ env.python-version }}
run: |
python -m pip install pytest requests
python tests/dl_samples.py %LIEF_SAMPLES_DIR%
python -m pip -vv install api/python
shell: cmd
- name: Run tests
run: |
python ./tests/run_pytest.py
shell: cmd
- name: 📊 Print sccache stats
- name: sccache stats
run: sccache --show-stats
- name: 🛑 Stop sccache server
- name: sccache server
run: sccache --stop-server || true
-130
View File
@@ -1,130 +0,0 @@
name: LIEF Windows x64
on:
push:
branches:
- 'master'
- 'release-**'
tags:
- '**'
jobs:
build:
runs-on: windows-2019
strategy:
matrix:
python-version: [3.8, 3.9, '3.10', '3.11', '3.12-dev']
fail-fast: false
env:
SCCACHE_CACHE_SIZE: 2G
SCCACHE_DIR: "C:\\Users\\runner\\AppData\\Local\\Mozilla\\sccache"
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
architecture: x64
- name: Install system dependencies
run: |
choco install ninja
choco install sccache
python -m pip install --upgrade pip setuptools
python -m pip install wheel mako
- uses: ilammy/msvc-dev-cmd@v1
with:
toolset: "14.16"
- name: Get Date
id: get-date
run: |
echo "date=$(/bin/date -u "+%Y-%m-%d-%H;%M;%S")" >> $GITHUB_OUTPUT
shell: bash
- name: Save sccache
uses: actions/cache@v3
continue-on-error: false
with:
path: "C:\\Users\\runner\\AppData\\Local\\Mozilla\\sccache"
key: ${{ runner.os }}-x64-sccache-${{ steps.get-date.outputs.date }}
restore-keys: |
${{ runner.os }}-x64-sccache-
- name: Start sccache server
run: sccache --start-server
- name: Set env variables
run: |
chcp 65001 #set code page to utf-8
echo ("LIEF_SAMPLES_DIR=" + $env:RUNNER_TEMP + "/samples") >> $env:GITHUB_ENV
- name: Upgrade pip
run: |
python -m pip install --upgrade pip
shell: cmd
- name: ⛓ Build Python ${{ matrix.python-version }} & Test
if: matrix.python-version == 3.8
run: |
python -m pip install pytest requests
python tests/dl_samples.py %LIEF_SAMPLES_DIR%
python -m pip -vv wheel --wheel-dir=dist/ api/python
python -m pip -vv install api/python
python ./tests/run_pytest.py
python ./scripts/windows/run_ctest.py ./api/python/build/temp.win-amd64-cpython-38/Release
python ./tests/run_tools_check.py ./api/python/build/temp.win-amd64-cpython-38/Release
shell: cmd
- name: ❱ Build Python ${{ matrix.python-version }}
if: matrix.python-version != 3.8
run: |
python -m pip -vv wheel --wheel-dir=dist/ api/python
shell: cmd
- name: ❱ Build SDK
if: matrix.python-version == 3.9
run: |
python ./scripts/windows/package_sdk.py
- name: 'Upload SDK Artifact'
if: matrix.python-version == 3.9
uses: actions/upload-artifact@v3
with:
name: windows-x64-sdk
path: build/*.zip
retention-days: 3
- name: 'Upload Python Wheel Artifact - ${{ matrix.python-version }}'
uses: actions/upload-artifact@v3
with:
name: windows-x64-wheel-${{ matrix.python-version }}
path: dist/*.whl
retention-days: 3
- name: 📊 Print sccache stats
run: sccache --show-stats
- name: 🛑 Stop sccache server
run: sccache --stop-server || true
- name: Setup WSL
uses: Vampire/setup-wsl@v2
with:
distribution: Debian
use-cache: 'true'
wsl-shell-user: root
set-as-default: 'true'
wsl-conf: |
[automount]
options = "metadata"
additional-packages:
ca-certificates
curl
locales
python3 python3-pip
git
openssl
ssh
- shell: wsl-bash {0}
name: Deploy
env:
LIEF_S3_KEY: ${{ secrets.LIEF_S3_KEY }}
LIEF_S3_SECRET: ${{ secrets.LIEF_S3_SECRET }}
GITHUB_ACTIONS: "true"
GITHUB_WORKSPACE: ${{ env.GITHUB_WORKSPACE }}
GITHUB_REF: ${{ env.GITHUB_REF }}
GITHUB_REPOSITORY: ${{ env.GITHUB_REPOSITORY }}
WSLENV: LIEF_S3_KEY:LIEF_S3_SECRET:GITHUB_ACTIONS:GITHUB_WORKSPACE:GITHUB_REF:GITHUB_REPOSITORY
run: |
python3 -m pip install --no-cache-dir --upgrade pip setuptools requests mako wheel boto3
python3 .github/deploy.py
-132
View File
@@ -1,132 +0,0 @@
name: LIEF Windows x86
on:
push:
branches:
- 'master'
- 'release-**'
- 'devel'
tags:
- '**'
jobs:
build:
runs-on: windows-2019
strategy:
matrix:
python-version: [3.8, 3.9, '3.10', '3.11', '3.12-dev']
fail-fast: false
env:
SCCACHE_CACHE_SIZE: 2G
SCCACHE_DIR: "C:\\Users\\runner\\AppData\\Local\\Mozilla\\sccache"
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
architecture: x86
- name: Install system dependencies
run: |
choco install ninja
choco install sccache
python -m pip install --upgrade pip setuptools
python -m pip install wheel mako
- uses: ilammy/msvc-dev-cmd@v1
with:
toolset: "14.16"
- name: Get Date
id: get-date
run: |
echo "date=$(/bin/date -u "+%Y-%m-%d-%H;%M;%S")" >> $GITHUB_OUTPUT
shell: bash
- name: Save sccache
uses: actions/cache@v3
continue-on-error: false
with:
path: "C:\\Users\\runner\\AppData\\Local\\Mozilla\\sccache"
key: ${{ runner.os }}-x86-sccache-${{ steps.get-date.outputs.date }}
restore-keys: |
${{ runner.os }}-x86-sccache-
- name: Start sccache server
run: sccache --start-server
- name: Set env variables
run: |
chcp 65001 #set code page to utf-8
echo ("LIEF_SAMPLES_DIR=" + $env:RUNNER_TEMP + "/samples") >> $env:GITHUB_ENV
- name: Set env variables
run: |
chcp 65001 #set code page to utf-8
echo ("PYLIEF_CONF=" + $env:GITHUB_WORKSPACE + "/scripts/windows/config-win32.toml") >> $env:GITHUB_ENV
- name: Upgrade pip
run: |
python -m pip install --upgrade pip
shell: cmd
- name: ⛓ Build Python ${{ matrix.python-version }} & Test
if: matrix.python-version == 3.8
run: |
python -m pip install pytest requests
python tests/dl_samples.py %LIEF_SAMPLES_DIR%
python -m pip -vv wheel --wheel-dir=dist/ api/python
python -m pip -vv install api/python
python ./tests/run_pytest.py
python ./scripts/windows/run_ctest.py ./api/python/build/temp.win32-cpython-38/Release
shell: cmd
- name: ❱ Build Python ${{ matrix.python-version }}
if: matrix.python-version != 3.8
run: |
python -m pip -vv wheel --wheel-dir=dist/ api/python
shell: cmd
- name: ❱ Build SDK
if: matrix.python-version == 3.9
run: |
python ./scripts/windows/package_sdk.py
- name: 'Upload SDK Artifact'
if: matrix.python-version == 3.9
uses: actions/upload-artifact@v3
with:
name: windows-x86-sdk
path: build/*.zip
retention-days: 3
- name: 'Upload Python Wheel Artifact - ${{ matrix.python-version }}'
uses: actions/upload-artifact@v3
with:
name: windows-x86-wheel-${{ matrix.python-version }}
path: dist/*.whl
retention-days: 3
- name: 📊 Print sccache stats
run: sccache --show-stats
- name: 🛑 Stop sccache server
run: sccache --stop-server || true
- name: Setup WSL
uses: Vampire/setup-wsl@v2
with:
distribution: Debian
use-cache: 'true'
wsl-shell-user: root
set-as-default: 'true'
wsl-conf: |
[automount]
options = "metadata"
additional-packages:
ca-certificates
curl
locales
python3 python3-pip
git
openssl
ssh
- shell: wsl-bash {0}
name: Deploy
env:
LIEF_S3_KEY: ${{ secrets.LIEF_S3_KEY }}
LIEF_S3_SECRET: ${{ secrets.LIEF_S3_SECRET }}
GITHUB_ACTIONS: "true"
GITHUB_WORKSPACE: ${{ env.GITHUB_WORKSPACE }}
GITHUB_REF: ${{ env.GITHUB_REF }}
GITHUB_REPOSITORY: ${{ env.GITHUB_REPOSITORY }}
WSLENV: LIEF_S3_KEY:LIEF_S3_SECRET:GITHUB_ACTIONS:GITHUB_WORKSPACE:GITHUB_REF:GITHUB_REPOSITORY
run: |
python3 -m pip install --no-cache-dir --upgrade pip setuptools requests mako wheel boto3
python3 .github/deploy.py
-73
View File
@@ -1,73 +0,0 @@
name: LIEF Windows x86 Quick
on:
push:
branches:
- '**'
- '!master'
- '!release-**'
tags-ignore:
- "**"
jobs:
build:
runs-on: windows-2019
strategy:
matrix:
python-version: [3.9]
env:
SCCACHE_CACHE_SIZE: 2G
SCCACHE_DIR: "C:\\Users\\runner\\AppData\\Local\\Mozilla\\sccache"
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
architecture: x86
- name: Install system dependencies
run: |
choco install ninja
choco install sccache
python -m pip install --upgrade pip setuptools
python -m pip install wheel mako
- uses: ilammy/msvc-dev-cmd@v1
with:
toolset: "14.16"
- name: Get Date
id: get-date
run: |
echo "date=$(/bin/date -u "+%Y-%m-%d-%H;%M;%S")" >> $GITHUB_OUTPUT
shell: bash
- name: Save sccache
uses: actions/cache@v3
continue-on-error: false
with:
path: "C:\\Users\\runner\\AppData\\Local\\Mozilla\\sccache"
key: ${{ runner.os }}-x86-sccache-${{ steps.get-date.outputs.date }}
restore-keys: |
${{ runner.os }}-x86-sccache-
- name: Start sccache server
run: sccache --start-server
- name: Set env variables
run: |
chcp 65001 #set code page to utf-8
echo ("LIEF_SAMPLES_DIR=" + $env:RUNNER_TEMP + "/samples") >> $env:GITHUB_ENV
- name: Upgrade pip
run: |
python -m pip install --upgrade pip
shell: cmd
- name: ⛓ Build Python ${{ matrix.python-version }} & Test
run: |
python -m pip install pytest requests
python tests/dl_samples.py %LIEF_SAMPLES_DIR%
python -m pip -vv install api/python
python ./tests/run_pytest.py
shell: cmd
- name: 📊 Print sccache stats
run: sccache --show-stats
- name: 🛑 Stop sccache server
run: sccache --stop-server || true
+4 -13
View File
@@ -203,7 +203,10 @@ source_group("Source Files" FILES ${LIBLIEF_SOURCE_FILES})
source_group("Header Files\\visitors" FILES ${LIEF_VISITOR_INCLUDE_FILES})
add_library(LIB_LIEF ${LIBLIEF_SOURCE_FILES} ${LIEF_INCLUDE_FILES})
add_library(LIEF::LIEF ALIAS LIB_LIEF)
if(NOT LIEF_PY_LIEF_EXT)
add_library(LIEF::LIEF ALIAS LIB_LIEF)
endif()
if(NOT LIEF_OPT_MBEDTLS_EXTERNAL)
set_source_files_properties(${mbedtls_src_crypto} PROPERTIES GENERATED TRUE)
@@ -457,8 +460,6 @@ else()
${CMAKE_CURRENT_BINARY_DIR}/include/LIEF/third-party/internal/span.hpp)
endif()
target_link_libraries(LIB_LIEF PRIVATE lief_spdlog)
if(ANDROID AND BUILD_SHARED_LIBS AND LIEF_LOGGING)
@@ -557,20 +558,10 @@ endif()
include(LIEFCompilerFlags)
# Profiling flags
# ---------------
if(LIEF_PROFILING)
add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/profiling")
endif()
# Coverage flags
# --------------
if(LIEF_COVERAGE)
target_compile_options(LIB_LIEF PRIVATE -g -O0 --coverage -fprofile-arcs
-ftest-coverage)
target_link_libraries(LIB_LIEF gcov)
endif()
set_target_properties(LIB_LIEF PROPERTIES
OUTPUT_NAME LIEF
EXPORT_NAME LIEF
+69 -106
View File
@@ -1,16 +1,25 @@
cmake_minimum_required(VERSION 3.1)
find_package(Python COMPONENTS Interpreter Development.Module REQUIRED)
find_package(Python REQUIRED COMPONENTS Interpreter Development.Module)
if (LIEF_PY_LIEF_EXT)
find_package(LIEF REQUIRED COMPONENTS STATIC)
message(STATUS "Using pre-installed version of LIEF")
set(LIEF_TARGET LIEF::LIEF)
else()
set(LIEF_TARGET LIB_LIEF)
endif()
include(FetchContent)
# Avoid warning about DOWNLOAD_EXTRACT_TIMESTAMP in CMake 3.24:
if (CMAKE_VERSION VERSION_GREATER_EQUAL "3.24.0")
cmake_policy(SET CMP0135 NEW)
endif()
include(ExternalProject)
include(CheckCXXCompilerFlag)
include(CheckCCompilerFlag)
macro(ADD_FLAG_IF_SUPPORTED flag name)
CHECK_C_COMPILER_FLAG("${flag}" "C_SUPPORTS_${name}")
CHECK_CXX_COMPILER_FLAG("${flag}" "CXX_SUPPORTS_${name}")
@@ -24,143 +33,102 @@ macro(ADD_FLAG_IF_SUPPORTED flag name)
endif()
endmacro()
add_library(lief_pybind11 INTERFACE)
if (LIEF_EXTERNAL_PYBIND11)
find_package(pybind11 REQUIRED)
find_package(PythonLibsNew MODULE REQUIRED)
target_link_libraries(lief_pybind11 INTERFACE pybind11::module)
get_target_property(PYBIND_INC_DIR pybind11::module INTERFACE_INCLUDE_DIRECTORIES)
target_include_directories(lief_pybind11 SYSTEM INTERFACE ${PYBIND_INC_DIR} ${Python_INCLUDE_DIRS})
if (LIEF_EXTERNAL_NANOBINDS)
find_package(nanobind REQUIRED)
else()
find_package(PythonLibsNew MODULE REQUIRED)
set(PYBIND11_VERSION 2.10.1)
set(PYBIND11_SHA256 SHA256=fcf94065efcfd0a7a828bacf118fa11c43f6390d0c805e3e6342ac119f2e9976)
set(PYBIND11_URL "${THIRD_PARTY_DIRECTORY}/pybind11-${PYBIND11_VERSION}.zip" CACHE STRING "URL to the Pybind11 repo")
ExternalProject_Add(lief_pybind11_project
URL ${PYBIND11_URL}
URL_HASH ${PYBIND11_SHA256}
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND "")
add_dependencies(lief_pybind11 lief_pybind11_project)
ExternalProject_get_property(lief_pybind11_project SOURCE_DIR)
target_include_directories(lief_pybind11 SYSTEM INTERFACE "${SOURCE_DIR}/include")
set(NANOBIND_VERSION 1c462d6)
set(NANOBIND_SHA256 SHA256=84e8334c97aa870fa5531108f945b77c24ad30addf09f9cb40c04ffc1f6f757b)
set(NANOBIND_URL "${THIRD_PARTY_DIRECTORY}/nanobind-${NANOBIND_VERSION}.zip" CACHE STRING "URL to the Nanobind")
FetchContent_Declare(nanobind
URL ${NANOBIND_URL}
URL_HASH ${NANOBIND_SHA256}
)
FetchContent_Populate(nanobind)
find_package(nanobind REQUIRED PATHS ${nanobind_SOURCE_DIR}/cmake NO_DEFAULT_PATH)
endif()
message(STATUS "Python version: ${PYTHON_VERSION}")
message(STATUS "Python lib: ${PYTHON_LIBRARY}")
message(STATUS "Python include: ${PYTHON_INCLUDE_DIR}")
message(STATUS "Python interpreter: ${PYTHON_EXECUTABLE}")
# Define source files
set(LIEF_PYTHON_BASIC_SRC
"${CMAKE_CURRENT_SOURCE_DIR}/src/pyLIEF.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/src/pyUtils.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/src/pyLogger.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/src/pyHash.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/src/pyObject.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/src/pyErr.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/src/encoding.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/src/PyIOStream.cpp"
)
list(APPEND LIEF_PYTHON_BASIC_SRC
"${CMAKE_CURRENT_SOURCE_DIR}/src/pyJson.cpp")
message(STATUS "Python version: ${Python_VERSION}")
message(STATUS "Python lib: ${Python_LIBRARIES}")
message(STATUS "Python include: ${Python_INCLUDE_DIRS}")
message(STATUS "Python interpreter: ${Python_EXECUTABLE}")
set(LIEF_PYTHON_SRC
${LIEF_PYTHON_BASIC_SRC}
)
set(LIEF_PYTHON_BASIC_HDR
"${CMAKE_CURRENT_SOURCE_DIR}/src/pyErr.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/src/pyIterators.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/src/pyLIEF.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/src/enums_wrapper.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/src/encoding.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/src/PyIOStream.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/src/pyLIEF.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/src/pySafeString.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/src/pyErr.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/src/pyIOStream.cpp"
)
set(LIEF_PYTHON_HDR
${LIEF_PYTHON_BASIC_HDR}
"${CMAKE_CURRENT_SOURCE_DIR}/src/pyLIEF.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/src/pyErr.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/src/pySafeString.hpp"
)
source_group("Header Files" FILES ${LIEF_PYTHON_BASIC_HDR})
nanobind_add_module(
pyLIEF
NB_STATIC
add_library(pyLIEF SHARED ${LIEF_PYTHON_SRC} ${LIEF_PYTHON_HDR})
${LIEF_PYTHON_SRC}
${LIEF_PYTHON_HDR}
# Do not default to -Os
NOMINSIZE
)
target_include_directories(pyLIEF PUBLIC
"${CMAKE_CURRENT_SOURCE_DIR}/src"
)
target_include_directories(pyLIEF SYSTEM PRIVATE
"${PYTHON_INCLUDE_DIR}"
"${PYBIND11_SOURCE_DIR}/include")
include("${CMAKE_CURRENT_SOURCE_DIR}/src/Abstract/CMakeLists.txt")
add_subdirectory(src/Abstract)
add_subdirectory(src/platforms)
if(LIEF_ELF)
include("${CMAKE_CURRENT_SOURCE_DIR}/src/ELF/CMakeLists.txt")
add_subdirectory(src/ELF)
endif()
if(LIEF_PE)
include("${CMAKE_CURRENT_SOURCE_DIR}/src/PE/CMakeLists.txt")
add_subdirectory(src/PE)
endif()
if(LIEF_MACHO)
include("${CMAKE_CURRENT_SOURCE_DIR}/src/MachO/CMakeLists.txt")
add_subdirectory(src/MachO)
endif()
if(LIEF_OAT)
include("${CMAKE_CURRENT_SOURCE_DIR}/src/OAT/CMakeLists.txt")
add_subdirectory(src/OAT)
endif()
if(LIEF_DEX)
include("${CMAKE_CURRENT_SOURCE_DIR}/src/DEX/CMakeLists.txt")
add_subdirectory(src/DEX)
endif()
if(LIEF_VDEX)
include("${CMAKE_CURRENT_SOURCE_DIR}/src/VDEX/CMakeLists.txt")
add_subdirectory(src/VDEX)
endif()
if(LIEF_ART)
include("${CMAKE_CURRENT_SOURCE_DIR}/src/ART/CMakeLists.txt")
add_subdirectory(src/ART)
endif()
include("${CMAKE_CURRENT_SOURCE_DIR}/src/platforms/CMakeLists.txt")
target_compile_features(pyLIEF PRIVATE cxx_attribute_deprecated)
set_target_properties(pyLIEF PROPERTIES
POSITION_INDEPENDENT_CODE ON
CXX_STANDARD 17
CXX_STANDARD_REQUIRED ON
CXX_VISIBILITY_PRESET hidden
C_VISIBILITY_PRESET hidden
PREFIX ""
OUTPUT_NAME "lief"
)
set_target_properties(pyLIEF PROPERTIES PYTHON_VERSION ${PYTHON_VERSION})
set(PYLIEF_DEPS_LIBRARIES LIB_LIEF)
if(LIEF_COVERAGE)
target_compile_options(pyLIEF PRIVATE -g -O0 --coverage -fprofile-arcs -ftest-coverage)
set(PYLIEF_DEPS_LIBRARIES ${PYLIEF_DEPS_LIBRARIES} gcov)
endif()
ADD_FLAG_IF_SUPPORTED("-Wno-macro-redefined" NO_MACRO_REDEFINED)
ADD_FLAG_IF_SUPPORTED("-Wno-deprecated-declarations" NO_DEPRECATED_DECLARATIONS)
set_target_properties(pyLIEF PROPERTIES PREFIX "" OUTPUT_NAME "lief")
target_link_libraries(pyLIEF PRIVATE lief_pybind11 lief_spdlog)
set_target_properties(pyLIEF PROPERTIES PYTHON_VERSION ${Python_VERSION})
target_link_libraries(pyLIEF PUBLIC ${LIEF_TARGET})
if(APPLE)
set_target_properties(pyLIEF PROPERTIES
MACOSX_RPATH ON
LINK_FLAGS "-undefined dynamic_lookup "
)
set_target_properties(pyLIEF PROPERTIES
MACOSX_RPATH ON
LINK_FLAGS "-undefined dynamic_lookup "
)
endif()
set_target_properties(pyLIEF PROPERTIES PREFIX "")
@@ -175,24 +143,19 @@ get_target_property(suffix pyLIEF SUFFIX)
set(LIEF_LIBRARY_NAME "lief${suffix}")
if (WIN32)
set(PYLIEF_DEPS_LIBRARIES ${PYLIEF_DEPS_LIBRARIES} ${PYTHON_LIBRARIES})
target_link_libraries(pyLIEF PUBLIC ${PYTHON_LIBRARIES})
endif()
target_link_libraries(pyLIEF PUBLIC ${PYLIEF_DEPS_LIBRARIES})
if (CMAKE_BUILD_TYPE MATCHES Release AND UNIX AND NOT APPLE)
add_custom_command(
TARGET pyLIEF
COMMENT "Strip LIEF Python bindings"
POST_BUILD
COMMAND ${CMAKE_STRIP} --strip-all $<TARGET_FILE:pyLIEF>
)
add_custom_command(TARGET pyLIEF
COMMENT "Strip LIEF Python bindings"
POST_BUILD
COMMAND ${CMAKE_STRIP} --strip-all $<TARGET_FILE:pyLIEF>
)
endif()
if (CMAKE_BUILD_TYPE MATCHES Release AND APPLE)
add_custom_command(
TARGET pyLIEF
add_custom_command(TARGET pyLIEF
COMMENT "Strip LIEF Python bindings"
POST_BUILD
COMMAND ${CMAKE_STRIP} -x -S $<TARGET_FILE:pyLIEF>
@@ -200,12 +163,12 @@ if (CMAKE_BUILD_TYPE MATCHES Release AND APPLE)
endif()
add_custom_command(TARGET pyLIEF POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:pyLIEF> ${PROJECT_BINARY_DIR}/api/python/lief
COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:pyLIEF> ${PROJECT_BINARY_DIR}/api/python/lief
)
if (MSVC)
add_custom_command(TARGET pyLIEF POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:pyLIEF> ${CMAKE_CURRENT_BINARY_DIR}
COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:pyLIEF> ${CMAKE_CURRENT_BINARY_DIR}
)
endif()
@@ -257,7 +257,7 @@ def main():
args = parser.parse_args()
lief.logging.set_level(args.main_verbosity)
if lief.PE.is_pe(args.file):
if lief.is_pe(args.file):
binary = None
try:
binary: lief.PE.Binary = lief.PE.parse(args.file)
+4 -4
View File
@@ -254,13 +254,13 @@ def print_relocations(binary, relocations):
for relocation in relocations:
type = str(relocation.type)
if binary.header.machine_type == ELF.ARCH.x86_64:
type = str(ELF.RELOCATION_X86_64(relocation.type))
type = str(relocation.type)
elif binary.header.machine_type == ELF.ARCH.i386:
type = str(ELF.RELOCATION_i386(relocation.type))
type = str(relocation.type)
elif binary.header.machine_type == ELF.ARCH.ARM:
type = str(ELF.RELOCATION_ARM(relocation.type))
type = str(relocation.type)
elif binary.header.machine_type == ELF.ARCH.AARCH64:
type = str(ELF.RELOCATION_AARCH64(relocation.type))
type = str(relocation.type)
symbol_name = ""
if relocation.has_symbol:
+6 -24
View File
@@ -598,26 +598,11 @@ def print_relocations(binary):
for reloc in binary.relocations:
type_str = ""
if reloc.origin == lief.MachO.RELOCATION_ORIGINS.DYLDINFO:
type_str = str(lief.MachO.REBASE_TYPES(reloc.type)).split(".")[-1]
if reloc.origin == lief.MachO.RELOCATION_ORIGINS.RELOC_TABLE:
if reloc.architecture == MachO.CPU_TYPES.x86:
type_str = str(MachO.X86_RELOCATION(reloc.type))
if reloc.architecture == MachO.CPU_TYPES.x86_64:
type_str = str(MachO.X86_64_RELOCATION(reloc.type))
if reloc.architecture == MachO.CPU_TYPES.ARM:
type_str = str(MachO.ARM_RELOCATION(reloc.type))
if reloc.architecture == MachO.CPU_TYPES.ARM64:
type_str = str(MachO.ARM64_RELOCATION(reloc.type))
if reloc.architecture == MachO.CPU_TYPES.POWERPC:
type_str = str(MachO.PPC_RELOCATION(reloc.type))
type_str = type_str.split(".")[-1]
rtype = reloc.type
if isinstance(rtype, int):
type_str = str(rtype)
else:
type_str = str(rtype).split(".")[-1]
symbol_name = ""
if reloc.has_symbol:
@@ -1019,9 +1004,6 @@ def main():
if args.show_chained_fixups or args.show_all:
print_chained_fixups(binary)
sys.exit(EXIT_STATUS)
if __name__ == "__main__":
main()
sys.exit(EXIT_STATUS)
+7 -16
View File
@@ -1,4 +1,4 @@
from typing import ClassVar, List
from typing import Any, ClassVar
from typing import overload
import lief # type: ignore
@@ -31,7 +31,7 @@ class Header(lief.Object):
@property
def image_size(self) -> int: ...
@property
def magic(self) -> List[int]: ...
def magic(self) -> list[int]: ...
@property
def nb_methods(self) -> int: ...
@property
@@ -54,29 +54,20 @@ class Header(lief.Object):
def version(self) -> int: ...
class STORAGE_MODES:
__members__: ClassVar[dict] = ... # read-only
LZ4: ClassVar[STORAGE_MODES] = ...
LZ4HC: ClassVar[STORAGE_MODES] = ...
UNCOMPRESSED: ClassVar[STORAGE_MODES] = ...
__entries: ClassVar[dict] = ...
def __init__(self, value: int) -> None: ...
@property
def name(self) -> str: ...
@property
def value(self) -> int: ...
__name__: Any
def __init__(self, *args, **kwargs) -> None: ...
def android_version(art_version: int) -> lief.Android.ANDROID_VERSIONS: ...
@overload
def is_art(path: str) -> bool: ...
@overload
def is_art(raw: List[int]) -> bool: ...
@overload
def parse(filename: str) -> lief.ART.File: ...
@overload
def parse(raw: List[int], name: str = ...) -> lief.ART.File: ...
def parse(raw: list[int], name: str = ...) -> lief.ART.File: ...
@overload
def parse(io: object, name: str = ...) -> lief.ART.File: ...
def parse(io: object, name: str = ...) -> object: ...
@overload
def version(file: str) -> int: ...
@overload
def version(raw: List[int]) -> int: ...
def version(raw: list[int]) -> int: ...
+5 -6
View File
@@ -1,9 +1,8 @@
from typing import ClassVar
from typing import Any, ClassVar
import lief.Android # type: ignore
class ANDROID_VERSIONS:
__members__: ClassVar[dict] = ... # read-only
UNKNOWN: ClassVar[ANDROID_VERSIONS] = ...
VERSION_601: ClassVar[ANDROID_VERSIONS] = ...
VERSION_700: ClassVar[ANDROID_VERSIONS] = ...
@@ -12,10 +11,10 @@ class ANDROID_VERSIONS:
VERSION_800: ClassVar[ANDROID_VERSIONS] = ...
VERSION_810: ClassVar[ANDROID_VERSIONS] = ...
VERSION_900: ClassVar[ANDROID_VERSIONS] = ...
__entries: ClassVar[dict] = ...
def __init__(self, value: int) -> None: ...
@property
def name(self) -> str: ...
__name__: Any
def __init__(self, *args, **kwargs) -> None: ...
@staticmethod
def from_value(arg: int, /) -> lief.Android.ANDROID_VERSIONS: ...
@property
def value(self) -> int: ...
+57 -76
View File
@@ -1,11 +1,10 @@
from typing import Any, ClassVar, Iterator, List, Tuple
from typing import Any, ClassVar
from typing import overload
import lief # type: ignore
import lief.DEX # type: ignore
class ACCESS_FLAGS:
__members__: ClassVar[dict] = ... # read-only
ABSTRACT: ClassVar[ACCESS_FLAGS] = ...
ANNOTATION: ClassVar[ACCESS_FLAGS] = ...
BRIDGE: ClassVar[ACCESS_FLAGS] = ...
@@ -26,39 +25,35 @@ class ACCESS_FLAGS:
UNKNOWN: ClassVar[ACCESS_FLAGS] = ...
VARARGS: ClassVar[ACCESS_FLAGS] = ...
VOLATILE: ClassVar[ACCESS_FLAGS] = ...
__entries: ClassVar[dict] = ...
def __init__(self, value: int) -> None: ...
@property
def name(self) -> str: ...
@property
def value(self) -> int: ...
__name__: Any
def __init__(self, *args, **kwargs) -> None: ...
class Class(lief.Object):
class it_fields:
def __init__(self, *args, **kwargs) -> None: ...
def __getitem__(self, arg0: int) -> lief.DEX.Field: ...
def __iter__(self) -> Iterator: ...
def __getitem__(self, arg: int, /) -> lief.DEX.Field: ...
def __iter__(self) -> lief.DEX.Class.it_fields: ...
def __len__(self) -> int: ...
def __next__(self) -> lief.DEX.Field: ...
class it_methods:
def __init__(self, *args, **kwargs) -> None: ...
def __getitem__(self, arg0: int) -> lief.DEX.Method: ...
def __iter__(self) -> Iterator: ...
def __getitem__(self, arg: int, /) -> lief.DEX.Method: ...
def __iter__(self) -> lief.DEX.Class.it_methods: ...
def __len__(self) -> int: ...
def __next__(self) -> lief.DEX.Method: ...
class it_named_fields:
def __init__(self, *args, **kwargs) -> None: ...
def __getitem__(self, arg0: int) -> lief.DEX.Field: ...
def __iter__(self) -> Iterator: ...
def __getitem__(self, arg: int, /) -> lief.DEX.Field: ...
def __iter__(self) -> lief.DEX.Class.it_named_fields: ...
def __len__(self) -> int: ...
def __next__(self) -> lief.DEX.Field: ...
class it_named_methods:
def __init__(self, *args, **kwargs) -> None: ...
def __getitem__(self, arg0: int) -> lief.DEX.Method: ...
def __iter__(self) -> Iterator: ...
def __getitem__(self, arg: int, /) -> lief.DEX.Method: ...
def __iter__(self) -> lief.DEX.Class.it_named_methods: ...
def __len__(self) -> int: ...
def __next__(self) -> lief.DEX.Method: ...
def __init__(self, *args, **kwargs) -> None: ...
@@ -66,9 +61,9 @@ class Class(lief.Object):
def get_method(self, name: str) -> lief.DEX.Class.it_named_methods: ...
def has(self, flag: lief.DEX.ACCESS_FLAGS) -> bool: ...
@property
def access_flags(self) -> List[lief.DEX.ACCESS_FLAGS]: ...
def access_flags(self) -> list[lief.DEX.ACCESS_FLAGS]: ...
@property
def dex2dex_info(self) -> Any: ...
def dex2dex_info(self) -> dict[lief.DEX.Method,dict[int,int]]: ...
@property
def fields(self) -> lief.DEX.Class.it_fields: ...
@property
@@ -97,7 +92,7 @@ class Field(lief.Object):
def __init__(self, *args, **kwargs) -> None: ...
def has(self, flag: lief.DEX.ACCESS_FLAGS) -> bool: ...
@property
def access_flags(self) -> List[lief.DEX.ACCESS_FLAGS]: ...
def access_flags(self) -> list[lief.DEX.ACCESS_FLAGS]: ...
@property
def cls(self) -> lief.DEX.Class: ...
@property
@@ -114,43 +109,43 @@ class Field(lief.Object):
class File(lief.Object):
class it_classes:
def __init__(self, *args, **kwargs) -> None: ...
def __getitem__(self, arg0: int) -> lief.DEX.Class: ...
def __iter__(self) -> Iterator: ...
def __getitem__(self, arg: int, /) -> lief.DEX.Class: ...
def __iter__(self) -> lief.DEX.File.it_classes: ...
def __len__(self) -> int: ...
def __next__(self) -> lief.DEX.Class: ...
class it_fields:
def __init__(self, *args, **kwargs) -> None: ...
def __getitem__(self, arg0: int) -> lief.DEX.Field: ...
def __iter__(self) -> Iterator: ...
def __getitem__(self, arg: int, /) -> lief.DEX.Field: ...
def __iter__(self) -> lief.DEX.File.it_fields: ...
def __len__(self) -> int: ...
def __next__(self) -> lief.DEX.Field: ...
class it_methods:
def __init__(self, *args, **kwargs) -> None: ...
def __getitem__(self, arg0: int) -> lief.DEX.Method: ...
def __iter__(self) -> Iterator: ...
def __getitem__(self, arg: int, /) -> lief.DEX.Method: ...
def __iter__(self) -> lief.DEX.File.it_methods: ...
def __len__(self) -> int: ...
def __next__(self) -> lief.DEX.Method: ...
class it_prototypes:
def __init__(self, *args, **kwargs) -> None: ...
def __getitem__(self, arg0: int) -> lief.DEX.Prototype: ...
def __iter__(self) -> Iterator: ...
def __getitem__(self, arg: int, /) -> lief.DEX.Prototype: ...
def __iter__(self) -> lief.DEX.File.it_prototypes: ...
def __len__(self) -> int: ...
def __next__(self) -> lief.DEX.Prototype: ...
class it_strings:
def __init__(self, *args, **kwargs) -> None: ...
def __getitem__(self, arg0: int) -> str: ...
def __iter__(self) -> Iterator: ...
def __getitem__(self, arg: int, /) -> str: ...
def __iter__(self) -> lief.DEX.File.it_strings: ...
def __len__(self) -> int: ...
def __next__(self) -> str: ...
class it_types:
def __init__(self, *args, **kwargs) -> None: ...
def __getitem__(self, arg0: int) -> lief.DEX.Type: ...
def __iter__(self) -> Iterator: ...
def __getitem__(self, arg: int, /) -> lief.DEX.Type: ...
def __iter__(self) -> lief.DEX.File.it_types: ...
def __len__(self) -> int: ...
def __next__(self) -> lief.DEX.Type: ...
location: str
@@ -161,7 +156,7 @@ class File(lief.Object):
@overload
def get_class(self, classname: int) -> lief.DEX.Class: ...
def has_class(self, classname: str) -> bool: ...
def raw(self, deoptimize: bool = ...) -> List[int]: ...
def raw(self, deoptimize: bool = ...) -> list[int]: ...
def save(self, output: str = ..., deoptimize: bool = ...) -> str: ...
@property
def classes(self) -> lief.DEX.File.it_classes: ...
@@ -189,41 +184,40 @@ class Header(lief.Object):
@property
def checksum(self) -> int: ...
@property
def classes(self) -> Tuple[int,int]: ...
def classes(self) -> tuple[int,int]: ...
@property
def data(self) -> Tuple[int,int]: ...
def data(self) -> tuple[int,int]: ...
@property
def endian_tag(self) -> int: ...
@property
def fields(self) -> Tuple[int,int]: ...
def fields(self) -> tuple[int,int]: ...
@property
def file_size(self) -> int: ...
@property
def header_size(self) -> int: ...
@property
def link(self) -> Tuple[int,int]: ...
def link(self) -> tuple[int,int]: ...
@property
def magic(self) -> List[int]: ...
def magic(self) -> list[int]: ...
@property
def map_offset(self) -> int: ...
@property
def methods(self) -> Tuple[int,int]: ...
def methods(self) -> tuple[int,int]: ...
@property
def nb_classes(self) -> int: ...
@property
def nb_methods(self) -> int: ...
@property
def prototypes(self) -> Tuple[int,int]: ...
def prototypes(self) -> tuple[int,int]: ...
@property
def signature(self) -> List[int]: ...
def signature(self) -> list[int]: ...
@property
def strings(self) -> Tuple[int,int]: ...
def strings(self) -> tuple[int,int]: ...
@property
def types(self) -> Tuple[int,int]: ...
def types(self) -> tuple[int,int]: ...
class MapItem(lief.Object):
class TYPES:
__members__: ClassVar[dict] = ... # read-only
ANNOTATION: ClassVar[MapItem.TYPES] = ...
ANNOTATIONS_DIRECTORY: ClassVar[MapItem.TYPES] = ...
ANNOTATION_SET: ClassVar[MapItem.TYPES] = ...
@@ -244,10 +238,10 @@ class MapItem(lief.Object):
STRING_ID: ClassVar[MapItem.TYPES] = ...
TYPE_ID: ClassVar[MapItem.TYPES] = ...
TYPE_LIST: ClassVar[MapItem.TYPES] = ...
__entries: ClassVar[dict] = ...
def __init__(self, value: int) -> None: ...
@property
def name(self) -> str: ...
__name__: Any
def __init__(self, *args, **kwargs) -> None: ...
@staticmethod
def from_value(arg: int, /) -> lief.DEX.MapItem.TYPES: ...
@property
def value(self) -> int: ...
def __init__(self, *args, **kwargs) -> None: ...
@@ -261,14 +255,14 @@ class MapItem(lief.Object):
class MapList(lief.Object):
class it_items_t:
def __init__(self, *args, **kwargs) -> None: ...
def __getitem__(self, arg0: int) -> lief.DEX.MapItem: ...
def __iter__(self) -> Iterator: ...
def __getitem__(self, arg: int, /) -> lief.DEX.MapItem: ...
def __iter__(self) -> lief.DEX.MapList.it_items_t: ...
def __len__(self) -> int: ...
def __next__(self) -> lief.DEX.MapItem: ...
def __init__(self, *args, **kwargs) -> None: ...
def get(self, type: lief.DEX.MapItem.TYPES) -> lief.DEX.MapItem: ...
def has(self, type: lief.DEX.MapItem.TYPES) -> bool: ...
def __getitem__(self, arg0: lief.DEX.MapItem.TYPES) -> lief.DEX.MapItem: ...
def __getitem__(self, arg: lief.DEX.MapItem.TYPES, /) -> lief.DEX.MapItem: ...
@property
def items(self) -> lief.DEX.MapList.it_items_t: ...
@@ -277,9 +271,9 @@ class Method(lief.Object):
def has(self, flag: lief.DEX.ACCESS_FLAGS) -> bool: ...
def insert_dex2dex_info(self, pc: int, index: int) -> None: ...
@property
def access_flags(self) -> List[lief.DEX.ACCESS_FLAGS]: ...
def access_flags(self) -> list[lief.DEX.ACCESS_FLAGS]: ...
@property
def bytecode(self) -> List[int]: ...
def bytecode(self) -> list[int]: ...
@property
def cls(self) -> lief.DEX.Class: ...
@property
@@ -298,8 +292,8 @@ class Method(lief.Object):
class Prototype(lief.Object):
class it_params:
def __init__(self, *args, **kwargs) -> None: ...
def __getitem__(self, arg0: int) -> lief.DEX.Type: ...
def __iter__(self) -> Iterator: ...
def __getitem__(self, arg: int, /) -> lief.DEX.Type: ...
def __iter__(self) -> lief.DEX.Prototype.it_params: ...
def __len__(self) -> int: ...
def __next__(self) -> lief.DEX.Type: ...
def __init__(self, *args, **kwargs) -> None: ...
@@ -310,7 +304,6 @@ class Prototype(lief.Object):
class Type(lief.Object):
class PRIMITIVES:
__members__: ClassVar[dict] = ... # read-only
BOOLEAN: ClassVar[Type.PRIMITIVES] = ...
BYTE: ClassVar[Type.PRIMITIVES] = ...
CHAR: ClassVar[Type.PRIMITIVES] = ...
@@ -320,27 +313,19 @@ class Type(lief.Object):
LONG: ClassVar[Type.PRIMITIVES] = ...
SHORT: ClassVar[Type.PRIMITIVES] = ...
VOID_T: ClassVar[Type.PRIMITIVES] = ...
__entries: ClassVar[dict] = ...
def __init__(self, value: int) -> None: ...
@property
def name(self) -> str: ...
@property
def value(self) -> int: ...
__name__: Any
def __init__(self, *args, **kwargs) -> None: ...
class TYPES:
__members__: ClassVar[dict] = ... # read-only
ARRAY: ClassVar[Type.TYPES] = ...
CLASS: ClassVar[Type.TYPES] = ...
PRIMITIVE: ClassVar[Type.TYPES] = ...
UNKNOWN: ClassVar[Type.TYPES] = ...
__entries: ClassVar[dict] = ...
def __init__(self, value: int) -> None: ...
@property
def name(self) -> str: ...
@property
def value(self) -> int: ...
__name__: Any
def __init__(self, *args, **kwargs) -> None: ...
def __init__(self, *args, **kwargs) -> None: ...
def pretty_name(self, *args, **kwargs) -> Any: ...
@staticmethod
def pretty_name(primitive: lief.DEX.Type.PRIMITIVES) -> str: ...
@property
def dim(self) -> int: ...
@property
@@ -350,17 +335,13 @@ class Type(lief.Object):
@property
def value(self) -> object: ...
@overload
def is_dex(path: str) -> bool: ...
@overload
def is_dex(raw: List[int]) -> bool: ...
@overload
def parse(filename: str) -> lief.DEX.File: ...
@overload
def parse(raw: List[int], name: str = ...) -> lief.DEX.File: ...
def parse(raw: list[int], name: str = ...) -> lief.DEX.File: ...
@overload
def parse(io: object, name: str = ...) -> lief.DEX.File: ...
def parse(io: object, name: str = ...) -> object: ...
@overload
def version(file: str) -> int: ...
@overload
def version(raw: List[int]) -> int: ...
def version(raw: list[int]) -> int: ...
+423 -343
View File
File diff suppressed because it is too large Load Diff
+246 -242
View File
File diff suppressed because it is too large Load Diff
+40 -66
View File
@@ -1,4 +1,4 @@
from typing import Any, ClassVar, Iterator, List
from typing import Any, ClassVar
from typing import overload
import lief # type: ignore
@@ -10,29 +10,29 @@ import lief.OAT # type: ignore
class Binary(lief.ELF.Binary):
class it_classes:
def __init__(self, *args, **kwargs) -> None: ...
def __getitem__(self, arg0: int) -> lief.OAT.Class: ...
def __iter__(self) -> Iterator: ...
def __getitem__(self, arg: int, /) -> lief.OAT.Class: ...
def __iter__(self) -> lief.OAT.Binary.it_classes: ...
def __len__(self) -> int: ...
def __next__(self) -> lief.OAT.Class: ...
class it_dex_files:
def __init__(self, *args, **kwargs) -> None: ...
def __getitem__(self, arg0: int) -> lief.DEX.File: ...
def __iter__(self) -> Iterator: ...
def __getitem__(self, arg: int, /) -> lief.DEX.File: ...
def __iter__(self) -> lief.OAT.Binary.it_dex_files: ...
def __len__(self) -> int: ...
def __next__(self) -> lief.DEX.File: ...
class it_methods:
def __init__(self, *args, **kwargs) -> None: ...
def __getitem__(self, arg0: int) -> lief.OAT.Method: ...
def __iter__(self) -> Iterator: ...
def __getitem__(self, arg: int, /) -> lief.OAT.Method: ...
def __iter__(self) -> lief.OAT.Binary.it_methods: ...
def __len__(self) -> int: ...
def __next__(self) -> lief.OAT.Method: ...
class it_oat_dex_files:
def __init__(self, *args, **kwargs) -> None: ...
def __getitem__(self, arg0: int) -> lief.OAT.DexFile: ...
def __iter__(self) -> Iterator: ...
def __getitem__(self, arg: int, /) -> lief.OAT.DexFile: ...
def __iter__(self) -> lief.OAT.Binary.it_oat_dex_files: ...
def __len__(self) -> int: ...
def __next__(self) -> lief.OAT.DexFile: ...
def __init__(self, *args, **kwargs) -> None: ...
@@ -58,8 +58,8 @@ class Binary(lief.ELF.Binary):
class Class(lief.Object):
class it_methods:
def __init__(self, *args, **kwargs) -> None: ...
def __getitem__(self, arg0: int) -> lief.OAT.Method: ...
def __iter__(self) -> Iterator: ...
def __getitem__(self, arg: int, /) -> lief.OAT.Method: ...
def __iter__(self) -> lief.OAT.Class.it_methods: ...
def __len__(self) -> int: ...
def __next__(self) -> lief.OAT.Method: ...
def __init__(self) -> None: ...
@@ -69,11 +69,11 @@ class Class(lief.Object):
@overload
def is_quickened(self, method_index: int) -> bool: ...
@overload
def method_offsets_index(self, arg0: lief.DEX.Method) -> int: ...
def method_offsets_index(self, arg: lief.DEX.Method, /) -> int: ...
@overload
def method_offsets_index(self, arg0: int) -> int: ...
def method_offsets_index(self, arg: int, /) -> int: ...
@property
def bitmap(self) -> List[int]: ...
def bitmap(self) -> list[int]: ...
@property
def fullname(self) -> str: ...
@property
@@ -96,7 +96,6 @@ class DexFile(lief.Object):
def has_dex_file(self) -> bool: ...
class HEADER_KEYS:
__members__: ClassVar[dict] = ... # read-only
BOOT_CLASS_PATH: ClassVar[HEADER_KEYS] = ...
CLASS_PATH: ClassVar[HEADER_KEYS] = ...
COMPILER_FILTER: ClassVar[HEADER_KEYS] = ...
@@ -108,30 +107,26 @@ class HEADER_KEYS:
IMAGE_LOCATION: ClassVar[HEADER_KEYS] = ...
NATIVE_DEBUGGABLE: ClassVar[HEADER_KEYS] = ...
PIC: ClassVar[HEADER_KEYS] = ...
__entries: ClassVar[dict] = ...
def __init__(self, value: int) -> None: ...
@property
def name(self) -> str: ...
@property
def value(self) -> int: ...
__name__: Any
def __init__(self, *args, **kwargs) -> None: ...
class Header(lief.Object):
class it_key_values_t:
class value_type:
value: str
def __init__(self, *args, **kwargs) -> None: ...
@property
def key(self) -> lief.OAT.HEADER_KEYS: ...
class element_t:
key: lief.OAT.HEADER_KEYS
value: str
def __init__(self, *args, **kwargs) -> None: ...
def __getitem__(self, arg0: int) -> lief.OAT.Header.it_key_values_t.value_type: ...
class it_key_values_t:
def __init__(self, *args, **kwargs) -> None: ...
def __getitem__(self, arg: int, /) -> lief.OAT.Header.element_t: ...
def __iter__(self) -> lief.OAT.Header.it_key_values_t: ...
def __len__(self) -> int: ...
def __next__(self) -> lief.OAT.Header.it_key_values_t.value_type: ...
def __next__(self) -> lief.OAT.Header.element_t: ...
def __init__(self) -> None: ...
def get(self, key: lief.OAT.HEADER_KEYS) -> str: ...
def set(self, key: lief.OAT.HEADER_KEYS, value: str) -> Any: ...
def __getitem__(self, arg0: lief.OAT.HEADER_KEYS) -> str: ...
def __setitem__(self, arg0: lief.OAT.HEADER_KEYS, arg1: str) -> Any: ...
def __getitem__(self, arg: lief.OAT.HEADER_KEYS, /) -> str: ...
def __setitem__(self, arg0: lief.OAT.HEADER_KEYS, arg1: str, /) -> Any: ...
@property
def checksum(self) -> int: ...
@property
@@ -155,9 +150,9 @@ class Header(lief.Object):
@property
def key_values(self) -> lief.OAT.Header.it_key_values_t: ...
@property
def keys(self) -> List[lief.OAT.HEADER_KEYS]: ...
def keys(self) -> list[lief.OAT.HEADER_KEYS]: ...
@property
def magic(self) -> List[int]: ...
def magic(self) -> list[int]: ...
@property
def nb_dex_files(self) -> int: ...
@property
@@ -171,12 +166,11 @@ class Header(lief.Object):
@property
def quick_to_interpreter_bridge_offset(self) -> int: ...
@property
def values(self) -> List[str]: ...
def values(self) -> list[str]: ...
@property
def version(self) -> int: ...
class INSTRUCTION_SETS:
__members__: ClassVar[dict] = ... # read-only
ARM: ClassVar[INSTRUCTION_SETS] = ...
ARM_64: ClassVar[INSTRUCTION_SETS] = ...
MIPS: ClassVar[INSTRUCTION_SETS] = ...
@@ -185,15 +179,11 @@ class INSTRUCTION_SETS:
THUMB2: ClassVar[INSTRUCTION_SETS] = ...
X86: ClassVar[INSTRUCTION_SETS] = ...
X86_64: ClassVar[INSTRUCTION_SETS] = ...
__entries: ClassVar[dict] = ...
def __init__(self, value: int) -> None: ...
@property
def name(self) -> str: ...
@property
def value(self) -> int: ...
__name__: Any
def __init__(self, *args, **kwargs) -> None: ...
class Method(lief.Object):
quick_code: List[int]
quick_code: list[int]
def __init__(self) -> None: ...
@property
def dex_method(self) -> lief.DEX.Method: ...
@@ -209,7 +199,6 @@ class Method(lief.Object):
def oat_class(self) -> lief.OAT.Class: ...
class OAT_CLASS_STATUS:
__members__: ClassVar[dict] = ... # read-only
ERROR: ClassVar[OAT_CLASS_STATUS] = ...
IDX: ClassVar[OAT_CLASS_STATUS] = ...
INITIALIZED: ClassVar[OAT_CLASS_STATUS] = ...
@@ -223,43 +212,28 @@ class OAT_CLASS_STATUS:
VERIFIED: ClassVar[OAT_CLASS_STATUS] = ...
VERIFYING: ClassVar[OAT_CLASS_STATUS] = ...
VERIFYING_AT_RUNTIME: ClassVar[OAT_CLASS_STATUS] = ...
__entries: ClassVar[dict] = ...
def __init__(self, value: int) -> None: ...
@property
def name(self) -> str: ...
@property
def value(self) -> int: ...
__name__: Any
def __init__(self, *args, **kwargs) -> None: ...
class OAT_CLASS_TYPES:
__members__: ClassVar[dict] = ... # read-only
ALL_COMPILED: ClassVar[OAT_CLASS_TYPES] = ...
NONE_COMPILED: ClassVar[OAT_CLASS_TYPES] = ...
SOME_COMPILED: ClassVar[OAT_CLASS_TYPES] = ...
__entries: ClassVar[dict] = ...
def __init__(self, value: int) -> None: ...
@property
def name(self) -> str: ...
@property
def value(self) -> int: ...
__name__: Any
def __init__(self, *args, **kwargs) -> None: ...
def android_version(arg0: int) -> lief.Android.ANDROID_VERSIONS: ...
@overload
def is_oat(binary: lief.ELF.Binary) -> bool: ...
@overload
def is_oat(path: str) -> bool: ...
@overload
def is_oat(raw: List[int]) -> bool: ...
def android_version(arg: int, /) -> lief.Android.ANDROID_VERSIONS: ...
@overload
def parse(oat_file: str) -> lief.OAT.Binary: ...
@overload
def parse(oat_file: str, vdex_file: str) -> lief.OAT.Binary: ...
@overload
def parse(raw: List[int]) -> lief.OAT.Binary: ...
def parse(raw: list[int]) -> lief.OAT.Binary: ...
@overload
def parse(io: object) -> lief.OAT.Binary: ...
def parse(io: object) -> object: ...
@overload
def version(binary: lief.ELF.Binary) -> int: ...
@overload
def version(file: str) -> int: ...
@overload
def version(raw: List[int]) -> int: ...
def version(raw: list[int]) -> int: ...
+371 -347
View File
File diff suppressed because it is too large Load Diff
+10 -11
View File
@@ -1,12 +1,17 @@
from typing import List
from typing import overload
import lief # type: ignore
import lief.Android # type: ignore
import lief.DEX # type: ignore
import lief.OAT # type: ignore
import lief.VDEX # type: ignore
class File(lief.Object):
class it_dex_files:
def __init__(self, *args, **kwargs) -> None: ...
def __getitem__(self, arg: int, /) -> lief.DEX.File: ...
def __iter__(self) -> lief.OAT.Binary.it_dex_files: ...
def __len__(self) -> int: ...
def __next__(self) -> lief.DEX.File: ...
def __init__(self, *args, **kwargs) -> None: ...
@property
def dex2dex_json_info(self) -> str: ...
@@ -20,7 +25,7 @@ class Header(lief.Object):
@property
def dex_size(self) -> int: ...
@property
def magic(self) -> List[int]: ...
def magic(self) -> list[int]: ...
@property
def nb_dex_files(self) -> int: ...
@property
@@ -32,16 +37,10 @@ class Header(lief.Object):
def android_version(vdex_version: int) -> lief.Android.ANDROID_VERSIONS: ...
@overload
def is_vdex(path: str) -> bool: ...
@overload
def is_vdex(raw: List[int]) -> bool: ...
@overload
def parse(filename: str) -> lief.VDEX.File: ...
@overload
def parse(raw: List[int], name: str = ...) -> lief.VDEX.File: ...
@overload
def parse(io: object, name: str = ...) -> lief.VDEX.File: ...
def parse(io: object, name: str = ...) -> object: ...
@overload
def version(file: str) -> int: ...
@overload
def version(raw: List[int]) -> int: ...
def version(raw: list[int]) -> int: ...
+11 -8
View File
@@ -1,12 +1,15 @@
import os
import sys
from . import _lief
from ._lief import *
from ._lief import __version__, __tag__, __commit__, __is_tagged__
import traceback
if len(__path__) > 0 and __path__[0] not in sys.path:
from . import _lief
from ._lief import *
from ._lief import __version__, __tag__, __commit__, __is_tagged__
# cf. https://github.com/pytorch/pytorch/blob/60a3b7425dde97fe8b46183c154a9c3b24f0c733/torch/__init__.py#L467-L470
for attr in dir(_lief):
candidate = getattr(_lief, attr)
if type(candidate) is type(_lief):
sys.modules.setdefault(f"lief.{attr}", candidate)
# cf. https://github.com/pytorch/pytorch/blob/60a3b7425dde97fe8b46183c154a9c3b24f0c733/torch/__init__.py#L467-L470
for attr in dir(_lief):
candidate = getattr(_lief, attr)
if type(candidate) is type(_lief):
sys.modules.setdefault(f"lief.{attr}", candidate)
+56 -135
View File
@@ -1,11 +1,10 @@
from typing import Any, ClassVar, Iterator, List, Set
from typing import Any, ClassVar, List
from . import ART, Android, DEX, ELF, MachO, OAT, PE, VDEX, logging # type: ignore
from typing import overload
import lief # type: ignore
class ARCHITECTURES:
__members__: ClassVar[dict] = ... # read-only
ARM: ClassVar[ARCHITECTURES] = ...
ARM64: ClassVar[ARCHITECTURES] = ...
INTEL: ClassVar[ARCHITECTURES] = ...
@@ -18,44 +17,39 @@ class ARCHITECTURES:
SYSZ: ClassVar[ARCHITECTURES] = ...
X86: ClassVar[ARCHITECTURES] = ...
XCORE: ClassVar[ARCHITECTURES] = ...
__entries: ClassVar[dict] = ...
def __init__(self, value: int) -> None: ...
@property
def name(self) -> str: ...
__name__: Any
def __init__(self, *args, **kwargs) -> None: ...
@staticmethod
def from_value(arg: int, /) -> lief.ARCHITECTURES: ...
@property
def value(self) -> int: ...
class Binary(Object):
class VA_TYPES:
__members__: ClassVar[dict] = ... # read-only
AUTO: ClassVar[Binary.VA_TYPES] = ...
RVA: ClassVar[Binary.VA_TYPES] = ...
VA: ClassVar[Binary.VA_TYPES] = ...
__entries: ClassVar[dict] = ...
def __init__(self, value: int) -> None: ...
@property
def name(self) -> str: ...
@property
def value(self) -> int: ...
__name__: Any
def __init__(self, *args, **kwargs) -> None: ...
class it_relocations:
def __init__(self, *args, **kwargs) -> None: ...
def __getitem__(self, arg0: int) -> lief.Relocation: ...
def __iter__(self) -> Iterator: ...
def __getitem__(self, arg: int, /) -> lief.Relocation: ...
def __iter__(self) -> Any: ...
def __len__(self) -> int: ...
def __next__(self) -> lief.Relocation: ...
class it_sections:
def __init__(self, *args, **kwargs) -> None: ...
def __getitem__(self, arg0: int) -> lief.Section: ...
def __iter__(self) -> Iterator: ...
def __getitem__(self, arg: int, /) -> lief.Section: ...
def __iter__(self) -> lief.Binary.it_sections: ...
def __len__(self) -> int: ...
def __next__(self) -> lief.Section: ...
class it_symbols:
def __init__(self, *args, **kwargs) -> None: ...
def __getitem__(self, arg0: int) -> lief.Symbol: ...
def __iter__(self) -> Iterator: ...
def __getitem__(self, arg: int, /) -> lief.Symbol: ...
def __iter__(self) -> Any: ...
def __len__(self) -> int: ...
def __next__(self) -> lief.Symbol: ...
def __init__(self, *args, **kwargs) -> None: ...
@@ -65,11 +59,11 @@ class Binary(Object):
def has_symbol(self, symbol_name: str) -> bool: ...
def offset_to_virtual_address(self, offset: int, slide: int = ...) -> object: ...
@overload
def patch_address(self, address: int, patch_value: List[int], va_type: lief.Binary.VA_TYPES = ...) -> None: ...
def patch_address(self, address: int, patch_value: list[int], va_type: lief.Binary.VA_TYPES = ...) -> None: ...
@overload
def patch_address(self, address: int, patch_value: int, size: int = ..., va_type: lief.Binary.VA_TYPES = ...) -> None: ...
def remove_section(self, name: str, clear: bool = ...) -> None: ...
def xref(self, virtual_address: int) -> List[int]: ...
def xref(self, virtual_address: int) -> list[int]: ...
@property
def abstract(self) -> lief.Binary: ...
@property
@@ -79,7 +73,7 @@ class Binary(Object):
@property
def entrypoint(self) -> int: ...
@property
def exported_functions(self) -> Any: ...
def exported_functions(self) -> list[lief.Function]: ...
@property
def format(self) -> lief.EXE_FORMATS: ...
@property
@@ -89,7 +83,7 @@ class Binary(Object):
@property
def imagebase(self) -> int: ...
@property
def imported_functions(self) -> Any: ...
def imported_functions(self) -> list[lief.Function]: ...
@property
def is_pie(self) -> bool: ...
@property
@@ -102,62 +96,55 @@ class Binary(Object):
def symbols(self) -> Any: ...
class ENDIANNESS:
__members__: ClassVar[dict] = ... # read-only
BIG: ClassVar[ENDIANNESS] = ...
LITTLE: ClassVar[ENDIANNESS] = ...
NONE: ClassVar[ENDIANNESS] = ...
__entries: ClassVar[dict] = ...
def __init__(self, value: int) -> None: ...
@property
def name(self) -> str: ...
__name__: Any
def __init__(self, *args, **kwargs) -> None: ...
@staticmethod
def from_value(arg: int, /) -> lief.ENDIANNESS: ...
@property
def value(self) -> int: ...
class EXE_FORMATS:
__members__: ClassVar[dict] = ... # read-only
ELF: ClassVar[EXE_FORMATS] = ...
MACHO: ClassVar[EXE_FORMATS] = ...
PE: ClassVar[EXE_FORMATS] = ...
UNKNOWN: ClassVar[EXE_FORMATS] = ...
__entries: ClassVar[dict] = ...
def __init__(self, value: int) -> None: ...
@property
def name(self) -> str: ...
__name__: Any
def __init__(self, *args, **kwargs) -> None: ...
@staticmethod
def from_value(arg: int, /) -> lief.EXE_FORMATS: ...
@property
def value(self) -> int: ...
class Function(Symbol):
class FLAGS:
__members__: ClassVar[dict] = ... # read-only
CONSTRUCTOR: ClassVar[Function.FLAGS] = ...
DEBUG: ClassVar[Function.FLAGS] = ...
DESTRUCTOR: ClassVar[Function.FLAGS] = ...
EXPORTED: ClassVar[Function.FLAGS] = ...
IMPORTED: ClassVar[Function.FLAGS] = ...
__entries: ClassVar[dict] = ...
def __init__(self, value: int) -> None: ...
@property
def name(self) -> str: ...
@property
def value(self) -> int: ...
__name__: Any
def __init__(self, *args, **kwargs) -> None: ...
address: int
@overload
def __init__(self) -> None: ...
@overload
def __init__(self, arg0: str) -> None: ...
def __init__(self, arg: str, /) -> None: ...
@overload
def __init__(self, arg0: int) -> None: ...
def __init__(self, arg: int, /) -> None: ...
@overload
def __init__(self, arg0: str, arg1: int) -> None: ...
def __init__(self, arg0: str, arg1: int, /) -> None: ...
def add(self, flag: lief.Function.FLAGS) -> lief.Function: ...
@property
def flags(self) -> List[lief.Function.FLAGS]: ...
def flags(self) -> list[lief.Function.FLAGS]: ...
class Header(Object):
architecture: Any
endianness: lief.ENDIANNESS
entrypoint: int
modes: Set[lief.MODES]
modes: set[lief.MODES]
object_type: lief.OBJECT_TYPES
def __init__(self) -> None: ...
@property
@@ -166,7 +153,6 @@ class Header(Object):
def is_64(self) -> bool: ...
class MODES:
__members__: ClassVar[dict] = ... # read-only
ARM: ClassVar[MODES] = ...
M16: ClassVar[MODES] = ...
M32: ClassVar[MODES] = ...
@@ -183,23 +169,22 @@ class MODES:
V7: ClassVar[MODES] = ...
V8: ClassVar[MODES] = ...
V9: ClassVar[MODES] = ...
__entries: ClassVar[dict] = ...
def __init__(self, value: int) -> None: ...
@property
def name(self) -> str: ...
__name__: Any
def __init__(self, *args, **kwargs) -> None: ...
@staticmethod
def from_value(arg: int, /) -> lief.MODES: ...
@property
def value(self) -> int: ...
class OBJECT_TYPES:
__members__: ClassVar[dict] = ... # read-only
EXECUTABLE: ClassVar[OBJECT_TYPES] = ...
LIBRARY: ClassVar[OBJECT_TYPES] = ...
NONE: ClassVar[OBJECT_TYPES] = ...
OBJECT: ClassVar[OBJECT_TYPES] = ...
__entries: ClassVar[dict] = ...
def __init__(self, value: int) -> None: ...
@property
def name(self) -> str: ...
__name__: Any
def __init__(self, *args, **kwargs) -> None: ...
@staticmethod
def from_value(arg: int, /) -> lief.OBJECT_TYPES: ...
@property
def value(self) -> int: ...
@@ -207,27 +192,23 @@ class Object:
def __init__(self, *args, **kwargs) -> None: ...
class PLATFORMS:
__members__: ClassVar[dict] = ... # read-only
ANDROID: ClassVar[PLATFORMS] = ...
IOS: ClassVar[PLATFORMS] = ...
LINUX: ClassVar[PLATFORMS] = ...
OSX: ClassVar[PLATFORMS] = ...
UNKNOWN: ClassVar[PLATFORMS] = ...
WINDOWS: ClassVar[PLATFORMS] = ...
__entries: ClassVar[dict] = ...
def __init__(self, value: int) -> None: ...
@property
def name(self) -> str: ...
__name__: Any
def __init__(self, *args, **kwargs) -> None: ...
@staticmethod
def from_value(arg: int, /) -> lief.PLATFORMS: ...
@property
def value(self) -> int: ...
class Relocation(Object):
address: int
size: int
@overload
def __init__(self) -> None: ...
@overload
def __init__(self, address: int, size: int) -> None: ...
def __init__(self, *args, **kwargs) -> None: ...
class Section(Object):
content: memoryview
@@ -235,10 +216,7 @@ class Section(Object):
offset: int
size: int
virtual_address: int
@overload
def __init__(self) -> None: ...
@overload
def __init__(self, name: str) -> None: ...
def __init__(self, *args, **kwargs) -> None: ...
@overload
def search(self, number: int, pos: int = ..., size: int = ...) -> int | None: ...
@overload
@@ -246,9 +224,9 @@ class Section(Object):
@overload
def search(self, bytes: bytes, pos: int = ...) -> int | None: ...
@overload
def search_all(self, number: int, size: int = ...) -> List[int]: ...
def search_all(self, number: int, size: int = ...) -> list[int]: ...
@overload
def search_all(self, str: str) -> List[int]: ...
def search_all(self, str: str) -> list[int]: ...
@property
def entropy(self) -> float: ...
@property
@@ -258,11 +236,9 @@ class Symbol(Object):
name: object
size: int
value: int
def __init__(self) -> None: ...
def __init__(self, *args, **kwargs) -> None: ...
class lief_errors:
__members__: ClassVar[dict] = ... # read-only
__entries: ClassVar[dict] = ...
asn1_bad_tag: ClassVar[lief_errors] = ...
build_error: ClassVar[lief_errors] = ...
conversion_error: ClassVar[lief_errors] = ...
@@ -276,81 +252,26 @@ class lief_errors:
parsing_error: ClassVar[lief_errors] = ...
read_error: ClassVar[lief_errors] = ...
read_out_of_bound: ClassVar[lief_errors] = ...
def __init__(self, value: int) -> None: ...
@property
def name(self) -> str: ...
@property
def value(self) -> int: ...
__name__: Any
def __init__(self, *args, **kwargs) -> None: ...
class ok_t:
def __init__(self, *args, **kwargs) -> None: ...
def __bool__(self) -> bool: ...
@overload
def art_version(filename: str) -> int: ...
@overload
def art_version(raw: List[int]) -> int: ...
def breakp() -> object: ...
def current_platform() -> lief.PLATFORMS: ...
def demangle(arg0: str) -> object: ...
@overload
def dex_version(filename: str) -> int: ...
def hash(arg: lief.Object, /) -> int: ...
@overload
def dex_version(raw: List[int]) -> int: ...
def hash(arg: list[int], /) -> int: ...
@overload
def hash(arg0: lief.Object) -> int: ...
def hash(arg: bytes, /) -> int: ...
@overload
def hash(arg0: List[int]) -> int: ...
@overload
def hash(arg0: bytes) -> int: ...
@overload
def hash(arg0: str) -> int: ...
@overload
def is_art(filename: str) -> bool: ...
@overload
def is_art(raw: List[int]) -> bool: ...
@overload
def is_dex(filename: str) -> bool: ...
@overload
def is_dex(raw: List[int]) -> bool: ...
@overload
def is_elf(filename: str) -> bool: ...
@overload
def is_elf(raw: List[int]) -> bool: ...
@overload
def is_macho(filename: str) -> bool: ...
@overload
def is_macho(raw: List[int]) -> bool: ...
@overload
def is_oat(filename: str) -> bool: ...
@overload
def is_oat(raw: List[int]) -> bool: ...
@overload
def is_oat(elf: lief.ELF.Binary) -> bool: ...
@overload
def is_pe(filename: str) -> bool: ...
@overload
def is_pe(raw: List[int]) -> bool: ...
@overload
def is_vdex(filename: str) -> bool: ...
@overload
def is_vdex(raw: List[int]) -> bool: ...
@overload
def oat_version(filename: str) -> int: ...
@overload
def oat_version(raw: List[int]) -> int: ...
@overload
def oat_version(elf: lief.ELF.Binary) -> int: ...
def hash(arg: str, /) -> int: ...
@overload
def parse(raw: bytes) -> lief.Binary: ...
@overload
def parse(filepath: str) -> lief.Binary: ...
@overload
def parse(io: object) -> object: ...
def shell() -> object: ...
def to_json(arg0: lief.Object) -> str: ...
def to_json_from_abstract(arg0: lief.Object) -> str: ...
@overload
def vdex_version(filename: str) -> int: ...
@overload
def vdex_version(raw: List[int]) -> int: ...
def to_json(arg: lief.Object, /) -> str: ...
+3 -8
View File
@@ -1,21 +1,16 @@
from typing import ClassVar
from typing import Any, ClassVar
import lief.logging # type: ignore
class LOGGING_LEVEL:
__members__: ClassVar[dict] = ... # read-only
CRITICAL: ClassVar[LOGGING_LEVEL] = ...
DEBUG: ClassVar[LOGGING_LEVEL] = ...
ERROR: ClassVar[LOGGING_LEVEL] = ...
INFO: ClassVar[LOGGING_LEVEL] = ...
TRACE: ClassVar[LOGGING_LEVEL] = ...
WARNING: ClassVar[LOGGING_LEVEL] = ...
__entries: ClassVar[dict] = ...
def __init__(self, value: int) -> None: ...
@property
def name(self) -> str: ...
@property
def value(self) -> int: ...
__name__: Any
def __init__(self, *args, **kwargs) -> None: ...
def disable() -> None: ...
def enable() -> None: ...
+125 -65
View File
@@ -50,40 +50,60 @@ class Config:
def build_type(self) -> str:
return self._config['lief']['build']['type']
def gen_cmake_option(self, output: str) -> List[str]:
cfg = self.build_type()
opt = [
f"-DCMAKE_BUILD_TYPE={cfg}",
def get_lief_format_opt(self):
opt = self._config["lief"]["formats"]
return (
"-DLIEF_ELF={}".format("ON" if opt["elf"] else "OFF"),
"-DLIEF_PE={}".format("ON" if opt["pe"] else "OFF"),
"-DLIEF_MACHO={}".format("ON" if opt["macho"] else "OFF"),
"-DLIEF_DEX={}".format("ON" if opt["dex"] else "OFF"),
"-DLIEF_ART={}".format("ON" if opt["art"] else "OFF"),
"-DLIEF_OAT={}".format("ON" if opt["oat"] else "OFF"),
"-DLIEF_VDEX={}".format("ON" if opt["vdex"] else "OFF"),
)
def get_lief_logging_opt(self):
opt = self._config["lief"]["logging"]
return (
"-DLIEF_LOGGING={}".format("ON" if opt["enabled"] else "OFF"),
"-DLIEF_LOGGING_DEBUG={}".format("ON" if opt["debug"] else "OFF"),
)
def get_python_opt(self):
config = ["-DLIEF_PYTHON_API=on"]
interpreter = Path(sys.executable)
base = sysconfig.get_config_var("base")
if base is not None:
config += [f"-DPython_ROOT_DIR={base}"]
config += [
f"-DPython_EXECUTABLE={interpreter.as_posix()}",
]
return config
def get_generic_opt(self, output: str):
return (
f"-DCMAKE_BUILD_TYPE={self.build_type()}",
f'-DCMAKE_LIBRARY_OUTPUT_DIRECTORY={output}',
"-DLIEF_USE_CCACHE={}".format("ON" if self._config["lief"]["build"]["cache"] else "OFF"),
] + [
"-DLIEF_PYTHON_API=on",
f"-DPYTHON_EXECUTABLE={sys.executable}",
] + [
"-DLIEF_ELF={}".format("ON" if self._config["lief"]["formats"]["elf"] else "OFF"),
"-DLIEF_PE={}".format("ON" if self._config["lief"]["formats"]["pe"] else "OFF"),
"-DLIEF_MACHO={}".format("ON" if self._config["lief"]["formats"]["macho"] else "OFF"),
"-DLIEF_DEX={}".format("ON" if self._config["lief"]["formats"]["dex"] else "OFF"),
"-DLIEF_ART={}".format("ON" if self._config["lief"]["formats"]["art"] else "OFF"),
"-DLIEF_OAT={}".format("ON" if self._config["lief"]["formats"]["oat"] else "OFF"),
"-DLIEF_VDEX={}".format("ON" if self._config["lief"]["formats"]["vdex"] else "OFF"),
] + [
"-DLIEF_LOGGING={}".format("ON" if self._config["lief"]["logging"]["enabled"] else "OFF"),
"-DLIEF_LOGGING_DEBUG={}".format("ON" if self._config["lief"]["logging"]["debug"] else "OFF"),
] + [
"-DLIEF_ENABLE_JSON={}".format("ON" if self._config["lief"]["features"]["json"] else "OFF"),
"-DLIEF_DISABLE_FROZEN={}".format("OFF" if self._config["lief"]["features"]["frozen"] else "ON"),
] + [
"-DLIEF_ENABLE_JSON={}".format("ON" if self._config["lief"]["features"]["json"] else "OFF"),
"-DLIEF_DISABLE_FROZEN={}".format("OFF" if self._config["lief"]["features"]["frozen"] else "ON"),
]
)
def get_feat_opt(self):
opt = self._config["lief"]["features"]
return (
"-DLIEF_ENABLE_JSON={}".format("ON" if opt["json"] else "OFF"),
"-DLIEF_DISABLE_FROZEN={}".format("OFF" if opt["frozen"] else "ON"),
)
def get_iwyu_opt(self):
if "include-what-you-use" in self._config["lief"]["build"]:
value = self._config["lief"]["build"]["include-what-you-use"]
opt.append(f"-DCMAKE_CXX_INCLUDE_WHAT_YOU_USE={value}")
return (f"-DCMAKE_CXX_INCLUDE_WHAT_YOU_USE={value}", )
else:
opt.append("-DCMAKE_CXX_INCLUDE_WHAT_YOU_USE=''")
return ("-DCMAKE_CXX_INCLUDE_WHAT_YOU_USE=''", )
def get_flags_opt(self):
opt = []
if "cxx-flags" in self._config["lief"]["build"]:
value = self._config["lief"]["build"]["cxx-flags"]
opt.append(f"-DCMAKE_CXX_FLAGS={value}")
@@ -96,16 +116,6 @@ class Config:
else:
opt.append("-DCMAKE_C_FLAGS=''")
if "extra-cmake-opt" in self._config["lief"]["build"]:
value = self._config["lief"]["build"]["extra-cmake-opt"]
if isinstance(value, str):
opt.append(value)
elif hasattr(value, "__iter__"):
opt.extend(value)
else:
print(f"Unsupported opt: {value} ({type(value)})")
sys.exit(1)
cxx_flags = os.getenv("CXXFLAGS", None)
c_flags = os.getenv("CFLAGS", None)
@@ -115,13 +125,86 @@ class Config:
if c_flags is not None:
opt.append(f'-DCMAKE_C_FLAGS={c_flags}')
return opt
def get_cmake_extra_opt(self):
opt = []
if "extra-cmake-opt" in self._config["lief"]["build"]:
value = self._config["lief"]["build"]["extra-cmake-opt"]
if isinstance(value, str):
opt.append(value)
elif hasattr(value, "__iter__"):
opt.extend(value)
else:
print(f"Unsupported opt: {value} ({type(value)})")
sys.exit(1)
return opt
def get_third_party_opt(self) -> List[str]:
if "third-party" not in self._config["lief"]:
return []
cmake_opt = []
tp_conf = self._config["lief"]["third-party"]
if "spdlog" in tp_conf:
cmake_opt += [
"-DLIEF_EXTERNAL_SPDLOG=ON",
"-Dspdlog_DIR={}".format(tp_conf["spdlog"])
]
return cmake_opt
def get_cross_compile_opt(self) -> List[str]:
if "cross-compilation" not in self._config["lief"]:
return []
cmake_opt = []
cross_conf = self._config["lief"]["cross-compilation"]
if "osx-arch" in cross_conf:
cmake_opt += [
f'-DCMAKE_OSX_ARCHITECTURES={cross_conf["osx-arch"]}'
]
return cmake_opt
def get_pre_compile_opt(self):
install_path = self._config["lief"]["build"].get("lief-install-dir", None)
if install_path is None:
return []
install_path = Path(install_path).expanduser().resolve().absolute()
if not install_path.is_dir():
report(f"{install_path} is not a valid directory")
return []
cmake_dir = install_path / "share" / "LIEF" / "cmake"
if not (cmake_dir / "LIEFConfig.cmake").is_file():
report(f"Missing LIEFConfig.cmake in {cmake_dir}")
return []
return (
"-DLIEF_PY_LIEF_EXT=on",
"-DLIEF_INSTALL=off",
f"-DLIEF_DIR={cmake_dir}",
)
def gen_cmake_option(self, output: str) -> List[str]:
cfg = self.build_type()
opt = [
*self.get_generic_opt(output),
*self.get_python_opt(),
*self.get_lief_format_opt(),
*self.get_feat_opt(),
*self.get_iwyu_opt(),
*self.get_flags_opt(),
*self.get_third_party_opt(),
*self.get_pre_compile_opt(),
*self.get_cross_compile_opt(),
*self.get_cmake_extra_opt()
]
if self._use_ninja():
opt = ["-G", "Ninja"] + opt
opt += self._get_third_party_opt()
opt += self._get_cross_compile_opt()
if Config.is_windows():
is64 = sys.maxsize > 2**32
opt += [
@@ -140,30 +223,6 @@ class Config:
return opt
def _get_third_party_opt(self) -> List[str]:
if "third-party" not in self._config["lief"]:
return []
cmake_opt = []
tp_conf = self._config["lief"]["third-party"]
if "spdlog" in tp_conf:
cmake_opt += [
"-DLIEF_EXTERNAL_SPDLOG=ON",
"-Dspdlog_DIR={}".format(tp_conf["spdlog"])
]
return cmake_opt
def _get_cross_compile_opt(self) -> List[str]:
if "cross-compilation" not in self._config["lief"]:
return []
cmake_opt = []
cross_conf = self._config["lief"]["cross-compilation"]
if "osx-arch" in cross_conf:
cmake_opt += [
f'-DCMAKE_OSX_ARCHITECTURES={cross_conf["osx-arch"]}'
]
return cmake_opt
def _get_jobs(self) -> List[str]:
if "parallel-jobs" in self._config["lief"]["build"]:
@@ -196,6 +255,7 @@ class Config:
def _use_ninja(self) -> bool:
return self._config['lief']['build']['ninja']
def get_compile_cmd(self):
config = self._config['lief']['build']['type']
return [
+5 -14
View File
@@ -1,19 +1,10 @@
set(LIEF_PYTHON_ART_SRC
"${CMAKE_CURRENT_LIST_DIR}/pyART.cpp"
"${CMAKE_CURRENT_LIST_DIR}/pyEnums.cpp"
"${CMAKE_CURRENT_LIST_DIR}/pyUtils.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pyHeader.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pyParser.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pyFile.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/pyUtils.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/init.cpp"
)
set(LIEF_PYTHON_ART_HDR
"${CMAKE_CURRENT_LIST_DIR}/pyART.hpp")
source_group("Source Files\\ART" FILES ${LIEF_PYTHON_ART_SRC})
source_group("Header Files\\ART" FILES ${LIEF_PYTHON_ART_HDR})
target_sources(pyLIEF PRIVATE "${LIEF_PYTHON_ART_SRC}" "${LIEF_PYTHON_ART_HDR}")
target_include_directories(pyLIEF PUBLIC "${CMAKE_CURRENT_LIST_DIR}" "${CMAKE_CURRENT_LIST_DIR}/../")
"${CMAKE_CURRENT_SOURCE_DIR}/pyART.hpp")
target_sources(pyLIEF PRIVATE ${LIEF_PYTHON_ART_SRC} ${LIEF_PYTHON_ART_HDR})
add_subdirectory(objects)
@@ -13,21 +13,39 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "pyART.hpp"
#include "ART/pyART.hpp"
#include "ART/init.hpp"
#include "LIEF/ART/Parser.hpp"
#include "LIEF/ART/File.hpp"
#include "LIEF/ART/Header.hpp"
#include "LIEF/ART/enums.hpp"
#include "LIEF/ART/EnumToString.hpp"
#define CREATE(X,Y) create<X>(Y)
#define PY_ENUM(x) to_string(x), x
namespace LIEF {
namespace ART {
void init_enums(py::module& m) {
namespace LIEF::ART::py {
py::enum_<STORAGE_MODES>(m, "STORAGE_MODES")
inline void init_objects(nb::module_& m) {
CREATE(Parser, m);
CREATE(File, m);
CREATE(Header, m);
}
inline void init_enums(nb::module_& m) {
nb::enum_<STORAGE_MODES>(m, "STORAGE_MODES")
.value(PY_ENUM(STORAGE_MODES::STORAGE_UNCOMPRESSED))
.value(PY_ENUM(STORAGE_MODES::STORAGE_LZ4))
.value(PY_ENUM(STORAGE_MODES::STORAGE_LZ4HC));
}
}
void init(nb::module_& m) {
nb::module_ mod = m.def_submodule("ART", "Python API for ART format");
init_enums(mod);
init_objects(mod);
init_utils(mod);
}
}
@@ -13,15 +13,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef PY_LIEF_ENCODING_H_
#define PY_LIEF_ENCODING_H_
#include <pybind11/pybind11.h>
#include <pybind11/eval.h>
namespace py = pybind11;
py::object safe_string_converter(const std::string& str);
#ifndef PY_LIEF_ART_INIT_H
#define PY_LIEF_ART_INIT_H
#include "pyLIEF.hpp"
namespace LIEF::ART::py {
void init(nb::module_& m);
void init_utils(nb::module_& m);
}
#endif
@@ -0,0 +1,9 @@
set(LIEF_PYTHON_ART_OBJ_SRC
"${CMAKE_CURRENT_SOURCE_DIR}/pyHeader.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/pyParser.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/pyFile.cpp"
)
target_sources(pyLIEF PRIVATE ${LIEF_PYTHON_ART_OBJ_SRC})
+10 -41
View File
@@ -14,54 +14,23 @@
* limitations under the License.
*/
#include "LIEF/ART/File.hpp"
#include "LIEF/ART/hash.hpp"
#include "pyART.hpp"
#include "ART/pyART.hpp"
#include <sstream>
#include <nanobind/stl/string.h>
namespace LIEF {
namespace ART {
template<class T>
using no_const_getter = T (File::*)(void);
template<class T, class P>
using no_const_func = T (File::*)(P);
template<class T>
using getter_t = T (File::*)(void) const;
template<class T>
using setter_t = void (File::*)(T);
namespace LIEF::ART::py {
template<>
void create<File>(py::module& m) {
void create<File>(nb::module_& m) {
nb::class_<File, LIEF::Object>(m, "File", "ART File representation"_doc)
// File object
py::class_<File, LIEF::Object>(m, "File", "ART File representation")
.def_property_readonly("header",
static_cast<no_const_getter<Header&>>(&File::header),
"Return the ART " RST_CLASS_REF(lief.ART.Header) "",
py::return_value_policy::reference)
.def("__eq__", &File::operator==)
.def("__ne__", &File::operator!=)
.def("__hash__",
[] (const File& file) {
return Hash::hash(file);
})
.def("__str__",
[] (const File& file)
{
std::ostringstream stream;
stream << file;
std::string str = stream.str();
return str;
});
.def_prop_ro("header",
nb::overload_cast<>(&File::header),
"Return the ART " RST_CLASS_REF(lief.ART.Header) ""_doc,
nb::rv_policy::reference_internal)
LIEF_DEFAULT_STR(Header);
}
}
}
+47 -68
View File
@@ -14,102 +14,81 @@
* limitations under the License.
*/
#include "LIEF/ART/Header.hpp"
#include "LIEF/ART/hash.hpp"
#include "pyART.hpp"
#include "ART/pyART.hpp"
#include <sstream>
#include <nanobind/stl/string.h>
#include <nanobind/stl/array.h>
namespace LIEF {
namespace ART {
template<class T>
using getter_t = T (Header::*)(void) const;
template<class T>
using setter_t = void (Header::*)(T);
namespace LIEF::ART::py {
template<>
void create<Header>(py::module& m) {
void create<Header>(nb::module_& m) {
py::class_<Header, LIEF::Object>(m, "Header", "ART Header representation")
.def_property_readonly("magic",
static_cast<getter_t<Header::magic_t>>(&Header::magic)
nb::class_<Header, Object>(m, "Header", "ART Header representation"_doc)
.def_prop_ro("magic",
nb::overload_cast<>(&Header::magic, nb::const_)
)
.def_property_readonly("version",
static_cast<getter_t<art_version_t>>(&Header::version)
.def_prop_ro("version",
nb::overload_cast<>(&Header::version, nb::const_)
)
.def_property_readonly("image_begin",
static_cast<getter_t<uint32_t>>(&Header::image_begin)
.def_prop_ro("image_begin",
nb::overload_cast<>(&Header::image_begin, nb::const_)
)
.def_property_readonly("image_size",
static_cast<getter_t<uint32_t>>(&Header::image_size)
.def_prop_ro("image_size",
nb::overload_cast<>(&Header::image_size, nb::const_)
)
.def_property_readonly("oat_checksum",
static_cast<getter_t<uint32_t>>(&Header::oat_checksum)
.def_prop_ro("oat_checksum",
nb::overload_cast<>(&Header::oat_checksum, nb::const_)
)
.def_property_readonly("oat_file_begin",
static_cast<getter_t<uint32_t>>(&Header::oat_file_begin)
.def_prop_ro("oat_file_begin",
nb::overload_cast<>(&Header::oat_file_begin, nb::const_)
)
.def_property_readonly("oat_file_end",
static_cast<getter_t<uint32_t>>(&Header::oat_file_end)
.def_prop_ro("oat_file_end",
nb::overload_cast<>(&Header::oat_file_end, nb::const_)
)
.def_property_readonly("oat_data_end",
static_cast<getter_t<uint32_t>>(&Header::oat_data_end)
.def_prop_ro("oat_data_end",
nb::overload_cast<>(&Header::oat_data_end, nb::const_)
)
.def_property_readonly("patch_delta",
static_cast<getter_t<int32_t>>(&Header::patch_delta)
.def_prop_ro("patch_delta",
nb::overload_cast<>(&Header::patch_delta, nb::const_)
)
.def_property_readonly("image_roots",
static_cast<getter_t<uint32_t>>(&Header::image_roots)
.def_prop_ro("image_roots",
nb::overload_cast<>(&Header::image_roots, nb::const_)
)
.def_property_readonly("pointer_size",
static_cast<getter_t<uint32_t>>(&Header::pointer_size)
.def_prop_ro("pointer_size",
nb::overload_cast<>(&Header::pointer_size, nb::const_)
)
.def_property_readonly("compile_pic",
static_cast<getter_t<bool>>(&Header::compile_pic)
.def_prop_ro("compile_pic",
nb::overload_cast<>(&Header::compile_pic, nb::const_)
)
.def_property_readonly("nb_sections",
static_cast<getter_t<uint32_t>>(&Header::nb_sections)
.def_prop_ro("nb_sections",
nb::overload_cast<>(&Header::nb_sections, nb::const_)
)
.def_property_readonly("nb_methods",
static_cast<getter_t<uint32_t>>(&Header::nb_methods)
.def_prop_ro("nb_methods",
nb::overload_cast<>(&Header::nb_methods, nb::const_)
)
.def_property_readonly("boot_image_begin",
static_cast<getter_t<uint32_t>>(&Header::boot_image_begin)
.def_prop_ro("boot_image_begin",
nb::overload_cast<>(&Header::boot_image_begin, nb::const_)
)
.def_property_readonly("boot_image_size",
static_cast<getter_t<uint32_t>>(&Header::boot_image_size)
.def_prop_ro("boot_image_size",
nb::overload_cast<>(&Header::boot_image_size, nb::const_)
)
.def_property_readonly("boot_oat_begin",
static_cast<getter_t<uint32_t>>(&Header::boot_oat_begin)
.def_prop_ro("boot_oat_begin",
nb::overload_cast<>(&Header::boot_oat_begin, nb::const_)
)
.def_property_readonly("boot_oat_size",
static_cast<getter_t<uint32_t>>(&Header::boot_oat_size)
.def_prop_ro("boot_oat_size",
nb::overload_cast<>(&Header::boot_oat_size, nb::const_)
)
.def_property_readonly("storage_mode",
static_cast<getter_t<STORAGE_MODES>>(&Header::storage_mode)
.def_prop_ro("storage_mode",
nb::overload_cast<>(&Header::storage_mode, nb::const_)
)
.def_property_readonly("data_size",
static_cast<getter_t<uint32_t>>(&Header::data_size)
.def_prop_ro("data_size",
nb::overload_cast<>(&Header::data_size, nb::const_)
)
.def("__eq__", &Header::operator==)
.def("__ne__", &Header::operator!=)
.def("__hash__",
[] (const Header& header) {
return Hash::hash(header);
})
.def("__str__",
[] (const Header& header)
{
std::ostringstream stream;
stream << header;
std::string str = stream.str();
return str;
});
}
LIEF_DEFAULT_STR(Header);
}
}
+28 -48
View File
@@ -13,68 +13,48 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "pyART.hpp"
#include "LIEF/ART/Parser.hpp"
#include "LIEF/ART/File.hpp"
#include "LIEF/logging.hpp"
#include "ART/pyART.hpp"
#include "pyIOStream.hpp"
#include <string>
#include <memory>
namespace LIEF {
namespace ART {
#include <nanobind/stl/string.h>
#include <nanobind/stl/vector.h>
#include <nanobind/stl/unique_ptr.h>
namespace LIEF::ART::py {
template<>
void create<Parser>(py::module& m) {
void create<Parser>(nb::module_& m) {
using namespace LIEF::py;
// Parser (Parser)
m.def("parse",
static_cast<std::unique_ptr<File> (*) (const std::string&)>(&Parser::parse),
"Parse the given filename and return an " RST_CLASS_REF(lief.ART.File) " object",
nb::overload_cast<const std::string&>(&Parser::parse),
"Parse the given filename and return an " RST_CLASS_REF(lief.ART.File) " object"_doc,
"filename"_a,
py::return_value_policy::take_ownership);
nb::rv_policy::take_ownership);
m.def("parse",
static_cast<std::unique_ptr<File> (*) (std::vector<uint8_t>, const std::string&)>(&Parser::parse),
"Parse the given raw data and return an " RST_CLASS_REF(lief.ART.File) " object",
nb::overload_cast<std::vector<uint8_t>, const std::string&>(&Parser::parse),
"Parse the given raw data and return an " RST_CLASS_REF(lief.ART.File) " object"_doc,
"raw"_a, "name"_a = "",
py::return_value_policy::take_ownership);
nb::rv_policy::take_ownership);
m.def("parse",
[] (py::object byteio, const std::string& name) {
const auto& io = py::module::import("io");
const auto& RawIOBase = io.attr("RawIOBase");
const auto& BufferedIOBase = io.attr("BufferedIOBase");
const auto& TextIOBase = io.attr("TextIOBase");
py::object rawio;
if (py::isinstance(byteio, RawIOBase)) {
rawio = byteio;
}
else if (py::isinstance(byteio, BufferedIOBase)) {
rawio = byteio.attr("raw");
}
else if (py::isinstance(byteio, TextIOBase)) {
rawio = byteio.attr("buffer").attr("raw");
}
else {
throw py::type_error(py::repr(byteio).cast<std::string>().c_str());
}
std::string raw_str = static_cast<py::bytes>(rawio.attr("readall")());
std::vector<uint8_t> raw = {
std::make_move_iterator(std::begin(raw_str)),
std::make_move_iterator(std::end(raw_str))};
return LIEF::ART::Parser::parse(std::move(raw), name);
},
"io"_a, "name"_a = "",
py::return_value_policy::take_ownership);
}
[] (nb::object byteio, const std::string& name) -> nb::object {
if (auto stream = PyIOStream::from_python(std::move(byteio))) {
auto ptr = std::make_unique<PyIOStream>(std::move(*stream));
return nb::cast(Parser::parse(stream->content(), name));
}
logging::log(logging::LOG_ERR, "Can't create a LIEF stream interface over the provided io");
return nb::none();
}, "io"_a, "name"_a = "", nb::rv_policy::take_ownership);
}
}
+5 -32
View File
@@ -13,41 +13,14 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef PY_LIEF_ART_H_
#define PY_LIEF_ART_H_
#include "LIEF/ART.hpp"
#ifndef PY_LIEF_ART_H
#define PY_LIEF_ART_H
#include "pyLIEF.hpp"
#define SPECIALIZE_CREATE(X) \
template<> \
void create<X>(py::module&)
#define CREATE(X,Y) create<X>(Y)
namespace LIEF {
namespace ART {
namespace LIEF::ART::py {
template<class T>
void create(py::module&);
void init_python_module(py::module& m);
void init_objects(py::module&);
void init_enums(py::module&);
void init_utils(py::module&);
SPECIALIZE_CREATE(Parser);
SPECIALIZE_CREATE(File);
SPECIALIZE_CREATE(Header);
void create(nb::module_&);
void init_utils(nb::module_&);
}
}
#endif
+19 -16
View File
@@ -13,42 +13,45 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "pyART.hpp"
#include "ART/pyART.hpp"
#include "LIEF/ART/utils.hpp"
namespace LIEF {
namespace ART {
#include <nanobind/stl/string.h>
#include <nanobind/stl/vector.h>
void init_utils(py::module& m) {
namespace LIEF::ART::py {
m.def("is_art",
static_cast<bool (*)(const std::string&)>(&is_art),
"Check if the **file** given in parameter is an ART",
void init_utils(nb::module_& m) {
nb::module_ lief_mod = nb::module_::import_(LIEF_MOD_NAME);
lief_mod.def("is_art",
nb::overload_cast<const std::string&>(&is_art),
"Check if the **file** given in parameter is an ART"_doc,
"path"_a);
m.def("is_art",
static_cast<bool (*)(const std::vector<uint8_t>&)>(&is_art),
"Check if the **raw data** given in parameter is a ART",
lief_mod.def("is_art",
nb::overload_cast<const std::vector<uint8_t>&>(&is_art),
"Check if the **raw data** given in parameter is a ART"_doc,
"raw"_a);
m.def("version",
static_cast<art_version_t (*)(const std::string&)>(&version),
"Return the ART version of the **file** given in parameter",
nb::overload_cast<const std::string&>(&version),
"Return the ART version of the **file** given in parameter"_doc,
"file"_a);
m.def("version",
static_cast<art_version_t (*)(const std::vector<uint8_t>&)>(&version),
"Return the ART version of the **raw data** given in parameter",
nb::overload_cast<const std::vector<uint8_t>&>(&version),
"Return the ART version of the **raw data** given in parameter"_doc,
"raw"_a);
m.def("android_version",
&android_version,
"Return the " RST_CLASS_REF(lief.Android.ANDROID_VERSIONS) " associated with the given ART version ",
"Return the " RST_CLASS_REF(lief.Android.ANDROID_VERSIONS) " associated with the given ART version "_doc,
"art_version"_a);
}
}
}
+13 -19
View File
@@ -1,25 +1,19 @@
set(LIEF_PYTHON_ABSTRACT_SRC
"${CMAKE_CURRENT_LIST_DIR}/pyAbstract.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pyBinary.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pyHeader.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pySection.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pyParser.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pySymbol.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pyRelocation.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pyFunction.cpp"
"${CMAKE_CURRENT_LIST_DIR}/pyEnums.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/init.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/enums.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/pyParser.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/pyHeader.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/pySymbol.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/pyRelocation.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/pySection.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/pyFunction.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/pyBinary.cpp"
)
set(LIEF_PYTHON_ABSTRACT_HDR
"${CMAKE_CURRENT_LIST_DIR}/pyAbstract.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/init.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/enums.hpp"
)
source_group("Source Files\\Abstract" FILES ${LIEF_PYTHON_ABSTRACT_SRC})
source_group("Header Files\\Abstract" FILES ${LIEF_PYTHON_ABSTRACT_HDR})
target_sources(pyLIEF PRIVATE "${LIEF_PYTHON_ABSTRACT_SRC}" "${LIEF_PYTHON_ABSTRACT_HDR}")
target_include_directories(pyLIEF PUBLIC "${CMAKE_CURRENT_LIST_DIR}")
target_sources(pyLIEF
PRIVATE ${LIEF_PYTHON_ABSTRACT_SRC} ${LIEF_PYTHON_ELF_HDR})
@@ -13,27 +13,28 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "pyAbstract.hpp"
#include "LIEF/Abstract/enums.hpp"
#include "enums.hpp"
#include "LIEF/enums.hpp"
#include "LIEF/Abstract/EnumToString.hpp"
#include "enums_wrapper.hpp"
#define PY_ENUM(x) LIEF::to_string(x), x
namespace LIEF {
#define PY_ENUM(x) to_string(x), x
void init_enums(py::module& m) {
py::enum_<EXE_FORMATS>(m, "EXE_FORMATS")
namespace LIEF::py {
void init_enums(nb::module_& m) {
enum_<EXE_FORMATS>(m, "EXE_FORMATS")
.value(PY_ENUM(EXE_FORMATS::FORMAT_UNKNOWN))
.value(PY_ENUM(EXE_FORMATS::FORMAT_ELF))
.value(PY_ENUM(EXE_FORMATS::FORMAT_PE))
.value(PY_ENUM(EXE_FORMATS::FORMAT_MACHO));
py::enum_<OBJECT_TYPES>(m, "OBJECT_TYPES")
enum_<OBJECT_TYPES>(m, "OBJECT_TYPES")
.value(PY_ENUM(OBJECT_TYPES::TYPE_NONE))
.value(PY_ENUM(OBJECT_TYPES::TYPE_EXECUTABLE))
.value(PY_ENUM(OBJECT_TYPES::TYPE_LIBRARY))
.value(PY_ENUM(OBJECT_TYPES::TYPE_OBJECT));
py::enum_<ARCHITECTURES>(m, "ARCHITECTURES")
enum_<ARCHITECTURES>(m, "ARCHITECTURES")
.value(PY_ENUM(ARCHITECTURES::ARCH_NONE))
.value(PY_ENUM(ARCHITECTURES::ARCH_ARM))
.value(PY_ENUM(ARCHITECTURES::ARCH_ARM64))
@@ -47,7 +48,7 @@ void init_enums(py::module& m) {
.value(PY_ENUM(ARCHITECTURES::ARCH_RISCV))
.value(PY_ENUM(ARCHITECTURES::ARCH_LOONGARCH));
py::enum_<MODES>(m, "MODES")
enum_<MODES>(m, "MODES")
.value(PY_ENUM(MODES::MODE_NONE))
.value(PY_ENUM(MODES::MODE_16))
.value(PY_ENUM(MODES::MODE_32))
@@ -65,9 +66,10 @@ void init_enums(py::module& m) {
.value(PY_ENUM(MODES::MODE_MIPS32))
.value(PY_ENUM(MODES::MODE_MIPS64));
py::enum_<ENDIANNESS>(m, "ENDIANNESS")
enum_<ENDIANNESS>(m, "ENDIANNESS")
.value(PY_ENUM(ENDIANNESS::ENDIAN_NONE))
.value(PY_ENUM(ENDIANNESS::ENDIAN_BIG))
.value(PY_ENUM(ENDIANNESS::ENDIAN_LITTLE));
}
}
@@ -13,14 +13,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "LIEF/config.h"
#include "LIEF/json.hpp"
#include "LIEF/Abstract/json.hpp"
#include "LIEF/Object.hpp"
#ifndef PY_LIEF_ENUMS_H
#define PY_LIEF_ENUMS_H
#include "pyLIEF.hpp"
void init_json_functions(py::module& m) {
m.def("to_json", &LIEF::to_json);
m.def("to_json_from_abstract", &LIEF::to_json_from_abstract);
namespace LIEF::py {
void init_enums(nb::module_& m);
}
#endif
@@ -13,32 +13,33 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef PY_LIEF_ABSTRACT_H_
#define PY_LIEF_ABSTRACT_H_
#include "pyLIEF.hpp"
#include "LIEF/Abstract.hpp"
#include "Abstract/init.hpp"
#include "Abstract/enums.hpp"
#define SPECIALIZE_CREATE(X) \
template<> \
void create<X>(py::module&)
#include "LIEF/Abstract/Header.hpp"
#include "LIEF/Abstract/Binary.hpp"
#include "LIEF/Abstract/Section.hpp"
#include "LIEF/Abstract/Symbol.hpp"
#include "LIEF/Abstract/Parser.hpp"
#include "LIEF/Abstract/Relocation.hpp"
#include "LIEF/Abstract/Function.hpp"
#define CREATE(X,Y) create<X>(Y)
namespace LIEF {
template<class T>
void create(py::module&);
namespace LIEF::py {
void init_python_module(py::module& m);
void init_objects(py::module&);
void init_enums(py::module&);
SPECIALIZE_CREATE(Header);
SPECIALIZE_CREATE(Binary);
SPECIALIZE_CREATE(Section);
SPECIALIZE_CREATE(Symbol);
SPECIALIZE_CREATE(Parser);
SPECIALIZE_CREATE(Relocation);
SPECIALIZE_CREATE(Function);
void init_objects(nb::module_& m) {
CREATE(Header, m);
CREATE(Binary, m);
CREATE(Section, m);
CREATE(Symbol, m);
CREATE(Parser, m);
CREATE(Relocation, m);
CREATE(Function, m);
}
void init_abstract(nb::module_& m) {
init_enums(m);
init_objects(m);
}
}
#endif
@@ -13,24 +13,17 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "pyVDEX.hpp"
#ifndef PY_LIEF_ABSTRACT_H
#define PY_LIEF_ABSTRACT_H
namespace LIEF {
namespace VDEX {
void init_python_module(py::module& m) {
py::module LIEF_VDEX_module = m.def_submodule("VDEX", "Python API for VDEX format");
init_objects(LIEF_VDEX_module);
init_utils(LIEF_VDEX_module);
namespace nanobind {
class module_;
}
namespace LIEF::py {
template<class T>
void create(nanobind::module_&);
void init_objects(py::module& m) {
CREATE(Parser, m);
CREATE(File, m);
CREATE(Header, m);
}
}
void init_abstract(nanobind::module_& m);
}
#endif
@@ -1,78 +0,0 @@
/* Copyright 2017 - 2023 R. Thomas
* Copyright 2017 - 2023 Quarkslab
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <sstream>
#include "pyAbstract.hpp"
#include "LIEF/Abstract/Header.hpp"
namespace LIEF {
template<class T>
using getter_t = T (Header::*)(void) const;
template<class T>
using setter_t = void (Header::*)(T);
template<>
void create<Header>(py::module& m) {
py::class_<Header, Object>(m, "Header")
.def(py::init())
.def_property("architecture",
static_cast<getter_t<ARCHITECTURES>>(&Header::architecture),
static_cast<setter_t<ARCHITECTURES>>(&Header::architecture),
"Target architecture (" RST_CLASS_REF(lief.ARCHITECTURES) ")")
.def_property("modes",
static_cast<getter_t<const std::set<MODES>&>>(&Header::modes),
static_cast<setter_t<const std::set<MODES>&>>(&Header::modes),
"Target " RST_CLASS_REF(lief.MODES) " (32-bits, 64-bits...)")
.def_property("entrypoint",
static_cast<getter_t<uint64_t>>(&Header::entrypoint),
static_cast<setter_t<uint64_t>>(&Header::entrypoint),
"Binary entrypoint")
.def_property("object_type",
static_cast<getter_t<OBJECT_TYPES>>(&Header::object_type),
static_cast<setter_t<OBJECT_TYPES>>(&Header::object_type),
"Type of the binary (executable, library...)\n"
"See: " RST_CLASS_REF(lief.OBJECT_TYPES) "")
.def_property("endianness",
static_cast<getter_t<ENDIANNESS>>(&Header::endianness),
static_cast<setter_t<ENDIANNESS>>(&Header::endianness),
"Binary endianness\n"
"See: " RST_CLASS_REF(lief.ENDIANNESS) "")
.def_property_readonly("is_32",
&Header::is_32,
"``True`` if the binary targets a ``32-bits`` architecture")
.def_property_readonly("is_64",
&Header::is_64,
"``True`` if the binary targets a ``64-bits`` architecture")
.def("__str__",
[] (const Header& header)
{
std::ostringstream stream;
stream << header;
std::string str = stream.str();
return str;
});
}
}
@@ -1,119 +0,0 @@
/* Copyright 2017 - 2023 R. Thomas
* Copyright 2017 - 2023 Quarkslab
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "pyAbstract.hpp"
#include "PyIOStream.hpp"
#include "LIEF/logging.hpp"
#include "LIEF/Abstract/Parser.hpp"
#include <string>
#include <stdexcept>
namespace LIEF {
template<>
void create<Parser>(py::module& m) {
m.def("parse",
[] (py::bytes bytes) {
std::string raw_str = bytes;
std::vector<uint8_t> raw = {
std::make_move_iterator(std::begin(raw_str)),
std::make_move_iterator(std::end(raw_str))
};
std::unique_ptr<Binary> binary;
std::exception_ptr ep;
Py_BEGIN_ALLOW_THREADS
try {
binary = Parser::parse(std::move(raw));
} catch (...) {
ep = std::current_exception();
}
Py_END_ALLOW_THREADS
if (ep) std::rethrow_exception(ep);
return binary;
},
R"delim(
Parse a binary supported by LIEF from the given bytes and return either:
- :class:`lief.ELF.Binary`
- :class:`lief.PE.Binary`
- :class:`lief.MachO.Binary`
depending on the given binary format.
)delim",
"raw"_a,
py::return_value_policy::take_ownership);
m.def("parse",
[] (const std::string& filepath) {
std::unique_ptr<Binary> binary;
std::exception_ptr ep;
Py_BEGIN_ALLOW_THREADS
try {
binary = Parser::parse(filepath);
} catch (...) {
ep = std::current_exception();
}
Py_END_ALLOW_THREADS
if (ep) std::rethrow_exception(ep);
return binary;
},
R"delim(
Parse a binary from the given file path and return either:
- :class:`lief.ELF.Binary`
- :class:`lief.PE.Binary`
- :class:`lief.MachO.Binary`
depending on the given binary format.
)delim",
"filepath"_a,
py::return_value_policy::take_ownership);
m.def("parse",
[] (py::object byteio) -> py::object {
if (auto stream = PyIOStream::from_python(byteio)) {
auto ptr = std::make_unique<PyIOStream>(std::move(*stream));
py::object binary;
std::exception_ptr ep;
Py_BEGIN_ALLOW_THREADS
try {
binary = py::cast(Parser::parse(std::move(ptr)));
} catch (...) {
ep = std::current_exception();
}
Py_END_ALLOW_THREADS
if (ep) std::rethrow_exception(ep);
return binary;
}
logging::log(logging::LOG_ERR, "Can't create a LIEF stream interface over the provided io");
return py::none();
},
R"delim(
Parse a binary supported by LIEF from the given Python IO interface and return either:
- :class:`lief.ELF.Binary`
- :class:`lief.PE.Binary`
- :class:`lief.MachO.Binary`
depending on the given binary format.
)delim",
"io"_a,
py::return_value_policy::take_ownership);
}
}
@@ -1,69 +0,0 @@
/* Copyright 2017 - 2023 R. Thomas
* Copyright 2017 - 2023 Quarkslab
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <sstream>
#include "pyAbstract.hpp"
#include "LIEF/Abstract/hash.hpp"
#include "LIEF/Abstract/Relocation.hpp"
namespace LIEF {
template<class T>
using getter_t = T (Relocation::*)(void) const;
template<class T>
using setter_t = void (Relocation::*)(T);
template<>
void create<Relocation>(py::module& m) {
py::class_<Relocation, Object>(m, "Relocation",
R"delim(
Class which represents an abstracted Relocation
)delim")
.def(py::init(),
"Default constructor")
.def(py::init<uint64_t, uint8_t>(),
"Constructor from an :attr:`~lief.Relocation.address` and a :attr:`~lief.Relocation.size`",
"address"_a, "size"_a)
.def_property("address",
static_cast<getter_t<uint64_t>>(&Relocation::address),
static_cast<setter_t<uint64_t>>(&Relocation::address),
"Relocation's address")
.def_property("size",
static_cast<getter_t<size_t>>(&Relocation::size),
static_cast<setter_t<size_t>>(&Relocation::size),
"Relocation's size (in **bits**)")
.def("__eq__", &Relocation::operator==)
.def("__ne__", &Relocation::operator!=)
.def("__hash__",
[] (const Relocation& relocation) {
return AbstractHash::hash(relocation);
})
.def("__str__",
[] (const Relocation& entry)
{
std::ostringstream stream;
stream << entry;
std::string str = stream.str();
return str;
});
}
}
@@ -1,135 +0,0 @@
/* Copyright 2017 - 2023 R. Thomas
* Copyright 2017 - 2023 Quarkslab
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <sstream>
#include "pyAbstract.hpp"
#include "LIEF/Abstract/Section.hpp"
namespace LIEF {
template<class T>
using getter_t = T (Section::*)(void) const;
template<class T>
using setter_t = void (Section::*)(T);
template<>
void create<Section>(py::module& m) {
py::class_<Section, Object>(m, "Section",
R"delim(
Class which represents an abstracted section
)delim")
.def(py::init(),
"Default constructor")
.def(py::init<const std::string&>(),
"Constructor from section name",
"name"_a)
.def_property("name",
[] (const Section& obj) {
return safe_string_converter(obj.name());
},
static_cast<setter_t<const std::string&>>(&Section::name),
"Section's name")
.def_property_readonly("fullname",
&Section::fullname,
"Return the **fullname** of the section including the trailing bytes")
.def_property("size",
static_cast<getter_t<uint64_t>>(&Section::size),
static_cast<setter_t<uint64_t>>(&Section::size),
"Section's size")
.def_property("offset",
static_cast<getter_t<uint64_t>>(&Section::offset),
static_cast<setter_t<uint64_t>>(&Section::offset),
"Section's file offset")
.def_property("virtual_address",
static_cast<getter_t<uint64_t>>(&Section::virtual_address),
static_cast<setter_t<uint64_t>>(&Section::virtual_address),
"Section's virtual address")
.def_property("content",
[] (const Section& self) {
span<const uint8_t> content = self.content();
return py::memoryview::from_memory(content.data(), content.size());
},
static_cast<setter_t<const std::vector<uint8_t>&>>(&Section::content),
"Section's content")
.def_property_readonly("entropy",
&Section::entropy,
"Section's entropy")
.def("search",
[] (const Section& self, uint64_t number, size_t pos, size_t size) -> py::object {
size_t res = self.search(number, pos, size);
if (res == Section::npos) {
return py::none();
}
return py::cast(res);
},
"Look for **integer** within the current section",
"number"_a, "pos"_a = 0, "size"_a = 0)
.def("search",
[] (const Section& self, const std::string& str, size_t pos) -> py::object {
size_t res = self.search(str, pos);
if (res == Section::npos) {
return py::none();
}
return py::cast(res);
},
"Look for **string** within the current section",
"str"_a, "pos"_a = 0)
.def("search",
[] (const Section& self, py::bytes bytes, size_t pos) -> py::object {
std::string raw_str = bytes;
std::vector<uint8_t> raw = {
std::make_move_iterator(std::begin(raw_str)),
std::make_move_iterator(std::end(raw_str))
};
size_t res = self.search(raw, pos);
if (res == Section::npos) {
return py::none();
}
return py::cast(res);
},
"Look for the given bytes within the current section",
"bytes"_a, "pos"_a = 0)
.def("search_all",
static_cast<std::vector<size_t> (Section::*)(uint64_t, size_t) const>(&Section::search_all),
"Look for **all** integers within the current section",
"number"_a, "size"_a = 0)
.def("search_all",
static_cast<std::vector<size_t> (Section::*)(const std::string&) const>(&Section::search_all),
"Look for all **strings** within the current section",
"str"_a)
.def("__str__",
[] (const Section& section)
{
std::ostringstream stream;
stream << section;
std::string str = stream.str();
return str;
});
}
}
@@ -1,66 +0,0 @@
/* Copyright 2017 - 2023 R. Thomas
* Copyright 2017 - 2023 Quarkslab
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "pyAbstract.hpp"
#include "LIEF/Abstract/Symbol.hpp"
#include <string>
#include <sstream>
namespace LIEF {
template<class T>
using getter_t = T (Symbol::*)(void) const;
template<class T>
using setter_t = void (Symbol::*)(T);
template<>
void create<Symbol>(py::module& m) {
py::class_<Symbol, Object>(m, "Symbol",
R"delim(
This class represents a symbol in an executable format.
)delim")
.def(py::init())
.def_property("name",
[] (const Symbol& obj) {
return safe_string_converter(obj.name());
},
static_cast<setter_t<const std::string&>>(&Symbol::name),
"Symbol's name")
.def_property("value",
static_cast<getter_t<uint64_t>>(&Symbol::value),
static_cast<setter_t<uint64_t>>(&Symbol::value),
"Symbol's value")
.def_property("size",
static_cast<getter_t<uint64_t>>(&Symbol::size),
static_cast<setter_t<uint64_t>>(&Symbol::size),
"Symbol's size")
.def("__str__",
[] (const Symbol& symbol)
{
std::ostringstream stream;
stream << symbol;
std::string str = stream.str();
return str;
});
}
}
@@ -13,43 +13,44 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <algorithm>
#include <sstream>
#include <iostream>
#include "pyAbstract.hpp"
#include "pyIterators.hpp"
#include <nanobind/stl/string.h>
#include <nanobind/stl/vector.h>
#include "Abstract/init.hpp"
#include "pyLIEF.hpp"
#include "pyErr.hpp"
#include "LIEF/Abstract/Binary.hpp"
#include "pySafeString.hpp"
#include "nanobind/extra/memoryview.hpp"
#include "pyIterator.hpp"
#include "LIEF/logging.hpp"
#include "LIEF/Abstract/Binary.hpp"
#include "LIEF/Abstract/Relocation.hpp"
#include "LIEF/Abstract/Symbol.hpp"
#include "LIEF/Abstract/Section.hpp"
#include "LIEF/Abstract/Header.hpp"
#include "LIEF/Abstract/EnumToString.hpp"
#define PY_ENUM(x) LIEF::to_string(x), x
namespace LIEF {
template<class T>
using getter_t = T (Binary::*)(void) const;
template<class T>
using setter_t = void (Binary::*)(T);
template<class T>
using it_t = T (Binary::*)(void);
template<class T, class P>
using no_const_func = T (Binary::*)(P);
namespace LIEF::py {
template<>
void create<Binary>(py::module& m) {
py::class_<Binary, Object> pybinary(m, "Binary",
void create<Binary>(nb::module_& m) {
nb::class_<Binary, Object> pybinary(m, "Binary",
R"delim(
File format abstract representation.
This object represents the abstraction of an executable file format.
It enables to access common features (like the :attr:`~lief.Binary.entrypoint`) regardless
of the concrete format (e.g. :attr:`lief.ELF.Binary.entrypoint`)
)delim");
)delim"_doc);
py::enum_<Binary::VA_TYPES>(pybinary, "VA_TYPES")
nb::enum_<Binary::VA_TYPES>(pybinary, "VA_TYPES")
.value(PY_ENUM(Binary::VA_TYPES::AUTO))
.value(PY_ENUM(Binary::VA_TYPES::VA))
.value(PY_ENUM(Binary::VA_TYPES::RVA));
@@ -59,117 +60,117 @@ void create<Binary>(py::module& m) {
init_ref_iterator<Binary::it_relocations>(pybinary, "it_relocations");
pybinary
.def_property_readonly("format",
.def_prop_ro("format",
&Binary::format,
"File format " RST_CLASS_REF(lief.EXE_FORMATS) " of the underlying binary.")
"File format " RST_CLASS_REF(lief.EXE_FORMATS) " of the underlying binary."_doc)
.def_property_readonly("is_pie",
.def_prop_ro("is_pie",
&Binary::is_pie,
"Check if the binary is position independent")
"Check if the binary is position independent"_doc)
.def_property_readonly("has_nx",
.def_prop_ro("has_nx",
&Binary::has_nx,
"Check if the binary has ``NX`` protection (non executable stack)")
"Check if the binary has ``NX`` protection (non executable stack)"_doc)
.def_property_readonly("header",
.def_prop_ro("header",
&Binary::header,
"Binary's abstract header (" RST_CLASS_REF(lief.Header) ")")
"Binary's abstract header (" RST_CLASS_REF(lief.Header) ")"_doc)
.def_property_readonly("entrypoint",
.def_prop_ro("entrypoint",
&Binary::entrypoint,
"Binary's entrypoint")
"Binary's entrypoint"_doc)
.def("remove_section",
static_cast<void (Binary::*)(const std::string&, bool)>(&Binary::remove_section),
"Remove the section with the given name",
nb::overload_cast<const std::string&, bool>(&Binary::remove_section),
"Remove the section with the given name"_doc,
"name"_a, "clear"_a = false)
.def_property_readonly("sections",
static_cast<it_t<Binary::it_sections>>(&Binary::sections),
"Return an iterator over the binary's abstract sections (" RST_CLASS_REF(lief.Section) ")",
py::return_value_policy::reference_internal)
.def_prop_ro("sections",
nb::overload_cast<>(&Binary::sections),
"Return an iterator over the binary's abstract sections (" RST_CLASS_REF(lief.Section) ")"_doc,
nb::keep_alive<0, 1>())
.def_property_readonly("relocations",
static_cast<it_t<Binary::it_relocations>>(&Binary::relocations),
"Return an iterator over abstract " RST_CLASS_REF(lief.Relocation) "",
py::return_value_policy::reference_internal)
.def_prop_ro("relocations",
nb::overload_cast<>(&Binary::relocations),
"Return an iterator over abstract " RST_CLASS_REF(lief.Relocation) ""_doc,
nb::keep_alive<0, 1>())
.def_property_readonly("exported_functions",
.def_prop_ro("exported_functions",
&Binary::exported_functions,
"Return the binary's exported " RST_CLASS_REF(lief.Function) "")
"Return the binary's exported " RST_CLASS_REF(lief.Function) ""_doc)
.def_property_readonly("imported_functions",
.def_prop_ro("imported_functions",
&Binary::imported_functions,
"Return the binary's imported " RST_CLASS_REF(lief.Function) " (name)")
"Return the binary's imported " RST_CLASS_REF(lief.Function) " (name)"_doc)
.def_property_readonly("libraries",
.def_prop_ro("libraries",
[] (const Binary& binary) {
const std::vector<std::string>& imported_libraries = binary.imported_libraries();
std::vector<py::object> imported_libraries_encoded;
std::vector<nb::object> imported_libraries_encoded;
imported_libraries_encoded.reserve(imported_libraries.size());
std::transform(
std::begin(imported_libraries), std::end(imported_libraries),
std::back_inserter(imported_libraries_encoded),
&safe_string_converter);
&safe_string);
return imported_libraries_encoded;
},
"Return binary's imported libraries (name)")
"Return binary's imported libraries (name)"_doc)
.def_property_readonly("symbols",
static_cast<it_t<Binary::it_symbols>>(&Binary::symbols),
"Return an iterator over the binary's abstract " RST_CLASS_REF(lief.Symbol) "",
py::return_value_policy::reference_internal)
.def_prop_ro("symbols",
nb::overload_cast<>(&Binary::symbols),
"Return an iterator over the binary's abstract " RST_CLASS_REF(lief.Symbol) ""_doc,
nb::keep_alive<0, 1>())
.def("has_symbol",
&Binary::has_symbol,
"Check if a " RST_CLASS_REF(lief.Symbol) " with the given name exists",
"Check if a " RST_CLASS_REF(lief.Symbol) " with the given name exists"_doc,
"symbol_name"_a)
.def("get_symbol",
static_cast<no_const_func<Symbol*, const std::string&>>(&Binary::get_symbol),
nb::overload_cast<const std::string&>(&Binary::get_symbol),
R"delim(
Return the :class:`~lief.Symbol` from the given ``name``.
If the symbol can't be found, it returns None.
)delim",
)delim"_doc,
"symbol_name"_a,
py::return_value_policy::reference_internal)
nb::rv_policy::reference_internal)
.def("get_function_address",
[] (const Binary& self, const std::string& name) {
return error_or(&Binary::get_function_address, self, name);
},
"Return the address of the given function name",
"Return the address of the given function name"_doc,
"function_name"_a)
.def("patch_address",
static_cast<void (Binary::*) (uint64_t, const std::vector<uint8_t>&, Binary::VA_TYPES)>(&Binary::patch_address),
nb::overload_cast<uint64_t, const std::vector<uint8_t>&, Binary::VA_TYPES>(&Binary::patch_address),
R"delim(
Patch the address with the given list of bytes.
The virtual address is specified in the first argument and the content in the second (as a list of bytes).
If the underlying binary is a PE, one can specify if the virtual address is a :attr:`~lief.Binary.VA_TYPES.RVA` or
a :attr:`~lief.Binary.VA_TYPES.VA`. By default, it is set to :attr:`~lief.Binary.VA_TYPES.AUTO`.
)delim",
)delim"_doc,
"address"_a, "patch_value"_a, "va_type"_a = Binary::VA_TYPES::AUTO)
.def("patch_address",
static_cast<void (Binary::*) (uint64_t, uint64_t, size_t, Binary::VA_TYPES)>(&Binary::patch_address),
nb::overload_cast<uint64_t, uint64_t, size_t, Binary::VA_TYPES>(&Binary::patch_address),
R"delim(
Patch the address with the given integer value.
The virtual address is specified in the first argument, the integer in the second and the integer's size of in third one.
If the underlying binary is a PE, one can specify if the virtual address is a :attr:`~lief.Binary.VA_TYPES.RVA` or
a :attr:`~lief.Binary.VA_TYPES.VA`. By default, it is set to :attr:`~lief.Binary.VA_TYPES.AUTO`.
)delim",
)delim"_doc,
"address"_a, "patch_value"_a, "size"_a = 8, "va_type"_a = Binary::VA_TYPES::AUTO)
.def("get_content_from_virtual_address",
[] (const Binary& self, uint64_t va, size_t size, Binary::VA_TYPES type) {
span<const uint8_t> content = self.get_content_from_virtual_address(va, size, type);
return py::memoryview::from_memory(content.data(), content.size());
.def("get_content_from_virtual_address",
[] (const Binary& self, uint64_t va, size_t size, Binary::VA_TYPES type) {
const span<const uint8_t> content = self.get_content_from_virtual_address(va, size, type);
return nb::memoryview::from_memory(content.data(), content.size());
},
R"delim(
Return the content located at the provided virtual address.
@@ -177,70 +178,55 @@ void create<Binary>(py::module& m) {
If the underlying binary is a PE, one can specify if the virtual address is a :attr:`~lief.Binary.VA_TYPES.RVA` or
a :attr:`~lief.Binary.VA_TYPES.VA`. By default, it is set to :attr:`~lief.Binary.VA_TYPES.AUTO`.
)delim",
)delim"_doc,
"virtual_address"_a, "size"_a, "va_type"_a = Binary::VA_TYPES::AUTO)
.def_property_readonly("abstract",
[m] (py::object& self) {
self.attr("__class__") = m.attr("Binary");
return self;
.def_prop_ro("abstract",
[] (nb::object& self) -> nb::object {
auto* ab = nb::cast<LIEF::Binary*>(self);
const nb::handle base_type = nb::type<LIEF::Binary>();
nb::object py_inst = nb::inst_reference(base_type, ab, self);
nb::inst_set_state(py_inst, /*ready=*/true, /*destruct=*/false);
return py_inst;
},
R"delim(
Return the abstract representation of the current binary (:class:`lief.Binary`)
)delim"_doc,
nb::rv_policy::reference_internal)
.. warning::
Getting this property modifies the ``__class__`` attribute such as
the current binary looks like a :class:`lief.Binary`.
To get back to the original binary, one needs to access :attr:`lief.Binary.concrete`
)delim",
py::return_value_policy::reference)
.def_property_readonly("concrete",
[m] (py::object& self) {
self.attr("__class__") = py::cast(self.cast<Binary*>()).attr("__class__");
return self;
.def_prop_ro("concrete",
[] (nb::object& self) {
return nb::cast(nb::cast<LIEF::Binary*>(self));
},
R"delim(
The *concrete* representation of the binary. Basically, this property cast a :class:`lief.Binary`
into a :class:`lief.PE.Binary`, :class:`lief.ELF.Binary` or :class:`lief.MachO.Binary`.
See also: :attr:`lief.Binary.abstract`
)delim",
py::return_value_policy::reference)
)delim"_doc,
nb::rv_policy::reference)
.def_property_readonly("ctor_functions",
.def_prop_ro("ctor_functions",
&Binary::ctor_functions,
"Constructor functions that are called prior to any other functions")
"Constructor functions that are called prior to any other functions"_doc)
.def("xref",
&Binary::xref,
"Return all **virtual addresses** that *use* the ``address`` given in parameter",
"Return all **virtual addresses** that *use* the ``address`` given in parameter"_doc,
"virtual_address"_a)
.def("offset_to_virtual_address",
[] (const Binary& self, uint64_t offset, uint64_t slide) {
return error_or(&Binary::offset_to_virtual_address, self, offset, slide);
},
"Convert an offset into a virtual address.",
"Convert an offset into a virtual address."_doc,
"offset"_a, "slide"_a = 0)
.def_property_readonly("imagebase",
.def_prop_ro("imagebase",
&Binary::imagebase,
"Default image base (i.e. if the ASLR is not enabled)")
"Default image base (i.e. if the ASLR is not enabled)"_doc)
.def("__str__",
[] (const Binary& binary)
{
std::ostringstream stream;
stream << binary;
std::string str = stream.str();
return str;
});
LIEF_DEFAULT_STR(LIEF::Binary);
}
}
@@ -13,31 +13,30 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "pyAbstract.hpp"
#include "LIEF/Abstract/Symbol.hpp"
#include <string>
#include <sstream>
#include <nanobind/stl/string.h>
#include <nanobind/stl/set.h>
#include <nanobind/stl/vector.h>
#include "Abstract/init.hpp"
#include "pyLIEF.hpp"
#include "LIEF/Abstract/Function.hpp"
#include "LIEF/Abstract/EnumToString.hpp"
#define PY_ENUM(x) LIEF::to_string(x), x
namespace LIEF {
template<class T>
using getter_t = T (Function::*)(void) const;
template<class T>
using setter_t = void (Function::*)(T);
namespace LIEF::py {
template<>
void create<Function>(py::module& m) {
py::class_<Function, Symbol> pyfunction(m, "Function",
void create<Function>(nb::module_& m) {
nb::class_<Function, Symbol> pyfunction(m, "Function",
R"delim(
Class which represents a Function in an executable file format.
)delim");
)delim"_doc);
py::enum_<Function::FLAGS>(pyfunction, "FLAGS")
nb::enum_<Function::FLAGS>(pyfunction, "FLAGS")
.value(PY_ENUM(Function::FLAGS::IMPORTED))
.value(PY_ENUM(Function::FLAGS::EXPORTED))
.value(PY_ENUM(Function::FLAGS::CONSTRUCTOR))
@@ -45,32 +44,26 @@ void create<Function>(py::module& m) {
.value(PY_ENUM(Function::FLAGS::DEBUG));
pyfunction
.def(py::init())
.def(py::init<const std::string&>())
.def(py::init<uint64_t>())
.def(py::init<const std::string&, uint64_t>())
.def(nb::init())
.def(nb::init<const std::string&>())
.def(nb::init<uint64_t>())
.def(nb::init<const std::string&, uint64_t>())
.def("add",
&Function::add,
"Add the given " RST_CLASS_REF(lief.Function.FLAGS) "",
"Add the given " RST_CLASS_REF(lief.Function.FLAGS) ""_doc,
"flag"_a)
.def_property_readonly("flags",
.def_prop_ro("flags",
&Function::flags,
"Function flags as a list of " RST_CLASS_REF(lief.Function.FLAGS) "")
"Function flags as a list of " RST_CLASS_REF(lief.Function.FLAGS) ""_doc)
.def_property("address",
static_cast<getter_t<uint64_t>>(&Function::address),
static_cast<setter_t<uint64_t>>(&Function::address),
"Function's address")
.def_prop_rw("address",
nb::overload_cast<>(&Function::address, nb::const_),
nb::overload_cast<uint64_t>(&Function::address),
"Function's address"_doc)
.def("__str__",
[] (const Function& f) {
std::ostringstream stream;
stream << f;
std::string str = stream.str();
return str;
});
}
LIEF_DEFAULT_STR(LIEF::Function);
}
}
+72
View File
@@ -0,0 +1,72 @@
/* Copyright 2017 - 2023 R. Thomas
* Copyright 2017 - 2023 Quarkslab
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <sstream>
#include <nanobind/stl/string.h>
#include <nanobind/stl/set.h>
#include "Abstract/init.hpp"
#include "pyLIEF.hpp"
#include "LIEF/Abstract/Header.hpp"
namespace LIEF::py {
template<>
void create<Header>(nb::module_& m) {
nb::class_<Header, Object>(m, "Header",
R"delim(
Class which represents an abstracted Header
)delim"_doc)
.def(nb::init())
.def_prop_rw("architecture",
nb::overload_cast<>(&Header::architecture, nb::const_),
nb::overload_cast<ARCHITECTURES>(&Header::architecture),
"Target architecture (" RST_CLASS_REF(lief.ARCHITECTURES) ")"_doc)
.def_prop_rw("modes",
nb::overload_cast<>(&Header::modes, nb::const_),
nb::overload_cast<const std::set<MODES>&>(&Header::modes),
"Target " RST_CLASS_REF(lief.MODES) " (32-bits, 64-bits...)"_doc)
.def_prop_rw("entrypoint",
nb::overload_cast<>(&Header::entrypoint, nb::const_),
nb::overload_cast<uint64_t>(&Header::entrypoint),
"Binary entrypoint"_doc)
.def_prop_rw("object_type",
nb::overload_cast<>(&Header::object_type, nb::const_),
nb::overload_cast<OBJECT_TYPES>(&Header::object_type),
"Type of the binary (executable, library...)\n"
"See: " RST_CLASS_REF(lief.OBJECT_TYPES) ""_doc)
.def_prop_rw("endianness",
nb::overload_cast<>(&Header::endianness, nb::const_),
nb::overload_cast<ENDIANNESS>(&Header::endianness),
"Binary endianness\n"
"See: " RST_CLASS_REF(lief.ENDIANNESS) ""_doc)
.def_prop_ro("is_32",
&Header::is_32,
"``True`` if the binary targets a ``32-bits`` architecture"_doc)
.def_prop_ro("is_64",
&Header::is_64,
"``True`` if the binary targets a ``64-bits`` architecture"_doc)
LIEF_DEFAULT_STR(LIEF::Header);
}
}
+89
View File
@@ -0,0 +1,89 @@
/* Copyright 2017 - 2023 R. Thomas
* Copyright 2017 - 2023 Quarkslab
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "Abstract/init.hpp"
#include "pyLIEF.hpp"
#include "pyIOStream.hpp"
#include <nanobind/stl/unique_ptr.h>
#include <nanobind/stl/string.h>
#include "LIEF/Abstract/Parser.hpp"
#include "LIEF/Abstract/Binary.hpp"
#include "LIEF/logging.hpp"
namespace LIEF::py {
template<>
void create<Parser>(nb::module_& m) {
m.def("parse",
[] (nb::bytes bytes) {
std::string raw_str(bytes.c_str(), bytes.size());
const std::vector<uint8_t> raw = {
std::make_move_iterator(std::begin(raw_str)),
std::make_move_iterator(std::end(raw_str))
};
std::unique_ptr<Binary> binary = Parser::parse(raw);
return binary;
},
R"delim(
Parse a binary supported by LIEF from the given bytes and return either:
- :class:`lief.ELF.Binary`
- :class:`lief.PE.Binary`
- :class:`lief.MachO.Binary`
depending on the given binary format.
)delim"_doc,
"raw"_a,
nb::rv_policy::take_ownership);
m.def("parse", nb::overload_cast<const std::string&>(&Parser::parse),
R"delim(
Parse a binary from the given file path and return either:
- :class:`lief.ELF.Binary`
- :class:`lief.PE.Binary`
- :class:`lief.MachO.Binary`
depending on the given binary format.
)delim"_doc,
"filepath"_a, nb::rv_policy::take_ownership);
m.def("parse",
[] (nb::object byteio) -> nb::object {
if (auto stream = PyIOStream::from_python(std::move(byteio))) {
auto ptr = std::make_unique<PyIOStream>(std::move(*stream));
return nb::cast(Parser::parse(std::move(ptr)));
}
logging::log(logging::LOG_ERR,
"Can't create a LIEF stream interface over the provided io");
return nb::none();
},
R"delim(
Parse a binary supported by LIEF from the given Python IO interface and return either:
- :class:`lief.ELF.Binary`
- :class:`lief.PE.Binary`
- :class:`lief.MachO.Binary`
depending on the given binary format.
)delim"_doc,
"io"_a,
nb::rv_policy::take_ownership);
}
}
+46
View File
@@ -0,0 +1,46 @@
/* Copyright 2017 - 2023 R. Thomas
* Copyright 2017 - 2023 Quarkslab
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <sstream>
#include <nanobind/stl/string.h>
#include "Abstract/init.hpp"
#include "pyLIEF.hpp"
#include "LIEF/Abstract/hash.hpp"
#include "LIEF/Abstract/Relocation.hpp"
namespace LIEF::py {
template<>
void create<Relocation>(nb::module_& m) {
nb::class_<Relocation, Object>(m, "Relocation",
R"delim(
Class which represents an abstracted Relocation
)delim")
.def_prop_rw("address",
nb::overload_cast<>(&Relocation::address, nb::const_),
nb::overload_cast<uint64_t>(&Relocation::address),
"Relocation's address"_doc)
.def_prop_rw("size",
nb::overload_cast<>(&Relocation::size, nb::const_),
nb::overload_cast<size_t>(&Relocation::size),
"Relocation's size (in **bits**)"_doc)
LIEF_DEFAULT_STR(LIEF::Relocation);
}
}
+132
View File
@@ -0,0 +1,132 @@
/* Copyright 2017 - 2023 R. Thomas
* Copyright 2017 - 2023 Quarkslab
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <sstream>
#include <nanobind/stl/string.h>
#include <nanobind/stl/vector.h>
#include "Abstract/init.hpp"
#include "pyLIEF.hpp"
#include "pySafeString.hpp"
#include "nanobind/extra/memoryview.hpp"
#include "LIEF/Abstract/Section.hpp"
namespace LIEF::py {
template<>
void create<Section>(nb::module_& m) {
nb::class_<Section, Object>(m, "Section",
R"delim(
Class which represents an abstracted section
)delim"_doc)
.def_prop_rw("name",
[] (const Section& obj) {
return safe_string(obj.name());
},
nb::overload_cast<const std::string&>(&Section::name),
"Section's name"_doc)
.def_prop_ro("fullname",
&Section::fullname,
"Return the **fullname** of the section including the trailing bytes"_doc)
.def_prop_rw("size",
nb::overload_cast<>(&Section::size, nb::const_),
nb::overload_cast<uint64_t>(&Section::size),
"Section's size"_doc)
.def_prop_rw("offset",
nb::overload_cast<>(&Section::offset, nb::const_),
nb::overload_cast<uint64_t>(&Section::offset),
"Section's file offset"_doc)
.def_prop_rw("virtual_address",
nb::overload_cast<>(&Section::virtual_address, nb::const_),
nb::overload_cast<uint64_t>(&Section::virtual_address),
"Section's virtual address"_doc)
.def_prop_rw("content",
[] (const Section& self) {
const span<const uint8_t> content = self.content();
return nb::memoryview::from_memory(content.data(), content.size());
},
nb::overload_cast<const std::vector<uint8_t>&>(&Section::content),
"Section's content"_doc)
.def_prop_ro("entropy",
&Section::entropy,
"Section's entropy"_doc)
.def("search",
[] (const Section& self,
uint64_t number, size_t pos, size_t size) -> nb::object
{
size_t res = self.search(number, pos, size);
if (res == Section::npos) {
return nb::none();
}
return nb::cast(res);
},
"Look for **integer** within the current section"_doc,
"number"_a, "pos"_a = 0, "size"_a = 0)
.def("search",
[] (const Section& self,
const std::string& str, size_t pos) ->nb::object
{
size_t res = self.search(str, pos);
if (res == Section::npos) {
return nb::none();
}
return nb::cast(res);
},
"Look for **string** within the current section"_doc,
"str"_a, "pos"_a = 0)
.def("search",
[] (const Section& self,
nb::bytes bytes, size_t pos) -> nb::object
{
std::string raw_str(bytes.c_str(), bytes.size());
const std::vector<uint8_t> raw = {
std::make_move_iterator(std::begin(raw_str)),
std::make_move_iterator(std::end(raw_str))
};
size_t res = self.search(raw, pos);
if (res == Section::npos) {
return nb::none();
}
return nb::cast(res);
},
"Look for the given bytes within the current section"_doc,
"bytes"_a, "pos"_a = 0)
.def("search_all",
nb::overload_cast<uint64_t, size_t>(&Section::search_all, nb::const_),
"Look for **all** integers within the current section"_doc,
"number"_a, "size"_a = 0)
.def("search_all",
nb::overload_cast<const std::string&>(&Section::search_all, nb::const_),
"Look for all **strings** within the current section"_doc,
"str"_a)
LIEF_DEFAULT_STR(LIEF::Section);
}
}
+53
View File
@@ -0,0 +1,53 @@
/* Copyright 2017 - 2023 R. Thomas
* Copyright 2017 - 2023 Quarkslab
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <sstream>
#include <nanobind/stl/string.h>
#include "Abstract/init.hpp"
#include "pyLIEF.hpp"
#include "pySafeString.hpp"
#include "LIEF/Abstract/Symbol.hpp"
namespace LIEF::py {
template<>
void create<Symbol>(nb::module_& m) {
nb::class_<Symbol, Object>(m, "Symbol",
R"delim(
This class represents a symbol in an executable format.
)delim"_doc)
.def_prop_rw("name",
[] (const Symbol& obj) {
return safe_string(obj.name());
},
nb::overload_cast<const std::string&>(&Symbol::name),
"Symbol's name"_doc)
.def_prop_rw("value",
nb::overload_cast<>(&Symbol::value, nb::const_),
nb::overload_cast<uint64_t>(&Symbol::value),
"Symbol's value"_doc)
.def_prop_rw("size",
nb::overload_cast<>(&Symbol::size, nb::const_),
nb::overload_cast<uint64_t>(&Symbol::size),
"Symbol's size"_doc)
LIEF_DEFAULT_STR(LIEF::Symbol);
}
}
+6 -20
View File
@@ -1,27 +1,13 @@
set(LIEF_PYTHON_DEX_SRC
"${CMAKE_CURRENT_LIST_DIR}/pyDEX.cpp"
"${CMAKE_CURRENT_LIST_DIR}/pyEnums.cpp"
"${CMAKE_CURRENT_LIST_DIR}/pyUtils.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pyHeader.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pyParser.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pyFile.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pyClass.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pyField.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pyMethod.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pyCodeInfo.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pyMapList.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pyMapItem.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pyType.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pyPrototype.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/init.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/pyEnums.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/pyUtils.cpp"
)
set(LIEF_PYTHON_DEX_HDR
"${CMAKE_CURRENT_LIST_DIR}/pyDEX.hpp")
"${CMAKE_CURRENT_SOURCE_DIR}/pyDEX.hpp")
source_group("Source Files\\DEX" FILES ${LIEF_PYTHON_DEX_SRC})
source_group("Header Files\\DEX" FILES ${LIEF_PYTHON_DEX_HDR})
target_sources(pyLIEF PRIVATE "${LIEF_PYTHON_DEX_SRC}" "${LIEF_PYTHON_DEX_HDR}")
target_include_directories(pyLIEF PUBLIC "${CMAKE_CURRENT_LIST_DIR}" "${CMAKE_CURRENT_LIST_DIR}/../")
target_sources(pyLIEF PRIVATE ${LIEF_PYTHON_DEX_SRC} ${LIEF_PYTHON_DEX_HDR})
add_subdirectory(objects)
@@ -13,21 +13,25 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "pyDEX.hpp"
#include "DEX/pyDEX.hpp"
#include "DEX/init.hpp"
#include "LIEF/DEX/Parser.hpp"
#include "LIEF/DEX/File.hpp"
#include "LIEF/DEX/Header.hpp"
#include "LIEF/DEX/Class.hpp"
#include "LIEF/DEX/Method.hpp"
#include "LIEF/DEX/Field.hpp"
#include "LIEF/DEX/Prototype.hpp"
#include "LIEF/DEX/Type.hpp"
#include "LIEF/DEX/MapList.hpp"
#include "LIEF/DEX/MapItem.hpp"
#include "LIEF/DEX/CodeInfo.hpp"
namespace LIEF {
namespace DEX {
void init_python_module(py::module& m) {
py::module LIEF_DEX_module = m.def_submodule("DEX", "Python API for DEX format");
#define CREATE(X,Y) create<X>(Y)
init_enums(LIEF_DEX_module);
init_objects(LIEF_DEX_module);
init_utils(LIEF_DEX_module);
}
void init_objects(py::module& m) {
namespace LIEF::DEX::py {
void init_objects(nb::module_& m) {
CREATE(Parser, m);
CREATE(File, m);
CREATE(Header, m);
@@ -41,5 +45,12 @@ void init_objects(py::module& m) {
CREATE(CodeInfo, m);
}
void init(nb::module_& m) {
nb::module_ mod = m.def_submodule("DEX", "Python API for DEX format");
init_enums(mod);
init_objects(mod);
init_utils(mod);
}
}
+25
View File
@@ -0,0 +1,25 @@
/* Copyright 2017 - 2023 R. Thomas
* Copyright 2017 - 2023 Quarkslab
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef PY_LIEF_DEX_INIT_H
#define PY_LIEF_DEX_INIT_H
#include "pyLIEF.hpp"
namespace LIEF::DEX::py {
void init(nb::module_& m);
void init_enums(nb::module_& m);
void init_utils(nb::module_& m);
}
#endif
+17
View File
@@ -0,0 +1,17 @@
set(LIEF_PYTHON_DEX_OBJ_SRC
"${CMAKE_CURRENT_SOURCE_DIR}/pyHeader.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/pyParser.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/pyFile.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/pyClass.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/pyField.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/pyMethod.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/pyCodeInfo.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/pyMapList.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/pyMapItem.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/pyType.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/pyPrototype.cpp"
)
target_sources(pyLIEF PRIVATE ${LIEF_PYTHON_DEX_OBJ_SRC})
+46 -79
View File
@@ -13,31 +13,27 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "LIEF/DEX/Class.hpp"
#include "LIEF/DEX/hash.hpp"
#include "pyIterators.hpp"
#include "pyDEX.hpp"
#include "DEX/pyDEX.hpp"
#include "LIEF/DEX/Class.hpp"
#include "LIEF/DEX/Field.hpp"
#include "LIEF/DEX/Method.hpp"
#include "pyIterator.hpp"
#include <sstream>
#include <nanobind/stl/string.h>
#include <nanobind/stl/vector.h>
#include <nanobind/stl/unordered_map.h>
namespace LIEF {
namespace DEX {
template<class T>
using getter_t = T (Class::*)(void) const;
template<class T>
using no_const_getter_t = T (Class::*)(void);
template<class T>
using setter_t = void (Class::*)(T);
namespace LIEF::DEX::py {
template<>
void create<Class>(py::module& m) {
void create<Class>(nb::module_& m) {
using namespace LIEF::py;
py::class_<Class, LIEF::Object> cls(m, "Class", "DEX Class representation");
nb::class_<Class, LIEF::Object> cls(m, "Class", "DEX Class representation"_doc);
init_ref_iterator<Class::it_methods>(cls, "it_methods");
init_ref_iterator<Class::it_fields>(cls, "it_fields");
@@ -46,84 +42,55 @@ void create<Class>(py::module& m) {
init_ref_iterator<Class::it_named_fields>(cls, "it_named_fields");
cls
.def_property_readonly("fullname",
&Class::fullname,
"Mangled class name (e.g. ``Lcom/example/android/MyActivity;``)")
.def_prop_ro("fullname", &Class::fullname,
"Mangled class name (e.g. ``Lcom/example/android/MyActivity;``)"_doc)
.def_property_readonly("pretty_name",
&Class::pretty_name,
"Demangled class name (e.g. ``com.example.android.MyActivity``)")
.def_prop_ro("pretty_name", &Class::pretty_name,
"Demangled class name (e.g. ``com.example.android.MyActivity``)"_doc)
.def_property_readonly("name",
&Class::name,
"Class name (e.g. ``MyActivity``)")
.def_prop_ro("name", &Class::name,
"Class name (e.g. ``MyActivity``)"_doc)
.def_property_readonly("source_filename",
&Class::source_filename,
"Original filename")
.def_prop_ro("source_filename", &Class::source_filename,
"Original filename"_doc)
.def_property_readonly("package_name",
&Class::package_name,
"Package Name (e.g. ``com.example.android``)")
.def_prop_ro("package_name", &Class::package_name,
"Package Name (e.g. ``com.example.android``)"_doc)
.def_property_readonly("has_parent",
&Class::has_parent,
"True if the current class extends another one")
.def_prop_ro("has_parent", &Class::has_parent,
"True if the current class extends another one"_doc)
.def_property_readonly("parent",
static_cast<no_const_getter_t<Class*>>(&Class::parent),
"" RST_CLASS_REF(lief.DEX.Class) " parent class")
.def_prop_ro("parent", nb::overload_cast<>(&Class::parent),
"" RST_CLASS_REF(lief.DEX.Class) " parent class"_doc)
.def_property_readonly("methods",
static_cast<no_const_getter_t<Class::it_methods>>(&Class::methods),
"Iterator over " RST_CLASS_REF(lief.DEX.Method) " implemented in this class")
.def_prop_ro("methods", nb::overload_cast<>(&Class::methods),
"Iterator over " RST_CLASS_REF(lief.DEX.Method) " implemented in this class"_doc)
.def("get_method",
static_cast<Class::it_named_methods(Class::*)(const std::string&)>(&Class::methods),
"Iterator over " RST_CLASS_REF(lief.DEX.Method) " (s) having the given name",
.def("get_method", nb::overload_cast<const std::string&>(&Class::methods),
"Iterator over " RST_CLASS_REF(lief.DEX.Method) " (s) having the given name"_doc,
"name"_a)
.def_property_readonly("fields",
static_cast<no_const_getter_t<Class::it_fields>>(&Class::fields),
"Iterator over " RST_CLASS_REF(lief.DEX.Field) " in this class")
.def_prop_ro("fields", nb::overload_cast<>(&Class::fields),
"Iterator over " RST_CLASS_REF(lief.DEX.Field) " in this class"_doc)
.def("get_field",
static_cast<Class::it_named_fields(Class::*)(const std::string&)>(&Class::fields),
"Iterator over " RST_CLASS_REF(lief.DEX.Field) " (s) having the given name",
.def("get_field", nb::overload_cast<const std::string&>(&Class::fields),
"Iterator over " RST_CLASS_REF(lief.DEX.Field) " (s) having the given name"_doc,
"name"_a)
.def_property_readonly("access_flags",
static_cast<getter_t<Class::access_flags_list_t>>(&Class::access_flags),
"List of " RST_CLASS_REF(lief.DEX.ACCESS_FLAGS) "")
.def_prop_ro("access_flags",
nb::overload_cast<>(&Class::access_flags, nb::const_),
"List of " RST_CLASS_REF(lief.DEX.ACCESS_FLAGS) ""_doc)
.def_property_readonly("dex2dex_info",
&Class::dex2dex_info,
"De-optimize information")
.def_prop_ro("dex2dex_info", &Class::dex2dex_info,
"De-optimize information"_doc)
.def_property_readonly("index",
&Class::index,
"Original index in the DEX class pool")
.def_prop_ro("index", &Class::index,
"Original index in the DEX class pool"_doc)
.def("has",
static_cast<bool(Class::*)(ACCESS_FLAGS) const>(&Class::has),
"Check if the given " RST_CLASS_REF(lief.DEX.ACCESS_FLAGS) " is present",
.def("has", nb::overload_cast<ACCESS_FLAGS>(&Class::has, nb::const_),
"Check if the given " RST_CLASS_REF(lief.DEX.ACCESS_FLAGS) " is present"_doc,
"flag"_a)
.def("__eq__", &Class::operator==)
.def("__ne__", &Class::operator!=)
.def("__hash__",
[] (const Class& cls) {
return Hash::hash(cls);
})
.def("__str__",
[] (const Class& cls) {
std::ostringstream stream;
stream << cls;
return stream.str();
});
}
LIEF_DEFAULT_STR(Class);
}
}
+6 -31
View File
@@ -14,44 +14,19 @@
* limitations under the License.
*/
#include "LIEF/DEX/CodeInfo.hpp"
#include "LIEF/DEX/hash.hpp"
#include "pyDEX.hpp"
#include "DEX/pyDEX.hpp"
#include <string>
#include <sstream>
namespace LIEF {
namespace DEX {
template<class T>
using getter_t = T (CodeInfo::*)(void) const;
template<class T>
using no_const_getter_t = T (CodeInfo::*)(void);
template<class T>
using setter_t = void (CodeInfo::*)(T);
namespace LIEF::DEX::py {
template<>
void create<CodeInfo>(py::module& m) {
void create<CodeInfo>(nb::module_& m) {
py::class_<CodeInfo, LIEF::Object>(m, "CodeInfo", "DEX CodeInfo representation")
.def("__eq__", &CodeInfo::operator==)
.def("__ne__", &CodeInfo::operator!=)
.def("__hash__",
[] (const CodeInfo& cinfo) {
return Hash::hash(cinfo);
})
.def("__str__",
[] (const CodeInfo& cinfo) {
std::ostringstream stream;
stream << cinfo;
return stream.str();
});
}
nb::class_<CodeInfo, LIEF::Object>(m, "CodeInfo", "DEX CodeInfo representation"_doc)
LIEF_DEFAULT_STR(CodeInfo);
}
}
+27 -53
View File
@@ -1,74 +1,48 @@
#include "LIEF/DEX/Field.hpp"
#include "LIEF/DEX/hash.hpp"
#include "LIEF/DEX/Class.hpp"
#include "LIEF/DEX/Type.hpp"
#include "pyDEX.hpp"
#include "DEX/pyDEX.hpp"
#include <sstream>
#include <nanobind/stl/string.h>
#include <nanobind/stl/vector.h>
namespace LIEF {
namespace DEX {
template<class T>
using getter_t = T (Field::*)(void) const;
template<class T>
using no_const_getter_t = T (Field::*)(void);
template<class T>
using setter_t = void (Field::*)(T);
namespace LIEF::DEX::py {
template<>
void create<Field>(py::module& m) {
void create<Field>(nb::module_& m) {
py::class_<Field, LIEF::Object>(m, "Field", "DEX Field representation")
.def_property_readonly("name",
nb::class_<Field, LIEF::Object>(m, "Field", "DEX Field representation"_doc)
.def_prop_ro("name",
&Field::name,
"Field's name")
"Field's name"_doc)
.def_property_readonly("index",
&Field::index,
"Original DEX file index of the field")
.def_prop_ro("index", &Field::index,
"Original DEX file index of the field"_doc)
.def_property_readonly("has_class",
&Field::has_class,
"True if a class is associated with this field")
.def_prop_ro("has_class", &Field::has_class,
"True if a class is associated with this field"_doc)
.def_property_readonly("cls",
static_cast<no_const_getter_t<Class*>>(&Field::cls),
"" RST_CLASS_REF(lief.DEX.Class) " associated with this field")
.def_prop_ro("cls", nb::overload_cast<>(&Field::cls),
"" RST_CLASS_REF(lief.DEX.Class) " associated with this field"_doc)
.def_property_readonly("is_static",
&Field::is_static,
"True if the field is static")
.def_prop_ro("is_static", &Field::is_static,
"True if the field is static"_doc)
.def_property_readonly("type",
static_cast<no_const_getter_t<Type*>>(&Field::type),
"" RST_CLASS_REF(lief.DEX.Type) " of this field", py::return_value_policy::reference)
.def_prop_ro("type", nb::overload_cast<>(&Field::type),
"" RST_CLASS_REF(lief.DEX.Type) " of this field"_doc,
nb::rv_policy::reference_internal)
.def_property_readonly("access_flags",
static_cast<getter_t<Field::access_flags_list_t>>(&Field::access_flags),
"List of " RST_CLASS_REF(lief.DEX.ACCESS_FLAGS) "")
.def_prop_ro("access_flags",
nb::overload_cast<>(&Field::access_flags, nb::const_),
"List of " RST_CLASS_REF(lief.DEX.ACCESS_FLAGS) ""_doc)
.def("has",
static_cast<bool(Field::*)(ACCESS_FLAGS) const>(&Field::has),
"Check if the given " RST_CLASS_REF(lief.DEX.ACCESS_FLAGS) " is present",
nb::overload_cast<ACCESS_FLAGS>(&Field::has, nb::const_),
"Check if the given " RST_CLASS_REF(lief.DEX.ACCESS_FLAGS) " is present"_doc,
"flag"_a)
.def("__eq__", &Field::operator==)
.def("__ne__", &Field::operator!=)
.def("__hash__",
[] (const Field& fld) {
return Hash::hash(fld);
})
.def("__str__",
[] (const Field& fld) {
std::ostringstream stream;
stream << fld;
return stream.str();
});
}
LIEF_DEFAULT_STR(Field);
}
}
+61 -83
View File
@@ -14,30 +14,28 @@
* limitations under the License.
*/
#include "LIEF/DEX/File.hpp"
#include "LIEF/DEX/hash.hpp"
#include "LIEF/DEX/Class.hpp"
#include "LIEF/DEX/Method.hpp"
#include "LIEF/DEX/Type.hpp"
#include "LIEF/DEX/Prototype.hpp"
#include "LIEF/DEX/Field.hpp"
#include "pyIterators.hpp"
#include "pyDEX.hpp"
#include "pyIterator.hpp"
#include "DEX/pyDEX.hpp"
#include <sstream>
namespace LIEF {
namespace DEX {
template<class T>
using getter_t = T (File::*)(void) const;
template<class T>
using no_const_getter_t = T (File::*)(void);
template<class T>
using setter_t = void (File::*)(T);
#include <nanobind/stl/string.h>
#include <nanobind/stl/vector.h>
#include <nanobind/stl/unique_ptr.h>
namespace LIEF::DEX::py {
template<>
void create<File>(py::module& m) {
void create<File>(nb::module_& m) {
using namespace LIEF::py;
py::class_<File, LIEF::Object> file(m, "File", "DEX File representation");
nb::class_<File, Object> file(m, "File", "DEX File representation"_doc);
init_ref_iterator<File::it_classes>(file, "it_classes");
init_ref_iterator<File::it_methods>(file, "it_methods");
@@ -47,98 +45,78 @@ void create<File>(py::module& m) {
init_ref_iterator<File::it_fields>(file, "it_fields");
file
.def_property_readonly("version",
&File::version,
"Dex version")
.def_prop_ro("version", &File::version,
"Dex version"_doc)
.def_property_readonly("header",
static_cast<no_const_getter_t<Header&>>(&File::header),
"Dex File " RST_CLASS_REF(lief.DEX.Header) "",
py::return_value_policy::reference)
.def_prop_ro("header", nb::overload_cast<>(&File::header, nb::const_),
"Dex File " RST_CLASS_REF(lief.DEX.Header) ""_doc,
nb::rv_policy::reference_internal)
.def_property_readonly("classes",
static_cast<no_const_getter_t<File::it_classes>>(&File::classes),
"Iterator over Dex " RST_CLASS_REF(lief.DEX.Class) "")
.def_prop_ro("classes", nb::overload_cast<>(&File::classes),
"Iterator over Dex " RST_CLASS_REF(lief.DEX.Class) ""_doc,
nb::keep_alive<0, 1>())
.def("has_class",
&File::has_class,
"Check if a class with a name given in parameter exists",
.def("has_class", &File::has_class,
"Check if a class with a name given in parameter exists"_doc,
"classname"_a)
.def("get_class",
static_cast<Class*(File::*)(const std::string&)>(&File::get_class),
"classname"_a,
py::return_value_policy::reference)
nb::overload_cast<const std::string&>(&File::get_class),
"classname"_a, nb::rv_policy::reference_internal)
.def("get_class",
static_cast<Class*(File::*)(size_t)>(&File::get_class),
"classname"_a,
py::return_value_policy::reference)
nb::overload_cast<size_t>(&File::get_class),
"classname"_a, nb::rv_policy::reference_internal)
.def_property_readonly("methods",
static_cast<no_const_getter_t<File::it_methods>>(&File::methods),
"Iterator over Dex " RST_CLASS_REF(lief.DEX.Method) "")
.def_prop_ro("methods", nb::overload_cast<>(&File::methods),
"Iterator over Dex " RST_CLASS_REF(lief.DEX.Method) ""_doc,
nb::keep_alive<0, 1>())
.def_property_readonly("fields",
static_cast<no_const_getter_t<File::it_fields>>(&File::fields),
"Iterator over Dex " RST_CLASS_REF(lief.DEX.Field) "")
.def_prop_ro("fields", nb::overload_cast<>(&File::fields),
"Iterator over Dex " RST_CLASS_REF(lief.DEX.Field) ""_doc,
nb::keep_alive<0, 1>())
.def_property_readonly("strings",
static_cast<no_const_getter_t<File::it_strings>>(&File::strings),
"Iterator over Dex strings")
.def_prop_ro("strings", nb::overload_cast<>(&File::strings),
"Iterator over Dex strings"_doc,
nb::keep_alive<0, 1>())
.def_property_readonly("types",
static_cast<no_const_getter_t<File::it_types>>(&File::types),
"Iterator over Dex " RST_CLASS_REF(lief.DEX.Type) "")
.def_prop_ro("types", nb::overload_cast<>(&File::types),
"Iterator over Dex " RST_CLASS_REF(lief.DEX.Type) ""_doc,
nb::keep_alive<0, 1>())
.def_property_readonly("prototypes",
static_cast<no_const_getter_t<File::it_prototypes>>(&File::prototypes),
"Iterator over Dex " RST_CLASS_REF(lief.DEX.Prototype) "")
.def_prop_ro("prototypes",
nb::overload_cast<>(&File::prototypes),
"Iterator over Dex " RST_CLASS_REF(lief.DEX.Prototype) ""_doc,
nb::keep_alive<0, 1>())
.def_property_readonly("map",
static_cast<no_const_getter_t<MapList&>>(&File::map),
"Dex " RST_CLASS_REF(lief.DEX.MapList) "")
.def_prop_ro("map", nb::overload_cast<>(&File::map, nb::const_),
"Dex " RST_CLASS_REF(lief.DEX.MapList) ""_doc)
.def("raw",
&File::raw,
"Original raw file",
.def("raw", &File::raw,
"Original raw file"_doc,
"deoptimize"_a = true)
.def_property("name",
static_cast<getter_t<const std::string&>>(&File::name),
static_cast<setter_t<const std::string&>>(&File::name),
"Name of the dex file")
.def_prop_rw("name",
nb::overload_cast<>(&File::name, nb::const_),
nb::overload_cast<const std::string&>(&File::name),
"Name of the dex file"_doc)
.def_property("location",
static_cast<getter_t<const std::string&>>(&File::location),
static_cast<setter_t<const std::string&>>(&File::location),
"Original location of the dex file")
.def_prop_rw("location",
nb::overload_cast<>(&File::location, nb::const_),
nb::overload_cast<const std::string&>(&File::location),
"Original location of the dex file"_doc)
//.def_property_readonly("dex2dex_info",
//.def_prop_ro("dex2dex_info",
// &File::dex2dex_info)
.def_property_readonly("dex2dex_json_info",
.def_prop_ro("dex2dex_json_info",
&File::dex2dex_json_info)
.def("save",
&File::save,
"Save the **original** file into the file given in first parameter",
.def("save", &File::save,
"Save the **original** file into the file given in first parameter"_doc,
"output"_a = "", "deoptimize"_a = true)
.def("__eq__", &File::operator==)
.def("__ne__", &File::operator!=)
.def("__hash__",
[] (const File& file) {
return Hash::hash(file);
})
.def("__str__",
[] (const File& file) {
std::ostringstream stream;
stream << file;
return stream.str();
});
LIEF_DEFAULT_STR(File);
}
}
}
+58 -78
View File
@@ -14,110 +14,90 @@
* limitations under the License.
*/
#include "LIEF/DEX/Header.hpp"
#include "LIEF/DEX/hash.hpp"
#include "pyDEX.hpp"
#include "DEX/pyDEX.hpp"
#include <sstream>
#include <nanobind/stl/string.h>
#include <nanobind/stl/array.h>
#include <nanobind/stl/vector.h>
#include <nanobind/stl/pair.h>
namespace LIEF {
namespace DEX {
template<class T>
using getter_t = T (Header::*)(void) const;
template<class T>
using setter_t = void (Header::*)(T);
namespace LIEF::DEX::py {
template<>
void create<Header>(py::module& m) {
void create<Header>(nb::module_& m) {
py::class_<Header, LIEF::Object>(m, "Header", "DEX Header")
nb::class_<Header, Object>(m, "Header", "DEX Header"_doc)
.def_property_readonly("magic",
static_cast<getter_t<Header::magic_t>>(&Header::magic),
.def_prop_ro("magic",
nb::overload_cast<>(&Header::magic, nb::const_),
"Magic value")
.def_property_readonly("checksum",
static_cast<getter_t<uint32_t>>(&Header::checksum),
"Checksum value of the rest of the file (without " RST_ATTR_REF(lief.DEX.Header.magic) ")")
.def_prop_ro("checksum",
nb::overload_cast<>(&Header::checksum, nb::const_),
"Checksum value of the rest of the file (without " RST_ATTR_REF(lief.DEX.Header.magic) ")"_doc)
.def_property_readonly("signature",
static_cast<getter_t<Header::signature_t>>(&Header::signature),
"SHA-1 signature of the rest of the file (without " RST_ATTR_REF(lief.DEX.Header.magic) " and " RST_ATTR_REF(lief.DEX.Header.checksum) ")")
.def_prop_ro("signature",
nb::overload_cast<>(&Header::signature, nb::const_),
R"delim(
SHA-1 signature of the rest of the file
(without :attr:`~lief.DEX.Header.magic` and :attr:`~lief.DEX.Header.checksum`).
)delim"_doc)
.def_property_readonly("file_size",
static_cast<getter_t<uint32_t>>(&Header::file_size),
"Size of the current DEX file")
.def_prop_ro("file_size",
nb::overload_cast<>(&Header::file_size, nb::const_),
"Size of the current DEX file"_doc)
.def_property_readonly("header_size",
static_cast<getter_t<uint32_t>>(&Header::header_size),
"Size of this header. Should be ``0x70``")
.def_prop_ro("header_size",
nb::overload_cast<>(&Header::header_size, nb::const_),
"Size of this header. Should be ``0x70``"_doc)
.def_property_readonly("endian_tag",
static_cast<getter_t<uint32_t>>(&Header::endian_tag),
"Endianness tag. Should be ``ENDIAN_CONSTANT``")
.def_prop_ro("endian_tag",
nb::overload_cast<>(&Header::endian_tag, nb::const_),
"Endianness tag. Should be ``ENDIAN_CONSTANT``"_doc)
.def_property_readonly("map_offset",
static_cast<getter_t<uint32_t>>(&Header::map),
"Offset from the start of the file to the map item")
.def_prop_ro("map_offset",
nb::overload_cast<>(&Header::map, nb::const_),
"Offset from the start of the file to the map item"_doc)
.def_property_readonly("strings",
static_cast<getter_t<Header::location_t>>(&Header::strings),
"String identifiers")
.def_prop_ro("strings",
nb::overload_cast<>(&Header::strings, nb::const_),
"String identifiers"_doc)
.def_property_readonly("link",
static_cast<getter_t<Header::location_t>>(&Header::link),
"Link (raw data)")
.def_prop_ro("link",
nb::overload_cast<>(&Header::link, nb::const_),
"Link (raw data)"_doc)
.def_property_readonly("types",
static_cast<getter_t<Header::location_t>>(&Header::types),
"Type identifiers")
.def_prop_ro("types",
nb::overload_cast<>(&Header::types, nb::const_),
"Type identifiers"_doc)
.def_property_readonly("prototypes",
static_cast<getter_t<Header::location_t>>(&Header::prototypes),
"Prototypes identifiers")
.def_prop_ro("prototypes",
nb::overload_cast<>(&Header::prototypes, nb::const_),
"Prototypes identifiers"_doc)
.def_property_readonly("fields",
static_cast<getter_t<Header::location_t>>(&Header::fields),
"Fields identifiers")
.def_prop_ro("fields", nb::overload_cast<>(&Header::fields, nb::const_),
"Fields identifiers"_doc)
.def_property_readonly("methods",
static_cast<getter_t<Header::location_t>>(&Header::methods),
"Methods identifiers")
.def_prop_ro("methods", nb::overload_cast<>(&Header::methods, nb::const_),
"Methods identifiers"_doc)
.def_property_readonly("classes",
static_cast<getter_t<Header::location_t>>(&Header::classes),
"Classess identifiers")
.def_prop_ro("classes", nb::overload_cast<>(&Header::classes, nb::const_),
"Classess identifiers"_doc)
.def_property_readonly("data",
static_cast<getter_t<Header::location_t>>(&Header::data),
"Raw data. Should be align on 32-bits")
.def_prop_ro("data", nb::overload_cast<>(&Header::data, nb::const_),
"Raw data. Should be align on 32-bits"_doc)
.def_property_readonly("nb_classes",
static_cast<getter_t<uint32_t>>(&Header::nb_classes),
"Number of classes in the current DEX")
.def_prop_ro("nb_classes",
nb::overload_cast<>(&Header::nb_classes, nb::const_),
"Number of classes in the current DEX"_doc)
.def_property_readonly("nb_methods",
static_cast<getter_t<uint32_t>>(&Header::nb_methods),
"Number of methods in the current DEX")
.def("__eq__", &Header::operator==)
.def("__ne__", &Header::operator!=)
.def("__hash__",
[] (const Header& header) {
return Hash::hash(header);
})
.def("__str__",
[] (const Header& header) {
std::ostringstream stream;
stream << header;
return stream.str();
});
}
.def_prop_ro("nb_methods",
nb::overload_cast<>(&Header::nb_methods, nb::const_),
"Number of methods in the current DEX"_doc)
LIEF_DEFAULT_STR(Header);
}
}
+17 -40
View File
@@ -14,34 +14,24 @@
* limitations under the License.
*/
#include "LIEF/DEX/MapItem.hpp"
#include "LIEF/DEX/hash.hpp"
#include "LIEF/DEX/EnumToString.hpp"
#include "pyDEX.hpp"
#include "DEX/pyDEX.hpp"
#include "enums_wrapper.hpp"
#include <sstream>
namespace LIEF {
namespace DEX {
#define PY_ENUM(x) to_string(x), x
template<class T>
using getter_t = T (MapItem::*)(void) const;
template<class T>
using no_const_getter_t = T (MapItem::*)(void);
template<class T>
using setter_t = void (MapItem::*)(T);
namespace LIEF::DEX::py {
template<>
void create<MapItem>(py::module& m) {
void create<MapItem>(nb::module_& m) {
py::class_<MapItem, LIEF::Object> mapitem(m, "MapItem", "DEX MapItem representation");
nb::class_<MapItem, LIEF::Object> mapitem(m, "MapItem",
"DEX MapItem representation"_doc);
py::enum_<MapItem::TYPES>(mapitem, "TYPES")
enum_<MapItem::TYPES>(mapitem, "TYPES")
.value(PY_ENUM(LIEF::DEX::MapItem::TYPES::HEADER))
.value(PY_ENUM(LIEF::DEX::MapItem::TYPES::STRING_ID))
.value(PY_ENUM(LIEF::DEX::MapItem::TYPES::TYPE_ID))
@@ -64,32 +54,19 @@ void create<MapItem>(py::module& m) {
.value(PY_ENUM(LIEF::DEX::MapItem::TYPES::ANNOTATIONS_DIRECTORY));
mapitem
.def_property_readonly("type",
static_cast<getter_t<MapItem::TYPES>>(&MapItem::type),
"" RST_CLASS_REF(lief.DEX.MapItem.TYPES) " of the item")
.def_prop_ro("type",
nb::overload_cast<>(&MapItem::type, nb::const_),
"" RST_CLASS_REF(lief.DEX.MapItem.TYPES) " of the item"_doc)
.def_property_readonly("offset",
static_cast<getter_t<uint32_t>>(&MapItem::offset),
"Offset from the start of the file to the items in question")
.def_prop_ro("offset",
nb::overload_cast<>(&MapItem::offset, nb::const_),
"Offset from the start of the file to the items in question"_doc)
.def_property_readonly("size",
static_cast<getter_t<uint32_t>>(&MapItem::size),
"count of the number of items to be found at the indicated offset")
.def_prop_ro("size",
nb::overload_cast<>(&MapItem::size, nb::const_),
"count of the number of items to be found at the indicated offset"_doc)
.def("__eq__", &MapItem::operator==)
.def("__ne__", &MapItem::operator!=)
.def("__hash__",
[] (const MapItem& mlist) {
return Hash::hash(mlist);
})
.def("__str__",
[] (const MapItem& mlist) {
std::ostringstream stream;
stream << mlist;
return stream.str();
});
LIEF_DEFAULT_STR(MapItem);
}
}
}
+21 -43
View File
@@ -14,65 +14,43 @@
* limitations under the License.
*/
#include "LIEF/DEX/MapList.hpp"
#include "LIEF/DEX/hash.hpp"
#include "pyDEX.hpp"
#include "pyIterators.hpp"
#include "DEX/pyDEX.hpp"
#include "pyIterator.hpp"
namespace LIEF {
namespace DEX {
template<class T>
using getter_t = T (MapList::*)(void) const;
template<class T>
using no_const_getter_t = T (MapList::*)(void);
template<class T>
using setter_t = void (MapList::*)(T);
#include <sstream>
#include <nanobind/stl/string.h>
#include <nanobind/stl/vector.h>
namespace LIEF::DEX::py {
template<>
void create<MapList>(py::module& m) {
void create<MapList>(nb::module_& m) {
using namespace LIEF::py;
py::class_<MapList, LIEF::Object> map_list(m, "MapList", "DEX MapList representation");
nb::class_<MapList, LIEF::Object> map_list(m, "MapList",
"DEX MapList representation"_doc);
init_ref_iterator<MapList::it_items_t>(map_list, "it_items_t");
map_list
.def_property_readonly("items",
static_cast<no_const_getter_t<MapList::it_items_t>>(&MapList::items),
"Iterator over " RST_CLASS_REF(lief.DEX.MapItem) "")
.def_prop_ro("items", nb::overload_cast<>(&MapList::items),
"Iterator over " RST_CLASS_REF(lief.DEX.MapItem) ""_doc)
.def("has",
&MapList::has,
"Check if the given " RST_CLASS_REF(lief.DEX.MapItem.TYPES) " is present",
.def("has", &MapList::has,
"Check if the given " RST_CLASS_REF(lief.DEX.MapItem.TYPES) " is present"_doc,
"type"_a)
.def("get",
static_cast<MapItem&(MapList::*)(MapItem::TYPES)>(&MapList::get),
"Return the " RST_CLASS_REF(lief.DEX.MapItem.TYPES) " from "
"the given " RST_CLASS_REF(lief.DEX.MapItem.TYPES) "",
"type"_a,
py::return_value_policy::reference)
.def("get", nb::overload_cast<MapItem::TYPES>(&MapList::get),
R"delim(
Return the :class:`~lief.DEX.MapItem` from the given
:class:`~lief.DEX.MapItem.TYPES`
)delim"_doc, "type"_a, nb::rv_policy::reference_internal)
.def("__getitem__",
static_cast<MapItem&(MapList::*)(MapItem::TYPES)>(&MapList::get))
nb::overload_cast<MapItem::TYPES>(&MapList::get))
.def("__eq__", &MapList::operator==)
.def("__ne__", &MapList::operator!=)
.def("__hash__",
[] (const MapList& mlist) {
return Hash::hash(mlist);
})
.def("__str__",
[] (const MapList& mlist) {
std::ostringstream stream;
stream << mlist;
return stream.str();
});
}
LIEF_DEFAULT_STR(MapList);
}
}
+33 -63
View File
@@ -14,89 +14,59 @@
* limitations under the License.
*/
#include "LIEF/DEX/Method.hpp"
#include "LIEF/DEX/hash.hpp"
#include "LIEF/DEX/Prototype.hpp"
#include "LIEF/DEX/Class.hpp"
#include "pyDEX.hpp"
#include "DEX/pyDEX.hpp"
#include <sstream>
#include <nanobind/stl/string.h>
#include <nanobind/stl/vector.h>
namespace LIEF {
namespace DEX {
template<class T>
using getter_t = T (Method::*)(void) const;
template<class T>
using no_const_getter_t = T (Method::*)(void);
template<class T>
using setter_t = void (Method::*)(T);
namespace LIEF::DEX::py {
template<>
void create<Method>(py::module& m) {
void create<Method>(nb::module_& m) {
py::class_<Method, LIEF::Object>(m, "Method", "DEX Method representation")
.def_property_readonly("name",
&Method::name,
"Method's name")
nb::class_<Method, LIEF::Object>(m, "Method", "DEX Method representation"_doc)
.def_prop_ro("name", &Method::name,
"Method's name"_doc)
.def_property_readonly("index",
&Method::index,
"Original DEX file index of the method")
.def_prop_ro("index", &Method::index,
"Original DEX file index of the method"_doc)
.def_property_readonly("has_class",
&Method::has_class,
"True if a class is associated with this method")
.def_prop_ro("has_class", &Method::has_class,
"True if a class is associated with this method"_doc)
.def_property_readonly("cls",
static_cast<no_const_getter_t<Class*>>(&Method::cls),
"" RST_CLASS_REF(lief.DEX.Class) " associated with this method")
.def_prop_ro("cls", nb::overload_cast<>(&Method::cls, nb::const_),
"" RST_CLASS_REF(lief.DEX.Class) " associated with this method"_doc)
.def_property_readonly("code_offset",
static_cast<getter_t<uint64_t>>(&Method::code_offset),
"Offset to the Dalvik Bytecode")
.def_prop_ro("code_offset", nb::overload_cast<>(&Method::code_offset, nb::const_),
"Offset to the Dalvik Bytecode"_doc)
.def_property_readonly("bytecode",
static_cast<getter_t<const Method::bytecode_t&>>(&Method::bytecode),
"Dalvik Bytecode as a list of bytes")
.def_prop_ro("bytecode", nb::overload_cast<>(&Method::bytecode, nb::const_),
"Dalvik Bytecode as a list of bytes"_doc)
.def_property_readonly("is_virtual",
&Method::is_virtual,
"True if the method is a virtual (not **private**, **static**, **final**, **constructor**)")
.def_prop_ro("is_virtual", &Method::is_virtual,
"True if the method is a virtual (not **private**, **static**, **final**, **constructor**)"_doc)
.def_property_readonly("prototype",
static_cast<no_const_getter_t<Prototype*>>(&Method::prototype),
"" RST_CLASS_REF(lief.DEX.Prototype) " of this method")
.def_prop_ro("prototype",
nb::overload_cast<>(&Method::prototype, nb::const_),
"" RST_CLASS_REF(lief.DEX.Prototype) " of this method"_doc)
.def_property_readonly("access_flags",
static_cast<getter_t<Method::access_flags_list_t>>(&Method::access_flags),
"List of " RST_CLASS_REF(lief.DEX.ACCESS_FLAGS) "")
.def_prop_ro("access_flags",
nb::overload_cast<>(&Method::access_flags, nb::const_),
"List of " RST_CLASS_REF(lief.DEX.ACCESS_FLAGS) ""_doc)
.def("has",
static_cast<bool(Method::*)(ACCESS_FLAGS) const>(&Method::has),
"Check if the given " RST_CLASS_REF(lief.DEX.ACCESS_FLAGS) " is present",
.def("has", nb::overload_cast<ACCESS_FLAGS>(&Method::has, nb::const_),
"Check if the given " RST_CLASS_REF(lief.DEX.ACCESS_FLAGS) " is present"_doc,
"flag"_a)
.def("insert_dex2dex_info",
&Method::insert_dex2dex_info,
"Insert de-optimization information",
.def("insert_dex2dex_info", &Method::insert_dex2dex_info,
"Insert de-optimization information"_doc,
"pc"_a, "index"_a)
.def("__eq__", &Method::operator==)
.def("__ne__", &Method::operator!=)
.def("__hash__",
[] (const Method& cls) {
return Hash::hash(cls);
})
.def("__str__",
[] (const Method& cls) {
std::ostringstream stream;
stream << cls;
return stream.str();
});
LIEF_DEFAULT_STR(Method);
}
}
}
+25 -45
View File
@@ -13,67 +13,47 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "pyDEX.hpp"
#include "DEX/pyDEX.hpp"
#include "LIEF/DEX/Parser.hpp"
#include "LIEF/DEX/File.hpp"
#include "LIEF/logging.hpp"
#include "pyIOStream.hpp"
#include <string>
#include <memory>
namespace LIEF {
namespace DEX {
#include <nanobind/stl/string.h>
#include <nanobind/stl/vector.h>
#include <nanobind/stl/unique_ptr.h>
namespace LIEF::DEX::py {
template<>
void create<Parser>(py::module& m) {
void create<Parser>(nb::module_& m) {
using namespace LIEF::py;
m.def("parse",
static_cast<std::unique_ptr<File> (*) (const std::string&)>(&Parser::parse),
"Parse the given filename and return a " RST_CLASS_REF(lief.DEX.File) " object",
"Parse the given filename and return a " RST_CLASS_REF(lief.DEX.File) " object"_doc,
"filename"_a,
py::return_value_policy::take_ownership);
nb::rv_policy::take_ownership);
m.def("parse",
static_cast<std::unique_ptr<File>(*)(std::vector<uint8_t>, const std::string&)>(&Parser::parse),
"Parse the given raw data and return a " RST_CLASS_REF(lief.DEX.File) " object",
"Parse the given raw data and return a " RST_CLASS_REF(lief.DEX.File) " object"_doc,
"raw"_a, "name"_a = "",
py::return_value_policy::take_ownership);
nb::rv_policy::take_ownership);
m.def("parse",
[] (py::object byteio, const std::string& name) {
const auto& io = py::module::import("io");
const auto& RawIOBase = io.attr("RawIOBase");
const auto& BufferedIOBase = io.attr("BufferedIOBase");
const auto& TextIOBase = io.attr("TextIOBase");
py::object rawio;
if (py::isinstance(byteio, RawIOBase)) {
rawio = byteio;
}
else if (py::isinstance(byteio, BufferedIOBase)) {
rawio = byteio.attr("raw");
}
else if (py::isinstance(byteio, TextIOBase)) {
rawio = byteio.attr("buffer").attr("raw");
}
else {
throw py::type_error(py::repr(byteio).cast<std::string>().c_str());
}
std::string raw_str = static_cast<py::bytes>(rawio.attr("readall")());
std::vector<uint8_t> raw = {
std::make_move_iterator(std::begin(raw_str)),
std::make_move_iterator(std::end(raw_str))};
return LIEF::DEX::Parser::parse(std::move(raw), name);
},
"io"_a, "name"_a = "",
py::return_value_policy::take_ownership);
}
[] (nb::object byteio, const std::string& name) -> nb::object {
if (auto stream = PyIOStream::from_python(std::move(byteio))) {
auto ptr = std::make_unique<PyIOStream>(std::move(*stream));
return nb::cast(LIEF::DEX::Parser::parse(stream->content(), name));
}
logging::log(logging::LOG_ERR, "Can't create a LIEF stream interface over the provided io");
return nb::none();
}, "io"_a, "name"_a = "", nb::rv_policy::take_ownership);
}
}
+20 -39
View File
@@ -14,56 +14,37 @@
* limitations under the License.
*/
#include "LIEF/DEX/Prototype.hpp"
#include "LIEF/DEX/hash.hpp"
#include "LIEF/DEX/Type.hpp"
#include "pyDEX.hpp"
#include "pyIterators.hpp"
#include "DEX/pyDEX.hpp"
#include "pyIterator.hpp"
namespace LIEF {
namespace DEX {
template<class T>
using getter_t = T (Prototype::*)(void) const;
template<class T>
using no_const_getter_t = T (Prototype::*)(void);
template<class T>
using setter_t = void (Prototype::*)(T);
#include <string>
#include <sstream>
#include <nanobind/stl/string.h>
#include <nanobind/stl/vector.h>
namespace LIEF::DEX::py {
template<>
void create<Prototype>(py::module& m) {
void create<Prototype>(nb::module_& m) {
using namespace LIEF::py;
py::class_<Prototype, LIEF::Object> proto(m, "Prototype", "DEX Prototype representation");
nb::class_<Prototype, LIEF::Object> proto(m, "Prototype",
"DEX Prototype representation"_doc);
init_ref_iterator<Prototype::it_params>(proto, "it_params");
proto
.def_property_readonly("return_type",
static_cast<no_const_getter_t<Type*>>(&Prototype::return_type),
"" RST_CLASS_REF(lief.DEX.Type) " returned",
py::return_value_policy::reference)
.def_prop_ro("return_type",
nb::overload_cast<>(&Prototype::return_type, nb::const_),
"" RST_CLASS_REF(lief.DEX.Type) " returned"_doc,
nb::rv_policy::reference_internal)
.def_property_readonly("parameters_type",
static_cast<no_const_getter_t<Prototype::it_params>>(&Prototype::parameters_type),
"Iterator over parameters " RST_CLASS_REF(lief.DEX.Type) "")
.def("__eq__", &Prototype::operator==)
.def("__ne__", &Prototype::operator!=)
.def("__hash__",
[] (const Prototype& ptype) {
return Hash::hash(ptype);
})
.def("__str__",
[] (const Prototype& ptype) {
std::ostringstream stream;
stream << ptype;
return stream.str();
});
}
.def_prop_ro("parameters_type",
nb::overload_cast<>(&Prototype::parameters_type),
"Iterator over parameters " RST_CLASS_REF(lief.DEX.Type) ""_doc)
LIEF_DEFAULT_STR(Prototype);
}
}
+28 -53
View File
@@ -14,41 +14,33 @@
* limitations under the License.
*/
#include "LIEF/DEX/Type.hpp"
#include "LIEF/DEX/hash.hpp"
#include "LIEF/DEX/Class.hpp"
#include "LIEF/DEX/EnumToString.hpp"
#include "pyDEX.hpp"
#include "DEX/pyDEX.hpp"
#include <sstream>
#include <string>
#include <nanobind/stl/string.h>
#define PY_ENUM(x) to_string(x), x
namespace LIEF {
namespace DEX {
template<class T>
using getter_t = T (Type::*)(void) const;
template<class T>
using no_const_getter_t = T (Type::*)(void);
template<class T>
using setter_t = void (Type::*)(T);
namespace LIEF::DEX::py {
template<>
void create<Type>(py::module& m) {
void create<Type>(nb::module_& m) {
py::class_<Type, LIEF::Object> pytype(m, "Type", "DEX Type representation");
nb::class_<Type, LIEF::Object> pytype(m, "Type",
"DEX Type representation"_doc);
py::enum_<Type::TYPES>(pytype, "TYPES")
nb::enum_<Type::TYPES>(pytype, "TYPES")
.value(PY_ENUM(Type::TYPES::UNKNOWN))
.value(PY_ENUM(Type::TYPES::ARRAY))
.value(PY_ENUM(Type::TYPES::PRIMITIVE))
.value(PY_ENUM(Type::TYPES::CLASS));
py::enum_<Type::PRIMITIVES>(pytype, "PRIMITIVES")
nb::enum_<Type::PRIMITIVES>(pytype, "PRIMITIVES")
.value(PY_ENUM(Type::PRIMITIVES::VOID_T))
.value(PY_ENUM(Type::PRIMITIVES::BOOLEAN))
.value(PY_ENUM(Type::PRIMITIVES::BYTE))
@@ -59,69 +51,52 @@ void create<Type>(py::module& m) {
.value(PY_ENUM(Type::PRIMITIVES::FLOAT))
.value(PY_ENUM(Type::PRIMITIVES::DOUBLE));
pytype
.def_property_readonly("type",
&Type::type,
"" RST_CLASS_REF(lief.DEX.Type.TYPES) " of this object")
.def_prop_ro("type", &Type::type,
"" RST_CLASS_REF(lief.DEX.Type.TYPES) " of this object"_doc)
.def_property_readonly("value",
[] (Type& type) -> py::object {
.def_prop_ro("value",
[] (Type& type) -> nb::object {
switch (type.type()) {
case Type::TYPES::ARRAY:
{
return py::cast(type.array());
return nb::cast(type.array());
}
case Type::TYPES::CLASS:
{
return py::cast(type.cls(), py::return_value_policy::reference);
return nb::cast(type.cls(), nb::rv_policy::reference_internal);
}
case Type::TYPES::PRIMITIVE:
{
return py::cast(type.primitive());
return nb::cast(type.primitive());
}
case Type::TYPES::UNKNOWN:
default:
{
return py::none{};
return nb::none();
}
}
},
"Depending on the " RST_CLASS_REF(lief.DEX.Type.TYPES) ", return "
" " RST_CLASS_REF(lief.DEX.Class) " or " RST_CLASS_REF(lief.DEX.Type.PRIMITIVES) " or array",
py::return_value_policy::reference)
" " RST_CLASS_REF(lief.DEX.Class) " or " RST_CLASS_REF(lief.DEX.Type.PRIMITIVES) " or array"_doc,
nb::rv_policy::reference_internal)
.def_property_readonly("dim",
.def_prop_ro("dim",
&Type::dim,
"If the current type is an array, return its dimension otherwise 0")
.def_property_readonly("underlying_array_type",
static_cast<no_const_getter_t<Type&>>(&Type::underlying_array_type),
"Underlying type of the array",
py::return_value_policy::reference)
.def_prop_ro("underlying_array_type",
nb::overload_cast<>(&Type::underlying_array_type, nb::const_),
"Underlying type of the array"_doc,
nb::rv_policy::reference_internal)
.def_static("pretty_name",
&Type::pretty_name,
"Pretty name of primitives",
.def_static("pretty_name", &Type::pretty_name,
"Pretty name of primitives"_doc,
"primitive"_a)
.def("__eq__", &Type::operator==)
.def("__ne__", &Type::operator!=)
.def("__hash__",
[] (const Type& type) {
return Hash::hash(type);
})
.def("__str__",
[] (const Type& type) {
std::ostringstream stream;
stream << type;
return stream.str();
});
}
LIEF_DEFAULT_STR(Type);
}
}
+4 -38
View File
@@ -13,48 +13,14 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef PY_LIEF_DEX_H_
#define PY_LIEF_DEX_H_
#include "LIEF/DEX.hpp"
#ifndef PY_LIEF_DEX_H
#define PY_LIEF_DEX_H
#include "pyLIEF.hpp"
#define SPECIALIZE_CREATE(X) \
template<> \
void create<X>(py::module&)
#define CREATE(X,Y) create<X>(Y)
namespace LIEF {
namespace DEX {
namespace LIEF::DEX::py {
template<class T>
void create(py::module&);
void init_python_module(py::module& m);
void init_objects(py::module&);
void init_enums(py::module&);
void init_utils(py::module&);
SPECIALIZE_CREATE(Parser);
SPECIALIZE_CREATE(File);
SPECIALIZE_CREATE(Header);
SPECIALIZE_CREATE(Class);
SPECIALIZE_CREATE(Method);
SPECIALIZE_CREATE(Field);
SPECIALIZE_CREATE(Prototype);
SPECIALIZE_CREATE(Type);
SPECIALIZE_CREATE(MapList);
SPECIALIZE_CREATE(MapItem);
SPECIALIZE_CREATE(CodeInfo);
}
void create(nb::module_&);
}
+4 -7
View File
@@ -13,17 +13,16 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "pyDEX.hpp"
#include "DEX/pyDEX.hpp"
#include "LIEF/DEX/enums.hpp"
#include "LIEF/DEX/EnumToString.hpp"
#define PY_ENUM(x) to_string(x), x
namespace LIEF {
namespace DEX {
void init_enums(py::module& m) {
namespace LIEF::DEX::py {
void init_enums(nb::module_& m) {
py::enum_<ACCESS_FLAGS>(m, "ACCESS_FLAGS")
nb::enum_<ACCESS_FLAGS>(m, "ACCESS_FLAGS")
.value(PY_ENUM(ACCESS_FLAGS::ACC_UNKNOWN))
.value(PY_ENUM(ACCESS_FLAGS::ACC_PUBLIC))
.value(PY_ENUM(ACCESS_FLAGS::ACC_PRIVATE))
@@ -44,7 +43,5 @@ void init_enums(py::module& m) {
.value(PY_ENUM(ACCESS_FLAGS::ACC_ENUM))
.value(PY_ENUM(ACCESS_FLAGS::ACC_CONSTRUCTOR))
.value(PY_ENUM(ACCESS_FLAGS::ACC_DECLARED_SYNCHRONIZED));
}
}
}
+18 -17
View File
@@ -13,37 +13,38 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "pyDEX.hpp"
#include "DEX/pyDEX.hpp"
#include "LIEF/DEX/utils.hpp"
namespace LIEF {
namespace DEX {
#include <nanobind/stl/string.h>
#include <nanobind/stl/vector.h>
void init_utils(py::module& m) {
namespace LIEF::DEX::py {
m.def("is_dex",
static_cast<bool (*)(const std::string&)>(&is_dex),
"Check if the **file** given in parameter is a DEX",
void init_utils(nb::module_& m) {
nb::module_ lief_mod = nb::module_::import_(LIEF_MOD_NAME);
lief_mod.def("is_dex",
nb::overload_cast<const std::string&>(&is_dex),
"Check if the **file** given in parameter is a DEX"_doc,
"path"_a);
m.def("is_dex",
static_cast<bool (*)(const std::vector<uint8_t>&)>(&is_dex),
"Check if the **raw data** given in parameter is a DEX",
lief_mod.def("is_dex",
nb::overload_cast<const std::vector<uint8_t>&>(&is_dex),
"Check if the **raw data** given in parameter is a DEX"_doc,
"raw"_a);
m.def("version",
static_cast<dex_version_t (*)(const std::string&)>(&version),
"Return the DEX version of the **file** given in parameter",
nb::overload_cast<const std::string&>(&version),
"Return the DEX version of the **file** given in parameter"_doc,
"file"_a);
m.def("version",
static_cast<dex_version_t (*)(const std::vector<uint8_t>&)>(&version),
"Return the DEX version of the **raw data** given in parameter",
nb::overload_cast<const std::vector<uint8_t>&>(&version),
"Return the DEX version of the **raw data** given in parameter"_doc,
"raw"_a);
}
}
}
+8 -38
View File
@@ -1,47 +1,17 @@
set(LIEF_PYTHON_ELF_SRC
"${CMAKE_CURRENT_LIST_DIR}/pyELF.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pyDynamicEntry.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pySymbolVersionAuxRequirement.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pySymbolVersion.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pyDynamicEntryRunPath.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pySymbolVersionRequirement.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pyBinary.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pySymbolVersionDefinition.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pyHeader.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pySymbolVersionAux.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pyDynamicEntryArray.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pyDynamicEntryFlags.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pySegment.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pySection.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pyDynamicEntryRpath.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pyRelocation.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pyDynamicSharedObject.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pyParser.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pyParserConfig.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pyDynamicEntryLibrary.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pySymbol.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pyGnuHash.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pySysvHash.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pyBuilder.cpp"
"${CMAKE_CURRENT_LIST_DIR}/pyEnums.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/init.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/enums.cpp"
)
set(LIEF_PYTHON_ELF_NOTE
"${CMAKE_CURRENT_LIST_DIR}/objects/pyNote.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pyNoteDetails.cpp"
)
list(APPEND LIEF_PYTHON_ELF_SRC ${LIEF_PYTHON_ELF_NOTE})
include("${CMAKE_CURRENT_LIST_DIR}/objects/NoteDetails/CMakeLists.txt")
set(LIEF_PYTHON_ELF_HDR
"${CMAKE_CURRENT_LIST_DIR}/pyELF.hpp")
"${CMAKE_CURRENT_SOURCE_DIR}/pyELF.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/init.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/enums.hpp"
)
source_group("Source Files\\ELF" FILES ${LIEF_PYTHON_ELF_SRC})
source_group("Header Files\\ELF" FILES ${LIEF_PYTHON_ELF_HDR})
target_sources(pyLIEF PRIVATE "${LIEF_PYTHON_ELF_SRC}" "${LIEF_PYTHON_ELF_HDR}")
target_include_directories(pyLIEF PUBLIC "${CMAKE_CURRENT_LIST_DIR}")
target_sources(pyLIEF PRIVATE ${LIEF_PYTHON_ELF_SRC} ${LIEF_PYTHON_ELF_HDR})
add_subdirectory(objects)
@@ -13,31 +13,26 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "pyELF.hpp"
#include "enums_wrapper.hpp"
#include "ELF/enums.hpp"
#include "LIEF/ELF/enums.hpp"
#include "LIEF/ELF/EnumToString.hpp"
#include "enums_wrapper.hpp"
#define PY_ENUM(x) to_string(x), x
namespace LIEF {
namespace ELF {
void init_enums(py::module& m) {
LIEF::enum_<ELF_CLASS>(m, "ELF_CLASS")
namespace LIEF::ELF::py {
void init_enums(nb::module_& m) {
enum_<ELF_CLASS>(m, "ELF_CLASS")
.value(PY_ENUM(ELF_CLASS::ELFCLASSNONE))
.value(PY_ENUM(ELF_CLASS::ELFCLASS32))
.value(PY_ENUM(ELF_CLASS::ELFCLASS64));
LIEF::enum_<ELF_DATA>(m, "ELF_DATA")
enum_<ELF_DATA>(m, "ELF_DATA")
.value(PY_ENUM(ELF_DATA::ELFDATANONE))
.value(PY_ENUM(ELF_DATA::ELFDATA2LSB))
.value(PY_ENUM(ELF_DATA::ELFDATA2MSB));
LIEF::enum_<OS_ABI>(m, "OS_ABI")
enum_<OS_ABI>(m, "OS_ABI")
.value(PY_ENUM(OS_ABI::ELFOSABI_SYSTEMV))
.value(PY_ENUM(OS_ABI::ELFOSABI_HPUX))
.value(PY_ENUM(OS_ABI::ELFOSABI_NETBSD))
@@ -63,7 +58,7 @@ void init_enums(py::module& m) {
.value(PY_ENUM(OS_ABI::ELFOSABI_STANDALONE));
// Enum for the *e_type* of ElfXX_Ehdr
LIEF::enum_<E_TYPE>(m, "E_TYPE")
enum_<E_TYPE>(m, "E_TYPE")
.value(PY_ENUM(E_TYPE::ET_NONE))
.value(PY_ENUM(E_TYPE::ET_REL))
.value(PY_ENUM(E_TYPE::ET_EXEC))
@@ -73,12 +68,12 @@ void init_enums(py::module& m) {
.value(PY_ENUM(E_TYPE::ET_HIPROC));
//! Enum for the *e_version* of ElfXX_Ehdr;
LIEF::enum_<VERSION>(m, "VERSION")
enum_<VERSION>(m, "VERSION")
.value(PY_ENUM(VERSION::EV_NONE))
.value(PY_ENUM(VERSION::EV_CURRENT));
// Enum for the *e_machine* of ElfXX_Ehdr
LIEF::enum_<ARCH>(m, "ARCH")
enum_<ARCH>(m, "ARCH")
.value(PY_ENUM(ARCH::EM_NONE))
.value(PY_ENUM(ARCH::EM_M32))
.value(PY_ENUM(ARCH::EM_SPARC))
@@ -260,7 +255,7 @@ void init_enums(py::module& m) {
//! Enum for the *sh_type* of ElfXX_Shdr;
LIEF::enum_<ELF_SECTION_TYPES>(m, "SECTION_TYPES")
enum_<ELF_SECTION_TYPES>(m, "SECTION_TYPES")
.value(PY_ENUM(ELF_SECTION_TYPES::SHT_NULL))
.value(PY_ENUM(ELF_SECTION_TYPES::SHT_PROGBITS))
.value(PY_ENUM(ELF_SECTION_TYPES::SHT_SYMTAB))
@@ -305,7 +300,7 @@ void init_enums(py::module& m) {
//! Enum for the *sh_flags* field of ElfXX_Shdr;
LIEF::enum_<ELF_SECTION_FLAGS>(m, "SECTION_FLAGS", py::arithmetic())
enum_<ELF_SECTION_FLAGS>(m, "SECTION_FLAGS", nb::is_arithmetic())
.value(PY_ENUM(ELF_SECTION_FLAGS::SHF_NONE))
.value(PY_ENUM(ELF_SECTION_FLAGS::SHF_WRITE))
.value(PY_ENUM(ELF_SECTION_FLAGS::SHF_ALLOC))
@@ -325,7 +320,7 @@ void init_enums(py::module& m) {
.value(PY_ENUM(ELF_SECTION_FLAGS::SHF_HEX_GPREL));
//! Enum for the *p_type* field of ElfXX_Phdr
LIEF::enum_<SEGMENT_TYPES>(m, "SEGMENT_TYPES")
enum_<SEGMENT_TYPES>(m, "SEGMENT_TYPES")
.value(PY_ENUM(SEGMENT_TYPES::PT_NULL))
.value(PY_ENUM(SEGMENT_TYPES::PT_LOAD))
.value(PY_ENUM(SEGMENT_TYPES::PT_DYNAMIC))
@@ -343,13 +338,13 @@ void init_enums(py::module& m) {
.value("UNWIND", SEGMENT_TYPES::PT_ARM_UNWIND);
//! Enum for the *p_flags* field of ElfXX_Phdr
LIEF::enum_<ELF_SEGMENT_FLAGS>(m, "SEGMENT_FLAGS", py::arithmetic())
enum_<ELF_SEGMENT_FLAGS>(m, "SEGMENT_FLAGS", nb::is_arithmetic())
.value(PY_ENUM(ELF_SEGMENT_FLAGS::PF_NONE))
.value(PY_ENUM(ELF_SEGMENT_FLAGS::PF_X))
.value(PY_ENUM(ELF_SEGMENT_FLAGS::PF_W))
.value(PY_ENUM(ELF_SEGMENT_FLAGS::PF_R));
LIEF::enum_<DYNAMIC_TAGS>(m, "DYNAMIC_TAGS")
enum_<DYNAMIC_TAGS>(m, "DYNAMIC_TAGS")
.value(PY_ENUM(DYNAMIC_TAGS::DT_NULL))
.value(PY_ENUM(DYNAMIC_TAGS::DT_NEEDED))
.value(PY_ENUM(DYNAMIC_TAGS::DT_PLTRELSZ))
@@ -449,7 +444,7 @@ void init_enums(py::module& m) {
.value(PY_ENUM(DYNAMIC_TAGS::DT_RELRCOUNT));
LIEF::enum_<ELF_SYMBOL_TYPES>(m, "SYMBOL_TYPES")
enum_<ELF_SYMBOL_TYPES>(m, "SYMBOL_TYPES")
.value(PY_ENUM(ELF_SYMBOL_TYPES::STT_NOTYPE))
.value(PY_ENUM(ELF_SYMBOL_TYPES::STT_OBJECT))
.value(PY_ENUM(ELF_SYMBOL_TYPES::STT_FUNC))
@@ -460,14 +455,14 @@ void init_enums(py::module& m) {
.value(PY_ENUM(ELF_SYMBOL_TYPES::STT_GNU_IFUNC));
LIEF::enum_<SYMBOL_BINDINGS>(m, "SYMBOL_BINDINGS")
enum_<SYMBOL_BINDINGS>(m, "SYMBOL_BINDINGS")
.value(PY_ENUM(SYMBOL_BINDINGS::STB_LOCAL))
.value(PY_ENUM(SYMBOL_BINDINGS::STB_GLOBAL))
.value(PY_ENUM(SYMBOL_BINDINGS::STB_WEAK))
.value(PY_ENUM(SYMBOL_BINDINGS::STB_GNU_UNIQUE));
LIEF::enum_<RELOC_x86_64>(m, "RELOCATION_X86_64")
enum_<RELOC_x86_64>(m, "RELOCATION_X86_64")
.value(PY_ENUM(RELOC_x86_64::R_X86_64_NONE))
.value(PY_ENUM(RELOC_x86_64::R_X86_64_64))
.value(PY_ENUM(RELOC_x86_64::R_X86_64_PC32))
@@ -514,7 +509,7 @@ void init_enums(py::module& m) {
.value(PY_ENUM(RELOC_x86_64::R_X86_64_REX_GOTPCRELX));
LIEF::enum_<RELOC_ARM>(m, "RELOCATION_ARM")
enum_<RELOC_ARM>(m, "RELOCATION_ARM")
.value(PY_ENUM(RELOC_ARM::R_ARM_NONE))
.value(PY_ENUM(RELOC_ARM::R_ARM_PC24))
.value(PY_ENUM(RELOC_ARM::R_ARM_ABS32))
@@ -655,7 +650,7 @@ void init_enums(py::module& m) {
.value(PY_ENUM(RELOC_ARM::R_ARM_RBASE));
LIEF::enum_<RELOC_i386>(m, "RELOCATION_i386")
enum_<RELOC_i386>(m, "RELOCATION_i386")
.value(PY_ENUM(RELOC_i386::R_386_NONE))
.value(PY_ENUM(RELOC_i386::R_386_32))
.value(PY_ENUM(RELOC_i386::R_386_PC32))
@@ -699,7 +694,7 @@ void init_enums(py::module& m) {
.value(PY_ENUM(RELOC_i386::R_386_NUM));
LIEF::enum_<RELOC_AARCH64>(m, "RELOCATION_AARCH64")
enum_<RELOC_AARCH64>(m, "RELOCATION_AARCH64")
.value(PY_ENUM(RELOC_AARCH64::R_AARCH64_NONE))
.value(PY_ENUM(RELOC_AARCH64::R_AARCH64_ABS64))
.value(PY_ENUM(RELOC_AARCH64::R_AARCH64_ABS32))
@@ -824,7 +819,7 @@ void init_enums(py::module& m) {
.value(PY_ENUM(RELOC_AARCH64::R_AARCH64_TLSDESC))
.value(PY_ENUM(RELOC_AARCH64::R_AARCH64_IRELATIVE));
LIEF::enum_<RELOC_POWERPC32>(m, "RELOCATION_PPC")
enum_<RELOC_POWERPC32>(m, "RELOCATION_PPC")
.value(PY_ENUM(RELOC_POWERPC32::R_PPC_NONE))
.value(PY_ENUM(RELOC_POWERPC32::R_PPC_ADDR32))
.value(PY_ENUM(RELOC_POWERPC32::R_PPC_ADDR24))
@@ -883,7 +878,7 @@ void init_enums(py::module& m) {
.value(PY_ENUM(RELOC_POWERPC32::R_PPC_REL16_HI))
.value(PY_ENUM(RELOC_POWERPC32::R_PPC_REL16_HA));
LIEF::enum_<RELOC_POWERPC64>(m, "RELOCATION_PPC64")
enum_<RELOC_POWERPC64>(m, "RELOCATION_PPC64")
.value(PY_ENUM(RELOC_POWERPC64::R_PPC64_NONE))
.value(PY_ENUM(RELOC_POWERPC64::R_PPC64_ADDR32))
.value(PY_ENUM(RELOC_POWERPC64::R_PPC64_ADDR24))
@@ -969,7 +964,7 @@ void init_enums(py::module& m) {
.value(PY_ENUM(RELOC_POWERPC64::R_PPC64_REL16_HI))
.value(PY_ENUM(RELOC_POWERPC64::R_PPC64_REL16_HA));
LIEF::enum_<RELOC_MIPS>(m, "RELOCATION_MIPS")
enum_<RELOC_MIPS>(m, "RELOCATION_MIPS")
.value(PY_ENUM(RELOC_MIPS::R_MIPS_NONE))
.value(PY_ENUM(RELOC_MIPS::R_MIPS_16))
.value(PY_ENUM(RELOC_MIPS::R_MIPS_32))
@@ -1080,7 +1075,7 @@ void init_enums(py::module& m) {
.value(PY_ENUM(RELOC_MIPS::R_MICROMIPS_PC18_S3))
.value(PY_ENUM(RELOC_MIPS::R_MICROMIPS_PC19_S2));
LIEF::enum_<RELOC_LOONGARCH>(m, "RELOCATION_LOONGARCH")
enum_<RELOC_LOONGARCH>(m, "RELOCATION_LOONGARCH")
.value(PY_ENUM(RELOC_LOONGARCH::R_LARCH_NONE))
.value(PY_ENUM(RELOC_LOONGARCH::R_LARCH_32))
.value(PY_ENUM(RELOC_LOONGARCH::R_LARCH_64))
@@ -1171,14 +1166,14 @@ void init_enums(py::module& m) {
.value(PY_ENUM(RELOC_LOONGARCH::R_LARCH_32_PCREL))
.value(PY_ENUM(RELOC_LOONGARCH::R_LARCH_RELAX));
LIEF::enum_<DYNSYM_COUNT_METHODS>(m, "DYNSYM_COUNT_METHODS")
enum_<DYNSYM_COUNT_METHODS>(m, "DYNSYM_COUNT_METHODS")
.value(PY_ENUM(DYNSYM_COUNT_METHODS::COUNT_AUTO))
.value(PY_ENUM(DYNSYM_COUNT_METHODS::COUNT_SECTION))
.value(PY_ENUM(DYNSYM_COUNT_METHODS::COUNT_HASH))
.value(PY_ENUM(DYNSYM_COUNT_METHODS::COUNT_RELOCATIONS));
LIEF::enum_<NOTE_TYPES>(m, "NOTE_TYPES")
enum_<NOTE_TYPES>(m, "NOTE_TYPES")
.value(PY_ENUM(NOTE_TYPES::NT_UNKNOWN))
.value(PY_ENUM(NOTE_TYPES::NT_GNU_ABI_TAG))
.value(PY_ENUM(NOTE_TYPES::NT_GNU_HWCAP))
@@ -1190,7 +1185,7 @@ void init_enums(py::module& m) {
.value(PY_ENUM(NOTE_TYPES::NT_CRASHPAD));
LIEF::enum_<NOTE_TYPES_CORE>(m, "NOTE_TYPES_CORE")
enum_<NOTE_TYPES_CORE>(m, "NOTE_TYPES_CORE")
.value(PY_ENUM(NOTE_TYPES_CORE::NT_CORE_UNKNOWN))
.value(PY_ENUM(NOTE_TYPES_CORE::NT_PRSTATUS))
.value(PY_ENUM(NOTE_TYPES_CORE::NT_PRFPREG))
@@ -1212,7 +1207,7 @@ void init_enums(py::module& m) {
.value(PY_ENUM(NOTE_TYPES_CORE::NT_386_XSTATE));
LIEF::enum_<NOTE_ABIS>(m, "NOTE_ABIS")
enum_<NOTE_ABIS>(m, "NOTE_ABIS")
.value(PY_ENUM(NOTE_ABIS::ELF_NOTE_UNKNOWN))
.value(PY_ENUM(NOTE_ABIS::ELF_NOTE_OS_LINUX))
.value(PY_ENUM(NOTE_ABIS::ELF_NOTE_OS_GNU))
@@ -1222,14 +1217,14 @@ void init_enums(py::module& m) {
.value(PY_ENUM(NOTE_ABIS::ELF_NOTE_OS_SYLLABLE));
LIEF::enum_<RELOCATION_PURPOSES>(m, "RELOCATION_PURPOSES")
enum_<RELOCATION_PURPOSES>(m, "RELOCATION_PURPOSES")
.value(PY_ENUM(RELOCATION_PURPOSES::RELOC_PURPOSE_NONE))
.value(PY_ENUM(RELOCATION_PURPOSES::RELOC_PURPOSE_PLTGOT))
.value(PY_ENUM(RELOCATION_PURPOSES::RELOC_PURPOSE_DYNAMIC))
.value(PY_ENUM(RELOCATION_PURPOSES::RELOC_PURPOSE_OBJECT));
LIEF::enum_<ARM_EFLAGS>(m, "ARM_EFLAGS", py::arithmetic())
enum_<ARM_EFLAGS>(m, "ARM_EFLAGS", nb::is_arithmetic())
.value(PY_ENUM(ARM_EFLAGS::EF_ARM_SOFT_FLOAT))
.value(PY_ENUM(ARM_EFLAGS::EF_ARM_VFP_FLOAT))
.value(PY_ENUM(ARM_EFLAGS::EF_ARM_EABI_UNKNOWN))
@@ -1240,10 +1235,10 @@ void init_enums(py::module& m) {
.value(PY_ENUM(ARM_EFLAGS::EF_ARM_EABI_VER5));
LIEF::enum_<PPC64_EFLAGS>(m, "PPC64_EFLAGS", py::arithmetic())
enum_<PPC64_EFLAGS>(m, "PPC64_EFLAGS", nb::is_arithmetic())
.value(PY_ENUM(PPC64_EFLAGS::EF_PPC64_ABI));
LIEF::enum_<MIPS_EFLAGS>(m, "MIPS_EFLAGS", py::arithmetic())
enum_<MIPS_EFLAGS>(m, "MIPS_EFLAGS", nb::is_arithmetic())
.value(PY_ENUM(MIPS_EFLAGS::EF_MIPS_NOREORDER))
.value(PY_ENUM(MIPS_EFLAGS::EF_MIPS_PIC))
.value(PY_ENUM(MIPS_EFLAGS::EF_MIPS_CPIC))
@@ -1288,7 +1283,7 @@ void init_enums(py::module& m) {
.value(PY_ENUM(MIPS_EFLAGS::EF_MIPS_ARCH_32R6))
.value(PY_ENUM(MIPS_EFLAGS::EF_MIPS_ARCH_64R6));
LIEF::enum_<HEXAGON_EFLAGS>(m, "HEXAGON_EFLAGS", py::arithmetic())
enum_<HEXAGON_EFLAGS>(m, "HEXAGON_EFLAGS", nb::is_arithmetic())
.value(PY_ENUM(HEXAGON_EFLAGS::EF_HEXAGON_MACH_V2))
.value(PY_ENUM(HEXAGON_EFLAGS::EF_HEXAGON_MACH_V3))
.value(PY_ENUM(HEXAGON_EFLAGS::EF_HEXAGON_MACH_V4))
@@ -1299,12 +1294,12 @@ void init_enums(py::module& m) {
.value(PY_ENUM(HEXAGON_EFLAGS::EF_HEXAGON_ISA_V4))
.value(PY_ENUM(HEXAGON_EFLAGS::EF_HEXAGON_ISA_V5));
LIEF::enum_<LOONGARCH_EFLAGS>(m, "LOONGARCH_EFLAGS", py::arithmetic())
enum_<LOONGARCH_EFLAGS>(m, "LOONGARCH_EFLAGS", nb::is_arithmetic())
.value(PY_ENUM(LOONGARCH_EFLAGS::EF_LOONGARCH_ABI_SOFT_FLOAT))
.value(PY_ENUM(LOONGARCH_EFLAGS::EF_LOONGARCH_ABI_SINGLE_FLOAT))
.value(PY_ENUM(LOONGARCH_EFLAGS::EF_LOONGARCH_ABI_DOUBLE_FLOAT));
LIEF::enum_<IDENTITY>(m, "IDENTITY")
enum_<IDENTITY>(m, "IDENTITY")
.value(PY_ENUM(IDENTITY::EI_MAG0))
.value(PY_ENUM(IDENTITY::EI_MAG1))
.value(PY_ENUM(IDENTITY::EI_MAG2))
@@ -1318,21 +1313,21 @@ void init_enums(py::module& m) {
.value(PY_ENUM(IDENTITY::EI_NIDENT));
LIEF::enum_<SYMBOL_SECTION_INDEX>(m, "SYMBOL_SECTION_INDEX")
enum_<SYMBOL_SECTION_INDEX>(m, "SYMBOL_SECTION_INDEX")
.value(PY_ENUM(SYMBOL_SECTION_INDEX::SHN_UNDEF))
.value(PY_ENUM(SYMBOL_SECTION_INDEX::SHN_ABS))
.value(PY_ENUM(SYMBOL_SECTION_INDEX::SHN_COMMON))
.value(PY_ENUM(SYMBOL_SECTION_INDEX::SHN_HIRESERVE));
LIEF::enum_<DYNAMIC_FLAGS>(m, "DYNAMIC_FLAGS", py::arithmetic())
enum_<DYNAMIC_FLAGS>(m, "DYNAMIC_FLAGS", nb::is_arithmetic())
.value(PY_ENUM(DYNAMIC_FLAGS::DF_ORIGIN))
.value(PY_ENUM(DYNAMIC_FLAGS::DF_SYMBOLIC))
.value(PY_ENUM(DYNAMIC_FLAGS::DF_TEXTREL))
.value(PY_ENUM(DYNAMIC_FLAGS::DF_BIND_NOW))
.value(PY_ENUM(DYNAMIC_FLAGS::DF_STATIC_TLS));
LIEF::enum_<DYNAMIC_FLAGS_1>(m, "DYNAMIC_FLAGS_1", py::arithmetic())
enum_<DYNAMIC_FLAGS_1>(m, "DYNAMIC_FLAGS_1", nb::is_arithmetic())
.value(PY_ENUM(DYNAMIC_FLAGS_1::DF_1_NOW))
.value(PY_ENUM(DYNAMIC_FLAGS_1::DF_1_GLOBAL))
.value(PY_ENUM(DYNAMIC_FLAGS_1::DF_1_GROUP))
@@ -1361,14 +1356,11 @@ void init_enums(py::module& m) {
.value(PY_ENUM(DYNAMIC_FLAGS_1::DF_1_SINGLETON))
.value(PY_ENUM(DYNAMIC_FLAGS_1::DF_1_PIE));
LIEF::enum_<ELF_SYMBOL_VISIBILITY>(m, "SYMBOL_VISIBILITY")
enum_<ELF_SYMBOL_VISIBILITY>(m, "SYMBOL_VISIBILITY")
.value(PY_ENUM(ELF_SYMBOL_VISIBILITY::STV_DEFAULT))
.value(PY_ENUM(ELF_SYMBOL_VISIBILITY::STV_HIDDEN))
.value(PY_ENUM(ELF_SYMBOL_VISIBILITY::STV_INTERNAL))
.value(PY_ENUM(ELF_SYMBOL_VISIBILITY::STV_PROTECTED));
}
}
}
+23
View File
@@ -0,0 +1,23 @@
/* Copyright 2017 - 2023 R. Thomas
* Copyright 2017 - 2023 Quarkslab
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef PY_LIEF_ELF_ENUMS_H
#define PY_LIEF_ELF_ENUMS_H
#include "pyLIEF.hpp"
namespace LIEF::ELF::py {
void init_enums(nb::module_& m);
}
#endif
+114
View File
@@ -0,0 +1,114 @@
/* Copyright 2017 - 2023 R. Thomas
* Copyright 2017 - 2023 Quarkslab
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "ELF/init.hpp"
#include "ELF/enums.hpp"
#include "ELF/pyELF.hpp"
#include <nanobind/stl/string.h>
#include <nanobind/stl/vector.h>
#include "LIEF/ELF/Builder.hpp"
#include "LIEF/ELF/DynamicEntry.hpp"
#include "LIEF/ELF/DynamicEntryArray.hpp"
#include "LIEF/ELF/DynamicEntryFlags.hpp"
#include "LIEF/ELF/DynamicEntryLibrary.hpp"
#include "LIEF/ELF/DynamicEntryRpath.hpp"
#include "LIEF/ELF/DynamicEntryRunPath.hpp"
#include "LIEF/ELF/DynamicSharedObject.hpp"
#include "LIEF/ELF/GnuHash.hpp"
#include "LIEF/ELF/Header.hpp"
#include "LIEF/ELF/Note.hpp"
#include "LIEF/ELF/NoteDetails.hpp"
#include "LIEF/ELF/NoteDetails/AndroidNote.hpp"
#include "LIEF/ELF/NoteDetails/NoteAbi.hpp"
#include "LIEF/ELF/NoteDetails/core/CoreAuxv.hpp"
#include "LIEF/ELF/NoteDetails/core/CoreFile.hpp"
#include "LIEF/ELF/NoteDetails/core/CorePrPsInfo.hpp"
#include "LIEF/ELF/NoteDetails/core/CorePrStatus.hpp"
#include "LIEF/ELF/NoteDetails/core/CoreSigInfo.hpp"
#include "LIEF/ELF/Parser.hpp"
#include "LIEF/ELF/Relocation.hpp"
#include "LIEF/ELF/Section.hpp"
#include "LIEF/ELF/Segment.hpp"
#include "LIEF/ELF/SymbolVersion.hpp"
#include "LIEF/ELF/SymbolVersionAux.hpp"
#include "LIEF/ELF/SymbolVersionAuxRequirement.hpp"
#include "LIEF/ELF/SymbolVersionDefinition.hpp"
#include "LIEF/ELF/SymbolVersionRequirement.hpp"
#include "LIEF/ELF/SysvHash.hpp"
#include "LIEF/ELF/utils.hpp"
#define CREATE(X,Y) create<X>(Y)
namespace LIEF::ELF::py {
void init_objects(nb::module_& m) {
CREATE(ParserConfig, m);
CREATE(Parser, m);
CREATE(SymbolVersion, m);
CREATE(Binary, m);
CREATE(Header, m);
CREATE(Section, m);
CREATE(Segment, m);
CREATE(Symbol, m);
CREATE(Relocation, m);
CREATE(SymbolVersionAux, m);
CREATE(SymbolVersionAuxRequirement, m);
CREATE(SymbolVersionDefinition,m );
CREATE(SymbolVersionRequirement, m);
CREATE(DynamicEntry, m);
CREATE(DynamicEntryLibrary, m);
CREATE(DynamicSharedObject, m);
CREATE(DynamicEntryArray, m);
CREATE(DynamicEntryRpath, m);
CREATE(DynamicEntryRunPath, m);
CREATE(DynamicEntryFlags, m);
CREATE(GnuHash, m);
CREATE(SysvHash, m);
CREATE(Builder, m);
CREATE(Note, m);
CREATE(NoteDetails, m);
CREATE(AndroidNote, m);
CREATE(NoteAbi, m);
CREATE(CorePrPsInfo, m);
CREATE(CoreFile, m);
CREATE(CoreFileEntry, m);
CREATE(CorePrStatus, m);
CREATE(CoreAuxv, m);
CREATE(CoreSigInfo, m);
}
inline void init_utils(nb::module_&) {
nb::module_ lief_mod = nb::module_::import_(LIEF_MOD_NAME);
lief_mod.def("is_elf",
nb::overload_cast<const std::string&>(&is_elf),
"Check if the given file is an ``ELF``",
"filename"_a);
lief_mod.def("is_elf",
nb::overload_cast<const std::vector<uint8_t>&>(&is_elf),
"Check if the given raw data is an ``ELF``",
"raw"_a);
}
void init(nb::module_& m) {
nb::module_ elf_mod = m.def_submodule("ELF", "Python API for the ELF format");
init_utils(m);
init_enums(elf_mod);
init_objects(elf_mod);
}
}
+23
View File
@@ -0,0 +1,23 @@
/* Copyright 2017 - 2023 R. Thomas
* Copyright 2017 - 2023 Quarkslab
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef PY_LIEF_ELF_INIT_H
#define PY_LIEF_ELF_INIT_H
#include "pyLIEF.hpp"
namespace LIEF::ELF::py {
void init(nb::module_& m);
}
#endif
+32
View File
@@ -0,0 +1,32 @@
set(LIEF_PYTHON_ELF_OBJECT_SRC
"${CMAKE_CURRENT_SOURCE_DIR}/pyParser.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/pyBinary.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/pyBuilder.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/pyDynamicEntry.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/pyDynamicEntryArray.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/pyDynamicEntryFlags.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/pyDynamicEntryLibrary.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/pyDynamicEntryRpath.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/pyDynamicEntryRunPath.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/pyDynamicSharedObject.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/pyGnuHash.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/pyHeader.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/pyParserConfig.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/pyNote.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/pyNoteDetails.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/pyRelocation.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/pySection.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/pySegment.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/pySymbol.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/pySymbolVersion.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/pySymbolVersionAux.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/pySymbolVersionAuxRequirement.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/pySymbolVersionRequirement.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/pySymbolVersionDefinition.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/pySysvHash.cpp"
)
target_sources(pyLIEF PRIVATE ${LIEF_PYTHON_ELF_OBJECT_SRC})
add_subdirectory(NoteDetails)
@@ -1,11 +1,9 @@
set(LIEF_PYTHON_ELF_NOTE_DETAILS_SRC
"${CMAKE_CURRENT_LIST_DIR}/pyAndroidNote.cpp"
"${CMAKE_CURRENT_LIST_DIR}/pyNoteAbi.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/pyAndroidNote.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/pyNoteAbi.cpp"
)
target_sources(pyLIEF PRIVATE "${LIEF_PYTHON_ELF_NOTE_DETAILS_SRC}")
include("${CMAKE_CURRENT_LIST_DIR}/core/CMakeLists.txt")
add_subdirectory(core)
@@ -1,10 +1,10 @@
set(LIEF_PYTHON_ELF_NOTE_DETAILS_CORE
"${CMAKE_CURRENT_LIST_DIR}/pyCorePrPsInfo.cpp"
"${CMAKE_CURRENT_LIST_DIR}/pyCoreFile.cpp"
"${CMAKE_CURRENT_LIST_DIR}/pyCoreFileEntry.cpp"
"${CMAKE_CURRENT_LIST_DIR}/pyCorePrStatus.cpp"
"${CMAKE_CURRENT_LIST_DIR}/pyCoreAuxv.cpp"
"${CMAKE_CURRENT_LIST_DIR}/pyCoreSigInfo.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/pyCorePrPsInfo.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/pyCoreFile.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/pyCoreFileEntry.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/pyCorePrStatus.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/pyCoreAuxv.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/pyCoreSigInfo.cpp"
)
target_sources(pyLIEF PRIVATE "${LIEF_PYTHON_ELF_NOTE_DETAILS_CORE}")
@@ -15,31 +15,24 @@
*/
#include <string>
#include <sstream>
#include <nanobind/stl/string.h>
#include <nanobind/stl/map.h>
#include "pyELF.hpp"
#include "ELF/pyELF.hpp"
#include "LIEF/ELF/hash.hpp"
#include "LIEF/ELF/NoteDetails/core/CoreAuxv.hpp"
#include "LIEF/ELF/EnumToString.hpp"
#include "enums_wrapper.hpp"
#define PY_ENUM(x) LIEF::ELF::to_string(x), x
namespace LIEF {
namespace ELF {
template<class T>
using getter_t = T (CoreAuxv::*)(void) const;
template<class T>
using setter_t = void (CoreAuxv::*)(T);
namespace LIEF::ELF::py {
template<>
void create<CoreAuxv>(py::module& m) {
void create<CoreAuxv>(nb::module_& m) {
py::class_<CoreAuxv, NoteDetails> cls(m, "CoreAuxv");
nb::class_<CoreAuxv, NoteDetails> cls(m, "CoreAuxv");
LIEF::enum_<AUX_TYPE>(cls, "TYPES")
.value(PY_ENUM(AUX_TYPE::AT_NULL))
.value(PY_ENUM(AUX_TYPE::AT_IGNORE))
@@ -75,68 +68,44 @@ void create<CoreAuxv>(py::module& m) {
.value(PY_ENUM(AUX_TYPE::AT_L1D_CACHESHAPE));
cls
.def_property("values",
static_cast<getter_t<const CoreAuxv::val_context_t&>>(&CoreAuxv::values),
static_cast<setter_t<const CoreAuxv::val_context_t&>>(&CoreAuxv::values),
"Current values as a dictionarry for which keys are AUXV types")
.def_prop_rw("values",
nb::overload_cast<>(&CoreAuxv::values, nb::const_),
nb::overload_cast<const CoreAuxv::val_context_t&>(&CoreAuxv::values),
"Current values as a dictionary for which keys are AUXV types"_doc)
.def("get",
[] (const CoreAuxv& status, AUX_TYPE atype) -> py::object {
[] (const CoreAuxv& status, AUX_TYPE atype) -> nb::object {
bool error;
uint64_t val = status.get(atype, &error);
const uint64_t val = status.get(atype, &error);
if (error) {
return py::none();
return nb::none();
}
return py::int_(val);
return nb::int_(val);
},
"Return the type value",
"Return the type value"_doc,
"type"_a)
.def("set",
&CoreAuxv::set,
"Set type value",
"Set type value"_doc,
"type"_a, "value"_a)
.def("has",
&CoreAuxv::has,
"Check if a value is associated with the given type",
"Check if a value is associated with the given type"_doc,
"type"_a)
.def("__getitem__",
&CoreAuxv::operator[],
"",
py::return_value_policy::copy)
nb::rv_policy::copy)
.def("__setitem__",
[] (CoreAuxv& status, AUX_TYPE atype, uint64_t val) {
status.set(atype, val);
},
"")
.def("__contains__",
&CoreAuxv::has,
"")
.def("__eq__", &CoreAuxv::operator==)
.def("__ne__", &CoreAuxv::operator!=)
.def("__hash__",
[] (const CoreAuxv& note) {
return Hash::hash(note);
})
.def("__str__",
[] (const CoreAuxv& note)
{
std::ostringstream stream;
stream << note;
std::string str = stream.str();
return str;
});
.def("__contains__", &CoreAuxv::has)
LIEF_DEFAULT_STR(LIEF::ELF::CoreAuxv);
}
}
} // namespace ELF
} // namespace LIEF
@@ -16,61 +16,38 @@
#include <string>
#include <sstream>
#include <vector>
#include <nanobind/stl/string.h>
#include <nanobind/make_iterator.h>
#include <nanobind/stl/bind_vector.h>
#include "pyELF.hpp"
#include "ELF/pyELF.hpp"
#include "LIEF/ELF/hash.hpp"
#include "LIEF/ELF/NoteDetails/core/CoreFile.hpp"
namespace LIEF {
namespace ELF {
template<class T>
using getter_t = T (CoreFile::*)(void) const;
template<class T>
using setter_t = void (CoreFile::*)(T);
namespace LIEF::ELF::py {
template<>
void create<CoreFile>(py::module& m) {
void create<CoreFile>(nb::module_& m) {
py::class_<CoreFile, NoteDetails> cls(m, "CoreFile");
py::bind_vector<CoreFile::files_t>(cls, "files_t");
nb::class_<CoreFile, NoteDetails> cls(m, "CoreFile");
nb::bind_vector<CoreFile::files_t>(cls, "files_t");
cls
.def_property("files",
static_cast<getter_t<const CoreFile::files_t&>>(&CoreFile::files),
static_cast<setter_t<const CoreFile::files_t&>>(&CoreFile::files),
"List of files mapped in core. (list of " RST_CLASS_REF(lief.ELF.CoreFileEntry) ")")
.def_prop_rw("files",
nb::overload_cast<>(&CoreFile::files, nb::const_),
nb::overload_cast<const CoreFile::files_t&>(&CoreFile::files),
"List of files mapped in core. (list of " RST_CLASS_REF(lief.ELF.CoreFileEntry) ")"_doc)
.def("__len__",
&CoreFile::count,
"Number of files mapped in core"
)
"Number of files mapped in core"_doc)
.def("__iter__",
[] (const CoreFile& f) {
return py::make_iterator(std::begin(f), std::end(f));
},
py::keep_alive<0, 1>())
.def("__eq__", &CoreFile::operator==)
.def("__ne__", &CoreFile::operator!=)
.def("__hash__",
[] (const CoreFile& note) {
return Hash::hash(note);
})
.def("__str__",
[] (const CoreFile& note)
{
std::ostringstream stream;
stream << note;
std::string str = stream.str();
return str;
});
}
[&m] (const CoreFile& f) {
return nb::make_iterator(nanobind::type<CoreFile>(), "corefile_it",
std::begin(f), std::end(f));
}, nb::keep_alive<0, 1>())
LIEF_DEFAULT_STR(LIEF::ELF::CoreFile);
}
}
@@ -15,41 +15,31 @@
*/
#include <string>
#include <sstream>
#include <vector>
#include <nanobind/stl/string.h>
#include "pyELF.hpp"
#include "ELF/pyELF.hpp"
#include "LIEF/ELF/NoteDetails/core/CoreFile.hpp"
namespace LIEF {
namespace ELF {
namespace LIEF::ELF::py {
template<>
void create<CoreFileEntry>(py::module& m) {
void create<CoreFileEntry>(nb::module_& m) {
py::class_<CoreFileEntry>(m, "CoreFileEntry")
nb::class_<CoreFileEntry>(m, "CoreFileEntry")
.def_readwrite("start", &CoreFileEntry::start,
"Start address of mapped file")
.def_rw("start", &CoreFileEntry::start,
"Start address of mapped file"_doc)
.def_readwrite("end", &CoreFileEntry::end,
"End address of mapped file")
.def_rw("end", &CoreFileEntry::end,
"End address of mapped file"_doc)
.def_readwrite("file_ofs", &CoreFileEntry::file_ofs,
"Offset (in core) of mapped file")
.def_rw("file_ofs", &CoreFileEntry::file_ofs,
"Offset (in core) of mapped file"_doc)
.def_readwrite("path", &CoreFileEntry::path,
"Path of mapped file")
.def("__str__",
[] (const CoreFileEntry& entry)
{
std::ostringstream stream;
stream << entry;
return stream.str();
});
.def_rw("path", &CoreFileEntry::path,
"Path of mapped file"_doc)
LIEF_DEFAULT_STR(LIEF::ELF::CoreFileEntry);
}
}
}
@@ -15,90 +15,60 @@
*/
#include <string>
#include <sstream>
#include <nanobind/stl/string.h>
#include "pyELF.hpp"
#include "ELF/pyELF.hpp"
#include "LIEF/ELF/hash.hpp"
#include "LIEF/ELF/NoteDetails/core/CorePrPsInfo.hpp"
namespace LIEF {
namespace ELF {
template<class T>
using getter_t = T (CorePrPsInfo::*)(void) const;
template<class T>
using setter_t = void (CorePrPsInfo::*)(T);
namespace LIEF::ELF::py {
template<>
void create<CorePrPsInfo>(py::module& m) {
void create<CorePrPsInfo>(nb::module_& m) {
py::class_<CorePrPsInfo, NoteDetails>(m, "CorePrPsInfo")
nb::class_<CorePrPsInfo, NoteDetails>(m, "CorePrPsInfo")
.def_property("file_name",
static_cast<getter_t<std::string>>(&CorePrPsInfo::file_name),
static_cast<setter_t<const std::string&>>(&CorePrPsInfo::file_name),
"Process file name"
)
.def_prop_rw("file_name",
nb::overload_cast<>(&CorePrPsInfo::file_name, nb::const_),
nb::overload_cast<const std::string&>(&CorePrPsInfo::file_name),
"Process file name"_doc)
.def_property("flags",
static_cast<getter_t<uint64_t>>(&CorePrPsInfo::flags),
static_cast<setter_t<uint64_t>>(&CorePrPsInfo::flags),
"Process flags"
)
.def_prop_rw("flags",
nb::overload_cast<>(&CorePrPsInfo::flags, nb::const_),
nb::overload_cast<uint64_t>(&CorePrPsInfo::flags),
"Process flags"_doc)
.def_property("uid",
static_cast<getter_t<uint32_t>>(&CorePrPsInfo::uid),
static_cast<setter_t<uint32_t>>(&CorePrPsInfo::uid),
"Process User ID"
)
.def_prop_rw("uid",
nb::overload_cast<>(&CorePrPsInfo::uid, nb::const_),
nb::overload_cast<uint32_t>(&CorePrPsInfo::uid),
"Process User ID"_doc)
.def_property("gid",
static_cast<getter_t<uint32_t>>(&CorePrPsInfo::gid),
static_cast<setter_t<uint32_t>>(&CorePrPsInfo::gid),
"Process Group ID"
)
.def_prop_rw("gid",
nb::overload_cast<>(&CorePrPsInfo::gid, nb::const_),
nb::overload_cast<uint32_t>(&CorePrPsInfo::gid),
"Process Group ID"_doc)
.def_property("pid",
static_cast<getter_t<int32_t>>(&CorePrPsInfo::pid),
static_cast<setter_t<int32_t>>(&CorePrPsInfo::pid),
"Process ID"
)
.def_prop_rw("pid",
nb::overload_cast<>(&CorePrPsInfo::pid, nb::const_),
nb::overload_cast<int32_t>(&CorePrPsInfo::pid),
"Process ID"_doc)
.def_property("ppid",
static_cast<getter_t<int32_t>>(&CorePrPsInfo::ppid),
static_cast<setter_t<int32_t>>(&CorePrPsInfo::ppid),
"Process parent ID"
)
.def_prop_rw("ppid",
nb::overload_cast<>(&CorePrPsInfo::ppid, nb::const_),
nb::overload_cast<int32_t>(&CorePrPsInfo::ppid),
"Process parent ID"_doc)
.def_property("pgrp",
static_cast<getter_t<int32_t>>(&CorePrPsInfo::pgrp),
static_cast<setter_t<int32_t>>(&CorePrPsInfo::pgrp),
"Process session group ID"
)
.def_prop_rw("pgrp",
nb::overload_cast<>(&CorePrPsInfo::pgrp, nb::const_),
nb::overload_cast<int32_t>(&CorePrPsInfo::pgrp),
"Process session group ID"_doc)
.def_property("sid",
static_cast<getter_t<int32_t>>(&CorePrPsInfo::sid),
static_cast<setter_t<int32_t>>(&CorePrPsInfo::sid),
"Process session ID"
)
.def_prop_rw("sid",
nb::overload_cast<>(&CorePrPsInfo::sid, nb::const_),
nb::overload_cast<int32_t>(&CorePrPsInfo::sid),
"Process session ID"_doc)
.def("__eq__", &CorePrPsInfo::operator==)
.def("__ne__", &CorePrPsInfo::operator!=)
.def("__hash__",
[] (const CorePrPsInfo& note) {
return Hash::hash(note);
})
.def("__str__",
[] (const CorePrPsInfo& note)
{
std::ostringstream stream;
stream << note;
std::string str = stream.str();
return str;
});
LIEF_DEFAULT_STR(LIEF::ELF::CorePrPsInfo);
}
}
}
@@ -15,165 +15,141 @@
*/
#include <string>
#include <sstream>
#include <nanobind/stl/string.h>
#include <nanobind/stl/map.h>
#include "pyELF.hpp"
#include "ELF/pyELF.hpp"
#include "LIEF/ELF/hash.hpp"
#include "LIEF/ELF/NoteDetails/core/CorePrStatus.hpp"
#include "LIEF/ELF/EnumToString.hpp"
#include "enums_wrapper.hpp"
#define PY_ENUM(x) LIEF::ELF::to_string(x), x
namespace LIEF {
namespace ELF {
template<class T>
using getter_t = T (CorePrStatus::*)(void) const;
template<class T>
using setter_t = void (CorePrStatus::*)(T);
namespace LIEF::ELF::py {
template<>
void create<CorePrStatus>(py::module& m) {
void create<CorePrStatus>(nb::module_& m) {
py::class_<CorePrStatus, NoteDetails> cls(m, "CorePrStatus");
nb::class_<CorePrStatus, NoteDetails> cls(m, "CorePrStatus");
py::class_<CorePrStatus::timeval_t>(cls, "timeval")
.def_readwrite("sec", &CorePrStatus::timeval_t::sec)
.def_readwrite("usec", &CorePrStatus::timeval_t::usec);
nb::class_<CorePrStatus::timeval_t>(cls, "timeval")
.def_rw("sec", &CorePrStatus::timeval_t::sec)
.def_rw("usec", &CorePrStatus::timeval_t::usec);
py::class_<CorePrStatus::siginfo_t>(cls, "siginfo_t")
.def_readwrite("sicode", &CorePrStatus::siginfo_t::si_code)
.def_readwrite("errno", &CorePrStatus::siginfo_t::si_errno)
.def_readwrite("signo", &CorePrStatus::siginfo_t::si_signo);
nb::class_<CorePrStatus::siginfo_t>(cls, "siginfo_t")
.def_rw("sicode", &CorePrStatus::siginfo_t::si_code)
.def_rw("errno", &CorePrStatus::siginfo_t::si_errno)
.def_rw("signo", &CorePrStatus::siginfo_t::si_signo);
cls
.def_property("siginfo",
static_cast<getter_t<const CorePrStatus::siginfo_t&>>(&CorePrStatus::siginfo),
static_cast<setter_t<const CorePrStatus::siginfo_t&>>(&CorePrStatus::siginfo),
"Info associated with the signal")
.def_prop_rw("siginfo",
nb::overload_cast<>(&CorePrStatus::siginfo, nb::const_),
nb::overload_cast<const CorePrStatus::siginfo_t&>(&CorePrStatus::siginfo),
"Info associated with the signal"_doc)
.def_property("current_sig",
static_cast<getter_t<uint16_t>>(&CorePrStatus::current_sig),
static_cast<setter_t<uint16_t>>(&CorePrStatus::current_sig),
"Current Signal")
.def_prop_rw("current_sig",
nb::overload_cast<>(&CorePrStatus::current_sig, nb::const_),
nb::overload_cast<uint16_t>(&CorePrStatus::current_sig),
"Current Signal"_doc)
.def_property("sigpend",
static_cast<getter_t<uint64_t>>(&CorePrStatus::sigpend),
static_cast<setter_t<uint64_t>>(&CorePrStatus::sigpend),
"Set of pending signals")
.def_prop_rw("sigpend",
nb::overload_cast<>(&CorePrStatus::sigpend, nb::const_),
nb::overload_cast<uint64_t>(&CorePrStatus::sigpend),
"Set of pending signals"_doc)
.def_property("sighold",
static_cast<getter_t<uint64_t>>(&CorePrStatus::sighold),
static_cast<setter_t<uint64_t>>(&CorePrStatus::sighold),
"Set of held signals")
.def_prop_rw("sighold",
nb::overload_cast<>(&CorePrStatus::sighold, nb::const_),
nb::overload_cast<uint64_t>(&CorePrStatus::sighold),
"Set of held signals"_doc)
.def_property("pid",
static_cast<getter_t<int32_t>>(&CorePrStatus::pid),
static_cast<setter_t<int32_t>>(&CorePrStatus::pid),
"Process ID")
.def_prop_rw("pid",
nb::overload_cast<>(&CorePrStatus::pid, nb::const_),
nb::overload_cast<int32_t>(&CorePrStatus::pid),
"Process ID"_doc)
.def_property("ppid",
static_cast<getter_t<int32_t>>(&CorePrStatus::ppid),
static_cast<setter_t<int32_t>>(&CorePrStatus::ppid),
"Process parent ID")
.def_prop_rw("ppid",
nb::overload_cast<>(&CorePrStatus::ppid, nb::const_),
nb::overload_cast<int32_t>(&CorePrStatus::ppid),
"Process parent ID"_doc)
.def_property("pgrp",
static_cast<getter_t<int32_t>>(&CorePrStatus::pgrp),
static_cast<setter_t<int32_t>>(&CorePrStatus::pgrp),
"Process group ID")
.def_prop_rw("pgrp",
nb::overload_cast<>(&CorePrStatus::pgrp, nb::const_),
nb::overload_cast<int32_t>(&CorePrStatus::pgrp),
"Process group ID"_doc)
.def_property("sid",
static_cast<getter_t<int32_t>>(&CorePrStatus::sid),
static_cast<setter_t<int32_t>>(&CorePrStatus::sid),
"Process session ID")
.def_prop_rw("sid",
nb::overload_cast<>(&CorePrStatus::sid, nb::const_),
nb::overload_cast<int32_t>(&CorePrStatus::sid),
"Process session ID"_doc)
.def_property("utime",
static_cast<getter_t<CorePrStatus::timeval_t>>(&CorePrStatus::utime),
static_cast<setter_t<CorePrStatus::timeval_t>>(&CorePrStatus::utime),
"User time (" RST_CLASS_REF(lief.ELF.CorePrStatus.timeval) ")")
.def_prop_rw("utime",
nb::overload_cast<>(&CorePrStatus::utime, nb::const_),
nb::overload_cast<CorePrStatus::timeval_t>(&CorePrStatus::utime),
"User time (" RST_CLASS_REF(lief.ELF.CorePrStatus.timeval) ")"_doc)
.def_property("utime",
static_cast<getter_t<CorePrStatus::timeval_t>>(&CorePrStatus::utime),
static_cast<setter_t<CorePrStatus::timeval_t>>(&CorePrStatus::utime),
"User time (" RST_CLASS_REF(lief.ELF.CorePrStatus.timeval) ")")
.def_prop_rw("utime",
nb::overload_cast<>(&CorePrStatus::utime, nb::const_),
nb::overload_cast<CorePrStatus::timeval_t>(&CorePrStatus::utime),
"User time (" RST_CLASS_REF(lief.ELF.CorePrStatus.timeval) ")"_doc)
.def_property("stime",
static_cast<getter_t<CorePrStatus::timeval_t>>(&CorePrStatus::stime),
static_cast<setter_t<CorePrStatus::timeval_t>>(&CorePrStatus::stime),
"System time (" RST_CLASS_REF(lief.ELF.CorePrStatus.timeval) ")")
.def_prop_rw("stime",
nb::overload_cast<>(&CorePrStatus::stime, nb::const_),
nb::overload_cast<CorePrStatus::timeval_t>(&CorePrStatus::stime),
"System time (" RST_CLASS_REF(lief.ELF.CorePrStatus.timeval) ")"_doc)
.def_property("cutime",
static_cast<getter_t<CorePrStatus::timeval_t>>(&CorePrStatus::cutime),
static_cast<setter_t<CorePrStatus::timeval_t>>(&CorePrStatus::cutime),
"Cumulative user time (" RST_CLASS_REF(lief.ELF.CorePrStatus.timeval) ")")
.def_prop_rw("cutime",
nb::overload_cast<>(&CorePrStatus::cutime, nb::const_),
nb::overload_cast<CorePrStatus::timeval_t>(&CorePrStatus::cutime),
"Cumulative user time (" RST_CLASS_REF(lief.ELF.CorePrStatus.timeval) ")"_doc)
.def_property("cstime",
static_cast<getter_t<CorePrStatus::timeval_t>>(&CorePrStatus::cstime),
static_cast<setter_t<CorePrStatus::timeval_t>>(&CorePrStatus::cstime),
"Cumulative system time (" RST_CLASS_REF(lief.ELF.CorePrStatus.timeval) ")")
.def_prop_rw("cstime",
nb::overload_cast<>(&CorePrStatus::cstime, nb::const_),
nb::overload_cast<CorePrStatus::timeval_t>(&CorePrStatus::cstime),
"Cumulative system time (" RST_CLASS_REF(lief.ELF.CorePrStatus.timeval) ")"_doc)
.def_property("register_context",
static_cast<getter_t<const CorePrStatus::reg_context_t&>>(&CorePrStatus::reg_context),
static_cast<setter_t<const CorePrStatus::reg_context_t&>>(&CorePrStatus::reg_context),
.def_prop_rw("register_context",
nb::overload_cast<>(&CorePrStatus::reg_context, nb::const_),
nb::overload_cast<const CorePrStatus::reg_context_t&>(&CorePrStatus::reg_context),
"Current registers state as a dictionary where the keys are "
RST_CLASS_REF(lief.ELF.CorePrStatus.REGISTERS) " and the values the register's value")
RST_CLASS_REF(lief.ELF.CorePrStatus.REGISTERS) " and the values the register's value"_doc)
.def("get",
[] (const CorePrStatus& status, CorePrStatus::REGISTERS reg) -> py::object {
[] (const CorePrStatus& status, CorePrStatus::REGISTERS reg) -> nb::object {
bool error;
uint64_t val = status.get(reg, &error);
const uint64_t val = status.get(reg, &error);
if (error) {
return py::none();
return nb::none();
}
return py::int_(val);
return nb::int_(val);
},
"Return the register value",
"Return the register value"_doc,
"register"_a)
.def("set",
&CorePrStatus::set,
"Set register value",
"Set register value"_doc,
"register"_a, "value"_a)
.def("has",
&CorePrStatus::has,
"Check if a value is associated with the given register",
"Check if a value is associated with the given register"_doc,
"register"_a)
.def("__getitem__",
&CorePrStatus::operator[],
"",
py::return_value_policy::copy)
nb::rv_policy::copy)
.def("__setitem__",
[] (CorePrStatus& status, CorePrStatus::REGISTERS reg, uint64_t val) {
status.set(reg, val);
},
"")
.def("__contains__",
&CorePrStatus::has,
"")
.def("__eq__", &CorePrStatus::operator==)
.def("__ne__", &CorePrStatus::operator!=)
.def("__hash__",
[] (const CorePrStatus& note) {
return Hash::hash(note);
})
.def("__str__",
[] (const CorePrStatus& note)
{
std::ostringstream stream;
stream << note;
std::string str = stream.str();
return str;
});
.def("__contains__",
&CorePrStatus::has)
LIEF_DEFAULT_STR(LIEF::ELF::CorePrStatus);
LIEF::enum_<CorePrStatus::REGISTERS>(cls, "REGISTERS")
@@ -271,7 +247,5 @@ void create<CorePrStatus>(py::module& m) {
.value(PY_ENUM(CorePrStatus::REGISTERS::AARCH64_X31))
.value(PY_ENUM(CorePrStatus::REGISTERS::AARCH64_PC))
.value(PY_ENUM(CorePrStatus::REGISTERS::AARCH64__));
}
} // namespace ELF
} // namespace LIEF
}
@@ -15,59 +15,34 @@
*/
#include <string>
#include <sstream>
#include <nanobind/stl/string.h>
#include "pyELF.hpp"
#include "ELF/pyELF.hpp"
#include "LIEF/ELF/hash.hpp"
#include "LIEF/ELF/NoteDetails/core/CoreSigInfo.hpp"
namespace LIEF {
namespace ELF {
template<class T>
using getter_t = T (CoreSigInfo::*)(void) const;
template<class T>
using setter_t = void (CoreSigInfo::*)(T);
namespace LIEF::ELF::py {
template<>
void create<CoreSigInfo>(py::module& m) {
void create<CoreSigInfo>(nb::module_& m) {
py::class_<CoreSigInfo, NoteDetails>(m, "CoreSigInfo")
nb::class_<CoreSigInfo, NoteDetails>(m, "CoreSigInfo")
.def_property("signo",
static_cast<getter_t<int32_t>>(&CoreSigInfo::signo),
static_cast<setter_t<int32_t>>(&CoreSigInfo::signo),
"Signal number")
.def_prop_rw("signo",
nb::overload_cast<>(&CoreSigInfo::signo, nb::const_),
nb::overload_cast<int32_t>(&CoreSigInfo::signo),
"Signal number"_doc)
.def_property("sigcode",
static_cast<getter_t<int32_t>>(&CoreSigInfo::sigcode),
static_cast<setter_t<int32_t>>(&CoreSigInfo::sigcode),
"Signal code")
.def_property("sigerrno",
static_cast<getter_t<int32_t>>(&CoreSigInfo::sigerrno),
static_cast<setter_t<int32_t>>(&CoreSigInfo::sigerrno),
"If non-zero, an errno value associated with this signal")
.def("__eq__", &CoreSigInfo::operator==)
.def("__ne__", &CoreSigInfo::operator!=)
.def("__hash__",
[] (const CoreSigInfo& note) {
return Hash::hash(note);
})
.def("__str__",
[] (const CoreSigInfo& note)
{
std::ostringstream stream;
stream << note;
std::string str = stream.str();
return str;
});
.def_prop_rw("sigcode",
nb::overload_cast<>(&CoreSigInfo::sigcode, nb::const_),
nb::overload_cast<int32_t>(&CoreSigInfo::sigcode),
"Signal code"_doc)
.def_prop_rw("sigerrno",
nb::overload_cast<>(&CoreSigInfo::sigerrno, nb::const_),
nb::overload_cast<int32_t>(&CoreSigInfo::sigerrno),
"If non-zero, an errno value associated with this signal"_doc)
LIEF_DEFAULT_STR(LIEF::ELF::CoreSigInfo);
}
}
} // namespace ELF
} // namespace LIEF
@@ -15,60 +15,33 @@
*/
#include <string>
#include <sstream>
#include <nanobind/stl/string.h>
#include "pyELF.hpp"
#include "ELF/pyELF.hpp"
#include "LIEF/ELF/hash.hpp"
#include "LIEF/ELF/NoteDetails/AndroidNote.hpp"
namespace LIEF {
namespace ELF {
template<class T>
using getter_t = T (AndroidNote::*)(void) const;
template<class T>
using setter_t = void (AndroidNote::*)(T);
namespace LIEF::ELF::py {
template<>
void create<AndroidNote>(py::module& m) {
void create<AndroidNote>(nb::module_& m) {
nb::class_<AndroidNote, NoteDetails>(m, "AndroidNote")
.def_prop_rw("sdk_version",
nb::overload_cast<>(&AndroidNote::sdk_version, nb::const_),
nb::overload_cast<uint32_t>(&AndroidNote::sdk_version),
"Target SDK platform"_doc)
py::class_<AndroidNote, NoteDetails>(m, "AndroidNote")
.def_prop_rw("ndk_version",
nb::overload_cast<>(&AndroidNote::ndk_version, nb::const_),
nb::overload_cast<const std::string&>(&AndroidNote::ndk_version),
"Android NDK version used to build the current binary"_doc)
.def_property("sdk_version",
static_cast<getter_t<uint32_t>>(&AndroidNote::sdk_version),
static_cast<setter_t<uint32_t>>(&AndroidNote::sdk_version),
"Target SDK platform"
)
.def_prop_rw("ndk_build_number",
nb::overload_cast<>(&AndroidNote::ndk_build_number, nb::const_),
nb::overload_cast<const std::string&>(&AndroidNote::ndk_build_number),
"Android NDK build number"_doc)
.def_property("ndk_version",
static_cast<getter_t<std::string>>(&AndroidNote::ndk_version),
static_cast<setter_t<const std::string&>>(&AndroidNote::ndk_version),
"Android NDK version used to build the current binary"
)
.def_property("ndk_build_number",
static_cast<getter_t<std::string>>(&AndroidNote::ndk_build_number),
static_cast<setter_t<const std::string&>>(&AndroidNote::ndk_build_number),
"Android NDK build number"
)
.def("__eq__", &AndroidNote::operator==)
.def("__ne__", &AndroidNote::operator!=)
.def("__hash__",
[] (const AndroidNote& note) {
return Hash::hash(note);
})
.def("__str__",
[] (const AndroidNote& note)
{
std::ostringstream stream;
stream << note;
std::string str = stream.str();
return str;
});
LIEF_DEFAULT_STR(LIEF::ELF::AndroidNote);
}
}
}
@@ -15,52 +15,27 @@
*/
#include <string>
#include <sstream>
#include <nanobind/stl/string.h>
#include <nanobind/stl/array.h>
#include "pyELF.hpp"
#include "ELF/pyELF.hpp"
#include "LIEF/ELF/hash.hpp"
#include "LIEF/ELF/NoteDetails/NoteAbi.hpp"
namespace LIEF {
namespace ELF {
template<class T>
using getter_t = T (NoteAbi::*)(void) const;
template<class T>
using setter_t = void (NoteAbi::*)(T);
namespace LIEF::ELF::py {
template<>
void create<NoteAbi>(py::module& m) {
void create<NoteAbi>(nb::module_& m) {
nb::class_<NoteAbi, NoteDetails>(m, "NoteAbi")
py::class_<NoteAbi, NoteDetails>(m, "NoteAbi")
.def_prop_ro("abi",
nb::overload_cast<>(&NoteAbi::abi, nb::const_),
"Return the target " RST_CLASS_REF(lief.ELF.NOTE_ABIS) ""_doc)
.def_property_readonly("abi",
static_cast<getter_t<NOTE_ABIS>>(&NoteAbi::abi),
"Return the target " RST_CLASS_REF(lief.ELF.NOTE_ABIS) ""
)
.def_property_readonly("version",
static_cast<getter_t<NoteAbi::version_t>>(&NoteAbi::version),
"Return the target version as ``(Major, Minor, Patch)``"
)
.def("__eq__", &NoteAbi::operator==)
.def("__ne__", &NoteAbi::operator!=)
.def("__hash__",
[] (const NoteAbi& note) {
return Hash::hash(note);
})
.def("__str__",
[] (const NoteAbi& note)
{
std::ostringstream stream;
stream << note;
std::string str = stream.str();
return str;
});
}
.def_prop_ro("version",
nb::overload_cast<>(&NoteAbi::version, nb::const_),
"Return the target version as ``(Major, Minor, Patch)``"_doc)
LIEF_DEFAULT_STR(LIEF::ELF::NoteAbi);
}
}
File diff suppressed because it is too large Load Diff
+41 -40
View File
@@ -14,69 +14,70 @@
* limitations under the License.
*/
#include <nanobind/stl/string.h>
#include <nanobind/stl/vector.h>
#include "pyELF.hpp"
#include "ELF/pyELF.hpp"
#include "LIEF/ELF/Binary.hpp"
#include "LIEF/ELF/Builder.hpp"
namespace LIEF {
namespace ELF {
namespace LIEF::ELF::py {
template<>
void create<Builder>(py::module& m) {
py::class_<Builder> builder(m, "Builder",
void create<Builder>(nb::module_& m) {
nb::class_<Builder> builder(m, "Builder",
R"delim(
Class which takes an :class:`lief.ELF.Binary` object and reconstructs a valid binary
)delim");
)delim"_doc);
py::class_<Builder::config_t>(builder, "config_t",
"Interface to tweak the " RST_CLASS_REF(lief.ELF.Builder) "")
.def(py::init<>())
.def_readwrite("force_relocate", &Builder::config_t::force_relocate,
"Force to relocate all the ELF structures that can be relocated (mostly for testing)")
nb::class_<Builder::config_t>(builder, "config_t",
"Interface to tweak the " RST_CLASS_REF(lief.ELF.Builder) ""_doc)
.def(nb::init<>())
.def_rw("force_relocate", &Builder::config_t::force_relocate,
"Force to relocate all the ELF structures that can be relocated (mostly for testing)"_doc)
.def_readwrite("dt_hash", &Builder::config_t::dt_hash)
.def_readwrite("dyn_str", &Builder::config_t::dyn_str)
.def_readwrite("dynamic_section", &Builder::config_t::dynamic_section)
.def_readwrite("fini_array", &Builder::config_t::fini_array)
.def_readwrite("init_array", &Builder::config_t::init_array)
.def_readwrite("interpreter", &Builder::config_t::interpreter)
.def_readwrite("jmprel", &Builder::config_t::jmprel)
.def_readwrite("notes", &Builder::config_t::notes)
.def_readwrite("preinit_array", &Builder::config_t::preinit_array)
.def_readwrite("rela", &Builder::config_t::rela)
.def_readwrite("static_symtab", &Builder::config_t::static_symtab)
.def_readwrite("sym_verdef", &Builder::config_t::sym_verdef)
.def_readwrite("sym_verneed", &Builder::config_t::sym_verneed)
.def_readwrite("sym_versym", &Builder::config_t::sym_versym)
.def_readwrite("symtab", &Builder::config_t::symtab);
.def_rw("dt_hash", &Builder::config_t::dt_hash)
.def_rw("dyn_str", &Builder::config_t::dyn_str)
.def_rw("dynamic_section", &Builder::config_t::dynamic_section)
.def_rw("fini_array", &Builder::config_t::fini_array)
.def_rw("init_array", &Builder::config_t::init_array)
.def_rw("interpreter", &Builder::config_t::interpreter)
.def_rw("jmprel", &Builder::config_t::jmprel)
.def_rw("notes", &Builder::config_t::notes)
.def_rw("preinit_array", &Builder::config_t::preinit_array)
.def_rw("rela", &Builder::config_t::rela)
.def_rw("static_symtab", &Builder::config_t::static_symtab)
.def_rw("sym_verdef", &Builder::config_t::sym_verdef)
.def_rw("sym_verneed", &Builder::config_t::sym_verneed)
.def_rw("sym_versym", &Builder::config_t::sym_versym)
.def_rw("symtab", &Builder::config_t::symtab);
builder
.def(py::init<Binary&>(),
"Constructor that takes a " RST_CLASS_REF(lief.ELF.Binary) "",
.def(nb::init<Binary&>(),
"Constructor that takes a " RST_CLASS_REF(lief.ELF.Binary) ""_doc,
"elf_binary"_a)
.def("build",
static_cast<void (Builder::*)(void)>(&Builder::build),
"Perform the build of the provided ELF binary")
[] (Builder& self) {
return self.build();
},
"Perform the build of the provided ELF binary"_doc)
.def_property("config",
&Builder::config,
&Builder::set_config,
"Tweak the ELF builder with the provided config parameter",
py::return_value_policy::reference_internal)
.def_prop_rw("config", &Builder::config, &Builder::set_config,
"Tweak the ELF builder with the provided config parameter"_doc,
nb::rv_policy::reference_internal)
.def("write",
static_cast<void (Builder::*)(const std::string&) const>(&Builder::write),
"Write the build result into the ``output`` file",
nb::overload_cast<const std::string&>(&Builder::write, nb::const_),
"Write the build result into the ``output`` file"_doc,
"output"_a)
.def("get_build",
&Builder::get_build,
"Return the build result as a ``list`` of bytes",
py::return_value_policy::reference_internal);
"Return the build result as a ``list`` of bytes"_doc,
nb::rv_policy::reference_internal);
}
}
}
+19 -46
View File
@@ -13,73 +13,46 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <string>
#include <sstream>
#include <nanobind/stl/string.h>
#include "pyELF.hpp"
#include "ELF/pyELF.hpp"
#include "LIEF/ELF/DynamicEntry.hpp"
#include "LIEF/ELF/hash.hpp"
namespace LIEF {
namespace ELF {
template<class T>
using getter_t = T (DynamicEntry::*)(void) const;
template<class T>
using setter_t = void (DynamicEntry::*)(T);
namespace LIEF::ELF::py {
template<>
void create<DynamicEntry>(py::module& m) {
// DynamicEntry object
py::class_<DynamicEntry, LIEF::Object>(m, "DynamicEntry",
void create<DynamicEntry>(nb::module_& m) {
nb::class_<DynamicEntry, LIEF::Object>(m, "DynamicEntry",
R"delim(
Class which represents an entry in the dynamic table
These entries are located in the ``.dynamic`` section or the ``PT_DYNAMIC`` segment
)delim")
.def(py::init<>(),
"Default constructor")
)delim"_doc)
.def(nb::init<>(),
"Default constructor"_doc)
.def(py::init<DYNAMIC_TAGS, uint64_t>(),
"Constructor from a " RST_CLASS_REF(lief.ELF.DYNAMIC_TAGS) " and value",
.def(nb::init<DYNAMIC_TAGS, uint64_t>(),
"Constructor from a " RST_CLASS_REF(lief.ELF.DYNAMIC_TAGS) " and value"_doc,
"tag"_a, "value"_a)
.def_property("tag",
static_cast<getter_t<DYNAMIC_TAGS>>(&DynamicEntry::tag),
static_cast<setter_t<DYNAMIC_TAGS>>(&DynamicEntry::tag),
"Return the entry's " RST_CLASS_REF(lief.ELF.DYNAMIC_TAGS) " which represent the entry type")
.def_prop_rw("tag",
nb::overload_cast<>(&DynamicEntry::tag, nb::const_),
nb::overload_cast<DYNAMIC_TAGS>(&DynamicEntry::tag),
"Return the entry's " RST_CLASS_REF(lief.ELF.DYNAMIC_TAGS) " which represent the entry type"_doc)
.def_property("value",
static_cast<getter_t<uint64_t>>(&DynamicEntry::value),
static_cast<setter_t<uint64_t>>(&DynamicEntry::value),
.def_prop_rw("value",
nb::overload_cast<>(&DynamicEntry::value, nb::const_),
nb::overload_cast<uint64_t>(&DynamicEntry::value),
R"delim(
Return the entry's value
The meaning of the value strongly depends on the tag.
It can be an offset, an index, a flag, ...
)delim")
)delim"_doc)
.def("__eq__", &DynamicEntry::operator==)
.def("__ne__", &DynamicEntry::operator!=)
.def("__hash__",
[] (const DynamicEntry& entry) {
return Hash::hash(entry);
})
.def("__str__",
[] (const DynamicEntry& dynamicEntry)
{
std::ostringstream stream;
stream << dynamicEntry;
std::string str = stream.str();
return str;
});
LIEF_DEFAULT_STR(LIEF::ELF::DynamicEntry);
}
}
}
@@ -12,33 +12,24 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
*/
#include <string>
#include <sstream>
#include "pyELF.hpp"
#include <nanobind/operators.h>
#include <nanobind/stl/string.h>
#include <nanobind/stl/vector.h>
#include "LIEF/ELF/hash.hpp"
#include "ELF/pyELF.hpp"
#include "LIEF/ELF/DynamicEntryArray.hpp"
#include "LIEF/ELF/DynamicEntry.hpp"
namespace LIEF {
namespace ELF {
template<class T>
using getter_t = T (DynamicEntryArray::*)(void) const;
template<class T>
using setter_t = void (DynamicEntryArray::*)(T);
namespace LIEF::ELF::py {
template<>
void create<DynamicEntryArray>(py::module& m) {
// Dynamic Entry Array object
py::class_<DynamicEntryArray, DynamicEntry>(m, "DynamicEntryArray",
void create<DynamicEntryArray>(nb::module_& m) {
nb::class_<DynamicEntryArray, DynamicEntry>(m, "DynamicEntryArray",
R"delim(
Class that represent an Array in the dynamic table.
This entry is associated with constructors:
@@ -48,66 +39,49 @@ void create<DynamicEntryArray>(py::module& m) {
The underlying values are 64-bits integers to cover both:
ELF32 and ELF64 binaries.
)delim")
.def(py::init<>())
)delim"_doc)
.def(nb::init<>())
.def(py::init<DYNAMIC_TAGS, uint64_t>(),
"Constructor with " RST_CLASS_REF(lief.ELF.DYNAMIC_TAGS) " and value",
.def(nb::init<DYNAMIC_TAGS, uint64_t>(),
"Constructor with " RST_CLASS_REF(lief.ELF.DYNAMIC_TAGS) " and value"_doc,
"tag"_a, "value"_a)
.def_property("array",
static_cast<std::vector<uint64_t>& (DynamicEntryArray::*)()>(&DynamicEntryArray::array),
static_cast<setter_t<const std::vector<uint64_t>&>>(&DynamicEntryArray::array),
"Return the array as a list of intergers",
py::return_value_policy::reference)
.def_prop_rw("array",
nb::overload_cast<>(&DynamicEntryArray::array, nb::const_),
nb::overload_cast<const std::vector<uint64_t>&>(&DynamicEntryArray::array),
"Return the array as a list of intergers"_doc,
nb::rv_policy::reference_internal)
.def("insert",
&DynamicEntryArray::insert,
"Insert the given ``function`` at ``pos``",
"Insert the given ``function`` at ``pos``"_doc,
"pos"_a, "function"_a,
py::return_value_policy::reference)
nb::rv_policy::reference_internal)
.def("append",
&DynamicEntryArray::append,
"Append the given ``function`` ",
"Append the given ``function`` "_doc,
"function"_a,
py::return_value_policy::reference)
nb::rv_policy::reference_internal)
.def("remove",
&DynamicEntryArray::remove,
"Remove the given ``function`` ",
"Remove the given ``function`` "_doc,
"function"_a,
py::return_value_policy::reference)
nb::rv_policy::reference_internal)
.def(py::self += uint64_t())
.def(py::self -= uint64_t())
.def(nb::self += uint64_t())
.def(nb::self -= uint64_t())
.def("__getitem__",
static_cast<uint64_t& (DynamicEntryArray::*)(size_t)>(&DynamicEntryArray::operator[]),
py::return_value_policy::reference)
nb::overload_cast<size_t>(&DynamicEntryArray::operator[]),
nb::rv_policy::reference_internal)
.def("__len__",
&DynamicEntryArray::size)
.def("__eq__", &DynamicEntryArray::operator==)
.def("__ne__", &DynamicEntryArray::operator!=)
.def("__hash__",
[] (const DynamicEntryArray& entry) {
return Hash::hash(entry);
})
.def("__str__",
[] (const DynamicEntryArray& entry)
{
std::ostringstream stream;
stream << entry;
std::string str = stream.str();
return str;
});
LIEF_DEFAULT_STR(LIEF::ELF::DynamicEntryArray);
}
}
}
@@ -13,104 +13,79 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "pyELF.hpp"
#include <string>
#include <sstream>
#include "LIEF/ELF/hash.hpp"
#include <nanobind/operators.h>
#include <nanobind/stl/string.h>
#include <nanobind/stl/set.h>
#include "ELF/pyELF.hpp"
#include "LIEF/ELF/DynamicEntryFlags.hpp"
#include "LIEF/ELF/DynamicEntry.hpp"
#include <string>
#include <sstream>
namespace LIEF {
namespace ELF {
template<class T>
using getter_t = T (DynamicEntryFlags::*)(void) const;
template<class T>
using setter_t = void (DynamicEntryFlags::*)(T);
namespace LIEF::ELF::py {
template<>
void create<DynamicEntryFlags>(py::module& m) {
void create<DynamicEntryFlags>(nb::module_& m) {
nb::class_<DynamicEntryFlags, DynamicEntry>(m, "DynamicEntryFlags")
.def(nb::init<>())
py::class_<DynamicEntryFlags, DynamicEntry>(m, "DynamicEntryFlags")
.def(py::init<>())
.def(py::init<DYNAMIC_TAGS, uint64_t>(),
"Constructor with " RST_CLASS_REF(lief.ELF.DYNAMIC_TAGS) " and value",
.def(nb::init<DYNAMIC_TAGS, uint64_t>(),
"Constructor with " RST_CLASS_REF(lief.ELF.DYNAMIC_TAGS) " and value"_doc,
"tag"_a, "value"_a)
.def_property_readonly("flags",
.def_prop_ro("flags",
&DynamicEntryFlags::flags,
"Return list of " RST_CLASS_REF(lief.ELF.DYNAMIC_FLAGS) " or " RST_CLASS_REF(lief.ELF.DYNAMIC_FLAGS_1) " (integer)",
py::return_value_policy::move)
"Return list of " RST_CLASS_REF(lief.ELF.DYNAMIC_FLAGS) " or " RST_CLASS_REF(lief.ELF.DYNAMIC_FLAGS_1) " (integer)"_doc,
nb::rv_policy::move)
.def("has",
static_cast<bool (DynamicEntryFlags::*)(DYNAMIC_FLAGS) const>(&DynamicEntryFlags::has),
"Check if this entry contains the given " RST_CLASS_REF(lief.ELF.DYNAMIC_FLAGS) "",
nb::overload_cast<DYNAMIC_FLAGS>(&DynamicEntryFlags::has, nb::const_),
"Check if this entry contains the given " RST_CLASS_REF(lief.ELF.DYNAMIC_FLAGS) ""_doc,
"flag"_a)
.def("has",
static_cast<bool (DynamicEntryFlags::*)(DYNAMIC_FLAGS_1) const>(&DynamicEntryFlags::has),
"Check if this entry contains the given " RST_CLASS_REF(lief.ELF.DYNAMIC_FLAGS_1) "",
nb::overload_cast<DYNAMIC_FLAGS_1>(&DynamicEntryFlags::has, nb::const_),
"Check if this entry contains the given " RST_CLASS_REF(lief.ELF.DYNAMIC_FLAGS_1) ""_doc,
"flag"_a)
.def("add",
static_cast<void (DynamicEntryFlags::*)(DYNAMIC_FLAGS)>(&DynamicEntryFlags::add),
"Add the given " RST_CLASS_REF(lief.ELF.DYNAMIC_FLAGS) "",
nb::overload_cast<DYNAMIC_FLAGS>(&DynamicEntryFlags::add),
"Add the given " RST_CLASS_REF(lief.ELF.DYNAMIC_FLAGS) ""_doc,
"flag"_a)
.def("add",
static_cast<void (DynamicEntryFlags::*)(DYNAMIC_FLAGS_1)>(&DynamicEntryFlags::add),
"Add the given " RST_CLASS_REF(lief.ELF.DYNAMIC_FLAGS_1) "",
nb::overload_cast<DYNAMIC_FLAGS_1>(&DynamicEntryFlags::add),
"Add the given " RST_CLASS_REF(lief.ELF.DYNAMIC_FLAGS_1) ""_doc,
"flag"_a)
.def("remove",
static_cast<void (DynamicEntryFlags::*)(DYNAMIC_FLAGS)>(&DynamicEntryFlags::remove),
"Remove the given " RST_CLASS_REF(lief.ELF.DYNAMIC_FLAGS) "",
nb::overload_cast<DYNAMIC_FLAGS>(&DynamicEntryFlags::remove),
"Remove the given " RST_CLASS_REF(lief.ELF.DYNAMIC_FLAGS) ""_doc,
"flag"_a)
.def("remove",
static_cast<void (DynamicEntryFlags::*)(DYNAMIC_FLAGS_1)>(&DynamicEntryFlags::remove),
"Remove the given " RST_CLASS_REF(lief.ELF.DYNAMIC_FLAGS_1) "",
nb::overload_cast<DYNAMIC_FLAGS_1>(&DynamicEntryFlags::remove),
"Remove the given " RST_CLASS_REF(lief.ELF.DYNAMIC_FLAGS_1) ""_doc,
"flag"_a)
.def(nb::self += DYNAMIC_FLAGS())
.def(nb::self += DYNAMIC_FLAGS_1())
.def("__eq__", &DynamicEntryFlags::operator==)
.def("__ne__", &DynamicEntryFlags::operator!=)
.def("__hash__",
[] (const DynamicEntryFlags& entry) {
return Hash::hash(entry);
})
.def(py::self += DYNAMIC_FLAGS())
.def(py::self += DYNAMIC_FLAGS_1())
.def(py::self -= DYNAMIC_FLAGS())
.def(py::self -= DYNAMIC_FLAGS_1())
.def(nb::self -= DYNAMIC_FLAGS())
.def(nb::self -= DYNAMIC_FLAGS_1())
.def("__contains__",
static_cast<bool (DynamicEntryFlags::*)(DYNAMIC_FLAGS) const>(&DynamicEntryFlags::has),
"Check if the given " RST_CLASS_REF(lief.ELF.DYNAMIC_FLAGS) " is present")
nb::overload_cast<DYNAMIC_FLAGS>(&DynamicEntryFlags::has, nb::const_),
"Check if the given " RST_CLASS_REF(lief.ELF.DYNAMIC_FLAGS) " is present"_doc)
.def("__contains__",
static_cast<bool (DynamicEntryFlags::*)(DYNAMIC_FLAGS_1) const>(&DynamicEntryFlags::has),
"Check if the given " RST_CLASS_REF(lief.ELF.DYNAMIC_FLAGS_1) " is present")
nb::overload_cast<DYNAMIC_FLAGS_1>(&DynamicEntryFlags::has, nb::const_),
"Check if the given " RST_CLASS_REF(lief.ELF.DYNAMIC_FLAGS_1) " is present"_doc)
.def("__str__",
[] (const DynamicEntryFlags& entry)
{
std::ostringstream stream;
stream << entry;
std::string str = stream.str();
return str;
});
LIEF_DEFAULT_STR(LIEF::ELF::DynamicEntryFlags);
}
}
}
@@ -13,63 +13,39 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "pyELF.hpp"
#include <string>
#include <sstream>
#include <nanobind/stl/string.h>
#include "LIEF/ELF/hash.hpp"
#include "ELF/pyELF.hpp"
#include "pySafeString.hpp"
#include "LIEF/ELF/DynamicEntryLibrary.hpp"
#include "LIEF/ELF/DynamicEntry.hpp"
#include <string>
#include <sstream>
namespace LIEF {
namespace ELF {
template<class T>
using getter_t = T (DynamicEntryLibrary::*)(void) const;
template<class T>
using setter_t = void (DynamicEntryLibrary::*)(T);
namespace LIEF::ELF::py {
template<>
void create<DynamicEntryLibrary>(py::module& m) {
py::class_<DynamicEntryLibrary, DynamicEntry>(m, "DynamicEntryLibrary",
void create<DynamicEntryLibrary>(nb::module_& m) {
nb::class_<DynamicEntryLibrary, DynamicEntry>(m, "DynamicEntryLibrary",
R"delim(
Class which represents a ``DT_NEEDED`` entry in the dynamic table.
This kind of entry is usually used to create library dependency.
)delim")
)delim"_doc)
.def(py::init<const std::string &>(),
"Constructor from a library name",
.def(nb::init<const std::string &>(),
"Constructor from a library name"_doc,
"library_name"_a)
.def_property("name",
.def_prop_rw("name",
[] (const DynamicEntryLibrary& obj) {
return safe_string_converter(obj.name());
return LIEF::py::safe_string(obj.name());
},
static_cast<setter_t<const std::string&>>(&DynamicEntryLibrary::name),
"Library associated with this entry (e.g. ``libc.so.6``)")
nb::overload_cast<const std::string&>(&DynamicEntryLibrary::name),
"Library associated with this entry (e.g. ``libc.so.6``)"_doc)
.def("__eq__", &DynamicEntryLibrary::operator==)
.def("__ne__", &DynamicEntryLibrary::operator!=)
.def("__hash__",
[] (const DynamicEntryLibrary& entry) {
return Hash::hash(entry);
})
.def("__str__",
[] (const DynamicEntryLibrary& dynamicEntryLibrary)
{
std::ostringstream stream;
stream << dynamicEntryLibrary;
std::string str = stream.str();
return str;
});
LIEF_DEFAULT_STR(LIEF::ELF::DynamicEntryLibrary);
}
}
}
@@ -13,101 +13,78 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "pyELF.hpp"
#include <string>
#include <sstream>
#include "LIEF/ELF/hash.hpp"
#include <nanobind/operators.h>
#include <nanobind/stl/string.h>
#include <nanobind/stl/vector.h>
#include "ELF/pyELF.hpp"
#include "pySafeString.hpp"
#include "LIEF/ELF/DynamicEntryRpath.hpp"
#include "LIEF/ELF/DynamicEntry.hpp"
#include <string>
#include <sstream>
namespace LIEF {
namespace ELF {
template<class T>
using getter_t = T (DynamicEntryRpath::*)(void) const;
template<class T>
using setter_t = void (DynamicEntryRpath::*)(T);
namespace LIEF::ELF::py {
template<>
void create<DynamicEntryRpath>(py::module& m) {
py::class_<DynamicEntryRpath, DynamicEntry>(m, "DynamicEntryRpath",
void create<DynamicEntryRpath>(nb::module_& m) {
nb::class_<DynamicEntryRpath, DynamicEntry>(m, "DynamicEntryRpath",
R"delim(
Class which represents a ``DT_RPATH`` entry. This attribute is
deprecated (cf. ``man ld``) in favour of ``DT_RUNPATH`` (See :class:`~lief.ELF.DynamicRunPath`)
)delim")
)delim"_doc)
.def(py::init<const std::string &>(),
"Constructor from (r)path",
.def(nb::init<const std::string &>(),
"Constructor from (r)path"_doc,
"path"_a = "")
.def(py::init<const std::vector<std::string> &>(),
"Constructor from a list of paths",
.def(nb::init<const std::vector<std::string> &>(),
"Constructor from a list of paths"_doc,
"paths"_a)
.def_property("name",
.def_prop_rw("name",
[] (const DynamicEntryRpath& obj) {
return safe_string_converter(obj.name());
return LIEF::py::safe_string(obj.name());
},
static_cast<setter_t<const std::string&>>(&DynamicEntryRpath::name),
"The actual rpath as a string")
nb::overload_cast<const std::string&>(&DynamicEntryRpath::name),
"The actual rpath as a string"_doc)
.def_property("rpath",
.def_prop_rw("rpath",
[] (const DynamicEntryRpath& obj) {
return safe_string_converter(obj.rpath());
return LIEF::py::safe_string(obj.rpath());
},
static_cast<setter_t<const std::string&>>(&DynamicEntryRpath::rpath),
"The actual rpath as a string")
nb::overload_cast<const std::string&>(&DynamicEntryRpath::rpath),
"The actual rpath as a string"_doc)
.def_property("paths",
static_cast<getter_t<std::vector<std::string> >>(&DynamicEntryRpath::paths),
static_cast<setter_t<const std::vector<std::string>&>>(&DynamicEntryRpath::paths),
"Paths as a list")
.def_prop_rw("paths",
nb::overload_cast<>(&DynamicEntryRpath::paths, nb::const_),
nb::overload_cast<const std::vector<std::string>&>(&DynamicEntryRpath::paths),
"Paths as a list"_doc)
.def("insert",
&DynamicEntryRpath::insert,
"Insert a ``path`` at the given ``position``",
"Insert a ``path`` at the given ``position``"_doc,
"position"_a, "path"_a,
py::return_value_policy::reference)
nb::rv_policy::reference_internal)
.def("append",
&DynamicEntryRpath::append,
"Append the given ``path`` ",
"Append the given ``path`` "_doc,
"path"_a,
py::return_value_policy::reference)
nb::rv_policy::reference_internal)
.def("remove",
&DynamicEntryRpath::remove,
"Remove the given ``path`` ",
"Remove the given ``path`` "_doc,
"path"_a,
py::return_value_policy::reference)
nb::rv_policy::reference_internal)
.def(py::self += std::string())
.def(py::self -= std::string())
.def(nb::self += std::string())
.def(nb::self -= std::string())
.def("__eq__", &DynamicEntryRpath::operator==)
.def("__ne__", &DynamicEntryRpath::operator!=)
.def("__hash__",
[] (const DynamicEntryRpath& entry) {
return Hash::hash(entry);
})
.def("__str__",
[] (const DynamicEntryRpath& entry)
{
std::ostringstream stream;
stream << entry;
std::string str = stream.str();
return str;
});
LIEF_DEFAULT_STR(LIEF::ELF::DynamicEntryRpath);
}
}
}

Some files were not shown because too many files have changed in this diff Show More