diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 771d9034b64c..a2c7c77500f9 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -58,7 +58,8 @@ updates: semver-minor-days: 5 semver-patch-days: 5 exclude: - - '@node-core/doc-kit' + - '@doc-kit/*' + - '@node-core/*' commit-message: prefix: tools open-pull-requests-limit: 10 diff --git a/.github/label-pr-config.yml b/.github/label-pr-config.yml index 8b36066473f4..f30b6b8a5e3e 100644 --- a/.github/label-pr-config.yml +++ b/.github/label-pr-config.yml @@ -15,6 +15,7 @@ subSystemLabels: /^src\/uv\./: c++, libuv /^src\/(?:connect(?:ion)?|pipe|tcp)_/: c++, net /^src\/node_os/: c++, os + /^src\/permission\//: c++, permission /^src\/(?:node_main|signal_)/: c++, process /^src\/timer[_s]/: c++, timers /^src\/node_root_certs/: c++, tls @@ -102,6 +103,7 @@ subSystemLabels: /^lib\/test.js$/: test_runner /^lib\/v8.js$/: v8 module /^lib\/internal\/url\.js$/: whatwg-url + /^lib\/internal\/process\/permission\.js$/: permission /^lib\/internal\/modules\/esm/: esm /^lib\/internal\/modules/: module /^lib\/internal\/source_map/: source maps @@ -116,6 +118,13 @@ subSystemLabels: exlusiveLabels: # More specific tests + /^test\/(?:parallel|sequential)\/test-(?:[^/]+-)?permission(?:-|\.)/: test, permission + /^test\/ffi\/test-ffi-permissions?(?:-|\.)/: test, permission + /^test\/addons\/no-addons\/permission\.js$/: test, addons, permission + /^test\/es-module\/test-[^/]*-permission(?:-|\.)/: test, esm, permission + /^test\/module-hooks\/test-[^/]*-permission(?:-|\.)/: test, module, loaders, permission + /^test\/fixtures\/permission\//: test, permission + /^test\/fixtures\/rc\/permission-namespace\.json$/: test, permission /^test\/addons\//: test, addons /^test\/debugger/: test, debugger /^test\/doctool\//: test, doc, tools @@ -150,6 +159,7 @@ exlusiveLabels: # test_runner documentation /^doc\/api\/test.md$/: doc, test_runner # Automatically tag JS subsystem-specific API doc changes + /^doc\/api\/permissions\.md$/: doc, permission /^doc\/api\/(\w+)\.md$/: doc, $1 # Add deprecations label to PRs that affect doc/api/deprecations.md /^doc\/api\/deprecations.md$/: doc, deprecations @@ -162,6 +172,7 @@ exlusiveLabels: /^doc\//: doc # More specific benchmarks + /^benchmark\/fs\/readfile-permission-enabled\.js$/: benchmark, fs, permission /^benchmark\/buffers\//: benchmark, buffer /^benchmark\/es\//: benchmark, v8 engine /^benchmark\/_http/: benchmark, http @@ -198,6 +209,7 @@ allJsSubSystems: - os - path - perf_hooks + - permission - process - punycode - querystring diff --git a/.github/workflows/auto-start-ci.yml b/.github/workflows/auto-start-ci.yml index dc827d62ba71..85f3e92f2ffb 100644 --- a/.github/workflows/auto-start-ci.yml +++ b/.github/workflows/auto-start-ci.yml @@ -1,6 +1,9 @@ # This action uses the following secrets: # JENKINS_USER: GitHub user whose Jenkins token is defined below -# JENKINS_TOKEN: Jenkins token, to be used to start CI +# JENKINS_TOKEN: Jenkins token, to be used to start or resume CI +# Optional repository variables: +# AUTO_START_CI_BATCH_SIZE: maximum PRs to process per run (default: 5) +# AUTO_START_CI_MAX_WORKLOAD: pause at this many running or queued PR jobs (default: 15) name: Auto Start CI on: @@ -30,16 +33,25 @@ jobs: steps: - name: Get Pull Requests id: get_prs_for_ci - run: > - echo "numbers=$(gh pr list \ + # Explicit bash enables pipefail so jq cannot hide a failed gh query. + shell: bash + run: | + if ! [[ "$BATCH_SIZE" =~ ^[1-9][0-9]*$ ]]; then + echo '::error::AUTO_START_CI_BATCH_SIZE must be a strictly positive integer' + exit 1 + fi + # Filter before selecting the batch; UNKNOWN mergeability is retried later. + numbers=$(gh pr list \ --repo "$GITHUB_REPOSITORY" \ - --label 'request-ci' \ - --json 'number' \ - --search 'review:approved' \ - -t '{{ range . }}{{ .number }} {{ end }}' \ - --limit 5)" >> "$GITHUB_OUTPUT" + --json 'number,mergeable' \ + --search 'review:approved label:request-ci,resume-ci' \ + --limit 100 \ + | jq --argjson limit "$BATCH_SIZE" \ + '[.[] | select(.mergeable == "MERGEABLE") | .number] | .[:$limit] | map(tostring) | join(" ")' -r) + echo "numbers=$numbers" >> "$GITHUB_OUTPUT" env: GH_TOKEN: ${{ github.token }} + BATCH_SIZE: ${{ vars.AUTO_START_CI_BATCH_SIZE || '5' }} start-ci: permissions: checks: read @@ -70,7 +82,7 @@ jobs: GH_TOKEN: ${{ github.token }} JENKINS_TOKEN: ${{ secrets.JENKINS_TOKEN }} - - name: Start the CI + - name: Start or resume the CI run: | read -r -a numbers <<< "$PULL_REQUESTS" curl -fsSL "https://github.com/${GITHUB_REPOSITORY}/raw/${GITHUB_SHA}/tools/actions/start-ci.sh" \ @@ -78,3 +90,4 @@ jobs: env: GH_TOKEN: ${{ github.token }} PULL_REQUESTS: ${{ needs.get-prs-for-ci.outputs.numbers }} + MAX_WORKLOAD: ${{ vars.AUTO_START_CI_MAX_WORKLOAD || '15' }} diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml index 92bab7856bb6..0e901de78d9a 100644 --- a/.github/workflows/benchmark.yml +++ b/.github/workflows/benchmark.yml @@ -121,15 +121,11 @@ jobs: --pure --keep TAR_DIR --keep FLAKY_TESTS \ --keep SCCACHE_GHA_ENABLED --keep SCCACHE_GHA_RW_MODE \ --keep ACTIONS_CACHE_SERVICE_V2 --keep ACTIONS_RESULTS_URL --keep ACTIONS_RUNTIME_TOKEN \ - --arg useSeparateDerivationForV8 true \ --arg withPerfetto ${{ matrix.perfetto || false }} \ - --arg loadJSBuiltinsDynamically false \ --arg ccache '(import {}).sccache' \ - --arg devTools '[]' \ - --arg benchmarkTools '[]' \ --run ' make build-ci -j4 V=1 && sccache --stop-server - ' + ' tools/nix/ci-shell.nix mv out/Release/node base_node - name: Checkout the merge commit @@ -141,15 +137,11 @@ jobs: nix-shell \ -I nixpkgs=./tools/nix/pkgs.nix \ --pure --keep SCCACHE_LOCAL_RW_MODE \ - --arg useSeparateDerivationForV8 true \ --arg withPerfetto ${{ matrix.perfetto || false }} \ - --arg loadJSBuiltinsDynamically false \ --arg ccache '(import {}).sccache' \ - --arg devTools '[]' \ - --arg benchmarkTools '[]' \ --run ' make build-ci -j4 V=1 - ' + ' tools/nix/ci-shell.nix env: SCCACHE_LOCAL_RW_MODE: READ_ONLY @@ -232,7 +224,7 @@ jobs: nix-shell \ -I nixpkgs=./tools/nix/pkgs.nix \ --pure \ - -E '(import {}).mkShell { buildInputs = import ./tools/nix/benchmarkTools.nix { withHttpBenchmarkDeps = false; }; }' \ + -E '(import {}).mkShellNoCC { buildInputs = import ./tools/nix/benchmarkTools.nix { withHttpBenchmarkDeps = false; }; }' \ --run ' export LC_ALL=C.UTF-8 echo "> [!WARNING] " diff --git a/.github/workflows/build-shared.yml b/.github/workflows/build-shared.yml index 7d77c13e568d..73f7ec6afbbf 100644 --- a/.github/workflows/build-shared.yml +++ b/.github/workflows/build-shared.yml @@ -85,12 +85,9 @@ jobs: -I "nixpkgs=$TAR_DIR/tools/nix/pkgs.nix" \ --pure --keep TAR_DIR --keep FLAKY_TESTS \ --keep SCCACHE_GHA_ENABLED --keep ACTIONS_CACHE_SERVICE_V2 --keep ACTIONS_RESULTS_URL --keep ACTIONS_RUNTIME_TOKEN \ - --arg loadJSBuiltinsDynamically false \ --arg ccache "${NIX_SCCACHE:-null}" \ - --arg devTools '[]' \ - --arg benchmarkTools '[]' \ --arg pkcs11 ${{ inputs.pkcs11-store-test }} \ ${{ inputs.extra-nix-flags }} \ --run ' make -C "$TAR_DIR" run-ci -j4 V=1 TEST_CI_ARGS="-p actions --measure-flakiness 9 --skip-tests=$CI_SKIP_TESTS" - ' "$TAR_DIR/shell.nix" + ' "$TAR_DIR/tools/nix/ci-shell.nix" diff --git a/.github/workflows/build-tarball.yml b/.github/workflows/build-tarball.yml index 045bd3ae93c2..53e625ef889b 100644 --- a/.github/workflows/build-tarball.yml +++ b/.github/workflows/build-tarball.yml @@ -67,6 +67,7 @@ env: PYTHON_VERSION: '3.14' FLAKY_TESTS: keep_retrying CLANG_VERSION: '19' + NODE_VERSION: lts/* permissions: contents: read @@ -84,12 +85,16 @@ jobs: with: python-version: ${{ env.PYTHON_VERSION }} allow-prereleases: true + - name: Use Node.js ${{ env.NODE_VERSION }} + uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 + with: + node-version: ${{ env.NODE_VERSION }} - name: Make tarball run: | export DISTTYPE=nightly export DATESTRING=$(date "+%Y-%m-%d") export COMMIT=$(git rev-parse --short=10 "$GITHUB_SHA") - ./configure && make tar -j4 SKIP_XZ=1 + ./configure && make tar -j4 SKIP_XZ=1 GZIP_COMPRESSION=6 - name: Upload tarball artifact uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 1b3179ef4af1..d8eca1f2b798 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -30,15 +30,15 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@b96794f015dfd88f77b49b1c93e0fa7110f94c63 # v4.38.0 + uses: github/codeql-action/init@2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2 # v4.38.2 with: languages: ${{ matrix.language }} config-file: ./.github/codeql-config.yml - name: Autobuild - uses: github/codeql-action/autobuild@b96794f015dfd88f77b49b1c93e0fa7110f94c63 # v4.38.0 + uses: github/codeql-action/autobuild@2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2 # v4.38.2 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@b96794f015dfd88f77b49b1c93e0fa7110f94c63 # v4.38.0 + uses: github/codeql-action/analyze@2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2 # v4.38.2 with: category: /language:${{matrix.language}} diff --git a/.github/workflows/coverage-linux-without-intl.yml b/.github/workflows/coverage-linux-without-intl.yml index a98492ec668e..9b8f8e2fd831 100644 --- a/.github/workflows/coverage-linux-without-intl.yml +++ b/.github/workflows/coverage-linux-without-intl.yml @@ -85,6 +85,6 @@ jobs: - name: Clean tmp run: rm -rf coverage/tmp && rm -rf out - name: Upload - uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0 + uses: codecov/codecov-action@0b35c9ecc4f0529d0eb674914510c22f85b196b4 # v7.1.0 with: directory: ./coverage diff --git a/.github/workflows/coverage-linux.yml b/.github/workflows/coverage-linux.yml index 4ba373b790a2..0c7fc292d346 100644 --- a/.github/workflows/coverage-linux.yml +++ b/.github/workflows/coverage-linux.yml @@ -85,6 +85,6 @@ jobs: - name: Clean tmp run: rm -rf coverage/tmp && rm -rf out - name: Upload - uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0 + uses: codecov/codecov-action@0b35c9ecc4f0529d0eb674914510c22f85b196b4 # v7.1.0 with: directory: ./coverage diff --git a/.github/workflows/coverage-windows.yml b/.github/workflows/coverage-windows.yml index 5da225b17127..a4db4ccc08c7 100644 --- a/.github/workflows/coverage-windows.yml +++ b/.github/workflows/coverage-windows.yml @@ -101,6 +101,6 @@ jobs: - name: Clean tmp run: npx rimraf ./coverage/tmp - name: Upload - uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0 + uses: codecov/codecov-action@0b35c9ecc4f0529d0eb674914510c22f85b196b4 # v7.1.0 with: directory: ./coverage diff --git a/.github/workflows/linters.yml b/.github/workflows/linters.yml index 848fffc117a1..9afdb2ef5a64 100644 --- a/.github/workflows/linters.yml +++ b/.github/workflows/linters.yml @@ -41,6 +41,12 @@ jobs: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: persist-credentials: false + # Skip large vendored trees that lint-cpp does not use. + sparse-checkout: | + /* + !/deps/openssl/ + !/deps/v8/ + sparse-checkout-cone-mode: false - name: Set up Python ${{ env.PYTHON_VERSION }} uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 with: @@ -54,7 +60,8 @@ jobs: steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: - fetch-depth: 0 + # The first parent of the PR merge commit is the base branch commit. + fetch-depth: 2 persist-credentials: false - name: Use Node.js ${{ env.NODE_VERSION }} uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 @@ -72,7 +79,7 @@ jobs: # because it is irrelevant. We already check if the formatter produced # a diff in the next line. # Refs: https://github.com/nodejs/node/pull/42764 - CLANG_FORMAT_START="$(git merge-base HEAD refs/remotes/origin/$GITHUB_BASE_REF)" \ + CLANG_FORMAT_START=HEAD^ \ make format-cpp || true git --no-pager diff --exit-code && EXIT_CODE="$?" || EXIT_CODE="$?" if [ "$EXIT_CODE" != "0" ] @@ -93,13 +100,29 @@ jobs: with: persist-credentials: false - name: Use Node.js ${{ env.NODE_VERSION }} + id: setup-node uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: node-version: ${{ env.NODE_VERSION }} + cache: npm + cache-dependency-path: | + tools/doc/package-lock.json + tools/eslint/package-lock.json + tools/lint-md/package-lock.json + - name: Cache ESLint results + uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 + env: + # ESLint only invalidates its cache on config changes, so the key also + # covers the custom rules and the files they read. + cache-prefix: eslint-${{ runner.os }}-${{ steps.setup-node.outputs.node-version }}-${{ hashFiles('eslint.config.mjs', '*/eslint.config_partial.mjs', 'tools/eslint/*', 'tools/eslint-rules/**', 'doc/api/errors.md', 'doc/api/deprecations.md') }} + with: + path: .eslintcache + key: ${{ env.cache-prefix }}-${{ github.sha }} + restore-keys: ${{ env.cache-prefix }}- - name: Lint JavaScript files run: | set +e - NODE=$(command -v node) make lint-js + NODE=$(command -v node) make lint-js ESLINT_CACHE_FLAGS='--cache --cache-strategy content' EXIT_CODE="$?" if [ "$EXIT_CODE" != "0" ]; then echo @@ -129,7 +152,7 @@ jobs: - name: Lint markdown files run: | echo "::add-matcher::.github/workflows/remark-lint-problem-matcher.json" - NODE=$(command -v node) make lint-md + NODE=$(command -v node) make lint-md ESLINT_CACHE_FLAGS='--cache --cache-strategy content' env: NODE_RELEASED_VERSIONS: ${{ steps.get-released-versions.outputs.NODE_RELEASED_VERSIONS }} diff --git a/.github/workflows/nix-changes.yml b/.github/workflows/nix-changes.yml index 8aeaf2c0e4e1..c80e9e53f546 100644 --- a/.github/workflows/nix-changes.yml +++ b/.github/workflows/nix-changes.yml @@ -68,10 +68,16 @@ jobs: - name: Compute requisites before change run: | - git reset HEAD^ --hard - # TODO(aduh95): remove this once list-requisites.sh has reached `main` - [ -f tools/nix/list-requisites.sh ] || git checkout FETCH_HEAD -- tools/nix/list-requisites.sh + BASE_SHA="$(git rev-parse HEAD^)" + if [ -n "$PUSH_BEFORE_SHA" ] && [ "$PUSH_BEFORE_SHA" != "$BASE_SHA" ] \ + && [ "$PUSH_BEFORE_SHA" != "0000000000000000000000000000000000000000" ] \ + && git fetch --no-tags --depth=1 origin "$PUSH_BEFORE_SHA"; then + BASE_SHA="$PUSH_BEFORE_SHA" + fi + git reset "$BASE_SHA" --hard ./tools/nix/list-requisites.sh > requisites-${{ matrix.system }}-before.list + env: + PUSH_BEFORE_SHA: ${{ github.event_name == 'push' && github.event.before || '' }} - name: Output diff run: | diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 4a7415bc90e1..2663019bcc2a 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -76,6 +76,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: Upload to code-scanning - uses: github/codeql-action/upload-sarif@b96794f015dfd88f77b49b1c93e0fa7110f94c63 # v4.38.0 + uses: github/codeql-action/upload-sarif@2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2 # v4.38.2 with: sarif_file: results.sarif diff --git a/.github/workflows/test-linux-perfetto.yml b/.github/workflows/test-linux-perfetto.yml index ce31704f8166..d2bfbfbd6890 100644 --- a/.github/workflows/test-linux-perfetto.yml +++ b/.github/workflows/test-linux-perfetto.yml @@ -62,6 +62,9 @@ jobs: - name: Build working-directory: node run: make build-ci -j4 V=1 CONFIG_FLAGS="--error-on-warn --v8-enable-temporal-support --with-perfetto" + - name: Get trace_processor + working-directory: node + run: make tools/perfetto/trace_processor_shell - name: Test working-directory: node run: make test-ci -j1 V=1 TEST_CI_ARGS="-p actions --measure-flakiness 9" diff --git a/.github/workflows/test-shared.yml b/.github/workflows/test-shared.yml index 9f4d2e031f58..8292ac253fd2 100644 --- a/.github/workflows/test-shared.yml +++ b/.github/workflows/test-shared.yml @@ -13,11 +13,12 @@ on: - android-patches/** - benchmarks/** - codecov.yml + - deps/LIEF/** - deps/ada/** - deps/brotli/** - deps/cares/** - - deps/crates/** - deps/corepack/** + - deps/crates/** - deps/googletest/** - deps/histogram/** - deps/icu-small/** @@ -70,11 +71,12 @@ on: - android-patches/** - benchmarks/** - codecov.yml + - deps/LIEF/** - deps/ada/** - deps/brotli/** - deps/cares/** - - deps/crates/** - deps/corepack/** + - deps/crates/** - deps/googletest/** - deps/histogram/** - deps/icu-small/** @@ -133,7 +135,7 @@ jobs: run: | export DATESTRING=$(date "+%Y-%m-%d") export COMMIT=$(git rev-parse --short=10 "$GITHUB_SHA") - ./configure && make tar -j4 SKIP_XZ=1 SKIP_SHARED_DEPS=1 + ./configure && make tar -j4 SKIP_XZ=1 SKIP_SHARED_DEPS=1 GZIP_COMPRESSION=6 env: DISTTYPE: nightly @@ -165,10 +167,7 @@ jobs: with: runner: ${{ matrix.runner }} with-sccache: ${{ github.base_ref == 'main' || github.ref_name == 'main' }} - extra-nix-flags: | - --arg useSeparateDerivationForV8 true \ - ${{ matrix.perfetto && '--arg withPerfetto true \' || '\' }} - ${{ endsWith(matrix.system, '-darwin') && '--arg withAmaro false --arg withLief false --arg withSQLite false --arg withFFI false --arg extraConfigFlags ''["--without-inspector" "--without-node-options"]'' \' || '\' }} + extra-nix-flags: ${{ matrix.perfetto && '--arg withPerfetto true' || '' }} secrets: CACHIX_AUTH_TOKEN: ${{ secrets.CACHIX_AUTH_TOKEN }} @@ -200,7 +199,7 @@ jobs: id: v8-drv run: | V8_DRV=$( - nix-instantiate -E "builtins.filter (p: p.pname == ''v8'') (import $TAR_DIR/shell.nix { useSeparateDerivationForV8=true; }).buildInputs" + nix-instantiate -E "builtins.filter (p: p.pname == ''v8'') (import $TAR_DIR/tools/nix/ci-shell.nix {}).buildInputs" ) V8_STORE_PATH=$(nix-store -q --outputs "$V8_DRV") echo "V8_DRV=$V8_DRV" >> "$GITHUB_OUTPUT" diff --git a/.github/workflows/tools.yml b/.github/workflows/tools.yml index fe2db7ac95c4..497a5c1230f1 100644 --- a/.github/workflows/tools.yml +++ b/.github/workflows/tools.yml @@ -28,6 +28,7 @@ on: - inspector_protocol - libffi - libuv + - lief - llhttp - minimatch - nbytes @@ -150,6 +151,7 @@ jobs: - id: icu subsystem: deps label: dependencies, test, icu + requires-python: true run: | ./tools/dep_updaters/update-icu.sh > temp-output cat temp-output @@ -158,6 +160,7 @@ jobs: - id: inspector_protocol subsystem: deps label: dependencies, inspector + requires-python: true run: | ./tools/dep_updaters/update-inspector-protocol.sh > temp-output cat temp-output @@ -179,6 +182,15 @@ jobs: cat temp-output tail -n1 temp-output | grep "NEW_VERSION=" >> "$GITHUB_ENV" || true rm temp-output + - id: lief + subsystem: deps + label: dependencies, dont-land-on-v22.x + requires-python: true + run: | + ./tools/dep_updaters/update-lief.sh > temp-output + cat temp-output + tail -n1 temp-output | grep "NEW_VERSION=" >> "$GITHUB_ENV" || true + rm temp-output - id: llhttp subsystem: deps label: dependencies @@ -321,9 +333,7 @@ jobs: with: persist-credentials: false - name: Set up Python ${{ env.PYTHON_VERSION }} - if: | - (matrix.id == 'icu' || matrix.id == 'inspector_protocol') && - (github.event_name == 'schedule' || inputs.id == 'all' || inputs.id == matrix.id) + if: matrix.requires-python && (github.event_name == 'schedule' || inputs.id == 'all' || inputs.id == matrix.id) uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 with: python-version: ${{ env.PYTHON_VERSION }} diff --git a/.github/workflows/update-openssl.yml b/.github/workflows/update-openssl.yml index 10eb3289a1f7..b81a260312ba 100644 --- a/.github/workflows/update-openssl.yml +++ b/.github/workflows/update-openssl.yml @@ -27,6 +27,7 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GH_USER_TOKEN }} - name: Create PR with first commit + id: create-pull-request if: env.NEW_VERSION uses: gr2m/create-or-update-pull-request-action@b65137ca591da0b9f43bad7b24df13050ea45d1b # v1.10.1 # Creates a PR with the new OpenSSL source code committed @@ -41,6 +42,7 @@ jobs: title: 'deps: update OpenSSL to ${{ env.NEW_VERSION }}' path: deps/openssl update-pull-request-title-and-body: true + draft: true - name: Regenerate platform specific files if: env.NEW_VERSION run: | @@ -59,3 +61,9 @@ jobs: branch: actions/tools-update-openssl # Custom branch *just* for this Action. commit-message: 'deps: update archs files for openssl-${{ env.NEW_VERSION }}' path: deps/openssl + - name: Mark PR as ready for review + if: env.NEW_VERSION + env: + GITHUB_TOKEN: ${{ secrets.GH_USER_TOKEN }} + PR_ID: ${{ steps.create-pull-request.outputs.pull-request-number }} + run: gh --repo "$GITHUB_REPOSITORY" pr ready "$PR_ID" diff --git a/.gitignore b/.gitignore index 9277cdf090f0..2a878492247b 100644 --- a/.gitignore +++ b/.gitignore @@ -103,6 +103,11 @@ _UpgradeReport_Files/ tools/*/*.i tools/*/*.i.tmp +# === Rules for pgo artifacts === +*.profdata +*.profraw +*.gcda + # === Rules for release artifacts === /*.tar.* /*.pkg @@ -116,6 +121,9 @@ tools/*/*.i.tmp /tools/eslint/node_modules /tools/lint-md/node_modules +# === Rules for tools/perfetto === +/tools/perfetto/trace_processor_shell + # === Rules for test artifacts === /*.tap /*.xml diff --git a/BUILDING.md b/BUILDING.md index b0459237623f..0bb93c77cfa0 100644 --- a/BUILDING.md +++ b/BUILDING.md @@ -107,7 +107,7 @@ platforms. This is true regardless of entries in the table below. | Operating System | Architectures | Versions | Support Type | Notes | | ---------------- | ---------------- | --------------------------------- | ------------ | ---------------------------------------------------------- | | GNU/Linux | x64 | kernel >= 4.18[^1], glibc >= 2.28 | Tier 1 | e.g. Ubuntu 20.04, Debian 10, RHEL 8 | -| GNU/Linux | x64 | kernel >= 3.10, musl >= 1.1.19 | Experimental | e.g. Alpine 3.8 | +| GNU/Linux | x64 | kernel >= 6.12, musl >= 1.2.5 | Tier 2 | e.g. Alpine 3.22 | | GNU/Linux | x86 | kernel >= 3.10, glibc >= 2.17 | Experimental | Downgraded as of Node.js 10 | | GNU/Linux | arm64 | kernel >= 4.18[^1], glibc >= 2.28 | Tier 1 | e.g. Ubuntu 20.04, Debian 10, RHEL 8 | | GNU/Linux | armv7 | kernel >= 4.18[^1], glibc >= 2.28 | Experimental | Downgraded as of Node.js 24 | diff --git a/CHANGELOG.md b/CHANGELOG.md index 5144a3613230..b6ccca763b4a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -41,7 +41,8 @@ release. -26.10.0
+26.11.0
+26.10.0
26.9.0
26.8.2
26.8.1
diff --git a/Makefile b/Makefile index c9f3ad5f05e2..8549e5885fcd 100644 --- a/Makefile +++ b/Makefile @@ -235,6 +235,7 @@ distclean: ## Remove all build and test artifacts. $(RM) -r node_modules $(RM) -r deps/icu $(RM) -r deps/icu4c*.tgz deps/icu4c*.zip deps/icu-tmp + $(RM) tools/perfetto/trace_processor_shell $(RM) $(BINARYTAR).* $(TARBALL).* .PHONY: check @@ -338,6 +339,18 @@ coverage-run-js: ## Run JavaScript tests with coverage. TEST_CI_ARGS="$(TEST_CI_ARGS) --type=coverage" $(MAKE) jstest $(MAKE) coverage-report-js +TRACE_PROCESSOR_SHELL_PATH ?= tools/perfetto/trace_processor_shell + +# The downloaded copy has to match the vendored perfetto, so a version bump +# re-downloads it. An overridden path is a build we do not manage and may not +# be writable, so it gets no prerequisite and is left alone once it exists. +ifeq ($(TRACE_PROCESSOR_SHELL_PATH),tools/perfetto/trace_processor_shell) +TRACE_PROCESSOR_SHELL_DEPS = deps/perfetto/VERSION +endif + +$(TRACE_PROCESSOR_SHELL_PATH): $(TRACE_PROCESSOR_SHELL_DEPS) + @tools/perfetto/get_trace_processor $@ + .PHONY: test # This does not run tests of third-party libraries inside deps. test: all ## Run default tests and build docs. @@ -389,7 +402,12 @@ ifeq ($(OSTYPE),os400) DOCBUILDSTAMP_PREREQS := $(DOCBUILDSTAMP_PREREQS) out/$(BUILDTYPE)/node.exp endif -DOC_KIT ?= tools/doc/node_modules/@node-core/doc-kit/bin/cli.mjs +DOC_KIT ?= tools/doc/node_modules/@doc-kit/cli/bin/cli.mjs +ifeq ($(V),1) +DOC_KIT_LOG_LEVEL ?= debug +else +DOC_KIT_LOG_LEVEL ?= info +endif node_use_openssl_and_icu = $(call available-node,"-p" \ "process.versions.openssl != undefined && process.versions.icu != undefined") @@ -858,7 +876,7 @@ VERSION=v$(RAWVER) .PHONY: doc-only .NOTPARALLEL: doc-only -doc-only: $(apidoc_dirs) $(apidocs_html) $(apidocs_json) out/doc/api/all.html out/doc/api/all.json out/doc/llms.txt out/doc/apilinks.json ## Builds the docs with the local or the global Node.js binary. +doc-only: $(apidoc_dirs) $(apidocs_html) $(apidocs_json) out/doc/api/all.json out/doc/llms.txt out/doc/apilinks.json ## Builds the docs with the local or the global Node.js binary. .PHONY: doc doc: $(NODE_EXE) doc-only ## Build Node.js, and then build the documentation with the new binary. @@ -895,15 +913,10 @@ $(apidocs_html) $(apidocs_json) out/doc/api/all.html out/doc/api/all.json &: $(a else \ $(call available-node, \ $(DOC_KIT) generate \ - -t legacy-html-all \ - -t legacy-json-all \ - -i doc/api/*.md \ - --ignore $(skip_apidoc_files) \ - -o out/doc/api \ - -c ./CHANGELOG.md \ + --log-level $(DOC_KIT_LOG_LEVEL) \ + --config-file tools/doc/web.doc-kit.config.mjs \ -v $(VERSION) \ - --index doc/api/index.md \ - --type-map doc/type-map.json \ + $(if $(JOBS),-p $(JOBS)) \ ) \ fi endif @@ -914,13 +927,11 @@ out/doc/llms.txt: $(apidoc_sources) tools/doc/node_modules | out/doc else \ $(call available-node, \ $(DOC_KIT) generate \ + --log-level $(DOC_KIT_LOG_LEVEL) \ + --config-file tools/doc/web.doc-kit.config.mjs \ -t llms-txt \ - -i doc/api/*.md \ - --ignore $(skip_apidoc_files) \ -o $(@D) \ - -c ./CHANGELOG.md \ -v $(VERSION) \ - --type-map doc/type-map.json \ ) \ fi @@ -930,12 +941,10 @@ out/doc/apilinks.json: $(wildcard lib/*.js) tools/doc/node_modules | out/doc else \ $(call available-node, \ $(DOC_KIT) generate \ - -t api-links \ - -i lib/*.js \ + --log-level $(DOC_KIT_LOG_LEVEL) \ + --config-file tools/doc/api-links.doc-kit.config.mjs \ -o $(@D) \ - -c ./CHANGELOG.md \ -v $(VERSION) \ - --type-map doc/type-map.json \ ) \ fi @@ -949,6 +958,7 @@ node.1: doc/api/cli.md tools/doc/node_modules else \ $(call available-node, \ $(DOC_KIT) generate \ + --log-level $(DOC_KIT_LOG_LEVEL) \ -v $(VERSION) \ --config-file tools/doc/man-page.doc-kit.config.mjs \ -o doc \ @@ -1124,6 +1134,7 @@ HAS_XZ ?= $(shell command -v xz > /dev/null 2>&1; [ $$? -eq 0 ] && echo 1 || ech SKIP_XZ ?= 0 XZ = $(shell [ $(HAS_XZ) -eq 1 ] && [ $(SKIP_XZ) -eq 0 ] && echo 1 || echo 0) XZ_COMPRESSION ?= 9e +GZIP_COMPRESSION ?= 9 PKG=$(TARNAME).pkg MACOSOUTDIR=out/macos @@ -1356,7 +1367,7 @@ endif find $(TARNAME)/ -type l | xargs $(RM) tar -cf $(TARNAME).tar $(TARNAME) $(RM) -r $(TARNAME) - gzip -c -f -9 $(TARNAME).tar > $(TARNAME).tar.gz + gzip -c -f -$(GZIP_COMPRESSION) $(TARNAME).tar > $(TARNAME).tar.gz ifeq ($(XZ), 1) xz -c -f -$(XZ_COMPRESSION) $(TARNAME).tar > $(TARNAME).tar.xz endif @@ -1401,7 +1412,7 @@ $(TARBALL)-headers: release-only find $(TARNAME)/ -type l | xargs $(RM) tar -cf $(TARNAME)-headers.tar $(TARNAME) $(RM) -r $(TARNAME) - gzip -c -f -9 $(TARNAME)-headers.tar > $(TARNAME)-headers.tar.gz + gzip -c -f -$(GZIP_COMPRESSION) $(TARNAME)-headers.tar > $(TARNAME)-headers.tar.gz ifeq ($(XZ), 1) xz -c -f -$(XZ_COMPRESSION) $(TARNAME)-headers.tar > $(TARNAME)-headers.tar.xz endif @@ -1446,7 +1457,7 @@ ifeq ($(OSTYPE),darwin) endif tar -cf $(BINARYNAME).tar $(BINARYNAME) $(RM) -r $(BINARYNAME) - gzip -c -f -9 $(BINARYNAME).tar > $(BINARYNAME).tar.gz + gzip -c -f -$(GZIP_COMPRESSION) $(BINARYNAME).tar > $(BINARYNAME).tar.gz ifeq ($(XZ), 1) xz -c -f -$(XZ_COMPRESSION) $(BINARYNAME).tar > $(BINARYNAME).tar.xz endif @@ -1515,6 +1526,7 @@ tools/.manpagelintstamp: doc/node.1 doc/api/cli.md tools/doc/node_modules $(RM) -r tools/doc/.manpagecheck && \ $(call available-node, \ $(DOC_KIT) generate \ + --log-level $(DOC_KIT_LOG_LEVEL) \ -v $(VERSION) \ --config-file tools/doc/man-page.doc-kit.config.mjs \ ) \ @@ -1535,10 +1547,10 @@ format-md: tools/lint-md/node_modules/remark-parse/package.json ## Format the ma @$(call available-node,$(run-format-md)) - +ESLINT_CACHE_FLAGS ?= --cache LINT_JS_TARGETS = eslint.config.mjs benchmark doc lib test tools -run-lint-js = tools/eslint/node_modules/eslint/bin/eslint.js --cache \ +run-lint-js = tools/eslint/node_modules/eslint/bin/eslint.js $(ESLINT_CACHE_FLAGS) \ --max-warnings=0 --report-unused-disable-directives \ --concurrency auto $(LINT_JS_TARGETS) run-lint-js-fix = $(run-lint-js) --fix diff --git a/README.md b/README.md index d90887e0f5d8..d14fba943dd0 100644 --- a/README.md +++ b/README.md @@ -445,6 +445,8 @@ For information about the governance of the Node.js project, see **Vladimir Morozov** <> (he/him) * [watilde](https://github.com/watilde) - **Daijiro Wachi** <> (he/him) +* [XadillaX](https://github.com/XadillaX) - + **Khaidi Chu** <> (he/him) * [ZYSzys](https://github.com/ZYSzys) - **Yongsheng Zhang** <> (he/him) @@ -725,8 +727,6 @@ For information about the governance of the Node.js project, see **Thomas Watson** <> * [whitlockjc](https://github.com/whitlockjc) - **Jeremy Whitlock** <> -* [XadillaX](https://github.com/XadillaX) - - **Khaidi Chu** <> (he/him) * [yashLadha](https://github.com/yashLadha) - **Yash Ladha** <> (he/him) * [yhwang](https://github.com/yhwang) - diff --git a/SECURITY.md b/SECURITY.md index f5a4ef3370ad..7afe640ecf64 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -430,14 +430,14 @@ the community they pose. * Examples of scenarios that are **not** Node.js vulnerabilities: * Allowing untrusted users to register SQLite user-defined functions via - `node:sqlite` (`DatabaseSync`) that can perform arbitrary operations + `node:sqlite` (`Database`) that can perform arbitrary operations (e.g., closing database connections during query execution, causing crashes or use-after-free conditions). * Loading SQLite extensions using the `allowExtension` option in - `DatabaseSync` — this option must be explicitly set to `true` by the + `Database` — this option must be explicitly set to `true` by the application, and enabling it is the application operator's responsibility. * Using `node:sqlite` built-in SQL functions or pragmas (e.g., - `ATTACH DATABASE`) to read or write files — `DatabaseSync` operates with + `ATTACH DATABASE`) to read or write files — `Database` operates with the same file-system access as the process itself, and it is the application's responsibility to restrict what SQL is executed. * Exposing `child_process.exec()` or similar APIs to untrusted users without @@ -532,7 +532,7 @@ The following are **not** vulnerabilities in Node.js: access. Inconsistent checks on these paths are treated as regular bugs and should be reported through the public issue tracker. -* **`node:sqlite` and the permission model**: `DatabaseSync` operates with the +* **`node:sqlite` and the permission model**: `Database` operates with the same file-system privileges as the process. Using SQL pragmas or built-in SQLite mechanisms (e.g., `ATTACH DATABASE`) to access files does not bypass the permission model — the permission model does not intercept SQL-level diff --git a/benchmark/buffers/buffer-islatin1.js b/benchmark/buffers/buffer-islatin1.js new file mode 100644 index 000000000000..6396873a7263 --- /dev/null +++ b/benchmark/buffers/buffer-islatin1.js @@ -0,0 +1,57 @@ +'use strict'; + +const common = require('../common.js'); +const buffer = require('node:buffer'); +const assert = require('node:assert'); + +const bench = common.createBenchmark(main, { + n: [1e7], + length: ['short', 'long'], + // onebyte: one-byte representation (O(1) check) + // twobyte: two-byte representation containing only code units <= 0xFF + // invalid: ends with a code unit > 0xFF + input: ['onebyte', 'twobyte', 'invalid'], + method: ['isLatin1', 'loop', 'regex'], +}); + +function loop(str) { + for (let i = 0; i < str.length; i++) { + if (str.charCodeAt(i) > 255) return false; + } + return true; +} + +const notLatin1Re = /[\u0100-\uffff]/; +function regex(str) { + return !notLatin1Re.test(str); +} + +const methods = { isLatin1: buffer.isLatin1, loop, regex }; + +function main({ n, length, input, method }) { + const base = length === 'short' ? 'hello w\u00f6rld' : 'hello w\u00f6rld'.repeat(200); + let str; + switch (input) { + case 'onebyte': + str = base; + break; + case 'twobyte': + // Slicing a two-byte string keeps the two-byte representation. + str = ('\u0100' + base).slice(1); + break; + case 'invalid': + str = base + '\u0100'; + break; + } + const expected = input !== 'invalid'; + const fn = methods[method]; + assert.strictEqual(fn(str), expected); + + bench.start(); + let result; + for (let i = 0; i < n; ++i) { + result = fn(str); + } + bench.end(n); + assert.strictEqual(result, expected); +} diff --git a/benchmark/buffers/buffer-stringlength.js b/benchmark/buffers/buffer-stringlength.js new file mode 100644 index 000000000000..00fc5c35026e --- /dev/null +++ b/benchmark/buffers/buffer-stringlength.js @@ -0,0 +1,28 @@ +'use strict'; + +const common = require('../common.js'); +const { Buffer } = require('node:buffer'); +const assert = require('node:assert'); + +const bench = common.createBenchmark(main, { + n: [1e6], + encoding: ['utf8', 'latin1', 'base64'], + len: [32, 4096, 1048576], + input: ['ascii', 'multibyte', 'invalid'], +}); + +function main({ n, encoding, len, input }) { + let buf; + if (input === 'ascii') { + buf = Buffer.alloc(len, 'a'); + } else { + buf = Buffer.alloc(len - (len % 3), '€'); + if (input === 'invalid') buf = Buffer.concat([buf, Buffer.from([0xE2, 0x82])]); + } + const expected = buf.toString(encoding).length; + bench.start(); + for (let i = 0; i < n; ++i) { + assert.strictEqual(Buffer.stringLength(buf, encoding), expected); + } + bench.end(n); +} diff --git a/benchmark/crypto/timingSafeEqual.js b/benchmark/crypto/timingSafeEqual.js index 475807dba4ea..bd8962a3bdf4 100644 --- a/benchmark/crypto/timingSafeEqual.js +++ b/benchmark/crypto/timingSafeEqual.js @@ -7,10 +7,14 @@ const { randomBytes, timingSafeEqual } = require('node:crypto'); const bench = common.createBenchmark(main, { n: [1e5], bufferSize: [10, 100, 200, 2_100, 22_023], +}, { + test: { bufferSize: 256 }, }); function main({ n, bufferSize }) { const bufs = [randomBytes(bufferSize), randomBytes(bufferSize)]; + // Ensure the buffers differ even if the random bytes are identical. + bufs[1][0] = bufs[0][0] ^ 1; bench.start(); let count = 0; for (let i = 0; i < n; i++) { diff --git a/benchmark/crypto/webcrypto-export.js b/benchmark/crypto/webcrypto-export.js new file mode 100644 index 000000000000..4d96b54ec74d --- /dev/null +++ b/benchmark/crypto/webcrypto-export.js @@ -0,0 +1,47 @@ +'use strict'; + +const common = require('../common.js'); +const fixtures = require('../../test/common/fixtures.js'); +const { createPrivateKey, createPublicKey, subtle } = require('node:crypto'); + +const bench = common.createBenchmark(main, { + keyType: ['hmac', 'aes-gcm', 'ecdsa-private', 'rsa-private', 'rsa-public'], + n: [1e5], +}); + +async function createKey(keyType) { + switch (keyType) { + case 'hmac': + return subtle.importKey( + 'raw', new Uint8Array(32), { name: 'HMAC', hash: 'SHA-256' }, + true, ['sign', 'verify']); + case 'aes-gcm': + return subtle.importKey( + 'raw', new Uint8Array(32), 'AES-GCM', + true, ['encrypt', 'decrypt', 'wrapKey', 'unwrapKey']); + case 'ecdsa-private': + return createPrivateKey(fixtures.readKey('ec_p256_private.pem')) + .toCryptoKey({ name: 'ECDSA', namedCurve: 'P-256' }, true, ['sign']); + case 'rsa-private': + return createPrivateKey(fixtures.readKey('rsa_private_2048.pem')) + .toCryptoKey({ name: 'RSA-PSS', hash: 'SHA-256' }, true, ['sign']); + case 'rsa-public': + return createPublicKey(fixtures.readKey('rsa_private_2048.pem')) + .toCryptoKey({ name: 'RSA-PSS', hash: 'SHA-256' }, true, ['verify']); + default: + throw new Error(`Unsupported key type: ${keyType}`); + } +} + +async function main({ n, keyType }) { + const key = await createKey(keyType); + let result; + + bench.start(); + for (let i = 0; i < n; i++) + result = await subtle.exportKey('jwk', key); + bench.end(n); + + if (result.kty === undefined) + throw new Error('Missing key type'); +} diff --git a/benchmark/ffi/add-64.js b/benchmark/ffi/add-64.js deleted file mode 100644 index d3b8f9e21e03..000000000000 --- a/benchmark/ffi/add-64.js +++ /dev/null @@ -1,26 +0,0 @@ -'use strict'; - -const common = require('../common.js'); -const ffi = require('node:ffi'); -const { libraryPath, ensureFixtureLibrary } = require('./common.js'); - -const bench = common.createBenchmark(main, { - n: [1e7], -}); - -ensureFixtureLibrary(); - -const { lib, functions } = ffi.dlopen(libraryPath, { - add_f64: { return: 'f64', arguments: ['f64', 'f64'] }, -}); - -const add = functions.add_f64; - -function main({ n }) { - bench.start(); - for (let i = 0; i < n; ++i) - add(20.5, 21.5); - bench.end(n); - - lib.close(); -} diff --git a/benchmark/ffi/string-length-buffer-direct.js b/benchmark/ffi/string-length-direct.js similarity index 100% rename from benchmark/ffi/string-length-buffer-direct.js rename to benchmark/ffi/string-length-direct.js diff --git a/benchmark/ffi/string-length-string-direct.js b/benchmark/ffi/string-length-string-direct.js deleted file mode 100644 index b2de28b209e8..000000000000 --- a/benchmark/ffi/string-length-string-direct.js +++ /dev/null @@ -1,28 +0,0 @@ -'use strict'; - -const common = require('../common.js'); -const ffi = require('node:ffi'); -const { libraryPath, ensureFixtureLibrary } = require('./common.js'); - -const bench = common.createBenchmark(main, { - n: [1e7], -}); - -ensureFixtureLibrary(); - -const { lib, functions } = ffi.dlopen(libraryPath, { - string_length: { return: 'u64', arguments: ['pointer'] }, -}); - -const fn = functions.string_length; -const string = Buffer.from('hello\0'); -const pointer = ffi.getRawPointer(string); - -function main({ n }) { - bench.start(); - for (let i = 0; i < n; ++i) - fn(pointer); - bench.end(n); - - lib.close(); -} diff --git a/benchmark/fixtures/coverage-many-branches.js b/benchmark/fixtures/coverage-many-branches.js index 9cb6360336e0..45f9c4b7f525 100644 --- a/benchmark/fixtures/coverage-many-branches.js +++ b/benchmark/fixtures/coverage-many-branches.js @@ -30,7 +30,7 @@ class CoveredClass { } } -// Excercise coverage of functions: +// Exercise coverage of functions: function add(x, y) { const mt = new CoveredClass(x, y); return mt.add(); diff --git a/benchmark/fixtures/simple-http-server.js b/benchmark/fixtures/simple-http-server.js index fb5b0d87c16e..808ee7e4b2dc 100644 --- a/benchmark/fixtures/simple-http-server.js +++ b/benchmark/fixtures/simple-http-server.js @@ -114,6 +114,12 @@ module.exports = http.createServer((req, res) => { else res.writeHead(status, { 'Content-Length': len.toString() }); break; + case 'setHeaderImplicit': + // Let end() derive the message framing: no Content-Length or + // Transfer-Encoding header and no writeHead() call. + res.statusCode = status; + res.setHeader('Content-Type', 'text/plain'); + break; default: if (chunkedEnc) { res.writeHead(status, { diff --git a/benchmark/http/incoming_headers.js b/benchmark/http/incoming_headers.js index 21e15fcd7d69..8a1b8bf7de7a 100644 --- a/benchmark/http/incoming_headers.js +++ b/benchmark/http/incoming_headers.js @@ -6,16 +6,20 @@ const bench = common.createBenchmark(main, { connections: [50], // Concurrent connections headers: [20], // Number of header lines to append after the common headers w: [0, 6], // Amount of trailing whitespace + read: [0, 1], // Whether the handler reads req.headers duration: 5, }); -function main({ connections, headers, w, duration }) { +function main({ connections, headers, w, read, duration }) { const server = http.createServer((req, res) => { + if (read && req.headers.host === undefined) { + throw new Error('Missing Host header'); + } res.end(); }); server.listen(0, () => { - const headers = { + const requestHeaders = { 'Content-Type': 'text/plain', 'Accept': 'text/plain', 'User-Agent': 'nodejs-benchmark', @@ -28,12 +32,12 @@ function main({ connections, headers, w, duration }) { // - wrk can only send trailing OWS. This is a side-effect of wrk // processing requests with http-parser before sending them, causing // leading OWS to be stripped. - headers[`foo${i}`] = `some header value ${i}${' \t'.repeat(w / 2)}`; + requestHeaders[`foo${i}`] = `some header value ${i}${' \t'.repeat(w / 2)}`; } bench.http({ path: '/', connections, - headers, + headers: requestHeaders, duration, port: server.address().port, }, () => { diff --git a/benchmark/http/is_valid_header.js b/benchmark/http/is_valid_header.js new file mode 100644 index 000000000000..cefe5c1f87ce --- /dev/null +++ b/benchmark/http/is_valid_header.js @@ -0,0 +1,120 @@ +'use strict'; + +// Compares the non-throwing header validators (http.isValidHeaderName() and +// http.isValidHeaderValue()) with the throwing ones (http.validateHeaderName() +// and http.validateHeaderValue()) used inside try/catch. + +const common = require('../common.js'); +const assert = require('assert'); +const { + isValidHeaderName, + isValidHeaderValue, + validateHeaderName, + validateHeaderValue, +} = require('http'); + +const inputs = { + name: { + valid: [ + 'ETag', 'date', 'Vary', 'server', 'Expires', 'location', 'Connection', + 'content-type', 'Cache-Control', 'content-length', 'x-frame-options', + 'Transfer-Encoding', 'x-request-id', + ], + invalid: [ + '', ':', 'bad header', 'x-forwarded-fםr', '中文呢', '((((())))', + ':alternate-protocol', 'alternate-protocol:', 'x\r\ninjected', + ], + }, + value: { + valid: [ + 'W/"2-d4cbb29"', 'OK', 'Express', 'application/json', + 'application/json; charset=utf-8', 'sessionid=; Path=/', + 'text/html; charset=utf-8', '10', 'max-age=0, no-cache', 'gzip, br', + ], + // Invalid under both 'strict' and 'relaxed' validation. + invalid: [ + 'a\r\nb', 'value\n', 'cr\r', 'nul\0byte', 'לא תקין', 'emoji \u{1F600}', + 'x'.repeat(64) + '\r\n', + ], + }, +}; + +const bench = common.createBenchmark(main, { + method: [ + 'isValidHeaderName', + 'validateHeaderName', + 'isValidHeaderValue', + 'validateHeaderValue', + ], + input: ['valid', 'invalid'], + httpValidation: ['strict', 'relaxed'], + n: [1e6], +}, { + // httpValidation only applies to isValidHeaderValue(). + combinationFilter: (p) => + p.httpValidation === 'strict' || p.method === 'isValidHeaderValue', +}); + +function main({ n, method, input, httpValidation }) { + let valid = 0; + + switch (method) { + case 'isValidHeaderName': { + const list = inputs.name[input]; + const len = list.length; + bench.start(); + for (let i = 0; i < n; i++) { + if (isValidHeaderName(list[i % len])) valid++; + } + bench.end(n); + break; + } + case 'validateHeaderName': { + const list = inputs.name[input]; + const len = list.length; + bench.start(); + for (let i = 0; i < n; i++) { + try { + validateHeaderName(list[i % len]); + valid++; + } catch { + // Invalid name. + } + } + bench.end(n); + break; + } + case 'isValidHeaderValue': { + const list = inputs.value[input]; + const len = list.length; + const options = httpValidation === 'strict' ? undefined : { httpValidation }; + bench.start(); + for (let i = 0; i < n; i++) { + if (isValidHeaderValue(list[i % len], options)) valid++; + } + bench.end(n); + break; + } + case 'validateHeaderValue': { + const list = inputs.value[input]; + const len = list.length; + bench.start(); + for (let i = 0; i < n; i++) { + try { + validateHeaderValue('x-header', list[i % len]); + valid++; + } catch { + // Invalid value. + } + } + bench.end(n); + break; + } + default: + throw new Error(`Unexpected method: ${method}`); + } + + // Consume the result so the loop cannot be optimized away, and make sure + // the inputs are what they claim to be. + assert.strictEqual(valid, input === 'valid' ? n : 0); +} diff --git a/benchmark/http/set-header.js b/benchmark/http/set-header.js index 8bf00b84ad0a..0936c1309e2d 100644 --- a/benchmark/http/set-header.js +++ b/benchmark/http/set-header.js @@ -2,7 +2,7 @@ const common = require('../common.js'); const bench = common.createBenchmark(main, { - res: ['normal', 'setHeader', 'setHeaderWH'], + res: ['normal', 'setHeader', 'setHeaderWH', 'setHeaderImplicit'], duration: 5, }); @@ -15,6 +15,7 @@ const c = 50; // normal: writeHead(status, {...}) // setHeader: statusCode = status, setHeader(...) x2 // setHeaderWH: setHeader(...), writeHead(status, ...) +// setHeaderImplicit: statusCode = status, setHeader(...) x1, framing left to end() function main({ res, duration }) { const server = require('../fixtures/simple-http-server.js') .listen(0) diff --git a/benchmark/mime/mimetype-parse.js b/benchmark/mime/mimetype-parse.js new file mode 100644 index 000000000000..2aec20ceb062 --- /dev/null +++ b/benchmark/mime/mimetype-parse.js @@ -0,0 +1,53 @@ +'use strict'; + +const common = require('../common'); +const assert = require('assert'); +const { MIMEType } = require('util'); + +const bench = common.createBenchmark(main, { + n: [1e5], + value: [ + 'application/json', + 'text/html; charset=utf-8', + 'multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW', + 'text/plain; charset="utf-8"; foo="b\\"ar"; x=y', + 'not a mime type', + ], + operation: ['parse', 'essence', 'params.get'], +}); + +function main({ n, value, operation }) { + const length = 1024; + const array = []; + let fn; + switch (operation) { + case 'parse': + fn = () => MIMEType.parse(value); + break; + case 'essence': + fn = () => MIMEType.parse(value)?.essence ?? null; + break; + case 'params.get': + fn = () => MIMEType.parse(value)?.params.get('charset') ?? null; + break; + default: + throw new Error(`Unsupported operation ${operation}`); + } + + // Warm up. + for (let i = 0; i < length; ++i) { + array.push(fn()); + } + + bench.start(); + for (let i = 0; i < n; ++i) { + array[i % length] = fn(); + } + bench.end(n); + + // Verify the entries to prevent dead code elimination from making + // the benchmark invalid. + for (let i = 0; i < length; ++i) { + assert.notStrictEqual(array[i], undefined); + } +} diff --git a/benchmark/misc/startup-cli-version.js b/benchmark/misc/startup-cli-version.js index a553f90621f4..f67be6263feb 100644 --- a/benchmark/misc/startup-cli-version.js +++ b/benchmark/misc/startup-cli-version.js @@ -8,7 +8,7 @@ const path = require('path'); // checked into the source code. We use --version because the output // tends to be minimal and fewer operations are done to generate // these so that the startup cost is still dominated by a more -// indispensible part of the CLI. +// indispensable part of the CLI. // NOTE: not all tools are present in tarball hence need to filter const availableCli = [ 'tools/eslint/node_modules/eslint/bin/eslint.js', diff --git a/benchmark/misc/structured-clone.js b/benchmark/misc/structured-clone.js index 257671df44b0..38c0d0aed232 100644 --- a/benchmark/misc/structured-clone.js +++ b/benchmark/misc/structured-clone.js @@ -4,7 +4,7 @@ const common = require('../common.js'); const assert = require('assert'); const bench = common.createBenchmark(main, { - type: ['string', 'object', 'arraybuffer'], + type: ['int', 'string', 'object', 'arraybuffer'], n: [1e4], }); @@ -12,6 +12,11 @@ function main({ n, type }) { const data = []; switch (type) { + case 'int': + for (let i = 0; i < n; ++i) { + data.push(i); + } + break; case 'string': for (let i = 0; i < n; ++i) { data.push(new Date().toISOString()); diff --git a/benchmark/misc/webcrypto-util.js b/benchmark/misc/webcrypto-util.js new file mode 100644 index 000000000000..581602ab347f --- /dev/null +++ b/benchmark/misc/webcrypto-util.js @@ -0,0 +1,117 @@ +'use strict'; + +const common = require('../common.js'); + +const inputs = [ + 'arraybuffer', + 'uint8array', + 'dataview', + 'buffer', + 'sharedview', + 'empty-arraybuffer', + 'empty-uint8array', + 'empty-dataview', + 'detached-arraybuffer', + 'detached-uint8array', + 'detached-dataview', +]; + +const bench = common.createBenchmark(main, { + op: [ + ...inputs.flatMap((input) => [`byteLength:${input}`, `bytes:${input}`]), + 'truncate:arraybuffer:100', + 'truncate:arraybuffer:128', + 'truncate:uint8array:100', + 'truncate:uint8array:128', + 'usages:0', + 'usages:1', + 'usages:2', + 'usages:4', + ], + n: [1e6], +}, { flags: ['--expose-internals'] }); + +function createInput(input) { + const empty = input.startsWith('empty-'); + const detached = input.startsWith('detached-'); + const type = input.replace(/^(empty|detached)-/, ''); + const size = empty ? 0 : 32; + const buffer = new ArrayBuffer(size + 16); + let value; + switch (type) { + case 'arraybuffer': + value = new ArrayBuffer(size); + break; + case 'uint8array': + value = new Uint8Array(buffer, 8, size); + break; + case 'dataview': + value = new DataView(buffer, 8, size); + break; + case 'buffer': + value = Buffer.from(buffer, 8, size); + break; + case 'sharedview': + value = new Uint8Array(new SharedArrayBuffer(size)); + break; + default: + throw new Error(`Unsupported input: ${input}`); + } + if (detached) { + const backing = type === 'arraybuffer' ? value : buffer; + structuredClone(backing, { transfer: [backing] }); + } + return value; +} + +function main({ n, op }) { + const { + getBufferSourceByteLength, + getBufferSourceBytes, + getUsagesFromMask, + getUsagesMask, + truncateToBitLength, + } = require('internal/crypto/util'); + const [operation, input, length] = op.split(':'); + let run; + switch (operation) { + case 'byteLength': { + const value = createInput(input); + run = () => getBufferSourceByteLength(value); + break; + } + case 'bytes': { + const value = createInput(input); + run = () => getBufferSourceBytes(value); + break; + } + case 'truncate': { + const value = createInput(input); + const bits = Number(length); + run = () => truncateToBitLength(bits, value); + break; + } + case 'usages': { + const usages = { + 0: [], + 1: ['sign'], + 2: ['sign', 'verify'], + 4: ['encrypt', 'decrypt', 'wrapKey', 'unwrapKey'], + }; + const mask = getUsagesMask(usages[input]); + run = () => getUsagesFromMask(mask); + break; + } + default: + throw new Error(`Unsupported operation: ${operation}`); + } + + let result; + bench.start(); + for (let i = 0; i < n; i++) + result = run(); + bench.end(n); + + if (result === undefined) + throw new Error('Missing benchmark result'); +} diff --git a/benchmark/misc/webcrypto-webidl.js b/benchmark/misc/webcrypto-webidl.js index 0f6275ed0951..318ea7982071 100644 --- a/benchmark/misc/webcrypto-webidl.js +++ b/benchmark/misc/webcrypto-webidl.js @@ -6,6 +6,13 @@ const bench = common.createBenchmark(main, { op: [ 'normalizeAlgorithm-string', 'normalizeAlgorithm-dict', + 'normalizeAlgorithm-validate-aes-gcm', + 'normalizeAlgorithm-validate-aes-cbc', + 'normalizeAlgorithm-validate-aes-ctr', + 'normalizeAlgorithm-validate-aes-generate', + 'normalizeAlgorithm-validate-hkdf', + 'normalizeAlgorithm-validate-hmac', + 'normalizeAlgorithm-validate-rsa', 'webidl-dict', 'webidl-algorithm-identifier-string', 'webidl-algorithm-identifier-object', @@ -17,7 +24,7 @@ const bench = common.createBenchmark(main, { }, { flags: ['--expose-internals'] }); function main({ n, op }) { - const { normalizeAlgorithm } = require('internal/crypto/util'); + const { normalizeAlgorithm, validateAlgorithm } = require('internal/crypto/util'); switch (op) { case 'normalizeAlgorithm-string': { @@ -37,6 +44,54 @@ function main({ n, op }) { bench.end(n); break; } + case 'normalizeAlgorithm-validate-aes-gcm': + case 'normalizeAlgorithm-validate-aes-cbc': + case 'normalizeAlgorithm-validate-aes-ctr': + case 'normalizeAlgorithm-validate-aes-generate': + case 'normalizeAlgorithm-validate-hkdf': + case 'normalizeAlgorithm-validate-hmac': + case 'normalizeAlgorithm-validate-rsa': { + const cases = { + 'aes-gcm': [ + { name: 'AES-GCM', iv: new Uint8Array(12), tagLength: 128 }, + 'encrypt', + ], + 'aes-cbc': [ + { name: 'AES-CBC', iv: new Uint8Array(16) }, + 'encrypt', + ], + 'aes-ctr': [ + { name: 'AES-CTR', counter: new Uint8Array(16), length: 64 }, + 'encrypt', + ], + 'aes-generate': [{ name: 'AES-GCM', length: 256 }, 'generateKey'], + 'hkdf': [ + { + name: 'HKDF', hash: 'SHA-256', + salt: new Uint8Array(32), info: new Uint8Array(32), + }, + 'deriveBits', + ], + 'hmac': [{ name: 'HMAC', hash: 'SHA-256', length: 256 }, 'importKey'], + 'rsa': [ + { + name: 'RSA-PSS', hash: 'SHA-256', modulusLength: 2048, + publicExponent: new Uint8Array([1, 0, 1]), + }, + 'generateKey', + ], + }; + const name = op.slice('normalizeAlgorithm-validate-'.length); + const [input, operation] = cases[name]; + bench.start(); + for (let i = 0; i < n; i++) { + const normalized = normalizeAlgorithm(input, operation); + // Older revisions validate inside normalizeAlgorithm. + validateAlgorithm?.(normalized, operation); + } + bench.end(n); + break; + } case 'webidl-dict': { // WebIDL dictionary converter in isolation. const webidl = require('internal/crypto/webidl'); @@ -85,7 +140,7 @@ function main({ n, op }) { break; } case 'webidl-dict-ensure-sha': { - // Exercises ensureSHA on a hash member. + // Converts a dictionary containing a hash identifier. const webidl = require('internal/crypto/webidl'); const input = { name: 'RSASSA-PKCS1-v1_5', hash: 'SHA-256' }; const opts = { prefix: 'test', context: 'test' }; diff --git a/benchmark/napi/make_callback/.gitignore b/benchmark/napi/make_callback/.gitignore new file mode 100644 index 000000000000..567609b1234a --- /dev/null +++ b/benchmark/napi/make_callback/.gitignore @@ -0,0 +1 @@ +build/ diff --git a/benchmark/napi/make_callback/binding.cc b/benchmark/napi/make_callback/binding.cc new file mode 100644 index 000000000000..85d335170fb0 --- /dev/null +++ b/benchmark/napi/make_callback/binding.cc @@ -0,0 +1,58 @@ +#include +#include +#include + +using v8::Context; +using v8::Function; +using v8::FunctionCallbackInfo; +using v8::Global; +using v8::HandleScope; +using v8::Isolate; +using v8::Local; +using v8::Object; +using v8::Value; + +struct State { + uv_timer_t timer; + Isolate* isolate; + int64_t n; + Global fn; + Global done; +}; + +static void OnTimer(uv_timer_t* handle) { + State* state = static_cast(handle->data); + Isolate* isolate = state->isolate; + HandleScope handle_scope(isolate); + Local fn = state->fn.Get(isolate); + Local context = fn->GetCreationContextChecked(isolate); + Context::Scope context_scope(context); + Local recv = context->Global(); + for (int64_t i = 0; i < state->n; i++) { + HandleScope inner_scope(isolate); + (void)node::MakeCallback(isolate, recv, fn, 0, nullptr, {0, 0}); + } + Local done = state->done.Get(isolate); + (void)node::MakeCallback(isolate, recv, done, 0, nullptr, {0, 0}); + uv_close(reinterpret_cast(&state->timer), + [](uv_handle_t* h) { delete static_cast(h->data); }); +} + +// run(n, fn, done): calls fn n times from a timer, then calls done. +static void Run(const FunctionCallbackInfo& args) { + Isolate* isolate = args.GetIsolate(); + State* state = new State; + state->isolate = isolate; + state->n = args[0]->IntegerValue(isolate->GetCurrentContext()).FromJust(); + state->fn.Reset(isolate, args[1].As()); + state->done.Reset(isolate, args[2].As()); + state->timer.data = state; + uv_timer_init(node::GetCurrentEventLoop(isolate), &state->timer); + uv_timer_start(&state->timer, OnTimer, 0, 0); +} + +static void Initialize(Local target, Local module, void* data) { + NODE_SET_METHOD(target, "run", Run); +} + +NODE_MODULE(NODE_GYP_MODULE_NAME, Initialize) diff --git a/benchmark/napi/make_callback/binding.gyp b/benchmark/napi/make_callback/binding.gyp new file mode 100644 index 000000000000..3bfb84493f3e --- /dev/null +++ b/benchmark/napi/make_callback/binding.gyp @@ -0,0 +1,8 @@ +{ + 'targets': [ + { + 'target_name': 'binding', + 'sources': [ 'binding.cc' ] + } + ] +} diff --git a/benchmark/napi/make_callback/index.js b/benchmark/napi/make_callback/index.js new file mode 100644 index 000000000000..8c3dba383437 --- /dev/null +++ b/benchmark/napi/make_callback/index.js @@ -0,0 +1,23 @@ +'use strict'; + +const common = require('../../common.js'); + +// The addon calls into JS with node::MakeCallback from a libuv timer, so +// every call opens a top-level callback scope, like an I/O callback does. + +let binding; +try { + binding = require(`./build/${common.buildType}/binding`); +} catch { + console.error('napi/make_callback/index.js Binding failed to load'); + process.exit(0); +} + +const bench = common.createBenchmark(main, { + n: [1e6, 1e7], +}); + +function main({ n }) { + bench.start(); + binding.run(n, () => {}, () => bench.end(n)); +} diff --git a/benchmark/perf_hooks/histogram-snapshot.js b/benchmark/perf_hooks/histogram-snapshot.js new file mode 100644 index 000000000000..79b13fecb0f6 --- /dev/null +++ b/benchmark/perf_hooks/histogram-snapshot.js @@ -0,0 +1,24 @@ +'use strict'; + +const assert = require('assert'); +const common = require('../common.js'); +const { createHistogram } = require('perf_hooks'); + +const bench = common.createBenchmark(main, { + n: [1e3], + highest: [1e6, Number.MAX_SAFE_INTEGER], + figures: [2, 3], +}); + +let snapshot; + +function main({ n, highest, figures }) { + const histogram = createHistogram({ highest, figures }); + for (let i = 1; i <= 1e4; i++) histogram.record(i); + + bench.start(); + for (let i = 0; i < n; i++) snapshot = histogram.snapshot(); + bench.end(n); + + assert.strictEqual(snapshot.count, 1e4); +} diff --git a/benchmark/perf_hooks/nodetiming-uvmetricsinfo.js b/benchmark/perf_hooks/nodetiming-uvmetricsinfo.js index 1d8d174de14f..d646631f4e9c 100644 --- a/benchmark/perf_hooks/nodetiming-uvmetricsinfo.js +++ b/benchmark/perf_hooks/nodetiming-uvmetricsinfo.js @@ -11,6 +11,7 @@ const { const bench = common.createBenchmark(main, { n: [1e6], events: [1, 1000, 10000], + api: ['number', 'bigint'], }); async function runEvents(events) { @@ -19,11 +20,19 @@ async function runEvents(events) { } } -async function main({ n, events }) { +async function main({ n, events, api }) { await runEvents(events); - bench.start(); - for (let i = 0; i < n; i++) { - assert.ok(performance.nodeTiming.uvMetricsInfo); + if (api === 'bigint') { + bench.start(); + for (let i = 0; i < n; i++) { + assert.ok(performance.nodeTiming.uvMetricsInfoBigInt); + } + bench.end(n); + } else { + bench.start(); + for (let i = 0; i < n; i++) { + assert.ok(performance.nodeTiming.uvMetricsInfo); + } + bench.end(n); } - bench.end(n); } diff --git a/benchmark/sqlite/sqlite-diagnostic-channel.js b/benchmark/sqlite/sqlite-diagnostic-channel.js index 0610839653df..a962a97d7c3b 100644 --- a/benchmark/sqlite/sqlite-diagnostic-channel.js +++ b/benchmark/sqlite/sqlite-diagnostic-channel.js @@ -12,7 +12,7 @@ const bench = common.createBenchmark(main, { function main(conf) { const { n, mode } = conf; - const db = new sqlite.DatabaseSync(':memory:'); + const db = new sqlite.Database(':memory:'); db.exec('CREATE TABLE t (x INTEGER)'); const insert = db.prepare('INSERT INTO t VALUES (?)'); diff --git a/benchmark/sqlite/sqlite-is-transaction.js b/benchmark/sqlite/sqlite-is-transaction.js index dca31a18d986..b4b7f238d038 100644 --- a/benchmark/sqlite/sqlite-is-transaction.js +++ b/benchmark/sqlite/sqlite-is-transaction.js @@ -9,7 +9,7 @@ const bench = common.createBenchmark(main, { }); function main(conf) { - const db = new sqlite.DatabaseSync(':memory:'); + const db = new sqlite.Database(':memory:'); if (conf.transaction === 'true') { db.exec('BEGIN'); diff --git a/benchmark/sqlite/sqlite-prepare-insert.js b/benchmark/sqlite/sqlite-prepare-insert.js index 58e97274c98f..2f56fd5602fa 100644 --- a/benchmark/sqlite/sqlite-prepare-insert.js +++ b/benchmark/sqlite/sqlite-prepare-insert.js @@ -17,7 +17,7 @@ const bench = common.createBenchmark(main, { }); function main(conf) { - const db = new sqlite.DatabaseSync(':memory:'); + const db = new sqlite.Database(':memory:'); db.exec('CREATE TABLE text_column_type (text_column TEXT)'); db.exec('CREATE TABLE integer_column_type (integer_column INTEGER)'); diff --git a/benchmark/sqlite/sqlite-prepare-select-all-options.js b/benchmark/sqlite/sqlite-prepare-select-all-options.js index 336a6b176b0d..9acada928b8b 100644 --- a/benchmark/sqlite/sqlite-prepare-select-all-options.js +++ b/benchmark/sqlite/sqlite-prepare-select-all-options.js @@ -19,7 +19,7 @@ function main(conf) { return acc; }, {}); - const db = new sqlite.DatabaseSync(':memory:', optionsObj); + const db = new sqlite.Database(':memory:', optionsObj); db.exec( 'CREATE TABLE foo (text_column TEXT, integer_column INTEGER, real_column REAL, blob_column BLOB)', diff --git a/benchmark/sqlite/sqlite-prepare-select-all.js b/benchmark/sqlite/sqlite-prepare-select-all.js index c8487dca471b..e4d269b6afda 100644 --- a/benchmark/sqlite/sqlite-prepare-select-all.js +++ b/benchmark/sqlite/sqlite-prepare-select-all.js @@ -24,7 +24,7 @@ const bench = common.createBenchmark(main, { }); function main(conf) { - const db = new sqlite.DatabaseSync(':memory:'); + const db = new sqlite.Database(':memory:'); // Create only the necessary table for the benchmark type. // If the statement includes 'foo_large', create the foo_large table; otherwise, create the foo table. diff --git a/benchmark/sqlite/sqlite-prepare-select-get-options.js b/benchmark/sqlite/sqlite-prepare-select-get-options.js index eb2e5074151a..bbd23b69dcf4 100644 --- a/benchmark/sqlite/sqlite-prepare-select-get-options.js +++ b/benchmark/sqlite/sqlite-prepare-select-get-options.js @@ -18,7 +18,7 @@ function main(conf) { return acc; }, {}); - const db = new sqlite.DatabaseSync(':memory:', optionsObj); + const db = new sqlite.Database(':memory:', optionsObj); db.exec( 'CREATE TABLE foo (text_column TEXT, integer_column INTEGER, real_column REAL, blob_column BLOB)', diff --git a/benchmark/sqlite/sqlite-prepare-select-get.js b/benchmark/sqlite/sqlite-prepare-select-get.js index 0fff29ce5686..c7d2a9f833b0 100644 --- a/benchmark/sqlite/sqlite-prepare-select-get.js +++ b/benchmark/sqlite/sqlite-prepare-select-get.js @@ -18,7 +18,7 @@ const bench = common.createBenchmark(main, { }); function main(conf) { - const db = new sqlite.DatabaseSync(':memory:'); + const db = new sqlite.Database(':memory:'); // Create only the necessary table for the benchmark type. // If the statement includes 'foo_large', create the foo_large table; otherwise, create the foo table. diff --git a/benchmark/streams/iter-throughput-share-sync.js b/benchmark/streams/iter-throughput-share-sync.js new file mode 100644 index 000000000000..3a5de56b5922 --- /dev/null +++ b/benchmark/streams/iter-throughput-share-sync.js @@ -0,0 +1,37 @@ +'use strict'; + +const common = require('../common.js'); + +const bench = common.createBenchmark(main, { + consumers: [2, 8, 32], + batches: [1e4], + n: [5], +}, { + flags: ['--experimental-stream-iter'], +}); + +function main({ consumers, batches, n }) { + const { shareSync } = require('stream/iter'); + const chunk = Buffer.alloc(1024); + let bytes = 0; + + function* source() { + for (let i = 0; i < batches; i++) yield [chunk]; + } + + bench.start(); + for (let run = 0; run < n; run++) { + const shared = shareSync(source(), { budget: 65536 }); + const readers = Array.from({ length: consumers }, () => + shared.pull()[Symbol.iterator]()); + for (let i = 0; i < batches; i++) { + for (let j = 0; j < consumers; j++) { + bytes += readers[j].next().value[0].byteLength; + } + } + } + if (bytes !== batches * consumers * n * chunk.byteLength) { + throw new Error('Incorrect byte count'); + } + bench.end(batches * consumers * n); +} diff --git a/benchmark/webstreams/lifecycle.js b/benchmark/webstreams/lifecycle.js index 421538e4bfd8..00dfced4f212 100644 --- a/benchmark/webstreams/lifecycle.js +++ b/benchmark/webstreams/lifecycle.js @@ -9,7 +9,7 @@ const { const bench = common.createBenchmark(main, { n: [5e4], - kind: ['readable', 'pipe-to', 'pipe-through'], + kind: ['readable', 'async-iterator', 'pipe-to', 'pipe-through'], }); const chunk = Buffer.alloc(1024); @@ -37,6 +37,18 @@ async function readable(n) { assert.strictEqual(chunks, n * 4); } +async function asyncIterator(n) { + let chunks = 0; + bench.start(); + for (let i = 0; i < n; i++) { + for await (const chunk of new ReadableStream(makeSource())) { + if (chunk) chunks++; + } + } + bench.end(n); + assert.strictEqual(chunks, n * 4); +} + async function pipeTo(n) { let chunks = 0; bench.start(); @@ -66,6 +78,9 @@ function main({ n, kind }) { case 'readable': readable(n); break; + case 'async-iterator': + asyncIterator(n); + break; case 'pipe-to': pipeTo(n); break; diff --git a/benchmark/webstreams/writable-write.js b/benchmark/webstreams/writable-write.js new file mode 100644 index 000000000000..9cc6a6af2423 --- /dev/null +++ b/benchmark/webstreams/writable-write.js @@ -0,0 +1,31 @@ +'use strict'; +const common = require('../common.js'); +const assert = require('node:assert'); +const { WritableStream } = require('node:stream/web'); + +const bench = common.createBenchmark(main, { + n: [1e5], + type: ['await', 'queued'], +}); + +async function main({ n, type }) { + let count = 0; + const ws = new WritableStream({ + write() { + count++; + }, + }, { highWaterMark: type === 'queued' ? n : 1 }); + const writer = ws.getWriter(); + bench.start(); + if (type === 'await') { + for (let i = 0; i < n; i++) + await writer.write('a'); + } else { + for (let i = 1; i < n; i++) + writer.write('a'); + await writer.write('a'); + } + bench.end(n); + await writer.close(); + assert.strictEqual(count, n); +} diff --git a/benchmark/zlib/zstd-compress.js b/benchmark/zlib/zstd-compress.js new file mode 100644 index 000000000000..b898397c2228 --- /dev/null +++ b/benchmark/zlib/zstd-compress.js @@ -0,0 +1,41 @@ +'use strict'; +const common = require('../common.js'); +const fs = require('fs'); +const zlib = require('zlib'); + +const bench = common.createBenchmark(main, { + method: ['zstdCompress', 'zstdCompressSync'], + level: [3, 12], + inputLen: [16 * 1024, 256 * 1024], + n: [100], +}); + +function main({ n, method, level, inputLen }) { + const input = Buffer.alloc(inputLen, fs.readFileSync(__filename)); + const opts = { params: { [zlib.constants.ZSTD_c_compressionLevel]: level } }; + + switch (method) { + // Performs `n` single zstdCompress operations + case 'zstdCompress': { + let i = 0; + bench.start(); + (function next(err) { + if (err) throw err; + if (i++ === n) + return bench.end(n); + zlib.zstdCompress(input, opts, next); + })(); + break; + } + // Performs `n` single zstdCompressSync operations + case 'zstdCompressSync': { + bench.start(); + for (let i = 0; i < n; ++i) + zlib.zstdCompressSync(input, opts); + bench.end(n); + break; + } + default: + throw new Error('Unsupported zstd method'); + } +} diff --git a/common.gypi b/common.gypi index 71712d308472..de80a68f492f 100644 --- a/common.gypi +++ b/common.gypi @@ -12,6 +12,7 @@ 'msvs_multi_core_compile': '0', # we do enable multicore compiles, but not using the V8 way 'enable_pgo_generate%': '0', 'enable_pgo_use%': '0', + 'pgo_profile%': '', 'clang_profile_lib%': '', 'python%': 'python', 'emulator%': [], @@ -43,7 +44,7 @@ # Reset this number to 0 on major V8 upgrades. # Increment by one for each non-official patch applied to deps/v8. - 'v8_embedder_string': '-node.34', + 'v8_embedder_string': '-node.37', ##### V8 defaults for Node.js ##### @@ -128,10 +129,6 @@ ['OS=="linux" or OS=="openharmony"', { 'node_section_ordering_info%': '' }], - ['OS == "zos"', { - # use ICU data file on z/OS - 'icu_use_data_file_flag%': 1 - }] ], }, @@ -193,6 +190,7 @@ }], ['clang==1', { 'lto': ' -flto ', # Clang + 'pgo_use': '-fprofile-use=<(pgo_profile)', }, { 'lto': ' -flto=4 -ffat-lto-objects ', # GCC }], @@ -225,11 +223,7 @@ # pull in V8's postmortem metadata 'ldflags': [ '-Wl,-z,allextract' ] }], - ['OS=="zos"', { - # increase performance, number from experimentation - 'cflags': [ '-qINLINE=::150:100000' ] - }], - ['OS!="mac" and OS!="win" and OS!="zos"', { + ['OS!="mac" and OS!="win"', { # -fno-omit-frame-pointer is necessary for the --perf_basic_prof # flag to work correctly. perf(1) gets confused about JS stack # frames otherwise, even with --call-graph dwarf. @@ -247,6 +241,34 @@ },], ], },], + ['OS=="mac"', { + 'conditions': [ + ['enable_pgo_generate=="true"', { + 'xcode_settings': { + 'OTHER_CFLAGS': ['<(pgo_generate)'], + }, + 'target_conditions': [ + ['_type!="static_library"', { + 'xcode_settings': { + 'OTHER_LDFLAGS': ['<(pgo_generate)'], + }, + }], + ], + }], + ['enable_pgo_use=="true"', { + 'xcode_settings': { + 'OTHER_CFLAGS': ['<(pgo_use)'], + }, + 'target_conditions': [ + ['_type!="static_library"', { + 'xcode_settings': { + 'OTHER_LDFLAGS': ['<(pgo_use)'], + }, + }], + ], + }], + ], + }], ['OS=="win"', { 'conditions': [ ['enable_lto=="true"', { @@ -455,7 +477,7 @@ [ 'target_arch=="arm64"', { 'msvs_configuration_platform': 'arm64', }], - ['asan == 1 and OS != "mac" and OS != "zos"', { + ['asan == 1 and OS != "mac"', { 'cflags+': [ '-fno-omit-frame-pointer', '-fsanitize=address', @@ -483,7 +505,7 @@ }], ], }], - ['ubsan == 1 and OS != "mac" and OS != "zos"', { + ['ubsan == 1 and OS != "mac"', { 'cflags+': [ '-fno-omit-frame-pointer', '-fsanitize=undefined', @@ -566,11 +588,11 @@ 'NOMINMAX', ], }], - [ 'OS in "linux freebsd openbsd solaris aix os400 openharmony"', { + [ 'OS in "linux freebsd openbsd solaris aix os400 openharmony zos"', { 'cflags': [ '-pthread' ], 'ldflags': [ '-pthread' ], }], - [ 'OS in "linux freebsd openbsd solaris android aix os400 cloudabi openharmony"', { + [ 'OS in "linux freebsd openbsd solaris android aix os400 cloudabi openharmony zos"', { 'cflags': [ '-Wall', '-Wextra', '-Wno-unused-parameter', ], 'cflags_cc': [ '-fno-rtti', @@ -589,6 +611,9 @@ 'cflags': [ '-I/usr/local/include' ], 'ldflags': [ '-Wl,-z,wxneeded' ], }], + [ 'OS=="zos"', { + 'ldflags!': [ '-rdynamic' ], + }], ['_toolset=="host"', { 'conditions': [ [ 'host_arch=="ia32"', { @@ -807,6 +832,8 @@ }], ['OS == "zos"', { 'defines': [ + 'ZOSLIB_OVERRIDE_CLIB', + 'ZOSLIB_ALIGNED_NEWDEL', '_XOPEN_SOURCE_EXTENDED', '_XOPEN_SOURCE=600', '_UNIX03_THREADS', @@ -814,40 +841,37 @@ '_UNIX03_SOURCE', '_OPEN_SYS_SOCK_IPV6', '_OPEN_SYS_FILE_EXT=1', + '_POSIX_C_SOURCE=200809L', '_POSIX_SOURCE', '_OPEN_SYS', '_OPEN_SYS_IF_EXT', - '_OPEN_SYS_SOCK_IPV6', '_OPEN_MSGQ_EXT', '_LARGE_TIME_API', - '_ALL_SOURCE', '_AE_BIMODAL=1', - '__IBMCPP_TR1__', + '_EXT', 'NODE_PLATFORM="os390"', 'PATH_MAX=1024', '_ENHANCED_ASCII_EXT=0xFFFFFFFF', - '_Export=extern', - '__static_assert=static_assert', ], 'cflags': [ - '-q64', - '-Wc,DLL', - '-Wa,GOFF', - '-qARCH=10', - '-qASCII', - '-qTUNE=12', - '-qENUM=INT', - '-qEXPORTALL', - '-qASM', - ], - 'cflags_cc': [ - '-qxclang=-std=c++14', + '-fno-short-enums', + '-fno-xl-pragma-pack', + '-fstack-protector', + '-fvisibility=default', + '-fzos-le-char-mode=ascii', + '-m64', + '-march=z14', + '-mzos-target=zosv2r5', ], 'ldflags': [ - '-q64', + '-m64', + '-mzos-target=zosv2r5', ], # for addons due to v8config.h include of "zos-base.h": - 'include_dirs': ['<(zoslib_include_dir)'], + 'include_dirs': [ + '<(zoslib_include_dir)', + '<(zoslib_include_dir)/include-wrappers/c++', + ], }], ], } diff --git a/configure.py b/configure.py index 8b3332a461f4..acda6a16c96c 100755 --- a/configure.py +++ b/configure.py @@ -208,14 +208,15 @@ dest="enable_pgo_generate", default=None, help="Enable profiling with pgo of a binary. This feature is only available " - "on linux with gcc and g++ 5.4.1 or newer and on windows.") + "on linux with GCC or Clang, on macOS with Clang, and on windows.") parser.add_argument("--enable-pgo-use", action="store_true", dest="enable_pgo_use", default=None, help="Enable use of the profile generated with --enable-pgo-generate. This " - "feature is only available on linux with gcc and g++ 5.4.1 or newer and on windows.") + "feature is only available on linux with GCC or Clang, on macOS " + "with Clang, and on windows.") parser.add_argument("--enable-lto", action="store_true", @@ -847,7 +848,7 @@ static_optgroup.add_argument('--static-zoslib-gyp', action='store', dest='static_zoslib_gyp', - help='path to zoslib.gyp file for includes and to link to static zoslib library') + help='path to zoslib.gyp file for includes and to link to static zoslib libraries') parser.add_argument('--tag', action='store', @@ -1864,12 +1865,13 @@ def configure_mips(o, target_arch): o['variables']['v8_host_byteorder'] = host_byteorder def configure_zos(o): - o['variables']['node_static_zoslib'] = b(True) - if options.static_zoslib_gyp: - # Apply to all Node.js components for now - o['variables']['zoslib_include_dir'] = Path(options.static_zoslib_gyp).parent / 'include' + if os.environ.get('ZOSLIB_INCLUDES'): + o['variables']['zoslib_include_dir'] = os.environ.get('ZOSLIB_INCLUDES') o['include_dirs'] += [o['variables']['zoslib_include_dir']] else: + raise Exception('Environment variable ZOSLIB_INCLUDES= is required.') + + if not options.static_zoslib_gyp: raise Exception('--static-zoslib-gyp= is required.') def clang_version_ge(version_checked): @@ -2004,18 +2006,9 @@ def configure_node(o): else: o['variables']['node_enable_v8_vtunejit'] = 'false' - if (flavor != 'linux' and flavor != 'win') and (options.enable_pgo_generate or options.enable_pgo_use): + if flavor not in ('linux', 'mac', 'win') and (options.enable_pgo_generate or options.enable_pgo_use): raise Exception( - 'The pgo option is supported only on linux and windows.') - - if flavor == 'linux': - if options.enable_pgo_generate or options.enable_pgo_use: - version_checked = (5, 4, 1) - if not gcc_version_ge(version_checked): - version_checked_str = ".".join(map(str, version_checked)) - raise Exception( - 'The options --enable-pgo-generate and --enable-pgo-use ' - f'are supported for gcc and gxx {version_checked_str} or newer only.') + 'The pgo option is supported only on linux, macOS, and windows.') if options.enable_pgo_generate and options.enable_pgo_use: raise Exception( @@ -2024,6 +2017,24 @@ def configure_node(o): '--enable-pgo-generate first, profile node, and then recompile ' 'with --enable-pgo-use') + if flavor in ('linux', 'mac'): + if options.enable_pgo_generate or options.enable_pgo_use: + clang_compilers = [try_check_compiler(compiler, language)[1] + for compiler, language in ((CC, 'c'), (CXX, 'c++'))] + if all(clang_compilers): + profile = os.path.abspath('node.profdata') + if options.enable_pgo_use and not os.path.isfile(profile): + raise Exception( + f'PGO profile not found: {profile}. Run llvm-profdata merge first.') + o['variables']['pgo_profile'] = profile + elif flavor == 'mac' or any(clang_compilers): + raise Exception('PGO requires both CC and CXX to use Clang on macOS ' + 'or the same compiler family on linux.') + elif not gcc_version_ge((5, 4, 1)): + raise Exception( + 'The options --enable-pgo-generate and --enable-pgo-use ' + 'require gcc and gxx 5.4.1 or newer.') + o['variables']['enable_pgo_generate'] = b(options.enable_pgo_generate) o['variables']['enable_pgo_use'] = b(options.enable_pgo_use) @@ -2261,9 +2272,6 @@ def configure_v8(o, configs): case 'none': warn('Temporal support disabled when compiling without ICU') options.v8_disable_temporal_support = True - case 'system-icu': - warn('Temporal support disabled when compiling with a shared ICU library') - options.v8_disable_temporal_support = True o['variables']['v8_enable_temporal_support'] = 0 if options.v8_disable_temporal_support else 1 o['variables']['v8_trace_maps'] = 1 if options.trace_maps else 0 o['variables']['v8_use_perfetto'] = 1 if options.with_perfetto else 0 @@ -2544,6 +2552,8 @@ def icu_download(path): # always set icu_small, node.gyp depends on it being defined. o['variables']['icu_small'] = b(False) o['variables']['icu_system'] = b(False) + # always set this + o['variables']['v8_enable_temporal_systemicu'] = 1 # prevent data override o['defines'] += ['ICU_NO_USER_DATA_OVERRIDE'] @@ -2786,8 +2796,8 @@ def icu_download(path): icu_config['variables']['icu_asm_ext'] = 'S' icu_config['variables']['icu_asm_opts'] = [ '-a', 'xlc' ] elif sys.platform == 'zos': - icu_config['variables']['icu_asm_ext'] = 'S' - icu_config['variables']['icu_asm_opts'] = [ '-a', 'zos' ] + icu_config['variables']['icu_asm_ext'] = 'c' + icu_config['variables']['icu_asm_opts'] = [] else: # assume GCC-compatible asm is OK icu_config['variables']['icu_asm_ext'] = 'S' diff --git a/deps/LIEF/LICENSE b/deps/LIEF/LICENSE index 0c225d7eeb80..f0c1a1afd4c6 100644 --- a/deps/LIEF/LICENSE +++ b/deps/LIEF/LICENSE @@ -186,8 +186,8 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright 2017 - 2025 R. Thomas - Copyright 2017 - 2025 Quarkslab + Copyright 2017 - 2026 R. Thomas + Copyright 2017 - 2026 Quarkslab Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/deps/LIEF/README.md b/deps/LIEF/README.md index 0276c436d973..4e7c41949f3b 100644 --- a/deps/LIEF/README.md +++ b/deps/LIEF/README.md @@ -17,28 +17,39 @@ modify and abstract ELF, PE and MachO formats. **Main features**: - * **Parsing**: LIEF can parse [ELF](https://lief.re/doc/latest/formats/elf/index.html), [PE](https://lief.re/doc/latest/formats/pe/index.html), [MachO](https://lief.re/doc/latest/formats/macho/index.html), [COFF](https://lief.re/doc/latest/formats/coff/index.html), OAT, DEX, VDEX, ART and provides an user-friendly API to access to internals. - * **Modify**: LIEF can use to modify some parts of these formats (adding a section, changing a symbol's name, ...) + * **Parsing**: LIEF can parse [ELF](https://lief.re/doc/latest/formats/elf/index.html), [PE](https://lief.re/doc/latest/formats/pe/index.html), [MachO](https://lief.re/doc/latest/formats/macho/index.html), [COFF](https://lief.re/doc/latest/formats/coff/index.html), OAT, DEX, VDEX, ART and provides a user-friendly API to access their internals. + * **Modify**: LIEF can be used to modify some parts of these formats (adding a section, changing a symbol's name, ...) * **Abstract**: Three formats have common features like sections, symbols, entry point... LIEF factors them. - * **API**: LIEF can be used in [C++](https://lief.re/doc/latest/doxygen/), Python, [Rust](https://lief-rs.s3.fr-par.scw.cloud/doc/latest/lief/index.html) and C + * **API**: You can use LIEF via [C++](https://lief.re/doc/latest/doxygen/), Python, [Rust](https://lief-rs.s3.fr-par.scw.cloud/doc/latest/lief/index.html), C and + [Node.js](https://github.com/Piebald-AI/node-lief) (unofficial, AI-generated) **Extended features**: + * [**Runtime**](https://lief.re/doc/latest/runtime/intro.html) * [**DWARF/PDB** Support](https://lief.re/doc/latest/extended/debug_info/index.html) * [**Objective-C** Metadata](https://lief.re/doc/latest/extended/objc/index.html) * [**Dyld Shared Cache**](https://lief.re/doc/latest/extended/dsc/index.html) with support for extracting Dylib * [**Disassembler**](https://lief.re/doc/latest/extended/disassembler/index.html): AArch64, x86/x86-64, ARM, RISC-V, Mips, PowerPC, eBPF - * [**Assembler**](https://lief.re/doc/latest/extended/assembler/index.html): AArch64, x86/x86-64 + * [**Assembler**](https://lief.re/doc/latest/extended/assembler/index.html): AArch64, x86/x86-64, RISC-V **Plugins**: * [**Ghidra**](https://lief.re/doc/latest/plugins/ghidra/index.html) * [**BinaryNinja**](https://lief.re/doc/latest/plugins/binaryninja/index.html) +# Sponsors + +
+

+ +
+
+

+ # Content - [About](#about) -- [Download / Install](#downloads--install) +- [Downloads / Install](#downloads--install) - [Getting started](#getting-started) - [Blog](https://lief.re/blog/) - [Documentation](#documentation) @@ -56,21 +67,21 @@ modify and abstract ELF, PE and MachO formats. - [ELF Coredump](https://lief.re/doc/latest/tutorials/12_elf_coredump.html) - [PE Authenticode](https://lief.re/doc/latest/tutorials/13_pe_authenticode.html) - [Contact](#contact) -- [About](#about) +- [About](#about-1) - [Authors](#authors) - [License](#license) - [Bibtex](#bibtex) ## Downloads / Install -## C++ +### C++ ```cmake find_package(LIEF REQUIRED) target_link_libraries(my-project LIEF::LIEF) ``` -## Rust +### Rust ```toml [package] @@ -79,10 +90,16 @@ version = "0.0.1" edition = "2021" [dependencies] -lief = "0.17.1" +lief = "1.0.0" ``` -## Python +### Homebrew + +```console +brew install lief +``` + +### Python To install the latest **version** (release): @@ -102,7 +119,7 @@ pip install [--user] --force-reinstall --index-url https://lief.s3-website.fr-pa - **Nightly**: * SDK: https://lief.s3-website.fr-par.scw.cloud/latest/sdk * Python Wheels: https://lief.s3-website.fr-par.scw.cloud/latest/lief -- **v0.17.1**: https://github.com/lief-project/LIEF/releases/tag/0.17.1 +- **v1.0.0**: https://github.com/lief-project/LIEF/releases/tag/1.0.0 Here are guides to install or integrate LIEF: @@ -124,15 +141,14 @@ for section in binary.sections: print(section.name, section.virtual_address) # PE -binary = lief.parse("C:\\Windows\\explorer.exe") - -if rheader := pe.rich_header: +binary = lief.parse(r"C:\Windows\explorer.exe") +if (rheader := binary.rich_header) is not None: print(rheader.key) # Mach-O binary = lief.parse("/usr/bin/ls") -for fixup in binary.dyld_chained_fixups: - print(fixup) +if (fixups := binary.dyld_chained_fixups) is not None: + print(fixups) ``` ### Rust @@ -153,27 +169,30 @@ if let Some(Binary::PE(pe)) = Binary::parse(path.as_str()) { ### C++ ```cpp +#include #include int main(int argc, char** argv) { // ELF if (std::unique_ptr elf = LIEF::ELF::Parser::parse("/bin/ls")) { for (const LIEF::ELF::Section& section : elf->sections()) { - std::cout << section->name() << ' ' << section->virtual_address() << '\n'; + std::cout << section.name() << ' ' << section.virtual_address() << '\n'; } } // PE if (std::unique_ptr pe = LIEF::PE::Parser::parse("C:\\Windows\\explorer.exe")) { - if (const LIEF::PE::RichHeader* rheader : pe->rich_header()) { + if (const LIEF::PE::RichHeader* rheader = pe->rich_header()) { std::cout << rheader->key() << '\n'; } } // Mach-O if (std::unique_ptr macho = LIEF::MachO::Parser::parse("/bin/ls")) { - for (const LIEF::MachO::DyldChainedFixups& fixup : macho->dyld_chained_fixups()) { - std::cout << fixup << '\n'; + for (const LIEF::MachO::Binary& bin : *macho) { + if (const LIEF::MachO::DyldChainedFixups* fixups = bin.dyld_chained_fixups()) { + std::cout << *fixups << '\n'; + } } } @@ -182,25 +201,6 @@ int main(int argc, char** argv) { ``` -### C (Limited API) - -```cpp -#include - -int main(int argc, char** argv) { - Elf_Binary_t* elf = elf_parse("/usr/bin/ls"); - - Elf_Section_t** sections = elf->sections; - - for (size_t i = 0; sections[i] != NULL; ++i) { - printf("%s\n", sections[i]->name); - } - - elf_binary_destroy(elf); - return 0; -} -``` - ## Documentation * [Main documentation](https://lief.re/doc/latest/index.html) @@ -220,7 +220,7 @@ Romain Thomas ([@rh0main](https://www.romainthomas.fr/)) - Formerly at [Quarksla ### License -LIEF is provided under the [Apache 2.0 license](https://github.com/lief-project/LIEF/blob/0.17.1/LICENSE). +[Apache 2.0](https://github.com/lief-project/LIEF/blob/1.0.0/LICENSE). ### Bibtex @@ -233,5 +233,3 @@ LIEF is provided under the [Apache 2.0 license](https://github.com/lief-project/ year = "2017" } ``` - - diff --git a/deps/LIEF/config/mbedtls/config.h b/deps/LIEF/config/mbedtls/config.h index 1007c99aee06..fc29d0b91f82 100644 --- a/deps/LIEF/config/mbedtls/config.h +++ b/deps/LIEF/config/mbedtls/config.h @@ -1,5 +1,9 @@ #include "mbedtls/mbedtls_config.h" -#if defined (MBEDTLS_ARCH_IS_X86) -#undef MBEDTLS_AESNI_C +#if defined(MBEDTLS_ARCH_IS_X86) + #undef MBEDTLS_AESNI_C +#endif + +#if defined(MBEDTLS_DEBUG_C) + #undef MBEDTLS_DEBUG_C #endif diff --git a/deps/LIEF/config/mbedtls/psa_config.h b/deps/LIEF/config/mbedtls/psa_config.h new file mode 100644 index 000000000000..836d9b1461b6 --- /dev/null +++ b/deps/LIEF/config/mbedtls/psa_config.h @@ -0,0 +1,14 @@ +// Disable MbedTLS options that are not thread-safe. See +// `tests/scripts/components-sanitizers.sh` in the MbedTLS tree: both options +// are unset there when building with MBEDTLS_THREADING_PTHREAD under TSan. +#if defined(MBEDTLS_THREADING_C) + // Self-tests do not currently use multiple threads. + #if defined(MBEDTLS_SELF_TEST) + #undef MBEDTLS_SELF_TEST + #endif + + // Interruptible ECC operations are not thread-safe. + #if defined(MBEDTLS_ECP_RESTARTABLE) + #undef MBEDTLS_ECP_RESTARTABLE + #endif +#endif diff --git a/deps/LIEF/include/LIEF/ART.hpp b/deps/LIEF/include/LIEF/ART.hpp index 7d920b61be47..4695f8f6c42b 100644 --- a/deps/LIEF/include/LIEF/ART.hpp +++ b/deps/LIEF/include/LIEF/ART.hpp @@ -1,5 +1,5 @@ -/* Copyright 2017 - 2025 R. Thomas - * Copyright 2017 - 2025 Quarkslab +/* Copyright 2017 - 2026 R. Thomas + * Copyright 2017 - 2026 Quarkslab * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,10 +19,10 @@ #include "LIEF/config.h" #if defined(LIEF_ART_SUPPORT) -#include "LIEF/ART/Parser.hpp" -#include "LIEF/ART/utils.hpp" -#include "LIEF/ART/File.hpp" -#include "LIEF/ART/EnumToString.hpp" + #include "LIEF/ART/Parser.hpp" + #include "LIEF/ART/utils.hpp" + #include "LIEF/ART/File.hpp" + #include "LIEF/ART/EnumToString.hpp" #endif #endif diff --git a/deps/LIEF/include/LIEF/ART/EnumToString.hpp b/deps/LIEF/include/LIEF/ART/EnumToString.hpp index a377b91a3576..82f0b104bcd6 100644 --- a/deps/LIEF/include/LIEF/ART/EnumToString.hpp +++ b/deps/LIEF/include/LIEF/ART/EnumToString.hpp @@ -1,5 +1,5 @@ -/* Copyright 2017 - 2025 R. Thomas - * Copyright 2017 - 2025 Quarkslab +/* Copyright 2017 - 2026 R. Thomas + * Copyright 2017 - 2026 Quarkslab * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -37,4 +37,3 @@ LIEF_API const char* to_string(ART_44::IMAGE_ROOTS e); } // namespace LIEF #endif - diff --git a/deps/LIEF/include/LIEF/ART/File.hpp b/deps/LIEF/include/LIEF/ART/File.hpp index ea00a53ac186..9f1c8ee330c5 100644 --- a/deps/LIEF/include/LIEF/ART/File.hpp +++ b/deps/LIEF/include/LIEF/ART/File.hpp @@ -1,5 +1,5 @@ -/* Copyright 2017 - 2025 R. Thomas - * Copyright 2017 - 2025 Quarkslab +/* Copyright 2017 - 2026 R. Thomas + * Copyright 2017 - 2026 Quarkslab * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -31,10 +31,10 @@ class LIEF_API File : public Object { public: File& operator=(const File& copy) = delete; - File(const File& copy) = delete; + File(const File& copy) = delete; - const Header& header() const; - Header& header(); + const Header& header() const LIEF_LIFETIMEBOUND; + Header& header() LIEF_LIFETIMEBOUND; void accept(Visitor& visitor) const override; diff --git a/deps/LIEF/include/LIEF/ART/Header.hpp b/deps/LIEF/include/LIEF/ART/Header.hpp index 3aef2eb4e20a..00eaf63c6a9f 100644 --- a/deps/LIEF/include/LIEF/ART/Header.hpp +++ b/deps/LIEF/include/LIEF/ART/Header.hpp @@ -1,5 +1,5 @@ -/* Copyright 2017 - 2025 R. Thomas - * Copyright 2017 - 2025 Quarkslab +/* Copyright 2017 - 2026 R. Thomas + * Copyright 2017 - 2026 Quarkslab * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -85,43 +85,43 @@ class LIEF_API Header : public Object { ~Header() override; private: - magic_t magic_; - art_version_t version_; + magic_t magic_{}; + art_version_t version_ = 0; - uint32_t image_begin_; - uint32_t image_size_; + uint32_t image_begin_ = 0; + uint32_t image_size_ = 0; - uint32_t oat_checksum_; + uint32_t oat_checksum_ = 0; - uint32_t oat_file_begin_; - uint32_t oat_file_end_; + uint32_t oat_file_begin_ = 0; + uint32_t oat_file_end_ = 0; - uint32_t oat_data_begin_; - uint32_t oat_data_end_; + uint32_t oat_data_begin_ = 0; + uint32_t oat_data_end_ = 0; - int32_t patch_delta_; - uint32_t image_roots_; + int32_t patch_delta_ = 0; + uint32_t image_roots_ = 0; - uint32_t pointer_size_; + uint32_t pointer_size_ = 0; - bool compile_pic_; + bool compile_pic_ = false; - uint32_t nb_sections_; - uint32_t nb_methods_; + uint32_t nb_sections_ = 0; + uint32_t nb_methods_ = 0; - bool is_pic_; + bool is_pic_ = false; // From ART 29 // =========== - uint32_t boot_image_begin_; - uint32_t boot_image_size_; + uint32_t boot_image_begin_ = 0; + uint32_t boot_image_size_ = 0; - uint32_t boot_oat_begin_; - uint32_t boot_oat_size_; + uint32_t boot_oat_begin_ = 0; + uint32_t boot_oat_size_ = 0; - STORAGE_MODES storage_mode_; + STORAGE_MODES storage_mode_ = STORAGE_MODES::STORAGE_UNCOMPRESSED; - uint32_t data_size_; + uint32_t data_size_ = 0; }; } // Namespace ART diff --git a/deps/LIEF/include/LIEF/ART/Parser.hpp b/deps/LIEF/include/LIEF/ART/Parser.hpp index 21d2250e4e92..5ff6bed37e71 100644 --- a/deps/LIEF/include/LIEF/ART/Parser.hpp +++ b/deps/LIEF/include/LIEF/ART/Parser.hpp @@ -1,5 +1,5 @@ -/* Copyright 2017 - 2025 R. Thomas - * Copyright 2017 - 2025 Quarkslab +/* Copyright 2017 - 2026 R. Thomas + * Copyright 2017 - 2026 Quarkslab * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -28,14 +28,15 @@ namespace ART { class File; -/// Class which parses an ART file and transform into a ART::File object +/// Class which parses an ART file and transforms it into an ART::File object class LIEF_API Parser { public: static std::unique_ptr parse(const std::string& file); - static std::unique_ptr parse(std::vector data, const std::string& name = ""); + static std::unique_ptr parse(std::vector data, + const std::string& name = ""); Parser& operator=(const Parser& copy) = delete; - Parser(const Parser& copy) = delete; + Parser(const Parser& copy) = delete; private: Parser(); @@ -95,8 +96,8 @@ class LIEF_API Parser { //// Parse a **Single** java.lang.DexCache object - //template - //void parse_class_roots(size_t object_offset); + // template + // void parse_class_roots(size_t object_offset); std::unique_ptr file_; std::unique_ptr stream_; diff --git a/deps/LIEF/include/LIEF/ART/enums.hpp b/deps/LIEF/include/LIEF/ART/enums.hpp index 2165ea497bd7..e149609b43e5 100644 --- a/deps/LIEF/include/LIEF/ART/enums.hpp +++ b/deps/LIEF/include/LIEF/ART/enums.hpp @@ -1,5 +1,5 @@ -/* Copyright 2017 - 2025 R. Thomas - * Copyright 2017 - 2025 Quarkslab +/* Copyright 2017 - 2026 R. Thomas + * Copyright 2017 - 2026 Quarkslab * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,32 +21,32 @@ namespace ART { enum STORAGE_MODES { STORAGE_UNCOMPRESSED = 0, - STORAGE_LZ4 = 1, - STORAGE_LZ4HC = 2, + STORAGE_LZ4 = 1, + STORAGE_LZ4HC = 2, }; namespace ART_17 { enum IMAGE_METHODS { - RESOLUTION_METHOD = 0, - IMT_CONFLICT_METHOD = 1, - IMT_UNIMPLEMENTED_METHOD = 2, - CALLEE_SAVE_METHOD = 3, - REFS_ONLY_SAVE_METHOD = 4, + RESOLUTION_METHOD = 0, + IMT_CONFLICT_METHOD = 1, + IMT_UNIMPLEMENTED_METHOD = 2, + CALLEE_SAVE_METHOD = 3, + REFS_ONLY_SAVE_METHOD = 4, REFS_AND_ARGS_SAVE_METHOD = 5, }; enum IMAGE_SECTIONS { - SECTION_OBJECTS = 0, - SECTION_ART_FIELDS = 1, - SECTION_ART_METHODS = 2, - SECTION_INTERNED_STRINGS = 3, - SECTION_IMAGE_BITMAP = 4, + SECTION_OBJECTS = 0, + SECTION_ART_FIELDS = 1, + SECTION_ART_METHODS = 2, + SECTION_INTERNED_STRINGS = 3, + SECTION_IMAGE_BITMAP = 4, }; enum IMAGE_ROOTS { - DEX_CACHES = 0, - CLASS_ROOTS = 1, + DEX_CACHES = 0, + CLASS_ROOTS = 1, }; @@ -59,19 +59,18 @@ using ART_17::IMAGE_METHODS; using ART_17::IMAGE_ROOTS; enum IMAGE_SECTIONS { - SECTION_OBJECTS = 0, - SECTION_ART_FIELDS = 1, - SECTION_ART_METHODS = 2, - SECTION_RUNTIME_METHODS = 3, // New in ART 29 - SECTION_IMT_CONFLICT_TABLES = 4, // New in ART 29 - SECTION_DEX_CACHE_ARRAYS = 5, // New in ART 29 - SECTION_INTERNED_STRINGS = 6, - SECTION_CLASS_TABLE = 7, // New in ART 29 - SECTION_IMAGE_BITMAP = 8, + SECTION_OBJECTS = 0, + SECTION_ART_FIELDS = 1, + SECTION_ART_METHODS = 2, + SECTION_RUNTIME_METHODS = 3, // New in ART 29 + SECTION_IMT_CONFLICT_TABLES = 4, // New in ART 29 + SECTION_DEX_CACHE_ARRAYS = 5, // New in ART 29 + SECTION_INTERNED_STRINGS = 6, + SECTION_CLASS_TABLE = 7, // New in ART 29 + SECTION_IMAGE_BITMAP = 8, }; - } // Namespace ART_29 @@ -81,16 +80,16 @@ using ART_29::IMAGE_METHODS; using ART_29::IMAGE_ROOTS; enum IMAGE_SECTIONS { - SECTION_OBJECTS = 0, - SECTION_ART_FIELDS = 1, - SECTION_ART_METHODS = 2, - SECTION_RUNTIME_METHODS = 3, - SECTION_IM_TABLES = 4, // New in ART 30 - SECTION_IMT_CONFLICT_TABLES = 5, - SECTION_DEX_CACHE_ARRAYS = 6, - SECTION_INTERNED_STRINGS = 7, - SECTION_CLASS_TABLE = 8, - SECTION_IMAGE_BITMAP = 9, + SECTION_OBJECTS = 0, + SECTION_ART_FIELDS = 1, + SECTION_ART_METHODS = 2, + SECTION_RUNTIME_METHODS = 3, + SECTION_IM_TABLES = 4, // New in ART 30 + SECTION_IMT_CONFLICT_TABLES = 5, + SECTION_DEX_CACHE_ARRAYS = 6, + SECTION_INTERNED_STRINGS = 7, + SECTION_CLASS_TABLE = 8, + SECTION_IMAGE_BITMAP = 9, }; } // Namespace ART_30 @@ -100,19 +99,19 @@ namespace ART_44 { using ART_30::IMAGE_SECTIONS; enum IMAGE_METHODS { - RESOLUTION_METHOD = 0, - IMT_CONFLICT_METHOD = 1, - IMT_UNIMPLEMENTED_METHOD = 2, + RESOLUTION_METHOD = 0, + IMT_CONFLICT_METHOD = 1, + IMT_UNIMPLEMENTED_METHOD = 2, SAVE_ALL_CALLEE_SAVES_METHOD = 3, // New in ART 44 - SAVE_REFS_ONLY_METHOD = 4, // New in ART 44 - SAVE_REFS_AND_ARGS_METHOD = 5, // New in ART 44 - SAVE_EVERYTHING_METHOD = 6, // New in ART 44 + SAVE_REFS_ONLY_METHOD = 4, // New in ART 44 + SAVE_REFS_AND_ARGS_METHOD = 5, // New in ART 44 + SAVE_EVERYTHING_METHOD = 6, // New in ART 44 }; enum IMAGE_ROOTS { - DEX_CACHES = 0, - CLASS_ROOTS = 1, + DEX_CACHES = 0, + CLASS_ROOTS = 1, CLASS_LOADER = 2, // New in ART 44 }; diff --git a/deps/LIEF/include/LIEF/ART/hash.hpp b/deps/LIEF/include/LIEF/ART/hash.hpp index 1aaa7d3acd92..66f0a6a7e11b 100644 --- a/deps/LIEF/include/LIEF/ART/hash.hpp +++ b/deps/LIEF/include/LIEF/ART/hash.hpp @@ -1,5 +1,5 @@ -/* Copyright 2017 - 2025 R. Thomas - * Copyright 2017 - 2025 Quarkslab +/* Copyright 2017 - 2026 R. Thomas + * Copyright 2017 - 2026 Quarkslab * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -35,8 +35,8 @@ class LIEF_API Hash : public LIEF::Hash { using LIEF::Hash::visit; public: - void visit(const File& file) override; - void visit(const Header& header) override; + void visit(const File& file) override; + void visit(const Header& header) override; ~Hash() override; }; diff --git a/deps/LIEF/include/LIEF/ART/java_structures.hpp b/deps/LIEF/include/LIEF/ART/java_structures.hpp index da3514aaffe6..5b78d94f9814 100644 --- a/deps/LIEF/include/LIEF/ART/java_structures.hpp +++ b/deps/LIEF/include/LIEF/ART/java_structures.hpp @@ -1,5 +1,5 @@ -/* Copyright 2017 - 2025 R. Thomas - * Copyright 2017 - 2025 Quarkslab +/* Copyright 2017 - 2026 R. Thomas + * Copyright 2017 - 2026 Quarkslab * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -49,25 +49,25 @@ struct brooks_read_barrier_t { template struct jobject_t { heap_reference_t klass; - uint32_t monitor; - T brooks_read_barrier; + uint32_t monitor; + T brooks_read_barrier; }; template<> struct jobject_t { heap_reference_t klass; - uint32_t monitor; + uint32_t monitor; }; template struct ALIGNED_(4) jarray_t { jobject_t object; - int32_t length; + int32_t length; uint32_t* elements; }; template struct ALIGNED_(4) jclass_t { - jobject_t object; + jobject_t object; heap_reference_t class_loader; heap_reference_t component_type; @@ -86,8 +86,8 @@ struct ALIGNED_(4) jclass_t { uint64_t virtual_methods; uint32_t class_size; uint32_t clinit_thread_id; - int32_t dex_class_def_idx; - int32_t dex_type_idx; + int32_t dex_class_def_idx; + int32_t dex_type_idx; uint32_t num_direct_methods; uint32_t num_instance_fields; uint32_t num_reference_instance_fields; @@ -97,15 +97,15 @@ struct ALIGNED_(4) jclass_t { uint32_t object_size; uint32_t primitive_type; uint32_t reference_instance_offsets; - int32_t status; + int32_t status; }; template struct ALIGNED_(4) jstring_t { jobject_t object; - int32_t count; - uint32_t hash_code; - uint16_t* value; + int32_t count; + uint32_t hash_code; + uint16_t* value; }; template @@ -118,7 +118,7 @@ struct ALIGNED_(4) jdex_cache_t { heap_reference_t resolved_methods; heap_reference_t resolved_types; heap_reference_t strings; - uint64_t dex_file; + uint64_t dex_file; }; @@ -132,7 +132,7 @@ namespace ART_29 { /// Namespace related to the Java part of ART 29 namespace Java { -using heap_reference_t = ART_17::Java::heap_reference_t; +using heap_reference_t = ART_17::Java::heap_reference_t; using brooks_read_barrier_t = ART_17::Java::brooks_read_barrier_t; template @@ -143,9 +143,9 @@ using jarray_t = ART_17::Java::jarray_t; template struct ALIGNED_(4) jclass_t { - jobject_t object; + jobject_t object; - heap_reference_t annotation_type; // ADDED in ART 29 + heap_reference_t annotation_type; // ADDED in ART 29 heap_reference_t class_loader; heap_reference_t component_type; heap_reference_t dex_cache; @@ -153,19 +153,19 @@ struct ALIGNED_(4) jclass_t { heap_reference_t iftable; heap_reference_t name; heap_reference_t super_class; - heap_reference_t verify_error; // Type CHANGED from Class to Object + heap_reference_t verify_error; // Type CHANGED from Class to Object heap_reference_t vtable; uint32_t access_flags; - uint64_t dex_cache_strings; // direct_methods REPLACED with dex_cache_string + uint64_t dex_cache_strings; // direct_methods REPLACED with dex_cache_string uint64_t ifields; - uint64_t methods; // ADDED in ART 29 + uint64_t methods; // ADDED in ART 29 uint64_t sfields; - uint32_t class_flags; // virtual_methods REPLACED with class_flags + uint32_t class_flags; // virtual_methods REPLACED with class_flags uint32_t class_size; uint32_t clinit_thread_id; - int32_t dex_class_def_idx; - int32_t dex_type_idx; + int32_t dex_class_def_idx; + int32_t dex_type_idx; // uint32_t num_direct_methods; // REMOVED in ART 29 // uint32_t num_instance_fields; // REMOVED in ART 29 uint32_t num_reference_instance_fields; @@ -175,10 +175,10 @@ struct ALIGNED_(4) jclass_t { uint32_t object_size; uint32_t primitive_type; uint32_t reference_instance_offsets; - int32_t status; + int32_t status; - uint16_t copied_methods_offset; // ADDED in ART 29 - uint16_t virtual_methods_offset; // ADDED in ART 29 + uint16_t copied_methods_offset; // ADDED in ART 29 + uint16_t virtual_methods_offset; // ADDED in ART 29 }; @@ -192,20 +192,18 @@ struct ALIGNED_(4) jdex_cache_t { heap_reference_t dex; heap_reference_t location; - uint64_t dex_file; // LOCATION CHANGED - uint64_t resolved_fields; // TYPE CHANGED from heap_reference_t to uint64_t - uint64_t resolved_methods; // TYPE CHANGED from heap_reference_t to uint64_t - uint64_t resolved_types; // TYPE CHANGED from heap_reference_t to uint64_t - uint64_t strings; // TYPE CHANGED from heap_reference_t to uint64_t - uint32_t num_resolved_fields; // ADDED in ART 29 - uint32_t num_resolved_methods; // ADDED in ART 29 - uint32_t num_resolved_types; // ADDED in ART 29 - uint32_t num_strings; // ADDED in ART 29 + uint64_t dex_file; // LOCATION CHANGED + uint64_t resolved_fields; // TYPE CHANGED from heap_reference_t to uint64_t + uint64_t resolved_methods; // TYPE CHANGED from heap_reference_t to uint64_t + uint64_t resolved_types; // TYPE CHANGED from heap_reference_t to uint64_t + uint64_t strings; // TYPE CHANGED from heap_reference_t to uint64_t + uint32_t num_resolved_fields; // ADDED in ART 29 + uint32_t num_resolved_methods; // ADDED in ART 29 + uint32_t num_resolved_types; // ADDED in ART 29 + uint32_t num_strings; // ADDED in ART 29 }; - - } // Namespace Java } // Namespace ART_29 @@ -218,7 +216,7 @@ namespace ART_30 { /// Namespace related to the Java part of ART 30 namespace Java { -using heap_reference_t = ART_29::Java::heap_reference_t; +using heap_reference_t = ART_29::Java::heap_reference_t; using brooks_read_barrier_t = ART_29::Java::brooks_read_barrier_t; template @@ -250,7 +248,7 @@ namespace ART_44 { namespace Java { -using heap_reference_t = ART_30::Java::heap_reference_t; +using heap_reference_t = ART_30::Java::heap_reference_t; using brooks_read_barrier_t = ART_30::Java::brooks_read_barrier_t; template @@ -261,13 +259,13 @@ using jarray_t = ART_30::Java::jarray_t; template struct ALIGNED_(4) jclass_t { - jobject_t object; + jobject_t object; // heap_reference_t annotation_type; // REMOVED in ART 44 heap_reference_t class_loader; heap_reference_t component_type; heap_reference_t dex_cache; - heap_reference_t ext_data; // ADDED in ART 44 + heap_reference_t ext_data; // ADDED in ART 44 heap_reference_t iftable; heap_reference_t name; heap_reference_t super_class; @@ -279,19 +277,19 @@ struct ALIGNED_(4) jclass_t { uint64_t ifields; uint64_t methods; uint64_t sfields; - uint32_t access_flags; // ADDED in ART 44 + uint32_t access_flags; // ADDED in ART 44 uint32_t class_flags; uint32_t class_size; uint32_t clinit_thread_id; - int32_t dex_class_def_idx; - int32_t dex_type_idx; + int32_t dex_class_def_idx; + int32_t dex_type_idx; uint32_t num_reference_instance_fields; uint32_t num_reference_static_fields; uint32_t object_size; - uint32_t object_size_alloc_fast_path; // ADDED in ART 44 + uint32_t object_size_alloc_fast_path; // ADDED in ART 44 uint32_t primitive_type; uint32_t reference_instance_offsets; - int32_t status; + int32_t status; uint16_t copied_methods_offset; uint16_t virtual_methods_offset; }; @@ -310,19 +308,19 @@ struct ALIGNED_(4) jdex_cache_t { // heap_reference_t dex; // REMOVED in ART 44 heap_reference_t location; - uint32_t num_resolved_call_sites; // ADDED in ART 44 (related to DEX38 format) - uint64_t dex_file; - uint64_t resolved_call_sites; // ADDED in ART 44 (related to DEX38 format) - uint64_t resolved_fields; - uint64_t resolved_method_types; // ADDED in ART 44 - uint64_t resolved_methods; - uint64_t resolved_types; - uint64_t strings; - uint32_t num_resolved_fields; - uint32_t num_resolved_methods_types; // ADDED in ART 44 - uint32_t num_resolved_methods; - uint32_t num_resolved_types; - uint32_t num_strings; + uint32_t num_resolved_call_sites; // ADDED in ART 44 (related to DEX38 format) + uint64_t dex_file; + uint64_t resolved_call_sites; // ADDED in ART 44 (related to DEX38 format) + uint64_t resolved_fields; + uint64_t resolved_method_types; // ADDED in ART 44 + uint64_t resolved_methods; + uint64_t resolved_types; + uint64_t strings; + uint32_t num_resolved_fields; + uint32_t num_resolved_methods_types; // ADDED in ART 44 + uint32_t num_resolved_methods; + uint32_t num_resolved_types; + uint32_t num_strings; }; @@ -338,7 +336,7 @@ namespace ART_46 { /// Namespace related to the Java part of ART 46 namespace Java { -using heap_reference_t = ART_44::Java::heap_reference_t; +using heap_reference_t = ART_44::Java::heap_reference_t; using brooks_read_barrier_t = ART_44::Java::brooks_read_barrier_t; template @@ -367,7 +365,7 @@ namespace ART_56 { /// Namespace related to the Java part of ART 46 namespace Java { -using heap_reference_t = ART_46::Java::heap_reference_t; +using heap_reference_t = ART_46::Java::heap_reference_t; using brooks_read_barrier_t = ART_46::Java::brooks_read_barrier_t; template @@ -393,5 +391,4 @@ using jdex_cache_t = ART_46::Java::jdex_cache_t; } // Namespace LIEF - #endif diff --git a/deps/LIEF/include/LIEF/ART/json.hpp b/deps/LIEF/include/LIEF/ART/json.hpp index 3302272bd8c5..502f5d6f48c9 100644 --- a/deps/LIEF/include/LIEF/ART/json.hpp +++ b/deps/LIEF/include/LIEF/ART/json.hpp @@ -1,5 +1,5 @@ -/* Copyright 2017 - 2025 R. Thomas - * Copyright 2017 - 2025 Quarkslab +/* Copyright 2017 - 2026 R. Thomas + * Copyright 2017 - 2026 Quarkslab * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/deps/LIEF/include/LIEF/ART/types.hpp b/deps/LIEF/include/LIEF/ART/types.hpp index 706e4143d08f..f88380ba0ca4 100644 --- a/deps/LIEF/include/LIEF/ART/types.hpp +++ b/deps/LIEF/include/LIEF/ART/types.hpp @@ -1,5 +1,5 @@ -/* Copyright 2017 - 2025 R. Thomas - * Copyright 2017 - 2025 Quarkslab +/* Copyright 2017 - 2026 R. Thomas + * Copyright 2017 - 2026 Quarkslab * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/deps/LIEF/include/LIEF/ART/utils.hpp b/deps/LIEF/include/LIEF/ART/utils.hpp index fc4bcd8e3eed..4e0e47495fee 100644 --- a/deps/LIEF/include/LIEF/ART/utils.hpp +++ b/deps/LIEF/include/LIEF/ART/utils.hpp @@ -1,5 +1,5 @@ -/* Copyright 2017 - 2025 R. Thomas - * Copyright 2017 - 2025 Quarkslab +/* Copyright 2017 - 2026 R. Thomas + * Copyright 2017 - 2026 Quarkslab * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/deps/LIEF/include/LIEF/ASM.hpp b/deps/LIEF/include/LIEF/ASM.hpp index 5bc1a376b2c5..a09dd1f34b33 100644 --- a/deps/LIEF/include/LIEF/ASM.hpp +++ b/deps/LIEF/include/LIEF/ASM.hpp @@ -1,5 +1,5 @@ -/* Copyright 2017 - 2025 R. Thomas - * Copyright 2017 - 2025 Quarkslab +/* Copyright 2017 - 2026 R. Thomas + * Copyright 2017 - 2026 Quarkslab * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/deps/LIEF/include/LIEF/Abstract.hpp b/deps/LIEF/include/LIEF/Abstract.hpp index bc10e6694865..ee5162f860f3 100644 --- a/deps/LIEF/include/LIEF/Abstract.hpp +++ b/deps/LIEF/include/LIEF/Abstract.hpp @@ -1,5 +1,5 @@ -/* Copyright 2017 - 2025 R. Thomas - * Copyright 2017 - 2025 Quarkslab +/* Copyright 2017 - 2026 R. Thomas + * Copyright 2017 - 2026 Quarkslab * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/deps/LIEF/include/LIEF/Abstract/Binary.hpp b/deps/LIEF/include/LIEF/Abstract/Binary.hpp index 8e4f738a76ef..1944a94ad24c 100644 --- a/deps/LIEF/include/LIEF/Abstract/Binary.hpp +++ b/deps/LIEF/include/LIEF/Abstract/Binary.hpp @@ -1,5 +1,5 @@ -/* Copyright 2017 - 2025 R. Thomas - * Copyright 2017 - 2025 Quarkslab +/* Copyright 2017 - 2026 R. Thomas + * Copyright 2017 - 2026 Quarkslab * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,6 +20,7 @@ #include #include +#include "LIEF/compiler_attributes.hpp" #include "LIEF/visibility.h" #include "LIEF/Object.hpp" #include "LIEF/iterators.hpp" @@ -58,7 +59,6 @@ class Engine; /// Subclasses like LIEF::PE::Binary implement format-specific API class LIEF_API Binary : public Object { public: - /// Enumeration of virtual address types used for patching and memory access. enum class VA_TYPES { /// Automatically determine if the address is absolute or relative @@ -69,7 +69,7 @@ class LIEF_API Binary : public Object { RVA = 1, /// Absolute Virtual Address. - VA = 2 + VA = 2, }; enum FORMATS { @@ -131,13 +131,15 @@ class LIEF_API Binary : public Object { return get_abstract_header(); } - /// Return an iterator over the abstracted symbols in which the elements **can** be modified - it_symbols symbols() { + /// Return an iterator over the abstracted symbols in which the elements **can** + /// be modified + it_symbols symbols() LIEF_LIFETIMEBOUND { return get_abstract_symbols(); } - /// Return an iterator over the abstracted symbols in which the elements **can't** be modified - it_const_symbols symbols() const { + /// Return an iterator over the abstracted symbols in which the elements + /// **can't** be modified + it_const_symbols symbols() const LIEF_LIFETIMEBOUND { return const_cast(this)->get_abstract_symbols(); } @@ -148,30 +150,30 @@ class LIEF_API Binary : public Object { /// Return the Symbol with the given name /// If the symbol does not exist, return a nullptr - const Symbol* get_symbol(const std::string& name) const; + const Symbol* get_symbol(const std::string& name) const LIEF_LIFETIMEBOUND; - Symbol* get_symbol(const std::string& name) { + Symbol* get_symbol(const std::string& name) LIEF_LIFETIMEBOUND { return const_cast(static_cast(this)->get_symbol(name)); } /// Return an iterator over the binary's sections (LIEF::Section) - it_sections sections() { + it_sections sections() LIEF_LIFETIMEBOUND { return get_abstract_sections(); } - it_const_sections sections() const { + it_const_sections sections() const LIEF_LIFETIMEBOUND { return const_cast(this)->get_abstract_sections(); } /// Remove **all** the sections in the underlying binary virtual void remove_section(const std::string& name, bool clear = false) = 0; - /// Return an iterator over the binary relocation (LIEF::Relocation) - it_relocations relocations() { + /// Return an iterator over the binary relocations (LIEF::Relocation) + it_relocations relocations() LIEF_LIFETIMEBOUND { return get_abstract_relocations(); } - it_const_relocations relocations() const { + it_const_relocations relocations() const LIEF_LIFETIMEBOUND { return const_cast(this)->get_abstract_relocations(); } @@ -199,7 +201,8 @@ class LIEF_API Binary : public Object { } /// Return the address of the given function name - virtual result get_function_address(const std::string& func_name) const; + virtual result + get_function_address(const std::string& func_name) const; /// Method so that a ``visitor`` can visit us void accept(Visitor& visitor) const override; @@ -212,7 +215,8 @@ class LIEF_API Binary : public Object { /// @param[in] patch_value Patch to apply /// @param[in] addr_type Specify if the address should be used as an /// absolute virtual address or a RVA - virtual void patch_address(uint64_t address, const std::vector& patch_value, + virtual void patch_address(uint64_t address, + const std::vector& patch_value, VA_TYPES addr_type = VA_TYPES::AUTO) = 0; /// Patch the address with the given value @@ -220,23 +224,26 @@ class LIEF_API Binary : public Object { /// @param[in] address Address to patch /// @param[in] patch_value Patch to apply /// @param[in] size Size of the value in **bytes** (1, 2, ... 8) - /// @param[in] addr_type Specify if the address should be used as an absolute virtual address or an RVA - virtual void patch_address(uint64_t address, uint64_t patch_value, size_t size = sizeof(uint64_t), + /// @param[in] addr_type Specify if the address should be used as an absolute + /// virtual address or an RVA + virtual void patch_address(uint64_t address, uint64_t patch_value, + size_t size = sizeof(uint64_t), VA_TYPES addr_type = VA_TYPES::AUTO) = 0; /// Return the content located at the given virtual address - virtual span - get_content_from_virtual_address(uint64_t virtual_address, uint64_t size, - VA_TYPES addr_type = VA_TYPES::AUTO) const = 0; + virtual span get_content_from_virtual_address( + uint64_t virtual_address, uint64_t size, VA_TYPES addr_type = VA_TYPES::AUTO + ) const LIEF_LIFETIMEBOUND = 0; /// Get the integer value at the given virtual address template - LIEF::result get_int_from_virtual_address( - uint64_t va, VA_TYPES addr_type = VA_TYPES::AUTO) const - { + LIEF::result + get_int_from_virtual_address(uint64_t va, + VA_TYPES addr_type = VA_TYPES::AUTO) const { T value; static_assert(std::is_integral::value, "Require an integral type"); - span raw = get_content_from_virtual_address(va, sizeof(T), addr_type); + span raw = + get_content_from_virtual_address(va, sizeof(T), addr_type); if (raw.empty() || raw.size() < sizeof(T)) { return make_error_code(lief_errors::read_error); } @@ -270,14 +277,17 @@ class LIEF_API Binary : public Object { /// Convert the given offset into a virtual address. /// /// @param[in] offset The offset to convert. - /// @param[in] slide If not 0, it will replace the default base address (if any) - virtual result offset_to_virtual_address(uint64_t offset, uint64_t slide = 0) const = 0; + /// @param[in] slide If not 0, it will replace the default base address (if + /// any) + virtual result offset_to_virtual_address(uint64_t offset, + uint64_t slide = 0) const = 0; virtual std::ostream& print(std::ostream& os) const { return os; } - LIEF_API friend std::ostream& operator<<(std::ostream& os, const Binary& binary) { + LIEF_API friend std::ostream& operator<<(std::ostream& os, + const Binary& binary) { binary.print(os); return os; } @@ -293,9 +303,9 @@ class LIEF_API Binary : public Object { /// use LIEF::pdb::load() or LIEF::pdb::DebugInfo::from_file() to get PDB debug /// info. /// - /// \warning This function requires LIEF's extended version otherwise it - /// **always** return a nullptr - DebugInfo* debug_info() const; + /// @warning This function requires LIEF's extended version otherwise it + /// **always** returns a nullptr + DebugInfo* debug_info() const LIEF_LIFETIMEBOUND; /// Disassemble code starting at the given virtual address and with the given /// size. @@ -307,7 +317,7 @@ class LIEF_API Binary : public Object { /// } /// ``` /// - /// \see LIEF::assembly::Instruction + /// @see LIEF::assembly::Instruction instructions_it disassemble(uint64_t address, size_t size) const; /// Disassemble code starting at the given virtual address @@ -319,7 +329,7 @@ class LIEF_API Binary : public Object { /// } /// ``` /// - /// \see LIEF::assembly::Instruction + /// @see LIEF::assembly::Instruction instructions_it disassemble(uint64_t address) const; /// Disassemble code for the given symbol name @@ -331,13 +341,13 @@ class LIEF_API Binary : public Object { /// } /// ``` /// - /// \see LIEF::assembly::Instruction + /// @see LIEF::assembly::Instruction instructions_it disassemble(const std::string& function) const; /// Disassemble code provided by the given buffer at the specified /// `address` parameter. /// - /// \see LIEF::assembly::Instruction + /// @see LIEF::assembly::Instruction instructions_it disassemble(const uint8_t* buffer, size_t size, uint64_t address = 0) const; @@ -345,7 +355,7 @@ class LIEF_API Binary : public Object { /// Disassemble code provided by the given vector of bytes at the specified /// `address` parameter. /// - /// \see LIEF::assembly::Instruction + /// @see LIEF::assembly::Instruction instructions_it disassemble(const std::vector& buffer, uint64_t address = 0) const { return disassemble(buffer.data(), buffer.size(), address); @@ -356,7 +366,8 @@ class LIEF_API Binary : public Object { return disassemble(buffer.data(), buffer.size(), address); } - instructions_it disassemble(LIEF::span buffer, uint64_t address = 0) const { + instructions_it disassemble(LIEF::span buffer, + uint64_t address = 0) const { return disassemble(buffer.data(), buffer.size(), address); } @@ -374,17 +385,18 @@ class LIEF_API Binary : public Object { /// If you need to configure the assembly engine or to define addresses for /// symbols, you can provide your own assembly::AssemblerConfig. std::vector assemble(uint64_t address, const std::string& Asm, - assembly::AssemblerConfig& config = assembly::AssemblerConfig::default_config()); + assembly::AssemblerConfig& config = + assembly::AssemblerConfig::default_config()); /// Assemble **and patch** the address with the given LLVM MCInst. /// - /// \warning Because of ABI compatibility, this MCInst can **only be used** + /// @warning Because of ABI compatibility, this MCInst can **only be used** /// with the **same** version of LLVM used by LIEF (see documentation) std::vector assemble(uint64_t address, const llvm::MCInst& inst); /// Assemble **and patch** the address with the given LLVM MCInst. /// - /// \warning Because of ABI compatibility, this MCInst can **only be used** + /// @warning Because of ABI compatibility, this MCInst can **only be used** /// with the **same** version of LLVM used by LIEF (see documentation) std::vector assemble(uint64_t address, const std::vector& insts); @@ -393,23 +405,30 @@ class LIEF_API Binary : public Object { /// the format of the current binary virtual uint64_t page_size() const; - /// Load and associate an external debug file (e.g., DWARF or PDB) with this binary. + /// Load and associate an external debug file (e.g., DWARF or PDB) with this + /// binary. /// - /// This method attempts to load the debug information from the file located at the given path, - /// and binds it to the current binary instance. If successful, it returns a pointer to the - /// loaded DebugInfo object. + /// This method attempts to load the debug information from the file located at + /// the given path, and binds it to the current binary instance. If successful, + /// it returns a pointer to the loaded DebugInfo object. /// - /// \param path Path to the external debug file (e.g., `.dwarf`, `.pdb`) - /// \return Pointer to the loaded DebugInfo object on success, or `nullptr` on failure. + /// @param path Path to the external debug file (e.g., `.dwarf`, `.pdb`) + /// @return Pointer to the loaded DebugInfo object on success, or `nullptr` on + /// failure. /// - /// \warning It is the caller's responsibility to ensure that the debug file is + /// @warning It is the caller's responsibility to ensure that the debug file is /// compatible with the binary. Incorrect associations may lead to /// inconsistent or invalid results. /// - /// \note This function does not verify that the debug file matches the binary's unique - /// identifier (e.g., build ID, GUID). + /// @note This function does not verify that the debug file matches the binary's + /// unique identifier (e.g., build ID, GUID). DebugInfo* load_debug_info(const std::string& path); + /// Size of the binary when mapped in memory + virtual uint64_t virtual_size() const { + return 0; + } + protected: FORMATS format_ = FORMATS::UNKNOWN; mutable std::unique_ptr debug_info_; @@ -421,14 +440,15 @@ class LIEF_API Binary : public Object { template LIEF_LOCAL assembly::Engine* get_cache_engine(uint64_t address, F&& f) const; - // These functions need to be overloaded by the object that claims to extend this Abstract Binary + // These functions need to be overloaded by the object that claims to extend this + // Abstract Binary virtual Header get_abstract_header() const = 0; virtual symbols_t get_abstract_symbols() = 0; virtual sections_t get_abstract_sections() = 0; virtual relocations_t get_abstract_relocations() = 0; - virtual functions_t get_abstract_exported_functions() const = 0; - virtual functions_t get_abstract_imported_functions() const = 0; + virtual functions_t get_abstract_exported_functions() const = 0; + virtual functions_t get_abstract_imported_functions() const = 0; virtual std::vector get_abstract_imported_libraries() const = 0; }; diff --git a/deps/LIEF/include/LIEF/Abstract/DebugInfo.hpp b/deps/LIEF/include/LIEF/Abstract/DebugInfo.hpp index 24961cf79134..5792a14b3b0f 100644 --- a/deps/LIEF/include/LIEF/Abstract/DebugInfo.hpp +++ b/deps/LIEF/include/LIEF/Abstract/DebugInfo.hpp @@ -1,4 +1,4 @@ -/* Copyright 2022 - 2025 R. Thomas +/* Copyright 2022 - 2026 R. Thomas * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -34,13 +34,14 @@ class DebugInfo; /// Users can use this interface to access high-level debug features like /// resolving function addresses. /// -/// See: LIEF::pdb::DebugInfo, LIEF::dwarf::DebugInfo +/// @see LIEF::pdb::DebugInfo, LIEF::dwarf::DebugInfo class LIEF_API DebugInfo { public: friend class Binary; enum class FORMAT { UNKNOWN = 0, - DWARF, PDB, + DWARF, + PDB, }; DebugInfo(std::unique_ptr impl); @@ -61,7 +62,7 @@ class LIEF_API DebugInfo { template const T* as() const { static_assert(std::is_base_of::value, - "Require Instruction inheritance"); + "Requires DebugInfo inheritance"); if (T::classof(this)) { return static_cast(this); } @@ -69,7 +70,8 @@ class LIEF_API DebugInfo { } /// Attempt to resolve the address of the function specified by `name`. - virtual optional find_function_address(const std::string& name) const = 0; + virtual optional + find_function_address(const std::string& name) const = 0; protected: std::unique_ptr impl_; diff --git a/deps/LIEF/include/LIEF/Abstract/Function.hpp b/deps/LIEF/include/LIEF/Abstract/Function.hpp index 66004763d6ec..f41bbc0424a6 100644 --- a/deps/LIEF/include/LIEF/Abstract/Function.hpp +++ b/deps/LIEF/include/LIEF/Abstract/Function.hpp @@ -1,5 +1,5 @@ -/* Copyright 2017 - 2025 R. Thomas - * Copyright 2017 - 2025 Quarkslab +/* Copyright 2017 - 2026 R. Thomas + * Copyright 2017 - 2026 Quarkslab * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -50,24 +50,21 @@ class LIEF_API Function : public Symbol { /// returns its virtual address in the binary EXPORTED = 1 << 3, - /// The function is **imported** by the binary and the address() should return 0 + /// The function is **imported** by the binary and the address() should return + /// 0 IMPORTED = 1 << 4, }; public: Function() = default; Function(const std::string& name) : - Symbol(name) - {} + Symbol(name) {} Function(uint64_t address) : - Function("", address) - {} + Function("", address) {} Function(const std::string& name, uint64_t address) : - Symbol(name, address) - {} + Symbol(name, address) {} Function(const std::string& name, uint64_t address, FLAGS flags) : - Function(name, address) - { + Function(name, address) { flags_ = flags; } @@ -94,8 +91,8 @@ class LIEF_API Function : public Symbol { return ((uint32_t)flags_ & (uint32_t)f) != 0; } - /// Address of the current function. For functions that are set with the FLAGS::IMPORTED flag, - /// this value is likely 0. + /// Address of the current function. For functions that are set with the + /// FLAGS::IMPORTED flag, this value is likely 0. uint64_t address() const { return value_; } @@ -106,7 +103,8 @@ class LIEF_API Function : public Symbol { void accept(Visitor& visitor) const override; - LIEF_API friend std::ostream& operator<<(std::ostream& os, const Function& entry); + LIEF_API friend std::ostream& operator<<(std::ostream& os, + const Function& entry); protected: FLAGS flags_ = FLAGS::NONE; @@ -118,4 +116,3 @@ LIEF_API const char* to_string(Function::FLAGS e); ENABLE_BITMASK_OPERATORS(LIEF::Function::FLAGS); #endif - diff --git a/deps/LIEF/include/LIEF/Abstract/Header.hpp b/deps/LIEF/include/LIEF/Abstract/Header.hpp index 036e64cf5a54..55ade3dffeee 100644 --- a/deps/LIEF/include/LIEF/Abstract/Header.hpp +++ b/deps/LIEF/include/LIEF/Abstract/Header.hpp @@ -1,5 +1,5 @@ -/* Copyright 2017 - 2025 R. Thomas - * Copyright 2017 - 2025 Quarkslab +/* Copyright 2017 - 2026 R. Thomas + * Copyright 2017 - 2026 Quarkslab * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -67,9 +67,9 @@ class LIEF_API Header : public Object { BITS_16 = 1LLU << 0, /// 16-bits architecture BITS_32 = 1LLU << 1, /// 32-bits architecture BITS_64 = 1LLU << 2, /// 64-bits architecture - THUMB = 1LLU << 3, /// Support ARM Thumb mode + THUMB = 1LLU << 3, /// Support ARM Thumb mode - ARM64E = 1LLU << 4, /// ARM64 with extended (security) features + ARM64E = 1LLU << 4, /// ARM64 with extended (security) features }; enum class OBJECT_TYPES { @@ -130,7 +130,7 @@ class LIEF_API Header : public Object { protected: ARCHITECTURES architecture_ = ARCHITECTURES::UNKNOWN; - OBJECT_TYPES object_type_ = OBJECT_TYPES::UNKNOWN; + OBJECT_TYPES object_type_ = OBJECT_TYPES::UNKNOWN; uint64_t entrypoint_ = 0; ENDIANNESS endianness_ = ENDIANNESS::UNKNOWN; MODES modes_ = MODES::NONE; diff --git a/deps/LIEF/include/LIEF/Abstract/Parser.hpp b/deps/LIEF/include/LIEF/Abstract/Parser.hpp index 9a3665192bb6..8a252cf68cc3 100644 --- a/deps/LIEF/include/LIEF/Abstract/Parser.hpp +++ b/deps/LIEF/include/LIEF/Abstract/Parser.hpp @@ -1,5 +1,5 @@ -/* Copyright 2017 - 2025 R. Thomas - * Copyright 2017 - 2025 Quarkslab +/* Copyright 2017 - 2026 R. Thomas + * Copyright 2017 - 2026 Quarkslab * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,6 +18,7 @@ #include #include +#include #include #include "LIEF/visibility.h" @@ -50,7 +51,7 @@ class LIEF_API Parser { protected: Parser(const std::string& file); - uint64_t binary_size_ = 0; + uint64_t binary_size_ = 0; virtual ~Parser(); Parser(); diff --git a/deps/LIEF/include/LIEF/Abstract/Relocation.hpp b/deps/LIEF/include/LIEF/Abstract/Relocation.hpp index c22f8e7a508c..339a0d3f6097 100644 --- a/deps/LIEF/include/LIEF/Abstract/Relocation.hpp +++ b/deps/LIEF/include/LIEF/Abstract/Relocation.hpp @@ -1,5 +1,5 @@ -/* Copyright 2017 - 2025 R. Thomas - * Copyright 2017 - 2025 Quarkslab +/* Copyright 2017 - 2026 R. Thomas + * Copyright 2017 - 2026 Quarkslab * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -32,8 +32,7 @@ class LIEF_API Relocation : public Object { /// Constructor from a relocation's address and size Relocation(uint64_t address, uint8_t size) : address_(address), - size_(size) - {} + size_(size) {} ~Relocation() override = default; @@ -41,7 +40,7 @@ class LIEF_API Relocation : public Object { Relocation(const Relocation&) = default; void swap(Relocation& other) { std::swap(address_, other.address_); - std::swap(size_, other.size_); + std::swap(size_, other.size_); } /// Relocation's address @@ -66,31 +65,32 @@ class LIEF_API Relocation : public Object { void accept(Visitor& visitor) const override; - /// Comparaison based on the Relocation's **address** + /// Comparison based on the Relocation's **address** virtual bool operator<(const Relocation& rhs) const { return address() < rhs.address(); } - /// Comparaison based on the Relocation's **address** + /// Comparison based on the Relocation's **address** virtual bool operator<=(const Relocation& rhs) const { return !(address() > rhs.address()); } - /// Comparaison based on the Relocation's **address** + /// Comparison based on the Relocation's **address** virtual bool operator>(const Relocation& rhs) const { return address() > rhs.address(); } - /// Comparaison based on the Relocation's **address** + /// Comparison based on the Relocation's **address** virtual bool operator>=(const Relocation& rhs) const { return !(address() < rhs.address()); } - LIEF_API friend std::ostream& operator<<(std::ostream& os, const Relocation& entry); + LIEF_API friend std::ostream& operator<<(std::ostream& os, + const Relocation& entry); protected: uint64_t address_ = 0; - uint8_t size_ = 0; + uint8_t size_ = 0; }; diff --git a/deps/LIEF/include/LIEF/Abstract/Section.hpp b/deps/LIEF/include/LIEF/Abstract/Section.hpp index eb89b42ccc57..8e9129500733 100644 --- a/deps/LIEF/include/LIEF/Abstract/Section.hpp +++ b/deps/LIEF/include/LIEF/Abstract/Section.hpp @@ -1,5 +1,5 @@ -/* Copyright 2017 - 2025 R. Thomas - * Copyright 2017 - 2025 Quarkslab +/* Copyright 2017 - 2026 R. Thomas + * Copyright 2017 - 2026 Quarkslab * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,6 +22,7 @@ #include "LIEF/span.hpp" #include "LIEF/Object.hpp" +#include "LIEF/compiler_attributes.hpp" #include "LIEF/visibility.h" namespace LIEF { @@ -32,27 +33,26 @@ class LIEF_API Section : public Object { Section() = default; Section(std::string name) : - name_(std::move(name)) - {} + name_(std::move(name)) {} ~Section() override = default; Section& operator=(const Section&) = default; Section(const Section&) = default; - /// section's name + /// Section's name virtual std::string name() const { return name_.c_str(); } - /// Return the **complete** section's name which might + /// Return the **complete** section's name which might include /// trailing (``0``) bytes virtual const std::string& fullname() const { return name_; } - /// section's content - virtual span content() const { + /// Section's content + virtual span content() const LIEF_LIFETIMEBOUND { return {}; } @@ -61,7 +61,7 @@ class LIEF_API Section : public Object { size_ = size; } - /// section's size (size in the binary, not the virtual size) + /// Section's size (size in the binary, not the virtual size) virtual uint64_t size() const { return size_; } @@ -118,9 +118,9 @@ class LIEF_API Section : public Object { protected: std::string name_; - uint64_t virtual_address_ = 0; - uint64_t size_ = 0; - uint64_t offset_ = 0; + uint64_t virtual_address_ = 0; + uint64_t size_ = 0; + uint64_t offset_ = 0; private: template diff --git a/deps/LIEF/include/LIEF/Abstract/Symbol.hpp b/deps/LIEF/include/LIEF/Abstract/Symbol.hpp index 8d9802beec34..ce4ed5d3aebe 100644 --- a/deps/LIEF/include/LIEF/Abstract/Symbol.hpp +++ b/deps/LIEF/include/LIEF/Abstract/Symbol.hpp @@ -1,5 +1,5 @@ -/* Copyright 2017 - 2025 R. Thomas - * Copyright 2017 - 2025 Quarkslab +/* Copyright 2017 - 2026 R. Thomas + * Copyright 2017 - 2026 Quarkslab * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,16 +29,16 @@ class LIEF_API Symbol : public Object { public: Symbol() = default; Symbol(std::string name) : - name_(std::move(name)) - {} + name_(std::move(name)) {} Symbol(std::string name, uint64_t value) : - name_(std::move(name)), value_(value) - {} + name_(std::move(name)), + value_(value) {} Symbol(std::string name, uint64_t value, uint64_t size) : - name_(std::move(name)), value_(value), size_(size) - {} + name_(std::move(name)), + value_(value), + size_(size) {} Symbol(const Symbol&) = default; Symbol& operator=(const Symbol&) = default; @@ -64,7 +64,7 @@ class LIEF_API Symbol : public Object { name_ = std::move(name); } - // Symbol's value which is usually the **address** of the symbol + /// Symbol's value which is usually the **address** of the symbol virtual uint64_t value() const { return value_; } @@ -72,7 +72,7 @@ class LIEF_API Symbol : public Object { value_ = value; } - /// This size of the symbol (when applicable) + /// The size of the symbol (when applicable) virtual uint64_t size() const { return size_; } @@ -94,4 +94,3 @@ class LIEF_API Symbol : public Object { } #endif - diff --git a/deps/LIEF/include/LIEF/Abstract/hash.hpp b/deps/LIEF/include/LIEF/Abstract/hash.hpp index 26f4a375f446..b38537966bff 100644 --- a/deps/LIEF/include/LIEF/Abstract/hash.hpp +++ b/deps/LIEF/include/LIEF/Abstract/hash.hpp @@ -1,5 +1,5 @@ -/* Copyright 2017 - 2025 R. Thomas - * Copyright 2017 - 2025 Quarkslab +/* Copyright 2017 - 2026 R. Thomas + * Copyright 2017 - 2026 Quarkslab * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -34,12 +34,12 @@ class LIEF_API AbstractHash : public LIEF::Hash { using LIEF::Hash::visit; public: - void visit(const Binary& binary) override; - void visit(const Header& header) override; - void visit(const Section& section) override; - void visit(const Symbol& symbol) override; + void visit(const Binary& binary) override; + void visit(const Header& header) override; + void visit(const Section& section) override; + void visit(const Symbol& symbol) override; void visit(const Relocation& relocation) override; - void visit(const Function& function) override; + void visit(const Function& function) override; ~AbstractHash() override; }; diff --git a/deps/LIEF/include/LIEF/Abstract/json.hpp b/deps/LIEF/include/LIEF/Abstract/json.hpp index fa05cec34584..c133c1b54a91 100644 --- a/deps/LIEF/include/LIEF/Abstract/json.hpp +++ b/deps/LIEF/include/LIEF/Abstract/json.hpp @@ -1,5 +1,5 @@ -/* Copyright 2017 - 2025 R. Thomas - * Copyright 2017 - 2025 Quarkslab +/* Copyright 2017 - 2026 R. Thomas + * Copyright 2017 - 2026 Quarkslab * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,5 +26,4 @@ LIEF_API std::string to_json_from_abstract(const Object& v); } -#endif // LIEF_JSON_SUPPORT - +#endif diff --git a/deps/LIEF/include/LIEF/BinaryStream/ASN1Reader.hpp b/deps/LIEF/include/LIEF/BinaryStream/ASN1Reader.hpp index 385bb35dd22c..e0f15ec8d496 100644 --- a/deps/LIEF/include/LIEF/BinaryStream/ASN1Reader.hpp +++ b/deps/LIEF/include/LIEF/BinaryStream/ASN1Reader.hpp @@ -1,5 +1,5 @@ -/* Copyright 2017 - 2025 R. Thomas - * Copyright 2017 - 2025 Quarkslab +/* Copyright 2017 - 2026 R. Thomas + * Copyright 2017 - 2026 Quarkslab * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -34,8 +34,7 @@ class ASN1Reader { ASN1Reader() = delete; ASN1Reader(BinaryStream& stream) : - stream_(stream) - {} + stream_(stream) {} ASN1Reader(const ASN1Reader&) = delete; ASN1Reader& operator=(const ASN1Reader&) = delete; diff --git a/deps/LIEF/include/LIEF/BinaryStream/BinaryStream.hpp b/deps/LIEF/include/LIEF/BinaryStream/BinaryStream.hpp index 48c16034e1df..6be76072b0a1 100644 --- a/deps/LIEF/include/LIEF/BinaryStream/BinaryStream.hpp +++ b/deps/LIEF/include/LIEF/BinaryStream/BinaryStream.hpp @@ -1,5 +1,5 @@ -/* Copyright 2017 - 2025 R. Thomas - * Copyright 2017 - 2025 Quarkslab +/* Copyright 2017 - 2026 R. Thomas + * Copyright 2017 - 2026 Quarkslab * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,6 +21,7 @@ #include #include #include +#include #include "LIEF/endianness_support.hpp" #include "LIEF/errors.hpp" @@ -28,6 +29,7 @@ namespace LIEF { class ASN1Reader; +class Binary; /// Class that is used to a read stream of data from different sources class LIEF_API BinaryStream { @@ -40,13 +42,13 @@ class LIEF_API BinaryStream { MEMORY, SPAN, FILE, + DUMP, ELF_DATA_HANDLER, }; BinaryStream(STREAM_TYPE type) : - stype_(type) - {} + stype_(type) {} virtual ~BinaryStream() = default; virtual uint64_t size() const = 0; @@ -54,6 +56,18 @@ class LIEF_API BinaryStream { return stype_; } + bool is_memory_stream() const { + return type() == STREAM_TYPE::MEMORY; + } + + bool is_dump_stream() const { + return type() == STREAM_TYPE::DUMP; + } + + bool is_memory_view() const { + return is_memory_stream() || is_dump_stream(); + } + result read_uleb128(size_t* size = nullptr) const; result read_sleb128(size_t* size = nullptr) const; @@ -61,7 +75,9 @@ class LIEF_API BinaryStream { result read_string(size_t maxsize = ~static_cast(0)) const; result peek_string(size_t maxsize = ~static_cast(0)) const; - result peek_string_at(size_t offset, size_t maxsize = ~static_cast(0)) const; + result + peek_string_at(size_t offset, + size_t maxsize = ~static_cast(0)) const; result read_u16string() const; result peek_u16string() const; @@ -73,27 +89,31 @@ class LIEF_API BinaryStream { result peek_u16string_at(size_t offset, size_t length) const; - virtual ok_error_t peek_data(std::vector& container, - uint64_t offset, uint64_t size, - uint64_t virtual_address = 0) - { + virtual ok_error_t peek_data(std::vector& container, uint64_t offset, + uint64_t size, uint64_t virtual_address = 0) { if (size == 0) { return ok(); } // Even though offset + size < ... => offset < ... // the addition could overflow so it's worth checking both - const bool read_ok = offset <= this->size() && (offset + size) <= this->size() - /* Check for an overflow */ - && (static_cast(offset) >= 0 && static_cast(size) >= 0) - && (static_cast(offset + size) >= 0); + const bool read_ok = offset <= this->size() && + (offset + size) <= this->size() + /* Check for an overflow */ + && (static_cast(offset) >= 0 && + static_cast(size) >= 0) && + (static_cast(offset + size) >= 0); if (!read_ok) { return make_error_code(lief_errors::read_error); } - container.resize(size); - if (peek_in(container.data(), offset, size, virtual_address)) { - return ok(); + + if (container.size() < size) { + std::vector buffer(size); + const ok_error_t res = peek_in(buffer.data(), offset, size, virtual_address); + container = std::move(buffer); + return res; } - return make_error_code(lief_errors::read_error); + + return peek_in(container.data(), offset, size, virtual_address); } virtual ok_error_t read_data(std::vector& container, uint64_t size) { @@ -130,7 +150,8 @@ class LIEF_API BinaryStream { } template - ok_error_t peek_objects_at(uint64_t offset, std::vector& container, uint64_t count) { + ok_error_t peek_objects_at(uint64_t offset, std::vector& container, + uint64_t count) { if (count == 0) { return ok(); } @@ -144,22 +165,25 @@ class LIEF_API BinaryStream { return make_error_code(lief_errors::read_error); } - container.resize(count); + ok_error_t res = make_error_code(lief_errors::inconsistent); - if (!peek_in(container.data(), pos(), size)) { - setpos(current_p); - return make_error_code(lief_errors::read_error); + if (container.size() < count) { + std::vector buffer(count); + res = peek_in(buffer.data(), pos(), size); + container = std::move(buffer); + } else { + res = peek_in(container.data(), pos(), size); } setpos(current_p); - return ok(); + return res; } void setpos(size_t pos) const { pos_ = pos; } - const BinaryStream& increment_pos(size_t value) const { + const BinaryStream& increment_pos(size_t value) const LIEF_LIFETIMEBOUND { pos_ += value; return *this; } @@ -176,10 +200,14 @@ class LIEF_API BinaryStream { return pos_; } - operator bool() const { + bool is_valid() const { return pos_ < size(); } + operator bool() const { + return is_valid(); + } + template const T* read_array(size_t size) const; @@ -190,10 +218,12 @@ class LIEF_API BinaryStream { } // Even though offset + size < ... => offset < ... // the addition could overflow so it's worth checking both - const bool read_ok = pos_ <= size() && (pos_ + N) <= size() - /* Check for an overflow */ - && (static_cast(pos_) >= 0 && static_cast(N) >= 0) - && (static_cast(pos_ + N) >= 0); + const bool read_ok = + pos_ <= size() && + (pos_ + N) <= size() + /* Check for an overflow */ + && (static_cast(pos_) >= 0 && static_cast(N) >= 0) && + (static_cast(pos_ + N) >= 0); if (!read_ok) { return make_error_code(lief_errors::read_error); @@ -236,7 +266,8 @@ class LIEF_API BinaryStream { bool can_read(size_t offset) const; bool can_read(int64_t offset, int64_t size) const { - return offset < (int64_t)this->size() && (offset + size) < (int64_t)this->size(); + return offset < (int64_t)this->size() && + size < ((int64_t)this->size() - offset); } size_t align(size_t align_on) const; @@ -247,16 +278,15 @@ class LIEF_API BinaryStream { template static bool is_all_zero(const T& buffer) { - const auto* ptr = reinterpret_cast(&buffer); - return std::all_of(ptr, ptr + sizeof(T), - [] (uint8_t x) { return x == 0; }); + const auto* ptr = reinterpret_cast(&buffer); + return std::all_of(ptr, ptr + sizeof(T), [](uint8_t x) { return x == 0; }); } bool should_swap() const { return endian_swap_; } - virtual const uint8_t* p() const { + virtual const uint8_t* p() const { return nullptr; } @@ -284,11 +314,10 @@ class LIEF_API BinaryStream { uint64_t virtual_address = 0) const = 0; virtual ok_error_t peek_in(void* dst, uint64_t offset, uint64_t size, uint64_t virtual_address = 0) const { + if (dst == nullptr) { + return make_error_code(lief_errors::read_error); + } if (auto raw = read_at(offset, size, virtual_address)) { - if (dst == nullptr) { - return make_error_code(lief_errors::read_error); - } - const void* ptr = *raw; if (ptr == nullptr) { @@ -301,6 +330,25 @@ class LIEF_API BinaryStream { return make_error_code(lief_errors::read_error); } + template + const T* cast() const { + static_assert(std::is_base_of::value, + "Require BinaryStream inheritance"); + if (T::classof(*this)) { + return static_cast(this); + } + return nullptr; + } + + template + T* cast() { + return const_cast(static_cast(this)->cast()); + } + + virtual bool bind_binary(Binary& /*bin*/) { + return false; + } + protected: BinaryStream() = default; @@ -319,15 +367,13 @@ class ScopedStream { explicit ScopedStream(BinaryStream& stream, uint64_t pos) : pos_{stream.pos()}, - stream_{stream} - { + stream_{stream} { stream_.setpos(pos); } explicit ScopedStream(BinaryStream& stream) : pos_{stream.pos()}, - stream_{stream} - {} + stream_{stream} {} ~ScopedStream() { stream_.setpos(pos_); @@ -360,15 +406,13 @@ class ToggleEndianness { explicit ToggleEndianness(BinaryStream& stream, bool value) : endian_swap_(stream.should_swap()), - stream_{stream} - { + stream_{stream} { stream.set_endian_swap(value); } explicit ToggleEndianness(BinaryStream& stream) : endian_swap_(stream.should_swap()), - stream_{stream} - { + stream_{stream} { stream.set_endian_swap(!stream_.should_swap()); } diff --git a/deps/LIEF/include/LIEF/BinaryStream/DumpStream.hpp b/deps/LIEF/include/LIEF/BinaryStream/DumpStream.hpp new file mode 100644 index 000000000000..e7d1fec8ddf8 --- /dev/null +++ b/deps/LIEF/include/LIEF/BinaryStream/DumpStream.hpp @@ -0,0 +1,97 @@ +/* Copyright 2017 - 2026 R. Thomas + * Copyright 2017 - 2026 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 LIEF_DUMP_STREAM_H +#define LIEF_DUMP_STREAM_H + +#include +#include + +#include "LIEF/compiler_attributes.hpp" +#include "LIEF/errors.hpp" +#include "LIEF/visibility.h" +#include "LIEF/BinaryStream/BinaryStream.hpp" + +namespace LIEF { +class Binary; + +/// This stream interface provides facilities to parse a dumped binary. +/// +/// A dump is a contiguous capture of a process memory that starts at a given +/// base address. This stream owns (or weakly references) +/// another BinaryStream that holds the raw dump and translates file offsets +/// into dump offsets according to this base address and the binary layout. +class LIEF_API DumpStream : public BinaryStream { + public: + DumpStream() = delete; + DumpStream(uintptr_t base_address, BinaryStream& ref) : + BinaryStream(BinaryStream::STREAM_TYPE::DUMP), + baseaddr_(base_address), + ref_(&ref) {} + + DumpStream(uintptr_t base_address, std::unique_ptr owned) : + BinaryStream(BinaryStream::STREAM_TYPE::DUMP), + baseaddr_(base_address), + owned_(std::move(owned)), + ref_(owned_.get()) {} + + DumpStream(const DumpStream&) = delete; + DumpStream& operator=(const DumpStream&) = delete; + + DumpStream(DumpStream&&) noexcept = default; + DumpStream& operator=(DumpStream&&) noexcept = default; + + uintptr_t base_address() const { + return baseaddr_; + } + + Binary* binary() LIEF_LIFETIMEBOUND { + return binary_; + } + + uint64_t size() const override { + return ref_->size(); + } + + bool bind_binary(Binary& bin) override { + binary_ = &bin; + return true; + } + + std::vector content() const; + + result read_at(uint64_t /*offset*/, uint64_t /*size*/, + uint64_t /*virtual_address*/ = 0) const override { + return make_error_code(lief_errors::not_supported); + } + + ok_error_t peek_in(void* dst, uint64_t offset, uint64_t size, + uint64_t virtual_address = 0) const override; + + ~DumpStream() override = default; + + static bool classof(const BinaryStream& stream) { + return stream.type() == BinaryStream::STREAM_TYPE::DUMP; + } + + protected: + uintptr_t baseaddr_ = 0; + Binary* binary_ = nullptr; + std::unique_ptr owned_; + BinaryStream* ref_ = nullptr; +}; +} + +#endif diff --git a/deps/LIEF/include/LIEF/BinaryStream/FileStream.hpp b/deps/LIEF/include/LIEF/BinaryStream/FileStream.hpp index 0e5d3e5cc86d..dc3583e64e9f 100644 --- a/deps/LIEF/include/LIEF/BinaryStream/FileStream.hpp +++ b/deps/LIEF/include/LIEF/BinaryStream/FileStream.hpp @@ -1,5 +1,5 @@ -/* Copyright 2017 - 2025 R. Thomas - * Copyright 2017 - 2025 Quarkslab +/* Copyright 2017 - 2026 R. Thomas + * Copyright 2017 - 2026 Quarkslab * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -33,8 +33,7 @@ class LIEF_API FileStream : public BinaryStream { FileStream(std::ifstream fs, uint64_t size) : BinaryStream(STREAM_TYPE::FILE), ifs_(std::move(fs)), - size_(size) - {} + size_(size) {} FileStream() = delete; @@ -56,7 +55,7 @@ class LIEF_API FileStream : public BinaryStream { } ok_error_t peek_in(void* dst, uint64_t offset, uint64_t size, - uint64_t /* virtual_address */= 0) const override { + uint64_t /* virtual_address */ = 0) const override { if (offset > size_ || offset + size > size_) { return make_error_code(lief_errors::read_error); } diff --git a/deps/LIEF/include/LIEF/BinaryStream/MemoryStream.hpp b/deps/LIEF/include/LIEF/BinaryStream/MemoryStream.hpp index 9bce7e764be3..bfa9588365b8 100644 --- a/deps/LIEF/include/LIEF/BinaryStream/MemoryStream.hpp +++ b/deps/LIEF/include/LIEF/BinaryStream/MemoryStream.hpp @@ -1,5 +1,5 @@ -/* Copyright 2017 - 2025 R. Thomas - * Copyright 2017 - 2025 Quarkslab +/* Copyright 2017 - 2026 R. Thomas + * Copyright 2017 - 2026 Quarkslab * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -35,8 +35,7 @@ class LIEF_API MemoryStream : public BinaryStream { MemoryStream(uintptr_t base_address, uint64_t size) : BinaryStream(BinaryStream::STREAM_TYPE::MEMORY), baseaddr_(base_address), - size_(size) - {} + size_(size) {} MemoryStream(const MemoryStream&) = delete; MemoryStream& operator=(const MemoryStream&) = delete; @@ -45,7 +44,7 @@ class LIEF_API MemoryStream : public BinaryStream { MemoryStream& operator=(MemoryStream&&) noexcept = default; uintptr_t base_address() const { - return this->baseaddr_; + return baseaddr_; } const uint8_t* p() const override { @@ -60,18 +59,19 @@ class LIEF_API MemoryStream : public BinaryStream { return start() + size_; } - void binary(Binary& bin) { - this->binary_ = &bin; - } - Binary* binary() { - return this->binary_; + return binary_; } uint64_t size() const override { return size_; } + bool bind_binary(Binary& bin) override { + binary_ = &bin; + return true; + } + ~MemoryStream() override = default; static bool classof(const BinaryStream& stream) { @@ -79,7 +79,8 @@ class LIEF_API MemoryStream : public BinaryStream { } protected: - result read_at(uint64_t offset, uint64_t size, uint64_t va) const override; + result read_at(uint64_t offset, uint64_t size, + uint64_t va) const override; uintptr_t baseaddr_ = 0; uint64_t size_ = 0; Binary* binary_ = nullptr; diff --git a/deps/LIEF/include/LIEF/BinaryStream/SpanStream.hpp b/deps/LIEF/include/LIEF/BinaryStream/SpanStream.hpp index ce7e8b4c0033..27ffea72cac2 100644 --- a/deps/LIEF/include/LIEF/BinaryStream/SpanStream.hpp +++ b/deps/LIEF/include/LIEF/BinaryStream/SpanStream.hpp @@ -1,5 +1,5 @@ -/* Copyright 2017 - 2025 R. Thomas - * Copyright 2017 - 2025 Quarkslab +/* Copyright 2017 - 2026 R. Thomas + * Copyright 2017 - 2026 Quarkslab * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -45,21 +45,17 @@ class LIEF_API SpanStream : public BinaryStream { } SpanStream(span data) : - SpanStream(data.data(), data.size()) - {} + SpanStream(data.data(), data.size()) {} SpanStream(span data) : - SpanStream(data.data(), data.size()) - {} + SpanStream(data.data(), data.size()) {} SpanStream(const uint8_t* p, size_t size) : BinaryStream(BinaryStream::STREAM_TYPE::SPAN), - data_{p, p + size} - {} + data_{p, p + size} {} SpanStream(const std::vector& data) : - SpanStream(data.data(), data.size()) - {} + SpanStream(data.data(), data.size()) {} std::unique_ptr clone() const { return std::unique_ptr(new SpanStream(*this)); @@ -94,7 +90,7 @@ class LIEF_API SpanStream : public BinaryStream { } result slice(size_t offset, size_t size) const { - if (offset > data_.size() || (offset + size) > data_.size()) { + if (offset > data_.size() || size > data_.size() - offset) { return make_error_code(lief_errors::read_out_of_bound); } return data_.subspan(offset, size); @@ -115,9 +111,10 @@ class LIEF_API SpanStream : public BinaryStream { ~SpanStream() override = default; protected: - result read_at(uint64_t offset, uint64_t size, uint64_t /*va*/) const override { + result read_at(uint64_t offset, uint64_t size, + uint64_t /*va*/) const override { const uint64_t stream_size = this->size(); - if (offset > stream_size || (offset + size) > stream_size) { + if (offset > stream_size || size > stream_size - offset) { return make_error_code(lief_errors::read_error); } return data_.data() + offset; diff --git a/deps/LIEF/include/LIEF/BinaryStream/VectorStream.hpp b/deps/LIEF/include/LIEF/BinaryStream/VectorStream.hpp index 44293aa8c857..7d17d97a4c52 100644 --- a/deps/LIEF/include/LIEF/BinaryStream/VectorStream.hpp +++ b/deps/LIEF/include/LIEF/BinaryStream/VectorStream.hpp @@ -1,5 +1,5 @@ -/* Copyright 2017 - 2025 R. Thomas - * Copyright 2017 - 2025 Quarkslab +/* Copyright 2017 - 2026 R. Thomas + * Copyright 2017 - 2026 Quarkslab * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -36,8 +36,7 @@ class LIEF_API VectorStream : public BinaryStream { VectorStream(std::vector data) : BinaryStream(BinaryStream::STREAM_TYPE::VECTOR), binary_(std::move(data)), - size_(binary_.size()) - {} + size_(binary_.size()) {} VectorStream() = delete; @@ -82,9 +81,10 @@ class LIEF_API VectorStream : public BinaryStream { } protected: - result read_at(uint64_t offset, uint64_t size, uint64_t /*va*/) const override { + result read_at(uint64_t offset, uint64_t size, + uint64_t /*va*/) const override { const uint64_t stream_size = this->size(); - if (offset > stream_size || (offset + size) > stream_size) { + if (offset > stream_size || size > stream_size - offset) { return make_error_code(lief_errors::read_error); } return binary_.data() + offset; diff --git a/deps/LIEF/include/LIEF/COFF.hpp b/deps/LIEF/include/LIEF/COFF.hpp index dcc13dbde0d3..64775817a3cd 100644 --- a/deps/LIEF/include/LIEF/COFF.hpp +++ b/deps/LIEF/include/LIEF/COFF.hpp @@ -1,5 +1,5 @@ -/* Copyright 2017 - 2025 R. Thomas - * Copyright 2017 - 2025 Quarkslab +/* Copyright 2017 - 2026 R. Thomas + * Copyright 2017 - 2026 Quarkslab * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,30 +13,30 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#ifndef LIEF_COFF_H -#define LIEF_COFF_H +#ifndef LIEF_COFF_H +#define LIEF_COFF_H #include "LIEF/config.h" #if defined(LIEF_COFF_SUPPORT) -#include "LIEF/COFF/Binary.hpp" -#include "LIEF/COFF/utils.hpp" -#include "LIEF/COFF/Parser.hpp" -#include "LIEF/COFF/Header.hpp" -#include "LIEF/COFF/BigObjHeader.hpp" -#include "LIEF/COFF/RegularHeader.hpp" -#include "LIEF/COFF/ParserConfig.hpp" -#include "LIEF/COFF/Section.hpp" -#include "LIEF/COFF/Relocation.hpp" -#include "LIEF/COFF/Symbol.hpp" -#include "LIEF/COFF/String.hpp" + #include "LIEF/COFF/Binary.hpp" + #include "LIEF/COFF/utils.hpp" + #include "LIEF/COFF/Parser.hpp" + #include "LIEF/COFF/Header.hpp" + #include "LIEF/COFF/BigObjHeader.hpp" + #include "LIEF/COFF/RegularHeader.hpp" + #include "LIEF/COFF/ParserConfig.hpp" + #include "LIEF/COFF/Section.hpp" + #include "LIEF/COFF/Relocation.hpp" + #include "LIEF/COFF/Symbol.hpp" + #include "LIEF/COFF/String.hpp" -#include "LIEF/COFF/AuxiliarySymbol.hpp" -#include "LIEF/COFF/AuxiliarySymbols/AuxiliarybfAndefSymbol.hpp" -#include "LIEF/COFF/AuxiliarySymbols/AuxiliaryCLRToken.hpp" -#include "LIEF/COFF/AuxiliarySymbols/AuxiliaryFile.hpp" -#include "LIEF/COFF/AuxiliarySymbols/AuxiliaryFunctionDefinition.hpp" -#include "LIEF/COFF/AuxiliarySymbols/AuxiliarySectionDefinition.hpp" -#include "LIEF/COFF/AuxiliarySymbols/AuxiliaryWeakExternal.hpp" + #include "LIEF/COFF/AuxiliarySymbol.hpp" + #include "LIEF/COFF/AuxiliarySymbols/AuxiliarybfAndefSymbol.hpp" + #include "LIEF/COFF/AuxiliarySymbols/AuxiliaryCLRToken.hpp" + #include "LIEF/COFF/AuxiliarySymbols/AuxiliaryFile.hpp" + #include "LIEF/COFF/AuxiliarySymbols/AuxiliaryFunctionDefinition.hpp" + #include "LIEF/COFF/AuxiliarySymbols/AuxiliarySectionDefinition.hpp" + #include "LIEF/COFF/AuxiliarySymbols/AuxiliaryWeakExternal.hpp" #endif #endif diff --git a/deps/LIEF/include/LIEF/COFF/AuxiliarySymbol.hpp b/deps/LIEF/include/LIEF/COFF/AuxiliarySymbol.hpp index 398776a324d4..9d7970f57880 100644 --- a/deps/LIEF/include/LIEF/COFF/AuxiliarySymbol.hpp +++ b/deps/LIEF/include/LIEF/COFF/AuxiliarySymbol.hpp @@ -1,5 +1,5 @@ -/* Copyright 2017 - 2025 R. Thomas - * Copyright 2017 - 2025 Quarkslab +/* Copyright 2017 - 2026 R. Thomas + * Copyright 2017 - 2026 Quarkslab * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,6 +20,7 @@ #include #include +#include "LIEF/compiler_attributes.hpp" #include "LIEF/visibility.h" #include "LIEF/span.hpp" @@ -32,14 +33,12 @@ class Symbol; /// Class that represents an auxiliary symbol. /// /// An auxiliary symbol has the same size as a regular LIEF::PE::Symbol (18 -/// bytes) but its content depends on the the parent symbol. +/// bytes) but its content depends on the parent symbol. class LIEF_API AuxiliarySymbol { public: AuxiliarySymbol() = default; AuxiliarySymbol(std::vector payload) : - type_(TYPE::UNKNOWN), - payload_(std::move(payload)) - {} + payload_(std::move(payload)) {} AuxiliarySymbol(const AuxiliarySymbol&) = default; AuxiliarySymbol& operator=(const AuxiliarySymbol&) = default; @@ -47,7 +46,7 @@ class LIEF_API AuxiliarySymbol { AuxiliarySymbol& operator=(AuxiliarySymbol&&) = default; LIEF_LOCAL static std::unique_ptr - parse(Symbol& sym, std::vector payload); + parse(Symbol& sym, std::vector payload); virtual std::unique_ptr clone() const { return std::unique_ptr(new AuxiliarySymbol(*this)); @@ -59,19 +58,22 @@ class LIEF_API AuxiliarySymbol { CLR_TOKEN, /// Auxiliary Format 1 from the PE-COFF documentation FUNC_DEF, + /// Auxiliary Format 2: .bf and .ef Symbols from the PE-COFF documentation BF_AND_EF, + /// Auxiliary Format 3: Weak Externals from the PE-COFF documentation WEAK_EXTERNAL, + /// Auxiliary Format 4: Files from the PE-COFF documentation FILE, + /// Auxiliary Format 5: Section Definitions from the PE-COFF documentation SEC_DEF, }; AuxiliarySymbol(TYPE ty) : - type_(ty) - {} + type_(ty) {} static TYPE get_aux_type(const Symbol& sym); @@ -80,11 +82,11 @@ class LIEF_API AuxiliarySymbol { } /// For unknown type **only**, return the raw representation of this symbol - span payload() const { + span payload() const LIEF_LIFETIMEBOUND { return payload_; } - span payload() { + span payload() LIEF_LIFETIMEBOUND { return payload_; } @@ -92,7 +94,7 @@ class LIEF_API AuxiliarySymbol { virtual ~AuxiliarySymbol() = default; - /// Helper to **downcast** a AuxiliarySymbol into a concrete implementation + /// Helper to **downcast** an AuxiliarySymbol into a concrete implementation template const T* as() const { static_assert(std::is_base_of::value, @@ -108,9 +110,8 @@ class LIEF_API AuxiliarySymbol { return const_cast(static_cast(this)->as()); } - LIEF_API friend - std::ostream& operator<<(std::ostream& os, const AuxiliarySymbol& aux) - { + LIEF_API friend std::ostream& operator<<(std::ostream& os, + const AuxiliarySymbol& aux) { os << aux.to_string(); return os; } diff --git a/deps/LIEF/include/LIEF/COFF/AuxiliarySymbols/AuxiliaryCLRToken.hpp b/deps/LIEF/include/LIEF/COFF/AuxiliarySymbols/AuxiliaryCLRToken.hpp index cc2ee5feb71f..65059a062499 100644 --- a/deps/LIEF/include/LIEF/COFF/AuxiliarySymbols/AuxiliaryCLRToken.hpp +++ b/deps/LIEF/include/LIEF/COFF/AuxiliarySymbols/AuxiliaryCLRToken.hpp @@ -1,5 +1,5 @@ -/* Copyright 2017 - 2025 R. Thomas - * Copyright 2017 - 2025 Quarkslab +/* Copyright 2017 - 2026 R. Thomas + * Copyright 2017 - 2026 Quarkslab * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,6 +18,7 @@ #include +#include "LIEF/compiler_attributes.hpp" #include "LIEF/visibility.h" #include "LIEF/COFF/AuxiliarySymbol.hpp" @@ -32,11 +33,10 @@ class LIEF_API AuxiliaryCLRToken : public AuxiliarySymbol { friend class Parser; LIEF_LOCAL static std::unique_ptr - parse(const std::vector& payload); + parse(const std::vector& payload); AuxiliaryCLRToken() : - AuxiliarySymbol(AuxiliarySymbol::TYPE::CLR_TOKEN) - {} + AuxiliarySymbol(AuxiliarySymbol::TYPE::CLR_TOKEN) {} AuxiliaryCLRToken(uint8_t aux_type, uint8_t reserved, uint32_t symbol_idx, std::vector rgb_reserved) : @@ -44,8 +44,7 @@ class LIEF_API AuxiliaryCLRToken : public AuxiliarySymbol { aux_type_(aux_type), reserved_(reserved), symbol_idx_(symbol_idx), - rgb_reserved_(std::move(rgb_reserved)) - {} + rgb_reserved_(std::move(rgb_reserved)) {} AuxiliaryCLRToken(const AuxiliaryCLRToken&) = default; AuxiliaryCLRToken& operator=(const AuxiliaryCLRToken&) = default; @@ -82,7 +81,7 @@ class LIEF_API AuxiliaryCLRToken : public AuxiliarySymbol { } /// Reserved (padding) values. Should be 0 - span rgb_reserved() const { + span rgb_reserved() const LIEF_LIFETIMEBOUND { return rgb_reserved_; } @@ -93,6 +92,7 @@ class LIEF_API AuxiliaryCLRToken : public AuxiliarySymbol { } ~AuxiliaryCLRToken() override = default; + private: uint8_t aux_type_ = 0; uint8_t reserved_ = 0; diff --git a/deps/LIEF/include/LIEF/COFF/AuxiliarySymbols/AuxiliaryFile.hpp b/deps/LIEF/include/LIEF/COFF/AuxiliarySymbols/AuxiliaryFile.hpp index 28ed0142d341..102fa70141ce 100644 --- a/deps/LIEF/include/LIEF/COFF/AuxiliarySymbols/AuxiliaryFile.hpp +++ b/deps/LIEF/include/LIEF/COFF/AuxiliarySymbols/AuxiliaryFile.hpp @@ -1,5 +1,5 @@ -/* Copyright 2017 - 2025 R. Thomas - * Copyright 2017 - 2025 Quarkslab +/* Copyright 2017 - 2026 R. Thomas + * Copyright 2017 - 2026 Quarkslab * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,20 +29,19 @@ namespace COFF { /// The Symbol::name itself should start with `.file`, and this auxiliary record /// gives the name of a source-code file. /// -/// Reference: https://learn.microsoft.com/en-us/windows/win32/debug/pe-format#auxiliary-format-4-files +/// Reference: +/// https://learn.microsoft.com/en-us/windows/win32/debug/pe-format#auxiliary-format-4-files class LIEF_API AuxiliaryFile : public AuxiliarySymbol { public: LIEF_LOCAL static std::unique_ptr - parse(const std::vector& payload); + parse(const std::vector& payload); AuxiliaryFile() : - AuxiliarySymbol(AuxiliarySymbol::TYPE::FILE) - {} + AuxiliarySymbol(AuxiliarySymbol::TYPE::FILE) {} AuxiliaryFile(std::string file) : AuxiliarySymbol(AuxiliarySymbol::TYPE::FILE), - filename_(std::move(file)) - {} + filename_(std::move(file)) {} AuxiliaryFile(const AuxiliaryFile&) = default; AuxiliaryFile& operator=(const AuxiliaryFile&) = default; diff --git a/deps/LIEF/include/LIEF/COFF/AuxiliarySymbols/AuxiliaryFunctionDefinition.hpp b/deps/LIEF/include/LIEF/COFF/AuxiliarySymbols/AuxiliaryFunctionDefinition.hpp index a3f184ff7610..05e92ea04dd8 100644 --- a/deps/LIEF/include/LIEF/COFF/AuxiliarySymbols/AuxiliaryFunctionDefinition.hpp +++ b/deps/LIEF/include/LIEF/COFF/AuxiliarySymbols/AuxiliaryFunctionDefinition.hpp @@ -1,5 +1,5 @@ -/* Copyright 2017 - 2025 R. Thomas - * Copyright 2017 - 2025 Quarkslab +/* Copyright 2017 - 2026 R. Thomas + * Copyright 2017 - 2026 Quarkslab * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,35 +26,36 @@ namespace COFF { /// This auxiliary symbols marks the beginning of a function definition. /// -/// Reference: https://learn.microsoft.com/en-us/windows/win32/debug/pe-format#auxiliary-format-1-function-definitions +/// Reference: +/// https://learn.microsoft.com/en-us/windows/win32/debug/pe-format#auxiliary-format-1-function-definitions class LIEF_API AuxiliaryFunctionDefinition : public AuxiliarySymbol { public: LIEF_LOCAL static std::unique_ptr - parse(const std::vector& payload); + parse(const std::vector& payload); AuxiliaryFunctionDefinition() : - AuxiliarySymbol(AuxiliarySymbol::TYPE::FUNC_DEF) - {} + AuxiliarySymbol(AuxiliarySymbol::TYPE::FUNC_DEF) {} - AuxiliaryFunctionDefinition(uint32_t tagidx, uint32_t totalsz, - uint32_t ptr_line, uint32_t ptr_next_func, - uint16_t padding) : + AuxiliaryFunctionDefinition(uint32_t tagidx, uint32_t totalsz, uint32_t ptr_line, + uint32_t ptr_next_func, uint16_t padding) : AuxiliarySymbol(AuxiliarySymbol::TYPE::FUNC_DEF), tag_index_(tagidx), total_size_(totalsz), ptr_to_linenb_(ptr_line), ptr_to_next_func_(ptr_next_func), - padding_(padding) - {} + padding_(padding) {} AuxiliaryFunctionDefinition(const AuxiliaryFunctionDefinition&) = default; - AuxiliaryFunctionDefinition& operator=(const AuxiliaryFunctionDefinition&) = default; + AuxiliaryFunctionDefinition& + operator=(const AuxiliaryFunctionDefinition&) = default; AuxiliaryFunctionDefinition(AuxiliaryFunctionDefinition&&) = default; AuxiliaryFunctionDefinition& operator=(AuxiliaryFunctionDefinition&&) = default; std::unique_ptr clone() const override { - return std::unique_ptr(new AuxiliaryFunctionDefinition{*this}); + return std::unique_ptr( + new AuxiliaryFunctionDefinition{*this} + ); } /// The symbol-table index of the corresponding `.bf` (begin function) diff --git a/deps/LIEF/include/LIEF/COFF/AuxiliarySymbols/AuxiliarySectionDefinition.hpp b/deps/LIEF/include/LIEF/COFF/AuxiliarySymbols/AuxiliarySectionDefinition.hpp index 9037b7700af3..bcb36590a3bb 100644 --- a/deps/LIEF/include/LIEF/COFF/AuxiliarySymbols/AuxiliarySectionDefinition.hpp +++ b/deps/LIEF/include/LIEF/COFF/AuxiliarySymbols/AuxiliarySectionDefinition.hpp @@ -1,5 +1,5 @@ -/* Copyright 2017 - 2025 R. Thomas - * Copyright 2017 - 2025 Quarkslab +/* Copyright 2017 - 2026 R. Thomas + * Copyright 2017 - 2026 Quarkslab * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -30,11 +30,10 @@ namespace COFF { class LIEF_API AuxiliarySectionDefinition : public AuxiliarySymbol { public: LIEF_LOCAL static std::unique_ptr - parse(const std::vector& payload); + parse(const std::vector& payload); AuxiliarySectionDefinition() : - AuxiliarySymbol(AuxiliarySymbol::TYPE::SEC_DEF) - {} + AuxiliarySymbol(AuxiliarySymbol::TYPE::SEC_DEF) {} AuxiliarySectionDefinition(uint32_t length, uint16_t nb_relocs, uint16_t nb_lines, uint32_t checksum, @@ -47,27 +46,30 @@ class LIEF_API AuxiliarySectionDefinition : public AuxiliarySymbol { checksum_(checksum), sec_idx_(sec_idx), selection_((COMDAT_SELECTION)selection), - reserved_(reserved) - {} + reserved_(reserved) {} AuxiliarySectionDefinition(const AuxiliarySectionDefinition&) = default; - AuxiliarySectionDefinition& operator=(const AuxiliarySectionDefinition&) = default; + AuxiliarySectionDefinition& + operator=(const AuxiliarySectionDefinition&) = default; AuxiliarySectionDefinition(AuxiliarySectionDefinition&&) = default; AuxiliarySectionDefinition& operator=(AuxiliarySectionDefinition&&) = default; std::unique_ptr clone() const override { - return std::unique_ptr(new AuxiliarySectionDefinition{*this}); + return std::unique_ptr( + new AuxiliarySectionDefinition{*this} + ); } /// Values for the AuxiliarySectionDefinition::selection attribute /// - /// See: https://learn.microsoft.com/en-us/windows/win32/debug/pe-format#comdat-sections-object-only + /// See: + /// https://learn.microsoft.com/en-us/windows/win32/debug/pe-format#comdat-sections-object-only enum class COMDAT_SELECTION : uint8_t { NONE = 0, - /// If this symbol is already defined, the linker issues a `multiply defined symbol` - /// error. + /// If this symbol is already defined, the linker issues a `multiply defined + /// symbol` error. NODUPLICATES = 1, /// Any section that defines the same COMDAT symbol can be linked; the rest @@ -75,8 +77,8 @@ class LIEF_API AuxiliarySectionDefinition : public AuxiliarySymbol { ANY, /// The linker chooses an arbitrary section among the definitions for this - /// symbol. If all definitions are not the same size, a `multiply defined symbol` - /// error is issued. + /// symbol. If all definitions are not the same size, a `multiply defined + /// symbol` error is issued. SAME_SIZE, /// The linker chooses an arbitrary section among the definitions for this @@ -100,7 +102,7 @@ class LIEF_API AuxiliarySectionDefinition : public AuxiliarySymbol { /// The linker chooses the largest definition from among all of the definitions /// for this symbol. If multiple definitions have this size, the choice /// between them is arbitrary. - LARGEST + LARGEST, }; /// The size of section data. The same as `SizeOfRawData` in the section header. diff --git a/deps/LIEF/include/LIEF/COFF/AuxiliarySymbols/AuxiliaryWeakExternal.hpp b/deps/LIEF/include/LIEF/COFF/AuxiliarySymbols/AuxiliaryWeakExternal.hpp index 488f787dec12..7f79aa760fe2 100644 --- a/deps/LIEF/include/LIEF/COFF/AuxiliarySymbols/AuxiliaryWeakExternal.hpp +++ b/deps/LIEF/include/LIEF/COFF/AuxiliarySymbols/AuxiliaryWeakExternal.hpp @@ -1,5 +1,5 @@ -/* Copyright 2017 - 2025 R. Thomas - * Copyright 2017 - 2025 Quarkslab +/* Copyright 2017 - 2026 R. Thomas + * Copyright 2017 - 2026 Quarkslab * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,6 +19,7 @@ #include #include +#include "LIEF/compiler_attributes.hpp" #include "LIEF/visibility.h" #include "LIEF/COFF/AuxiliarySymbol.hpp" @@ -34,37 +35,39 @@ namespace COFF { /// /// If a definition of `sym1` is linked, then an external reference to the /// symbol is resolved normally. If a definition of `sym1` is not linked, then all -/// references to the weak external for `sym1` refer to `sym2` instead. The external -/// symbol, `sym2`, must always be linked; typically, it is defined in the module -/// that contains the weak reference to `sym1`. +/// references to the weak external for `sym1` refer to `sym2` instead. The +/// external symbol, `sym2`, must always be linked; typically, it is defined in the +/// module that contains the weak reference to `sym1`. /// -/// Reference: https://learn.microsoft.com/en-us/windows/win32/debug/pe-format#auxiliary-format-3-weak-externals +/// Reference: +/// https://learn.microsoft.com/en-us/windows/win32/debug/pe-format#auxiliary-format-3-weak-externals class LIEF_API AuxiliaryWeakExternal : public AuxiliarySymbol { public: enum class CHARACTERISTICS : uint32_t { /// No library search for `sym1` should be performed. SEARCH_NOLIBRARY = 1, - ///A library search for `sym1` should be performed. + + /// A library search for `sym1` should be performed. SEARCH_LIBRARY = 2, + /// `sym1` is an alias for sym2 SEARCH_ALIAS = 3, - ANTI_DEPENDENCY = 4 + + ANTI_DEPENDENCY = 4, }; LIEF_LOCAL static std::unique_ptr - parse(const std::vector& payload); + parse(const std::vector& payload); AuxiliaryWeakExternal() : - AuxiliarySymbol(AuxiliarySymbol::TYPE::WEAK_EXTERNAL) - {} + AuxiliarySymbol(AuxiliarySymbol::TYPE::WEAK_EXTERNAL) {} AuxiliaryWeakExternal(uint32_t sym_idx, uint32_t characteristics, std::vector padding) : AuxiliarySymbol(AuxiliarySymbol::TYPE::WEAK_EXTERNAL), sym_idx_(sym_idx), characteristics_(characteristics), - padding_(std::move(padding)) - { + padding_(std::move(padding)) { assert(padding_.size() == 10); } @@ -75,7 +78,9 @@ class LIEF_API AuxiliaryWeakExternal : public AuxiliarySymbol { AuxiliaryWeakExternal& operator=(AuxiliaryWeakExternal&&) = default; std::unique_ptr clone() const override { - return std::unique_ptr(new AuxiliaryWeakExternal{*this}); + return std::unique_ptr( + new AuxiliaryWeakExternal{*this} + ); } /// The symbol-table index of `sym2`, the symbol to be linked if `sym1` is not @@ -88,7 +93,7 @@ class LIEF_API AuxiliaryWeakExternal : public AuxiliarySymbol { return (CHARACTERISTICS)characteristics_; } - span padding() const { + span padding() const LIEF_LIFETIMEBOUND { return padding_; } diff --git a/deps/LIEF/include/LIEF/COFF/AuxiliarySymbols/AuxiliarybfAndefSymbol.hpp b/deps/LIEF/include/LIEF/COFF/AuxiliarySymbols/AuxiliarybfAndefSymbol.hpp index 53b0666b5888..c76b7de392cf 100644 --- a/deps/LIEF/include/LIEF/COFF/AuxiliarySymbols/AuxiliarybfAndefSymbol.hpp +++ b/deps/LIEF/include/LIEF/COFF/AuxiliarySymbols/AuxiliarybfAndefSymbol.hpp @@ -1,5 +1,5 @@ -/* Copyright 2017 - 2025 R. Thomas - * Copyright 2017 - 2025 Quarkslab +/* Copyright 2017 - 2026 R. Thomas + * Copyright 2017 - 2026 Quarkslab * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -28,11 +28,10 @@ namespace COFF { class LIEF_API AuxiliarybfAndefSymbol : public AuxiliarySymbol { public: LIEF_LOCAL static std::unique_ptr - parse(Symbol& sym, const std::vector& payload); + parse(Symbol& sym, const std::vector& payload); AuxiliarybfAndefSymbol() : - AuxiliarySymbol(AuxiliarySymbol::TYPE::BF_AND_EF) - {} + AuxiliarySymbol(AuxiliarySymbol::TYPE::BF_AND_EF) {} AuxiliarybfAndefSymbol(const AuxiliarybfAndefSymbol&) = default; AuxiliarybfAndefSymbol& operator=(const AuxiliarybfAndefSymbol&) = default; @@ -41,7 +40,9 @@ class LIEF_API AuxiliarybfAndefSymbol : public AuxiliarySymbol { AuxiliarybfAndefSymbol& operator=(AuxiliarybfAndefSymbol&&) = default; std::unique_ptr clone() const override { - return std::unique_ptr(new AuxiliarybfAndefSymbol{*this}); + return std::unique_ptr( + new AuxiliarybfAndefSymbol{*this} + ); } std::string to_string() const override { diff --git a/deps/LIEF/include/LIEF/COFF/BigObjHeader.hpp b/deps/LIEF/include/LIEF/COFF/BigObjHeader.hpp index a793092cd648..1ae5597453dd 100644 --- a/deps/LIEF/include/LIEF/COFF/BigObjHeader.hpp +++ b/deps/LIEF/include/LIEF/COFF/BigObjHeader.hpp @@ -1,5 +1,5 @@ -/* Copyright 2017 - 2025 R. Thomas - * Copyright 2017 - 2025 Quarkslab +/* Copyright 2017 - 2026 R. Thomas + * Copyright 2017 - 2026 Quarkslab * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,6 +20,7 @@ #include "LIEF/COFF/Header.hpp" +#include "LIEF/compiler_attributes.hpp" #include "LIEF/visibility.h" #include "LIEF/span.hpp" @@ -35,8 +36,7 @@ class LIEF_API BigObjHeader : public Header { public: static constexpr auto UUID_SZ = 16; BigObjHeader() : - Header(KIND::BIGOBJ) - {} + Header(KIND::BIGOBJ) {} static std::unique_ptr create(BinaryStream& stream); @@ -55,8 +55,9 @@ class LIEF_API BigObjHeader : public Header { return version_; } - /// Originally named `ClassID`, this uuid should match: `{D1BAA1C7-BAEE-4ba9-AF20-FAF66AA4DCB8}` - span uuid() const { + /// Originally named `ClassID`, this uuid should match: + /// `{D1BAA1C7-BAEE-4ba9-AF20-FAF66AA4DCB8}` + span uuid() const LIEF_LIFETIMEBOUND { return uuid_; } diff --git a/deps/LIEF/include/LIEF/COFF/Binary.hpp b/deps/LIEF/include/LIEF/COFF/Binary.hpp index 9467836970e7..4b0cb9f5b204 100644 --- a/deps/LIEF/include/LIEF/COFF/Binary.hpp +++ b/deps/LIEF/include/LIEF/COFF/Binary.hpp @@ -1,5 +1,5 @@ -/* Copyright 2017 - 2025 R. Thomas - * Copyright 2017 - 2025 Quarkslab +/* Copyright 2017 - 2026 R. Thomas + * Copyright 2017 - 2026 Quarkslab * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -61,7 +61,8 @@ class LIEF_API Binary { using it_relocations = ref_iterator; /// Iterator that outputs const Relocation& object - using it_const_relocations = const_ref_iterator; + using it_const_relocations = + const_ref_iterator; /// Internal container used to store COFF's strings using strings_table_t = std::vector; @@ -100,88 +101,92 @@ class LIEF_API Binary { } /// Iterator over the different sections located in this COFF binary - it_sections sections() { + it_sections sections() LIEF_LIFETIMEBOUND { return sections_; } - it_const_sections sections() const { + it_const_sections sections() const LIEF_LIFETIMEBOUND { return sections_; } /// Iterator over **all** the relocations used by this COFF binary - it_relocations relocations() { + it_relocations relocations() LIEF_LIFETIMEBOUND { return relocations_; } - it_const_relocations relocations() const { + it_const_relocations relocations() const LIEF_LIFETIMEBOUND { return relocations_; } /// Iterator over the COFF's symbols - it_symbols symbols() { + it_symbols symbols() LIEF_LIFETIMEBOUND { return symbols_; } - it_const_symbols symbols() const { + it_const_symbols symbols() const LIEF_LIFETIMEBOUND { return symbols_; } /// Iterator over the COFF's strings - it_const_strings_table string_table() const { + it_const_strings_table string_table() const LIEF_LIFETIMEBOUND { return strings_table_; } - it_strings_table string_table() { + it_strings_table string_table() LIEF_LIFETIMEBOUND { return strings_table_; } /// Try to find the COFF string at the given offset in the COFF string table. /// - /// \warning This offset must include the first 4 bytes holding the size of + /// @warning This offset must include the first 4 bytes holding the size of /// the table. Hence, the first string starts a the offset 4. - String* find_string(uint32_t offset) { + String* find_string(uint32_t offset) LIEF_LIFETIMEBOUND { auto it = std::find_if(strings_table_.begin(), strings_table_.end(), - [offset] (const String& item) { - return offset == item.offset(); - } - ); + [offset](const String& item) { + return offset == item.offset(); + }); return it == strings_table_.end() ? nullptr : &*it; } - const String* find_string(uint32_t offset) const { + const String* find_string(uint32_t offset) const LIEF_LIFETIMEBOUND { return const_cast(this)->find_string(offset); } /// Iterator over the functions implemented in this COFF - it_const_function functions() const; + it_const_function functions() const LIEF_LIFETIMEBOUND; - it_functions functions(); + it_functions functions() LIEF_LIFETIMEBOUND; /// Try to find the function (symbol) with the given name - const Symbol* find_function(const std::string& name) const; + const Symbol* find_function(const std::string& name) const LIEF_LIFETIMEBOUND; - Symbol* find_function(const std::string& name) { - return const_cast(static_cast(this)->find_function(name)); + Symbol* find_function(const std::string& name) LIEF_LIFETIMEBOUND { + return const_cast( + static_cast(this)->find_function(name) + ); } /// Try to find the function (symbol) with the given **demangled** name - const Symbol* find_demangled_function(const std::string& name) const; + const Symbol* + find_demangled_function(const std::string& name) const LIEF_LIFETIMEBOUND; - Symbol* find_demangled_function(const std::string& name) { - return const_cast(static_cast(this)->find_demangled_function(name)); + Symbol* find_demangled_function(const std::string& name) LIEF_LIFETIMEBOUND { + return const_cast( + static_cast(this)->find_demangled_function(name) + ); } /// Disassemble code for the given symbol /// /// ```cpp - /// const Symbol* func = binary->find_demangled_function("int __cdecl my_function(int, int)"); - /// auto insts = binary->disassemble(*func); - /// for (std::unique_ptr inst : insts) { + /// const Symbol* func = binary->find_demangled_function("int __cdecl + /// my_function(int, int)"); auto insts = binary->disassemble(*func); for + /// (std::unique_ptr inst : insts) { /// std::cout << inst->to_string() << '\n'; /// } /// ``` /// - /// \see LIEF::assembly::Instruction + /// @see LIEF::assembly::Instruction instructions_it disassemble(const Symbol& symbol) const; /// Disassemble code for the given symbol name @@ -193,13 +198,13 @@ class LIEF_API Binary { /// } /// ``` /// - /// \see LIEF::assembly::Instruction + /// @see LIEF::assembly::Instruction instructions_it disassemble(const std::string& symbol) const; /// Disassemble code provided by the given buffer at the specified /// `address` parameter. /// - /// \see LIEF::assembly::Instruction + /// @see LIEF::assembly::Instruction instructions_it disassemble(const uint8_t* buffer, size_t size, uint64_t address = 0) const; @@ -207,7 +212,7 @@ class LIEF_API Binary { /// Disassemble code provided by the given vector of bytes at the specified /// `address` parameter. /// - /// \see LIEF::assembly::Instruction + /// @see LIEF::assembly::Instruction instructions_it disassemble(const std::vector& buffer, uint64_t address = 0) const { return disassemble(buffer.data(), buffer.size(), address); @@ -218,7 +223,8 @@ class LIEF_API Binary { return disassemble(buffer.data(), buffer.size(), address); } - instructions_it disassemble(LIEF::span buffer, uint64_t address = 0) const { + instructions_it disassemble(LIEF::span buffer, + uint64_t address = 0) const { return disassemble(buffer.data(), buffer.size(), address); } diff --git a/deps/LIEF/include/LIEF/COFF/Header.hpp b/deps/LIEF/include/LIEF/COFF/Header.hpp index 5239b73faa49..a2b3038c53c7 100644 --- a/deps/LIEF/include/LIEF/COFF/Header.hpp +++ b/deps/LIEF/include/LIEF/COFF/Header.hpp @@ -1,5 +1,5 @@ -/* Copyright 2017 - 2025 R. Thomas - * Copyright 2017 - 2025 Quarkslab +/* Copyright 2017 - 2026 R. Thomas + * Copyright 2017 - 2026 Quarkslab * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -32,11 +32,10 @@ namespace COFF { /// `/bigobj` files class LIEF_API Header { public: - enum class KIND { UNKNOWN = 0, REGULAR, - BIGOBJ + BIGOBJ, }; /// The different architectures (mirrored from PE) @@ -48,8 +47,7 @@ class LIEF_API Header { Header() = default; Header(KIND kind) : - kind_(kind) - {} + kind_(kind) {} Header& operator=(const Header&) = default; Header(const Header&) = default; @@ -119,8 +117,7 @@ class LIEF_API Header { template const T* as() const { - static_assert(std::is_base_of::value, - "Require Header inheritance"); + static_assert(std::is_base_of::value, "Require Header inheritance"); if (T::classof(this)) { return static_cast(this); } diff --git a/deps/LIEF/include/LIEF/COFF/Parser.hpp b/deps/LIEF/include/LIEF/COFF/Parser.hpp index fa1a5ff79d7d..206cfa7325c2 100644 --- a/deps/LIEF/include/LIEF/COFF/Parser.hpp +++ b/deps/LIEF/include/LIEF/COFF/Parser.hpp @@ -1,5 +1,5 @@ -/* Copyright 2017 - 2025 R. Thomas - * Copyright 2017 - 2025 Quarkslab +/* Copyright 2017 - 2026 R. Thomas + * Copyright 2017 - 2026 Quarkslab * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,10 +16,10 @@ #ifndef LIEF_COFF_PARSER_H #define LIEF_COFF_PARSER_H #include +#include "LIEF/compiler_attributes.hpp" +#include "LIEF/BinaryStream/BinaryStream.hpp" #include "LIEF/visibility.h" - -#include "LIEF/BinaryStream/VectorStream.hpp" -#include "LIEF/BinaryStream/SpanStream.hpp" +#include "LIEF/errors.hpp" #include "LIEF/COFF/ParserConfig.hpp" #include "LIEF/COFF/Header.hpp" @@ -33,23 +33,20 @@ class Symbol; class Parser { public: + static constexpr size_t MAX_NB_SECTIONS = 1 << 20; + /// Parse the COFF binary referenced by the `stream` argument with the /// given config - static LIEF_API - std::unique_ptr parse(std::unique_ptr stream, - const ParserConfig& config = ParserConfig::default_conf()); + static LIEF_API std::unique_ptr + parse(std::unique_ptr stream, + const ParserConfig& config = ParserConfig::default_conf()); /// Parse the COFF binary pointed by the `file` argument with the given config - static std::unique_ptr parse(const std::string& file, - const ParserConfig& config = ParserConfig::default_conf()) - { - if (auto strm = VectorStream::from_file(file)) { - return parse(std::unique_ptr(new VectorStream(std::move(*strm))), config); - } - return nullptr; - } + static LIEF_API std::unique_ptr + parse(const std::string& file, + const ParserConfig& config = ParserConfig::default_conf()); - /// \private + /// @private struct SymSec { size_t sec_idx = 0; Symbol* symbol = nullptr; @@ -70,21 +67,17 @@ class Parser { /// <=> std::unordered_multimap
using SymSecMap = std::vector; - /// \private + /// @private LIEF_LOCAL void memoize(String str); - /// \private + /// @private LIEF_LOCAL String* find_coff_string(uint32_t offset) const; ~Parser(); private: Parser(std::unique_ptr stream, const ParserConfig& config, - Header::KIND kind) : - stream_(std::move(stream)), - kind_(kind), - config_(config) - {} + Header::KIND kind); ok_error_t process(); ok_error_t parse_header(); @@ -102,7 +95,7 @@ class Parser { std::map symbol_idx_; SymSecMap symsec_; - ParserConfig config_; + LIEF_MAYBE_UNUSED ParserConfig config_; }; } } diff --git a/deps/LIEF/include/LIEF/COFF/ParserConfig.hpp b/deps/LIEF/include/LIEF/COFF/ParserConfig.hpp index 3d0a09636b52..10de521a5d64 100644 --- a/deps/LIEF/include/LIEF/COFF/ParserConfig.hpp +++ b/deps/LIEF/include/LIEF/COFF/ParserConfig.hpp @@ -1,5 +1,5 @@ -/* Copyright 2017 - 2025 R. Thomas - * Copyright 2017 - 2025 Quarkslab +/* Copyright 2017 - 2026 R. Thomas + * Copyright 2017 - 2026 Quarkslab * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,7 +29,7 @@ class LIEF_API ParserConfig { } static const ParserConfig& all() { - // To be updated when there is options that are off by default + // To be updated when there are options that are off by default return default_conf(); } }; diff --git a/deps/LIEF/include/LIEF/COFF/RegularHeader.hpp b/deps/LIEF/include/LIEF/COFF/RegularHeader.hpp index 1aab5525400d..6f6cfa128057 100644 --- a/deps/LIEF/include/LIEF/COFF/RegularHeader.hpp +++ b/deps/LIEF/include/LIEF/COFF/RegularHeader.hpp @@ -1,5 +1,5 @@ -/* Copyright 2017 - 2025 R. Thomas - * Copyright 2017 - 2025 Quarkslab +/* Copyright 2017 - 2026 R. Thomas + * Copyright 2017 - 2026 Quarkslab * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,8 +26,7 @@ namespace COFF { class LIEF_API RegularHeader : public Header { public: RegularHeader() : - Header(KIND::REGULAR) - {} + Header(KIND::REGULAR) {} /// Create a RegularHeader from the given stream static std::unique_ptr create(BinaryStream& stream); @@ -42,7 +41,7 @@ class LIEF_API RegularHeader : public Header { return std::unique_ptr
(new RegularHeader(*this)); } - /// The size of the optional header that follows this header (should be 0) + /// The size of the optional header which follows this header (should be 0) uint16_t sizeof_optionalheader() const { return sizeof_optionalheader_; } diff --git a/deps/LIEF/include/LIEF/COFF/Relocation.hpp b/deps/LIEF/include/LIEF/COFF/Relocation.hpp index 960caf0ad8b3..78e5d2f81cbd 100644 --- a/deps/LIEF/include/LIEF/COFF/Relocation.hpp +++ b/deps/LIEF/include/LIEF/COFF/Relocation.hpp @@ -1,5 +1,5 @@ -/* Copyright 2017 - 2025 R. Thomas - * Copyright 2017 - 2025 Quarkslab +/* Copyright 2017 - 2026 R. Thomas + * Copyright 2017 - 2026 Quarkslab * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -35,11 +35,11 @@ class LIEF_API Relocation : public LIEF::Relocation { public: friend class Parser; - static constexpr uint32_t I386 = 1 << 17; - static constexpr uint32_t X64 = 1 << 18; - static constexpr uint32_t ARM = 1 << 19; + static constexpr uint32_t I386 = 1 << 17; + static constexpr uint32_t X64 = 1 << 18; + static constexpr uint32_t ARM = 1 << 19; static constexpr uint32_t ARM64 = 1 << 20; - static constexpr uint32_t MIPS = 1 << 21; + static constexpr uint32_t MIPS = 1 << 21; /// The different relocation types. /// @@ -48,87 +48,87 @@ class LIEF_API Relocation : public LIEF::Relocation { enum class TYPE : uint32_t { UNKNOWN = uint32_t(-1), I386_ABSOLUTE = I386 + 0x0000, - I386_DIR16 = I386 + 0x0001, - I386_REL16 = I386 + 0x0002, - I386_DIR32 = I386 + 0x0006, - I386_DIR32NB = I386 + 0x0007, - I386_SEG12 = I386 + 0x0009, - I386_SECTION = I386 + 0x000A, - I386_SECREL = I386 + 0x000B, - I386_TOKEN = I386 + 0x000C, - I386_SECREL7 = I386 + 0x000D, - I386_REL32 = I386 + 0x0014, + I386_DIR16 = I386 + 0x0001, + I386_REL16 = I386 + 0x0002, + I386_DIR32 = I386 + 0x0006, + I386_DIR32NB = I386 + 0x0007, + I386_SEG12 = I386 + 0x0009, + I386_SECTION = I386 + 0x000A, + I386_SECREL = I386 + 0x000B, + I386_TOKEN = I386 + 0x000C, + I386_SECREL7 = I386 + 0x000D, + I386_REL32 = I386 + 0x0014, AMD64_ABSOLUTE = X64 + 0x0000, - AMD64_ADDR64 = X64 + 0x0001, - AMD64_ADDR32 = X64 + 0x0002, + AMD64_ADDR64 = X64 + 0x0001, + AMD64_ADDR32 = X64 + 0x0002, AMD64_ADDR32NB = X64 + 0x0003, - AMD64_REL32 = X64 + 0x0004, - AMD64_REL32_1 = X64 + 0x0005, - AMD64_REL32_2 = X64 + 0x0006, - AMD64_REL32_3 = X64 + 0x0007, - AMD64_REL32_4 = X64 + 0x0008, - AMD64_REL32_5 = X64 + 0x0009, - AMD64_SECTION = X64 + 0x000A, - AMD64_SECREL = X64 + 0x000B, - AMD64_SECREL7 = X64 + 0x000C, - AMD64_TOKEN = X64 + 0x000D, - AMD64_SREL32 = X64 + 0x000E, - AMD64_PAIR = X64 + 0x000F, - AMD64_SSPAN32 = X64 + 0x0010, - - ARM_ABSOLUTE = ARM + 0x0000, - ARM_ADDR32 = ARM + 0x0001, - ARM_ADDR32NB = ARM + 0x0002, - ARM_BRANCH24 = ARM + 0x0003, - ARM_BRANCH11 = ARM + 0x0004, - ARM_TOKEN = ARM + 0x0005, - ARM_BLX24 = ARM + 0x0008, - ARM_BLX11 = ARM + 0x0009, - ARM_REL32 = ARM + 0x000A, - ARM_SECTION = ARM + 0x000E, - ARM_SECREL = ARM + 0x000F, - ARM_MOV32A = ARM + 0x0010, - ARM_MOV32T = ARM + 0x0011, + AMD64_REL32 = X64 + 0x0004, + AMD64_REL32_1 = X64 + 0x0005, + AMD64_REL32_2 = X64 + 0x0006, + AMD64_REL32_3 = X64 + 0x0007, + AMD64_REL32_4 = X64 + 0x0008, + AMD64_REL32_5 = X64 + 0x0009, + AMD64_SECTION = X64 + 0x000A, + AMD64_SECREL = X64 + 0x000B, + AMD64_SECREL7 = X64 + 0x000C, + AMD64_TOKEN = X64 + 0x000D, + AMD64_SREL32 = X64 + 0x000E, + AMD64_PAIR = X64 + 0x000F, + AMD64_SSPAN32 = X64 + 0x0010, + + ARM_ABSOLUTE = ARM + 0x0000, + ARM_ADDR32 = ARM + 0x0001, + ARM_ADDR32NB = ARM + 0x0002, + ARM_BRANCH24 = ARM + 0x0003, + ARM_BRANCH11 = ARM + 0x0004, + ARM_TOKEN = ARM + 0x0005, + ARM_BLX24 = ARM + 0x0008, + ARM_BLX11 = ARM + 0x0009, + ARM_REL32 = ARM + 0x000A, + ARM_SECTION = ARM + 0x000E, + ARM_SECREL = ARM + 0x000F, + ARM_MOV32A = ARM + 0x0010, + ARM_MOV32T = ARM + 0x0011, ARM_BRANCH20T = ARM + 0x0012, ARM_BRANCH24T = ARM + 0x0014, - ARM_BLX23T = ARM + 0x0015, - ARM_PAIR = ARM + 0x0016, + ARM_BLX23T = ARM + 0x0015, + ARM_PAIR = ARM + 0x0016, - ARM64_ABSOLUTE = ARM64 + 0x0000, - ARM64_ADDR32 = ARM64 + 0x0001, - ARM64_ADDR32NB = ARM64 + 0x0002, - ARM64_BRANCH26 = ARM64 + 0x0003, + ARM64_ABSOLUTE = ARM64 + 0x0000, + ARM64_ADDR32 = ARM64 + 0x0001, + ARM64_ADDR32NB = ARM64 + 0x0002, + ARM64_BRANCH26 = ARM64 + 0x0003, ARM64_PAGEBASE_REL21 = ARM64 + 0x0004, - ARM64_REL21 = ARM64 + 0x0005, + ARM64_REL21 = ARM64 + 0x0005, ARM64_PAGEOFFSET_12A = ARM64 + 0x0006, ARM64_PAGEOFFSET_12L = ARM64 + 0x0007, - ARM64_SECREL = ARM64 + 0x0008, - ARM64_SECREL_LOW12A = ARM64 + 0x0009, + ARM64_SECREL = ARM64 + 0x0008, + ARM64_SECREL_LOW12A = ARM64 + 0x0009, ARM64_SECREL_HIGH12A = ARM64 + 0x000A, - ARM64_SECREL_LOW12L = ARM64 + 0x000B, - ARM64_TOKEN = ARM64 + 0x000C, - ARM64_SECTION = ARM64 + 0x000D, - ARM64_ADDR64 = ARM64 + 0x000E, - ARM64_BRANCH19 = ARM64 + 0x000F, - ARM64_BRANCH14 = ARM64 + 0x0010, - ARM64_REL32 = ARM64 + 0x0011, - - MIPS_ABSOLUTE = MIPS + 0x0000, - MIPS_REFHALF = MIPS + 0x0001, - MIPS_REFWORD = MIPS + 0x0002, - MIPS_JMPADDR = MIPS + 0x0003, - MIPS_REFHI = MIPS + 0x0004, - MIPS_REFLO = MIPS + 0x0005, - MIPS_GPREL = MIPS + 0x0006, - MIPS_LITERAL = MIPS + 0x0007, - MIPS_SECTION = MIPS + 0x000A, - MIPS_SECREL = MIPS + 0x000B, - MIPS_SECRELLO = MIPS + 0x000C, - MIPS_SECRELHI = MIPS + 0x000D, + ARM64_SECREL_LOW12L = ARM64 + 0x000B, + ARM64_TOKEN = ARM64 + 0x000C, + ARM64_SECTION = ARM64 + 0x000D, + ARM64_ADDR64 = ARM64 + 0x000E, + ARM64_BRANCH19 = ARM64 + 0x000F, + ARM64_BRANCH14 = ARM64 + 0x0010, + ARM64_REL32 = ARM64 + 0x0011, + + MIPS_ABSOLUTE = MIPS + 0x0000, + MIPS_REFHALF = MIPS + 0x0001, + MIPS_REFWORD = MIPS + 0x0002, + MIPS_JMPADDR = MIPS + 0x0003, + MIPS_REFHI = MIPS + 0x0004, + MIPS_REFLO = MIPS + 0x0005, + MIPS_GPREL = MIPS + 0x0006, + MIPS_LITERAL = MIPS + 0x0007, + MIPS_SECTION = MIPS + 0x000A, + MIPS_SECREL = MIPS + 0x000B, + MIPS_SECRELLO = MIPS + 0x000C, + MIPS_SECRELHI = MIPS + 0x000D, MIPS_JMPADDR16 = MIPS + 0x0010, MIPS_REFWORDNB = MIPS + 0x0022, - MIPS_PAIR = MIPS + 0x0025, + MIPS_PAIR = MIPS + 0x0025, }; /// Convert a relocation enum type into a 16-bits value. @@ -139,32 +139,26 @@ class LIEF_API Relocation : public LIEF::Relocation { /// Create a relocation type from its raw value and the architecture static TYPE from_value(uint16_t value, Header::MACHINE_TYPES arch) { switch (arch) { - case Header::MACHINE_TYPES::ARM64: - return TYPE(value + ARM64); + case Header::MACHINE_TYPES::ARM64: return TYPE(value + ARM64); - case Header::MACHINE_TYPES::AMD64: - return TYPE(value + X64); + case Header::MACHINE_TYPES::AMD64: return TYPE(value + X64); - case Header::MACHINE_TYPES::I386: - return TYPE(value + I386); + case Header::MACHINE_TYPES::I386: return TYPE(value + I386); case Header::MACHINE_TYPES::ARM: case Header::MACHINE_TYPES::ARMNT: - case Header::MACHINE_TYPES::THUMB: - return TYPE(value + ARM); + case Header::MACHINE_TYPES::THUMB: return TYPE(value + ARM); - case Header::MACHINE_TYPES::R4000: - return TYPE(value + MIPS); + case Header::MACHINE_TYPES::R4000: return TYPE(value + MIPS); - default: - return TYPE::UNKNOWN; + default: return TYPE::UNKNOWN; } return TYPE::UNKNOWN; } /// Create a relocation from the given stream - static std::unique_ptr parse( - BinaryStream& stream, Header::MACHINE_TYPES arch); + static std::unique_ptr parse(BinaryStream& stream, + Header::MACHINE_TYPES arch); /// Symbol index associated with this relocation uint32_t symbol_idx() const { diff --git a/deps/LIEF/include/LIEF/COFF/Section.hpp b/deps/LIEF/include/LIEF/COFF/Section.hpp index d70a3117adf5..f3ca20eeea7e 100644 --- a/deps/LIEF/include/LIEF/COFF/Section.hpp +++ b/deps/LIEF/include/LIEF/COFF/Section.hpp @@ -1,5 +1,5 @@ -/* Copyright 2017 - 2025 R. Thomas - * Copyright 2017 - 2025 Quarkslab +/* Copyright 2017 - 2026 R. Thomas + * Copyright 2017 - 2026 Quarkslab * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,6 +19,7 @@ #include #include +#include "LIEF/compiler_attributes.hpp" #include "LIEF/visibility.h" #include "LIEF/Abstract/Section.hpp" #include "LIEF/PE/Section.hpp" @@ -60,9 +61,11 @@ class LIEF_API Section : public LIEF::Section { using it_relocations = ref_iterator; /// Iterator that outputs const Relocation& - using it_const_relocations = const_ref_iterator; + using it_const_relocations = + const_ref_iterator; - /// Container for the symbols associated with this section (owned by the Binary object) + /// Container for the symbols associated with this section (owned by the Binary + /// object) using symbols_t = std::vector; /// Iterator that outputs Symbol& @@ -85,7 +88,7 @@ class LIEF_API Section : public LIEF::Section { } /// Content wrapped by this section - span content() const override { + span content() const LIEF_LIFETIMEBOUND override { return content_; } @@ -110,7 +113,7 @@ class LIEF_API Section : public LIEF::Section { /// Number of relocations. /// - /// \warning If the number of relocations is greater than 0xFFFF (maximum + /// @warning If the number of relocations is greater than 0xFFFF (maximum /// value for 16-bits integer), then the number of relocations is /// stored in the virtual address of the **first** relocation. uint16_t numberof_relocations() const { @@ -151,32 +154,33 @@ class LIEF_API Section : public LIEF::Section { } /// Iterator over the relocations associated with this section - it_relocations relocations() { + it_relocations relocations() LIEF_LIFETIMEBOUND { return relocations_; } - it_const_relocations relocations() const { + it_const_relocations relocations() const LIEF_LIFETIMEBOUND { return relocations_; } /// Iterator over the symbols associated with this section - it_symbols symbols() { + it_symbols symbols() LIEF_LIFETIMEBOUND { return symbols_; } - it_const_symbols symbols() const { + it_const_symbols symbols() const LIEF_LIFETIMEBOUND { return symbols_; } - /// Return comdat infomration (only if the section has the + /// Return comdat information (only if the section has the /// CHARACTERISTICS::LNK_COMDAT characteristic) optional comdat_info() const; /// Whether there is a large number of relocations whose number need /// to be stored in the virtual address attribute bool has_extended_relocations() const { + static constexpr auto MAX_RELOC = /*uint16_t::max*/ 65535; return has_characteristic(CHARACTERISTICS::LNK_NRELOC_OVFL) && - numberof_relocations() == std::numeric_limits::max(); + numberof_relocations() == MAX_RELOC; } void content(const std::vector& data) override { @@ -217,6 +221,18 @@ class LIEF_API Section : public LIEF::Section { characteristics_ = characteristics; } + /// Return the COFF string associated with the section's name (or a nullptr) + /// + /// This coff string is usually present for long section names whose length + /// does not fit in the 8 bytes allocated by the COFF format. + String* coff_string() { + return coff_string_; + } + + const String* coff_string() const { + return coff_string_; + } + std::string to_string() const; LIEF_API friend std::ostream& operator<<(std::ostream& os, const Section& sec) { @@ -230,15 +246,17 @@ class LIEF_API Section : public LIEF::Section { Section() = default; std::vector content_; - uint32_t virtual_size_ = 0; + uint32_t virtual_size_ = 0; uint32_t pointer_to_relocations_ = 0; uint32_t pointer_to_linenumbers_ = 0; - uint16_t number_of_relocations_ = 0; - uint16_t number_of_linenumbers_ = 0; - uint32_t characteristics_ = 0; + uint16_t number_of_relocations_ = 0; + uint16_t number_of_linenumbers_ = 0; + uint32_t characteristics_ = 0; relocations_t relocations_; symbols_t symbols_; + + String* coff_string_ = nullptr; }; inline const char* to_string(Section::CHARACTERISTICS e) { diff --git a/deps/LIEF/include/LIEF/COFF/String.hpp b/deps/LIEF/include/LIEF/COFF/String.hpp index 8e678762642d..c2ffa3925aa7 100644 --- a/deps/LIEF/include/LIEF/COFF/String.hpp +++ b/deps/LIEF/include/LIEF/COFF/String.hpp @@ -1,5 +1,5 @@ -/* Copyright 2017 - 2025 R. Thomas - * Copyright 2017 - 2025 Quarkslab +/* Copyright 2017 - 2026 R. Thomas + * Copyright 2017 - 2026 Quarkslab * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,14 +29,14 @@ namespace COFF { /// Some of these strings can be used for section names that are greater than 8 /// bytes. See: LIEF::PE::Section::coff_string() /// -/// Reference: https://learn.microsoft.com/en-us/windows/win32/debug/pe-format#coff-string-table +/// Reference: +/// https://learn.microsoft.com/en-us/windows/win32/debug/pe-format#coff-string-table class LIEF_API String { public: String() = default; String(uint32_t offset, std::string str) : str_(std::move(str)), - offset_(offset) - {} + offset_(offset) {} String(const String&) = default; String& operator=(const String&) = default; @@ -47,7 +47,7 @@ class LIEF_API String { ~String() = default; /// The actual string - const std::string& str() const { + const std::string& str() const LIEF_LIFETIMEBOUND { return str_; } @@ -57,19 +57,17 @@ class LIEF_API String { return offset_; } - String& str(std::string str) { + String& str(std::string str) LIEF_LIFETIMEBOUND { str_ = std::move(str); return *this; } - String& offset(uint32_t value) { + String& offset(uint32_t value) LIEF_LIFETIMEBOUND { offset_ = value; return *this; } - friend LIEF_API - std::ostream& operator<<(std::ostream& os, const String& str) - { + friend LIEF_API std::ostream& operator<<(std::ostream& os, const String& str) { os << str.str(); return os; } diff --git a/deps/LIEF/include/LIEF/COFF/Symbol.hpp b/deps/LIEF/include/LIEF/COFF/Symbol.hpp index 3a9d8a97fcb4..d6b4f4f41ed6 100644 --- a/deps/LIEF/include/LIEF/COFF/Symbol.hpp +++ b/deps/LIEF/include/LIEF/COFF/Symbol.hpp @@ -1,5 +1,5 @@ -/* Copyright 2017 - 2025 R. Thomas - * Copyright 2017 - 2025 Quarkslab +/* Copyright 2017 - 2026 R. Thomas + * Copyright 2017 - 2026 Quarkslab * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -37,15 +37,17 @@ class LIEF_API Symbol : public LIEF::Symbol { friend class Parser; using auxiliary_symbols_t = std::vector>; - using it_auxiliary_symbols_t = ref_iterator; - using it_const_auxiliary_symbols_t = const_ref_iterator; + using it_auxiliary_symbols_t = + ref_iterator; + using it_const_auxiliary_symbols_t = + const_ref_iterator; struct parsing_context_t { std::function find_string; bool is_bigobj; }; - static std::unique_ptr parse( - parsing_context_t& ctx, BinaryStream& stream, size_t* idx); + static std::unique_ptr parse(parsing_context_t& ctx, + BinaryStream& stream, size_t* idx); Symbol(); Symbol(const Symbol&); @@ -58,8 +60,10 @@ class LIEF_API Symbol : public LIEF::Symbol { /// correspond to a section. Microsoft tools use this setting along with /// `.file` records. static constexpr auto SYM_SEC_IDX_DEBUG = -2; + /// The symbol has an absolute (non-relocatable) value and is not an address. static constexpr auto SYM_SEC_IDX_ABS = -1; + /// The symbol record is not yet assigned a section. A value of zero indicates /// that a reference to an external symbol is defined elsewhere. A value of /// non-zero is a common symbol with a size that is specified by the value. @@ -67,37 +71,38 @@ class LIEF_API Symbol : public LIEF::Symbol { static constexpr auto SYM_COMPLEX_TYPE_SHIFT = 4; - /// Reference: https://learn.microsoft.com/en-us/windows/win32/debug/pe-format#storage-class + /// Reference: + /// https://learn.microsoft.com/en-us/windows/win32/debug/pe-format#storage-class enum class STORAGE_CLASS : int32_t { INVALID = 0xFF, - END_OF_FUNCTION = -1, ///< Physical end of function - NONE = 0, ///< No symbol - AUTOMATIC = 1, ///< Stack variable - EXTERNAL = 2, ///< External symbol - STATIC = 3, ///< Static - REGISTER = 4, ///< Register variable - EXTERNAL_DEF = 5, ///< External definition - LABEL = 6, ///< Label - UNDEFINED_LABEL = 7, ///< Undefined label - MEMBER_OF_STRUCT = 8, ///< Member of structure - ARGUMENT = 9, ///< Function argument - STRUCT_TAG = 10, ///< Structure tag - MEMBER_OF_UNION = 11, ///< Member of union - UNION_TAG = 12, ///< Union tag - TYPE_DEFINITION = 13, ///< Type definition - UNDEFINED_STATIC = 14, ///< Undefined static - ENUM_TAG = 15, ///< Enumeration tag - MEMBER_OF_ENUM = 16, ///< Member of enumeration - REGISTER_PARAM = 17, ///< Register parameter - BIT_FIELD = 18, ///< Bit field - BLOCK = 100, - FUNCTION = 101, - END_OF_STRUCT = 102, ///< End of structure - FILE = 103, ///< File name - SECTION = 104, - WEAK_EXTERNAL = 105, ///< Duplicate tag - CLR_TOKEN = 107 + END_OF_FUNCTION = -1, ///< Physical end of function + NONE = 0, ///< No symbol + AUTOMATIC = 1, ///< Stack variable + EXTERNAL = 2, ///< External symbol + STATIC = 3, ///< Static + REGISTER = 4, ///< Register variable + EXTERNAL_DEF = 5, ///< External definition + LABEL = 6, ///< Label + UNDEFINED_LABEL = 7, ///< Undefined label + MEMBER_OF_STRUCT = 8, ///< Member of structure + ARGUMENT = 9, ///< Function argument + STRUCT_TAG = 10, ///< Structure tag + MEMBER_OF_UNION = 11, ///< Member of union + UNION_TAG = 12, ///< Union tag + TYPE_DEFINITION = 13, ///< Type definition + UNDEFINED_STATIC = 14, ///< Undefined static + ENUM_TAG = 15, ///< Enumeration tag + MEMBER_OF_ENUM = 16, ///< Member of enumeration + REGISTER_PARAM = 17, ///< Register parameter + BIT_FIELD = 18, ///< Bit field + BLOCK = 100, + FUNCTION = 101, + END_OF_STRUCT = 102, ///< End of structure + FILE = 103, ///< File name + SECTION = 104, + WEAK_EXTERNAL = 105, ///< Duplicate tag + CLR_TOKEN = 107, }; enum class BASE_TYPE : uint32_t { @@ -116,7 +121,7 @@ class LIEF_API Symbol : public LIEF::Symbol { TY_BYTE = 12, ///< A byte; unsigned 1-byte integer. TY_WORD = 13, ///< A word; unsigned 2-byte integer. TY_UINT = 14, ///< An unsigned integer of natural size. - TY_DWORD = 15 ///< An unsigned 4-byte integer. + TY_DWORD = 15, ///< An unsigned 4-byte integer. }; enum class COMPLEX_TYPE : uint32_t { @@ -192,8 +197,7 @@ class LIEF_API Symbol : public LIEF::Symbol { } bool is_undefined() const { - return is_external() && section_idx() == SYM_SEC_IDX_UNDEF && - value() == 0; + return is_external() && section_idx() == SYM_SEC_IDX_UNDEF && value() == 0; } bool is_function_line_info() const { @@ -223,7 +227,7 @@ class LIEF_API Symbol : public LIEF::Symbol { std::string& name() override; - /// COFF string used to represents the (long) symbol name + /// COFF string used to represent the (long) symbol name const String* coff_name() const { return coff_name_; } @@ -256,9 +260,7 @@ class LIEF_API Symbol : public LIEF::Symbol { std::string to_string() const; - LIEF_API friend - std::ostream& operator<<(std::ostream& os, const Symbol& entry) - { + LIEF_API friend std::ostream& operator<<(std::ostream& os, const Symbol& entry) { os << entry.to_string(); return os; } @@ -267,8 +269,8 @@ class LIEF_API Symbol : public LIEF::Symbol { private: template - static std::unique_ptr parse_impl( - parsing_context_t& ctx, BinaryStream& stream, size_t* idx); + static std::unique_ptr parse_impl(parsing_context_t& ctx, + BinaryStream& stream, size_t* idx); String* coff_name_ = nullptr; uint16_t type_ = 0; uint8_t storage_class_ = 0; diff --git a/deps/LIEF/include/LIEF/COFF/utils.hpp b/deps/LIEF/include/LIEF/COFF/utils.hpp index 73cb9fbf34ad..ead86f87efc2 100644 --- a/deps/LIEF/include/LIEF/COFF/utils.hpp +++ b/deps/LIEF/include/LIEF/COFF/utils.hpp @@ -1,5 +1,5 @@ -/* Copyright 2017 - 2025 R. Thomas - * Copyright 2017 - 2025 Quarkslab +/* Copyright 2017 - 2026 R. Thomas + * Copyright 2017 - 2026 Quarkslab * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,7 +17,6 @@ #define LIEF_COFF_UTILS_H #include "LIEF/visibility.h" #include "LIEF/COFF/Header.hpp" -#include "LIEF/BinaryStream/FileStream.hpp" #include "LIEF/BinaryStream/SpanStream.hpp" #include diff --git a/deps/LIEF/include/LIEF/DEX.hpp b/deps/LIEF/include/LIEF/DEX.hpp index f976b08117d5..28324a1fb04f 100644 --- a/deps/LIEF/include/LIEF/DEX.hpp +++ b/deps/LIEF/include/LIEF/DEX.hpp @@ -1,5 +1,5 @@ -/* Copyright 2017 - 2025 R. Thomas - * Copyright 2017 - 2025 Quarkslab +/* Copyright 2017 - 2026 R. Thomas + * Copyright 2017 - 2026 Quarkslab * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,15 +18,15 @@ #include "LIEF/config.h" #if defined(LIEF_DEX_SUPPORT) -#include "LIEF/DEX/Parser.hpp" -#include "LIEF/DEX/utils.hpp" -#include "LIEF/DEX/File.hpp" -#include "LIEF/DEX/Class.hpp" -#include "LIEF/DEX/Prototype.hpp" -#include "LIEF/DEX/Header.hpp" -#include "LIEF/DEX/Method.hpp" -#include "LIEF/DEX/Field.hpp" -#include "LIEF/DEX/EnumToString.hpp" + #include "LIEF/DEX/Parser.hpp" + #include "LIEF/DEX/utils.hpp" + #include "LIEF/DEX/File.hpp" + #include "LIEF/DEX/Class.hpp" + #include "LIEF/DEX/Prototype.hpp" + #include "LIEF/DEX/Header.hpp" + #include "LIEF/DEX/Method.hpp" + #include "LIEF/DEX/Field.hpp" + #include "LIEF/DEX/EnumToString.hpp" #endif #endif diff --git a/deps/LIEF/include/LIEF/DEX/Class.hpp b/deps/LIEF/include/LIEF/DEX/Class.hpp index 0b1baff36ad5..0a05a20d90a9 100644 --- a/deps/LIEF/include/LIEF/DEX/Class.hpp +++ b/deps/LIEF/include/LIEF/DEX/Class.hpp @@ -1,5 +1,5 @@ -/* Copyright 2017 - 2025 R. Thomas - * Copyright 2017 - 2025 Quarkslab +/* Copyright 2017 - 2026 R. Thomas + * Copyright 2017 - 2026 Quarkslab * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -56,7 +56,8 @@ class LIEF_API Class : public Object { public: static std::string package_normalized(const std::string& pkg_name); static std::string fullname_normalized(const std::string& pkg_cls); - static std::string fullname_normalized(const std::string& pkg, const std::string& cls_name); + static std::string fullname_normalized(const std::string& pkg, + const std::string& cls_name); Class(); Class(const Class&) = delete; @@ -124,10 +125,10 @@ class LIEF_API Class : public Object { private: std::string fullname_; - uint32_t access_flags_ = ACCESS_FLAGS::ACC_UNKNOWN; - Class* parent_ = nullptr; - methods_t methods_; - fields_t fields_; + uint32_t access_flags_ = ACCESS_FLAGS::ACC_UNKNOWN; + Class* parent_ = nullptr; + methods_t methods_; + fields_t fields_; std::string source_filename_; uint32_t original_index_ = UINT_MAX; diff --git a/deps/LIEF/include/LIEF/DEX/CodeInfo.hpp b/deps/LIEF/include/LIEF/DEX/CodeInfo.hpp index 85410e665b17..34c21b870b3f 100644 --- a/deps/LIEF/include/LIEF/DEX/CodeInfo.hpp +++ b/deps/LIEF/include/LIEF/DEX/CodeInfo.hpp @@ -1,5 +1,5 @@ -/* Copyright 2017 - 2025 R. Thomas - * Copyright 2017 - 2025 Quarkslab +/* Copyright 2017 - 2026 R. Thomas + * Copyright 2017 - 2026 Quarkslab * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -46,13 +46,13 @@ class LIEF_API CodeInfo : public Object { ~CodeInfo() override; - LIEF_API friend std::ostream& operator<<(std::ostream& os, const CodeInfo& cinfo); + LIEF_API friend std::ostream& operator<<(std::ostream& os, + const CodeInfo& cinfo); private: uint16_t nb_registers_ = 0; uint16_t args_input_sizes_ = 0; uint16_t output_sizes_ = 0; - }; } // Namespace DEX diff --git a/deps/LIEF/include/LIEF/DEX/EnumToString.hpp b/deps/LIEF/include/LIEF/DEX/EnumToString.hpp index 18336a7028b9..e155236f613c 100644 --- a/deps/LIEF/include/LIEF/DEX/EnumToString.hpp +++ b/deps/LIEF/include/LIEF/DEX/EnumToString.hpp @@ -1,5 +1,5 @@ -/* Copyright 2017 - 2025 R. Thomas - * Copyright 2017 - 2025 Quarkslab +/* Copyright 2017 - 2026 R. Thomas + * Copyright 2017 - 2026 Quarkslab * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -32,4 +32,3 @@ LIEF_API const char* to_string(Type::PRIMITIVES e); } // namespace LIEF #endif - diff --git a/deps/LIEF/include/LIEF/DEX/Field.hpp b/deps/LIEF/include/LIEF/DEX/Field.hpp index 25283a81e007..3eff71324bce 100644 --- a/deps/LIEF/include/LIEF/DEX/Field.hpp +++ b/deps/LIEF/include/LIEF/DEX/Field.hpp @@ -1,4 +1,4 @@ -/* Copyright 2021 - 2025 R. Thomas +/* Copyright 2021 - 2026 R. Thomas * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -30,9 +30,10 @@ namespace DEX { class Parser; class Class; -/// Class which represent a DEX Field +/// Class which represents a DEX Field class LIEF_API Field : public Object { friend class Parser; + public: using access_flags_list_t = std::vector; @@ -51,8 +52,8 @@ class LIEF_API Field : public Object { bool has_class() const; /// Class associated with this Field - const Class* cls() const; - Class* cls(); + const Class* cls() const LIEF_LIFETIMEBOUND; + Class* cls() LIEF_LIFETIMEBOUND; /// Index in the DEX Fields pool size_t index() const; @@ -61,8 +62,8 @@ class LIEF_API Field : public Object { bool is_static() const; /// Field's prototype - const Type* type() const; - Type* type(); + const Type* type() const LIEF_LIFETIMEBOUND; + Type* type() LIEF_LIFETIMEBOUND; void accept(Visitor& visitor) const override; diff --git a/deps/LIEF/include/LIEF/DEX/File.hpp b/deps/LIEF/include/LIEF/DEX/File.hpp index 6cf6240d82c8..226ffee53aca 100644 --- a/deps/LIEF/include/LIEF/DEX/File.hpp +++ b/deps/LIEF/include/LIEF/DEX/File.hpp @@ -1,5 +1,5 @@ -/* Copyright 2017 - 2025 R. Thomas - * Copyright 2017 - 2025 Quarkslab +/* Copyright 2017 - 2026 R. Thomas + * Copyright 2017 - 2026 Quarkslab * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -49,25 +49,27 @@ class LIEF_API File : public Object { using it_methods = ref_iterator; using it_const_methods = const_ref_iterator; - using strings_t = std::vector>; - using it_strings = ref_iterator; - using it_const_strings = const_ref_iterator; + using strings_t = std::vector>; + using it_strings = ref_iterator; + using it_const_strings = + const_ref_iterator; - using types_t = std::vector>; - using it_types = ref_iterator; - using it_const_types = const_ref_iterator; + using types_t = std::vector>; + using it_types = ref_iterator; + using it_const_types = const_ref_iterator; - using prototypes_t = std::vector>; - using it_prototypes = ref_iterator; - using it_const_prototypes = const_ref_iterator; + using prototypes_t = std::vector>; + using it_prototypes = ref_iterator; + using it_const_prototypes = + const_ref_iterator; - using fields_t = std::vector>; - using it_fields = ref_iterator; - using it_const_fields = const_ref_iterator; + using fields_t = std::vector>; + using it_fields = ref_iterator; + using it_const_fields = const_ref_iterator; public: File& operator=(const File& copy) = delete; - File(const File& copy) = delete; + File(const File& copy) = delete; /// Version of the current DEX file dex_version_t version() const; @@ -82,25 +84,25 @@ class LIEF_API File : public Object { void location(const std::string& location); /// DEX header - const Header& header() const; - Header& header(); + const Header& header() const LIEF_LIFETIMEBOUND; + Header& header() LIEF_LIFETIMEBOUND; /// **All** classes used in the DEX file - it_const_classes classes() const; - it_classes classes(); + it_const_classes classes() const LIEF_LIFETIMEBOUND; + it_classes classes() LIEF_LIFETIMEBOUND; /// Check if the given class name exists bool has_class(const std::string& class_name) const; /// Return the DEX::Class object associated with the given name - const Class* get_class(const std::string& class_name) const; + const Class* get_class(const std::string& class_name) const LIEF_LIFETIMEBOUND; - Class* get_class(const std::string& class_name); + Class* get_class(const std::string& class_name) LIEF_LIFETIMEBOUND; /// Return the DEX::Class object associated with the given index - const Class* get_class(size_t index) const; + const Class* get_class(size_t index) const LIEF_LIFETIMEBOUND; - Class* get_class(size_t index); + Class* get_class(size_t index) LIEF_LIFETIMEBOUND; /// De-optimize information dex2dex_info_t dex2dex_info() const; @@ -109,24 +111,24 @@ class LIEF_API File : public Object { std::string dex2dex_json_info() const; /// Return an iterator over **all** the DEX::Method used in this DEX file - it_const_methods methods() const; - it_methods methods(); + it_const_methods methods() const LIEF_LIFETIMEBOUND; + it_methods methods() LIEF_LIFETIMEBOUND; /// Return an iterator over **all** the DEX::Field used in this DEX file - it_const_fields fields() const; - it_fields fields(); + it_const_fields fields() const LIEF_LIFETIMEBOUND; + it_fields fields() LIEF_LIFETIMEBOUND; /// String pool - it_const_strings strings() const; - it_strings strings(); + it_const_strings strings() const LIEF_LIFETIMEBOUND; + it_strings strings() LIEF_LIFETIMEBOUND; /// Type pool - it_const_types types() const; - it_types types(); + it_const_types types() const LIEF_LIFETIMEBOUND; + it_types types() LIEF_LIFETIMEBOUND; /// Prototype pool - it_prototypes prototypes(); - it_const_prototypes prototypes() const; + it_prototypes prototypes() LIEF_LIFETIMEBOUND; + it_const_prototypes prototypes() const LIEF_LIFETIMEBOUND; /// DEX Map const MapList& map() const; @@ -151,20 +153,22 @@ class LIEF_API File : public Object { static void deoptimize_nop(uint8_t* inst_ptr, uint32_t value); static void deoptimize_return(uint8_t* inst_ptr, uint32_t value); - static void deoptimize_invoke_virtual(uint8_t* inst_ptr, uint32_t value, OPCODES new_inst); - static void deoptimize_instance_field_access(uint8_t* inst_ptr, uint32_t value, OPCODES new_inst); + static void deoptimize_invoke_virtual(uint8_t* inst_ptr, uint32_t value, + OPCODES new_inst); + static void deoptimize_instance_field_access(uint8_t* inst_ptr, uint32_t value, + OPCODES new_inst); std::string name_; std::string location_; - Header header_; - classes_t classes_; - methods_t methods_; - fields_t fields_; - strings_t strings_; - types_t types_; + Header header_; + classes_t classes_; + methods_t methods_; + fields_t fields_; + strings_t strings_; + types_t types_; prototypes_t prototypes_; - MapList map_; + MapList map_; classes_list_t class_list_; std::vector original_data_; diff --git a/deps/LIEF/include/LIEF/DEX/Header.hpp b/deps/LIEF/include/LIEF/DEX/Header.hpp index b1d269f7a211..d2cab3731ab5 100644 --- a/deps/LIEF/include/LIEF/DEX/Header.hpp +++ b/deps/LIEF/include/LIEF/DEX/Header.hpp @@ -1,6 +1,6 @@ -/* Copyright 2017 - 2025 R. Thomas - * Copyright 2017 - 2025 Quarkslab +/* Copyright 2017 - 2026 R. Thomas + * Copyright 2017 - 2026 Quarkslab * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -42,7 +42,7 @@ class LIEF_API Header : public Object { public: using location_t = std::pair; - using magic_t = std::array; + using magic_t = std::array; using signature_t = std::array; Header(); @@ -67,7 +67,7 @@ class LIEF_API Header : public Object { /// Size of this header. It should be 0x70 uint32_t header_size() const; - /// File endianess of the file + /// File endianness of the file uint32_t endian_tag() const; /// Offset from the start of the file to the map list (see: DEX::MapList) @@ -95,39 +95,39 @@ class LIEF_API Header : public Object { ~Header() override; private: - magic_t magic_; - uint32_t checksum_; - signature_t signature_; - uint32_t file_size_; + magic_t magic_{}; + uint32_t checksum_ = 0; + signature_t signature_{}; + uint32_t file_size_ = 0; - uint32_t header_size_; - uint32_t endian_tag_; + uint32_t header_size_ = 0; + uint32_t endian_tag_ = 0; - uint32_t link_size_; - uint32_t link_off_; + uint32_t link_size_ = 0; + uint32_t link_off_ = 0; - uint32_t map_off_; + uint32_t map_off_ = 0; - uint32_t string_ids_size_; - uint32_t string_ids_off_; + uint32_t string_ids_size_ = 0; + uint32_t string_ids_off_ = 0; - uint32_t type_ids_size_; - uint32_t type_ids_off_; + uint32_t type_ids_size_ = 0; + uint32_t type_ids_off_ = 0; - uint32_t proto_ids_size_; - uint32_t proto_ids_off_; + uint32_t proto_ids_size_ = 0; + uint32_t proto_ids_off_ = 0; - uint32_t field_ids_size_; - uint32_t field_ids_off_; + uint32_t field_ids_size_ = 0; + uint32_t field_ids_off_ = 0; - uint32_t method_ids_size_; - uint32_t method_ids_off_; + uint32_t method_ids_size_ = 0; + uint32_t method_ids_off_ = 0; - uint32_t class_defs_size_; - uint32_t class_defs_off_; + uint32_t class_defs_size_ = 0; + uint32_t class_defs_off_ = 0; - uint32_t data_size_; - uint32_t data_off_; + uint32_t data_size_ = 0; + uint32_t data_off_ = 0; }; } // Namespace DEX diff --git a/deps/LIEF/include/LIEF/DEX/MapItem.hpp b/deps/LIEF/include/LIEF/DEX/MapItem.hpp index bb791c472e18..2206a8aeeb48 100644 --- a/deps/LIEF/include/LIEF/DEX/MapItem.hpp +++ b/deps/LIEF/include/LIEF/DEX/MapItem.hpp @@ -1,5 +1,5 @@ -/* Copyright 2017 - 2025 R. Thomas - * Copyright 2017 - 2025 Quarkslab +/* Copyright 2017 - 2026 R. Thomas + * Copyright 2017 - 2026 Quarkslab * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -33,26 +33,26 @@ class LIEF_API MapItem : public Object { public: enum class TYPES : uint16_t { - HEADER = 0x0000, - STRING_ID = 0x0001, - TYPE_ID = 0x0002, - PROTO_ID = 0x0003, - FIELD_ID = 0x0004, - METHOD_ID = 0x0005, - CLASS_DEF = 0x0006, - CALL_SITE_ID = 0x0007, - METHOD_HANDLE = 0x0008, - MAP_LIST = 0x1000, - TYPE_LIST = 0x1001, + HEADER = 0x0000, + STRING_ID = 0x0001, + TYPE_ID = 0x0002, + PROTO_ID = 0x0003, + FIELD_ID = 0x0004, + METHOD_ID = 0x0005, + CLASS_DEF = 0x0006, + CALL_SITE_ID = 0x0007, + METHOD_HANDLE = 0x0008, + MAP_LIST = 0x1000, + TYPE_LIST = 0x1001, ANNOTATION_SET_REF_LIST = 0x1002, - ANNOTATION_SET = 0x1003, - CLASS_DATA = 0x2000, - CODE = 0x2001, - STRING_DATA = 0x2002, - DEBUG_INFO = 0x2003, - ANNOTATION = 0x2004, - ENCODED_ARRAY = 0x2005, - ANNOTATIONS_DIRECTORY = 0x2006, + ANNOTATION_SET = 0x1003, + CLASS_DATA = 0x2000, + CODE = 0x2001, + STRING_DATA = 0x2002, + DEBUG_INFO = 0x2003, + ANNOTATION = 0x2004, + ENCODED_ARRAY = 0x2005, + ANNOTATIONS_DIRECTORY = 0x2006, }; @@ -66,7 +66,7 @@ class LIEF_API MapItem : public Object { /// The type of the item TYPES type() const; - /// Reserved value (likely for alignment prupose) + /// Reserved value (likely for alignment purpose) uint16_t reserved() const; /// The number of elements (the real meaning depends on the type) @@ -84,11 +84,10 @@ class LIEF_API MapItem : public Object { ~MapItem() override; private: - TYPES type_; - uint16_t reserved_; - uint32_t size_; - uint32_t offset_; - + TYPES type_ = TYPES::HEADER; + uint16_t reserved_ = 0; + uint32_t size_ = 0; + uint32_t offset_ = 0; }; } // Namespace DEX diff --git a/deps/LIEF/include/LIEF/DEX/MapList.hpp b/deps/LIEF/include/LIEF/DEX/MapList.hpp index c0c59ee83b16..53559222f523 100644 --- a/deps/LIEF/include/LIEF/DEX/MapList.hpp +++ b/deps/LIEF/include/LIEF/DEX/MapList.hpp @@ -1,5 +1,5 @@ -/* Copyright 2017 - 2025 R. Thomas - * Copyright 2017 - 2025 Quarkslab +/* Copyright 2017 - 2026 R. Thomas + * Copyright 2017 - 2026 Quarkslab * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -38,9 +38,9 @@ class LIEF_API MapList : public Object { friend class Parser; public: - using items_t = std::map; - using it_items_t = ref_iterator>; - using it_const_items_t = const_ref_iterator>; + using items_t = std::map; + using it_items_t = ref_iterator>; + using it_const_items_t = const_ref_iterator>; public: MapList(); @@ -56,10 +56,10 @@ class LIEF_API MapList : public Object { bool has(MapItem::TYPES type) const; /// Return the LIEF::DEX::MapItem associated with the given type - const MapItem& get(MapItem::TYPES type) const; + const MapItem& get(MapItem::TYPES type) const LIEF_LIFETIMEBOUND; /// Return the LIEF::DEX::MapItem associated with the given type - MapItem& get(MapItem::TYPES type); + MapItem& get(MapItem::TYPES type) LIEF_LIFETIMEBOUND; /// Return the LIEF::DEX::MapItem associated with the given type const MapItem& operator[](MapItem::TYPES type) const; @@ -76,7 +76,6 @@ class LIEF_API MapList : public Object { private: items_t items_; - }; } // Namespace DEX diff --git a/deps/LIEF/include/LIEF/DEX/Method.hpp b/deps/LIEF/include/LIEF/DEX/Method.hpp index 54eec9bd6627..5f419760ac2c 100644 --- a/deps/LIEF/include/LIEF/DEX/Method.hpp +++ b/deps/LIEF/include/LIEF/DEX/Method.hpp @@ -1,5 +1,5 @@ -/* Copyright 2017 - 2025 R. Thomas - * Copyright 2017 - 2025 Quarkslab +/* Copyright 2017 - 2026 R. Thomas + * Copyright 2017 - 2026 Quarkslab * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -35,6 +35,7 @@ class Prototype; /// Class which represents a DEX::Method class LIEF_API Method : public Object { friend class Parser; + public: using access_flags_list_t = std::vector; @@ -67,7 +68,7 @@ class LIEF_API Method : public Object { size_t index() const; /// True if this method is a virtual one. - /// i.e. not **static**, **private**, **finale** or constructor + /// i.e. not **static**, **private**, **final** or constructor bool is_virtual() const; /// Method's prototype or a nullptr if it is not resolved @@ -110,7 +111,6 @@ class LIEF_API Method : public Object { CodeInfo code_info_; dex2dex_method_info_t dex2dex_info_; - }; } // Namespace DEX diff --git a/deps/LIEF/include/LIEF/DEX/Parser.hpp b/deps/LIEF/include/LIEF/DEX/Parser.hpp index 7b925d129da2..2d3337ec9da7 100644 --- a/deps/LIEF/include/LIEF/DEX/Parser.hpp +++ b/deps/LIEF/include/LIEF/DEX/Parser.hpp @@ -1,5 +1,5 @@ -/* Copyright 2017 - 2025 R. Thomas - * Copyright 2017 - 2025 Quarkslab +/* Copyright 2017 - 2026 R. Thomas + * Copyright 2017 - 2026 Quarkslab * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -37,13 +37,13 @@ class Type; /// Class which parses a DEX file to produce a DEX::File object class LIEF_API Parser { public: - /// Parse the DEX file from the file path given in parameter static std::unique_ptr parse(const std::string& file); - static std::unique_ptr parse(std::vector data, const std::string& name = ""); + static std::unique_ptr parse(std::vector data, + const std::string& name = ""); Parser& operator=(const Parser& copy) = delete; - Parser(const Parser& copy) = delete; + Parser(const Parser& copy) = delete; private: Parser(); diff --git a/deps/LIEF/include/LIEF/DEX/Prototype.hpp b/deps/LIEF/include/LIEF/DEX/Prototype.hpp index ff6413a5c0b8..37762487ec66 100644 --- a/deps/LIEF/include/LIEF/DEX/Prototype.hpp +++ b/deps/LIEF/include/LIEF/DEX/Prototype.hpp @@ -1,5 +1,5 @@ -/* Copyright 2017 - 2025 R. Thomas - * Copyright 2017 - 2025 Quarkslab +/* Copyright 2017 - 2026 R. Thomas + * Copyright 2017 - 2026 Quarkslab * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -31,16 +31,16 @@ class LIEF_API Prototype : public Object { public: using parameters_type_t = std::vector; - using it_params = ref_iterator; - using it_const_params = const_ref_iterator; + using it_params = ref_iterator; + using it_const_params = const_ref_iterator; public: Prototype(); Prototype(const Prototype& other); /// Type returned or a nullptr if not resolved - const Type* return_type() const; - Type* return_type(); + const Type* return_type() const LIEF_LIFETIMEBOUND; + Type* return_type() LIEF_LIFETIMEBOUND; /// Types of the parameters it_const_params parameters_type() const; @@ -49,14 +49,14 @@ class LIEF_API Prototype : public Object { void accept(Visitor& visitor) const override; - LIEF_API friend std::ostream& operator<<(std::ostream& os, const Prototype& type); + LIEF_API friend std::ostream& operator<<(std::ostream& os, + const Prototype& type); ~Prototype() override; private: Type* return_type_ = nullptr; parameters_type_t params_; - }; } // Namespace DEX diff --git a/deps/LIEF/include/LIEF/DEX/Type.hpp b/deps/LIEF/include/LIEF/DEX/Type.hpp index 0c93f4922f7e..749eb4faf1f5 100644 --- a/deps/LIEF/include/LIEF/DEX/Type.hpp +++ b/deps/LIEF/include/LIEF/DEX/Type.hpp @@ -1,5 +1,5 @@ -/* Copyright 2017 - 2025 R. Thomas - * Copyright 2017 - 2025 Quarkslab +/* Copyright 2017 - 2026 R. Thomas + * Copyright 2017 - 2026 Quarkslab * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,28 +29,29 @@ class Parser; class Class; /// Class which represents a DEX type as described in the -/// format specifications: https://source.android.com/devices/tech/dalvik/dex-format#typedescriptor +/// format specifications: +/// https://source.android.com/devices/tech/dalvik/dex-format#typedescriptor class LIEF_API Type : public Object { friend class Parser; public: enum class TYPES { - UNKNOWN = 0, + UNKNOWN = 0, PRIMITIVE = 1, - CLASS = 2, - ARRAY = 3, + CLASS = 2, + ARRAY = 3, }; enum class PRIMITIVES { - VOID_T = 0x01, + VOID_T = 0x01, BOOLEAN = 0x02, - BYTE = 0x03, - SHORT = 0x04, - CHAR = 0x05, - INT = 0x06, - LONG = 0x07, - FLOAT = 0x08, - DOUBLE = 0x09, + BYTE = 0x03, + SHORT = 0x04, + CHAR = 0x05, + INT = 0x06, + LONG = 0x07, + FLOAT = 0x08, + DOUBLE = 0x09, }; using array_t = std::vector; @@ -87,8 +88,8 @@ class LIEF_API Type : public Object { size_t dim() const; /// In the case of a TYPES::ARRAY, return the array's type - const Type& underlying_array_type() const; - Type& underlying_array_type(); + const Type& underlying_array_type() const LIEF_LIFETIMEBOUND; + Type& underlying_array_type() LIEF_LIFETIMEBOUND; void accept(Visitor& visitor) const override; diff --git a/deps/LIEF/include/LIEF/DEX/deopt.hpp b/deps/LIEF/include/LIEF/DEX/deopt.hpp index 4164a8ffecc4..4a23843fe89b 100644 --- a/deps/LIEF/include/LIEF/DEX/deopt.hpp +++ b/deps/LIEF/include/LIEF/DEX/deopt.hpp @@ -1,5 +1,5 @@ -/* Copyright 2017 - 2025 R. Thomas - * Copyright 2017 - 2025 Quarkslab +/* Copyright 2017 - 2026 R. Thomas + * Copyright 2017 - 2026 Quarkslab * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,8 +25,8 @@ class Method; // Method Index: {dex_pc: index, ...} using dex2dex_method_info_t = std::unordered_map; -using dex2dex_class_info_t = std::unordered_map; -using dex2dex_info_t = std::unordered_map; +using dex2dex_class_info_t = std::unordered_map; +using dex2dex_info_t = std::unordered_map; } } diff --git a/deps/LIEF/include/LIEF/DEX/enums.hpp b/deps/LIEF/include/LIEF/DEX/enums.hpp index 4e808d8f9b76..1bfe7d968e9a 100644 --- a/deps/LIEF/include/LIEF/DEX/enums.hpp +++ b/deps/LIEF/include/LIEF/DEX/enums.hpp @@ -1,5 +1,5 @@ -/* Copyright 2017 - 2025 R. Thomas - * Copyright 2017 - 2025 Quarkslab +/* Copyright 2017 - 2026 R. Thomas + * Copyright 2017 - 2026 Quarkslab * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,61 +20,51 @@ namespace LIEF { namespace DEX { enum ACCESS_FLAGS { - ACC_UNKNOWN = 0x0, - ACC_PUBLIC = 0x1, - ACC_PRIVATE = 0x2, - ACC_PROTECTED = 0x4, - ACC_STATIC = 0x8, - ACC_FINAL = 0x10, - ACC_SYNCHRONIZED = 0x20, - ACC_VOLATILE = 0x40, - ACC_BRIDGE = 0x40, - ACC_TRANSIENT = 0x80, - ACC_VARARGS = 0x80, - ACC_NATIVE = 0x100, - ACC_INTERFACE = 0x200, - ACC_ABSTRACT = 0x400, - ACC_STRICT = 0x800, - ACC_SYNTHETIC = 0x1000, - ACC_ANNOTATION = 0x2000, - ACC_ENUM = 0x4000, - ACC_CONSTRUCTOR = 0x10000, - ACC_DECLARED_SYNCHRONIZED = 0x20000 + ACC_UNKNOWN = 0x0, + ACC_PUBLIC = 0x1, + ACC_PRIVATE = 0x2, + ACC_PROTECTED = 0x4, + ACC_STATIC = 0x8, + ACC_FINAL = 0x10, + ACC_SYNCHRONIZED = 0x20, + ACC_VOLATILE = 0x40, + ACC_BRIDGE = 0x40, + ACC_TRANSIENT = 0x80, + ACC_VARARGS = 0x80, + ACC_NATIVE = 0x100, + ACC_INTERFACE = 0x200, + ACC_ABSTRACT = 0x400, + ACC_STRICT = 0x800, + ACC_SYNTHETIC = 0x1000, + ACC_ANNOTATION = 0x2000, + ACC_ENUM = 0x4000, + ACC_CONSTRUCTOR = 0x10000, + ACC_DECLARED_SYNCHRONIZED = 0x20000, }; enum METHOD_TYPES { - METHOD_UNKNOWN = 0x00, - METHOD_VIRTUAL = 0x01, - METHOD_DIRECT = 0x02, // Deprecated + METHOD_UNKNOWN = 0x00, + METHOD_VIRTUAL = 0x01, + METHOD_DIRECT = 0x02, // Deprecated - METHOD_EXTERN = 0x03, - METHOD_CTOR = 0x04, - METHOD_STATIC = 0x05, - METHOD_STATIC_CTOR = 0x06, + METHOD_EXTERN = 0x03, + METHOD_CTOR = 0x04, + METHOD_STATIC = 0x05, + METHOD_STATIC_CTOR = 0x06, }; static const ACCESS_FLAGS access_flags_list[] = { - ACCESS_FLAGS::ACC_UNKNOWN, - ACCESS_FLAGS::ACC_PUBLIC, - ACCESS_FLAGS::ACC_PRIVATE, - ACCESS_FLAGS::ACC_PROTECTED, - ACCESS_FLAGS::ACC_STATIC, - ACCESS_FLAGS::ACC_FINAL, - ACCESS_FLAGS::ACC_SYNCHRONIZED, - ACCESS_FLAGS::ACC_VOLATILE, - ACCESS_FLAGS::ACC_BRIDGE, - ACCESS_FLAGS::ACC_TRANSIENT, - ACCESS_FLAGS::ACC_VARARGS, - ACCESS_FLAGS::ACC_NATIVE, - ACCESS_FLAGS::ACC_INTERFACE, - ACCESS_FLAGS::ACC_ABSTRACT, - ACCESS_FLAGS::ACC_STRICT, - ACCESS_FLAGS::ACC_SYNTHETIC, - ACCESS_FLAGS::ACC_ANNOTATION, - ACCESS_FLAGS::ACC_ENUM, - ACCESS_FLAGS::ACC_CONSTRUCTOR, - ACCESS_FLAGS::ACC_DECLARED_SYNCHRONIZED, + ACCESS_FLAGS::ACC_UNKNOWN, ACCESS_FLAGS::ACC_PUBLIC, + ACCESS_FLAGS::ACC_PRIVATE, ACCESS_FLAGS::ACC_PROTECTED, + ACCESS_FLAGS::ACC_STATIC, ACCESS_FLAGS::ACC_FINAL, + ACCESS_FLAGS::ACC_SYNCHRONIZED, ACCESS_FLAGS::ACC_VOLATILE, + ACCESS_FLAGS::ACC_BRIDGE, ACCESS_FLAGS::ACC_TRANSIENT, + ACCESS_FLAGS::ACC_VARARGS, ACCESS_FLAGS::ACC_NATIVE, + ACCESS_FLAGS::ACC_INTERFACE, ACCESS_FLAGS::ACC_ABSTRACT, + ACCESS_FLAGS::ACC_STRICT, ACCESS_FLAGS::ACC_SYNTHETIC, + ACCESS_FLAGS::ACC_ANNOTATION, ACCESS_FLAGS::ACC_ENUM, + ACCESS_FLAGS::ACC_CONSTRUCTOR, ACCESS_FLAGS::ACC_DECLARED_SYNCHRONIZED, }; } diff --git a/deps/LIEF/include/LIEF/DEX/hash.hpp b/deps/LIEF/include/LIEF/DEX/hash.hpp index 42184a42af9e..c4c058f1b8ee 100644 --- a/deps/LIEF/include/LIEF/DEX/hash.hpp +++ b/deps/LIEF/include/LIEF/DEX/hash.hpp @@ -1,5 +1,5 @@ -/* Copyright 2017 - 2025 R. Thomas - * Copyright 2017 - 2025 Quarkslab +/* Copyright 2017 - 2026 R. Thomas + * Copyright 2017 - 2026 Quarkslab * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -46,16 +46,16 @@ class LIEF_API Hash : public LIEF::Hash { using LIEF::Hash::visit; public: - void visit(const File& file) override; - void visit(const Header& header) override; - void visit(const Class& cls) override; - void visit(const Field& field) override; - void visit(const Method& method) override; + void visit(const File& file) override; + void visit(const Header& header) override; + void visit(const Class& cls) override; + void visit(const Field& field) override; + void visit(const Method& method) override; void visit(const CodeInfo& code_info) override; - void visit(const Type& type) override; - void visit(const Prototype& type) override; - void visit(const MapItem& item) override; - void visit(const MapList& list) override; + void visit(const Type& type) override; + void visit(const Prototype& type) override; + void visit(const MapItem& item) override; + void visit(const MapList& list) override; ~Hash() override; }; diff --git a/deps/LIEF/include/LIEF/DEX/instructions.hpp b/deps/LIEF/include/LIEF/DEX/instructions.hpp index 4c076d4575fa..c344b9bfd631 100644 --- a/deps/LIEF/include/LIEF/DEX/instructions.hpp +++ b/deps/LIEF/include/LIEF/DEX/instructions.hpp @@ -1,5 +1,5 @@ -/* Copyright 2017 - 2025 R. Thomas - * Copyright 2017 - 2025 Quarkslab +/* Copyright 2017 - 2026 R. Thomas + * Copyright 2017 - 2026 Quarkslab * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,6 +18,7 @@ #include "LIEF/visibility.h" #include "LIEF/types.hpp" #include +#include namespace LIEF { namespace DEX { @@ -25,258 +26,258 @@ namespace DEX { enum SWITCH_ARRAY_IDENT : uint16_t { IDENT_PACKED_SWITCH = 0x0100, IDENT_SPARSE_SWITCH = 0x0200, - IDENT_FILL_ARRAY = 0x0300, + IDENT_FILL_ARRAY = 0x0300, }; /// The Dalvik Opcodes enum OPCODES : uint8_t { - OP_NOP = 0x00, - OP_MOVE = 0x01, - OP_MOVE_FROM_16 = 0x02, - OP_MOVE_16 = 0x03, - OP_MOVE_WIDE = 0x04, - OP_MOVE_WIDE_FROM_16 = 0x05, - OP_MOVE_WIDE_16 = 0x06, - OP_MOVE_OBJECT = 0x07, - OP_MOVE_OBJECT_FROM_16 = 0x08, - OP_MOVE_OBJECT_16 = 0x09, - OP_MOVE_RESULT = 0x0a, - OP_MOVE_RESULT_WIDE = 0x0b, - OP_MOVE_RESULT_OBJECT = 0x0c, - OP_MOVE_EXCEPTION = 0x0d, - OP_RETURN_VOID = 0x0e, - OP_RETURN = 0x0f, - OP_RETURN_WIDE = 0x10, - OP_RETURN_OBJECT = 0x11, - OP_CONST_4 = 0x12, - OP_CONST_16 = 0x13, - OP_CONST = 0x14, - OP_CONST_HIGH_16 = 0x15, - OP_CONST_WIDE_16 = 0x16, - OP_CONST_WIDE_32 = 0x17, - OP_CONST_WIDE = 0x18, - OP_CONST_WIDE_HIGH_16 = 0x19, - OP_CONST_STRING = 0x1a, - OP_CONST_STRING_JUMBO = 0x1b, - OP_CONST_CLASS = 0x1c, - OP_MONITOR_ENTER = 0x1d, - OP_MONITOR_EXIT = 0x1e, - OP_CHECK_CAST = 0x1f, - OP_INSTANCE_OF = 0x20, - OP_ARRAY_LENGTH = 0x21, - OP_NEW_INSTANCE = 0x22, - OP_NEW_ARRAY = 0x23, - OP_FILLED_NEW_ARRAY = 0x24, + OP_NOP = 0x00, + OP_MOVE = 0x01, + OP_MOVE_FROM_16 = 0x02, + OP_MOVE_16 = 0x03, + OP_MOVE_WIDE = 0x04, + OP_MOVE_WIDE_FROM_16 = 0x05, + OP_MOVE_WIDE_16 = 0x06, + OP_MOVE_OBJECT = 0x07, + OP_MOVE_OBJECT_FROM_16 = 0x08, + OP_MOVE_OBJECT_16 = 0x09, + OP_MOVE_RESULT = 0x0a, + OP_MOVE_RESULT_WIDE = 0x0b, + OP_MOVE_RESULT_OBJECT = 0x0c, + OP_MOVE_EXCEPTION = 0x0d, + OP_RETURN_VOID = 0x0e, + OP_RETURN = 0x0f, + OP_RETURN_WIDE = 0x10, + OP_RETURN_OBJECT = 0x11, + OP_CONST_4 = 0x12, + OP_CONST_16 = 0x13, + OP_CONST = 0x14, + OP_CONST_HIGH_16 = 0x15, + OP_CONST_WIDE_16 = 0x16, + OP_CONST_WIDE_32 = 0x17, + OP_CONST_WIDE = 0x18, + OP_CONST_WIDE_HIGH_16 = 0x19, + OP_CONST_STRING = 0x1a, + OP_CONST_STRING_JUMBO = 0x1b, + OP_CONST_CLASS = 0x1c, + OP_MONITOR_ENTER = 0x1d, + OP_MONITOR_EXIT = 0x1e, + OP_CHECK_CAST = 0x1f, + OP_INSTANCE_OF = 0x20, + OP_ARRAY_LENGTH = 0x21, + OP_NEW_INSTANCE = 0x22, + OP_NEW_ARRAY = 0x23, + OP_FILLED_NEW_ARRAY = 0x24, OP_FILLED_NEW_ARRAY_RANGE = 0x25, - OP_FILL_ARRAY_DATA = 0x26, - OP_THROW = 0x27, - OP_GOTO = 0x28, - OP_GOTO_16 = 0x29, - OP_GOTO_32 = 0x2a, - OP_PACKED_SWITCH = 0x2b, - OP_SPARSE_SWITCH = 0x2c, - OP_CMPL_FLOAT = 0x2d, - OP_CMPG_FLOAT = 0x2e, - OP_CMPL_DOUBLE = 0x2f, - OP_CMPG_DOUBLE = 0x30, - OP_CMP_LONG = 0x31, - OP_IF_EQ = 0x32, - OP_IF_NE = 0x33, - OP_IF_LT = 0x34, - OP_IF_GE = 0x35, - OP_IF_GT = 0x36, - OP_IF_LE = 0x37, - OP_IF_EQZ = 0x38, - OP_IF_NEZ = 0x39, - OP_IF_LTZ = 0x3a, - OP_IF_GEZ = 0x3b, - OP_IF_GTZ = 0x3c, - OP_IF_LEZ = 0x3d, - OP_AGET = 0x44, - OP_AGET_WIDE = 0x45, - OP_AGET_OBJECT = 0x46, - OP_AGET_BOOLEAN = 0x47, - OP_AGET_BYTE = 0x48, - OP_AGET_CHAR = 0x49, - OP_AGET_SHORT = 0x4a, - OP_APUT = 0x4b, - OP_APUT_WIDE = 0x4c, - OP_APUT_OBJECT = 0x4d, - OP_APUT_BOOLEAN = 0x4e, - OP_APUT_BYTE = 0x4f, - OP_APUT_CHAR = 0x50, - OP_APUT_SHORT = 0x51, - OP_IGET = 0x52, - OP_IGET_WIDE = 0x53, - OP_IGET_OBJECT = 0x54, - OP_IGET_BOOLEAN = 0x55, - OP_IGET_BYTE = 0x56, - OP_IGET_CHAR = 0x57, - OP_IGET_SHORT = 0x58, - OP_IPUT = 0x59, - OP_IPUT_WIDE = 0x5a, - OP_IPUT_OBJECT = 0x5b, - OP_IPUT_BOOLEAN = 0x5c, - OP_IPUT_BYTE = 0x5d, - OP_IPUT_CHAR = 0x5e, - OP_IPUT_SHORT = 0x5f, - OP_SGET = 0x60, - OP_SGET_WIDE = 0x61, - OP_SGET_OBJECT = 0x62, - OP_SGET_BOOLEAN = 0x63, - OP_SGET_BYTE = 0x64, - OP_SGET_CHAR = 0x65, - OP_SGET_SHORT = 0x66, - OP_SPUT = 0x67, - OP_SPUT_WIDE = 0x68, - OP_SPUT_OBJECT = 0x69, - OP_SPUT_BOOLEAN = 0x6a, - OP_SPUT_BYTE = 0x6b, - OP_SPUT_CHAR = 0x6c, - OP_SPUT_SHORT = 0x6d, - OP_INVOKE_VIRTUAL = 0x6e, - OP_INVOKE_SUPER = 0x6f, - OP_INVOKE_DIRECT = 0x70, - OP_INVOKE_STATIC = 0x71, - OP_INVOKE_INTERFACE = 0x72, + OP_FILL_ARRAY_DATA = 0x26, + OP_THROW = 0x27, + OP_GOTO = 0x28, + OP_GOTO_16 = 0x29, + OP_GOTO_32 = 0x2a, + OP_PACKED_SWITCH = 0x2b, + OP_SPARSE_SWITCH = 0x2c, + OP_CMPL_FLOAT = 0x2d, + OP_CMPG_FLOAT = 0x2e, + OP_CMPL_DOUBLE = 0x2f, + OP_CMPG_DOUBLE = 0x30, + OP_CMP_LONG = 0x31, + OP_IF_EQ = 0x32, + OP_IF_NE = 0x33, + OP_IF_LT = 0x34, + OP_IF_GE = 0x35, + OP_IF_GT = 0x36, + OP_IF_LE = 0x37, + OP_IF_EQZ = 0x38, + OP_IF_NEZ = 0x39, + OP_IF_LTZ = 0x3a, + OP_IF_GEZ = 0x3b, + OP_IF_GTZ = 0x3c, + OP_IF_LEZ = 0x3d, + OP_AGET = 0x44, + OP_AGET_WIDE = 0x45, + OP_AGET_OBJECT = 0x46, + OP_AGET_BOOLEAN = 0x47, + OP_AGET_BYTE = 0x48, + OP_AGET_CHAR = 0x49, + OP_AGET_SHORT = 0x4a, + OP_APUT = 0x4b, + OP_APUT_WIDE = 0x4c, + OP_APUT_OBJECT = 0x4d, + OP_APUT_BOOLEAN = 0x4e, + OP_APUT_BYTE = 0x4f, + OP_APUT_CHAR = 0x50, + OP_APUT_SHORT = 0x51, + OP_IGET = 0x52, + OP_IGET_WIDE = 0x53, + OP_IGET_OBJECT = 0x54, + OP_IGET_BOOLEAN = 0x55, + OP_IGET_BYTE = 0x56, + OP_IGET_CHAR = 0x57, + OP_IGET_SHORT = 0x58, + OP_IPUT = 0x59, + OP_IPUT_WIDE = 0x5a, + OP_IPUT_OBJECT = 0x5b, + OP_IPUT_BOOLEAN = 0x5c, + OP_IPUT_BYTE = 0x5d, + OP_IPUT_CHAR = 0x5e, + OP_IPUT_SHORT = 0x5f, + OP_SGET = 0x60, + OP_SGET_WIDE = 0x61, + OP_SGET_OBJECT = 0x62, + OP_SGET_BOOLEAN = 0x63, + OP_SGET_BYTE = 0x64, + OP_SGET_CHAR = 0x65, + OP_SGET_SHORT = 0x66, + OP_SPUT = 0x67, + OP_SPUT_WIDE = 0x68, + OP_SPUT_OBJECT = 0x69, + OP_SPUT_BOOLEAN = 0x6a, + OP_SPUT_BYTE = 0x6b, + OP_SPUT_CHAR = 0x6c, + OP_SPUT_SHORT = 0x6d, + OP_INVOKE_VIRTUAL = 0x6e, + OP_INVOKE_SUPER = 0x6f, + OP_INVOKE_DIRECT = 0x70, + OP_INVOKE_STATIC = 0x71, + OP_INVOKE_INTERFACE = 0x72, OP_RETURN_VOID_NO_BARRIER = 0x73, - OP_INVOKE_VIRTUAL_RANGE = 0x74, - OP_INVOKE_SUPER_RANGE = 0x75, - OP_INVOKE_DIRECT_RANGE = 0x76, - OP_INVOKE_STATIC_RANGE = 0x77, + OP_INVOKE_VIRTUAL_RANGE = 0x74, + OP_INVOKE_SUPER_RANGE = 0x75, + OP_INVOKE_DIRECT_RANGE = 0x76, + OP_INVOKE_STATIC_RANGE = 0x77, OP_INVOKE_INTERFACE_RANGE = 0x78, - OP_NEG_INT = 0x7b, - OP_NOT_INT = 0x7c, - OP_NEG_LONG = 0x7d, - OP_NOT_LONG = 0x7e, - OP_NEG_FLOAT = 0x7f, - OP_NEG_DOUBLE = 0x80, - OP_INT_TO_LONG = 0x81, - OP_INT_TO_FLOAT = 0x82, - OP_INT_TO_DOUBLE = 0x83, - OP_LONG_TO_INT = 0x84, - OP_LONG_TO_FLOAT = 0x85, - OP_LONG_TO_DOUBLE = 0x86, - OP_FLOAT_TO_INT = 0x87, - OP_FLOAT_TO_LONG = 0x88, - OP_FLOAT_TO_DOUBLE = 0x89, - OP_DOUBLE_TO_INT = 0x8a, - OP_DOUBLE_TO_LONG = 0x8b, - OP_DOUBLE_TO_FLOAT = 0x8c, - OP_INT_TO_BYTE = 0x8d, - OP_INT_TO_CHAR = 0x8e, - OP_INT_TO_SHORT = 0x8f, - OP_ADD_INT = 0x90, - OP_SUB_INT = 0x91, - OP_MUL_INT = 0x92, - OP_DIV_INT = 0x93, - OP_REM_INT = 0x94, - OP_AND_INT = 0x95, - OP_OR_INT = 0x96, - OP_XOR_INT = 0x97, - OP_SHL_INT = 0x98, - OP_SHR_INT = 0x99, - OP_USHR_INT = 0x9a, - OP_ADD_LONG = 0x9b, - OP_SUB_LONG = 0x9c, - OP_MUL_LONG = 0x9d, - OP_DIV_LONG = 0x9e, - OP_REM_LONG = 0x9f, - OP_AND_LONG = 0xa0, - OP_OR_LONG = 0xa1, - OP_XOR_LONG = 0xa2, - OP_SHL_LONG = 0xa3, - OP_SHR_LONG = 0xa4, - OP_USHR_LONG = 0xa5, - OP_ADD_FLOAT = 0xa6, - OP_SUB_FLOAT = 0xa7, - OP_MUL_FLOAT = 0xa8, - OP_DIV_FLOAT = 0xa9, - OP_REM_FLOAT = 0xaa, - OP_ADD_DOUBLE = 0xab, - OP_SUB_DOUBLE = 0xac, - OP_MUL_DOUBLE = 0xad, - OP_DIV_DOUBLE = 0xae, - OP_REM_DOUBLE = 0xaf, - OP_ADD_INT_2_ADDR = 0xb0, - OP_SUB_INT_2_ADDR = 0xb1, - OP_MUL_INT_2_ADDR = 0xb2, - OP_DIV_INT_2_ADDR = 0xb3, - OP_REM_INT_2_ADDR = 0xb4, - OP_AND_INT_2_ADDR = 0xb5, - OP_OR_INT_2_ADDR = 0xb6, - OP_XOR_INT_2_ADDR = 0xb7, - OP_SHL_INT_2_ADDR = 0xb8, - OP_SHR_INT_2_ADDR = 0xb9, - OP_USHR_INT_2_ADDR = 0xba, - OP_ADD_LONG_2_ADDR = 0xbb, - OP_SUB_LONG_2_ADDR = 0xbc, - OP_MUL_LONG_2_ADDR = 0xbd, - OP_DIV_LONG_2_ADDR = 0xbe, - OP_REM_LONG_2_ADDR = 0xbf, - OP_AND_LONG_2_ADDR = 0xc0, - OP_OR_LONG_2_ADDR = 0xc1, - OP_XOR_LONG_2_ADDR = 0xc2, - OP_SHL_LONG_2_ADDR = 0xc3, - OP_SHR_LONG_2_ADDR = 0xc4, - OP_USHR_LONG_2_ADDR = 0xc5, - OP_ADD_FLOAT_2_ADDR = 0xc6, - OP_SUB_FLOAT_2_ADDR = 0xc7, - OP_MUL_FLOAT_2_ADDR = 0xc8, - OP_DIV_FLOAT_2_ADDR = 0xc9, - OP_REM_FLOAT_2_ADDR = 0xca, - OP_ADD_DOUBLE_2_ADDR = 0xcb, - OP_SUB_DOUBLE_2_ADDR = 0xcc, - OP_MUL_DOUBLE_2_ADDR = 0xcd, - OP_DIV_DOUBLE_2_ADDR = 0xce, - OP_REM_DOUBLE_2_ADDR = 0xcf, - OP_ADD_INT_LIT_16 = 0xd0, - OP_RSUB_INT = 0xd1, - OP_MUL_INT_LIT_16 = 0xd2, - OP_DIV_INT_LIT_16 = 0xd3, - OP_REM_INT_LIT_16 = 0xd4, - OP_AND_INT_LIT_16 = 0xd5, - OP_OR_INT_LIT_16 = 0xd6, - OP_XOR_INT_LIT_16 = 0xd7, - OP_ADD_INT_LIT_8 = 0xd8, - OP_RSUB_INT_LIT_8 = 0xd9, - OP_MUL_INT_LIT_8 = 0xda, - OP_DIV_INT_LIT_8 = 0xdb, - OP_REM_INT_LIT_8 = 0xdc, - OP_AND_INT_LIT_8 = 0xdd, - OP_OR_INT_LIT_8 = 0xde, - OP_XOR_INT_LIT_8 = 0xdf, - OP_SHL_INT_LIT_8 = 0xe0, - OP_SHR_INT_LIT_8 = 0xe1, - OP_USHR_INT_LIT_8 = 0xe2, + OP_NEG_INT = 0x7b, + OP_NOT_INT = 0x7c, + OP_NEG_LONG = 0x7d, + OP_NOT_LONG = 0x7e, + OP_NEG_FLOAT = 0x7f, + OP_NEG_DOUBLE = 0x80, + OP_INT_TO_LONG = 0x81, + OP_INT_TO_FLOAT = 0x82, + OP_INT_TO_DOUBLE = 0x83, + OP_LONG_TO_INT = 0x84, + OP_LONG_TO_FLOAT = 0x85, + OP_LONG_TO_DOUBLE = 0x86, + OP_FLOAT_TO_INT = 0x87, + OP_FLOAT_TO_LONG = 0x88, + OP_FLOAT_TO_DOUBLE = 0x89, + OP_DOUBLE_TO_INT = 0x8a, + OP_DOUBLE_TO_LONG = 0x8b, + OP_DOUBLE_TO_FLOAT = 0x8c, + OP_INT_TO_BYTE = 0x8d, + OP_INT_TO_CHAR = 0x8e, + OP_INT_TO_SHORT = 0x8f, + OP_ADD_INT = 0x90, + OP_SUB_INT = 0x91, + OP_MUL_INT = 0x92, + OP_DIV_INT = 0x93, + OP_REM_INT = 0x94, + OP_AND_INT = 0x95, + OP_OR_INT = 0x96, + OP_XOR_INT = 0x97, + OP_SHL_INT = 0x98, + OP_SHR_INT = 0x99, + OP_USHR_INT = 0x9a, + OP_ADD_LONG = 0x9b, + OP_SUB_LONG = 0x9c, + OP_MUL_LONG = 0x9d, + OP_DIV_LONG = 0x9e, + OP_REM_LONG = 0x9f, + OP_AND_LONG = 0xa0, + OP_OR_LONG = 0xa1, + OP_XOR_LONG = 0xa2, + OP_SHL_LONG = 0xa3, + OP_SHR_LONG = 0xa4, + OP_USHR_LONG = 0xa5, + OP_ADD_FLOAT = 0xa6, + OP_SUB_FLOAT = 0xa7, + OP_MUL_FLOAT = 0xa8, + OP_DIV_FLOAT = 0xa9, + OP_REM_FLOAT = 0xaa, + OP_ADD_DOUBLE = 0xab, + OP_SUB_DOUBLE = 0xac, + OP_MUL_DOUBLE = 0xad, + OP_DIV_DOUBLE = 0xae, + OP_REM_DOUBLE = 0xaf, + OP_ADD_INT_2_ADDR = 0xb0, + OP_SUB_INT_2_ADDR = 0xb1, + OP_MUL_INT_2_ADDR = 0xb2, + OP_DIV_INT_2_ADDR = 0xb3, + OP_REM_INT_2_ADDR = 0xb4, + OP_AND_INT_2_ADDR = 0xb5, + OP_OR_INT_2_ADDR = 0xb6, + OP_XOR_INT_2_ADDR = 0xb7, + OP_SHL_INT_2_ADDR = 0xb8, + OP_SHR_INT_2_ADDR = 0xb9, + OP_USHR_INT_2_ADDR = 0xba, + OP_ADD_LONG_2_ADDR = 0xbb, + OP_SUB_LONG_2_ADDR = 0xbc, + OP_MUL_LONG_2_ADDR = 0xbd, + OP_DIV_LONG_2_ADDR = 0xbe, + OP_REM_LONG_2_ADDR = 0xbf, + OP_AND_LONG_2_ADDR = 0xc0, + OP_OR_LONG_2_ADDR = 0xc1, + OP_XOR_LONG_2_ADDR = 0xc2, + OP_SHL_LONG_2_ADDR = 0xc3, + OP_SHR_LONG_2_ADDR = 0xc4, + OP_USHR_LONG_2_ADDR = 0xc5, + OP_ADD_FLOAT_2_ADDR = 0xc6, + OP_SUB_FLOAT_2_ADDR = 0xc7, + OP_MUL_FLOAT_2_ADDR = 0xc8, + OP_DIV_FLOAT_2_ADDR = 0xc9, + OP_REM_FLOAT_2_ADDR = 0xca, + OP_ADD_DOUBLE_2_ADDR = 0xcb, + OP_SUB_DOUBLE_2_ADDR = 0xcc, + OP_MUL_DOUBLE_2_ADDR = 0xcd, + OP_DIV_DOUBLE_2_ADDR = 0xce, + OP_REM_DOUBLE_2_ADDR = 0xcf, + OP_ADD_INT_LIT_16 = 0xd0, + OP_RSUB_INT = 0xd1, + OP_MUL_INT_LIT_16 = 0xd2, + OP_DIV_INT_LIT_16 = 0xd3, + OP_REM_INT_LIT_16 = 0xd4, + OP_AND_INT_LIT_16 = 0xd5, + OP_OR_INT_LIT_16 = 0xd6, + OP_XOR_INT_LIT_16 = 0xd7, + OP_ADD_INT_LIT_8 = 0xd8, + OP_RSUB_INT_LIT_8 = 0xd9, + OP_MUL_INT_LIT_8 = 0xda, + OP_DIV_INT_LIT_8 = 0xdb, + OP_REM_INT_LIT_8 = 0xdc, + OP_AND_INT_LIT_8 = 0xdd, + OP_OR_INT_LIT_8 = 0xde, + OP_XOR_INT_LIT_8 = 0xdf, + OP_SHL_INT_LIT_8 = 0xe0, + OP_SHR_INT_LIT_8 = 0xe1, + OP_USHR_INT_LIT_8 = 0xe2, // ODEX - OP_IGET_QUICK = 0xe3, - OP_IGET_WIDE_QUICK = 0xe4, - OP_IGET_OBJECT_QUICK = 0xe5, - OP_IPUT_QUICK = 0xe6, - OP_IPUT_WIDE_QUICK = 0xe7, - OP_IPUT_OBJECT_QUICK = 0xe8, - OP_INVOKE_VIRTUAL_QUICK = 0xe9, - OP_INVOKE_VIRTUAL_RANGE_QUICK = 0xea, - OP_IPUT_BOOLEAN_QUICK = 0xeb, - OP_IPUT_BYTE_QUICK = 0xec, - OP_IPUT_CHAR_QUICK = 0xed, - OP_IPUT_SHORT_QUICK = 0xee, - OP_IGET_BOOLEAN_QUICK = 0xef, - OP_IGET_BYTE_QUICK = 0xf0, - OP_IGET_CHAR_QUICK = 0xf1, - OP_IGET_SHORT_QUICK = 0xf2, + OP_IGET_QUICK = 0xe3, + OP_IGET_WIDE_QUICK = 0xe4, + OP_IGET_OBJECT_QUICK = 0xe5, + OP_IPUT_QUICK = 0xe6, + OP_IPUT_WIDE_QUICK = 0xe7, + OP_IPUT_OBJECT_QUICK = 0xe8, + OP_INVOKE_VIRTUAL_QUICK = 0xe9, + OP_INVOKE_VIRTUAL_RANGE_QUICK = 0xea, + OP_IPUT_BOOLEAN_QUICK = 0xeb, + OP_IPUT_BYTE_QUICK = 0xec, + OP_IPUT_CHAR_QUICK = 0xed, + OP_IPUT_SHORT_QUICK = 0xee, + OP_IGET_BOOLEAN_QUICK = 0xef, + OP_IGET_BYTE_QUICK = 0xf0, + OP_IGET_CHAR_QUICK = 0xf1, + OP_IGET_SHORT_QUICK = 0xf2, // From DEX 38 - OP_INVOKE_POLYMORPHIC = 0xfa, + OP_INVOKE_POLYMORPHIC = 0xfa, OP_INVOKE_POLYMORPHIC_RANGE = 0xfb, - OP_INVOKE_CUSTOM = 0xfc, - OP_INVOKE_CUSTOM_RANGE = 0xfd, + OP_INVOKE_CUSTOM = 0xfc, + OP_INVOKE_CUSTOM_RANGE = 0xfd, // From DEX 39 - OP_CONST_METHOD_HANDLE = 0xfe, - OP_CONST_METHOD_TYPE = 0xff, + OP_CONST_METHOD_HANDLE = 0xfe, + OP_CONST_METHOD_TYPE = 0xff, }; enum INST_FORMATS : uint8_t { @@ -335,7 +336,7 @@ struct fill_array_data { uint16_t ident; uint16_t element_width; uint32_t size; - //uint8_t data[size]; + // uint8_t data[size]; }; @@ -349,8 +350,11 @@ LIEF_API bool is_switch_array(const uint8_t* ptr, const uint8_t* end); LIEF_API size_t switch_array_size(const uint8_t* ptr, const uint8_t* end); +inline bool valid_inst_size(const uint8_t* ptr, const uint8_t* end, size_t size) { + return size != 0 && size != SIZE_MAX && (size_t)(end - ptr) >= size; +} + } // Namespace LIEF } // Namespace DEX #endif - diff --git a/deps/LIEF/include/LIEF/DEX/json.hpp b/deps/LIEF/include/LIEF/DEX/json.hpp index 74b79fe48e45..30ebec061f95 100644 --- a/deps/LIEF/include/LIEF/DEX/json.hpp +++ b/deps/LIEF/include/LIEF/DEX/json.hpp @@ -1,5 +1,5 @@ -/* Copyright 2017 - 2025 R. Thomas - * Copyright 2017 - 2025 Quarkslab +/* Copyright 2017 - 2026 R. Thomas + * Copyright 2017 - 2026 Quarkslab * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/deps/LIEF/include/LIEF/DEX/types.hpp b/deps/LIEF/include/LIEF/DEX/types.hpp index e38b44ea5aeb..b66a071e0180 100644 --- a/deps/LIEF/include/LIEF/DEX/types.hpp +++ b/deps/LIEF/include/LIEF/DEX/types.hpp @@ -1,5 +1,5 @@ -/* Copyright 2017 - 2025 R. Thomas - * Copyright 2017 - 2025 Quarkslab +/* Copyright 2017 - 2026 R. Thomas + * Copyright 2017 - 2026 Quarkslab * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/deps/LIEF/include/LIEF/DEX/utils.hpp b/deps/LIEF/include/LIEF/DEX/utils.hpp index ceecc6b0a0a8..14166cd7f6d7 100644 --- a/deps/LIEF/include/LIEF/DEX/utils.hpp +++ b/deps/LIEF/include/LIEF/DEX/utils.hpp @@ -1,5 +1,5 @@ -/* Copyright 2017 - 2025 R. Thomas - * Copyright 2017 - 2025 Quarkslab +/* Copyright 2017 - 2026 R. Thomas + * Copyright 2017 - 2026 Quarkslab * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/deps/LIEF/include/LIEF/DWARF.hpp b/deps/LIEF/include/LIEF/DWARF.hpp index 39c516b5e6cb..086daaf2a87c 100644 --- a/deps/LIEF/include/LIEF/DWARF.hpp +++ b/deps/LIEF/include/LIEF/DWARF.hpp @@ -1,5 +1,5 @@ -/* Copyright 2017 - 2025 R. Thomas - * Copyright 2017 - 2025 Quarkslab +/* Copyright 2017 - 2026 R. Thomas + * Copyright 2017 - 2026 Quarkslab * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,6 +26,7 @@ #include "LIEF/DWARF/types.hpp" #include "LIEF/DWARF/Parameter.hpp" #include "LIEF/DWARF/Editor.hpp" +#include "LIEF/DWARF/LexicalBlock.hpp" #include "LIEF/DWARF/editor/CompilationUnit.hpp" #include "LIEF/DWARF/editor/Function.hpp" diff --git a/deps/LIEF/include/LIEF/DWARF/CompilationUnit.hpp b/deps/LIEF/include/LIEF/DWARF/CompilationUnit.hpp index c9491b530d40..98233ab516b9 100644 --- a/deps/LIEF/include/LIEF/DWARF/CompilationUnit.hpp +++ b/deps/LIEF/include/LIEF/DWARF/CompilationUnit.hpp @@ -1,4 +1,4 @@ -/* Copyright 2022 - 2025 R. Thomas +/* Copyright 2022 - 2026 R. Thomas * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,9 +18,11 @@ #include #include +#include "LIEF/compiler_attributes.hpp" #include "LIEF/visibility.h" #include "LIEF/range.hpp" #include "LIEF/iterators.hpp" +#include "LIEF/DebugDeclOpt.hpp" #include "LIEF/DWARF/Function.hpp" #include "LIEF/DWARF/Type.hpp" @@ -35,61 +37,52 @@ class CompilationUnitIt; /// This class represents a DWARF compilation unit class LIEF_API CompilationUnit { public: - class LIEF_API Iterator { + class Iterator final + : public iterator_facade_base { public: - using iterator_category = std::bidirectional_iterator_tag; - using value_type = std::unique_ptr; - using difference_type = std::ptrdiff_t; - using pointer = CompilationUnit*; - using reference = std::unique_ptr&; using implementation = details::CompilationUnitIt; + using iterator_facade_base::operator++; + using iterator_facade_base::operator--; - class LIEF_API PointerProxy { - // Inspired from LLVM's iterator_facade_base - friend class Iterator; - public: - pointer operator->() const { return R.get(); } + LIEF_API Iterator(); - private: - value_type R; + LIEF_API Iterator(std::unique_ptr impl); - template - PointerProxy(RefT &&R) : R(std::forward(R)) {} // NOLINT(bugprone-forwarding-reference-overload) - }; + LIEF_API Iterator(const Iterator&); + LIEF_API Iterator& operator=(const Iterator&); + + LIEF_API Iterator(Iterator&&) noexcept; + LIEF_API Iterator& operator=(Iterator&&) noexcept; - Iterator(const Iterator&); - Iterator(Iterator&&) noexcept; - Iterator(std::unique_ptr impl); - ~Iterator(); + LIEF_API ~Iterator(); friend LIEF_API bool operator==(const Iterator& LHS, const Iterator& RHS); - friend LIEF_API bool operator!=(const Iterator& LHS, const Iterator& RHS) { + friend bool operator!=(const Iterator& LHS, const Iterator& RHS) { return !(LHS == RHS); } - Iterator& operator++(); - Iterator& operator--(); + // NOLINTNEXTLINE(bugprone-derived-method-shadowing-base-method) + LIEF_API Iterator& operator++(); - Iterator operator--(int) { - Iterator tmp = *static_cast(this); - --*static_cast(this); - return tmp; - } + // NOLINTNEXTLINE(bugprone-derived-method-shadowing-base-method) + LIEF_API Iterator& operator--(); - Iterator operator++(int) { - Iterator tmp = *static_cast(this); - ++*static_cast(this); - return tmp; - } + LIEF_API const CompilationUnit& operator*() const LIEF_LIFETIMEBOUND; - std::unique_ptr operator*() const; + // NOLINTNEXTLINE(bugprone-derived-method-shadowing-base-method) + LIEF_API const CompilationUnit* operator->() const LIEF_LIFETIMEBOUND; - PointerProxy operator->() const { - return static_cast(this)->operator*(); - } + /// Transfer ownership of the compilation unit at the current position + /// to the caller. Returns `nullptr` if the iterator is past-the-end. + LIEF_API std::unique_ptr yield(); private: + void load() const; + std::unique_ptr impl_; + mutable std::unique_ptr cached_; }; /// Iterator over the dwarf::Function @@ -130,11 +123,10 @@ class LIEF_API CompilationUnit { Language() = default; Language(LANG lang, uint32_t version) : - lang(lang), version(version) - {} + lang(lang), + version(version) {} Language(LANG lang) : - Language(lang, 0) - {} + Language(lang, 0) {} Language(const Language&) = default; Language& operator=(const Language&) = default; @@ -169,7 +161,7 @@ class LIEF_API CompilationUnit { /// This value matches the `DW_AT_comp_dir` attribute std::string compilation_dir() const; - /// Original Language of this compilation unit. + /// Original language of this compilation unit. /// /// This value matches the `DW_AT_language` attribute. Language language() const; @@ -186,7 +178,7 @@ class LIEF_API CompilationUnit { /// between the lowest address and the highest that are not owned by the CU), /// then it returns the sum of **all** the address ranges owned by this CU. /// - /// If the compilation unit is **not** fragmented, then is basically returns + /// If the compilation unit is **not** fragmented, then it basically returns /// `high_address - low_address`. uint64_t size() const; @@ -199,16 +191,18 @@ class LIEF_API CompilationUnit { /// Try to find the function whose name is given in parameter. /// /// The provided name can be demangled - std::unique_ptr find_function(const std::string& name) const; + std::unique_ptr + find_function(const std::string& name) const LIEF_LIFETIMEBOUND; /// Try to find the function at the given address - std::unique_ptr find_function(uint64_t addr) const; + std::unique_ptr find_function(uint64_t addr) const LIEF_LIFETIMEBOUND; /// Try to find the Variable at the given address - std::unique_ptr find_variable(uint64_t addr) const; + std::unique_ptr find_variable(uint64_t addr) const LIEF_LIFETIMEBOUND; /// Try to find the Variable with the given name - std::unique_ptr find_variable(const std::string& name) const; + std::unique_ptr + find_variable(const std::string& name) const LIEF_LIFETIMEBOUND; /// Return an iterator over the functions implemented in this compilation /// unit. @@ -232,7 +226,7 @@ class LIEF_API CompilationUnit { /// The iterator will only return **one function** for `main` since /// `get_secret_env` is inlined and thus, its implementation is located in /// `main`. - functions_it functions() const; + functions_it functions() const LIEF_LIFETIMEBOUND; /// Return an iterator over the functions **imported** in this compilation /// unit **but not** implemented. @@ -251,14 +245,13 @@ class LIEF_API CompilationUnit { /// the iterator. On the other hand, `main()` is implemented in this /// compilation unit so it is not returned by imported_function() but /// functions(). - functions_it imported_functions() const; + functions_it imported_functions() const LIEF_LIFETIMEBOUND; /// Return an iterator over the different types defined in this /// compilation unit. - types_it types() const; - + types_it types() const LIEF_LIFETIMEBOUND; - /// Return an iterator over all the variables defined in the this compilation + /// Return an iterator over all the variables defined in this compilation /// unit: /// /// ```cpp @@ -270,7 +263,11 @@ class LIEF_API CompilationUnit { /// return C; /// } /// ``` - vars_it variables() const; + vars_it variables() const LIEF_LIFETIMEBOUND; + + /// Generate a C/C++ definition for the functions defined in this + /// compilation unit. + std::string to_decl(const DeclOpt& opt = DeclOpt()) const; private: std::unique_ptr impl_; @@ -279,4 +276,3 @@ class LIEF_API CompilationUnit { } } #endif - diff --git a/deps/LIEF/include/LIEF/DWARF/DebugInfo.hpp b/deps/LIEF/include/LIEF/DWARF/DebugInfo.hpp index ac76755b7906..2298ba3c753d 100644 --- a/deps/LIEF/include/LIEF/DWARF/DebugInfo.hpp +++ b/deps/LIEF/include/LIEF/DWARF/DebugInfo.hpp @@ -1,4 +1,4 @@ -/* Copyright 2022 - 2025 R. Thomas +/* Copyright 2022 - 2026 R. Thomas * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,6 +17,7 @@ #include #include +#include "LIEF/compiler_attributes.hpp" #include "LIEF/iterators.hpp" #include "LIEF/Abstract/DebugInfo.hpp" #include "LIEF/DWARF/CompilationUnit.hpp" @@ -53,23 +54,26 @@ class LIEF_API DebugInfo : public LIEF::DebugInfo { /// // Found /// } /// ``` - std::unique_ptr find_function(const std::string& name) const; + std::unique_ptr + find_function(const std::string& name) const LIEF_LIFETIMEBOUND; /// Try to find the function at the given **virtual** address - std::unique_ptr find_function(uint64_t addr) const; + std::unique_ptr find_function(uint64_t addr) const LIEF_LIFETIMEBOUND; /// Try to find the variable with the given name. This name can be mangled or /// not. - std::unique_ptr find_variable(const std::string& name) const; + std::unique_ptr + find_variable(const std::string& name) const LIEF_LIFETIMEBOUND; /// Try to find the variable at the given **virtual** address - std::unique_ptr find_variable(uint64_t addr) const; + std::unique_ptr find_variable(uint64_t addr) const LIEF_LIFETIMEBOUND; /// Try to find the type with the given name - std::unique_ptr find_type(const std::string& name) const; + std::unique_ptr + find_type(const std::string& name) const LIEF_LIFETIMEBOUND; /// Iterator on the CompilationUnit embedded in this dwarf - compilation_units_it compilation_units() const; + compilation_units_it compilation_units() const LIEF_LIFETIMEBOUND; /// Attempt to resolve the address of the function specified by `name`. optional find_function_address(const std::string& name) const override; diff --git a/deps/LIEF/include/LIEF/DWARF/Editor.hpp b/deps/LIEF/include/LIEF/DWARF/Editor.hpp index 3c63c1383389..e93881878c1f 100644 --- a/deps/LIEF/include/LIEF/DWARF/Editor.hpp +++ b/deps/LIEF/include/LIEF/DWARF/Editor.hpp @@ -1,4 +1,4 @@ -/* Copyright 2022 - 2025 R. Thomas +/* Copyright 2022 - 2026 R. Thomas * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,7 +16,9 @@ #define LIEF_DWARF_EDITOR_H #include #include +#include +#include "LIEF/compiler_attributes.hpp" #include "LIEF/visibility.h" namespace LIEF { @@ -37,11 +39,29 @@ class LIEF_API Editor { Editor() = delete; Editor(std::unique_ptr impl); + enum class FORMAT : uint32_t { + ELF, + MACHO, + PE, + }; + + enum class ARCH : uint32_t { + UNKNOWN, + X64, + X86, + AARCH64, + ARM, + }; + /// Instantiate an editor for the given binary object static std::unique_ptr from_binary(LIEF::Binary& bin); + /// Instantiate an editor for the given format and arch + static std::unique_ptr create(FORMAT fmt, ARCH arch); + /// Create a new compilation unit - std::unique_ptr create_compilation_unit(); + std::unique_ptr + create_compilation_unit() LIEF_LIFETIMEBOUND; /// Write the DWARF file to the specified output void write(const std::string& output); @@ -50,7 +70,6 @@ class LIEF_API Editor { private: std::unique_ptr impl_; - }; } diff --git a/deps/LIEF/include/LIEF/DWARF/Function.hpp b/deps/LIEF/include/LIEF/DWARF/Function.hpp index 495cbadac723..af98098f69ea 100644 --- a/deps/LIEF/include/LIEF/DWARF/Function.hpp +++ b/deps/LIEF/include/LIEF/DWARF/Function.hpp @@ -1,4 +1,4 @@ -/* Copyright 2022 - 2025 R. Thomas +/* Copyright 2022 - 2026 R. Thomas * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,9 +21,12 @@ #include "LIEF/visibility.h" #include "LIEF/errors.hpp" #include "LIEF/iterators.hpp" +#include "LIEF/compiler_attributes.hpp" + #include "LIEF/range.hpp" #include "LIEF/DWARF/Variable.hpp" #include "LIEF/DWARF/Type.hpp" +#include "LIEF/DWARF/LexicalBlock.hpp" #include "LIEF/asm/Instruction.hpp" namespace LIEF { @@ -41,62 +44,53 @@ class FunctionIt; /// `DW_TAG_subprogram` or `DW_TAG_inlined_subroutine`. class LIEF_API Function { public: - class LIEF_API Iterator { + class Iterator final + : public iterator_facade_base { public: - using iterator_category = std::bidirectional_iterator_tag; - using value_type = std::unique_ptr; - using difference_type = std::ptrdiff_t; - using pointer = Function*; - using reference = std::unique_ptr&; using implementation = details::FunctionIt; + using iterator_facade_base::operator++; + using iterator_facade_base::operator--; + + LIEF_API Iterator(); - class LIEF_API PointerProxy { - // Inspired from LLVM's iterator_facade_base - friend class Iterator; - public: - pointer operator->() const { return R.get(); } + LIEF_API Iterator(std::unique_ptr impl); - private: - value_type R; + LIEF_API Iterator(const Iterator&); + LIEF_API Iterator& operator=(const Iterator&); - template - PointerProxy(RefT &&R) : R(std::forward(R)) {} // NOLINT(bugprone-forwarding-reference-overload) - }; + LIEF_API Iterator(Iterator&&) noexcept; + LIEF_API Iterator& operator=(Iterator&&) noexcept; - Iterator(const Iterator&); - Iterator(Iterator&&) noexcept; - Iterator(std::unique_ptr impl); - ~Iterator(); + LIEF_API ~Iterator(); friend LIEF_API bool operator==(const Iterator& LHS, const Iterator& RHS); - friend LIEF_API bool operator!=(const Iterator& LHS, const Iterator& RHS) { + friend bool operator!=(const Iterator& LHS, const Iterator& RHS) { return !(LHS == RHS); } - Iterator& operator++(); - Iterator& operator--(); + // NOLINTNEXTLINE(bugprone-derived-method-shadowing-base-method) + LIEF_API Iterator& operator++(); - Iterator operator--(int) { - Iterator tmp = *static_cast(this); - --*static_cast(this); - return tmp; - } + // NOLINTNEXTLINE(bugprone-derived-method-shadowing-base-method) + LIEF_API Iterator& operator--(); - Iterator operator++(int) { - Iterator tmp = *static_cast(this); - ++*static_cast(this); - return tmp; - } + LIEF_API const Function& operator*() const LIEF_LIFETIMEBOUND; - std::unique_ptr operator*() const; + // NOLINTNEXTLINE(bugprone-derived-method-shadowing-base-method) + LIEF_API const Function* operator->() const LIEF_LIFETIMEBOUND; - PointerProxy operator->() const { - return static_cast(this)->operator*(); - } + /// Transfer ownership of the function at the current position to the + /// caller. Returns `nullptr` if the iterator is past-the-end. + LIEF_API std::unique_ptr yield(); private: + void load() const; + std::unique_ptr impl_; + mutable std::unique_ptr cached_; }; /// Iterator over the variables defined in the scope of this function @@ -104,6 +98,8 @@ class LIEF_API Function { using parameters_t = std::vector>; using thrown_types_t = std::vector>; + using lexical_blocks_it = iterator_range; + using instructions_it = iterator_range; Function(std::unique_ptr impl); @@ -114,7 +110,7 @@ class LIEF_API Function { /// The name of the function which is used for linking (`DW_AT_linkage_name`). /// /// This name differs from name() as it is usually mangled. The function - /// return an empty string if the linkage name is not available. + /// returns an empty string if the linkage name is not available. std::string linkage_name() const; /// Return the address of the function (`DW_AT_entry_pc` or `DW_AT_low_pc`). @@ -123,7 +119,7 @@ class LIEF_API Function { /// Return an iterator of variables (`DW_TAG_variable`) defined within the /// scope of this function. This includes regular stack-based variables as /// well as static ones. - vars_it variables() const; + vars_it variables() const LIEF_LIFETIMEBOUND; /// Whether this function is created by the compiler and not /// present in the original source code @@ -144,10 +140,10 @@ class LIEF_API Function { /// Return the dwarf::Type associated with the **return type** of this /// function - std::unique_ptr type() const; + std::unique_ptr type() const LIEF_LIFETIMEBOUND; /// Return the function's parameters (including any template parameter) - parameters_t parameters() const; + parameters_t parameters() const LIEF_LIFETIMEBOUND; /// List of exceptions (types) that can be thrown by the function. /// @@ -161,16 +157,26 @@ class LIEF_API Function { /// /// thrown_types() returns one element associated with the Type: /// `StatisticsError`. - thrown_types_t thrown_types() const; + thrown_types_t thrown_types() const LIEF_LIFETIMEBOUND; /// Return the scope in which this function is defined - std::unique_ptr scope() const; + std::unique_ptr scope() const LIEF_LIFETIMEBOUND; /// Disassemble the current function by returning an iterator over /// the assembly::Instruction - instructions_it instructions() const; + instructions_it instructions() const LIEF_LIFETIMEBOUND; + + /// Iterator over the LexicalBlock owned by this function + lexical_blocks_it lexical_blocks() const LIEF_LIFETIMEBOUND; + + /// Description (`DW_AT_description`) of this function or an empty string + std::string description() const; + + /// Generates a C/C++ definition for this function + std::string to_decl(const DeclOpt& opt = DeclOpt()) const; ~Function(); + private: std::unique_ptr impl_; }; diff --git a/deps/LIEF/include/LIEF/DWARF/LexicalBlock.hpp b/deps/LIEF/include/LIEF/DWARF/LexicalBlock.hpp new file mode 100644 index 000000000000..8f3ebbdd9b8a --- /dev/null +++ b/deps/LIEF/include/LIEF/DWARF/LexicalBlock.hpp @@ -0,0 +1,135 @@ +/* Copyright 2022 - 2026 R. Thomas + * + * 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 LIEF_DWARF_LEXICAL_BLOCK_H +#define LIEF_DWARF_LEXICAL_BLOCK_H + +#include "LIEF/compiler_attributes.hpp" +#include "LIEF/visibility.h" +#include "LIEF/iterators.hpp" +#include "LIEF/optional.hpp" +#include "LIEF/range.hpp" + +#include +#include +#include + +namespace LIEF { +namespace dwarf { + +namespace details { +class LexicalBlock; +class LexicalBlockIt; +} + +/// This class represents a DWARF lexical block (`DW_TAG_lexical_block`) +class LIEF_API LexicalBlock { + public: + class Iterator final + : public iterator_facade_base { + public: + using implementation = details::LexicalBlockIt; + using iterator_facade_base::operator++; + using iterator_facade_base::operator--; + + LIEF_API Iterator(); + + LIEF_API Iterator(std::unique_ptr impl); + + LIEF_API Iterator(const Iterator&); + LIEF_API Iterator& operator=(const Iterator&); + + LIEF_API Iterator(Iterator&&) noexcept; + LIEF_API Iterator& operator=(Iterator&&) noexcept; + + LIEF_API ~Iterator(); + + friend LIEF_API bool operator==(const Iterator& LHS, const Iterator& RHS); + friend bool operator!=(const Iterator& LHS, const Iterator& RHS) { + return !(LHS == RHS); + } + + // NOLINTNEXTLINE(bugprone-derived-method-shadowing-base-method) + LIEF_API Iterator& operator++(); + + // NOLINTNEXTLINE(bugprone-derived-method-shadowing-base-method) + LIEF_API Iterator& operator--(); + + LIEF_API const LexicalBlock& operator*() const LIEF_LIFETIMEBOUND; + + // NOLINTNEXTLINE(bugprone-derived-method-shadowing-base-method) + LIEF_API const LexicalBlock* operator->() const LIEF_LIFETIMEBOUND; + + /// Transfer ownership of the lexical block at the current position + /// to the caller. Returns `nullptr` if the iterator is past-the-end. + LIEF_API std::unique_ptr yield(); + + private: + void load() const; + + std::unique_ptr impl_; + mutable std::unique_ptr cached_; + }; + + using sub_blocks_it = iterator_range; + + LexicalBlock(std::unique_ptr impl); + LexicalBlock() = delete; + LexicalBlock& operator=(const LexicalBlock&) = delete; + LexicalBlock(const LexicalBlock&) = delete; + + /// Return the *name* associated with this lexical block or an + /// empty string + std::string name() const; + + /// Return the description associated with this lexical block or an + /// empty string + std::string description() const; + + /// Return an iterator over the sub-LexicalBlock owned by this block. + sub_blocks_it sub_blocks() const LIEF_LIFETIMEBOUND; + + /// Return the start address of this block + optional addr() const; + + /// Return the size of this block as the difference of the highest address and + /// the lowest address. + uint64_t size() const; + + /// Return the lowest virtual address owned by this block. + optional low_pc() const; + + /// Return the highest virtual address owned by this block. + optional high_pc() const; + + /// Return a list of address ranges owned by this block. + /// + /// If the lexical block owns a contiguous range, it should return + /// **a single** range. + std::vector ranges() const; + + ~LexicalBlock(); + + LIEF_LOCAL static std::unique_ptr + create(std::unique_ptr impl); + + protected: + std::unique_ptr impl_; +}; + +} +} +#endif diff --git a/deps/LIEF/include/LIEF/DWARF/Parameter.hpp b/deps/LIEF/include/LIEF/DWARF/Parameter.hpp index 9fa7c1211deb..9959987e6742 100644 --- a/deps/LIEF/include/LIEF/DWARF/Parameter.hpp +++ b/deps/LIEF/include/LIEF/DWARF/Parameter.hpp @@ -1,4 +1,4 @@ -/* Copyright 2022 - 2025 R. Thomas +/* Copyright 2022 - 2026 R. Thomas * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,9 +16,11 @@ #define LIEF_DWARF_PARAMETER_H #include "LIEF/visibility.h" +#include "LIEF/compiler_attributes.hpp" #include #include +#include namespace LIEF { namespace dwarf { @@ -41,19 +43,61 @@ class LIEF_API Parameter { TEMPLATE_VALUE, ///< DW_TAG_template_value_parameter FORMAL, ///< DW_TAG_formal_parameter }; + + /// This class exposes information about the location of a parameter + class LIEF_API Location { + public: + enum class Type : uint8_t { + UNKNOWN = 0, + REG, + }; + Location(Type ty) : + type(ty) {} + + template + const T* as() const { + if (T::classof(this)) { + return static_cast(this); + } + return nullptr; + } + + Type type = Type::UNKNOWN; + }; + + /// This class represents a register location + class LIEF_API RegisterLoc : public Location { + public: + RegisterLoc(uint64_t reg_id) : + Location(Type::REG), + id(reg_id) {} + + static bool classof(const Location* loc) { + return loc->type == Type::REG; + } + + /// DWARF id of the register + uint64_t id = 0; + }; + Parameter() = delete; - Parameter(Parameter&& other); - Parameter& operator=(Parameter&& other); + Parameter(Parameter&& other) noexcept; + Parameter& operator=(Parameter&& other) noexcept; Parameter& operator=(const Parameter&) = delete; Parameter(const Parameter&) = delete; + KIND kind() const; /// Name of the parameter std::string name() const; /// Type of this parameter - std::unique_ptr type() const; + std::unique_ptr type() const LIEF_LIFETIMEBOUND; + + /// Location of this parameter. For instance it can be a specific register + /// that is not following the calling convention. + std::unique_ptr location() const LIEF_LIFETIMEBOUND; template const T* as() const { @@ -65,8 +109,8 @@ class LIEF_API Parameter { virtual ~Parameter(); - LIEF_LOCAL static - std::unique_ptr create(std::unique_ptr impl); + LIEF_LOCAL static std::unique_ptr + create(std::unique_ptr impl); protected: Parameter(std::unique_ptr impl); @@ -130,7 +174,7 @@ class LIEF_API TemplateValue : public Parameter { /// /// The function `generic` has one parameters::TemplateType parameter: `Y`. class LIEF_API TemplateType : public Parameter { -public: + public: using Parameter::Parameter; static bool classof(const Parameter* P) { return P->kind() == Parameter::KIND::TEMPLATE_TYPE; diff --git a/deps/LIEF/include/LIEF/DWARF/Scope.hpp b/deps/LIEF/include/LIEF/DWARF/Scope.hpp index 61977c21aec5..dbe5e4321f74 100644 --- a/deps/LIEF/include/LIEF/DWARF/Scope.hpp +++ b/deps/LIEF/include/LIEF/DWARF/Scope.hpp @@ -1,4 +1,4 @@ -/* Copyright 2022 - 2025 R. Thomas +/* Copyright 2022 - 2026 R. Thomas * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -57,6 +57,7 @@ class LIEF_API Scope { std::string chained(const std::string& sep = "::") const; ~Scope(); + private: std::unique_ptr impl_; }; diff --git a/deps/LIEF/include/LIEF/DWARF/Type.hpp b/deps/LIEF/include/LIEF/DWARF/Type.hpp index 9e13e896c0d7..1ef238cf1b60 100644 --- a/deps/LIEF/include/LIEF/DWARF/Type.hpp +++ b/deps/LIEF/include/LIEF/DWARF/Type.hpp @@ -1,4 +1,4 @@ -/* Copyright 2022 - 2025 R. Thomas +/* Copyright 2022 - 2026 R. Thomas * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,10 +17,13 @@ #include +#include "LIEF/compiler_attributes.hpp" +#include "LIEF/iterators.hpp" #include "LIEF/visibility.h" #include "LIEF/errors.hpp" #include "LIEF/debug_loc.hpp" #include "LIEF/canbe_unique.hpp" +#include "LIEF/DebugDeclOpt.hpp" namespace LIEF { namespace dwarf { @@ -63,63 +66,62 @@ class TypeIt; /// - `DW_TAG_volatile_type` class LIEF_API Type { public: - class LIEF_API Iterator { + class Iterator final + : public iterator_facade_base { public: - using iterator_category = std::bidirectional_iterator_tag; - using value_type = std::unique_ptr; - using difference_type = std::ptrdiff_t; - using pointer = Type*; - using reference = std::unique_ptr&; using implementation = details::TypeIt; + using iterator_facade_base::operator++; + using iterator_facade_base::operator--; - class LIEF_API PointerProxy { - // Inspired from LLVM's iterator_facade_base - friend class Iterator; - public: - pointer operator->() const { return R.get(); } + LIEF_API Iterator(); - private: - value_type R; + LIEF_API Iterator(std::unique_ptr impl); - template - PointerProxy(RefT &&R) : R(std::forward(R)) {} // NOLINT(bugprone-forwarding-reference-overload) - }; + LIEF_API Iterator(const Iterator&); + LIEF_API Iterator& operator=(const Iterator&); - Iterator(const Iterator&); - Iterator(Iterator&&) noexcept; - Iterator(std::unique_ptr impl); - ~Iterator(); + LIEF_API Iterator(Iterator&&) noexcept; + LIEF_API Iterator& operator=(Iterator&&) noexcept; + + LIEF_API ~Iterator(); friend LIEF_API bool operator==(const Iterator& LHS, const Iterator& RHS); - friend LIEF_API bool operator!=(const Iterator& LHS, const Iterator& RHS) { + friend bool operator!=(const Iterator& LHS, const Iterator& RHS) { return !(LHS == RHS); } - Iterator& operator++(); - Iterator& operator--(); + // NOLINTNEXTLINE(bugprone-derived-method-shadowing-base-method) + LIEF_API Iterator& operator++(); - Iterator operator--(int) { - Iterator tmp = *static_cast(this); - --*static_cast(this); - return tmp; - } + // NOLINTNEXTLINE(bugprone-derived-method-shadowing-base-method) + LIEF_API Iterator& operator--(); - Iterator operator++(int) { - Iterator tmp = *static_cast(this); - ++*static_cast(this); - return tmp; - } + LIEF_API const Type& operator*() const LIEF_LIFETIMEBOUND; - std::unique_ptr operator*() const; + // NOLINTNEXTLINE(bugprone-derived-method-shadowing-base-method) + LIEF_API const Type* operator->() const LIEF_LIFETIMEBOUND; - PointerProxy operator->() const { - return static_cast(this)->operator*(); - } + /// Transfer ownership of the type at the current position to the + /// caller. Returns `nullptr` if the iterator is past-the-end. + LIEF_API std::unique_ptr yield(); private: + void load() const; + std::unique_ptr impl_; + mutable std::unique_ptr cached_; }; + LIEF_LOCAL Type(std::unique_ptr impl); + LIEF_LOCAL Type(details::Type& impl); + + Type(const Type&) = delete; + Type& operator=(const Type&) = delete; + + Type(Type&&) noexcept; + Type& operator=(Type&&) noexcept; + virtual ~Type(); enum class KIND { @@ -176,6 +178,9 @@ class LIEF_API Type { /// Return the scope in which this type is defined std::unique_ptr scope() const; + /// Generates a C/C++ definition for this type + std::string to_decl(const DeclOpt& opt = DeclOpt()) const; + template const T* as() const { if (T::classof(this)) { @@ -184,12 +189,10 @@ class LIEF_API Type { return nullptr; } - static std::unique_ptr create(std::unique_ptr impl); + static std::unique_ptr + create(std::unique_ptr impl LIEF_LIFETIMEBOUND); protected: - Type(std::unique_ptr impl); - Type(details::Type& impl); - LIEF::details::canbe_unique impl_; }; diff --git a/deps/LIEF/include/LIEF/DWARF/Variable.hpp b/deps/LIEF/include/LIEF/DWARF/Variable.hpp index dd457f45d6ea..6e5d4ef12182 100644 --- a/deps/LIEF/include/LIEF/DWARF/Variable.hpp +++ b/deps/LIEF/include/LIEF/DWARF/Variable.hpp @@ -1,4 +1,4 @@ -/* Copyright 2022 - 2025 R. Thomas +/* Copyright 2022 - 2026 R. Thomas * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,7 +17,9 @@ #include +#include "LIEF/iterators.hpp" #include "LIEF/visibility.h" +#include "LIEF/compiler_attributes.hpp" #include "LIEF/errors.hpp" #include "LIEF/debug_loc.hpp" #include "LIEF/DWARF/Type.hpp" @@ -35,61 +37,52 @@ class VariableIt; /// dwarf::Function or a dwarf::CompilationUnit class LIEF_API Variable { public: - class LIEF_API Iterator { + class Iterator final + : public iterator_facade_base { public: - using iterator_category = std::bidirectional_iterator_tag; - using value_type = std::unique_ptr; - using difference_type = std::ptrdiff_t; - using pointer = Variable*; - using reference = std::unique_ptr&; using implementation = details::VariableIt; + using iterator_facade_base::operator++; + using iterator_facade_base::operator--; - class LIEF_API PointerProxy { - // Inspired from LLVM's iterator_facade_base - friend class Iterator; - public: - pointer operator->() const { return R.get(); } + LIEF_API Iterator(); - private: - value_type R; + LIEF_API Iterator(std::unique_ptr impl); - template - PointerProxy(RefT &&R) : R(std::forward(R)) {} // NOLINT(bugprone-forwarding-reference-overload) - }; + LIEF_API Iterator(const Iterator&); + LIEF_API Iterator& operator=(const Iterator&); - Iterator(const Iterator&); - Iterator(Iterator&&) noexcept; - Iterator(std::unique_ptr impl); - ~Iterator(); + LIEF_API Iterator(Iterator&&) noexcept; + LIEF_API Iterator& operator=(Iterator&&) noexcept; + + LIEF_API ~Iterator(); friend LIEF_API bool operator==(const Iterator& LHS, const Iterator& RHS); - friend LIEF_API bool operator!=(const Iterator& LHS, const Iterator& RHS) { + friend bool operator!=(const Iterator& LHS, const Iterator& RHS) { return !(LHS == RHS); } - Iterator& operator++(); - Iterator& operator--(); + // NOLINTNEXTLINE(bugprone-derived-method-shadowing-base-method) + LIEF_API Iterator& operator++(); - Iterator operator--(int) { - Iterator tmp = *static_cast(this); - --*static_cast(this); - return tmp; - } + // NOLINTNEXTLINE(bugprone-derived-method-shadowing-base-method) + LIEF_API Iterator& operator--(); - Iterator operator++(int) { - Iterator tmp = *static_cast(this); - ++*static_cast(this); - return tmp; - } + LIEF_API const Variable& operator*() const LIEF_LIFETIMEBOUND; - std::unique_ptr operator*() const; + // NOLINTNEXTLINE(bugprone-derived-method-shadowing-base-method) + LIEF_API const Variable* operator->() const LIEF_LIFETIMEBOUND; - PointerProxy operator->() const { - return static_cast(this)->operator*(); - } + /// Transfer ownership of the variable at the current position to the + /// caller. Returns `nullptr` if the iterator is past-the-end. + LIEF_API std::unique_ptr yield(); private: + void load() const; + std::unique_ptr impl_; + mutable std::unique_ptr cached_; }; Variable(std::unique_ptr impl); @@ -100,7 +93,7 @@ class LIEF_API Variable { /// The name of the variable which is used for linking (`DW_AT_linkage_name`). /// /// This name differs from name() as it is usually mangled. The function - /// return an empty string if the linkage name is not available. + /// returns an empty string if the linkage name is not available. std::string linkage_name() const; /// Address of the variable. @@ -122,16 +115,26 @@ class LIEF_API Variable { /// Whether it's a `constexpr` variable bool is_constexpr() const; + /// Whether this variable is allocated on the stack + bool is_stack_based() const; + /// The original source location where the variable is defined. debug_location_t debug_location() const; /// Return the type of this variable - std::unique_ptr type() const; + std::unique_ptr type() const LIEF_LIFETIMEBOUND; /// Return the scope in which this variable is defined - std::unique_ptr scope() const; + std::unique_ptr scope() const LIEF_LIFETIMEBOUND; + + /// Description (`DW_AT_description`) of the variable or an empty string + std::string description() const; + + /// Generates a C/C++ definition for this variable + std::string to_decl(const DeclOpt& opt = DeclOpt()) const; ~Variable(); + private: std::unique_ptr impl_; }; diff --git a/deps/LIEF/include/LIEF/DWARF/editor/ArrayType.hpp b/deps/LIEF/include/LIEF/DWARF/editor/ArrayType.hpp index 2116dd9666e4..edd21ca7b098 100644 --- a/deps/LIEF/include/LIEF/DWARF/editor/ArrayType.hpp +++ b/deps/LIEF/include/LIEF/DWARF/editor/ArrayType.hpp @@ -1,4 +1,4 @@ -/* Copyright 2022 - 2025 R. Thomas +/* Copyright 2022 - 2026 R. Thomas * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,7 +25,11 @@ namespace editor { /// This class represents an array type (`DW_TAG_array_type`). class LIEF_API ArrayType : public Type { public: - using Type::Type; + template::value>::type> + ArrayType(Args&&... args) : + Type(std::forward(args)...) {} static bool classof(const Type* type); diff --git a/deps/LIEF/include/LIEF/DWARF/editor/BaseType.hpp b/deps/LIEF/include/LIEF/DWARF/editor/BaseType.hpp index f06db195b0ae..11b2dd3f026d 100644 --- a/deps/LIEF/include/LIEF/DWARF/editor/BaseType.hpp +++ b/deps/LIEF/include/LIEF/DWARF/editor/BaseType.hpp @@ -1,4 +1,4 @@ -/* Copyright 2022 - 2025 R. Thomas +/* Copyright 2022 - 2026 R. Thomas * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,7 +26,11 @@ namespace editor { /// This class represents a primitive type like `int, char`. class LIEF_API BaseType : public Type { public: - using Type::Type; + template::value>::type> + BaseType(Args&&... args) : + Type(std::forward(args)...) {} enum class ENCODING : uint32_t { NONE = 0, @@ -36,7 +40,7 @@ class LIEF_API BaseType : public Type { UNSIGNED, UNSIGNED_CHAR, BOOLEAN, - FLOAT + FLOAT, }; static bool classof(const Type* type); diff --git a/deps/LIEF/include/LIEF/DWARF/editor/CompilationUnit.hpp b/deps/LIEF/include/LIEF/DWARF/editor/CompilationUnit.hpp index b6b00714d0de..cabab90828da 100644 --- a/deps/LIEF/include/LIEF/DWARF/editor/CompilationUnit.hpp +++ b/deps/LIEF/include/LIEF/DWARF/editor/CompilationUnit.hpp @@ -1,4 +1,4 @@ -/* Copyright 2022 - 2025 R. Thomas +/* Copyright 2022 - 2026 R. Thomas * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,6 +18,8 @@ #include #include "LIEF/visibility.h" +#include "LIEF/compiler_attributes.hpp" + #include "LIEF/DWARF/editor/StructType.hpp" #include "LIEF/DWARF/editor/BaseType.hpp" #include "LIEF/DWARF/editor/FunctionType.hpp" @@ -47,46 +49,57 @@ class LIEF_API CompilationUnit { /// /// This attribute aims to inform about the program that generated this /// compilation unit (e.g. `LIEF Extended`) - CompilationUnit& set_producer(const std::string& producer); + CompilationUnit& set_producer(const std::string& producer) LIEF_LIFETIMEBOUND; /// Create a new function owned by this compilation unit - std::unique_ptr create_function(const std::string& name); + std::unique_ptr + create_function(const std::string& name) LIEF_LIFETIMEBOUND; /// Create a new **global** variable owned by this compilation unit - std::unique_ptr create_variable(const std::string& name); + std::unique_ptr + create_variable(const std::string& name) LIEF_LIFETIMEBOUND; /// Create a `DW_TAG_unspecified_type` type with the given name - std::unique_ptr create_generic_type(const std::string& name); + std::unique_ptr + create_generic_type(const std::string& name) LIEF_LIFETIMEBOUND; /// Create an enum type (`DW_TAG_enumeration_type`) - std::unique_ptr create_enum(const std::string& name); + std::unique_ptr + create_enum(const std::string& name) LIEF_LIFETIMEBOUND; - /// Create a typdef with the name provided in the first parameter which aliases + /// Create a typedef with the name provided in the first parameter which aliases /// the type provided in the second parameter - std::unique_ptr create_typedef(const std::string& name, const Type& type); + std::unique_ptr create_typedef(const std::string& name, + const Type& type) LIEF_LIFETIMEBOUND; /// Create a struct-like type (struct, class, union) with the given name. std::unique_ptr create_structure( - const std::string& name, StructType::TYPE kind = StructType::TYPE::STRUCT); + const std::string& name, StructType::TYPE kind = StructType::TYPE::STRUCT + ) LIEF_LIFETIMEBOUND; /// Create a primitive type with the given name and size. - std::unique_ptr create_base_type(const std::string& name, size_t size, - BaseType::ENCODING encoding = BaseType::ENCODING::NONE); + std::unique_ptr create_base_type( + const std::string& name, size_t size, + BaseType::ENCODING encoding = BaseType::ENCODING::NONE + ) LIEF_LIFETIMEBOUND; /// Create a function type with the given name. - std::unique_ptr create_function_type(const std::string& name); + std::unique_ptr + create_function_type(const std::string& name) LIEF_LIFETIMEBOUND; /// Create a pointer on the provided type - std::unique_ptr create_pointer_type(const Type& ty) { + std::unique_ptr + create_pointer_type(const Type& ty) LIEF_LIFETIMEBOUND { return ty.pointer_to(); } /// Create a `void` type - std::unique_ptr create_void_type(); + std::unique_ptr create_void_type() LIEF_LIFETIMEBOUND; /// Create an array type with the given name, type and size. - std::unique_ptr - create_array(const std::string& name, const Type& type, size_t count); + std::unique_ptr create_array(const std::string& name, + const Type& type, + size_t count) LIEF_LIFETIMEBOUND; ~CompilationUnit(); diff --git a/deps/LIEF/include/LIEF/DWARF/editor/EnumType.hpp b/deps/LIEF/include/LIEF/DWARF/editor/EnumType.hpp index 90d76fa0e91a..9eda1e305b10 100644 --- a/deps/LIEF/include/LIEF/DWARF/editor/EnumType.hpp +++ b/deps/LIEF/include/LIEF/DWARF/editor/EnumType.hpp @@ -1,4 +1,4 @@ -/* Copyright 2022 - 2025 R. Thomas +/* Copyright 2022 - 2026 R. Thomas * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,6 +17,7 @@ #include #include +#include "LIEF/compiler_attributes.hpp" #include "LIEF/visibility.h" #include "LIEF/DWARF/editor/Type.hpp" @@ -31,7 +32,11 @@ class EnumValue; /// This class represents an editable enum type (`DW_TAG_enumeration_type`) class LIEF_API EnumType : public Type { public: - using Type::Type; + template::value>::type> + EnumType(Args&&... args) : + Type(std::forward(args)...) {} /// This class represents an enum value class LIEF_API Value { @@ -40,16 +45,21 @@ class LIEF_API EnumType : public Type { Value(std::unique_ptr impl); ~Value(); + private: std::unique_ptr impl_; }; /// Define the number of bytes required to hold an instance of the /// enumeration (`DW_AT_byte_size`). - EnumType& set_size(uint64_t size); + EnumType& set_size(uint64_t size) LIEF_LIFETIMEBOUND; + + /// Set the underlying type that is used to encode this enum + EnumType& set_underlying_type(const Type& type) LIEF_LIFETIMEBOUND; /// Add an enum value by specifying its name and its integer value - std::unique_ptr add_value(const std::string& name, int64_t value); + std::unique_ptr add_value(const std::string& name, + int64_t value) LIEF_LIFETIMEBOUND; static bool classof(const Type* type); diff --git a/deps/LIEF/include/LIEF/DWARF/editor/Function.hpp b/deps/LIEF/include/LIEF/DWARF/editor/Function.hpp index e91f64139c05..4c341a1d5cfe 100644 --- a/deps/LIEF/include/LIEF/DWARF/editor/Function.hpp +++ b/deps/LIEF/include/LIEF/DWARF/editor/Function.hpp @@ -1,4 +1,4 @@ -/* Copyright 2022 - 2025 R. Thomas +/* Copyright 2022 - 2026 R. Thomas * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,6 +19,7 @@ #include #include +#include "LIEF/compiler_attributes.hpp" #include "LIEF/visibility.h" namespace LIEF { @@ -40,19 +41,27 @@ class LIEF_API Function { struct LIEF_API range_t { range_t() = default; range_t(uint64_t start, uint64_t end) : - start(start), end(end) - {} + start(start), + end(end) {} uint64_t start = 0; uint64_t end = 0; }; - /// This class represents a parameter of the current function (`DW_TAG_formal_parameter`) + /// This class represents a parameter of the current function + /// (`DW_TAG_formal_parameter`) class LIEF_API Parameter { public: Parameter() = delete; Parameter(std::unique_ptr impl); ~Parameter(); + + /// Assign this parameter to a specific named register. + Parameter& assign_register(const std::string& name) LIEF_LIFETIMEBOUND; + + /// Assign this parameter to the given DWARF register id (e.g. `DW_OP_reg0`). + Parameter& assign_register(uint64_t reg) LIEF_LIFETIMEBOUND; + private: std::unique_ptr impl_; }; @@ -63,7 +72,24 @@ class LIEF_API Function { LexicalBlock() = delete; LexicalBlock(std::unique_ptr impl); + /// Create a sub-block with the given low/high addresses. + std::unique_ptr add_block(uint64_t start, + uint64_t end) LIEF_LIFETIMEBOUND; + + /// Create a sub-block with the given range of addresses. + std::unique_ptr + add_block(const std::vector& range) LIEF_LIFETIMEBOUND; + + /// Create a `DW_AT_description` entry with the description + /// provided in parameter. + LexicalBlock& + add_description(const std::string& description) LIEF_LIFETIMEBOUND; + + /// Create a `DW_AT_name` entry to associate a name to this entry + LexicalBlock& add_name(const std::string& name) LIEF_LIFETIMEBOUND; + ~LexicalBlock(); + private: std::unique_ptr impl_; }; @@ -75,6 +101,7 @@ class LIEF_API Function { Label(std::unique_ptr impl); ~Label(); + private: std::unique_ptr impl_; }; @@ -83,39 +110,47 @@ class LIEF_API Function { Function(std::unique_ptr impl); /// Set the address of this function by defining `DW_AT_entry_pc` - Function& set_address(uint64_t addr); + Function& set_address(uint64_t addr) LIEF_LIFETIMEBOUND; /// Set the upper and lower bound addresses for this function. This assumes /// that the function is contiguous between `low` and `high`. /// /// Underneath, the function defines `DW_AT_low_pc` and `DW_AT_high_pc` - Function& set_low_high(uint64_t low, uint64_t high); + Function& set_low_high(uint64_t low, uint64_t high) LIEF_LIFETIMEBOUND; /// Set the ranges of addresses owned by the implementation of this function /// by setting the `DW_AT_ranges` attribute. /// - /// This setter should be used for non-contiguous function. - Function& set_ranges(const std::vector& ranges); + /// This setter should be used for non-contiguous functions. + Function& set_ranges(const std::vector& ranges) LIEF_LIFETIMEBOUND; /// Set the function as external by defining `DW_AT_external` to true. /// This means that the function is **imported** by the current compilation /// unit. - Function& set_external(); + Function& set_external() LIEF_LIFETIMEBOUND; /// Set the return type of this function - Function& set_return_type(const Type& type); + Function& set_return_type(const Type& type) LIEF_LIFETIMEBOUND; /// Add a parameter to the current function - std::unique_ptr add_parameter(const std::string& name, const Type& type); + std::unique_ptr add_parameter(const std::string& name, + const Type& type) LIEF_LIFETIMEBOUND; /// Create a stack-based variable owned by the current function - std::unique_ptr create_stack_variable(const std::string& name); + std::unique_ptr + create_stack_variable(const std::string& name) LIEF_LIFETIMEBOUND; /// Add a lexical block with the given range - std::unique_ptr add_lexical_block(uint64_t start, uint64_t end); + std::unique_ptr add_lexical_block(uint64_t start, + uint64_t end) LIEF_LIFETIMEBOUND; /// Add a label at the given address - std::unique_ptr