diff --git a/.configurations/configuration.dsc.yaml b/.configurations/configuration.dsc.yaml index f428817fea4ddb..9e38aaba78a412 100644 --- a/.configurations/configuration.dsc.yaml +++ b/.configurations/configuration.dsc.yaml @@ -5,11 +5,11 @@ properties: - resource: Microsoft.WinGet.DSC/WinGetPackage id: pythonPackage directives: - description: Install Python 3.12 + description: Install Python 3.14 module: Microsoft.WinGet.DSC allowPrerelease: true settings: - id: Python.Python.3.12 + id: Python.Python.3.14 source: winget - resource: Microsoft.WinGet.DSC/WinGetPackage id: vsPackage @@ -51,4 +51,4 @@ properties: settings: id: Nasm.Nasm source: winget - configurationVersion: 0.1.0 + configurationVersion: 0.1.1 diff --git a/.configurations/configuration.vsEnterprise.dsc.yaml b/.configurations/configuration.vsEnterprise.dsc.yaml index 48ba6bb0354669..4faf7d77d371d6 100644 --- a/.configurations/configuration.vsEnterprise.dsc.yaml +++ b/.configurations/configuration.vsEnterprise.dsc.yaml @@ -5,11 +5,11 @@ properties: - resource: Microsoft.WinGet.DSC/WinGetPackage id: pythonPackage directives: - description: Install Python 3.12 + description: Install Python 3.14 module: Microsoft.WinGet.DSC allowPrerelease: true settings: - id: Python.Python.3.12 + id: Python.Python.3.14 source: winget - resource: Microsoft.WinGet.DSC/WinGetPackage id: vsPackage @@ -51,4 +51,4 @@ properties: settings: id: Nasm.Nasm source: winget - configurationVersion: 0.1.0 + configurationVersion: 0.1.1 diff --git a/.configurations/configuration.vsProfessional.dsc.yaml b/.configurations/configuration.vsProfessional.dsc.yaml index 7c2c58bc0155e2..e094059e826c0e 100644 --- a/.configurations/configuration.vsProfessional.dsc.yaml +++ b/.configurations/configuration.vsProfessional.dsc.yaml @@ -5,11 +5,11 @@ properties: - resource: Microsoft.WinGet.DSC/WinGetPackage id: pythonPackage directives: - description: Install Python 3.12 + description: Install Python 3.14 module: Microsoft.WinGet.DSC allowPrerelease: true settings: - id: Python.Python.3.12 + id: Python.Python.3.14 source: winget - resource: Microsoft.WinGet.DSC/WinGetPackage id: vsPackage @@ -51,4 +51,4 @@ properties: settings: id: Nasm.Nasm source: winget - configurationVersion: 0.1.0 + configurationVersion: 0.1.1 diff --git a/.devcontainer/base/devcontainer.json b/.devcontainer/base/devcontainer.json index 9d14ab87572bea..083123eccacaa4 100644 --- a/.devcontainer/base/devcontainer.json +++ b/.devcontainer/base/devcontainer.json @@ -7,5 +7,6 @@ "mounts": [ "source=node-devcontainer-cache,target=/home/developer/nodejs/node/out,type=volume" ], - "postCreateCommand": "git restore-mtime" + "postCreateCommand": "git restore-mtime", + "postStartCommand": "cp /home/developer/envrc/static-libs.envrc /home/developer/nodejs/node/.envrc && direnv allow /home/developer/nodejs/node" } diff --git a/.gitattributes b/.gitattributes index bbfe62e6a034fd..36b6c2b11d095b 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,5 +1,7 @@ test/fixtures/* -text vcbuild.bat text eol=crlf +# disable eol conversion in vendored files. +deps/crates/vendor/**/* -text deps/npm/bin/npm text eol=lf deps/npm/bin/npx text eol=lf deps/corepack/shims/corepack text eol=lf diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 0164937307a770..6f2749a758891e 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -153,6 +153,7 @@ /test/parallel/test-runner-* @nodejs/test_runner # Single Executable Applications +/deps/LIEF @nodejs/single-executable /deps/postject @nodejs/single-executable /doc/api/single-executable-applications.md @nodejs/single-executable /doc/contributing/maintaining/maintaining-single-executable-application-support.md @nodejs/single-executable @@ -160,6 +161,7 @@ /test/fixtures/postject-copy @nodejs/single-executable /test/sea @nodejs/single-executable /tools/dep_updaters/update-postject.sh @nodejs/single-executable +/tools/dep_updaters/update-lief.sh @nodejs/single-executable # Permission Model /doc/api/permissions.md @nodejs/security-wg diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 0ec17d486e7712..dc01fd3fdac591 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -5,10 +5,10 @@ contact_links: about: Please file an issue in our help repo. - name: 📦 Have an issue with npm? url: https://github.com/npm/cli/issues - about: npm has a seperate issue tracker. + about: npm has a separate issue tracker. - name: 📡 Have an issue with undici? (`WebSocket`, `fetch`, etc.) url: https://github.com/nodejs/undici/issues - about: Undici has a seperate issue tracker. + about: Undici has a separate issue tracker. - name: 🌐 Found a problem with nodejs.org beyond the API reference docs? url: https://github.com/nodejs/nodejs.org/issues/new/choose about: Please file an issue in the Node.js website repo. diff --git a/.github/label-pr-config.yml b/.github/label-pr-config.yml index 0b94dd5755d7d6..4ff8bee4c56d64 100644 --- a/.github/label-pr-config.yml +++ b/.github/label-pr-config.yml @@ -80,7 +80,7 @@ subSystemLabels: /^deps\/v8\/tools\/gen-postmortem-metadata\.py/: v8 engine, python, post-mortem /^deps\/v8\//: v8 engine /^deps\/uvwasi\//: wasi - /^deps\/npm\//: npm, fast-track + /^deps\/npm\//: npm /^deps\/nghttp2\/nghttp2\.gyp/: build, http2 /^deps\/nghttp2\//: http2 /^deps\/ngtcp2\//: quic @@ -100,11 +100,13 @@ subSystemLabels: /^lib\/.*http2/: http2 /^lib\/worker_threads.js$/: worker /^lib\/test.js$/: test_runner + /^lib\/v8.js$/: v8 module /^lib\/internal\/url\.js$/: whatwg-url /^lib\/internal\/modules\/esm/: esm /^lib\/internal\/modules/: module /^lib\/internal\/webstreams/: web streams /^lib\/internal\/test_runner/: test_runner + /^lib\/internal\/v8\//: v8 module # All other lib/ files map directly /^lib\/_(\w+)_\w+\.js?$/: $1 # e.g. _(stream)_wrap diff --git a/.github/workflows/lint-release-proposal.yml b/.github/workflows/lint-release-proposal.yml index dbd8232fa40280..3ca5c5ce4f5ea5 100644 --- a/.github/workflows/lint-release-proposal.yml +++ b/.github/workflows/lint-release-proposal.yml @@ -26,6 +26,7 @@ jobs: - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: persist-credentials: false + fetch-depth: 2 - name: Lint release commit title format run: | EXPECTED_TITLE='^[[:digit:]]{4}-[[:digit:]]{2}-[[:digit:]]{2}, Version [[:digit:]]+\.[[:digit:]]+\.[[:digit:]]+ (\(Current|'.+' \(LTS)\)$' @@ -51,6 +52,29 @@ jobs: - name: Verify it's release-ready run: | SKIP_XZ=1 make release-only + - name: Lint release commit content + run: | + MAJOR="$(awk '/^#define NODE_MAJOR_VERSION / { print $3 }' src/node_version.h)" + + echo "Checking for expected files in the release commit:" + missing_expected= + for expected in CHANGELOG.md src/node_version.h doc/changelogs/; do + if git diff --exit-code --quiet --diff-filter=M HEAD^ -- "$expected"; then + echo "Missing expected file in diff: $expected" + missing_expected=1 + fi + done + [ -z "$missing_expected" ] || exit 1 + + echo "Checking for unexpected files in the release commit:" + set -ex + [ -z "$(git diff-tree --no-commit-id --name-only -r HEAD --\ + . \ + ':(exclude)CHANGELOG.md' \ + ':(exclude)src/node_version.h' \ + ':(exclude)test/parallel/test-process-release.js' \ + ':(exclude)doc/api/' \ + ":(exclude)doc/changelogs/CHANGELOG_V$MAJOR.md")" ] - name: Validate CHANGELOG id: releaser-info run: | diff --git a/.github/workflows/linters.yml b/.github/workflows/linters.yml index ea8805083d4d83..2d0c8b4ff39ef1 100644 --- a/.github/workflows/linters.yml +++ b/.github/workflows/linters.yml @@ -153,7 +153,7 @@ jobs: - name: Lint Nix files run: | nix-shell -I nixpkgs=./tools/nix/pkgs.nix -p 'nixfmt-tree' --run ' - treefmt --quiet --fail-on-change + treefmt --quiet --ci ' || git --no-pager diff --exit-code lint-py: diff --git a/.github/workflows/test-shared.yml b/.github/workflows/test-shared.yml index 9ac028af6e6fa2..310640538414ab 100644 --- a/.github/workflows/test-shared.yml +++ b/.github/workflows/test-shared.yml @@ -23,6 +23,7 @@ on: - deps/icu-small/** - deps/icu-tmp/** - deps/llhttp/** + - deps/nbytes/** - deps/nghttp2/** - deps/ngtcp2/** - deps/openssl/*/** @@ -71,6 +72,7 @@ on: - deps/icu-small/** - deps/icu-tmp/** - deps/llhttp/** + - deps/nbytes/** - deps/nghttp2/** - deps/ngtcp2/** - deps/openssl/*/** diff --git a/.gitignore b/.gitignore index bf839aa91c86e1..d283bce868da6c 100644 --- a/.gitignore +++ b/.gitignore @@ -144,6 +144,9 @@ tools/*/*.i.tmp /deps/**/.github/ # Ignore dependencies fetched by tools/v8/fetch_deps.py /deps/.cipd +!deps/LIEF/** +deps/LIEF/*.vcxproj* +deps/LIEF/*.sln # === Rules for Windows vcbuild.bat === /temp-vcbuild diff --git a/BUILDING.md b/BUILDING.md index 5428449b453127..8d0d7807e24090 100644 --- a/BUILDING.md +++ b/BUILDING.md @@ -222,9 +222,9 @@ Supported platforms and toolchains change with each major version of Node.js. This document is only valid for the current major version of Node.js. Consult previous versions of this document for older versions of Node.js: -* [Node.js 21](https://github.com/nodejs/node/blob/v21.x/BUILDING.md) +* [Node.js 24](https://github.com/nodejs/node/blob/v24.x/BUILDING.md) +* [Node.js 22](https://github.com/nodejs/node/blob/v22.x/BUILDING.md) * [Node.js 20](https://github.com/nodejs/node/blob/v20.x/BUILDING.md) -* [Node.js 18](https://github.com/nodejs/node/blob/v18.x/BUILDING.md) ## Building Node.js on supported platforms @@ -735,13 +735,13 @@ Refs: ##### Option 1: Manual install -* The current [version of Python][Python versions] from the - [Microsoft Store](https://apps.microsoft.com/store/search?publisher=Python+Software+Foundation) +* The current [version of Python][Python downloads] by following the instructions in + [Using Python on Windows][]. * The "Desktop development with C++" workload from [Visual Studio 2022 (17.13 or newer)](https://visualstudio.microsoft.com/downloads/) or the "C++ build tools" workload from the [Build Tools](https://aka.ms/vs/17/release/vs_buildtools.exe), - with the default optional components. Starting with Node.js v24, ClangCL is required to compile + with the default optional components. As of Node.js 24.0.0, ClangCL is required to compile on Windows. To enable it, two additional components are needed: * C++ Clang Compiler for Windows (Microsoft.VisualStudio.Component.VC.Llvm.Clang) * MSBuild support for LLVM toolset (Microsoft.VisualStudio.Component.VC.Llvm.ClangToolset) @@ -780,25 +780,17 @@ easily. These files will install the following [WinGet](https://learn.microsoft.com/en-us/windows/package-manager/winget/) packages: * Git for Windows with the `git` and Unix tools added to the `PATH` -* `Python 3.12` +* `Python 3.14` * `Visual Studio 2022` (Community, Enterprise or Professional) * `Visual Studio 2022 Build Tools` with Visual C++ workload, Clang and ClangToolset * `NetWide Assembler` -To install Node.js prerequisites from Powershell Terminal: +To install Node.js prerequisites from PowerShell Terminal: ```powershell winget configure .\.configurations\configuration.dsc.yaml ``` -Alternatively, you can use [Dev Home](https://learn.microsoft.com/en-us/windows/dev-home/) -to install the prerequisites: - -* Switch to `Machine Configuration` tab -* Click on `Configuration File` -* Choose the corresponding WinGet configuration file -* Click on `Set up as admin` - ##### Option 3: Automated install with Boxstarter A [Boxstarter](https://boxstarter.org/) script can be used for easy setup of @@ -1136,4 +1128,6 @@ by opening a pull request against the registry available at [AIX toolbox]: https://www.ibm.com/support/pages/aix-toolbox-open-source-software-overview [Developer Mode]: https://learn.microsoft.com/en-us/windows/advanced-settings/developer-mode +[Python downloads]: https://www.python.org/downloads/ [Python versions]: https://devguide.python.org/versions/ +[Using Python on Windows]: https://docs.python.org/3/using/windows.html diff --git a/CHANGELOG.md b/CHANGELOG.md index 508885ce927086..d3de0845b3d39b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -41,7 +41,8 @@ release. -25.4.0
+25.5.0
+25.4.0
25.3.0
25.2.1
25.2.0
diff --git a/LICENSE b/LICENSE index 8090eacac19436..9901165e6892ce 100644 --- a/LICENSE +++ b/LICENSE @@ -899,6 +899,32 @@ The externally maintained libraries used by Node.js are: written prior permission. M.I.T. makes no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. + + ---------------------------------------------------------------------- + + File: sorttable.js (only for ICU4J) + + The MIT Licence, for code from kryogenix.org + + Code downloaded from the Browser Experiments section of kryogenix.org is + licenced under the so-called MIT licence. The licence is below. + + Copyright (c) 1997-date Stuart Langridge + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. """ - libuv, located at deps/uv, is licensed as follows: @@ -960,6 +986,212 @@ The externally maintained libraries used by Node.js are: license. """ +- LIEF, located at deps/LIEF, is licensed as follows: + """ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2017 - 2025 R. Thomas + Copyright 2017 - 2025 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. + """ + - llhttp, located at deps/llhttp, is licensed as follows: """ This software is licensed under the MIT License. @@ -1022,7 +1254,8 @@ The externally maintained libraries used by Node.js are: SOFTWARE. """ -- postject, located at test/fixtures/postject-copy, is licensed as follows: +- postject, located at test/fixtures/postject-copy and used as a basis for + src/node_sea_bin.cc, is licensed as follows: """ Postject is licensed for use as follows: diff --git a/Makefile b/Makefile index 5afee2318c9bca..71f12062dd92e9 100644 --- a/Makefile +++ b/Makefile @@ -301,7 +301,6 @@ coverage-report-js: ## Report JavaScript coverage results. cctest: all ## Run the C++ tests using the built `cctest` executable. @out/$(BUILDTYPE)/$@ --gtest_filter=$(GTEST_FILTER) - '$(OUT_NODE)' ./test/embedding/test-embedding.js .PHONY: list-gtests list-gtests: ## List all available C++ gtests. @@ -571,7 +570,7 @@ test-all-suites: | clear-stalled test-build bench-addons-build doc-only ## Run a $(PYTHON) tools/test.py $(PARALLEL_ARGS) --mode=$(BUILDTYPE_LOWER) test/* JS_SUITES ?= default -NATIVE_SUITES ?= addons js-native-api node-api +NATIVE_SUITES ?= addons js-native-api node-api embedding # CI_* variables should be kept synchronized with the ones in vcbuild.bat CI_NATIVE_SUITES ?= $(NATIVE_SUITES) benchmark CI_JS_SUITES ?= $(JS_SUITES) pummel @@ -613,7 +612,6 @@ test-ci: | clear-stalled bench-addons-build build-addons build-js-native-api-tes $(PYTHON) tools/test.py $(PARALLEL_ARGS) -p tap --logfile test.tap \ --mode=$(BUILDTYPE_LOWER) --flaky-tests=$(FLAKY_TESTS) \ $(TEST_CI_ARGS) $(CI_JS_SUITES) $(CI_NATIVE_SUITES) $(CI_DOC) - '$(OUT_NODE)' ./test/embedding/test-embedding.js $(info Clean up any leftover processes, error if found.) ps awwx | grep Release/node | grep -v grep | cat @PS_OUT=`ps awwx | grep Release/node | grep -v grep | awk '{print $$1}'`; \ @@ -1242,6 +1240,7 @@ ifeq ($(SKIP_SHARED_DEPS), 1) $(RM) -r $(TARNAME)/deps/icu-small $(RM) -r $(TARNAME)/deps/icu-tmp $(RM) -r $(TARNAME)/deps/llhttp + $(RM) -r $(TARNAME)/deps/nbytes $(RM) -r $(TARNAME)/deps/nghttp2 $(RM) -r $(TARNAME)/deps/ngtcp2 find $(TARNAME)/deps/openssl -maxdepth 1 -type f ! -name 'nodejs-openssl.cnf' -exec $(RM) {} + diff --git a/README.md b/README.md index a7ea15defe7152..b3c620e91ce14b 100644 --- a/README.md +++ b/README.md @@ -453,6 +453,8 @@ For information about the governance of the Node.js project, see **Vladimir Morozov** <> (he/him) * [VoltrexKeyva](https://github.com/VoltrexKeyva) - **Mohammed Keyvanzadeh** <> (he/him) +* [watilde](https://github.com/watilde) - + **Daijiro Wachi** <> (he/him) * [zcbenz](https://github.com/zcbenz) - **Cheng Zhao** <> (he/him) * [ZYSzys](https://github.com/ZYSzys) - @@ -717,8 +719,6 @@ For information about the governance of the Node.js project, see **Vladimir Kurchatkin** <> * [vsemozhetbyt](https://github.com/vsemozhetbyt) - **Vse Mozhet Byt** <> (he/him) -* [watilde](https://github.com/watilde) - - **Daijiro Wachi** <> (he/him) * [watson](https://github.com/watson) - **Thomas Watson** <> * [whitlockjc](https://github.com/whitlockjc) - @@ -889,15 +889,15 @@ releases on a rotation basis as outlined in the * [bengl](https://github.com/bengl) - **Bryan English** <> (he/him) * [HeroDevs](https://www.herodevs.com/) - * [marco-ippolito](https://github.com/marco-ippolito) - + * [marco-ippolito](https://github.com/marco-ippolito) - OpenJSF handle: `Marco Ippolito` **Marco Ippolito** <> (he/him) * [NodeSource](https://nodesource.com/) * [juanarbol](https://github.com/juanarbol) - **Juan José Arboleda** <> (he/him) - * [RafaelGSS](https://github.com/RafaelGSS) - + * [RafaelGSS](https://github.com/RafaelGSS) - OpenJSF handle: `RafaelGSS` **Rafael Gonzaga** <> (he/him) * [Platformatic](https://platformatic.dev/) - * [mcollina](https://github.com/mcollina) - + * [mcollina](https://github.com/mcollina) - OpenJSF handle: `mcollina` **Matteo Collina** <> (he/him) * [Red Hat](https://redhat.com) / [IBM](https://ibm.com) * [joesepi](https://github.com/joesepi) - diff --git a/SECURITY.md b/SECURITY.md index 2270a0161feb89..5a90b8ff41d072 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -348,6 +348,21 @@ Security notifications will be distributed via the following methods. * * +### CVE publication timeline + +When security releases are published, there is a built-in delay before the +corresponding CVEs are publicly disclosed. This delay occurs because: + +1. After the security release, we request the vulnerability reporter to disclose + the details on HackerOne. +2. If the reporter does not disclose within one day, we proceed with forced + disclosure to publish the CVEs. +3. The disclosure then goes through HackerOne's approval process before the CVEs + become publicly available. + +As a result, CVEs may not be immediately available when security releases are +published, but will typically be disclosed within a few days of the release. + ## Comments on this policy If you have suggestions on how this process could be improved, please visit diff --git a/android-patches/trap-handler.h.patch b/android-patches/trap-handler.h.patch index f4f151f65261f1..6974259ffb8d7e 100644 --- a/android-patches/trap-handler.h.patch +++ b/android-patches/trap-handler.h.patch @@ -1,26 +1,47 @@ ---- trap-handler.h 2022-08-11 09:01:23.384000000 +0800 -+++ fixed-trap-handler.h 2022-08-11 09:09:15.352000000 +0800 -@@ -17,23 +17,7 @@ - namespace internal { - namespace trap_handler { - +--- trap-handler.h ++++ fixed-trap-handler.h +@@ -18,43 +18,1 @@ -// X64 on Linux, Windows, MacOS, FreeBSD. -#if V8_HOST_ARCH_X64 && V8_TARGET_ARCH_X64 && \ - ((V8_OS_LINUX && !V8_OS_ANDROID) || V8_OS_WIN || V8_OS_DARWIN || \ - V8_OS_FREEBSD) -#define V8_TRAP_HANDLER_SUPPORTED true --// Arm64 (non-simulator) on Mac. --#elif V8_TARGET_ARCH_ARM64 && V8_HOST_ARCH_ARM64 && V8_OS_DARWIN +-// Arm64 native on Linux, Windows, MacOS. +-#elif V8_TARGET_ARCH_ARM64 && V8_HOST_ARCH_ARM64 && \ +- ((V8_OS_LINUX && !V8_OS_ANDROID) || V8_OS_WIN || V8_OS_DARWIN) -#define V8_TRAP_HANDLER_SUPPORTED true +-// For Linux and Mac, enable the simulator when it's been requested. +-#if USE_SIMULATOR && ((V8_OS_LINUX && !V8_OS_ANDROID) || V8_OS_DARWIN) +-#define V8_TRAP_HANDLER_VIA_SIMULATOR +-#endif -// Arm64 simulator on x64 on Linux, Mac, or Windows. +-// +-// The simulator case uses some inline assembly code, which cannot be +-// compiled with MSVC, so don't enable the trap handler in that case. +-// (MSVC #defines _MSC_VER, but so does Clang when targeting Windows, hence +-// the check for __clang__.) -#elif V8_TARGET_ARCH_ARM64 && V8_HOST_ARCH_X64 && \ -- (V8_OS_LINUX || V8_OS_DARWIN) +- (V8_OS_LINUX || V8_OS_DARWIN || V8_OS_WIN) && \ +- (!defined(_MSC_VER) || defined(__clang__)) +-#define V8_TRAP_HANDLER_VIA_SIMULATOR +-#define V8_TRAP_HANDLER_SUPPORTED true +-// Loong64 (non-simulator) on Linux. +-#elif V8_TARGET_ARCH_LOONG64 && V8_HOST_ARCH_LOONG64 && V8_OS_LINUX +-#define V8_TRAP_HANDLER_SUPPORTED true +-// Loong64 simulator on x64 on Linux +-#elif V8_TARGET_ARCH_LOONG64 && V8_HOST_ARCH_X64 && V8_OS_LINUX +-#define V8_TRAP_HANDLER_VIA_SIMULATOR +-#define V8_TRAP_HANDLER_SUPPORTED true +-// RISCV64 (non-simulator) on Linux. +-#elif V8_TARGET_ARCH_RISCV64 && V8_HOST_ARCH_RISCV64 && V8_OS_LINUX && \ +- !V8_OS_ANDROID +-#define V8_TRAP_HANDLER_SUPPORTED true +-// RISCV64 simulator on x64 on Linux +-#elif V8_TARGET_ARCH_RISCV64 && V8_HOST_ARCH_X64 && V8_OS_LINUX -#define V8_TRAP_HANDLER_VIA_SIMULATOR -#define V8_TRAP_HANDLER_SUPPORTED true -// Everything else is unsupported. -#else - #define V8_TRAP_HANDLER_SUPPORTED false +-#define V8_TRAP_HANDLER_SUPPORTED false -#endif - - // Setup for shared library export. - #if defined(BUILDING_V8_SHARED) && defined(V8_OS_WIN) \ No newline at end of file ++#define V8_TRAP_HANDLER_SUPPORTED false diff --git a/benchmark/napi/create_object_with_properties/binding.cc b/benchmark/napi/create_object_with_properties/binding.cc index d7fae01d1659f9..fda692395b7488 100644 --- a/benchmark/napi/create_object_with_properties/binding.cc +++ b/benchmark/napi/create_object_with_properties/binding.cc @@ -58,7 +58,7 @@ static napi_value CreateObjectWithPropertiesNew(napi_env env, for (uint32_t i = 0; i < params.count; i++) { napi_value obj; - napi_create_object_with_properties( + node_api_create_object_with_properties( env, null_prototype, global_names, global_values, 20, &obj); } diff --git a/benchmark/napi/function_args/index.js b/benchmark/napi/function_args/index.js index 8ce9fa9d528f5c..2cf91650f4e77a 100644 --- a/benchmark/napi/function_args/index.js +++ b/benchmark/napi/function_args/index.js @@ -1,5 +1,5 @@ // Show the difference between calling a V8 binding C++ function -// relative to a comparable N-API C++ function, +// relative to a comparable Node-API C++ function, // in various types/numbers of arguments. // Reports n of calls per second. 'use strict'; @@ -19,7 +19,7 @@ try { try { napi = require(`./build/${common.buildType}/napi_binding`); } catch { - console.error(`${__filename}: NAPI-Binding failed to load`); + console.error(`${__filename}: Node-API binding failed to load`); process.exit(0); } diff --git a/benchmark/napi/function_call/index.js b/benchmark/napi/function_call/index.js index cde4c7ae223945..b22b5ac8b2151f 100644 --- a/benchmark/napi/function_call/index.js +++ b/benchmark/napi/function_call/index.js @@ -24,7 +24,7 @@ let napi_binding; try { napi_binding = require(`./build/${common.buildType}/napi_binding`); } catch { - console.error('misc/function_call/index.js NAPI-Binding failed to load'); + console.error('misc/function_call/index.js Node-API binding failed to load'); process.exit(0); } const napi = napi_binding.hello; diff --git a/benchmark/sqlite/sqlite-prepare-select-all-options.js b/benchmark/sqlite/sqlite-prepare-select-all-options.js new file mode 100644 index 00000000000000..336a6b176b0d87 --- /dev/null +++ b/benchmark/sqlite/sqlite-prepare-select-all-options.js @@ -0,0 +1,51 @@ +'use strict'; +const common = require('../common.js'); +const sqlite = require('node:sqlite'); +const assert = require('assert'); + +const bench = common.createBenchmark(main, { + n: [1e5], + tableSeedSize: [1e5], + statement: [ + 'SELECT * FROM foo LIMIT 1', + 'SELECT * FROM foo LIMIT 100', + ], + options: ['none', 'readBigInts', 'returnArrays', 'readBigInts|returnArrays'], +}); + +function main(conf) { + const optionsObj = conf.options === 'none' ? {} : conf.options.split('|').reduce((acc, key) => { + acc[key] = true; + return acc; + }, {}); + + const db = new sqlite.DatabaseSync(':memory:', optionsObj); + + db.exec( + 'CREATE TABLE foo (text_column TEXT, integer_column INTEGER, real_column REAL, blob_column BLOB)', + ); + + const fooInsertStatement = db.prepare( + 'INSERT INTO foo (text_column, integer_column, real_column, blob_column) VALUES (?, ?, ?, ?)', + ); + + for (let i = 0; i < conf.tableSeedSize; i++) { + fooInsertStatement.run( + crypto.randomUUID(), + Math.floor(Math.random() * 100), + Math.random(), + Buffer.from('example blob data'), + ); + } + + let i; + let deadCodeElimination; + + const stmt = db.prepare(conf.statement); + + bench.start(); + for (i = 0; i < conf.n; i += 1) deadCodeElimination = stmt.all(); + bench.end(conf.n); + + assert.ok(deadCodeElimination !== undefined); +} diff --git a/benchmark/sqlite/sqlite-prepare-select-get-options.js b/benchmark/sqlite/sqlite-prepare-select-get-options.js new file mode 100644 index 00000000000000..eb2e5074151af2 --- /dev/null +++ b/benchmark/sqlite/sqlite-prepare-select-get-options.js @@ -0,0 +1,50 @@ +'use strict'; +const common = require('../common.js'); +const sqlite = require('node:sqlite'); +const assert = require('assert'); + +const bench = common.createBenchmark(main, { + n: [1e5], + tableSeedSize: [1e5], + statement: [ + 'SELECT * FROM foo LIMIT 1', + ], + options: ['none', 'readBigInts', 'returnArrays', 'readBigInts|returnArrays'], +}); + +function main(conf) { + const optionsObj = conf.options === 'none' ? {} : conf.options.split('|').reduce((acc, key) => { + acc[key] = true; + return acc; + }, {}); + + const db = new sqlite.DatabaseSync(':memory:', optionsObj); + + db.exec( + 'CREATE TABLE foo (text_column TEXT, integer_column INTEGER, real_column REAL, blob_column BLOB)', + ); + + const fooInsertStatement = db.prepare( + 'INSERT INTO foo (text_column, integer_column, real_column, blob_column) VALUES (?, ?, ?, ?)', + ); + + for (let i = 0; i < conf.tableSeedSize; i++) { + fooInsertStatement.run( + crypto.randomUUID(), + Math.floor(Math.random() * 100), + Math.random(), + Buffer.from('example blob data'), + ); + } + + let i; + let deadCodeElimination; + + const stmt = db.prepare(conf.statement); + + bench.start(); + for (i = 0; i < conf.n; i += 1) deadCodeElimination = stmt.get(); + bench.end(conf.n); + + assert.ok(deadCodeElimination !== undefined); +} diff --git a/common.gypi b/common.gypi index cefbc4318b7f7e..5e1d6d8b695f2f 100644 --- a/common.gypi +++ b/common.gypi @@ -38,7 +38,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.15', + 'v8_embedder_string': '-node.18', ##### V8 defaults for Node.js ##### @@ -598,7 +598,7 @@ ], }, { # else it's `AIX` 'variables': { - 'gcc_major': ' +
+

+
+ +

+ Blog • + Documentation • + About +

+
+ +# About + +The purpose of this project is to provide a cross-platform library to parse, +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, ...) + * **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 + +**Extended features**: + + * [**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 + +**Plugins**: + + * [**Ghidra**](https://lief.re/doc/latest/plugins/ghidra/index.html) + * [**BinaryNinja**](https://lief.re/doc/latest/plugins/binaryninja/index.html) + +# Content + +- [About](#about) +- [Download / Install](#downloads--install) +- [Getting started](#getting-started) +- [Blog](https://lief.re/blog/) +- [Documentation](#documentation) + - [Rust](https://lief.re/doc/stable/rust/lief/) + - [Sphinx](https://lief.re/doc/latest/index.html) + - [Doxygen](https://lief.re/doc/latest/doxygen/index.html) + - Tutorials: + - [Parse and manipulate formats](https://lief.re/doc/latest/tutorials/01_play_with_formats.html) + - [Play with ELF symbols](https://lief.re/doc/latest/tutorials/03_elf_change_symbols.html) + - [PE Resources](https://lief.re/doc/latest/tutorials/07_pe_resource.html) + - [Transforming an ELF executable into a library](https://lief.re/doc/latest/tutorials/08_elf_bin2lib.html) + - [How to use frida on a non-rooted device](https://lief.re/doc/latest/tutorials/09_frida_lief.html) + - [Android formats](https://lief.re/doc/latest/tutorials/10_android_formats.html) + - [Mach-O modification](https://lief.re/doc/latest/tutorials/11_macho_modification.html) + - [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) + - [Authors](#authors) + - [License](#license) + - [Bibtex](#bibtex) + +## Downloads / Install + +## C++ + +```cmake +find_package(LIEF REQUIRED) +target_link_libraries(my-project LIEF::LIEF) +``` + +## Rust + +```toml +[package] +name = "my-awesome-project" +version = "0.0.1" +edition = "2021" + +[dependencies] +lief = "0.17.1" +``` + +## Python + +To install the latest **version** (release): + +```console +pip install lief +``` + +To install nightly build: + +```console +pip install [--user] --force-reinstall --index-url https://lief.s3-website.fr-par.scw.cloud/latest lief==1.0.0.dev0 +``` + +### Packages + +- LIEF Extended: https://extended.lief.re (GitHub OAuth) +- **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 + +Here are guides to install or integrate LIEF: + + * [Python](https://lief.re/doc/latest/installation.html#python) + * [Visual Studio](https://lief.re/doc/latest/installation.html#visual-studio-integration) + * [XCode](https://lief.re/doc/latest/installation.html#xcode-integration) + * [CMake](https://lief.re/doc/latest/installation.html#cmake-integration) + +## Getting started + +### Python + +```python +import lief + +# ELF +binary = lief.parse("/usr/bin/ls") +for section in binary.sections: + print(section.name, section.virtual_address) + +# PE +binary = lief.parse("C:\\Windows\\explorer.exe") + +if rheader := pe.rich_header: + print(rheader.key) + +# Mach-O +binary = lief.parse("/usr/bin/ls") +for fixup in binary.dyld_chained_fixups: + print(fixup) +``` + +### Rust + +```rust +use lief::Binary; +use lief::pe::debug::Entries::CodeViewPDB; + +if let Some(Binary::PE(pe)) = Binary::parse(path.as_str()) { + for entry in pe.debug() { + if let CodeViewPDB(pdb_view) = entry { + println!("{}", pdb_view.filename()); + } + } +} +``` + +### C++ + +```cpp +#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'; + } + } + + // PE + if (std::unique_ptr pe = LIEF::PE::Parser::parse("C:\\Windows\\explorer.exe")) { + 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'; + } + } + + return 0; +} + +``` + +### 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) +* [Doxygen](https://lief.re/doc/latest/doxygen/index.html) +* [Rust](https://lief.re/doc/stable/rust/lief/) + +## Contact + +* **Mail**: contact at lief re +* **Discord**: [LIEF](https://discord.gg/7hRFGWYedu) + +## About + +### Authors + +Romain Thomas ([@rh0main](https://www.romainthomas.fr/)) - Formerly at [Quarkslab](https://www.quarkslab.com) + +### License + +LIEF is provided under the [Apache 2.0 license](https://github.com/lief-project/LIEF/blob/0.17.1/LICENSE). + +### Bibtex + +```bibtex +@MISC {LIEF, + author = "Romain Thomas", + title = "LIEF - Library to Instrument Executable Formats", + howpublished = "https://lief.quarkslab.com/", + month = "apr", + year = "2017" +} +``` + + diff --git a/deps/LIEF/config/mbedtls/config.h b/deps/LIEF/config/mbedtls/config.h new file mode 100644 index 00000000000000..1007c99aee06ab --- /dev/null +++ b/deps/LIEF/config/mbedtls/config.h @@ -0,0 +1,5 @@ +#include "mbedtls/mbedtls_config.h" + +#if defined (MBEDTLS_ARCH_IS_X86) +#undef MBEDTLS_AESNI_C +#endif diff --git a/deps/LIEF/include/LIEF/ART.hpp b/deps/LIEF/include/LIEF/ART.hpp new file mode 100644 index 00000000000000..7d920b61be47c4 --- /dev/null +++ b/deps/LIEF/include/LIEF/ART.hpp @@ -0,0 +1,28 @@ +/* Copyright 2017 - 2025 R. Thomas + * Copyright 2017 - 2025 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_ART_H +#define LIEF_ART_H + +#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" +#endif + +#endif diff --git a/deps/LIEF/include/LIEF/ART/EnumToString.hpp b/deps/LIEF/include/LIEF/ART/EnumToString.hpp new file mode 100644 index 00000000000000..a377b91a35764b --- /dev/null +++ b/deps/LIEF/include/LIEF/ART/EnumToString.hpp @@ -0,0 +1,40 @@ +/* Copyright 2017 - 2025 R. Thomas + * Copyright 2017 - 2025 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_ART_ENUM_TO_STRING_H +#define LIEF_ART_ENUM_TO_STRING_H +#include "LIEF/visibility.h" +#include "LIEF/ART/enums.hpp" + +namespace LIEF { +namespace ART { + +LIEF_API const char* to_string(STORAGE_MODES e); + +LIEF_API const char* to_string(ART_17::IMAGE_SECTIONS e); +LIEF_API const char* to_string(ART_29::IMAGE_SECTIONS e); +LIEF_API const char* to_string(ART_30::IMAGE_SECTIONS e); + +LIEF_API const char* to_string(ART_17::IMAGE_METHODS e); +LIEF_API const char* to_string(ART_44::IMAGE_METHODS e); + +LIEF_API const char* to_string(ART_17::IMAGE_ROOTS e); +LIEF_API const char* to_string(ART_44::IMAGE_ROOTS e); + +} // namespace ART +} // namespace LIEF + +#endif + diff --git a/deps/LIEF/include/LIEF/ART/File.hpp b/deps/LIEF/include/LIEF/ART/File.hpp new file mode 100644 index 00000000000000..ea00a53ac186da --- /dev/null +++ b/deps/LIEF/include/LIEF/ART/File.hpp @@ -0,0 +1,55 @@ +/* Copyright 2017 - 2025 R. Thomas + * Copyright 2017 - 2025 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_ART_FILE_H +#define LIEF_ART_FILE_H +#include + +#include "LIEF/ART/Header.hpp" + +#include "LIEF/visibility.h" +#include "LIEF/Object.hpp" + +namespace LIEF { +namespace ART { +class Parser; + +class LIEF_API File : public Object { + friend class Parser; + + public: + File& operator=(const File& copy) = delete; + File(const File& copy) = delete; + + const Header& header() const; + Header& header(); + + void accept(Visitor& visitor) const override; + + + ~File() override; + + LIEF_API friend std::ostream& operator<<(std::ostream& os, const File& art_file); + + private: + File(); + + Header header_; +}; + +} +} + +#endif diff --git a/deps/LIEF/include/LIEF/ART/Header.hpp b/deps/LIEF/include/LIEF/ART/Header.hpp new file mode 100644 index 00000000000000..3aef2eb4e20a9a --- /dev/null +++ b/deps/LIEF/include/LIEF/ART/Header.hpp @@ -0,0 +1,130 @@ +/* Copyright 2017 - 2025 R. Thomas + * Copyright 2017 - 2025 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_ART_HEADER_H +#define LIEF_ART_HEADER_H + +#include +#include + +#include "LIEF/ART/types.hpp" +#include "LIEF/ART/enums.hpp" + +#include "LIEF/visibility.h" +#include "LIEF/Object.hpp" + +namespace LIEF { +namespace ART { +class Parser; + +class LIEF_API Header : public Object { + friend class Parser; + + public: + using magic_t = std::array; + + Header(); + + template + LIEF_LOCAL Header(const T* header); + + Header(const Header&); + Header& operator=(const Header&); + + magic_t magic() const; + art_version_t version() const; + + uint32_t image_begin() const; + uint32_t image_size() const; + + uint32_t oat_checksum() const; + + uint32_t oat_file_begin() const; + uint32_t oat_file_end() const; + + uint32_t oat_data_begin() const; + uint32_t oat_data_end() const; + + int32_t patch_delta() const; + + uint32_t image_roots() const; + + uint32_t pointer_size() const; + bool compile_pic() const; + + uint32_t nb_sections() const; + uint32_t nb_methods() const; + + uint32_t boot_image_begin() const; + uint32_t boot_image_size() const; + + uint32_t boot_oat_begin() const; + uint32_t boot_oat_size() const; + + STORAGE_MODES storage_mode() const; + + uint32_t data_size() const; + + void accept(Visitor& visitor) const override; + + + LIEF_API friend std::ostream& operator<<(std::ostream& os, const Header& hdr); + + ~Header() override; + + private: + magic_t magic_; + art_version_t version_; + + uint32_t image_begin_; + uint32_t image_size_; + + uint32_t oat_checksum_; + + uint32_t oat_file_begin_; + uint32_t oat_file_end_; + + uint32_t oat_data_begin_; + uint32_t oat_data_end_; + + int32_t patch_delta_; + uint32_t image_roots_; + + uint32_t pointer_size_; + + bool compile_pic_; + + uint32_t nb_sections_; + uint32_t nb_methods_; + + bool is_pic_; + + // From ART 29 + // =========== + uint32_t boot_image_begin_; + uint32_t boot_image_size_; + + uint32_t boot_oat_begin_; + uint32_t boot_oat_size_; + + STORAGE_MODES storage_mode_; + + uint32_t data_size_; +}; + +} // Namespace ART +} // Namespace LIEF + +#endif diff --git a/deps/LIEF/include/LIEF/ART/Parser.hpp b/deps/LIEF/include/LIEF/ART/Parser.hpp new file mode 100644 index 00000000000000..21d2250e4e92fa --- /dev/null +++ b/deps/LIEF/include/LIEF/ART/Parser.hpp @@ -0,0 +1,107 @@ +/* Copyright 2017 - 2025 R. Thomas + * Copyright 2017 - 2025 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_ART_PARSER_H +#define LIEF_ART_PARSER_H +#include +#include +#include + +#include "LIEF/ART/types.hpp" +#include "LIEF/visibility.h" + +namespace LIEF { +class BinaryStream; +namespace ART { +class File; + + +/// Class which parses an ART file and transform into a 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 = ""); + + Parser& operator=(const Parser& copy) = delete; + Parser(const Parser& copy) = delete; + + private: + Parser(); + Parser(const std::string& file); + Parser(std::vector data); + virtual ~Parser(); + + void init(const std::string& name, art_version_t version); + + template + void parse_file(); + + template + size_t parse_header(); + + template + void parse_sections(); + + template + void parse_roots(); + + template + void parse_methods(); + + // Section parsing + template + void parse_objects(size_t offset, size_t size); + + template + void parse_art_fields(size_t offset, size_t size); + + template + void parse_art_methods(size_t offset, size_t size); + + template + void parse_interned_strings(size_t offset, size_t size); + + // Parse an **Array** of java.lang.DexCache objects + template + void parse_dex_caches(size_t offset, size_t size); + + // Parse a **Single** java.lang.DexCache object + template + void parse_dex_cache(size_t object_offset); + + // Parse an **Array** of java.lang.Class objects + template + void parse_class_roots(size_t offset, size_t size); + + // Parse java.lang.Class objects + template + void parse_class(size_t offset); + + // Parse java.lang.String objects + template + void parse_jstring(size_t offset); + + + //// Parse a **Single** java.lang.DexCache object + //template + //void parse_class_roots(size_t object_offset); + + std::unique_ptr file_; + std::unique_ptr stream_; + uint32_t imagebase_ = 0; +}; +} // namespace ART +} // namespace LIEF +#endif diff --git a/deps/LIEF/include/LIEF/ART/enums.hpp b/deps/LIEF/include/LIEF/ART/enums.hpp new file mode 100644 index 00000000000000..2165ea497bd7ce --- /dev/null +++ b/deps/LIEF/include/LIEF/ART/enums.hpp @@ -0,0 +1,133 @@ +/* Copyright 2017 - 2025 R. Thomas + * Copyright 2017 - 2025 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_ART_ENUMS_H +#define LIEF_ART_ENUMS_H + +namespace LIEF { +namespace ART { + +enum STORAGE_MODES { + STORAGE_UNCOMPRESSED = 0, + 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, + 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, +}; + +enum IMAGE_ROOTS { + DEX_CACHES = 0, + CLASS_ROOTS = 1, +}; + + +} // Namespace ART_17 + + +namespace ART_29 { + +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, +}; + + + +} // Namespace ART_29 + + +namespace ART_30 { + +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, +}; + +} // Namespace ART_30 + +namespace ART_44 { + +using ART_30::IMAGE_SECTIONS; + +enum IMAGE_METHODS { + 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 +}; + + +enum IMAGE_ROOTS { + DEX_CACHES = 0, + CLASS_ROOTS = 1, + CLASS_LOADER = 2, // New in ART 44 +}; + +} // Namespace ART_44 + + +namespace ART_46 { + +using ART_30::IMAGE_SECTIONS; +using ART_30::IMAGE_METHODS; +using ART_30::IMAGE_ROOTS; + + +} // Namespace ART_46 + +} +} +#endif diff --git a/deps/LIEF/include/LIEF/ART/hash.hpp b/deps/LIEF/include/LIEF/ART/hash.hpp new file mode 100644 index 00000000000000..1aaa7d3acd9211 --- /dev/null +++ b/deps/LIEF/include/LIEF/ART/hash.hpp @@ -0,0 +1,47 @@ +/* Copyright 2017 - 2025 R. Thomas + * Copyright 2017 - 2025 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_ART_HASH_H +#define LIEF_ART_HASH_H + +#include "LIEF/visibility.h" +#include "LIEF/hash.hpp" + +namespace LIEF { +class Object; + +namespace ART { +class File; +class Header; + +class LIEF_API Hash : public LIEF::Hash { + public: + static LIEF::Hash::value_type hash(const Object& obj); + + public: + using LIEF::Hash::Hash; + using LIEF::Hash::visit; + + public: + void visit(const File& file) override; + void visit(const Header& header) override; + + ~Hash() override; +}; + +} +} + +#endif diff --git a/deps/LIEF/include/LIEF/ART/java_structures.hpp b/deps/LIEF/include/LIEF/ART/java_structures.hpp new file mode 100644 index 00000000000000..da3514aaffe6dc --- /dev/null +++ b/deps/LIEF/include/LIEF/ART/java_structures.hpp @@ -0,0 +1,397 @@ +/* Copyright 2017 - 2025 R. Thomas + * Copyright 2017 - 2025 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_ART_JAVA_STRUCTURES_H +#define LIEF_ART_JAVA_STRUCTURES_H + +#include +#include + +#include "LIEF/types.hpp" +#include "LIEF/ART/enums.hpp" +#include "LIEF/ART/types.hpp" + +namespace LIEF { +/// Namespace related to the LIEF's ART module +namespace ART { + +namespace details { + +struct no_brooks_read_barrier_t {}; + +// ====================== +// Android 6.0.1 - ART 17 +// ====================== +namespace ART_17 { + +/// Namespace related to the Java part of ART 17 +namespace Java { + +using heap_reference_t = uint32_t; + +struct brooks_read_barrier_t { + uint32_t x_rb_ptr; + uint32_t x_xpadding; +}; + +template +struct jobject_t { + heap_reference_t klass; + uint32_t monitor; + T brooks_read_barrier; +}; + +template<> +struct jobject_t { + heap_reference_t klass; + uint32_t monitor; +}; +template +struct ALIGNED_(4) jarray_t { + jobject_t object; + int32_t length; + uint32_t* elements; +}; + +template +struct ALIGNED_(4) jclass_t { + jobject_t object; + + heap_reference_t class_loader; + heap_reference_t component_type; + heap_reference_t dex_cache; + heap_reference_t dex_cache_strings; + heap_reference_t iftable; + heap_reference_t name; + heap_reference_t super_class; + heap_reference_t verify_error_class; + heap_reference_t vtable; + + uint32_t access_flags; + uint64_t direct_methods; + uint64_t ifields; + uint64_t sfields; + uint64_t virtual_methods; + uint32_t class_size; + uint32_t clinit_thread_id; + 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; + uint32_t num_reference_static_fields; + uint32_t num_static_fields; + uint32_t num_virtual_methods; + uint32_t object_size; + uint32_t primitive_type; + uint32_t reference_instance_offsets; + int32_t status; +}; + +template +struct ALIGNED_(4) jstring_t { + jobject_t object; + int32_t count; + uint32_t hash_code; + uint16_t* value; +}; + +template +struct ALIGNED_(4) jdex_cache_t { + jobject_t object; + + heap_reference_t dex; + heap_reference_t location; + heap_reference_t resolved_fields; + heap_reference_t resolved_methods; + heap_reference_t resolved_types; + heap_reference_t strings; + uint64_t dex_file; +}; + + +} // Namespace Java +} // Namespace ART_17 + +// ====================== +// Android 7.0.0 - ART 29 +// ====================== +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 brooks_read_barrier_t = ART_17::Java::brooks_read_barrier_t; + +template +using jobject_t = ART_17::Java::jobject_t; + +template +using jarray_t = ART_17::Java::jarray_t; + +template +struct ALIGNED_(4) jclass_t { + jobject_t object; + + heap_reference_t annotation_type; // ADDED in ART 29 + heap_reference_t class_loader; + heap_reference_t component_type; + heap_reference_t dex_cache; + // heap_reference_t dex_cache_strings; // REMOVED in ART 29 + 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 vtable; + + uint32_t access_flags; + uint64_t dex_cache_strings; // direct_methods REPLACED with dex_cache_string + uint64_t ifields; + uint64_t methods; // ADDED in ART 29 + uint64_t sfields; + 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; + // uint32_t num_direct_methods; // REMOVED in ART 29 + // uint32_t num_instance_fields; // REMOVED in ART 29 + uint32_t num_reference_instance_fields; + uint32_t num_reference_static_fields; + // uint32_t num_static_fields; // REMOVED in ART 29 + // uint32_t num_virtual_methods; // REMOVED in ART 29 + uint32_t object_size; + uint32_t primitive_type; + uint32_t reference_instance_offsets; + int32_t status; + + uint16_t copied_methods_offset; // ADDED in ART 29 + uint16_t virtual_methods_offset; // ADDED in ART 29 +}; + + +// No changes in jstring structure +template +using jstring_t = ART_17::Java::jstring_t; + +template +struct ALIGNED_(4) jdex_cache_t { + jobject_t object; + + 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 +}; + + + + +} // Namespace Java +} // Namespace ART_29 + + +// ====================== +// Android 7.1.X - ART 30 +// ====================== +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 brooks_read_barrier_t = ART_29::Java::brooks_read_barrier_t; + +template +using jobject_t = ART_29::Java::jobject_t; + +template +using jarray_t = ART_29::Java::jarray_t; + +template +using jclass_t = ART_29::Java::jclass_t; + +// No changes in jstring structure +template +using jstring_t = ART_29::Java::jstring_t; + +// No changes in jdex_cache structure +template +using jdex_cache_t = ART_29::Java::jdex_cache_t; + +} // Namespace Java +} // Namespace ART_30 + +// ====================== +// Android 8.0.0 - ART 44 +// ====================== +namespace ART_44 { + +/// Namespace related to the Java part of ART 44 +namespace Java { + + +using heap_reference_t = ART_30::Java::heap_reference_t; +using brooks_read_barrier_t = ART_30::Java::brooks_read_barrier_t; + +template +using jobject_t = ART_30::Java::jobject_t; + +template +using jarray_t = ART_30::Java::jarray_t; + +template +struct ALIGNED_(4) jclass_t { + 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 iftable; + heap_reference_t name; + heap_reference_t super_class; + // heap_reference_t verify_error; // REMOVED in ART 44 + heap_reference_t vtable; + + // uint32_t access_flags; // REMOVED in ART 44 + // uint64_t dex_cache_strings; // REMOVED in ART 44 + uint64_t ifields; + uint64_t methods; + uint64_t sfields; + 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; + 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 primitive_type; + uint32_t reference_instance_offsets; + int32_t status; + uint16_t copied_methods_offset; + uint16_t virtual_methods_offset; +}; + + +// No changes in jstring structure but string can be +// encoded as as char16_t or char (compressed) +// count[0] (LSB) == 1 ----> compressed +// count[0] (LSB) == 0 ----> chat16_t +template +using jstring_t = ART_30::Java::jstring_t; + +template +struct ALIGNED_(4) jdex_cache_t { + jobject_t object; + + // 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; +}; + + +} // Namespace Java +} // Namespace ART_44 + + +// ====================== +// Android 8.1.X - ART 46 +// ====================== +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 brooks_read_barrier_t = ART_44::Java::brooks_read_barrier_t; + +template +using jobject_t = ART_44::Java::jobject_t; + +template +using jarray_t = ART_44::Java::jarray_t; + +template +using jclass_t = ART_44::Java::jclass_t; + +template +using jstring_t = ART_44::Java::jstring_t; + +template +using jdex_cache_t = ART_44::Java::jdex_cache_t; + +} // Namespace Java +} // Namespace ART_46 + +// ====================== +// Android 9.0.0 - ART 66 +// ====================== +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 brooks_read_barrier_t = ART_46::Java::brooks_read_barrier_t; + +template +using jobject_t = ART_46::Java::jobject_t; + +template +using jarray_t = ART_46::Java::jarray_t; + +template +using jclass_t = ART_46::Java::jclass_t; + +template +using jstring_t = ART_46::Java::jstring_t; + +template +using jdex_cache_t = ART_46::Java::jdex_cache_t; + +} // Namespace Java +} // Namespace ART_56 + +} // namespace details +} // Namespace ART +} // Namespace LIEF + + + +#endif diff --git a/deps/LIEF/include/LIEF/ART/json.hpp b/deps/LIEF/include/LIEF/ART/json.hpp new file mode 100644 index 00000000000000..3302272bd8c51a --- /dev/null +++ b/deps/LIEF/include/LIEF/ART/json.hpp @@ -0,0 +1,31 @@ +/* Copyright 2017 - 2025 R. Thomas + * Copyright 2017 - 2025 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_ART_PUBLIC_JSON_H +#define LIEF_ART_PUBLIC_JSON_H + +#include "LIEF/visibility.h" +#include + +namespace LIEF { +class Object; +namespace ART { + +LIEF_API std::string to_json(const Object& v); + +} +} + +#endif diff --git a/deps/LIEF/include/LIEF/ART/types.hpp b/deps/LIEF/include/LIEF/ART/types.hpp new file mode 100644 index 00000000000000..706e4143d08fbc --- /dev/null +++ b/deps/LIEF/include/LIEF/ART/types.hpp @@ -0,0 +1,31 @@ +/* Copyright 2017 - 2025 R. Thomas + * Copyright 2017 - 2025 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_ART_TYPE_TRAITS_H +#define LIEF_ART_TYPE_TRAITS_H + +#include +#include +#include "LIEF/iterators.hpp" + +namespace LIEF { +namespace ART { + +using art_version_t = uint32_t; + +} // Namesapce ART +} // Namespace LIEF + +#endif diff --git a/deps/LIEF/include/LIEF/ART/utils.hpp b/deps/LIEF/include/LIEF/ART/utils.hpp new file mode 100644 index 00000000000000..fc4bcd8e3eede0 --- /dev/null +++ b/deps/LIEF/include/LIEF/ART/utils.hpp @@ -0,0 +1,51 @@ +/* Copyright 2017 - 2025 R. Thomas + * Copyright 2017 - 2025 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_ART_UTILS_H +#define LIEF_ART_UTILS_H + +#include +#include + +#include "LIEF/ART/types.hpp" + +#include "LIEF/platforms/android.hpp" + +#include "LIEF/types.hpp" +#include "LIEF/visibility.h" + +namespace LIEF { +namespace ART { + +/// Check if the given file is an ART one. +LIEF_API bool is_art(const std::string& file); + +/// Check if the given raw data is an ART one. +LIEF_API bool is_art(const std::vector& raw); + +/// Return the ART version of the given file +LIEF_API art_version_t version(const std::string& file); + +/// Return the ART version of the raw data +LIEF_API art_version_t version(const std::vector& raw); + +/// Return the ANDROID_VERSIONS associated with the given ART version +LIEF_API LIEF::Android::ANDROID_VERSIONS android_version(art_version_t version); + +} +} + + +#endif diff --git a/deps/LIEF/include/LIEF/ASM.hpp b/deps/LIEF/include/LIEF/ASM.hpp new file mode 100644 index 00000000000000..5bc1a376b2c5ba --- /dev/null +++ b/deps/LIEF/include/LIEF/ASM.hpp @@ -0,0 +1,28 @@ +/* Copyright 2017 - 2025 R. Thomas + * Copyright 2017 - 2025 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_ASM_H +#define LIEF_ASM_H +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#endif diff --git a/deps/LIEF/include/LIEF/Abstract.hpp b/deps/LIEF/include/LIEF/Abstract.hpp new file mode 100644 index 00000000000000..bc10e669486524 --- /dev/null +++ b/deps/LIEF/include/LIEF/Abstract.hpp @@ -0,0 +1,26 @@ +/* Copyright 2017 - 2025 R. Thomas + * Copyright 2017 - 2025 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_ABSTRACT_H +#define LIEF_ABSTRACT_H + +#include +#include +#include +#include +#include +#include + +#endif diff --git a/deps/LIEF/include/LIEF/Abstract/Binary.hpp b/deps/LIEF/include/LIEF/Abstract/Binary.hpp new file mode 100644 index 00000000000000..8e4f738a76efdb --- /dev/null +++ b/deps/LIEF/include/LIEF/Abstract/Binary.hpp @@ -0,0 +1,441 @@ +/* Copyright 2017 - 2025 R. Thomas + * Copyright 2017 - 2025 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_ABSTRACT_BINARY_H +#define LIEF_ABSTRACT_BINARY_H + +#include +#include +#include + +#include "LIEF/visibility.h" +#include "LIEF/Object.hpp" +#include "LIEF/iterators.hpp" +#include "LIEF/errors.hpp" +#include "LIEF/span.hpp" + +#include "LIEF/Abstract/Header.hpp" +#include "LIEF/Abstract/Function.hpp" + +#include "LIEF/asm/Instruction.hpp" +#include "LIEF/asm/AssemblerConfig.hpp" + +namespace llvm { +class MCInst; +} + +/// LIEF namespace +namespace LIEF { +class Section; +class Relocation; +class Symbol; + +class DebugInfo; + +namespace assembly { +class Engine; +} + +/// Generic interface representing a binary executable. +/// +/// This class provides a unified interface across multiple binary formats +/// such as ELF, PE, Mach-O, and others. It enables users to access binary +/// components like headers, sections, symbols, relocations, +/// and functions in a format-agnostic way. +/// +/// 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 + /// (default behavior). + AUTO = 0, + + /// Relative Virtual Address (RVA), offset from image base. + RVA = 1, + + /// Absolute Virtual Address. + VA = 2 + }; + + enum FORMATS { + UNKNOWN = 0, + ELF, + PE, + MACHO, + OAT, + }; + + using functions_t = std::vector; + + /// Internal container + using sections_t = std::vector; + + /// Iterator that outputs LIEF::Section& + using it_sections = ref_iterator; + + /// Iterator that outputs const LIEF::Section& + using it_const_sections = const_ref_iterator; + + /// Internal container + using symbols_t = std::vector; + + /// Iterator that outputs LIEF::Symbol& + using it_symbols = ref_iterator; + + /// Iterator that outputs const LIEF::Symbol& + using it_const_symbols = const_ref_iterator; + + /// Internal container + using relocations_t = std::vector; + + /// Iterator that outputs LIEF::Relocation& + using it_relocations = ref_iterator; + + /// Iterator that outputs const LIEF::Relocation& + using it_const_relocations = const_ref_iterator; + + /// Instruction iterator + using instructions_it = iterator_range; + + public: + Binary(); + Binary(FORMATS fmt); + + ~Binary() override; + + Binary& operator=(const Binary&) = delete; + Binary(const Binary&) = delete; + + /// Executable format (ELF, PE, Mach-O) of the underlying binary + FORMATS format() const { + return format_; + } + + /// Return the abstract header of the binary + Header header() const { + return get_abstract_header(); + } + + /// Return an iterator over the abstracted symbols in which the elements **can** be modified + it_symbols symbols() { + 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 const_cast(this)->get_abstract_symbols(); + } + + /// Check if a Symbol with the given name exists + bool has_symbol(const std::string& name) const { + return get_symbol(name) != nullptr; + } + + /// 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; + + Symbol* get_symbol(const std::string& name) { + return const_cast(static_cast(this)->get_symbol(name)); + } + + /// Return an iterator over the binary's sections (LIEF::Section) + it_sections sections() { + return get_abstract_sections(); + } + + it_const_sections sections() const { + 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 get_abstract_relocations(); + } + + it_const_relocations relocations() const { + return const_cast(this)->get_abstract_relocations(); + } + + /// Binary's entrypoint (if any) + virtual uint64_t entrypoint() const = 0; + + /// Binary's original size + uint64_t original_size() const { + return original_size_; + } + + /// Return the functions exported by the binary + functions_t exported_functions() const { + return get_abstract_exported_functions(); + } + + /// Return libraries which are imported by the binary + std::vector imported_libraries() const { + return get_abstract_imported_libraries(); + } + + /// Return functions imported by the binary + functions_t imported_functions() const { + return get_abstract_imported_functions(); + } + + /// Return the address of the given function name + 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; + + std::vector xref(uint64_t address) const; + + /// Patch the content at virtual address @p address with @p patch_value + /// + /// @param[in] address Address to patch + /// @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, + VA_TYPES addr_type = VA_TYPES::AUTO) = 0; + + /// Patch the address with the given value + /// + /// @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), + 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; + + /// 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 + { + T value; + static_assert(std::is_integral::value, "Require an integral 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); + } + + std::copy(raw.data(), raw.data() + sizeof(T), + reinterpret_cast(&value)); + return value; + } + + /// Change binary's original size. + /// + /// @warning + /// This function should be used carefully as some optimizations + /// can be performed with this value + void original_size(uint64_t size) { + original_size_ = size; + } + + /// Check if the binary is position independent + virtual bool is_pie() const = 0; + + /// Check if the binary uses ``NX`` protection + virtual bool has_nx() const = 0; + + /// Default image base address if the ASLR is not enabled. + virtual uint64_t imagebase() const = 0; + + /// Constructor functions that are called prior any other functions + virtual functions_t ctor_functions() const = 0; + + /// 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; + + virtual std::ostream& print(std::ostream& os) const { + return os; + } + + LIEF_API friend std::ostream& operator<<(std::ostream& os, const Binary& binary) { + binary.print(os); + return os; + } + + /// Return the debug info if present. It can be either a + /// LIEF::dwarf::DebugInfo or a LIEF::pdb::DebugInfo + /// + /// For ELF and Mach-O binaries, it returns the given DebugInfo object **only** + /// if the binary embeds the DWARF debug info in the binary itself. + /// + /// For PE file, this function tries to find the **external** PDB using + /// the LIEF::PE::CodeViewPDB::filename() output (if present). One can also + /// 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; + + /// Disassemble code starting at the given virtual address and with the given + /// size. + /// + /// ```cpp + /// auto insts = binary->disassemble(0xacde, 100); + /// for (std::unique_ptr inst : insts) { + /// std::cout << inst->to_string() << '\n'; + /// } + /// ``` + /// + /// \see LIEF::assembly::Instruction + instructions_it disassemble(uint64_t address, size_t size) const; + + /// Disassemble code starting at the given virtual address + /// + /// ```cpp + /// auto insts = binary->disassemble(0xacde); + /// for (std::unique_ptr inst : insts) { + /// std::cout << inst->to_string() << '\n'; + /// } + /// ``` + /// + /// \see LIEF::assembly::Instruction + instructions_it disassemble(uint64_t address) const; + + /// Disassemble code for the given symbol name + /// + /// ```cpp + /// auto insts = binary->disassemble("__libc_start_main"); + /// for (std::unique_ptr inst : insts) { + /// std::cout << inst->to_string() << '\n'; + /// } + /// ``` + /// + /// \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 + instructions_it disassemble(const uint8_t* buffer, size_t size, + uint64_t address = 0) const; + + + /// Disassemble code provided by the given vector of bytes at the specified + /// `address` parameter. + /// + /// \see LIEF::assembly::Instruction + instructions_it disassemble(const std::vector& buffer, + uint64_t address = 0) const { + return disassemble(buffer.data(), buffer.size(), address); + } + + instructions_it disassemble(LIEF::span buffer, + uint64_t address = 0) const { + return disassemble(buffer.data(), buffer.size(), address); + } + + instructions_it disassemble(LIEF::span buffer, uint64_t address = 0) const { + return disassemble(buffer.data(), buffer.size(), address); + } + + /// Assemble **and patch** the provided assembly code at the specified address. + /// + /// The function returns the generated assembly bytes + /// + /// ```cpp + /// bin->assemble(0x12000440, R"asm( + /// xor rax, rbx; + /// mov rcx, rax; + /// )asm"); + /// ``` + /// + /// 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()); + + /// Assemble **and patch** the address with the given LLVM MCInst. + /// + /// \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** + /// with the **same** version of LLVM used by LIEF (see documentation) + std::vector assemble(uint64_t address, + const std::vector& insts); + + /// Get the default memory page size according to the architecture and + /// 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. + /// + /// 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. + /// + /// \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). + DebugInfo* load_debug_info(const std::string& path); + + protected: + FORMATS format_ = FORMATS::UNKNOWN; + mutable std::unique_ptr debug_info_; + mutable std::unordered_map> engines_; + uint64_t original_size_ = 0; + + assembly::Engine* get_engine(uint64_t address) const; + + 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 + 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 std::vector get_abstract_imported_libraries() const = 0; +}; + +LIEF_API const char* to_string(Binary::VA_TYPES e); +LIEF_API const char* to_string(Binary::FORMATS e); + +} + + +#endif diff --git a/deps/LIEF/include/LIEF/Abstract/DebugInfo.hpp b/deps/LIEF/include/LIEF/Abstract/DebugInfo.hpp new file mode 100644 index 00000000000000..24961cf791341b --- /dev/null +++ b/deps/LIEF/include/LIEF/Abstract/DebugInfo.hpp @@ -0,0 +1,79 @@ +/* Copyright 2022 - 2025 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_DEBUGINFO_H +#define LIEF_DEBUGINFO_H +#include +#include +#include + +#include "LIEF/visibility.h" +#include "LIEF/optional.hpp" +namespace LIEF { + +class Binary; + +namespace details { +class DebugInfo; +} + +/// This class provides a generic interface for accessing debug information +/// from different formats such as DWARF and PDB. +/// +/// Users can use this interface to access high-level debug features like +/// resolving function addresses. +/// +/// See: LIEF::pdb::DebugInfo, LIEF::dwarf::DebugInfo +class LIEF_API DebugInfo { + public: + friend class Binary; + enum class FORMAT { + UNKNOWN = 0, + DWARF, PDB, + }; + DebugInfo(std::unique_ptr impl); + + virtual ~DebugInfo(); + + virtual FORMAT format() const { + return FORMAT::UNKNOWN; + } + + /// This function can be used to **down cast** a DebugInfo instance: + /// + /// ```cpp + /// std::unique_ptr dbg = bin->debug_info(); + /// if (const auto* dwarf = inst->as()) { + /// dwarf->find_function("main"); + /// } + /// ``` + template + const T* as() const { + static_assert(std::is_base_of::value, + "Require Instruction inheritance"); + if (T::classof(this)) { + return static_cast(this); + } + return nullptr; + } + + /// Attempt to resolve the address of the function specified by `name`. + virtual optional find_function_address(const std::string& name) const = 0; + + protected: + std::unique_ptr impl_; +}; + +} +#endif diff --git a/deps/LIEF/include/LIEF/Abstract/Function.hpp b/deps/LIEF/include/LIEF/Abstract/Function.hpp new file mode 100644 index 00000000000000..66004763d6eca7 --- /dev/null +++ b/deps/LIEF/include/LIEF/Abstract/Function.hpp @@ -0,0 +1,121 @@ +/* Copyright 2017 - 2025 R. Thomas + * Copyright 2017 - 2025 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_ABSTRACT_FUNCTION_H +#define LIEF_ABSTRACT_FUNCTION_H + +#include +#include + +#include "LIEF/Abstract/Symbol.hpp" +#include "LIEF/visibility.h" +#include "LIEF/enums.hpp" + +namespace LIEF { + +/// Class that represents a function in the binary +class LIEF_API Function : public Symbol { + public: + /// Flags used to characterize the semantics of the function + enum class FLAGS : uint32_t { + NONE = 0, + /// The function acts as a constructor. + /// + /// Usually this flag is associated with functions + /// that are located in the `.init_array`, `__mod_init_func` or `.tls` sections + CONSTRUCTOR = 1 << 0, + + /// The function acts as a destructor. + /// + /// Usually this flag is associated with functions + /// that are located in the `.fini_array` or `__mod_term_func` sections + DESTRUCTOR = 1 << 1, + + /// The function is associated with Debug information + DEBUG_INFO = 1 << 2, + + /// The function is exported by the binary and the address() method + /// returns its virtual address in the binary + EXPORTED = 1 << 3, + + /// 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) + {} + Function(uint64_t address) : + Function("", address) + {} + Function(const std::string& name, uint64_t address) : + Symbol(name, address) + {} + Function(const std::string& name, uint64_t address, FLAGS flags) : + Function(name, address) + { + flags_ = flags; + } + + Function(const Function&) = default; + Function& operator=(const Function&) = default; + + ~Function() override = default; + + /// List of FLAGS + std::vector flags_list() const; + + FLAGS flags() const { + return flags_; + } + + /// Add a flag to the current function + Function& add(FLAGS f) { + flags_ = (FLAGS)((uint32_t)flags_ | (uint32_t)f); + return *this; + } + + /// Check if the function has the given flag + bool has(FLAGS f) const { + 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. + uint64_t address() const { + return value_; + } + + void address(uint64_t address) { + value_ = address; + } + + void accept(Visitor& visitor) const override; + + LIEF_API friend std::ostream& operator<<(std::ostream& os, const Function& entry); + + protected: + FLAGS flags_ = FLAGS::NONE; +}; + +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 new file mode 100644 index 00000000000000..036e64cf5a5459 --- /dev/null +++ b/deps/LIEF/include/LIEF/Abstract/Header.hpp @@ -0,0 +1,147 @@ +/* Copyright 2017 - 2025 R. Thomas + * Copyright 2017 - 2025 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_ABSTRACT_HEADER_H +#define LIEF_ABSTRACT_HEADER_H + +#include +#include +#include + +#include "LIEF/Object.hpp" +#include "LIEF/visibility.h" +#include "LIEF/enums.hpp" + +namespace LIEF { +namespace ELF { +class Binary; +} + +namespace PE { +class Binary; +} + +namespace MachO { +class Binary; +} + +class LIEF_API Header : public Object { + public: + enum class ARCHITECTURES { + UNKNOWN = 0, + ARM, + ARM64, + MIPS, + X86, + X86_64, + PPC, + SPARC, + SYSZ, + XCORE, + RISCV, + LOONGARCH, + PPC64, + }; + + enum class ENDIANNESS { + UNKNOWN = 0, + BIG, + LITTLE, + }; + + enum MODES : uint64_t { + NONE = 0, + + 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 + + ARM64E = 1LLU << 4, /// ARM64 with extended (security) features + }; + + enum class OBJECT_TYPES { + UNKNOWN = 0, + EXECUTABLE, + LIBRARY, + OBJECT, + }; + + static Header from(const LIEF::ELF::Binary& elf); + static Header from(const LIEF::PE::Binary& pe); + static Header from(const LIEF::MachO::Binary& macho); + + Header() = default; + Header(const Header&) = default; + Header& operator=(const Header&) = default; + ~Header() override = default; + + /// Target architecture + ARCHITECTURES architecture() const { + return architecture_; + } + + /// Optional features for the given architecture + MODES modes() const { + return modes_; + } + + /// MODES as a vector + std::vector modes_list() const; + + bool is(MODES m) const { + return ((uint64_t)m & (uint64_t)modes_) != 0; + } + + OBJECT_TYPES object_type() const { + return object_type_; + } + uint64_t entrypoint() const { + return entrypoint_; + } + + ENDIANNESS endianness() const { + return endianness_; + } + + bool is_32() const { + return ((uint64_t)modes_ & (uint64_t)MODES::BITS_32) != 0; + } + + bool is_64() const { + return ((uint64_t)modes_ & (uint64_t)MODES::BITS_64) != 0; + } + + void accept(Visitor& visitor) const override; + + LIEF_API friend std::ostream& operator<<(std::ostream& os, const Header& hdr); + + protected: + ARCHITECTURES architecture_ = ARCHITECTURES::UNKNOWN; + OBJECT_TYPES object_type_ = OBJECT_TYPES::UNKNOWN; + uint64_t entrypoint_ = 0; + ENDIANNESS endianness_ = ENDIANNESS::UNKNOWN; + MODES modes_ = MODES::NONE; +}; + +LIEF_API const char* to_string(Header::ARCHITECTURES e); +LIEF_API const char* to_string(Header::OBJECT_TYPES e); +LIEF_API const char* to_string(Header::MODES e); +LIEF_API const char* to_string(Header::ENDIANNESS e); +} + +ENABLE_BITMASK_OPERATORS(LIEF::Header::MODES); + +#endif diff --git a/deps/LIEF/include/LIEF/Abstract/Parser.hpp b/deps/LIEF/include/LIEF/Abstract/Parser.hpp new file mode 100644 index 00000000000000..9a3665192bb635 --- /dev/null +++ b/deps/LIEF/include/LIEF/Abstract/Parser.hpp @@ -0,0 +1,60 @@ +/* Copyright 2017 - 2025 R. Thomas + * Copyright 2017 - 2025 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_ABSTRACT_PARSER_H +#define LIEF_ABSTRACT_PARSER_H + +#include +#include +#include + +#include "LIEF/visibility.h" + +namespace LIEF { +class BinaryStream; +class Binary; + +/// Main interface to parse an executable regardless of its format +class LIEF_API Parser { + public: + /// Construct an LIEF::Binary from the given filename + /// + /// @warning If the target file is a FAT Mach-O, it will return the **last** one + /// @see LIEF::MachO::Parser::parse + static std::unique_ptr parse(const std::string& filename); + + + /// Construct an LIEF::Binary from the given raw data + /// + /// @warning If the target file is a FAT Mach-O, it will return the **last** one + /// @see LIEF::MachO::Parser::parse + static std::unique_ptr parse(const std::vector& raw); + + /// Construct an LIEF::Binary from the given stream + /// + /// @warning If the target file is a FAT Mach-O, it will return the **last** one + /// @see LIEF::MachO::Parser::parse + static std::unique_ptr parse(std::unique_ptr stream); + + protected: + Parser(const std::string& file); + uint64_t binary_size_ = 0; + + virtual ~Parser(); + Parser(); +}; +} + +#endif diff --git a/deps/LIEF/include/LIEF/Abstract/Relocation.hpp b/deps/LIEF/include/LIEF/Abstract/Relocation.hpp new file mode 100644 index 00000000000000..c22f8e7a508cf6 --- /dev/null +++ b/deps/LIEF/include/LIEF/Abstract/Relocation.hpp @@ -0,0 +1,98 @@ +/* Copyright 2017 - 2025 R. Thomas + * Copyright 2017 - 2025 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_ABSTRACT_RELOCATION_H +#define LIEF_ABSTRACT_RELOCATION_H + +#include +#include + +#include "LIEF/Object.hpp" +#include "LIEF/visibility.h" + +namespace LIEF { +/// Class which represents an abstracted Relocation +class LIEF_API Relocation : public Object { + + public: + Relocation() = default; + + /// Constructor from a relocation's address and size + Relocation(uint64_t address, uint8_t size) : + address_(address), + size_(size) + {} + + ~Relocation() override = default; + + Relocation& operator=(const Relocation&) = default; + Relocation(const Relocation&) = default; + void swap(Relocation& other) { + std::swap(address_, other.address_); + std::swap(size_, other.size_); + } + + /// Relocation's address + virtual uint64_t address() const { + return address_; + } + + /// Relocation size in **bits** + virtual size_t size() const { + return size_; + } + + virtual void address(uint64_t address) { + address_ = address; + } + + virtual void size(size_t size) { + size_ = (uint8_t)size; + } + + /// Method so that the ``visitor`` can visit us + void accept(Visitor& visitor) const override; + + + /// Comparaison based on the Relocation's **address** + virtual bool operator<(const Relocation& rhs) const { + return address() < rhs.address(); + } + + /// Comparaison based on the Relocation's **address** + virtual bool operator<=(const Relocation& rhs) const { + return !(address() > rhs.address()); + } + + /// Comparaison based on the Relocation's **address** + virtual bool operator>(const Relocation& rhs) const { + return address() > rhs.address(); + } + + /// Comparaison 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); + + protected: + uint64_t address_ = 0; + uint8_t size_ = 0; +}; + + +} +#endif diff --git a/deps/LIEF/include/LIEF/Abstract/Section.hpp b/deps/LIEF/include/LIEF/Abstract/Section.hpp new file mode 100644 index 00000000000000..eb89b42ccc57a4 --- /dev/null +++ b/deps/LIEF/include/LIEF/Abstract/Section.hpp @@ -0,0 +1,131 @@ +/* Copyright 2017 - 2025 R. Thomas + * Copyright 2017 - 2025 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_ABSTRACT_SECTION_H +#define LIEF_ABSTRACT_SECTION_H + +#include +#include +#include + +#include "LIEF/span.hpp" +#include "LIEF/Object.hpp" +#include "LIEF/visibility.h" + +namespace LIEF { +/// Class which represents an abstracted section +class LIEF_API Section : public Object { + public: + static constexpr size_t npos = -1; + + Section() = default; + Section(std::string name) : + name_(std::move(name)) + {} + + ~Section() override = default; + + Section& operator=(const Section&) = default; + Section(const Section&) = default; + + /// section's name + virtual std::string name() const { + return name_.c_str(); + } + + /// Return the **complete** section's name which might + /// trailing (``0``) bytes + virtual const std::string& fullname() const { + return name_; + } + + /// section's content + virtual span content() const { + return {}; + } + + /// Change the section size + virtual void size(uint64_t size) { + size_ = size; + } + + /// section's size (size in the binary, not the virtual size) + virtual uint64_t size() const { + return size_; + } + + /// Offset in the binary + virtual uint64_t offset() const { + return offset_; + } + + /// Address where the section should be mapped + virtual uint64_t virtual_address() const { + return virtual_address_; + } + + virtual void virtual_address(uint64_t virtual_address) { + virtual_address_ = virtual_address; + } + + /// Change the section's name + virtual void name(std::string name) { + name_ = std::move(name); + } + + /// Change section content + virtual void content(const std::vector&) {} + + virtual void offset(uint64_t offset) { + offset_ = offset; + } + + /// Section's entropy + double entropy() const; + + // Search functions + // ================ + size_t search(uint64_t integer, size_t pos, size_t size) const; + size_t search(const std::vector& pattern, size_t pos = 0) const; + size_t search(const std::string& pattern, size_t pos = 0) const; + size_t search(uint64_t integer, size_t pos = 0) const; + + // Search all functions + // ==================== + std::vector search_all(uint64_t v, size_t size) const; + + std::vector search_all(uint64_t v) const; + + std::vector search_all(const std::string& v) const; + + /// Method so that the ``visitor`` can visit us + void accept(Visitor& visitor) const override; + + + LIEF_API friend std::ostream& operator<<(std::ostream& os, const Section& entry); + + protected: + std::string name_; + uint64_t virtual_address_ = 0; + uint64_t size_ = 0; + uint64_t offset_ = 0; + + private: + template + std::vector search_all_(const T& v) const; +}; +} + +#endif diff --git a/deps/LIEF/include/LIEF/Abstract/Symbol.hpp b/deps/LIEF/include/LIEF/Abstract/Symbol.hpp new file mode 100644 index 00000000000000..8d9802beec346c --- /dev/null +++ b/deps/LIEF/include/LIEF/Abstract/Symbol.hpp @@ -0,0 +1,97 @@ +/* Copyright 2017 - 2025 R. Thomas + * Copyright 2017 - 2025 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_ABSTRACT_SYMBOLS_H +#define LIEF_ABSTRACT_SYMBOLS_H + +#include +#include + +#include "LIEF/Object.hpp" +#include "LIEF/visibility.h" + +namespace LIEF { + +/// This class represents a symbol in an executable format. +class LIEF_API Symbol : public Object { + public: + Symbol() = default; + Symbol(std::string name) : + name_(std::move(name)) + {} + + Symbol(std::string name, uint64_t 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) + {} + + Symbol(const Symbol&) = default; + Symbol& operator=(const Symbol&) = default; + + Symbol(Symbol&&) = default; + Symbol& operator=(Symbol&&) = default; + + ~Symbol() override = default; + + void swap(Symbol& other) noexcept; + + /// Return the symbol's name + virtual const std::string& name() const { + return name_; + } + + virtual std::string& name() { + return name_; + } + + /// Set symbol name + virtual void name(std::string name) { + name_ = std::move(name); + } + + // Symbol's value which is usually the **address** of the symbol + virtual uint64_t value() const { + return value_; + } + virtual void value(uint64_t value) { + value_ = value; + } + + /// This size of the symbol (when applicable) + virtual uint64_t size() const { + return size_; + } + + virtual void size(uint64_t value) { + size_ = value; + } + + /// Method so that the ``visitor`` can visit us + void accept(Visitor& visitor) const override; + + LIEF_API friend std::ostream& operator<<(std::ostream& os, const Symbol& entry); + + protected: + std::string name_; + uint64_t value_ = 0; + uint64_t size_ = 0; +}; +} + +#endif + diff --git a/deps/LIEF/include/LIEF/Abstract/hash.hpp b/deps/LIEF/include/LIEF/Abstract/hash.hpp new file mode 100644 index 00000000000000..26f4a375f446e6 --- /dev/null +++ b/deps/LIEF/include/LIEF/Abstract/hash.hpp @@ -0,0 +1,49 @@ +/* Copyright 2017 - 2025 R. Thomas + * Copyright 2017 - 2025 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_ABSTRACT_HASH_H +#define LIEF_ABSTRACT_HASH_H + +#include "LIEF/visibility.h" +#include "LIEF/hash.hpp" + +namespace LIEF { +class Binary; +class Header; +class Relocation; +class Object; + +class LIEF_API AbstractHash : public LIEF::Hash { + public: + static LIEF::Hash::value_type hash(const Object& obj); + + public: + using LIEF::Hash::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 Relocation& relocation) override; + void visit(const Function& function) override; + + ~AbstractHash() override; +}; + +} + +#endif diff --git a/deps/LIEF/include/LIEF/Abstract/json.hpp b/deps/LIEF/include/LIEF/Abstract/json.hpp new file mode 100644 index 00000000000000..fa05cec3458482 --- /dev/null +++ b/deps/LIEF/include/LIEF/Abstract/json.hpp @@ -0,0 +1,30 @@ +/* Copyright 2017 - 2025 R. Thomas + * Copyright 2017 - 2025 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_ABSTRACT_JSON_H +#define LIEF_ABSTRACT_JSON_H + +#include "LIEF/visibility.h" +#include + +namespace LIEF { +class Object; + +LIEF_API std::string to_json_from_abstract(const Object& v); + +} + +#endif // LIEF_JSON_SUPPORT + diff --git a/deps/LIEF/include/LIEF/BinaryStream/ASN1Reader.hpp b/deps/LIEF/include/LIEF/BinaryStream/ASN1Reader.hpp new file mode 100644 index 00000000000000..385bb35dd22c08 --- /dev/null +++ b/deps/LIEF/include/LIEF/BinaryStream/ASN1Reader.hpp @@ -0,0 +1,72 @@ +/* Copyright 2017 - 2025 R. Thomas + * Copyright 2017 - 2025 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_ASN1_READER_H +#define LIEF_ASN1_READER_H + +#include +#include +#include +#include + +#include "LIEF/errors.hpp" + +struct mbedtls_x509_crt; +struct mbedtls_x509_time; + +namespace LIEF { +class BinaryStream; + +class ASN1Reader { + public: + ASN1Reader() = delete; + + ASN1Reader(BinaryStream& stream) : + stream_(stream) + {} + + ASN1Reader(const ASN1Reader&) = delete; + ASN1Reader& operator=(const ASN1Reader&) = delete; + + + result is_tag(int tag); + + result read_tag(int tag); + result read_len(); + result read_alg(); + result read_oid(); + result read_bool(); + result read_int(); + result read_int64(); + result> read_large_int(); + + result> read_bitstring(); + result> read_octet_string(); + result read_utf8_string(); + result> read_cert(); + result x509_read_names(); + result> x509_read_serial(); + result> x509_read_time(); + + std::string get_str_tag(); + + static std::string tag2str(int tag); + + private: + BinaryStream& stream_; +}; + +} +#endif diff --git a/deps/LIEF/include/LIEF/BinaryStream/BinaryStream.hpp b/deps/LIEF/include/LIEF/BinaryStream/BinaryStream.hpp new file mode 100644 index 00000000000000..48c16034e1df4f --- /dev/null +++ b/deps/LIEF/include/LIEF/BinaryStream/BinaryStream.hpp @@ -0,0 +1,476 @@ +/* Copyright 2017 - 2025 R. Thomas + * Copyright 2017 - 2025 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_BINARY_STREAM_H +#define LIEF_BINARY_STREAM_H + +#include +#include +#include +#include +#include + +#include "LIEF/endianness_support.hpp" +#include "LIEF/errors.hpp" +#include "LIEF/visibility.h" + +namespace LIEF { +class ASN1Reader; + +/// Class that is used to a read stream of data from different sources +class LIEF_API BinaryStream { + public: + friend class ASN1Reader; + + enum class STREAM_TYPE { + UNKNOWN = 0, + VECTOR, + MEMORY, + SPAN, + FILE, + + ELF_DATA_HANDLER, + }; + + BinaryStream(STREAM_TYPE type) : + stype_(type) + {} + virtual ~BinaryStream() = default; + virtual uint64_t size() const = 0; + + STREAM_TYPE type() const { + return stype_; + } + + result read_uleb128(size_t* size = nullptr) const; + result read_sleb128(size_t* size = nullptr) const; + + result read_dwarf_encoded(uint8_t encoding) const; + + 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 read_u16string() const; + result peek_u16string() const; + + result read_mutf8(size_t maxsize = ~static_cast(0)) const; + + result read_u16string(size_t length) const; + result peek_u16string(size_t length) const; + 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) + { + 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); + 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(); + } + return make_error_code(lief_errors::read_error); + } + + virtual ok_error_t read_data(std::vector& container, uint64_t size) { + if (!peek_data(container, pos(), size)) { + return make_error_code(lief_errors::read_error); + } + + increment_pos(size); + return ok(); + } + + ok_error_t read_data(std::vector& container) { + const size_t size = this->size() - this->pos(); + return read_data(container, size); + } + + template + ok_error_t read_objects(std::vector& container, uint64_t count) { + if (count == 0) { + return ok(); + } + const size_t size = count * sizeof(T); + auto ret = peek_objects(container, count); + if (!ret) { + return make_error_code(lief_errors::read_error); + } + increment_pos(size); + return ok(); + } + + template + ok_error_t peek_objects(std::vector& container, uint64_t count) { + return peek_objects_at(pos(), container, count); + } + + template + ok_error_t peek_objects_at(uint64_t offset, std::vector& container, uint64_t count) { + if (count == 0) { + return ok(); + } + const auto current_p = pos(); + setpos(offset); + + const size_t size = count * sizeof(T); + + if (!can_read(offset, size)) { + setpos(current_p); + return make_error_code(lief_errors::read_error); + } + + container.resize(count); + + if (!peek_in(container.data(), pos(), size)) { + setpos(current_p); + return make_error_code(lief_errors::read_error); + } + + setpos(current_p); + return ok(); + } + + void setpos(size_t pos) const { + pos_ = pos; + } + + const BinaryStream& increment_pos(size_t value) const { + pos_ += value; + return *this; + } + + void decrement_pos(size_t value) const { + if (pos_ > value) { + pos_ -= value; + } else { + pos_ = 0; + } + } + + size_t pos() const { + return pos_; + } + + operator bool() const { + return pos_ < size(); + } + + template + const T* read_array(size_t size) const; + + template + ok_error_t peek_array(std::array& dst) const { + if /*constexpr*/ (N == 0) { + return ok(); + } + // 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); + + if (!read_ok) { + return make_error_code(lief_errors::read_error); + } + if (peek_in(dst.data(), pos_, N)) { + return ok(); + } + return make_error_code(lief_errors::read_error); + } + + template + ok_error_t read_array(std::array& dst) const { + if (!peek_array(dst)) { + return make_error_code(lief_errors::read_error); + } + + increment_pos(N); + return ok(); + } + + template + result peek() const; + + template + result peek(size_t offset) const; + + template + const T* peek_array(size_t size) const; + + template + const T* peek_array(size_t offset, size_t size) const; + + template + result read() const; + + template + bool can_read() const; + + template + 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(); + } + + size_t align(size_t align_on) const; + + void set_endian_swap(bool swap) { + endian_swap_ = swap; + } + + 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; }); + } + + bool should_swap() const { + return endian_swap_; + } + + virtual const uint8_t* p() const { + return nullptr; + } + + virtual uint8_t* start() { + return const_cast(static_cast(this)->start()); + } + + virtual uint8_t* p() { + return const_cast(static_cast(this)->p()); + } + + virtual uint8_t* end() { + return const_cast(static_cast(this)->end()); + } + + virtual const uint8_t* start() const { + return nullptr; + } + + virtual const uint8_t* end() const { + return nullptr; + } + + virtual result read_at(uint64_t offset, uint64_t size, + 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 (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) { + return make_error_code(lief_errors::read_error); + } + + memcpy(dst, ptr, size); + return ok(); + } + return make_error_code(lief_errors::read_error); + } + + protected: + BinaryStream() = default; + + mutable size_t pos_ = 0; + bool endian_swap_ = false; + STREAM_TYPE stype_ = STREAM_TYPE::UNKNOWN; +}; + +class ScopedStream { + public: + ScopedStream(const ScopedStream&) = delete; + ScopedStream& operator=(const ScopedStream&) = delete; + + ScopedStream(ScopedStream&&) = delete; + ScopedStream& operator=(ScopedStream&&) = delete; + + explicit ScopedStream(BinaryStream& stream, uint64_t pos) : + pos_{stream.pos()}, + stream_{stream} + { + stream_.setpos(pos); + } + + explicit ScopedStream(BinaryStream& stream) : + pos_{stream.pos()}, + stream_{stream} + {} + + ~ScopedStream() { + stream_.setpos(pos_); + } + + BinaryStream* operator->() { + return &stream_; + } + + BinaryStream& operator*() { + return stream_; + } + + const BinaryStream& operator*() const { + return stream_; + } + + private: + uint64_t pos_ = 0; + BinaryStream& stream_; +}; + +class ToggleEndianness { + public: + ToggleEndianness(const ToggleEndianness&) = delete; + ToggleEndianness& operator=(const ToggleEndianness&) = delete; + + ToggleEndianness(ToggleEndianness&&) = delete; + ToggleEndianness& operator=(ToggleEndianness&&) = delete; + + explicit ToggleEndianness(BinaryStream& stream, bool value) : + endian_swap_(stream.should_swap()), + stream_{stream} + { + stream.set_endian_swap(value); + } + + explicit ToggleEndianness(BinaryStream& stream) : + endian_swap_(stream.should_swap()), + stream_{stream} + { + stream.set_endian_swap(!stream_.should_swap()); + } + + ~ToggleEndianness() { + stream_.set_endian_swap(endian_swap_); + } + + BinaryStream* operator->() { + return &stream_; + } + + BinaryStream& operator*() { + return stream_; + } + + const BinaryStream& operator*() const { + return stream_; + } + + private: + bool endian_swap_ = false; + BinaryStream& stream_; +}; + + +template +result BinaryStream::read() const { + result tmp = this->peek(); + if (!tmp) { + return tmp; + } + this->increment_pos(sizeof(T)); + return tmp; +} + +template +result BinaryStream::peek() const { + const auto current_p = pos(); + T ret{}; + if (auto res = peek_in(&ret, pos(), sizeof(T))) { + setpos(current_p); + if (endian_swap_) { + swap_endian(&ret); + } + return ret; + } + + setpos(current_p); + return make_error_code(lief_errors::read_error); +} + +template +result BinaryStream::peek(size_t offset) const { + const size_t saved_offset = this->pos(); + this->setpos(offset); + result r = this->peek(); + this->setpos(saved_offset); + return r; +} + + +template +const T* BinaryStream::peek_array(size_t size) const { + result raw = this->read_at(this->pos(), sizeof(T) * size); + if (!raw) { + return nullptr; + } + return reinterpret_cast(raw.value()); +} + +template +const T* BinaryStream::peek_array(size_t offset, size_t size) const { + const size_t saved_offset = this->pos(); + this->setpos(offset); + const T* r = this->peek_array(size); + this->setpos(saved_offset); + return r; +} + + +template +bool BinaryStream::can_read() const { + // Even though pos_ + sizeof(T) < ... => pos_ < ... + // the addition could overflow so it's worth checking both + return pos_ < size() && (pos_ + sizeof(T)) < size(); +} + + +template +bool BinaryStream::can_read(size_t offset) const { + // Even though offset + sizeof(T) < ... => offset < ... + // the addition could overflow so it's worth checking both + return offset < size() && (offset + sizeof(T)) < size(); +} + + +template +const T* BinaryStream::read_array(size_t size) const { + const T* tmp = this->peek_array(size); + this->increment_pos(sizeof(T) * size); + return tmp; +} + +} +#endif diff --git a/deps/LIEF/include/LIEF/BinaryStream/FileStream.hpp b/deps/LIEF/include/LIEF/BinaryStream/FileStream.hpp new file mode 100644 index 00000000000000..0e5d3e5cc86d9e --- /dev/null +++ b/deps/LIEF/include/LIEF/BinaryStream/FileStream.hpp @@ -0,0 +1,80 @@ +/* Copyright 2017 - 2025 R. Thomas + * Copyright 2017 - 2025 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_FILE_STREAM_H +#define LIEF_FILE_STREAM_H + +#include +#include +#include + +#include "LIEF/errors.hpp" +#include "LIEF/BinaryStream/BinaryStream.hpp" +#include "LIEF/visibility.h" + +namespace LIEF { + +/// Stream interface over a `std::ifstream` +class LIEF_API FileStream : public BinaryStream { + public: + static result from_file(const std::string& file); + FileStream(std::ifstream fs, uint64_t size) : + BinaryStream(STREAM_TYPE::FILE), + ifs_(std::move(fs)), + size_(size) + {} + + FileStream() = delete; + + FileStream(const FileStream&) = delete; + FileStream& operator=(const FileStream&) = delete; + + FileStream(FileStream&& other) noexcept = default; + FileStream& operator=(FileStream&& other) noexcept = default; + + uint64_t size() const override { + return size_; + } + + std::vector content() const; + ~FileStream() override = default; + + static bool classof(const BinaryStream& stream) { + return stream.type() == STREAM_TYPE::FILE; + } + + ok_error_t peek_in(void* dst, uint64_t offset, uint64_t size, + uint64_t /* virtual_address */= 0) const override { + if (offset > size_ || offset + size > size_) { + return make_error_code(lief_errors::read_error); + } + const auto pos = ifs_.tellg(); + ifs_.seekg(offset); + ifs_.read(static_cast(dst), size); + ifs_.seekg(pos); + return ok(); + } + + result read_at(uint64_t, uint64_t, uint64_t) const override { + return make_error_code(lief_errors::not_supported); + } + + protected: + mutable std::ifstream ifs_; + uint64_t size_ = 0; +}; +} + +#endif diff --git a/deps/LIEF/include/LIEF/BinaryStream/MemoryStream.hpp b/deps/LIEF/include/LIEF/BinaryStream/MemoryStream.hpp new file mode 100644 index 00000000000000..9bce7e764be3e9 --- /dev/null +++ b/deps/LIEF/include/LIEF/BinaryStream/MemoryStream.hpp @@ -0,0 +1,89 @@ +/* Copyright 2017 - 2025 R. Thomas + * Copyright 2017 - 2025 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_MEMORY_STREAM_H +#define LIEF_MEMORY_STREAM_H + +#include + +#include "LIEF/errors.hpp" +#include "LIEF/visibility.h" +#include "LIEF/BinaryStream/BinaryStream.hpp" + +namespace LIEF { +class Binary; +class LIEF_API MemoryStream : public BinaryStream { + public: + using BinaryStream::p; + using BinaryStream::end; + using BinaryStream::start; + + MemoryStream() = delete; + MemoryStream(uintptr_t base_address); + MemoryStream(uintptr_t base_address, uint64_t size) : + BinaryStream(BinaryStream::STREAM_TYPE::MEMORY), + baseaddr_(base_address), + size_(size) + {} + + MemoryStream(const MemoryStream&) = delete; + MemoryStream& operator=(const MemoryStream&) = delete; + + MemoryStream(MemoryStream&&) noexcept = default; + MemoryStream& operator=(MemoryStream&&) noexcept = default; + + uintptr_t base_address() const { + return this->baseaddr_; + } + + const uint8_t* p() const override { + return start() + pos(); + } + + const uint8_t* start() const override { + return reinterpret_cast(baseaddr_); + } + + const uint8_t* end() const override { + return start() + size_; + } + + void binary(Binary& bin) { + this->binary_ = &bin; + } + + Binary* binary() { + return this->binary_; + } + + uint64_t size() const override { + return size_; + } + + ~MemoryStream() override = default; + + static bool classof(const BinaryStream& stream) { + return stream.type() == BinaryStream::STREAM_TYPE::MEMORY; + } + + protected: + 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; +}; +} + +#endif diff --git a/deps/LIEF/include/LIEF/BinaryStream/SpanStream.hpp b/deps/LIEF/include/LIEF/BinaryStream/SpanStream.hpp new file mode 100644 index 00000000000000..ce7e8b4c003322 --- /dev/null +++ b/deps/LIEF/include/LIEF/BinaryStream/SpanStream.hpp @@ -0,0 +1,129 @@ +/* Copyright 2017 - 2025 R. Thomas + * Copyright 2017 - 2025 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_SPAN_STREAM_H +#define LIEF_SPAN_STREAM_H + +#include +#include +#include +#include +#include + +#include "LIEF/errors.hpp" +#include "LIEF/span.hpp" +#include "LIEF/visibility.h" +#include "LIEF/BinaryStream/BinaryStream.hpp" + +namespace LIEF { +class VectorStream; +class LIEF_API SpanStream : public BinaryStream { + public: + using BinaryStream::p; + using BinaryStream::end; + using BinaryStream::start; + + static result from_vector(const std::vector& data) { + return SpanStream(data); + } + + template + static result from_array(const std::array& data) { + return SpanStream(data.data(), N); + } + + SpanStream(span data) : + SpanStream(data.data(), data.size()) + {} + + SpanStream(span data) : + SpanStream(data.data(), data.size()) + {} + + SpanStream(const uint8_t* p, size_t size) : + BinaryStream(BinaryStream::STREAM_TYPE::SPAN), + data_{p, p + size} + {} + + SpanStream(const std::vector& data) : + SpanStream(data.data(), data.size()) + {} + + std::unique_ptr clone() const { + return std::unique_ptr(new SpanStream(*this)); + } + + SpanStream() = delete; + + SpanStream(const SpanStream& other) = default; + SpanStream& operator=(const SpanStream& other) = default; + + SpanStream(SpanStream&& other) noexcept = default; + SpanStream& operator=(SpanStream&& other) noexcept = default; + + uint64_t size() const override { + return data_.size(); + } + + const uint8_t* p() const override { + return data_.data() + this->pos(); + } + + const uint8_t* start() const override { + return data_.data(); + } + + const uint8_t* end() const override { + return data_.data() + size(); + } + + std::vector content() const { + return {data_.begin(), data_.end()}; + } + + result slice(size_t offset, size_t size) const { + if (offset > data_.size() || (offset + size) > data_.size()) { + return make_error_code(lief_errors::read_out_of_bound); + } + return data_.subspan(offset, size); + } + result slice(size_t offset) const { + if (offset > data_.size()) { + return make_error_code(lief_errors::read_out_of_bound); + } + return data_.subspan(offset, data_.size() - offset); + } + + std::unique_ptr to_vector() const; + + static bool classof(const BinaryStream& stream) { + return stream.type() == BinaryStream::STREAM_TYPE::SPAN; + } + + ~SpanStream() override = default; + + protected: + 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) { + return make_error_code(lief_errors::read_error); + } + return data_.data() + offset; + } + span data_; +}; +} + +#endif diff --git a/deps/LIEF/include/LIEF/BinaryStream/VectorStream.hpp b/deps/LIEF/include/LIEF/BinaryStream/VectorStream.hpp new file mode 100644 index 00000000000000..44293aa8c85795 --- /dev/null +++ b/deps/LIEF/include/LIEF/BinaryStream/VectorStream.hpp @@ -0,0 +1,97 @@ +/* Copyright 2017 - 2025 R. Thomas + * Copyright 2017 - 2025 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_VECTOR_STREAM_H +#define LIEF_VECTOR_STREAM_H + +#include +#include +#include + +#include "LIEF/errors.hpp" +#include "LIEF/visibility.h" +#include "LIEF/BinaryStream/BinaryStream.hpp" + +namespace LIEF { +class SpanStream; +class LIEF_API VectorStream : public BinaryStream { + public: + using BinaryStream::p; + using BinaryStream::end; + using BinaryStream::start; + + static result from_file(const std::string& file); + VectorStream(std::vector data) : + BinaryStream(BinaryStream::STREAM_TYPE::VECTOR), + binary_(std::move(data)), + size_(binary_.size()) + {} + + VectorStream() = delete; + + // VectorStream should not be copyable for performances reasons + VectorStream(const VectorStream&) = delete; + VectorStream& operator=(const VectorStream&) = delete; + + VectorStream(VectorStream&& other) noexcept = default; + VectorStream& operator=(VectorStream&& other) noexcept = default; + + uint64_t size() const override { + return size_; + } + + const std::vector& content() const { + return binary_; + } + + std::vector&& move_content() { + size_ = 0; + return std::move(binary_); + } + + const uint8_t* p() const override { + return this->binary_.data() + this->pos(); + } + + const uint8_t* start() const override { + return this->binary_.data(); + } + + const uint8_t* end() const override { + return this->binary_.data() + this->binary_.size(); + } + + + std::unique_ptr slice(uint32_t offset, size_t size) const; + std::unique_ptr slice(uint32_t offset) const; + + static bool classof(const BinaryStream& stream) { + return stream.type() == STREAM_TYPE::VECTOR; + } + + protected: + 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) { + return make_error_code(lief_errors::read_error); + } + return binary_.data() + offset; + } + std::vector binary_; + uint64_t size_ = 0; // Original size without alignment +}; +} + +#endif diff --git a/deps/LIEF/include/LIEF/COFF.hpp b/deps/LIEF/include/LIEF/COFF.hpp new file mode 100644 index 00000000000000..dcc13dbde0d3e8 --- /dev/null +++ b/deps/LIEF/include/LIEF/COFF.hpp @@ -0,0 +1,42 @@ +/* Copyright 2017 - 2025 R. Thomas + * Copyright 2017 - 2025 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_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/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 new file mode 100644 index 00000000000000..398776a324d418 --- /dev/null +++ b/deps/LIEF/include/LIEF/COFF/AuxiliarySymbol.hpp @@ -0,0 +1,125 @@ +/* Copyright 2017 - 2025 R. Thomas + * Copyright 2017 - 2025 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_COFF_AUXILIARY_SYMBOL_H +#define LIEF_COFF_AUXILIARY_SYMBOL_H + +#include +#include +#include + +#include "LIEF/visibility.h" +#include "LIEF/span.hpp" + +namespace LIEF { +class BinaryStream; + +namespace COFF { +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. +class LIEF_API AuxiliarySymbol { + public: + AuxiliarySymbol() = default; + AuxiliarySymbol(std::vector payload) : + type_(TYPE::UNKNOWN), + payload_(std::move(payload)) + {} + AuxiliarySymbol(const AuxiliarySymbol&) = default; + AuxiliarySymbol& operator=(const AuxiliarySymbol&) = default; + + AuxiliarySymbol(AuxiliarySymbol&&) = default; + AuxiliarySymbol& operator=(AuxiliarySymbol&&) = default; + + LIEF_LOCAL static std::unique_ptr + parse(Symbol& sym, std::vector payload); + + virtual std::unique_ptr clone() const { + return std::unique_ptr(new AuxiliarySymbol(*this)); + } + + /// Type discriminator for the subclasses + enum class TYPE { + UNKNOWN = 0, + 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) + {} + + static TYPE get_aux_type(const Symbol& sym); + + TYPE type() const { + return type_; + } + + /// For unknown type **only**, return the raw representation of this symbol + span payload() const { + return payload_; + } + + span payload() { + return payload_; + } + + virtual std::string to_string() const; + + virtual ~AuxiliarySymbol() = default; + + /// Helper to **downcast** a AuxiliarySymbol into a concrete implementation + template + const T* as() const { + static_assert(std::is_base_of::value, + "Require AuxiliarySymbol inheritance"); + if (T::classof(this)) { + return static_cast(this); + } + return nullptr; + } + + template + T* as() { + return const_cast(static_cast(this)->as()); + } + + LIEF_API friend + std::ostream& operator<<(std::ostream& os, const AuxiliarySymbol& aux) + { + os << aux.to_string(); + return os; + } + + protected: + TYPE type_ = TYPE::UNKNOWN; + std::vector payload_; +}; + +} +} +#endif diff --git a/deps/LIEF/include/LIEF/COFF/AuxiliarySymbols/AuxiliaryCLRToken.hpp b/deps/LIEF/include/LIEF/COFF/AuxiliarySymbols/AuxiliaryCLRToken.hpp new file mode 100644 index 00000000000000..cc2ee5feb71fb1 --- /dev/null +++ b/deps/LIEF/include/LIEF/COFF/AuxiliarySymbols/AuxiliaryCLRToken.hpp @@ -0,0 +1,106 @@ +/* Copyright 2017 - 2025 R. Thomas + * Copyright 2017 - 2025 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_COFF_AUXILIARY_CLR_TOKEN_H +#define LIEF_COFF_AUXILIARY_CLR_TOKEN_H + +#include + +#include "LIEF/visibility.h" +#include "LIEF/COFF/AuxiliarySymbol.hpp" + +namespace LIEF { +namespace COFF { +class Symbol; +class Parser; + +/// Auxiliary symbol associated with the `CLR_TOKEN` storage class +class LIEF_API AuxiliaryCLRToken : public AuxiliarySymbol { + public: + friend class Parser; + + LIEF_LOCAL static std::unique_ptr + parse(const std::vector& payload); + + AuxiliaryCLRToken() : + AuxiliarySymbol(AuxiliarySymbol::TYPE::CLR_TOKEN) + {} + + AuxiliaryCLRToken(uint8_t aux_type, uint8_t reserved, uint32_t symbol_idx, + std::vector rgb_reserved) : + AuxiliarySymbol(AuxiliarySymbol::TYPE::CLR_TOKEN), + aux_type_(aux_type), + reserved_(reserved), + symbol_idx_(symbol_idx), + rgb_reserved_(std::move(rgb_reserved)) + {} + + AuxiliaryCLRToken(const AuxiliaryCLRToken&) = default; + AuxiliaryCLRToken& operator=(const AuxiliaryCLRToken&) = default; + + AuxiliaryCLRToken(AuxiliaryCLRToken&&) = default; + AuxiliaryCLRToken& operator=(AuxiliaryCLRToken&&) = default; + + std::unique_ptr clone() const override { + return std::unique_ptr(new AuxiliaryCLRToken{*this}); + } + + /// `IMAGE_AUX_SYMBOL_TYPE` which should be `IMAGE_AUX_SYMBOL_TYPE_TOKEN_DEF` (1) + uint8_t aux_type() const { + return aux_type_; + } + + /// Reserved value (should be 0) + uint8_t reserved() const { + return aux_type_; + } + + /// Index in the symbol table + uint32_t symbol_idx() const { + return symbol_idx_; + } + + /// Symbol referenced by symbol_idx() (if resolved) + const Symbol* symbol() const { + return sym_; + } + + Symbol* symbol() { + return sym_; + } + + /// Reserved (padding) values. Should be 0 + span rgb_reserved() const { + return rgb_reserved_; + } + + std::string to_string() const override; + + static bool classof(const AuxiliarySymbol* sym) { + return sym->type() == AuxiliarySymbol::TYPE::CLR_TOKEN; + } + + ~AuxiliaryCLRToken() override = default; + private: + uint8_t aux_type_ = 0; + uint8_t reserved_ = 0; + uint32_t symbol_idx_ = 0; + std::vector rgb_reserved_; + Symbol* sym_ = nullptr; +}; + +} +} +#endif diff --git a/deps/LIEF/include/LIEF/COFF/AuxiliarySymbols/AuxiliaryFile.hpp b/deps/LIEF/include/LIEF/COFF/AuxiliarySymbols/AuxiliaryFile.hpp new file mode 100644 index 00000000000000..28ed0142d3415b --- /dev/null +++ b/deps/LIEF/include/LIEF/COFF/AuxiliarySymbols/AuxiliaryFile.hpp @@ -0,0 +1,85 @@ +/* Copyright 2017 - 2025 R. Thomas + * Copyright 2017 - 2025 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_PE_AUXILIARY_FILE_H +#define LIEF_PE_AUXILIARY_FILE_H + +#include + +#include "LIEF/visibility.h" +#include "LIEF/COFF/AuxiliarySymbol.hpp" + +namespace LIEF { +namespace COFF { + +/// This auxiliary symbol represents a filename (auxiliary format 4) +/// +/// 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 +class LIEF_API AuxiliaryFile : public AuxiliarySymbol { + public: + LIEF_LOCAL static std::unique_ptr + parse(const std::vector& payload); + + AuxiliaryFile() : + AuxiliarySymbol(AuxiliarySymbol::TYPE::FILE) + {} + + AuxiliaryFile(std::string file) : + AuxiliarySymbol(AuxiliarySymbol::TYPE::FILE), + filename_(std::move(file)) + {} + + AuxiliaryFile(const AuxiliaryFile&) = default; + AuxiliaryFile& operator=(const AuxiliaryFile&) = default; + + AuxiliaryFile(AuxiliaryFile&&) = default; + AuxiliaryFile& operator=(AuxiliaryFile&&) = default; + + std::unique_ptr clone() const override { + return std::unique_ptr(new AuxiliaryFile{*this}); + } + + /// The associated filename + const std::string& filename() const { + return filename_; + } + + AuxiliaryFile& filename(std::string file) { + filename_ = std::move(file); + return *this; + } + + std::string to_string() const override { + std::string out = "AuxiliaryFile {\n"; + out += " " + filename_ + "\n}"; + return out; + } + + ~AuxiliaryFile() override = default; + + static bool classof(const AuxiliarySymbol* sym) { + return sym->type() == AuxiliarySymbol::TYPE::FILE; + } + + protected: + std::string filename_; +}; + +} +} +#endif diff --git a/deps/LIEF/include/LIEF/COFF/AuxiliarySymbols/AuxiliaryFunctionDefinition.hpp b/deps/LIEF/include/LIEF/COFF/AuxiliarySymbols/AuxiliaryFunctionDefinition.hpp new file mode 100644 index 00000000000000..a3f184ff761041 --- /dev/null +++ b/deps/LIEF/include/LIEF/COFF/AuxiliarySymbols/AuxiliaryFunctionDefinition.hpp @@ -0,0 +1,110 @@ +/* Copyright 2017 - 2025 R. Thomas + * Copyright 2017 - 2025 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_COFF_AUXILIARY_FUNCTION_DEF_H +#define LIEF_COFF_AUXILIARY_FUNCTION_DEF_H + +#include + +#include "LIEF/visibility.h" +#include "LIEF/COFF/AuxiliarySymbol.hpp" + +namespace LIEF { +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 +class LIEF_API AuxiliaryFunctionDefinition : public AuxiliarySymbol { + public: + LIEF_LOCAL static std::unique_ptr + parse(const std::vector& payload); + + AuxiliaryFunctionDefinition() : + AuxiliarySymbol(AuxiliarySymbol::TYPE::FUNC_DEF) + {} + + 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) + {} + + AuxiliaryFunctionDefinition(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}); + } + + /// The symbol-table index of the corresponding `.bf` (begin function) + /// symbol record. + uint32_t tag_index() const { + return tag_index_; + } + + /// The size of the executable code for the function itself. + /// + /// If the function is in its own section, the `SizeOfRawData` in the section + /// header is greater or equal to this field, depending on alignment + /// considerations. + uint32_t total_size() const { + return total_size_; + } + + /// The file offset of the first COFF line-number entry for the function, + /// or zero if none exists (deprecated) + uint32_t ptr_to_line_number() const { + return ptr_to_linenb_; + } + + /// The symbol-table index of the record for the next function. If the function + /// is the last in the symbol table, this field is set to zero. + uint32_t ptr_to_next_func() const { + return ptr_to_next_func_; + } + + /// Padding value (should be 0) + uint16_t padding() const { + return padding_; + } + + std::string to_string() const override; + + static bool classof(const AuxiliarySymbol* sym) { + return sym->type() == AuxiliarySymbol::TYPE::FUNC_DEF; + } + + ~AuxiliaryFunctionDefinition() override = default; + + private: + uint32_t tag_index_ = 0; + uint32_t total_size_ = 0; + uint32_t ptr_to_linenb_ = 0; + uint32_t ptr_to_next_func_ = 0; + uint16_t padding_ = 0; +}; + +} +} +#endif diff --git a/deps/LIEF/include/LIEF/COFF/AuxiliarySymbols/AuxiliarySectionDefinition.hpp b/deps/LIEF/include/LIEF/COFF/AuxiliarySymbols/AuxiliarySectionDefinition.hpp new file mode 100644 index 00000000000000..9037b7700af3c9 --- /dev/null +++ b/deps/LIEF/include/LIEF/COFF/AuxiliarySymbols/AuxiliarySectionDefinition.hpp @@ -0,0 +1,166 @@ +/* Copyright 2017 - 2025 R. Thomas + * Copyright 2017 - 2025 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_COFF_AUXILIARY_SEC_DEF_H +#define LIEF_COFF_AUXILIARY_SEC_DEF_H + +#include + +#include "LIEF/visibility.h" +#include "LIEF/COFF/AuxiliarySymbol.hpp" + +namespace LIEF { +namespace COFF { + +/// This auxiliary symbol exposes information about the associated section. +/// +/// It **duplicates** some information that are provided in the section header +class LIEF_API AuxiliarySectionDefinition : public AuxiliarySymbol { + public: + LIEF_LOCAL static std::unique_ptr + parse(const std::vector& payload); + + AuxiliarySectionDefinition() : + AuxiliarySymbol(AuxiliarySymbol::TYPE::SEC_DEF) + {} + + AuxiliarySectionDefinition(uint32_t length, uint16_t nb_relocs, + uint16_t nb_lines, uint32_t checksum, + uint32_t sec_idx, uint8_t selection, + uint8_t reserved) : + AuxiliarySymbol(AuxiliarySymbol::TYPE::SEC_DEF), + length_(length), + nb_relocs_(nb_relocs), + nb_lines_(nb_lines), + checksum_(checksum), + sec_idx_(sec_idx), + selection_((COMDAT_SELECTION)selection), + reserved_(reserved) + {} + + AuxiliarySectionDefinition(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}); + } + + /// Values for the AuxiliarySectionDefinition::selection attribute + /// + /// 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. + NODUPLICATES = 1, + + /// Any section that defines the same COMDAT symbol can be linked; the rest + /// are removed. + 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. + SAME_SIZE, + + /// The linker chooses an arbitrary section among the definitions for this + /// symbol. If all definitions do not match exactly, a + /// `multiply defined symbol` error is issued. + EXACT_MATCH, + + /// The section is linked if a certain other COMDAT section is linked. + /// This other section is indicated by the Number field of the auxiliary + /// symbol record for the section definition. This setting is useful for + /// definitions that have components in multiple sections + /// (for example, code in one and data in another), but where all must be + /// linked or discarded as a set. The other section this section is + /// associated with must be a COMDAT section, which can be another + /// associative COMDAT section. An associative COMDAT section's section + /// association chain can't form a loop. The section association chain must + /// eventually come to a COMDAT section that doesn't have + /// COMDAT_SELECTION::ASSOCIATIVE set. + ASSOCIATIVE, + + /// 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 + }; + + /// The size of section data. The same as `SizeOfRawData` in the section header. + uint32_t length() const { + return length_; + } + + /// The number of relocation entries for the section. + uint16_t nb_relocs() const { + return nb_relocs_; + } + + /// The number of line-number entries for the section. + uint16_t nb_line_numbers() const { + return nb_lines_; + } + + /// The checksum for communal data. It is applicable if the + /// `IMAGE_SCN_LNK_COMDAT` flag is set in the section header. + uint32_t checksum() const { + return checksum_; + } + + /// One-based index into the section table for the associated section. + /// This is used when the COMDAT selection setting is 5. + uint32_t section_idx() const { + return sec_idx_; + } + + /// The COMDAT selection number. This is applicable if the section is a + /// COMDAT section. + COMDAT_SELECTION selection() const { + return selection_; + } + + /// Reserved value (should be 0) + uint8_t reserved() const { + return reserved_; + } + + std::string to_string() const override; + + static bool classof(const AuxiliarySymbol* sym) { + return sym->type() == AuxiliarySymbol::TYPE::SEC_DEF; + } + + ~AuxiliarySectionDefinition() override = default; + + private: + uint32_t length_ = 0; + uint16_t nb_relocs_ = 0; + uint16_t nb_lines_ = 0; + uint32_t checksum_ = 0; + uint32_t sec_idx_ = 0; + COMDAT_SELECTION selection_ = COMDAT_SELECTION::NONE; + uint8_t reserved_ = 0; +}; + +LIEF_API const char* to_string(AuxiliarySectionDefinition::COMDAT_SELECTION e); + +} +} +#endif diff --git a/deps/LIEF/include/LIEF/COFF/AuxiliarySymbols/AuxiliaryWeakExternal.hpp b/deps/LIEF/include/LIEF/COFF/AuxiliarySymbols/AuxiliaryWeakExternal.hpp new file mode 100644 index 00000000000000..488f787dec126c --- /dev/null +++ b/deps/LIEF/include/LIEF/COFF/AuxiliarySymbols/AuxiliaryWeakExternal.hpp @@ -0,0 +1,113 @@ +/* Copyright 2017 - 2025 R. Thomas + * Copyright 2017 - 2025 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_COFF_AUXILIARY_WEAK_EXTERNAL_H +#define LIEF_COFF_AUXILIARY_WEAK_EXTERNAL_H + +#include +#include + +#include "LIEF/visibility.h" +#include "LIEF/COFF/AuxiliarySymbol.hpp" + +namespace LIEF { + +namespace COFF { + +/// "Weak externals" are a mechanism for object files that allows flexibility at +/// link time. A module can contain an unresolved external symbol (`sym1`), but +/// it can also include an auxiliary record that indicates that if `sym1` is not +/// present at link time, another external symbol (`sym2`) is used to resolve +/// references instead. +/// +/// 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`. +/// +/// 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. + SEARCH_LIBRARY = 2, + /// `sym1` is an alias for sym2 + SEARCH_ALIAS = 3, + ANTI_DEPENDENCY = 4 + }; + + LIEF_LOCAL static std::unique_ptr + parse(const std::vector& payload); + + AuxiliaryWeakExternal() : + 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)) + { + assert(padding_.size() == 10); + } + + AuxiliaryWeakExternal(const AuxiliaryWeakExternal&) = default; + AuxiliaryWeakExternal& operator=(const AuxiliaryWeakExternal&) = default; + + AuxiliaryWeakExternal(AuxiliaryWeakExternal&&) = default; + AuxiliaryWeakExternal& operator=(AuxiliaryWeakExternal&&) = default; + + std::unique_ptr clone() const override { + return std::unique_ptr(new AuxiliaryWeakExternal{*this}); + } + + /// The symbol-table index of `sym2`, the symbol to be linked if `sym1` is not + /// found. + uint32_t sym_idx() const { + return sym_idx_; + } + + CHARACTERISTICS characteristics() const { + return (CHARACTERISTICS)characteristics_; + } + + span padding() const { + return padding_; + } + + std::string to_string() const override; + + static bool classof(const AuxiliarySymbol* sym) { + return sym->type() == AuxiliarySymbol::TYPE::WEAK_EXTERNAL; + } + + ~AuxiliaryWeakExternal() override = default; + + private: + uint32_t sym_idx_ = 0; + uint32_t characteristics_ = 0; + std::vector padding_; +}; + +LIEF_API const char* to_string(AuxiliaryWeakExternal::CHARACTERISTICS e); + +} +} +#endif diff --git a/deps/LIEF/include/LIEF/COFF/AuxiliarySymbols/AuxiliarybfAndefSymbol.hpp b/deps/LIEF/include/LIEF/COFF/AuxiliarySymbols/AuxiliarybfAndefSymbol.hpp new file mode 100644 index 00000000000000..53b0666b588842 --- /dev/null +++ b/deps/LIEF/include/LIEF/COFF/AuxiliarySymbols/AuxiliarybfAndefSymbol.hpp @@ -0,0 +1,60 @@ +/* Copyright 2017 - 2025 R. Thomas + * Copyright 2017 - 2025 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_COFF_AUXILIARY_BF_AND_EF_H +#define LIEF_COFF_AUXILIARY_BF_AND_EF_H + +#include + +#include "LIEF/visibility.h" +#include "LIEF/COFF/AuxiliarySymbol.hpp" + +namespace LIEF { + +namespace COFF { + +class LIEF_API AuxiliarybfAndefSymbol : public AuxiliarySymbol { + public: + LIEF_LOCAL static std::unique_ptr + parse(Symbol& sym, const std::vector& payload); + + AuxiliarybfAndefSymbol() : + AuxiliarySymbol(AuxiliarySymbol::TYPE::BF_AND_EF) + {} + + AuxiliarybfAndefSymbol(const AuxiliarybfAndefSymbol&) = default; + AuxiliarybfAndefSymbol& operator=(const AuxiliarybfAndefSymbol&) = default; + + AuxiliarybfAndefSymbol(AuxiliarybfAndefSymbol&&) = default; + AuxiliarybfAndefSymbol& operator=(AuxiliarybfAndefSymbol&&) = default; + + std::unique_ptr clone() const override { + return std::unique_ptr(new AuxiliarybfAndefSymbol{*this}); + } + + std::string to_string() const override { + return "AuxiliarybfAndefSymbol"; + } + + static bool classof(const AuxiliarySymbol* sym) { + return sym->type() == AuxiliarySymbol::TYPE::BF_AND_EF; + } + + ~AuxiliarybfAndefSymbol() override = default; +}; + +} +} +#endif diff --git a/deps/LIEF/include/LIEF/COFF/BigObjHeader.hpp b/deps/LIEF/include/LIEF/COFF/BigObjHeader.hpp new file mode 100644 index 00000000000000..a793092cd64887 --- /dev/null +++ b/deps/LIEF/include/LIEF/COFF/BigObjHeader.hpp @@ -0,0 +1,123 @@ +/* Copyright 2017 - 2025 R. Thomas + * Copyright 2017 - 2025 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_COFF_BIGOBJ_HEADER_H +#define LIEF_COFF_BIGOBJ_HEADER_H +#include +#include + +#include "LIEF/COFF/Header.hpp" + +#include "LIEF/visibility.h" +#include "LIEF/span.hpp" + +namespace LIEF { +namespace COFF { + +/// This class represents the header for a COFF object compiled +/// with `/bigobj` support (i.e. the number of sections can exceed 65536). +/// +/// The raw definition of the bigobj header is located in `winnt.h` and named +/// `ANON_OBJECT_HEADER_BIGOBJ` +class LIEF_API BigObjHeader : public Header { + public: + static constexpr auto UUID_SZ = 16; + BigObjHeader() : + Header(KIND::BIGOBJ) + {} + + static std::unique_ptr create(BinaryStream& stream); + + BigObjHeader& operator=(const BigObjHeader&) = default; + BigObjHeader(const BigObjHeader&) = default; + + BigObjHeader& operator=(BigObjHeader&&) = default; + BigObjHeader(BigObjHeader&&) = default; + + std::unique_ptr
clone() const override { + return std::unique_ptr
(new BigObjHeader(*this)); + } + + /// The version of this header which must be >= 2 + uint16_t version() const { + return version_; + } + + /// Originally named `ClassID`, this uuid should match: `{D1BAA1C7-BAEE-4ba9-AF20-FAF66AA4DCB8}` + span uuid() const { + return uuid_; + } + + /// Size of data that follows the header + uint32_t sizeof_data() const { + return sizeof_data_; + } + + /// 1 means that it contains metadata + uint32_t flags() const { + return flags_; + } + + /// Size of CLR metadata + uint32_t metadata_size() const { + return metadata_size_; + } + + /// Offset of CLR metadata + uint32_t metadata_offset() const { + return metadata_offset_; + } + + void version(uint16_t value) { + version_ = value; + } + + void sizeof_data(uint32_t value) { + sizeof_data_ = value; + } + + void flags(uint32_t value) { + flags_ = value; + } + + void metadata_size(uint32_t value) { + metadata_size_ = value; + } + + void metadata_offset(uint32_t value) { + metadata_offset_ = value; + } + + static bool classof(const Header* header) { + return header->kind() == Header::KIND::BIGOBJ; + } + + ~BigObjHeader() override = default; + + std::string to_string() const override; + + protected: + uint16_t version_ = 0; + std::array uuid_ = {}; + + uint32_t sizeof_data_ = 0; + uint32_t flags_ = 0; + uint32_t metadata_size_ = 0; + uint32_t metadata_offset_ = 0; +}; + +} +} +#endif diff --git a/deps/LIEF/include/LIEF/COFF/Binary.hpp b/deps/LIEF/include/LIEF/COFF/Binary.hpp new file mode 100644 index 00000000000000..9467836970e76b --- /dev/null +++ b/deps/LIEF/include/LIEF/COFF/Binary.hpp @@ -0,0 +1,252 @@ +/* Copyright 2017 - 2025 R. Thomas + * Copyright 2017 - 2025 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_COFF_BINARY_H +#define LIEF_COFF_BINARY_H +#include "LIEF/visibility.h" +#include "LIEF/iterators.hpp" +#include "LIEF/span.hpp" + +#include "LIEF/COFF/String.hpp" + +#include "LIEF/asm/Instruction.hpp" + +#include +#include +#include + +namespace LIEF { + +namespace assembly { +class Engine; +} + +namespace COFF { +class Header; +class Parser; +class Section; +class Relocation; +class Symbol; + +/// Class that represents a COFF Binary +class LIEF_API Binary { + public: + friend class Parser; + + /// Internal container used to store COFF's section + using sections_t = std::vector>; + + /// Iterator that outputs Section& object + using it_sections = ref_iterator; + + /// Iterator that outputs const Section& object + using it_const_sections = const_ref_iterator; + + /// Internal container used to store COFF's relocations + using relocations_t = std::vector>; + + /// Iterator that outputs Relocation& object + using it_relocations = ref_iterator; + + /// Iterator that outputs const Relocation& object + using it_const_relocations = const_ref_iterator; + + /// Internal container used to store COFF's strings + using strings_table_t = std::vector; + + /// Iterator that outputs String& object + using it_strings_table = ref_iterator; + + /// Iterator that outputs const String& object + using it_const_strings_table = const_ref_iterator; + + /// Internal container used to store COFF's symbols + using symbols_t = std::vector>; + + /// Iterator that outputs Symbol& object + using it_symbols = ref_iterator; + + /// Iterator that outputs Symbol& object + using it_const_symbols = const_ref_iterator; + + /// Instruction iterator + using instructions_it = iterator_range; + + /// Iterator which outputs COFF symbols representing functions + using it_functions = filter_iterator; + + /// Iterator which outputs COFF symbols representing functions + using it_const_function = const_filter_iterator; + + /// The COFF header + const Header& header() const { + return *header_; + } + + Header& header() { + return *header_; + } + + /// Iterator over the different sections located in this COFF binary + it_sections sections() { + return sections_; + } + + it_const_sections sections() const { + return sections_; + } + + /// Iterator over **all** the relocations used by this COFF binary + it_relocations relocations() { + return relocations_; + } + + it_const_relocations relocations() const { + return relocations_; + } + + /// Iterator over the COFF's symbols + it_symbols symbols() { + return symbols_; + } + + it_const_symbols symbols() const { + return symbols_; + } + + /// Iterator over the COFF's strings + it_const_strings_table string_table() const { + return strings_table_; + } + + it_strings_table string_table() { + 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 + /// the table. Hence, the first string starts a the offset 4. + String* find_string(uint32_t offset) { + auto it = std::find_if(strings_table_.begin(), strings_table_.end(), + [offset] (const String& item) { + return offset == item.offset(); + } + ); + return it == strings_table_.end() ? nullptr : &*it; + } + + const String* find_string(uint32_t offset) const { + return const_cast(this)->find_string(offset); + } + + /// Iterator over the functions implemented in this COFF + it_const_function functions() const; + + it_functions functions(); + + /// Try to find the function (symbol) with the given name + const Symbol* find_function(const std::string& name) const; + + Symbol* find_function(const std::string& name) { + 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; + + Symbol* find_demangled_function(const std::string& name) { + 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) { + /// std::cout << inst->to_string() << '\n'; + /// } + /// ``` + /// + /// \see LIEF::assembly::Instruction + instructions_it disassemble(const Symbol& symbol) const; + + /// Disassemble code for the given symbol name + /// + /// ```cpp + /// auto insts = binary->disassemble("main"); + /// for (std::unique_ptr inst : insts) { + /// std::cout << inst->to_string() << '\n'; + /// } + /// ``` + /// + /// \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 + instructions_it disassemble(const uint8_t* buffer, size_t size, + uint64_t address = 0) const; + + + /// Disassemble code provided by the given vector of bytes at the specified + /// `address` parameter. + /// + /// \see LIEF::assembly::Instruction + instructions_it disassemble(const std::vector& buffer, + uint64_t address = 0) const { + return disassemble(buffer.data(), buffer.size(), address); + } + + instructions_it disassemble(LIEF::span buffer, + uint64_t address = 0) const { + return disassemble(buffer.data(), buffer.size(), address); + } + + instructions_it disassemble(LIEF::span buffer, uint64_t address = 0) const { + return disassemble(buffer.data(), buffer.size(), address); + } + + std::string to_string() const; + + LIEF_API friend std::ostream& operator<<(std::ostream& os, const Binary& bin) { + os << bin.to_string(); + return os; + } + + ~Binary(); + + private: + Binary(); + std::unique_ptr
header_; + sections_t sections_; + relocations_t relocations_; + strings_table_t strings_table_; + symbols_t symbols_; + + mutable std::unordered_map> engines_; + + assembly::Engine* get_engine(uint64_t address) const; + + template + LIEF_LOCAL assembly::Engine* get_cache_engine(uint64_t address, F&& f) const; +}; + +} +} +#endif diff --git a/deps/LIEF/include/LIEF/COFF/Header.hpp b/deps/LIEF/include/LIEF/COFF/Header.hpp new file mode 100644 index 00000000000000..5239b73faa4979 --- /dev/null +++ b/deps/LIEF/include/LIEF/COFF/Header.hpp @@ -0,0 +1,155 @@ +/* Copyright 2017 - 2025 R. Thomas + * Copyright 2017 - 2025 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_COFF_HEADER_H +#define LIEF_COFF_HEADER_H +#include +#include +#include + +#include "LIEF/visibility.h" +#include "LIEF/PE/Header.hpp" + +namespace LIEF { +class BinaryStream; + +namespace COFF { + +/// Class that represents the COFF header. It is subclassed by +/// LIEF::COFF::RegularHeader and LIEF::COFF::BigObjHeader for normal vs +/// `/bigobj` files +class LIEF_API Header { + public: + + enum class KIND { + UNKNOWN = 0, + REGULAR, + BIGOBJ + }; + + /// The different architectures (mirrored from PE) + using MACHINE_TYPES = LIEF::PE::Header::MACHINE_TYPES; + + /// Create a header from the given stream + static std::unique_ptr
create(BinaryStream& stream); + static std::unique_ptr
create(BinaryStream& stream, KIND kind); + + Header() = default; + Header(KIND kind) : + kind_(kind) + {} + + Header& operator=(const Header&) = default; + Header(const Header&) = default; + + Header& operator=(Header&&) = default; + Header(Header&&) = default; + + virtual std::unique_ptr
clone() const = 0; + + /// The type of this header: whether it is regular or using the `/bigobj` + /// format + KIND kind() const { + return kind_; + } + + /// The machine type targeted by this COFF + MACHINE_TYPES machine() const { + return machine_; + } + + /// The number of sections + uint32_t nb_sections() const { + return nb_sections_; + } + + /// Offset of the symbols table + uint32_t pointerto_symbol_table() const { + return pointerto_symbol_table_; + } + + /// Number of symbols (including auxiliary symbols) + uint32_t nb_symbols() const { + return nb_symbols_; + } + + /// Timestamp when the COFF has been generated + uint32_t timedatestamp() const { + return timedatestamp_; + } + + void machine(MACHINE_TYPES machine) { + machine_ = machine; + } + + void nb_sections(uint32_t value) { + nb_sections_ = value; + } + + void pointerto_symbol_table(uint32_t value) { + pointerto_symbol_table_ = value; + } + + void nb_symbols(uint32_t value) { + nb_symbols_ = value; + } + + void timedatestamp(uint32_t value) { + timedatestamp_ = value; + } + + virtual std::string to_string() const; + + LIEF_API friend std::ostream& operator<<(std::ostream& os, const Header& hdr) { + os << hdr.to_string(); + return os; + } + + template + const T* as() const { + static_assert(std::is_base_of::value, + "Require Header inheritance"); + if (T::classof(this)) { + return static_cast(this); + } + return nullptr; + } + + virtual ~Header() = default; + + protected: + KIND kind_ = KIND::UNKNOWN; + MACHINE_TYPES machine_ = MACHINE_TYPES::UNKNOWN; + uint32_t nb_sections_ = 0; + uint32_t pointerto_symbol_table_ = 0; + uint32_t nb_symbols_ = 0; + uint32_t timedatestamp_ = 0; +}; + +LIEF_API inline const char* to_string(Header::KIND kind) { + switch (kind) { + case Header::KIND::UNKNOWN: return "UNKNOWN"; + case Header::KIND::REGULAR: return "REGULAR"; + case Header::KIND::BIGOBJ: return "BIGOBJ"; + } + return "UNKNOWN"; +} + +LIEF_API inline const char* to_string(Header::MACHINE_TYPES machine) { + return LIEF::PE::to_string(machine); +} +} +} +#endif diff --git a/deps/LIEF/include/LIEF/COFF/Parser.hpp b/deps/LIEF/include/LIEF/COFF/Parser.hpp new file mode 100644 index 00000000000000..fa1a5ff79d7d54 --- /dev/null +++ b/deps/LIEF/include/LIEF/COFF/Parser.hpp @@ -0,0 +1,109 @@ +/* Copyright 2017 - 2025 R. Thomas + * Copyright 2017 - 2025 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_COFF_PARSER_H +#define LIEF_COFF_PARSER_H +#include +#include "LIEF/visibility.h" + +#include "LIEF/BinaryStream/VectorStream.hpp" +#include "LIEF/BinaryStream/SpanStream.hpp" + +#include "LIEF/COFF/ParserConfig.hpp" +#include "LIEF/COFF/Header.hpp" + +namespace LIEF { +namespace COFF { +class Binary; +class Section; +class String; +class Symbol; + +class Parser { + public: + /// 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()); + + /// 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; + } + + /// \private + struct SymSec { + size_t sec_idx = 0; + Symbol* symbol = nullptr; + + friend bool operator<(const SymSec& lhs, const SymSec& rhs) { + return lhs.sec_idx < rhs.sec_idx; + } + + friend bool operator==(const SymSec& lhs, const SymSec& rhs) { + return lhs.sec_idx == rhs.sec_idx && lhs.symbol == rhs.symbol; + } + + friend bool operator!=(const SymSec& lhs, const SymSec& rhs) { + return !(lhs == rhs); + } + }; + + /// <=> std::unordered_multimap
+ using SymSecMap = std::vector; + + /// \private + LIEF_LOCAL void memoize(String str); + + /// \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) + {} + + ok_error_t process(); + ok_error_t parse_header(); + ok_error_t parse_optional_header(); + ok_error_t parse_sections(); + ok_error_t parse_relocations(Section& section); + ok_error_t parse_symbols(); + ok_error_t parse_string_table(); + + std::unique_ptr stream_; + std::unique_ptr bin_; + Header::KIND kind_ = Header::KIND::UNKNOWN; + + std::map memoize_coff_str_; + std::map symbol_idx_; + SymSecMap symsec_; + + ParserConfig config_; +}; +} +} +#endif diff --git a/deps/LIEF/include/LIEF/COFF/ParserConfig.hpp b/deps/LIEF/include/LIEF/COFF/ParserConfig.hpp new file mode 100644 index 00000000000000..3d0a09636b5262 --- /dev/null +++ b/deps/LIEF/include/LIEF/COFF/ParserConfig.hpp @@ -0,0 +1,38 @@ +/* Copyright 2017 - 2025 R. Thomas + * Copyright 2017 - 2025 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_COFF_PARSER_CONFIG_H +#define LIEF_COFF_PARSER_CONFIG_H + +#include "LIEF/visibility.h" + +namespace LIEF { +namespace COFF { +/// Class used to configure the COFF parser +class LIEF_API ParserConfig { + public: + static const ParserConfig& default_conf() { + static const ParserConfig DEFAULT; + return DEFAULT; + } + + static const ParserConfig& all() { + // To be updated when there is options that are off by default + return default_conf(); + } +}; +} +} +#endif diff --git a/deps/LIEF/include/LIEF/COFF/RegularHeader.hpp b/deps/LIEF/include/LIEF/COFF/RegularHeader.hpp new file mode 100644 index 00000000000000..1aab5525400d38 --- /dev/null +++ b/deps/LIEF/include/LIEF/COFF/RegularHeader.hpp @@ -0,0 +1,78 @@ +/* Copyright 2017 - 2025 R. Thomas + * Copyright 2017 - 2025 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_COFF_REGULAR_HEADER_H +#define LIEF_COFF_REGULAR_HEADER_H +#include +#include "LIEF/COFF/Header.hpp" +#include "LIEF/visibility.h" + +namespace LIEF { +namespace COFF { + +/// This class represents the COFF header for non-bigobj +class LIEF_API RegularHeader : public Header { + public: + RegularHeader() : + Header(KIND::REGULAR) + {} + + /// Create a RegularHeader from the given stream + static std::unique_ptr create(BinaryStream& stream); + + RegularHeader& operator=(const RegularHeader&) = default; + RegularHeader(const RegularHeader&) = default; + + RegularHeader& operator=(RegularHeader&&) = default; + RegularHeader(RegularHeader&&) = default; + + std::unique_ptr
clone() const override { + return std::unique_ptr
(new RegularHeader(*this)); + } + + /// The size of the optional header that follows this header (should be 0) + uint16_t sizeof_optionalheader() const { + return sizeof_optionalheader_; + } + + /// Characteristics + uint16_t characteristics() const { + return characteristics_; + } + + void sizeof_optionalheader(uint16_t value) { + sizeof_optionalheader_ = value; + } + + void characteristics(uint16_t value) { + characteristics_ = value; + } + + static bool classof(const Header* header) { + return header->kind() == Header::KIND::REGULAR; + } + + ~RegularHeader() override = default; + + std::string to_string() const override; + + protected: + uint16_t sizeof_optionalheader_ = 0; + uint16_t characteristics_ = 0; +}; + +} +} +#endif diff --git a/deps/LIEF/include/LIEF/COFF/Relocation.hpp b/deps/LIEF/include/LIEF/COFF/Relocation.hpp new file mode 100644 index 00000000000000..960caf0ad8b3c0 --- /dev/null +++ b/deps/LIEF/include/LIEF/COFF/Relocation.hpp @@ -0,0 +1,218 @@ +/* Copyright 2017 - 2025 R. Thomas + * Copyright 2017 - 2025 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_COFF_RELOCATION_H +#define LIEF_COFF_RELOCATION_H +#include +#include +#include + +#include "LIEF/visibility.h" +#include "LIEF/COFF/Header.hpp" +#include "LIEF/Abstract/Relocation.hpp" + +namespace LIEF { +class BinaryStream; +namespace COFF { +class Section; +class Parser; +class Symbol; + +/// This class represents a COFF relocation +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 ARM64 = 1 << 20; + static constexpr uint32_t MIPS = 1 << 21; + + /// The different relocation types. + /// + /// Please note that the original type is encoded on 16 bits but we encode + /// the type on 32-bits by adding a discriminator from the 17th bit + 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, + + AMD64_ABSOLUTE = X64 + 0x0000, + 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, + ARM_BRANCH20T = ARM + 0x0012, + ARM_BRANCH24T = ARM + 0x0014, + 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_PAGEBASE_REL21 = ARM64 + 0x0004, + 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_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, + MIPS_JMPADDR16 = MIPS + 0x0010, + MIPS_REFWORDNB = MIPS + 0x0022, + MIPS_PAIR = MIPS + 0x0025, + }; + + /// Convert a relocation enum type into a 16-bits value. + static uint16_t to_value(TYPE rtype) { + return (uint16_t)rtype; + } + + /// 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::AMD64: + return TYPE(value + X64); + + 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::R4000: + return TYPE(value + MIPS); + + 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); + + /// Symbol index associated with this relocation + uint32_t symbol_idx() const { + return symbol_idx_; + } + + /// Symbol associated with the relocation (if any) + Symbol* symbol() { + return symbol_; + } + + const Symbol* symbol() const { + return symbol_; + } + + /// Type of the relocation + TYPE type() const { + return type_; + } + + /// Section in which the relocation takes place + Section* section() { + return section_; + } + + const Section* section() const { + return section_; + } + + std::string to_string() const; + + LIEF_API friend std::ostream& operator<<(std::ostream& os, const Relocation& R) { + os << R.to_string(); + return os; + } + + ~Relocation() override = default; + + private: + Relocation() = default; + uint32_t symbol_idx_ = 0; + TYPE type_ = TYPE::UNKNOWN; + Section* section_ = nullptr; + Symbol* symbol_ = nullptr; +}; + +LIEF_API const char* to_string(Relocation::TYPE e); + +} +} +#endif diff --git a/deps/LIEF/include/LIEF/COFF/Section.hpp b/deps/LIEF/include/LIEF/COFF/Section.hpp new file mode 100644 index 00000000000000..d70a3117adf5e2 --- /dev/null +++ b/deps/LIEF/include/LIEF/COFF/Section.hpp @@ -0,0 +1,250 @@ +/* Copyright 2017 - 2025 R. Thomas + * Copyright 2017 - 2025 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_COFF_SECTION_H +#define LIEF_COFF_SECTION_H +#include +#include +#include + +#include "LIEF/visibility.h" +#include "LIEF/Abstract/Section.hpp" +#include "LIEF/PE/Section.hpp" +#include "LIEF/COFF/AuxiliarySymbols/AuxiliarySectionDefinition.hpp" +#include "LIEF/iterators.hpp" +#include "LIEF/optional.hpp" + +namespace LIEF { +class BinaryStream; + +namespace COFF { +class Relocation; +class Parser; +class Symbol; + + +/// This class represents a COFF section +class LIEF_API Section : public LIEF::Section { + public: + friend class Parser; + using LIEF::Section::name; + + using COMDAT_SELECTION = AuxiliarySectionDefinition::COMDAT_SELECTION; + + /// This structure wraps comdat information which is composed of the symbol + /// associated with the comdat section and its selection flag + struct LIEF_API ComdatInfo { + Symbol* symbol = nullptr; + COMDAT_SELECTION kind = COMDAT_SELECTION::NONE; + }; + + /// Mirror Characteristics from PE + using CHARACTERISTICS = LIEF::PE::Section::CHARACTERISTICS; + + /// Container for the relocations in this section (owned by the Binary object) + using relocations_t = std::vector; + + /// Iterator that outputs Relocation& + using it_relocations = ref_iterator; + + /// Iterator that outputs const Relocation& + using it_const_relocations = const_ref_iterator; + + /// Container for the symbols associated with this section (owned by the Binary object) + using symbols_t = std::vector; + + /// Iterator that outputs Symbol& + using it_symbols = ref_iterator; + + /// Iterator that outputs const Symbol& + using it_const_symbols = const_ref_iterator; + + /// Parse a section from the given stream + static std::unique_ptr
parse(BinaryStream& stream); + + /// Return the size of the data in the section. + uint32_t sizeof_raw_data() const { + return size_; + } + + /// Virtual size of the section (should be 0) + uint32_t virtual_size() const { + return virtual_size_; + } + + /// Content wrapped by this section + span content() const override { + return content_; + } + + /// Offset to the section's content + uint32_t pointerto_raw_data() const { + return offset_; + } + + /// Offset to the relocation table + uint32_t pointerto_relocation() const { + return pointer_to_relocations_; + } + + /// The file pointer to the beginning of line-number entries for the section. + /// + /// This is set to zero if there are no COFF line numbers. + /// This value should be zero for an image because COFF debugging information + /// is deprecated and modern debug information relies on the PDB files. + uint32_t pointerto_line_numbers() const { + return pointer_to_linenumbers_; + } + + /// Number of relocations. + /// + /// \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 { + return number_of_relocations_; + } + + /// Number of line number entries (if any). + uint16_t numberof_line_numbers() const { + return number_of_linenumbers_; + } + + /// Characteristics of the section: it provides information about + /// the permissions of the section when mapped. It can also provide + /// information about the *purpose* of the section (contain code, BSS-like, ...) + uint32_t characteristics() const { + return characteristics_; + } + + /// Check if the section has the given CHARACTERISTICS + bool has_characteristic(CHARACTERISTICS c) const { + return (characteristics() & (uint32_t)c) > 0; + } + + /// List of the section characteristics + std::vector characteristics_list() const { + return LIEF::PE::Section::characteristics_to_list(characteristics_); + } + + /// True if the section can be discarded as needed. + /// + /// This is typically the case for debug-related sections + bool is_discardable() const { + return has_characteristic(CHARACTERISTICS::MEM_DISCARDABLE); + } + + void clear(uint8_t c) { + std::fill(content_.begin(), content_.end(), c); + } + + /// Iterator over the relocations associated with this section + it_relocations relocations() { + return relocations_; + } + + it_const_relocations relocations() const { + return relocations_; + } + + /// Iterator over the symbols associated with this section + it_symbols symbols() { + return symbols_; + } + + it_const_symbols symbols() const { + return symbols_; + } + + /// Return comdat infomration (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 { + return has_characteristic(CHARACTERISTICS::LNK_NRELOC_OVFL) && + numberof_relocations() == std::numeric_limits::max(); + } + + void content(const std::vector& data) override { + content_ = data; + } + + void name(std::string name) override; + + void virtual_size(uint32_t virtual_sz) { + virtual_size_ = virtual_sz; + } + + void pointerto_raw_data(uint32_t ptr) { + offset(ptr); + } + + void pointerto_relocation(uint32_t ptr) { + pointer_to_relocations_ = ptr; + } + + void pointerto_line_numbers(uint32_t ptr) { + pointer_to_linenumbers_ = ptr; + } + + void numberof_relocations(uint16_t nb) { + number_of_relocations_ = nb; + } + + void numberof_line_numbers(uint16_t nb) { + number_of_linenumbers_ = nb; + } + + void sizeof_raw_data(uint32_t size) { + this->size(size); + } + + void characteristics(uint32_t characteristics) { + characteristics_ = characteristics; + } + + std::string to_string() const; + + LIEF_API friend std::ostream& operator<<(std::ostream& os, const Section& sec) { + os << sec.to_string(); + return os; + } + + ~Section() override = default; + + private: + Section() = default; + + std::vector content_; + 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; + + relocations_t relocations_; + symbols_t symbols_; +}; + +inline const char* to_string(Section::CHARACTERISTICS e) { + return LIEF::PE::to_string(e); +} + +} +} +#endif diff --git a/deps/LIEF/include/LIEF/COFF/String.hpp b/deps/LIEF/include/LIEF/COFF/String.hpp new file mode 100644 index 00000000000000..8e678762642dc8 --- /dev/null +++ b/deps/LIEF/include/LIEF/COFF/String.hpp @@ -0,0 +1,83 @@ +/* Copyright 2017 - 2025 R. Thomas + * Copyright 2017 - 2025 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_COFF_STRING_H +#define LIEF_COFF_STRING_H +#include +#include +#include + +#include "LIEF/visibility.h" + +namespace LIEF { +namespace COFF { + +/// This class represents a string located in the COFF string table. +/// +/// 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 +class LIEF_API String { + public: + String() = default; + String(uint32_t offset, std::string str) : + str_(std::move(str)), + offset_(offset) + {} + + String(const String&) = default; + String& operator=(const String&) = default; + + String(String&&) = default; + String& operator=(String&&) = default; + + ~String() = default; + + /// The actual string + const std::string& str() const { + return str_; + } + + /// The offset of this string the in the COFF string table. + /// This offset includes the first 4-bytes that holds the table size + uint32_t offset() const { + return offset_; + } + + String& str(std::string str) { + str_ = std::move(str); + return *this; + } + + String& offset(uint32_t value) { + offset_ = value; + return *this; + } + + friend LIEF_API + std::ostream& operator<<(std::ostream& os, const String& str) + { + os << str.str(); + return os; + } + + private: + std::string str_; + uint32_t offset_ = 0; +}; +} +} +#endif diff --git a/deps/LIEF/include/LIEF/COFF/Symbol.hpp b/deps/LIEF/include/LIEF/COFF/Symbol.hpp new file mode 100644 index 00000000000000..3a9d8a97fcb4b7 --- /dev/null +++ b/deps/LIEF/include/LIEF/COFF/Symbol.hpp @@ -0,0 +1,286 @@ +/* Copyright 2017 - 2025 R. Thomas + * Copyright 2017 - 2025 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_COFF_SYMBOL_H +#define LIEF_COFF_SYMBOL_H + +#include "LIEF/Abstract/Symbol.hpp" +#include "LIEF/visibility.h" +#include "LIEF/iterators.hpp" + +#include +#include + +namespace LIEF { +class BinaryStream; +namespace COFF { +class Parser; +class AuxiliarySymbol; +class String; +class Section; + +/// This class represents a COFF symbol +class LIEF_API Symbol : public LIEF::Symbol { + public: + 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; + + 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); + + Symbol(); + Symbol(const Symbol&); + Symbol& operator=(const Symbol&); + + Symbol(Symbol&&); + Symbol& operator=(Symbol&&); + + /// The symbol provides general type or debugging information but does not + /// 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. + static constexpr auto SYM_SEC_IDX_UNDEF = 0; + + static constexpr auto SYM_COMPLEX_TYPE_SHIFT = 4; + + /// 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 + }; + + enum class BASE_TYPE : uint32_t { + TY_NULL = 0, ///< No type information or unknown base type. + TY_VOID = 1, ///< Used with void pointers and functions. + TY_CHAR = 2, ///< A character (signed byte). + TY_SHORT = 3, ///< A 2-byte signed integer. + TY_INT = 4, ///< A natural integer type on the target. + TY_LONG = 5, ///< A 4-byte signed integer. + TY_FLOAT = 6, ///< A 4-byte floating-point number. + TY_DOUBLE = 7, ///< An 8-byte floating-point number. + TY_STRUCT = 8, ///< A structure. + TY_UNION = 9, ///< An union. + TY_ENUM = 10, ///< An enumerated type. + TY_MOE = 11, ///< A member of enumeration (a specific value). + 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. + }; + + enum class COMPLEX_TYPE : uint32_t { + TY_NULL = 0, ///< No complex type; simple scalar variable. + TY_POINTER = 1, ///< A pointer to base type. + TY_FUNCTION = 2, ///< A function that returns a base type. + TY_ARRAY = 3, ///< An array of base type. + }; + + /// Check if the given section index is a reserved value + static constexpr bool is_reversed_sec_idx(int16_t idx) { + return idx <= 0; + } + + /// The symbol type. The first byte represents the base type (see: base_type()) + /// while the upper byte represents the complex type, if any (see: + /// complex_type()). + uint16_t type() const { + return type_; + } + + /// Storage class of the symbol which indicates what kind of definition a + /// symbol represents. + STORAGE_CLASS storage_class() const { + return (STORAGE_CLASS)storage_class_; + } + + /// The simple (base) data type + BASE_TYPE base_type() const { + return (BASE_TYPE)(type_ & 0x0F); + } + + /// The complex type (if any) + COMPLEX_TYPE complex_type() const { + return (COMPLEX_TYPE)((type_ & 0xF0) >> SYM_COMPLEX_TYPE_SHIFT); + } + + /// The signed integer that identifies the section, using a one-based index + /// into the section table. Some values have special meaning: + /// + /// * 0: 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. + /// * -1: The symbol has an absolute (non-relocatable) value and is not an + /// address. + /// * -2: The symbol provides general type or debugging information but does + /// not correspond to a section. Microsoft tools use this setting along + /// with `.file` records + int16_t section_idx() const { + return section_idx_; + } + + /// Section associated with this symbol (if any) + Section* section() { + return section_; + } + + const Section* section() const { + return section_; + } + + bool is_external() const { + return storage_class() == STORAGE_CLASS::EXTERNAL; + } + + bool is_weak_external() const { + return storage_class() == STORAGE_CLASS::WEAK_EXTERNAL; + } + + bool is_absolute() const { + return section_idx() == SYM_SEC_IDX_ABS; + } + + bool is_undefined() const { + return is_external() && section_idx() == SYM_SEC_IDX_UNDEF && + value() == 0; + } + + bool is_function_line_info() const { + return storage_class() == STORAGE_CLASS::FUNCTION; + } + + bool is_function() const { + return complex_type() == COMPLEX_TYPE::TY_FUNCTION; + } + + bool is_file_record() const { + return storage_class() == STORAGE_CLASS::FILE; + } + + /// Auxiliary symbols associated with this symbol. + it_auxiliary_symbols_t auxiliary_symbols() { + return auxiliary_symbols_; + } + + it_const_auxiliary_symbols_t auxiliary_symbols() const { + return auxiliary_symbols_; + } + + /// Name of the symbol. If the symbol does not use a short name, it returns + /// the string pointed by the COFF string offset + const std::string& name() const override; + + std::string& name() override; + + /// COFF string used to represents the (long) symbol name + const String* coff_name() const { + return coff_name_; + } + + String* coff_name() { + return coff_name_; + } + + /// Demangled representation of the symbol or an empty string if it can't + /// be demangled + std::string demangled_name() const; + + Symbol& type(uint16_t ty) { + type_ = ty; + return *this; + } + + Symbol& storage_class(uint8_t value) { + storage_class_ = value; + return *this; + } + + Symbol& section_idx(int16_t idx) { + section_idx_ = idx; + return *this; + } + + /// Add a new auxiliary record + AuxiliarySymbol& add_aux(std::unique_ptr sym); + + std::string to_string() const; + + LIEF_API friend + std::ostream& operator<<(std::ostream& os, const Symbol& entry) + { + os << entry.to_string(); + return os; + } + + ~Symbol() override; + + private: + template + 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; + int16_t section_idx_ = 0; + auxiliary_symbols_t auxiliary_symbols_; + Section* section_ = nullptr; +}; + +LIEF_API const char* to_string(Symbol::STORAGE_CLASS e); +LIEF_API const char* to_string(Symbol::BASE_TYPE e); +LIEF_API const char* to_string(Symbol::COMPLEX_TYPE e); + +} +} +#endif diff --git a/deps/LIEF/include/LIEF/COFF/utils.hpp b/deps/LIEF/include/LIEF/COFF/utils.hpp new file mode 100644 index 00000000000000..73cb9fbf34ad82 --- /dev/null +++ b/deps/LIEF/include/LIEF/COFF/utils.hpp @@ -0,0 +1,63 @@ +/* Copyright 2017 - 2025 R. Thomas + * Copyright 2017 - 2025 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_COFF_UTILS_H +#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 + +namespace LIEF { +namespace COFF { + +/// This function determines if the given stream wraps a COFF binary and if so, +/// whether it's a regular or bigobj COFF. +LIEF_API Header::KIND get_kind(BinaryStream& stream); + +/// Check if the given stream wraps a COFF file +LIEF_API inline bool is_coff(BinaryStream& stream) { + return get_kind(stream) != Header::KIND::UNKNOWN; +} + +/// Check if the `file` is a COFF +LIEF_API bool is_coff(const std::string& file); + +/// Check if the given buffer points to a COFF file +LIEF_API inline bool is_coff(const uint8_t* buffer, size_t size) { + LIEF::SpanStream strm(buffer, size); + return is_coff(strm); +} + +/// Check if the given buffer points to a COFF file +LIEF_API inline bool is_coff(const std::vector& buffer) { + return is_coff(buffer.data(), buffer.size()); +} + +/// Check if the COFF file wrapped by the given stream is a `bigobj` +LIEF_API inline bool is_bigobj(BinaryStream& stream) { + return get_kind(stream) == Header::KIND::BIGOBJ; +} + +/// Check if the COFF file wrapped by the given stream is regular +/// (i.e. not a bigobj) +LIEF_API inline bool is_regular(BinaryStream& stream) { + return get_kind(stream) == Header::KIND::REGULAR; +} + +} +} +#endif diff --git a/deps/LIEF/include/LIEF/DEX.hpp b/deps/LIEF/include/LIEF/DEX.hpp new file mode 100644 index 00000000000000..f976b08117d525 --- /dev/null +++ b/deps/LIEF/include/LIEF/DEX.hpp @@ -0,0 +1,32 @@ +/* Copyright 2017 - 2025 R. Thomas + * Copyright 2017 - 2025 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_DEX_H +#define LIEF_DEX_H +#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" +#endif + +#endif diff --git a/deps/LIEF/include/LIEF/DEX/Class.hpp b/deps/LIEF/include/LIEF/DEX/Class.hpp new file mode 100644 index 00000000000000..0b1baff36ad5f2 --- /dev/null +++ b/deps/LIEF/include/LIEF/DEX/Class.hpp @@ -0,0 +1,138 @@ +/* Copyright 2017 - 2025 R. Thomas + * Copyright 2017 - 2025 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_DEX_CLASS_H +#define LIEF_DEX_CLASS_H + +#include +#include + +#include "LIEF/visibility.h" +#include "LIEF/Object.hpp" +#include "LIEF/iterators.hpp" + +#include "LIEF/DEX/enums.hpp" +#include "LIEF/DEX/deopt.hpp" + +namespace LIEF { +namespace DEX { +class Parser; +class Field; +class Method; + +/// Class which represents a DEX Class (i.e. a Java/Kotlin class) +class LIEF_API Class : public Object { + friend class Parser; + + public: + using access_flags_list_t = std::vector; + + using methods_t = std::vector; + using it_methods = ref_iterator; + using it_const_methods = const_ref_iterator; + + using fields_t = std::vector; + using it_fields = ref_iterator; + using it_const_fields = const_ref_iterator; + + using it_named_methods = filter_iterator; + using it_const_named_methods = const_filter_iterator; + + using it_named_fields = filter_iterator; + using it_const_named_fields = const_filter_iterator; + + 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); + + Class(); + Class(const Class&) = delete; + Class& operator=(const Class&) = delete; + + Class(std::string fullname, uint32_t access_flags = ACCESS_FLAGS::ACC_UNKNOWN, + Class* parent = nullptr, std::string source_filename = ""); + + /// Mangled class name (e.g. ``Lcom/example/android/MyActivity;``) + const std::string& fullname() const; + + /// Package Name + std::string package_name() const; + + /// Class name + std::string name() const; + + /// Demangled class name + std::string pretty_name() const; + + /// Check if the class has the given access flag + bool has(ACCESS_FLAGS f) const; + + /// Access flags used by this class + access_flags_list_t access_flags() const; + + /// Filename associated with this class (if any) + const std::string& source_filename() const; + + /// True if the current class extends another one + bool has_parent() const; + + /// Parent class + const Class* parent() const; + Class* parent(); + + /// Methods implemented in this class + it_const_methods methods() const; + it_methods methods(); + + /// Return Methods having the given name + it_named_methods methods(const std::string& name); + it_const_named_methods methods(const std::string& name) const; + + /// Fields implemented in this class + it_const_fields fields() const; + it_fields fields(); + + /// Return Fields having the given name + it_named_fields fields(const std::string& name); + it_const_named_fields fields(const std::string& name) const; + + /// De-optimize information + dex2dex_class_info_t dex2dex_info() const; + + /// Original index in the DEX class pool + size_t index() const; + + void accept(Visitor& visitor) const override; + + + LIEF_API friend std::ostream& operator<<(std::ostream& os, const Class& cls); + + ~Class() override; + + private: + std::string fullname_; + 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; +}; + +} // Namespace DEX +} // Namespace LIEF +#endif diff --git a/deps/LIEF/include/LIEF/DEX/CodeInfo.hpp b/deps/LIEF/include/LIEF/DEX/CodeInfo.hpp new file mode 100644 index 00000000000000..85410e665b1700 --- /dev/null +++ b/deps/LIEF/include/LIEF/DEX/CodeInfo.hpp @@ -0,0 +1,60 @@ +/* Copyright 2017 - 2025 R. Thomas + * Copyright 2017 - 2025 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_DEX_CODE_INFO_H +#define LIEF_DEX_CODE_INFO_H + +#include +#include + +#include "LIEF/visibility.h" +#include "LIEF/Object.hpp" + +namespace LIEF { +namespace DEX { +namespace details { +struct code_item; +} + +class Parser; + +class LIEF_API CodeInfo : public Object { + friend class Parser; + + public: + CodeInfo(); + CodeInfo(const details::code_item& codeitem); + + CodeInfo(const CodeInfo&); + CodeInfo& operator=(const CodeInfo&); + + void accept(Visitor& visitor) const override; + + uint16_t nb_registers() const; + + ~CodeInfo() override; + + 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 +} // Namespace LIEF +#endif diff --git a/deps/LIEF/include/LIEF/DEX/EnumToString.hpp b/deps/LIEF/include/LIEF/DEX/EnumToString.hpp new file mode 100644 index 00000000000000..18336a7028b940 --- /dev/null +++ b/deps/LIEF/include/LIEF/DEX/EnumToString.hpp @@ -0,0 +1,35 @@ +/* Copyright 2017 - 2025 R. Thomas + * Copyright 2017 - 2025 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_DEX_ENUM_TO_STRING_H +#define LIEF_DEX_ENUM_TO_STRING_H +#include "LIEF/visibility.h" +#include "LIEF/DEX/enums.hpp" +#include "LIEF/DEX/MapItem.hpp" +#include "LIEF/DEX/Type.hpp" + +namespace LIEF { +namespace DEX { + +LIEF_API const char* to_string(MapItem::TYPES e); +LIEF_API const char* to_string(ACCESS_FLAGS e); +LIEF_API const char* to_string(Type::TYPES e); +LIEF_API const char* to_string(Type::PRIMITIVES e); + +} // namespace DEX +} // namespace LIEF + +#endif + diff --git a/deps/LIEF/include/LIEF/DEX/Field.hpp b/deps/LIEF/include/LIEF/DEX/Field.hpp new file mode 100644 index 00000000000000..25283a81e00718 --- /dev/null +++ b/deps/LIEF/include/LIEF/DEX/Field.hpp @@ -0,0 +1,94 @@ +/* Copyright 2021 - 2025 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_DEX_FIELD_H +#define LIEF_DEX_FIELD_H + +#include +#include + +#include "LIEF/DEX/enums.hpp" + +#include "LIEF/visibility.h" +#include "LIEF/Object.hpp" + +#include "LIEF/DEX/Type.hpp" + +namespace LIEF { +namespace DEX { +class Parser; +class Class; + +/// Class which represent a DEX Field +class LIEF_API Field : public Object { + friend class Parser; + public: + using access_flags_list_t = std::vector; + + public: + Field(); + Field(std::string name, Class* parent = nullptr); + + Field(const Field&); + Field& operator=(const Field&); + + /// Name of the Field + const std::string& name() const; + + /// True if a class is associated with this field + /// (which should be the case) + bool has_class() const; + + /// Class associated with this Field + const Class* cls() const; + Class* cls(); + + /// Index in the DEX Fields pool + size_t index() const; + + /// True if this field is a static one. + bool is_static() const; + + /// Field's prototype + const Type* type() const; + Type* type(); + + void accept(Visitor& visitor) const override; + + /// Check if the field has the given ACCESS_FLAGS + bool has(ACCESS_FLAGS f) const; + + /// ACCESS_FLAGS as a list + access_flags_list_t access_flags() const; + + + LIEF_API friend std::ostream& operator<<(std::ostream& os, const Field& mtd); + + ~Field() override; + + private: + void set_static(bool v); + + private: + std::string name_; + Class* parent_ = nullptr; + Type* type_ = nullptr; + uint32_t access_flags_ = 0; + uint32_t original_index_ = UINT_MAX; + bool is_static_ = false; +}; + +} // Namespace DEX +} // Namespace LIEF +#endif diff --git a/deps/LIEF/include/LIEF/DEX/File.hpp b/deps/LIEF/include/LIEF/DEX/File.hpp new file mode 100644 index 00000000000000..6cf6240d82c8de --- /dev/null +++ b/deps/LIEF/include/LIEF/DEX/File.hpp @@ -0,0 +1,176 @@ +/* Copyright 2017 - 2025 R. Thomas + * Copyright 2017 - 2025 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_DEX_FILE_H +#define LIEF_DEX_FILE_H +#include + +#include "LIEF/visibility.h" +#include "LIEF/Object.hpp" + +#include "LIEF/DEX/Header.hpp" +#include "LIEF/DEX/MapList.hpp" +#include "LIEF/DEX/instructions.hpp" +#include "LIEF/DEX/deopt.hpp" +#include "LIEF/DEX/types.hpp" + +namespace LIEF { +namespace DEX { +class Parser; +class Class; +class Method; +class Type; +class Prototype; +class Field; + +/// Class that represents a DEX file +class LIEF_API File : public Object { + friend class Parser; + + public: + using classes_t = std::unordered_map; + using classes_list_t = std::vector>; + using it_classes = ref_iterator; + using it_const_classes = const_ref_iterator; + + using methods_t = std::vector>; + 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 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 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; + + /// Version of the current DEX file + dex_version_t version() const; + + /// Name of this file + const std::string& name() const; + + void name(const std::string& name); + + /// Location of this file + const std::string& location() const; + void location(const std::string& location); + + /// DEX header + const Header& header() const; + Header& header(); + + /// **All** classes used in the DEX file + it_const_classes classes() const; + it_classes classes(); + + /// 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; + + Class* get_class(const std::string& class_name); + + /// Return the DEX::Class object associated with the given index + const Class* get_class(size_t index) const; + + Class* get_class(size_t index); + + /// De-optimize information + dex2dex_info_t dex2dex_info() const; + + /// De-optimize information as JSON + 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(); + + /// Return an iterator over **all** the DEX::Field used in this DEX file + it_const_fields fields() const; + it_fields fields(); + + /// String pool + it_const_strings strings() const; + it_strings strings(); + + /// Type pool + it_const_types types() const; + it_types types(); + + /// Prototype pool + it_prototypes prototypes(); + it_const_prototypes prototypes() const; + + /// DEX Map + const MapList& map() const; + MapList& map(); + + /// Extract the current dex file and deoptimize it + std::string save(const std::string& path = "", bool deoptimize = true) const; + + std::vector raw(bool deoptimize = true) const; + + void accept(Visitor& visitor) const override; + + + ~File() override; + + LIEF_API friend std::ostream& operator<<(std::ostream& os, const File& file); + + private: + File(); + + void add_class(std::unique_ptr cls); + + 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); + + std::string name_; + std::string location_; + + Header header_; + classes_t classes_; + methods_t methods_; + fields_t fields_; + strings_t strings_; + types_t types_; + prototypes_t prototypes_; + MapList map_; + + classes_list_t class_list_; + std::vector original_data_; +}; + +} +} + +#endif diff --git a/deps/LIEF/include/LIEF/DEX/Header.hpp b/deps/LIEF/include/LIEF/DEX/Header.hpp new file mode 100644 index 00000000000000..b1d269f7a2119a --- /dev/null +++ b/deps/LIEF/include/LIEF/DEX/Header.hpp @@ -0,0 +1,136 @@ + +/* Copyright 2017 - 2025 R. Thomas + * Copyright 2017 - 2025 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_DEX_HEADER_H +#define LIEF_DEX_HEADER_H + +#include +#include +#include +#include + +#include "LIEF/visibility.h" +#include "LIEF/Object.hpp" + +namespace LIEF { +class Visitor; + +namespace DEX { +class Parser; + +/// Class which represents the DEX header. +/// This is the first structure that begins the DEX format. +/// +/// The official documentation is provided here: +/// https://source.android.com/devices/tech/dalvik/dex-format#header-item +class LIEF_API Header : public Object { + friend class Parser; + + public: + using location_t = std::pair; + + using magic_t = std::array; + using signature_t = std::array; + + Header(); + Header(const Header&); + Header& operator=(const Header&); + + template + LIEF_LOCAL Header(const T& header); + + /// The DEX magic bytes (``DEX\n`` followed by the DEX version) + magic_t magic() const; + + /// The file checksum + uint32_t checksum() const; + + /// SHA-1 DEX signature (which is not really used as a signature) + signature_t signature() const; + + /// Size of the entire file (including the current the header) + uint32_t file_size() const; + + /// Size of this header. It should be 0x70 + uint32_t header_size() const; + + /// File endianess of the file + uint32_t endian_tag() const; + + /// Offset from the start of the file to the map list (see: DEX::MapList) + uint32_t map() const; + + /// Offset and size of the string pool + location_t strings() const; + location_t link() const; + location_t types() const; + location_t prototypes() const; + location_t fields() const; + location_t methods() const; + location_t classes() const; + location_t data() const; + + uint32_t nb_classes() const; + + uint32_t nb_methods() const; + + void accept(Visitor& visitor) const override; + + + LIEF_API friend std::ostream& operator<<(std::ostream& os, const Header& hdr); + + ~Header() override; + + private: + magic_t magic_; + uint32_t checksum_; + signature_t signature_; + uint32_t file_size_; + + uint32_t header_size_; + uint32_t endian_tag_; + + uint32_t link_size_; + uint32_t link_off_; + + uint32_t map_off_; + + uint32_t string_ids_size_; + uint32_t string_ids_off_; + + uint32_t type_ids_size_; + uint32_t type_ids_off_; + + uint32_t proto_ids_size_; + uint32_t proto_ids_off_; + + uint32_t field_ids_size_; + uint32_t field_ids_off_; + + uint32_t method_ids_size_; + uint32_t method_ids_off_; + + uint32_t class_defs_size_; + uint32_t class_defs_off_; + + uint32_t data_size_; + uint32_t data_off_; +}; + +} // Namespace DEX +} // Namespace LIEF + +#endif diff --git a/deps/LIEF/include/LIEF/DEX/MapItem.hpp b/deps/LIEF/include/LIEF/DEX/MapItem.hpp new file mode 100644 index 00000000000000..bb791c472e18f1 --- /dev/null +++ b/deps/LIEF/include/LIEF/DEX/MapItem.hpp @@ -0,0 +1,96 @@ +/* Copyright 2017 - 2025 R. Thomas + * Copyright 2017 - 2025 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_MAP_ITEM_H +#define LIEF_MAP_ITEM_H + +#include +#include + +#include "LIEF/visibility.h" +#include "LIEF/Object.hpp" + +namespace LIEF { +namespace DEX { +class Parser; +class Class; + +/// Class which represents an element of the MapList object +class LIEF_API MapItem : public Object { + friend class Parser; + + 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, + 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, + + }; + + public: + MapItem(); + MapItem(TYPES type, uint32_t offset, uint32_t size, uint16_t reserved = 0); + + MapItem(const MapItem&); + MapItem& operator=(const MapItem&); + + /// The type of the item + TYPES type() const; + + /// Reserved value (likely for alignment prupose) + uint16_t reserved() const; + + /// The number of elements (the real meaning depends on the type) + uint32_t size() const; + + /// Offset from the start of the DEX file to the items associated with + /// the underlying TYPES + uint32_t offset() const; + + void accept(Visitor& visitor) const override; + + + LIEF_API friend std::ostream& operator<<(std::ostream& os, const MapItem& item); + + ~MapItem() override; + + private: + TYPES type_; + uint16_t reserved_; + uint32_t size_; + uint32_t offset_; + +}; + +} // Namespace DEX +} // Namespace LIEF +#endif diff --git a/deps/LIEF/include/LIEF/DEX/MapList.hpp b/deps/LIEF/include/LIEF/DEX/MapList.hpp new file mode 100644 index 00000000000000..c0c59ee83b1657 --- /dev/null +++ b/deps/LIEF/include/LIEF/DEX/MapList.hpp @@ -0,0 +1,84 @@ +/* Copyright 2017 - 2025 R. Thomas + * Copyright 2017 - 2025 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_MAP_LIST_H +#define LIEF_MAP_LIST_H +#include +#include + +#include "LIEF/visibility.h" +#include "LIEF/iterators.hpp" +#include "LIEF/Object.hpp" + +#include "LIEF/DEX/MapItem.hpp" + +namespace LIEF { +namespace DEX { +class Parser; +class Class; + +/// Class which represents the ``map_list`` structure that +/// follows the main DEX header. +/// +/// This MapList aims at referencing the location of other DEX structures as +/// described in https://source.android.com/devices/tech/dalvik/dex-format#map-item +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>; + + public: + MapList(); + + MapList(const MapList&); + MapList& operator=(const MapList&); + + /// Iterator over LIEF::DEX::MapItem + it_items_t items(); + it_const_items_t items() const; + + /// Check if the given type exists + bool has(MapItem::TYPES type) const; + + /// Return the LIEF::DEX::MapItem associated with the given type + const MapItem& get(MapItem::TYPES type) const; + + /// Return the LIEF::DEX::MapItem associated with the given type + MapItem& get(MapItem::TYPES type); + + /// Return the LIEF::DEX::MapItem associated with the given type + const MapItem& operator[](MapItem::TYPES type) const; + + /// Return the LIEF::DEX::MapItem associated with the given type + MapItem& operator[](MapItem::TYPES type); + + void accept(Visitor& visitor) const override; + + + LIEF_API friend std::ostream& operator<<(std::ostream& os, const MapList& mtd); + + ~MapList() override; + + private: + items_t items_; + +}; + +} // Namespace DEX +} // Namespace LIEF +#endif diff --git a/deps/LIEF/include/LIEF/DEX/Method.hpp b/deps/LIEF/include/LIEF/DEX/Method.hpp new file mode 100644 index 00000000000000..54eec9bd6627f1 --- /dev/null +++ b/deps/LIEF/include/LIEF/DEX/Method.hpp @@ -0,0 +1,118 @@ +/* Copyright 2017 - 2025 R. Thomas + * Copyright 2017 - 2025 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_DEX_METHOD_H +#define LIEF_DEX_METHOD_H + +#include +#include + +#include "LIEF/visibility.h" +#include "LIEF/Object.hpp" + +#include "LIEF/DEX/enums.hpp" +#include "LIEF/DEX/CodeInfo.hpp" +#include "LIEF/DEX/deopt.hpp" + +namespace LIEF { +namespace DEX { +class Parser; +class Class; +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; + + public: + using bytecode_t = std::vector; + Method(); + Method(std::string name, Class* parent = nullptr); + + Method(const Method&); + Method& operator=(const Method&); + + /// Name of the Method + const std::string& name() const; + + /// True if a class is associated with this method + bool has_class() const; + + /// DEX::Class associated with this Method or a nullptr + /// if not resolved + const Class* cls() const; + Class* cls(); + + /// Offset to the Dalvik Bytecode + uint64_t code_offset() const; + + /// Dalvik Bytecode as bytes + const bytecode_t& bytecode() const; + + /// Index in the DEX Methods pool + size_t index() const; + + /// True if this method is a virtual one. + /// i.e. not **static**, **private**, **finale** or constructor + bool is_virtual() const; + + /// Method's prototype or a nullptr if it is not resolved + const Prototype* prototype() const; + Prototype* prototype(); + + void insert_dex2dex_info(uint32_t pc, uint32_t index); + + void accept(Visitor& visitor) const override; + + const dex2dex_method_info_t& dex2dex_info() const; + + /// Check if the current method has the given ACCESS_FLAGS + bool has(ACCESS_FLAGS f) const; + + /// ACCESS_FLAGS as an std::set + access_flags_list_t access_flags() const; + + // CodeInfo to get additional data about a method i.e. argument count + const CodeInfo& code_info() const; + + LIEF_API friend std::ostream& operator<<(std::ostream& os, const Method& mtd); + + ~Method() override; + + private: + void set_virtual(bool v); + + private: + std::string name_; + Class* parent_ = nullptr; + Prototype* prototype_ = nullptr; + uint32_t access_flags_ = ACCESS_FLAGS::ACC_UNKNOWN; + uint32_t original_index_ = UINT_MAX; + bool is_virtual_ = false; + + uint64_t code_offset_ = 0; + std::vector bytecode_; + + CodeInfo code_info_; + + dex2dex_method_info_t dex2dex_info_; + +}; + +} // Namespace DEX +} // Namespace LIEF +#endif diff --git a/deps/LIEF/include/LIEF/DEX/Parser.hpp b/deps/LIEF/include/LIEF/DEX/Parser.hpp new file mode 100644 index 00000000000000..7b925d129da240 --- /dev/null +++ b/deps/LIEF/include/LIEF/DEX/Parser.hpp @@ -0,0 +1,124 @@ +/* Copyright 2017 - 2025 R. Thomas + * Copyright 2017 - 2025 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_DEX_PARSER_H +#define LIEF_DEX_PARSER_H + +#include +#include +#include +#include + +#include "LIEF/visibility.h" +#include "LIEF/DEX/types.hpp" + +namespace LIEF { +class VectorStream; + +namespace DEX { +class Class; +class Method; +class Field; +class File; +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 = ""); + + Parser& operator=(const Parser& copy) = delete; + Parser(const Parser& copy) = delete; + + private: + Parser(); + Parser(const std::string& file); + Parser(std::vector data); + ~Parser(); + + void init(const std::string& name, dex_version_t version); + + template + void parse_file(); + + template + void parse_header(); + + template + void parse_map(); + + template + void parse_strings(); + + template + void parse_types(); + + template + void parse_fields(); + + template + void parse_prototypes(); + + template + void parse_methods(); + + template + void parse_classes(); + + template + void parse_class_data(uint32_t offset, Class& cls); + + template + void parse_field(size_t index, Class& cls, bool is_static); + + template + void parse_method(size_t index, Class& cls, bool is_virtual); + + template + void parse_code_info(uint32_t offset, Method& method); + + void resolve_inheritance(); + + void resolve_external_methods(); + + void resolve_external_fields(); + + void resolve_types(); + + std::unique_ptr file_; + + // Map of inheritance relationship when parsing classes ('parse_classes') + // The key is the parent class name of the value + std::unordered_multimap inheritance_; + + // Map of method/class relationship when parsing methods ('parse_methods') + // The key is the Class name in which the method is defined + std::unordered_multimap class_method_map_; + + // Map of field/class relationship when parsing fields ('parse_fields') + // The key is the Class name in which the field is defined + std::unordered_multimap class_field_map_; + + std::unordered_multimap class_type_map_; + + std::unique_ptr stream_; +}; + +} // namespace DEX +} // namespace LIEF +#endif diff --git a/deps/LIEF/include/LIEF/DEX/Prototype.hpp b/deps/LIEF/include/LIEF/DEX/Prototype.hpp new file mode 100644 index 00000000000000..ff6413a5c0b88e --- /dev/null +++ b/deps/LIEF/include/LIEF/DEX/Prototype.hpp @@ -0,0 +1,64 @@ +/* Copyright 2017 - 2025 R. Thomas + * Copyright 2017 - 2025 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_DEX_PROTOTYPE_H +#define LIEF_DEX_PROTOTYPE_H + +#include "LIEF/visibility.h" +#include "LIEF/Object.hpp" +#include "LIEF/iterators.hpp" + +namespace LIEF { +namespace DEX { +class Parser; +class Type; + +/// Class which represents a DEX method prototype +class LIEF_API Prototype : public Object { + friend class Parser; + + public: + using parameters_type_t = std::vector; + 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(); + + /// Types of the parameters + it_const_params parameters_type() const; + it_params parameters_type(); + + void accept(Visitor& visitor) const override; + + + 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 +} // Namespace LIEF +#endif diff --git a/deps/LIEF/include/LIEF/DEX/Type.hpp b/deps/LIEF/include/LIEF/DEX/Type.hpp new file mode 100644 index 00000000000000..0c93f4922f7ea8 --- /dev/null +++ b/deps/LIEF/include/LIEF/DEX/Type.hpp @@ -0,0 +1,113 @@ +/* Copyright 2017 - 2025 R. Thomas + * Copyright 2017 - 2025 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_DEX_TYPE_H +#define LIEF_DEX_TYPE_H + +#include +#include +#include + +#include "LIEF/visibility.h" +#include "LIEF/Object.hpp" + +namespace LIEF { +namespace DEX { +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 +class LIEF_API Type : public Object { + friend class Parser; + + public: + enum class TYPES { + UNKNOWN = 0, + PRIMITIVE = 1, + CLASS = 2, + ARRAY = 3, + }; + + enum class PRIMITIVES { + VOID_T = 0x01, + BOOLEAN = 0x02, + BYTE = 0x03, + SHORT = 0x04, + CHAR = 0x05, + INT = 0x06, + LONG = 0x07, + FLOAT = 0x08, + DOUBLE = 0x09, + }; + + using array_t = std::vector; + + public: + static std::string pretty_name(PRIMITIVES p); + + public: + Type(); + Type(const std::string& mangled); + Type(const Type& other); + + /// Whether it is a primitive type, a class, ... + TYPES type() const; + + const Class& cls() const; + const array_t& array() const; + const PRIMITIVES& primitive() const; + + /// **IF** the current type is a TYPES::CLASS, return the + /// associated DEX::CLASS. Otherwise the returned value is **undefined**. + Class& cls(); + + /// **IF** the current type is a TYPES::ARRAY, return the + /// associated array. Otherwise the returned value is **undefined**. + array_t& array(); + + /// **IF** the current type is a TYPES::PRIMITIVE, return the + /// associated PRIMITIVES. Otherwise the returned value is **undefined**. + PRIMITIVES& primitive(); + + /// Return the array dimension if the current type is + /// an array. Otherwise it returns 0 + 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(); + + void accept(Visitor& visitor) const override; + + + LIEF_API friend std::ostream& operator<<(std::ostream& os, const Type& type); + + ~Type() override; + + private: + void parse(const std::string& type); + + TYPES type_{TYPES::UNKNOWN}; + union { + Class* cls_{nullptr}; + array_t* array_; + PRIMITIVES* basic_; + }; +}; + +} // Namespace DEX +} // Namespace LIEF +#endif diff --git a/deps/LIEF/include/LIEF/DEX/deopt.hpp b/deps/LIEF/include/LIEF/DEX/deopt.hpp new file mode 100644 index 00000000000000..4164a8ffecc43b --- /dev/null +++ b/deps/LIEF/include/LIEF/DEX/deopt.hpp @@ -0,0 +1,34 @@ +/* Copyright 2017 - 2025 R. Thomas + * Copyright 2017 - 2025 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_DEX_DEOPT_TYPES_H +#define LIEF_DEX_DEOPT_TYPES_H +#include +#include + +namespace LIEF { +namespace DEX { +class Class; +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; + +} +} + +#endif diff --git a/deps/LIEF/include/LIEF/DEX/enums.hpp b/deps/LIEF/include/LIEF/DEX/enums.hpp new file mode 100644 index 00000000000000..4e808d8f9b76d1 --- /dev/null +++ b/deps/LIEF/include/LIEF/DEX/enums.hpp @@ -0,0 +1,82 @@ +/* Copyright 2017 - 2025 R. Thomas + * Copyright 2017 - 2025 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_DEX_ENUMS_H +#define LIEF_DEX_ENUMS_H + +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 +}; + + +enum METHOD_TYPES { + METHOD_UNKNOWN = 0x00, + METHOD_VIRTUAL = 0x01, + METHOD_DIRECT = 0x02, // Deprecated + + 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, +}; + +} +} +#endif diff --git a/deps/LIEF/include/LIEF/DEX/hash.hpp b/deps/LIEF/include/LIEF/DEX/hash.hpp new file mode 100644 index 00000000000000..42184a42af9ef1 --- /dev/null +++ b/deps/LIEF/include/LIEF/DEX/hash.hpp @@ -0,0 +1,66 @@ +/* Copyright 2017 - 2025 R. Thomas + * Copyright 2017 - 2025 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_DEX_HASH_H +#define LIEF_DEX_HASH_H + +#include "LIEF/visibility.h" +#include "LIEF/hash.hpp" + +namespace LIEF { +class Object; + +namespace DEX { + +class Class; +class Field; +class File; +class Header; +class MapItem; +class MapList; +class Method; +class Prototype; +class CodeInfo; +class Type; + +/// Class which implements a visitor to compute +/// a **deterministic** hash for LIEF DEX objects +class LIEF_API Hash : public LIEF::Hash { + public: + static LIEF::Hash::value_type hash(const Object& obj); + + public: + using LIEF::Hash::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 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; + + ~Hash() override; +}; + +} +} + +#endif diff --git a/deps/LIEF/include/LIEF/DEX/instructions.hpp b/deps/LIEF/include/LIEF/DEX/instructions.hpp new file mode 100644 index 00000000000000..4c076d4575fabb --- /dev/null +++ b/deps/LIEF/include/LIEF/DEX/instructions.hpp @@ -0,0 +1,356 @@ +/* Copyright 2017 - 2025 R. Thomas + * Copyright 2017 - 2025 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_DEX_INSTRUCTIONS_H +#define LIEF_DEX_INSTRUCTIONS_H +#include "LIEF/visibility.h" +#include "LIEF/types.hpp" +#include + +namespace LIEF { +namespace DEX { + +enum SWITCH_ARRAY_IDENT : uint16_t { + IDENT_PACKED_SWITCH = 0x0100, + IDENT_SPARSE_SWITCH = 0x0200, + 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_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_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_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, + + // 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, + + // From DEX 38 + OP_INVOKE_POLYMORPHIC = 0xfa, + OP_INVOKE_POLYMORPHIC_RANGE = 0xfb, + OP_INVOKE_CUSTOM = 0xfc, + OP_INVOKE_CUSTOM_RANGE = 0xfd, + + // From DEX 39 + OP_CONST_METHOD_HANDLE = 0xfe, + OP_CONST_METHOD_TYPE = 0xff, +}; + +enum INST_FORMATS : uint8_t { + F_00x = 0, + F_10x, + F_12x, + F_11n, + F_11x, + F_10t, + F_20t, + F_20bc, + F_22x, + F_21t, + F_21s, + F_21h, + F_21c, + F_23x, + F_22b, + F_22t, + F_22s, + F_22c, + F_22cs, + F_30t, + F_32x, + F_31i, + F_31t, + F_31c, + F_35c, + F_35ms, + F_35mi, + F_3rc, + F_3rms, + F_3rmi, + F_51l, + + // Since DEX 38 + F_45cc, + F_4rcc, +}; + +struct packed_switch { + uint16_t ident; // 0x0100 + uint16_t size; + uint32_t first_key; + // uint32_t targets[size] +}; + + +struct sparse_switch { + uint16_t ident; // 0x0200 + uint16_t size; + // uint32_t targets[size] +}; + +struct fill_array_data { + uint16_t ident; + uint16_t element_width; + uint32_t size; + //uint8_t data[size]; +}; + + +/// Return the INST_FORMATS format associated with the given opcode +LIEF_API INST_FORMATS inst_format_from_opcode(OPCODES op); + +LIEF_API size_t inst_size_from_format(INST_FORMATS fmt); +LIEF_API size_t inst_size_from_opcode(OPCODES op); + +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); + +} // Namespace LIEF +} // Namespace DEX + +#endif + diff --git a/deps/LIEF/include/LIEF/DEX/json.hpp b/deps/LIEF/include/LIEF/DEX/json.hpp new file mode 100644 index 00000000000000..74b79fe48e4584 --- /dev/null +++ b/deps/LIEF/include/LIEF/DEX/json.hpp @@ -0,0 +1,33 @@ +/* Copyright 2017 - 2025 R. Thomas + * Copyright 2017 - 2025 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_DEX_PUBLIC_JSON_H +#define LIEF_DEX_PUBLIC_JSON_H + +#include "LIEF/visibility.h" +#include + +namespace LIEF { +class Object; + +namespace DEX { + +LIEF_API std::string to_json(const Object& v); + +} +} + + +#endif diff --git a/deps/LIEF/include/LIEF/DEX/types.hpp b/deps/LIEF/include/LIEF/DEX/types.hpp new file mode 100644 index 00000000000000..e38b44ea5aeba9 --- /dev/null +++ b/deps/LIEF/include/LIEF/DEX/types.hpp @@ -0,0 +1,28 @@ +/* Copyright 2017 - 2025 R. Thomas + * Copyright 2017 - 2025 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_DEX_TYPEDEF_H +#define LIEF_DEX_TYPEDEF_H +#include + +namespace LIEF { +namespace DEX { + +using dex_version_t = uint32_t; + +} +} + +#endif diff --git a/deps/LIEF/include/LIEF/DEX/utils.hpp b/deps/LIEF/include/LIEF/DEX/utils.hpp new file mode 100644 index 00000000000000..ceecc6b0a0a8cc --- /dev/null +++ b/deps/LIEF/include/LIEF/DEX/utils.hpp @@ -0,0 +1,49 @@ +/* Copyright 2017 - 2025 R. Thomas + * Copyright 2017 - 2025 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_DEX_UTILS_H +#define LIEF_DEX_UTILS_H + +#include +#include + +#include "LIEF/DEX/types.hpp" + +#include "LIEF/types.hpp" +#include "LIEF/visibility.h" + +namespace LIEF { +class BinaryStream; +namespace DEX { + +/// Check if the given file is a DEX. +LIEF_API bool is_dex(const std::string& file); + +/// Check if the given raw data is a DEX. +LIEF_API bool is_dex(const std::vector& raw); + +/// Return the DEX version of the given file +LIEF_API dex_version_t version(const std::string& file); + +/// Return the DEX version of the raw data +LIEF_API dex_version_t version(const std::vector& raw); + +dex_version_t version(BinaryStream& stream); + +} +} + + +#endif diff --git a/deps/LIEF/include/LIEF/DWARF.hpp b/deps/LIEF/include/LIEF/DWARF.hpp new file mode 100644 index 00000000000000..39c516b5e6cbf0 --- /dev/null +++ b/deps/LIEF/include/LIEF/DWARF.hpp @@ -0,0 +1,42 @@ +/* Copyright 2017 - 2025 R. Thomas + * Copyright 2017 - 2025 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_DWARF_H +#define LIEF_DWARF_H + +#include "LIEF/DWARF/enums.hpp" +#include "LIEF/DWARF/DebugInfo.hpp" +#include "LIEF/DWARF/CompilationUnit.hpp" +#include "LIEF/DWARF/Function.hpp" +#include "LIEF/DWARF/Variable.hpp" +#include "LIEF/DWARF/Scope.hpp" +#include "LIEF/DWARF/Type.hpp" +#include "LIEF/DWARF/types.hpp" +#include "LIEF/DWARF/Parameter.hpp" +#include "LIEF/DWARF/Editor.hpp" + +#include "LIEF/DWARF/editor/CompilationUnit.hpp" +#include "LIEF/DWARF/editor/Function.hpp" +#include "LIEF/DWARF/editor/Variable.hpp" +#include "LIEF/DWARF/editor/Type.hpp" +#include "LIEF/DWARF/editor/PointerType.hpp" +#include "LIEF/DWARF/editor/EnumType.hpp" +#include "LIEF/DWARF/editor/BaseType.hpp" +#include "LIEF/DWARF/editor/ArrayType.hpp" +#include "LIEF/DWARF/editor/FunctionType.hpp" +#include "LIEF/DWARF/editor/TypeDef.hpp" +#include "LIEF/DWARF/editor/StructType.hpp" + +#endif diff --git a/deps/LIEF/include/LIEF/DWARF/CompilationUnit.hpp b/deps/LIEF/include/LIEF/DWARF/CompilationUnit.hpp new file mode 100644 index 00000000000000..c9491b530d4099 --- /dev/null +++ b/deps/LIEF/include/LIEF/DWARF/CompilationUnit.hpp @@ -0,0 +1,282 @@ +/* Copyright 2022 - 2025 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_COMPILATION_UNIT_H +#define LIEF_DWARF_COMPILATION_UNIT_H +#include +#include +#include + +#include "LIEF/visibility.h" +#include "LIEF/range.hpp" +#include "LIEF/iterators.hpp" +#include "LIEF/DWARF/Function.hpp" +#include "LIEF/DWARF/Type.hpp" + +namespace LIEF { +namespace dwarf { + +namespace details { +class CompilationUnit; +class CompilationUnitIt; +} + +/// This class represents a DWARF compilation unit +class LIEF_API CompilationUnit { + public: + class LIEF_API Iterator { + 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; + + class LIEF_API PointerProxy { + // Inspired from LLVM's iterator_facade_base + friend class Iterator; + public: + pointer operator->() const { return R.get(); } + + private: + value_type R; + + template + PointerProxy(RefT &&R) : R(std::forward(R)) {} // NOLINT(bugprone-forwarding-reference-overload) + }; + + Iterator(const Iterator&); + Iterator(Iterator&&) noexcept; + Iterator(std::unique_ptr impl); + ~Iterator(); + + friend LIEF_API bool operator==(const Iterator& LHS, const Iterator& RHS); + friend LIEF_API bool operator!=(const Iterator& LHS, const Iterator& RHS) { + return !(LHS == RHS); + } + + Iterator& operator++(); + Iterator& operator--(); + + Iterator operator--(int) { + Iterator tmp = *static_cast(this); + --*static_cast(this); + return tmp; + } + + Iterator operator++(int) { + Iterator tmp = *static_cast(this); + ++*static_cast(this); + return tmp; + } + + std::unique_ptr operator*() const; + + PointerProxy operator->() const { + return static_cast(this)->operator*(); + } + + private: + std::unique_ptr impl_; + }; + + /// Iterator over the dwarf::Function + using functions_it = iterator_range; + + /// Iterator over the dwarf::Type + using types_it = iterator_range; + + /// Iterator over the CompilationUnit's variables + using vars_it = iterator_range; + + /// Languages supported by the DWARF (v5) format. + /// See: https://dwarfstd.org/languages.html + /// + /// Some languages (like C++11, C++17, ..) have a version (11, 17, ...) which + /// is stored in a dedicated attribute: #version + class Language { + public: + enum LANG : uint32_t { + UNKNOWN = 0, + C, + CPP, + RUST, + DART, + MODULA, + FORTRAN, + SWIFT, + D, + JAVA, + COBOL, + }; + + /// The language itself + LANG lang = UNKNOWN; + + /// Version of the language (e.g. 17 for C++17) + uint32_t version = 0; + + Language() = default; + Language(LANG lang, uint32_t version) : + lang(lang), version(version) + {} + Language(LANG lang) : + Language(lang, 0) + {} + + Language(const Language&) = default; + Language& operator=(const Language&) = default; + Language(Language&&) = default; + Language& operator=(Language&&) = default; + ~Language() = default; + }; + CompilationUnit(std::unique_ptr impl); + ~CompilationUnit(); + + /// Name of the file associated with this compilation unit (e.g. `test.cpp`) + /// Return an **empty** string if the name is not found or can't be resolved + /// + /// This value matches the `DW_AT_name` attribute + std::string name() const; + + /// Information about the program (or library) that generated this compilation + /// unit. For instance, it can output: `Debian clang version 17.0.6`. + /// + /// It returns an **empty** string if the producer is not present or can't be + /// resolved + /// + /// This value matches the `DW_AT_producer` attribute + std::string producer() const; + + /// Return the path to the directory in which the compilation took place for + /// compiling this compilation unit (e.g. `/workdir/build`) + /// + /// It returns an **empty** string if the entry is not present or can't be + /// resolved + /// + /// This value matches the `DW_AT_comp_dir` attribute + std::string compilation_dir() const; + + /// Original Language of this compilation unit. + /// + /// This value matches the `DW_AT_language` attribute. + Language language() const; + + /// Return the lowest virtual address owned by this compilation unit. + uint64_t low_address() const; + + /// Return the highest virtual address owned by this compilation unit. + uint64_t high_address() const; + + /// Return the size of the compilation unit according to its range of address. + /// + /// If the compilation is fragmented (i.e. there are some address ranges + /// 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 + /// `high_address - low_address`. + uint64_t size() const; + + /// Return a list of address ranges owned by this compilation unit. + /// + /// If the compilation unit owns a contiguous range, it should return + /// **a single** range. + std::vector ranges() const; + + /// 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; + + /// Try to find the function at the given address + std::unique_ptr find_function(uint64_t addr) const; + + /// Try to find the Variable at the given address + std::unique_ptr find_variable(uint64_t addr) const; + + /// Try to find the Variable with the given name + std::unique_ptr find_variable(const std::string& name) const; + + /// Return an iterator over the functions implemented in this compilation + /// unit. + /// + /// Note that this iterator only iterates over the functions that have a + /// **concrete** implementation in the compilation unit. + /// + /// For instance with this code: + /// + /// ```cpp + /// inline const char* get_secret_env() { + /// return getenv("MY_SECRET_ENV"); + /// } + /// + /// int main() { + /// printf("%s", get_secret_env()); + /// return 0; + /// } + /// ``` + /// + /// 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; + + /// Return an iterator over the functions **imported** in this compilation + /// unit **but not** implemented. + /// + /// For instance with this code: + /// + /// ```cpp + /// #include + /// int main() { + /// printf("Hello\n"); + /// return 0; + /// } + /// ``` + /// + /// `printf` is imported from the standard libc so the function is returned by + /// 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; + + /// Return an iterator over the different types defined in this + /// compilation unit. + types_it types() const; + + + /// Return an iterator over all the variables defined in the this compilation + /// unit: + /// + /// ```cpp + /// static int A = 1; // Returned by the iterator + /// static const char* B = "Hello"; // Returned by the iterator + /// + /// int get() { + /// static int C = 2; // Returned by the iterator + /// return C; + /// } + /// ``` + vars_it variables() const; + + private: + std::unique_ptr impl_; +}; + +} +} +#endif + diff --git a/deps/LIEF/include/LIEF/DWARF/DebugInfo.hpp b/deps/LIEF/include/LIEF/DWARF/DebugInfo.hpp new file mode 100644 index 00000000000000..ac76755b7906d3 --- /dev/null +++ b/deps/LIEF/include/LIEF/DWARF/DebugInfo.hpp @@ -0,0 +1,96 @@ +/* Copyright 2022 - 2025 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_INFO_H +#define LIEF_DWARF_INFO_H +#include +#include + +#include "LIEF/iterators.hpp" +#include "LIEF/Abstract/DebugInfo.hpp" +#include "LIEF/DWARF/CompilationUnit.hpp" + +#include "LIEF/visibility.h" + +namespace LIEF { +/// Namespace for the DWARF debug format +namespace dwarf { +class Function; +class Variable; + +/// This class represents a DWARF debug information. It can embed different +/// compilation units which can be accessed through compilation_units() . +/// +/// This class can be instantiated from LIEF::Binary::debug_info() or load() +class LIEF_API DebugInfo : public LIEF::DebugInfo { + public: + using LIEF::DebugInfo::DebugInfo; + + static std::unique_ptr from_file(const std::string& path); + + /// Iterator over the CompilationUnit + using compilation_units_it = iterator_range; + + /// Try to find the function with the given name (mangled or not) + /// + /// ```cpp + /// const DebugInfo& info = ...; + /// if (auto func = info.find_function("_ZNSt6localeD1Ev")) { + /// // Found + /// } + /// if (auto func = info.find_function("std::locale::~locale()")) { + /// // Found + /// } + /// ``` + std::unique_ptr find_function(const std::string& name) const; + + /// Try to find the function at the given **virtual** address + std::unique_ptr find_function(uint64_t addr) const; + + /// 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; + + /// Try to find the variable at the given **virtual** address + std::unique_ptr find_variable(uint64_t addr) const; + + /// Try to find the type with the given name + std::unique_ptr find_type(const std::string& name) const; + + /// Iterator on the CompilationUnit embedded in this dwarf + compilation_units_it compilation_units() const; + + /// Attempt to resolve the address of the function specified by `name`. + optional find_function_address(const std::string& name) const override; + + FORMAT format() const override { + return LIEF::DebugInfo::FORMAT::DWARF; + } + + static bool classof(const LIEF::DebugInfo* info) { + return info->format() == LIEF::DebugInfo::FORMAT::DWARF; + } + + ~DebugInfo() override = default; +}; + + +/// Load DWARF file from the given path +inline std::unique_ptr load(const std::string& dwarf_path) { + return DebugInfo::from_file(dwarf_path); +} + +} +} +#endif diff --git a/deps/LIEF/include/LIEF/DWARF/Editor.hpp b/deps/LIEF/include/LIEF/DWARF/Editor.hpp new file mode 100644 index 00000000000000..3c63c13833894a --- /dev/null +++ b/deps/LIEF/include/LIEF/DWARF/Editor.hpp @@ -0,0 +1,58 @@ +/* Copyright 2022 - 2025 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_EDITOR_H +#define LIEF_DWARF_EDITOR_H +#include +#include + +#include "LIEF/visibility.h" + +namespace LIEF { +class Binary; +namespace dwarf { + +namespace details { +class Editor; +} + +namespace editor { +class CompilationUnit; +} + +/// This class exposes the main API to create DWARF information +class LIEF_API Editor { + public: + Editor() = delete; + Editor(std::unique_ptr impl); + + /// Instantiate an editor for the given binary object + static std::unique_ptr from_binary(LIEF::Binary& bin); + + /// Create a new compilation unit + std::unique_ptr create_compilation_unit(); + + /// Write the DWARF file to the specified output + void write(const std::string& output); + + ~Editor(); + + private: + std::unique_ptr impl_; + +}; + +} +} +#endif diff --git a/deps/LIEF/include/LIEF/DWARF/Function.hpp b/deps/LIEF/include/LIEF/DWARF/Function.hpp new file mode 100644 index 00000000000000..495cbadac72317 --- /dev/null +++ b/deps/LIEF/include/LIEF/DWARF/Function.hpp @@ -0,0 +1,180 @@ +/* Copyright 2022 - 2025 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_FUNCTION_H +#define LIEF_DWARF_FUNCTION_H + +#include +#include + +#include "LIEF/visibility.h" +#include "LIEF/errors.hpp" +#include "LIEF/iterators.hpp" +#include "LIEF/range.hpp" +#include "LIEF/DWARF/Variable.hpp" +#include "LIEF/DWARF/Type.hpp" +#include "LIEF/asm/Instruction.hpp" + +namespace LIEF { +namespace dwarf { + +class Scope; +class Parameter; + +namespace details { +class Function; +class FunctionIt; +} + +/// This class represents a DWARF function which can be associated with either: +/// `DW_TAG_subprogram` or `DW_TAG_inlined_subroutine`. +class LIEF_API Function { + public: + class LIEF_API Iterator { + 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; + + class LIEF_API PointerProxy { + // Inspired from LLVM's iterator_facade_base + friend class Iterator; + public: + pointer operator->() const { return R.get(); } + + private: + value_type R; + + template + PointerProxy(RefT &&R) : R(std::forward(R)) {} // NOLINT(bugprone-forwarding-reference-overload) + }; + + Iterator(const Iterator&); + Iterator(Iterator&&) noexcept; + Iterator(std::unique_ptr impl); + ~Iterator(); + + friend LIEF_API bool operator==(const Iterator& LHS, const Iterator& RHS); + + friend LIEF_API bool operator!=(const Iterator& LHS, const Iterator& RHS) { + return !(LHS == RHS); + } + + Iterator& operator++(); + Iterator& operator--(); + + Iterator operator--(int) { + Iterator tmp = *static_cast(this); + --*static_cast(this); + return tmp; + } + + Iterator operator++(int) { + Iterator tmp = *static_cast(this); + ++*static_cast(this); + return tmp; + } + + std::unique_ptr operator*() const; + + PointerProxy operator->() const { + return static_cast(this)->operator*(); + } + + private: + std::unique_ptr impl_; + }; + + /// Iterator over the variables defined in the scope of this function + using vars_it = iterator_range; + using parameters_t = std::vector>; + using thrown_types_t = std::vector>; + + using instructions_it = iterator_range; + + Function(std::unique_ptr impl); + + /// The name of the function (`DW_AT_name`) + std::string name() const; + + /// 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. + std::string linkage_name() const; + + /// Return the address of the function (`DW_AT_entry_pc` or `DW_AT_low_pc`). + result address() const; + + /// 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; + + /// Whether this function is created by the compiler and not + /// present in the original source code + bool is_artificial() const; + + /// Whether the function is defined **outside** the current compilation unit + /// (`DW_AT_external`). + bool is_external() const; + + /// Return the size taken by this function in the binary + uint64_t size() const; + + /// Ranges of virtual addresses owned by this function + std::vector ranges() const; + + /// Original source code location + debug_location_t debug_location() const; + + /// Return the dwarf::Type associated with the **return type** of this + /// function + std::unique_ptr type() const; + + /// Return the function's parameters (including any template parameter) + parameters_t parameters() const; + + /// List of exceptions (types) that can be thrown by the function. + /// + /// For instance, given this Swift code: + /// + /// ```swift + /// func summarize(_ ratings: [Int]) throws(StatisticsError) { + /// // ... + /// } + /// ``` + /// + /// thrown_types() returns one element associated with the Type: + /// `StatisticsError`. + thrown_types_t thrown_types() const; + + /// Return the scope in which this function is defined + std::unique_ptr scope() const; + + /// Disassemble the current function by returning an iterator over + /// the assembly::Instruction + instructions_it instructions() const; + + ~Function(); + private: + std::unique_ptr impl_; +}; + +} +} +#endif diff --git a/deps/LIEF/include/LIEF/DWARF/Parameter.hpp b/deps/LIEF/include/LIEF/DWARF/Parameter.hpp new file mode 100644 index 00000000000000..9fa7c1211deb86 --- /dev/null +++ b/deps/LIEF/include/LIEF/DWARF/Parameter.hpp @@ -0,0 +1,146 @@ +/* Copyright 2022 - 2025 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_PARAMETER_H +#define LIEF_DWARF_PARAMETER_H + +#include "LIEF/visibility.h" + +#include +#include + +namespace LIEF { +namespace dwarf { + +class Type; + +namespace details { +class Parameter; +} + +/// This class represents a DWARF parameter which can be either: +/// - A regular function parameter (see: parameters::Formal) +/// - A template type parameter (see: parameters::TemplateType) +/// - A template value parameter (see: parameters::TemplateValue) +class LIEF_API Parameter { + public: + enum class KIND { + UNKNOWN = 0, + TEMPLATE_TYPE, ///< DW_TAG_template_type_parameter + TEMPLATE_VALUE, ///< DW_TAG_template_value_parameter + FORMAL, ///< DW_TAG_formal_parameter + }; + Parameter() = delete; + Parameter(Parameter&& other); + Parameter& operator=(Parameter&& other); + 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; + + template + const T* as() const { + if (T::classof(this)) { + return static_cast(this); + } + return nullptr; + } + + virtual ~Parameter(); + + LIEF_LOCAL static + std::unique_ptr create(std::unique_ptr impl); + + protected: + Parameter(std::unique_ptr impl); + std::unique_ptr impl_; +}; + +namespace parameters { + +/// This class represents a regular function parameter. +/// +/// For instance, given this prototype: +/// +/// ```cpp +/// int main(int argc, const char** argv); +/// ``` +/// +/// The function `main` has two parameters::Formal parameters: +/// +/// 1. `argc` (Parameter::name) typed as `int` (types::Base from Parameter::type) +/// 2. `argv` (Parameter::name) typed as `const char**` +/// (types::Const from Parameter::type) +class LIEF_API Formal : public Parameter { + public: + using Parameter::Parameter; + static bool classof(const Parameter* P) { + return P->kind() == Parameter::KIND::FORMAL; + } + + ~Formal() override = default; +}; + + +/// This class represents a template **value** parameter. +/// +/// For instance, given this prototype: +/// +/// ```cpp +/// template +/// void generic(); +/// ``` +/// +/// The function `generic` has one parameters::TemplateValue parameter: `X`. +class LIEF_API TemplateValue : public Parameter { + public: + using Parameter::Parameter; + static bool classof(const Parameter* P) { + return P->kind() == Parameter::KIND::TEMPLATE_VALUE; + } + + ~TemplateValue() override = default; +}; + +/// This class represents a template **type** parameter. +/// +/// For instance, given this prototype: +/// +/// ```cpp +/// template +/// void generic(); +/// ``` +/// +/// The function `generic` has one parameters::TemplateType parameter: `Y`. +class LIEF_API TemplateType : public Parameter { +public: + using Parameter::Parameter; + static bool classof(const Parameter* P) { + return P->kind() == Parameter::KIND::TEMPLATE_TYPE; + } + + ~TemplateType() override = default; +}; + +} + +} +} +#endif diff --git a/deps/LIEF/include/LIEF/DWARF/Scope.hpp b/deps/LIEF/include/LIEF/DWARF/Scope.hpp new file mode 100644 index 00000000000000..61977c21aec5e6 --- /dev/null +++ b/deps/LIEF/include/LIEF/DWARF/Scope.hpp @@ -0,0 +1,66 @@ +/* Copyright 2022 - 2025 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_SCOPE_H +#define LIEF_DWARF_SCOPE_H + +#include +#include +#include + +#include "LIEF/visibility.h" + +namespace LIEF { +namespace dwarf { + +namespace details { +class Scope; +} + +/// This class materializes a scope in which Function, Variable, Type, ... +/// can be defined. +class LIEF_API Scope { + public: + enum class TYPE : uint32_t { + UNKNOWN = 0, + UNION, + CLASS, + STRUCT, + NAMESPACE, + FUNCTION, + COMPILATION_UNIT, + }; + Scope(std::unique_ptr impl); + + /// Name of the scope. For instance namespace's name or function's name. + std::string name() const; + + /// Parent scope (if any) + std::unique_ptr parent() const; + + /// The current scope type + TYPE type() const; + + /// Represent the whole chain of all (parent) scopes using the provided + /// separator. E.g. `ns1::ns2::Class1::Struct2::Type` + std::string chained(const std::string& sep = "::") const; + + ~Scope(); + private: + std::unique_ptr impl_; +}; + +} +} +#endif diff --git a/deps/LIEF/include/LIEF/DWARF/Type.hpp b/deps/LIEF/include/LIEF/DWARF/Type.hpp new file mode 100644 index 00000000000000..9e13e896c0d782 --- /dev/null +++ b/deps/LIEF/include/LIEF/DWARF/Type.hpp @@ -0,0 +1,198 @@ +/* Copyright 2022 - 2025 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_TYPE_H +#define LIEF_DWARF_TYPE_H + +#include + +#include "LIEF/visibility.h" +#include "LIEF/errors.hpp" +#include "LIEF/debug_loc.hpp" +#include "LIEF/canbe_unique.hpp" + +namespace LIEF { +namespace dwarf { +class Scope; + +namespace details { +class Type; +class TypeIt; +} + +/// This class represents a DWARF Type which includes: +/// +/// - `DW_TAG_array_type` +/// - `DW_TAG_atomic_type` +/// - `DW_TAG_base_type` +/// - `DW_TAG_class_type` +/// - `DW_TAG_coarray_type` +/// - `DW_TAG_const_type` +/// - `DW_TAG_dynamic_type` +/// - `DW_TAG_enumeration_type` +/// - `DW_TAG_file_type` +/// - `DW_TAG_immutable_type` +/// - `DW_TAG_interface_type` +/// - `DW_TAG_packed_type` +/// - `DW_TAG_pointer_type` +/// - `DW_TAG_ptr_to_member_type` +/// - `DW_TAG_reference_type` +/// - `DW_TAG_restrict_type` +/// - `DW_TAG_rvalue_reference_type` +/// - `DW_TAG_set_type` +/// - `DW_TAG_shared_type` +/// - `DW_TAG_string_type` +/// - `DW_TAG_structure_type` +/// - `DW_TAG_subroutine_type` +/// - `DW_TAG_template_alias` +/// - `DW_TAG_thrown_type` +/// - `DW_TAG_typedef` +/// - `DW_TAG_union_type` +/// - `DW_TAG_unspecified_type` +/// - `DW_TAG_volatile_type` +class LIEF_API Type { + public: + class LIEF_API Iterator { + 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; + + class LIEF_API PointerProxy { + // Inspired from LLVM's iterator_facade_base + friend class Iterator; + public: + pointer operator->() const { return R.get(); } + + private: + value_type R; + + template + PointerProxy(RefT &&R) : R(std::forward(R)) {} // NOLINT(bugprone-forwarding-reference-overload) + }; + + Iterator(const Iterator&); + Iterator(Iterator&&) noexcept; + Iterator(std::unique_ptr impl); + ~Iterator(); + + friend LIEF_API bool operator==(const Iterator& LHS, const Iterator& RHS); + friend LIEF_API bool operator!=(const Iterator& LHS, const Iterator& RHS) { + return !(LHS == RHS); + } + + Iterator& operator++(); + Iterator& operator--(); + + Iterator operator--(int) { + Iterator tmp = *static_cast(this); + --*static_cast(this); + return tmp; + } + + Iterator operator++(int) { + Iterator tmp = *static_cast(this); + ++*static_cast(this); + return tmp; + } + + std::unique_ptr operator*() const; + + PointerProxy operator->() const { + return static_cast(this)->operator*(); + } + + private: + std::unique_ptr impl_; + }; + + virtual ~Type(); + + enum class KIND { + UNKNOWN = 0, + UNSPECIFIED, + BASE, + CONST_KIND, + CLASS, + ARRAY, + POINTER, + STRUCT, + UNION, + TYPEDEF, + REF, + SET_TYPE, + STRING, + SUBROUTINE, + POINTER_MEMBER, + PACKED, + FILE, + THROWN, + VOLATILE, + RESTRICT, + INTERFACE, + SHARED, + RVALREF, + TEMPLATE_ALIAS, + COARRAY, + DYNAMIC, + ATOMIC, + IMMUTABLE, + ENUM, + }; + + KIND kind() const; + + /// Whether this type is a `DW_TAG_unspecified_type` + bool is_unspecified() const { + return kind() == KIND::UNSPECIFIED; + } + + /// Return the type's name using either `DW_AT_name` or `DW_AT_picture_string` + /// (if any). + result name() const; + + /// Return the size of the type or an error if it can't be computed. + /// + /// This size should match the equivalent of `sizeof(Type)`. + result size() const; + + /// Return the debug location where this type is defined. + debug_location_t location() const; + + /// Return the scope in which this type is defined + std::unique_ptr scope() const; + + template + const T* as() const { + if (T::classof(this)) { + return static_cast(this); + } + return nullptr; + } + + static std::unique_ptr create(std::unique_ptr impl); + + protected: + Type(std::unique_ptr impl); + Type(details::Type& impl); + + LIEF::details::canbe_unique impl_; +}; + +} +} +#endif diff --git a/deps/LIEF/include/LIEF/DWARF/Variable.hpp b/deps/LIEF/include/LIEF/DWARF/Variable.hpp new file mode 100644 index 00000000000000..dd457f45d6ea8e --- /dev/null +++ b/deps/LIEF/include/LIEF/DWARF/Variable.hpp @@ -0,0 +1,141 @@ +/* Copyright 2022 - 2025 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_VARIABLE_H +#define LIEF_DWARF_VARIABLE_H + +#include + +#include "LIEF/visibility.h" +#include "LIEF/errors.hpp" +#include "LIEF/debug_loc.hpp" +#include "LIEF/DWARF/Type.hpp" + +namespace LIEF { +namespace dwarf { +class Scope; + +namespace details { +class Variable; +class VariableIt; +} + +/// This class represents a DWARF variable which can be owned by a +/// dwarf::Function or a dwarf::CompilationUnit +class LIEF_API Variable { + public: + class LIEF_API Iterator { + 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; + + class LIEF_API PointerProxy { + // Inspired from LLVM's iterator_facade_base + friend class Iterator; + public: + pointer operator->() const { return R.get(); } + + private: + value_type R; + + template + PointerProxy(RefT &&R) : R(std::forward(R)) {} // NOLINT(bugprone-forwarding-reference-overload) + }; + + Iterator(const Iterator&); + Iterator(Iterator&&) noexcept; + Iterator(std::unique_ptr impl); + ~Iterator(); + + friend LIEF_API bool operator==(const Iterator& LHS, const Iterator& RHS); + friend LIEF_API bool operator!=(const Iterator& LHS, const Iterator& RHS) { + return !(LHS == RHS); + } + + Iterator& operator++(); + Iterator& operator--(); + + Iterator operator--(int) { + Iterator tmp = *static_cast(this); + --*static_cast(this); + return tmp; + } + + Iterator operator++(int) { + Iterator tmp = *static_cast(this); + ++*static_cast(this); + return tmp; + } + + std::unique_ptr operator*() const; + + PointerProxy operator->() const { + return static_cast(this)->operator*(); + } + + private: + std::unique_ptr impl_; + }; + + Variable(std::unique_ptr impl); + + /// Name of the variable (usually demangled) + std::string name() const; + + /// 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. + std::string linkage_name() const; + + /// Address of the variable. + /// + /// If the variable is **static**, it returns the **virtual address** + /// where it is defined. + /// If the variable is stack-based, it returns the **relative offset** from + /// the frame based register. + /// + /// If the address can't be resolved, it returns a lief_errors. + result address() const; + + /// Return the size of the variable (or a lief_errors if it can't be + /// resolved). + /// + /// This size is defined by its type. + result size() const; + + /// Whether it's a `constexpr` variable + bool is_constexpr() 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; + + /// Return the scope in which this variable is defined + std::unique_ptr scope() const; + + ~Variable(); + private: + std::unique_ptr impl_; +}; + +} +} +#endif diff --git a/deps/LIEF/include/LIEF/DWARF/editor/ArrayType.hpp b/deps/LIEF/include/LIEF/DWARF/editor/ArrayType.hpp new file mode 100644 index 00000000000000..2116dd9666e4b8 --- /dev/null +++ b/deps/LIEF/include/LIEF/DWARF/editor/ArrayType.hpp @@ -0,0 +1,38 @@ +/* Copyright 2022 - 2025 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_EDITOR_ARRAY_TYPE_H +#define LIEF_DWARF_EDITOR_ARRAY_TYPE_H + +#include "LIEF/visibility.h" +#include "LIEF/DWARF/editor/Type.hpp" + +namespace LIEF { +namespace dwarf { +namespace editor { + +/// This class represents an array type (`DW_TAG_array_type`). +class LIEF_API ArrayType : public Type { + public: + using Type::Type; + + static bool classof(const Type* type); + + ~ArrayType() override = default; +}; + +} +} +} +#endif diff --git a/deps/LIEF/include/LIEF/DWARF/editor/BaseType.hpp b/deps/LIEF/include/LIEF/DWARF/editor/BaseType.hpp new file mode 100644 index 00000000000000..f06db195b0aef7 --- /dev/null +++ b/deps/LIEF/include/LIEF/DWARF/editor/BaseType.hpp @@ -0,0 +1,50 @@ +/* Copyright 2022 - 2025 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_EDITOR_BASE_TYPE_H +#define LIEF_DWARF_EDITOR_BASE_TYPE_H + +#include +#include "LIEF/visibility.h" +#include "LIEF/DWARF/editor/Type.hpp" + +namespace LIEF { +namespace dwarf { +namespace editor { + +/// This class represents a primitive type like `int, char`. +class LIEF_API BaseType : public Type { + public: + using Type::Type; + + enum class ENCODING : uint32_t { + NONE = 0, + ADDRESS, + SIGNED, + SIGNED_CHAR, + UNSIGNED, + UNSIGNED_CHAR, + BOOLEAN, + FLOAT + }; + + static bool classof(const Type* type); + + ~BaseType() override = default; +}; + +} +} +} +#endif diff --git a/deps/LIEF/include/LIEF/DWARF/editor/CompilationUnit.hpp b/deps/LIEF/include/LIEF/DWARF/editor/CompilationUnit.hpp new file mode 100644 index 00000000000000..b6b00714d0de5f --- /dev/null +++ b/deps/LIEF/include/LIEF/DWARF/editor/CompilationUnit.hpp @@ -0,0 +1,100 @@ +/* Copyright 2022 - 2025 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_EDITOR_COMPILATION_UNIT_H +#define LIEF_DWARF_EDITOR_COMPILATION_UNIT_H +#include +#include + +#include "LIEF/visibility.h" +#include "LIEF/DWARF/editor/StructType.hpp" +#include "LIEF/DWARF/editor/BaseType.hpp" +#include "LIEF/DWARF/editor/FunctionType.hpp" +#include "LIEF/DWARF/editor/PointerType.hpp" + +namespace LIEF { +namespace dwarf { +namespace editor { +class Function; +class Variable; +class Type; +class EnumType; +class TypeDef; +class ArrayType; + +namespace details { +class CompilationUnit; +} + +/// This class represents an **editable** DWARF compilation unit +class LIEF_API CompilationUnit { + public: + CompilationUnit() = delete; + CompilationUnit(std::unique_ptr impl); + + /// Set the `DW_AT_producer` producer attribute. + /// + /// This attribute aims to inform about the program that generated this + /// compilation unit (e.g. `LIEF Extended`) + CompilationUnit& set_producer(const std::string& producer); + + /// Create a new function owned by this compilation unit + std::unique_ptr create_function(const std::string& name); + + /// Create a new **global** variable owned by this compilation unit + std::unique_ptr create_variable(const std::string& name); + + /// Create a `DW_TAG_unspecified_type` type with the given name + std::unique_ptr create_generic_type(const std::string& name); + + /// Create an enum type (`DW_TAG_enumeration_type`) + std::unique_ptr create_enum(const std::string& name); + + /// Create a typdef 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); + + /// 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); + + /// 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); + + /// Create a function type with the given name. + std::unique_ptr create_function_type(const std::string& name); + + /// Create a pointer on the provided type + std::unique_ptr create_pointer_type(const Type& ty) { + return ty.pointer_to(); + } + + /// Create a `void` type + std::unique_ptr create_void_type(); + + /// 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); + + ~CompilationUnit(); + + private: + std::unique_ptr impl_; +}; + +} +} +} +#endif diff --git a/deps/LIEF/include/LIEF/DWARF/editor/EnumType.hpp b/deps/LIEF/include/LIEF/DWARF/editor/EnumType.hpp new file mode 100644 index 00000000000000..90d76fa0e91a4e --- /dev/null +++ b/deps/LIEF/include/LIEF/DWARF/editor/EnumType.hpp @@ -0,0 +1,62 @@ +/* Copyright 2022 - 2025 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_EDITOR_ENUM_TYPE_H +#define LIEF_DWARF_EDITOR_ENUM_TYPE_H +#include +#include + +#include "LIEF/visibility.h" +#include "LIEF/DWARF/editor/Type.hpp" + +namespace LIEF { +namespace dwarf { +namespace editor { + +namespace details { +class EnumValue; +} + +/// This class represents an editable enum type (`DW_TAG_enumeration_type`) +class LIEF_API EnumType : public Type { + public: + using Type::Type; + + /// This class represents an enum value + class LIEF_API Value { + public: + Value() = delete; + 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); + + /// Add an enum value by specifying its name and its integer value + std::unique_ptr add_value(const std::string& name, int64_t value); + + static bool classof(const Type* type); + + ~EnumType() override = default; +}; + +} +} +} +#endif diff --git a/deps/LIEF/include/LIEF/DWARF/editor/Function.hpp b/deps/LIEF/include/LIEF/DWARF/editor/Function.hpp new file mode 100644 index 00000000000000..e91f64139c055e --- /dev/null +++ b/deps/LIEF/include/LIEF/DWARF/editor/Function.hpp @@ -0,0 +1,129 @@ +/* Copyright 2022 - 2025 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_EDITOR_FUNCTION_H +#define LIEF_DWARF_EDITOR_FUNCTION_H +#include +#include +#include +#include + +#include "LIEF/visibility.h" + +namespace LIEF { +namespace dwarf { +namespace editor { +class Type; +class Variable; + +namespace details { +class Function; +class FunctionParameter; +class FunctionLexicalBlock; +class FunctionLabel; +} + +/// This class represents an **editable** DWARF function (`DW_TAG_subprogram`) +class LIEF_API Function { + public: + struct LIEF_API range_t { + range_t() = default; + range_t(uint64_t start, uint64_t 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`) + class LIEF_API Parameter { + public: + Parameter() = delete; + Parameter(std::unique_ptr impl); + + ~Parameter(); + private: + std::unique_ptr impl_; + }; + + /// This class mirrors the `DW_TAG_lexical_block` DWARF tag + class LIEF_API LexicalBlock { + public: + LexicalBlock() = delete; + LexicalBlock(std::unique_ptr impl); + + ~LexicalBlock(); + private: + std::unique_ptr impl_; + }; + + /// This class mirrors the `DW_TAG_label` DWARF tag + class LIEF_API Label { + public: + Label() = delete; + Label(std::unique_ptr impl); + + ~Label(); + private: + std::unique_ptr impl_; + }; + + Function() = delete; + Function(std::unique_ptr impl); + + /// Set the address of this function by defining `DW_AT_entry_pc` + Function& set_address(uint64_t addr); + + /// 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); + + /// 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); + + /// 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(); + + /// Set the return type of this function + Function& set_return_type(const Type& type); + + /// Add a parameter to the current function + std::unique_ptr add_parameter(const std::string& name, const Type& type); + + /// Create a stack-based variable owned by the current function + std::unique_ptr create_stack_variable(const std::string& name); + + /// Add a lexical block with the given range + std::unique_ptr add_lexical_block(uint64_t start, uint64_t end); + + /// Add a label at the given address + std::unique_ptr