├── .buckconfig ├── .buckroot ├── .github └── workflows │ ├── black.yml │ ├── bpftools.yml │ └── jdwp.yml ├── .gitignore ├── .gitmodules ├── .pyre_configuration ├── .vscode └── settings.json ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── Makefile ├── README.md ├── Vagrantfile ├── docker └── Dockerfile ├── docs └── phone_setup.md ├── licenses └── lgpl-3.0.txt ├── projects ├── argp │ ├── README │ ├── build.mk │ └── headers │ │ └── argp-wrapper.h ├── bcc │ ├── README │ └── build.mk ├── black │ ├── README │ └── build.mk ├── bpftrace │ ├── README │ ├── build.mk │ └── strip-thunk ├── buck2 │ ├── README │ ├── REDME │ └── build.mk ├── cereal │ ├── README │ └── build.mk ├── cmake │ ├── README │ └── build.mk ├── elfutils │ ├── README │ ├── android_fixups │ │ └── libintl.h │ └── build.mk ├── ffi │ ├── README │ └── build.mk ├── flex │ ├── README │ └── build.mk ├── gnulib │ ├── README │ └── build.mk ├── jdwp │ ├── BUCK │ ├── __init__.py │ ├── build.mk │ ├── codegen │ │ ├── BUCK │ │ ├── dataclass_generator.py │ │ ├── new_type_generator.py │ │ └── types.py │ ├── defs │ │ ├── BUCK │ │ ├── command_sets │ │ │ ├── event_request.py │ │ │ ├── reference_type.py │ │ │ └── virtual_machine.py │ │ ├── constants.py │ │ └── schema.py │ ├── main.py │ ├── runtime │ │ ├── BUCK │ │ ├── async_streams.py │ │ └── jdwpstruct.py │ └── tests │ │ ├── BUCK │ │ ├── defs │ │ └── schema.py │ │ ├── runtime │ │ └── import.py │ │ ├── test_dataclass_generator.py │ │ ├── test_new_type_generator.py │ │ └── test_types.py ├── libbpf │ ├── README │ └── build.mk ├── licenses.mk ├── llvm │ ├── README │ └── build.mk ├── obstack │ ├── README │ └── build.mk ├── project.mk ├── pyre │ ├── README │ └── build.mk ├── python │ ├── README │ ├── build.mk │ └── python.xinstall.template ├── stdc++fs │ ├── README │ ├── build.mk │ └── thunks.cpp ├── xz │ ├── README │ └── build.mk └── zlib │ └── build.mk ├── scripts ├── build-docker-image.sh ├── centos-install-deps.sh ├── download-ndk.sh ├── jammy-install-deps.sh └── run-docker-build-env.sh ├── sysroot ├── bpftools.mk ├── run.sh ├── setup.sh └── wrapper.sh.template └── toolchains ├── BUCK ├── autotools.mk ├── cmake.mk ├── config.site.host.template ├── config.site.template └── toolchains.mk /.buckconfig: -------------------------------------------------------------------------------- 1 | [repositories] 2 | root = . 3 | prelude = prelude 4 | toolchains = toolchains 5 | none = none 6 | 7 | [repository_aliases] 8 | config = prelude 9 | fbcode = none 10 | fbsource = none 11 | buck = none 12 | 13 | [parser] 14 | target_platform_detector_spec = target:root//...->prelude//platforms:default 15 | 16 | [project] 17 | ignore = .git 18 | 19 | [build] 20 | execution_platforms = prelude//platforms:default 21 | -------------------------------------------------------------------------------- /.buckroot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookexperimental/ExtendedAndroidTools/1a3601739d5fbcb6e272d8425d8e3b099e16523f/.buckroot -------------------------------------------------------------------------------- /.github/workflows/black.yml: -------------------------------------------------------------------------------- 1 | name: Lint Codebase 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | lint_codebase: 7 | name: Lint and format codebase 8 | runs-on: ubuntu-22.04 9 | 10 | steps: 11 | - uses: actions/checkout@v4 12 | - uses: psf/black@stable 13 | with: 14 | options: "--check --verbose" 15 | src: "./projects/jdwp" 16 | 17 | 18 | -------------------------------------------------------------------------------- /.github/workflows/bpftools.yml: -------------------------------------------------------------------------------- 1 | name: Build bpftools archives 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | build_bpftools: 7 | name: Build bpftools archive 8 | runs-on: ubuntu-22.04 9 | strategy: 10 | matrix: 11 | env: 12 | - ARCH: arm64 13 | - ARCH: x86_64 14 | steps: 15 | - uses: actions/checkout@v4 16 | - name: Install dependencies 17 | run: sudo ./scripts/jammy-install-deps.sh 18 | - name: Setup NDK 19 | run: ./scripts/download-ndk.sh 20 | - name: Build 21 | env: ${{matrix.env}} 22 | run: make bpftools NDK_PATH=`pwd`/android-ndk-r27b NDK_ARCH=${{ matrix.env['ARCH'] }} 23 | - uses: actions/upload-artifact@v4 24 | with: 25 | name: bpftools-android-${{ matrix.env['ARCH'] }}.tar.gz 26 | path: bpftools-${{ matrix.env['ARCH'] }}.tar.gz 27 | 28 | build_bpftools_min: 29 | name: Build bpftools-min archive 30 | runs-on: ubuntu-22.04 31 | strategy: 32 | matrix: 33 | env: 34 | - ARCH: arm64 35 | - ARCH: x86_64 36 | steps: 37 | - uses: actions/checkout@v4 38 | - name: Install dependencies 39 | run: sudo ./scripts/jammy-install-deps.sh 40 | - name: Setup NDK 41 | run: ./scripts/download-ndk.sh 42 | - name: Build 43 | run: make bpftools-min NDK_PATH=`pwd`/android-ndk-r27b NDK_ARCH=${{ matrix.env['ARCH'] }} 44 | - uses: actions/upload-artifact@v4 45 | with: 46 | name: bpftools-min-android-${{ matrix.env['ARCH'] }}.tar.gz 47 | path: bpftools-min-${{ matrix.env['ARCH'] }}.tar.gz 48 | 49 | build_bpftrace_static: 50 | name: Build static bpftrace binaries 51 | runs-on: ubuntu-22.04 52 | strategy: 53 | matrix: 54 | env: 55 | - ARCH: arm64 56 | - ARCH: x86_64 57 | - ARCH: armv7 58 | steps: 59 | - uses: actions/checkout@v4 60 | - name: Install dependencies 61 | run: sudo ./scripts/jammy-install-deps.sh 62 | - name: Setup NDK 63 | run: ./scripts/download-ndk.sh 64 | - name: Build 65 | run: make bpftrace NDK_PATH=`pwd`/android-ndk-r27b NDK_ARCH=${{ matrix.env['ARCH'] }} STATIC_LINKING=true LLVM_BPF_ONLY=true 66 | - uses: actions/upload-artifact@v4 67 | with: 68 | name: bpftrace-android-${{ matrix.env['ARCH'] }} 69 | path: out/android/${{ matrix.env['ARCH'] }}/bin/bpftrace 70 | -------------------------------------------------------------------------------- /.github/workflows/jdwp.yml: -------------------------------------------------------------------------------- 1 | name: Build jdwp project 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | build_jdwp_project: 7 | name: Build and Test JDWP Project 8 | runs-on: ubuntu-22.04 9 | 10 | steps: 11 | - name: Checkout repository and submodules 12 | uses: actions/checkout@v3 13 | with: 14 | submodules: recursive 15 | - name: Initialize JDWP Project Dependencies 16 | run: make buck2-host python-host pyre-host 17 | - name: Build and run 18 | run: | 19 | eval `make setup-env` 20 | buck2 run //projects/jdwp:main 21 | - name: Run Tests 22 | run: | 23 | eval `make setup-env` 24 | buck2 test //projects/jdwp/tests/... 25 | - name: Run Pyre Type Checking 26 | run: | 27 | eval `make setup-env` 28 | cd projects/jdwp && pyre --version=client check 29 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # -*- mode: gitignore; -*- 2 | 3 | # editors' temp files 4 | *~ 5 | \#*\# 6 | .\#* 7 | 8 | # build files 9 | /build/ 10 | /out/ 11 | /buck-out/ 12 | 13 | # sources 14 | /projects/*/sources 15 | 16 | # Vagrant files 17 | .vagrant/ 18 | ubuntu-bionic-18.04-cloudimg-console.log 19 | 20 | # pyre 21 | .pyre/ 22 | 23 | bpftools-arm64.tar.gz 24 | bpftools-min-arm64.tar.gz 25 | bpftools-x86_64.tar.gz 26 | bpftools-min-x86_64.tar.gz 27 | bpftools-armv7.tar.gz 28 | bpftools-min-armv7.tar.gz 29 | bpftools-86.tar.gz 30 | bpftools-min-x86.tar.gz 31 | 32 | .flake8 33 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "prelude"] 2 | path = prelude 3 | url = https://github.com/facebook/buck2-prelude.git 4 | -------------------------------------------------------------------------------- /.pyre_configuration: -------------------------------------------------------------------------------- 1 | { 2 | "use_buck2": true, 3 | "bxl_builder": "prelude//python/sourcedb/classic.bxl:build", 4 | "targets": [ 5 | "root//projects/jdwp/..." 6 | ], 7 | "ignore_all_errors": [ 8 | "out" 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "[python]": { 3 | "editor.defaultFormatter": "ms-python.black-formatter" 4 | }, 5 | "python.formatting.provider": "none" 6 | } 7 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to make participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, sex characteristics, gender identity and expression, 9 | level of experience, education, socio-economic status, nationality, personal 10 | appearance, race, religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies within all project spaces, and it also applies when 49 | an individual is representing the project or its community in public spaces. 50 | Examples of representing a project or community include using an official 51 | project e-mail address, posting via an official social media account, or acting 52 | as an appointed representative at an online or offline event. Representation of 53 | a project may be further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at . All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 72 | 73 | [homepage]: https://www.contributor-covenant.org 74 | 75 | For answers to common questions about this code of conduct, see 76 | https://www.contributor-covenant.org/faq 77 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to ExtendedAndroidTools 2 | We want to make contributing to this project as easy and transparent as 3 | possible. 4 | 5 | ## Pull Requests 6 | We actively welcome your pull requests. 7 | 8 | 1. Fork the repo and create your branch from `main`. 9 | 2. If you've added code that should be tested, add tests. 10 | 3. If you've changed APIs, update the documentation. 11 | 4. Ensure the test suite passes. 12 | 5. Make sure your code lints. 13 | 6. If you haven't already, complete the Contributor License Agreement ("CLA"). 14 | 15 | ## Contributor License Agreement ("CLA") 16 | In order to accept your pull request, we need you to submit a CLA. You only need 17 | to do this once to work on any of Facebook's open source projects. 18 | 19 | Complete your CLA here: 20 | 21 | ## Issues 22 | We use GitHub issues to track public bugs. Please ensure your description is 23 | clear and has sufficient instructions to be able to reproduce the issue. 24 | 25 | Facebook has a [bounty program](https://www.facebook.com/whitehat/) for the safe 26 | disclosure of security bugs. In those cases, please go through the process 27 | outlined on that page and do not file a public issue. 28 | 29 | ## License 30 | By contributing to ExtendedAndroidTools, you agree that your contributions will be licensed 31 | under the LICENSE file in the root directory of this source tree. 32 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Copyright (c) Meta Platforms, Inc. and affiliates. 2 | 3 | # number of threads to use. This value is passed to recursive make calls as -j 4 | # option. 5 | THREADS = 4 6 | 7 | # arch: arm64, armv7, or x86_64 8 | NDK_ARCH = arm64 9 | 10 | # Release or Debug 11 | BUILD_TYPE = Release 12 | 13 | # For tools that support it, statically link against non-NDK dependencies to 14 | # produce a self-contained binary. 15 | STATIC_LINKING = false 16 | 17 | # Only enable support for the BPF target in LLVM. This reduces the code size, 18 | # but note that not all tools may work (in particular, bcc's rwengine also 19 | # requires support for the $NDK_ARCH target) 20 | LLVM_BPF_ONLY = false 21 | 22 | BUILD_DIR = build 23 | ANDROID_BUILD_DIR = $(BUILD_DIR)/android/$(NDK_ARCH) 24 | HOST_BUILD_DIR = $(BUILD_DIR)/host 25 | DOWNLOADS_DIR = $(BUILD_DIR)/downloads 26 | 27 | OUT_DIR = out 28 | ANDROID_OUT_DIR = $(OUT_DIR)/android/$(NDK_ARCH) 29 | ANDROID_SYSROOTS_OUT_DIR = $(OUT_DIR)/sysroots/$(NDK_ARCH) 30 | HOST_OUT_DIR = $(OUT_DIR)/host 31 | 32 | HOST_OS = $(shell uname -o) 33 | HOST_MACHINE = $(shell uname -m) 34 | 35 | export PATH:=$(abspath $(HOST_OUT_DIR)/bin):$(PATH) 36 | 37 | all: 38 | @echo "Choose a project to build" 39 | 40 | include toolchains/toolchains.mk 41 | 42 | $(ANDROID_BUILD_DIR) $(HOST_BUILD_DIR) $(DOWNLOADS_DIR) $(ANDROID_SYSROOTS_OUT_DIR): 43 | mkdir -p $@ 44 | 45 | $(ANDROID_OUT_DIR) $(HOST_OUT_DIR): 46 | mkdir -p $@ 47 | mkdir $@/bin 48 | mkdir $@/include 49 | mkdir $@/lib 50 | mkdir $@/lib/pkgconfig 51 | mkdir $@/share 52 | mkdir $@/licenses 53 | 54 | clean: 55 | -rm -fr $(BUILD_DIR) 56 | -rm -fr $(OUT_DIR) 57 | 58 | setup-env: 59 | @echo "export PATH=\"$(PATH)\"" 60 | 61 | .PHONY: clean fetch-sources remove-sources install uninstall setup-env 62 | .DELETE_ON_ERROR: 63 | 64 | include projects/project.mk 65 | include projects/licenses.mk 66 | include projects/*/build.mk 67 | include sysroot/*.mk 68 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ExtendedAndroidTools 2 | Extended Android Tools is a set of makefiles and build environment cross compiling Linux tools we all love for Android. All tools are built using their native build systems (autotools, cmake, etc) and Android NDK. Reference build environment is provided via Docker. 3 | 4 | # List of supported software 5 | - [bpftrace](https://github.com/iovisor/bpftrace) 6 | - [bcc](https://github.com/iovisor/bcc) 7 | - [llvm & clang](https://github.com/llvm/llvm-project) 8 | - [python](https://github.com/python/cpython) 9 | - [libffi](https://github.com/libffi/libffi) 10 | - [flex](https://github.com/westes/flex) 11 | - [libelf (part of elfutils)](https://sourceware.org/elfutils/) 12 | - [argp (part of gnulib)](https://www.gnu.org/software/gnulib/) 13 | - [XZ Utils](https://tukaani.org/xz/) 14 | 15 | # Build environment 16 | ## Docker (recommended) 17 | Provided [Dockerfile](https://github.com/facebookexperimental/ExtendedAndroidTools/blob/main/docker/Dockerfile) defines the reference build environment. You can access it using the following commands: 18 | ``` 19 | # Build the Docker image 20 | ./scripts/build-docker-image.sh 21 | 22 | # Run the environment 23 | ./scripts/run-docker-build-env.sh 24 | 25 | # Build a target of your choice from within the container 26 | > make python 27 | > make bpftools 28 | 29 | # Build and run host tools 30 | > make python-host 31 | > eval `make setup-env` 32 | > python3 33 | ``` 34 | 35 | ## Vagrant 36 | ExtendedAndroidTools also provides a [Vagrantfile](https://github.com/facebookexperimental/ExtendedAndroidTools/blob/main/Vagrantfile): 37 | ``` 38 | # Startup (potentially provision new) VM 39 | vagrant up 40 | 41 | # ssh into a running VM 42 | vagrant ssh 43 | 44 | # Go to the shared directory 45 | > cd /vagrant 46 | 47 | # build the project of your choise 48 | > make python 49 | > make bpftools 50 | ``` 51 | 52 | ## Setting up enviornment on your own 53 | ExtendedAndroidTools depends on Android NDK and few programs and libraries that are listed in [this script](https://github.com/facebookexperimental/ExtendedAndroidTools/blob/main/scripts/jammy-install-deps.sh). You should be be able to install them with a package manager of your choice. NDK can be downloaded using [this script](https://github.com/facebookexperimental/ExtendedAndroidTools/blob/main/scripts/download-ndk.sh). 54 | 55 | ``` 56 | make python NDK_PATH= 57 | make bpftools NDK_PATH= 58 | 59 | # Build and run host tools 60 | > make python-host 61 | > eval `make setup-env` 62 | > python3 63 | ``` 64 | # Sysroots 65 | When projects are built the resulting binaries/libraries are placed in `bin` and `lib` subdirectories of `out/android/$ARCH/` directory. To run a particular tool on an Android device it needs to be pushed together with all the libraries it depends on to the device. In addition the shell environment needs to be configured appropriately for the runtime loader to be able to locate and load those libraries when the tool is executed. To help automate these steps ExtendedAndroidTools provides helper targets preparing sysroot archives consisting of selected executables and libraries, together with scripts setting up the environment. Those archives can be pushed to a device, extracted, and used without any further setup. 66 | 67 | ``` 68 | # build bpftools, sysroot containing bpftrace, python and bcc 69 | # see the 'Build environment' section for more details on building 70 | make bpftools 71 | 72 | adb push bpftools-arm64.tar.gz /data/local/tmp 73 | adb shell "cd /data/local/tmp && tar xf bpftools-arm64.tar.gz" 74 | 75 | # enjoy new tools 76 | adb shell /data/local/tmp/bpftools/bpftrace -e 'uprobe:/system/lib64/libc.so:malloc { @ = hist(arg0); }' 77 | ``` 78 | 79 | # Android device requirements 80 | Some of the tools require root privileges to run. In addition BPF tools require Linux kernel to provide BPF capabilities: BPF, Kprobes and Uprobes. Most of Android kernels are based on Linux versions that are either too old, or have some or all of the necessary features disabled. The most straigtforward way to access Android environment providing root access and some BPF capabilities (BPF + Uprobes) is to use API 30 Android emulator **without** Google Play Store. To read more on preparing other devices see [dedicated documentation](docs/phone_setup.md). 81 | 82 | # Variables impacting build process 83 | - `THREADS` - number of jobs to run simultaneously. This value is passed to nested make invocations via `-j` option. The default value is 4. 84 | - `NDK_ARCH` - x86_64 or arm64. Architecture to cross compile for. The default value is arm64 85 | - `BUILD_TYPE` - Release or Debug, controlls amount of debug info to be included in resulting libs and binaries. The default value is Release. 86 | 87 | ``` 88 | # The following builds debug version of bpftools sysroot for x86_64 89 | # Warning: this takes very long and resulting binaries are big, prepare ~100GB of disk space 90 | 91 | make bpftools NDK_ARCH=x86_64 BUILD_TYPE=Debug THREADS=1 92 | ``` 93 | 94 | # Variables impacting execution of tools 95 | - `BPFTRACE_KERNEL_SOURCE` - if set indicates directory bpftrace should read kernel headers from 96 | - `BCC_KERNEL_SOURCE` - if set indicates directory bcc should read kernel headers from 97 | - `BCC_SYMFS` - if set indicates directory containing unstripped elf binaries for better stack symbolication 98 | 99 | ## Contributing 100 | See the [CONTRIBUTING.md](CONTRIBUTING.md) file. 101 | 102 | ## License 103 | See the [LICENSE](LICENSE) file. 104 | -------------------------------------------------------------------------------- /Vagrantfile: -------------------------------------------------------------------------------- 1 | # Copyright (c) Meta Platforms, Inc. and affiliates. 2 | 3 | Vagrant.configure("2") do |config| 4 | config.vm.box = "ubuntu/jammy64" 5 | 6 | config.vm.provider "virtualbox" do |vb| 7 | vb.memory = 8192 8 | vb.cpus = 2 9 | end 10 | 11 | config.vm.provision "deps", type: "shell", path: "scripts/jammy-install-deps.sh" 12 | 13 | config.vm.provision "ndk", type: "shell", after: "deps" do |s| 14 | s.path = "scripts/download-ndk.sh" 15 | s.args = ["/opt/ndk"] 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /docker/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright (c) Meta Platforms, Inc. and affiliates. 2 | 3 | FROM ubuntu:jammy 4 | 5 | COPY jammy-install-deps.sh / 6 | COPY download-ndk.sh / 7 | 8 | RUN bash -c "/jammy-install-deps.sh" && \ 9 | bash -c "/download-ndk.sh /opt/ndk" 10 | 11 | WORKDIR /ExtendedAndroidTools 12 | 13 | ENTRYPOINT ["/bin/bash"] 14 | -------------------------------------------------------------------------------- /docs/phone_setup.md: -------------------------------------------------------------------------------- 1 | # Setting up a phone 2 | This document describes steps necessary to enable BPF, Uprobes and Kprobes on some Android devices. Note that these steps reduce security and might result in voiding warranties. Follow the steps at your own risk. 3 | 4 | ## Root 5 | There are multiple ways of acquiring root access on an Android devices: 6 | - using Android emulator without Google Play Store 7 | - rooting 8 | - building and flashing userdebug AOSP images 9 | 10 | Procedure of acquiring AOSP sources, configuring, building and flashing is documented [here](https://source.android.com/setup/build). 11 | 12 | ## BPF enabled kernel 13 | Most recent Android kernels support limited BPF tracing out of the box. Pixel 4 and API 30 emulator ship with Linux kernel having BPF and Uprobes enabled. Older devices run kernels that predate many of BPF capabilities (Pixel 3a runs 4.9, Pixel 2 runs 4.4) and require some essential commits to be backported, including arm64 Uprobes support (added in 4.10). Kprobes on the other hand are disabled even in the newest kernels as they might be considered a security risk (at least in the past Kprobe support collided with a security mechanism enforcing control flow: [CFI](https://source.android.com/devices/tech/debug/kcfi)) 14 | 15 | Extended Android Tools does not provide kernel sources. You might need to address mentioned issues in your own fork or use kernels from other sources. Here is a list of some BPF-enabled Android kernels that are not part of Extended Android Tools: 16 | - [Pixel 3a](https://github.com/michalgr/kernel_msm/tree/QP1A.190711.020.C3.bpf) 17 | - [Pixel 2](https://github.com/michalgr/kernel_msm/tree/bpf_wahoo_defconfig) 18 | - [API 28 emulator](https://github.com/michalgr/kernel_goldfish) 19 | 20 | Compiling and flashing Android kernels is described [here](https://source.android.com/setup/build/building-kernels). 21 | 22 | ## Updating kernel modules 23 | Since Android 9 some kernel modules are compiled as standalone `.ko` files. Those files need to be kept in sync with the kernel in order for wifi or touch screen to work properly. Those files are located on vendor partition which is not built as part of AOSP and is downloaded as standalone `.img` file instead (at least this is the case with Google phones). In addition [verified boot](https://source.android.com/security/verifiedboot) mechanism prevents modifications to vendor partition on device. To work around that you might need to disable dm-verity (`adb disable-verity`), remounting vendor partition writable (`adb remount -R`) and pushing kernel modules to `/vendor/lib/modules/`. 24 | -------------------------------------------------------------------------------- /licenses/lgpl-3.0.txt: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. 166 | -------------------------------------------------------------------------------- /projects/argp/README: -------------------------------------------------------------------------------- 1 | libarpg 2 | 3 | license: LGPLv3 4 | license url: https://www.gnu.org/licenses/lgpl-3.0.txt 5 | 6 | Libargp is part of gnulib: http://savannah.gnu.org/projects/gnulib. 7 | In order to extract argp from gnulib you need to run gnulib-tool tool which is 8 | distributed together with gnulib sources. In order to extract libargp to 9 | run gnulib-tool like this: 10 | cd 11 | ./gnulib-tool --create-testdir --lib="libargp" --dir= argp 12 | 13 | Building: 14 | gnulib-tool produces autotools like package with the regular configure script. 15 | However, there are a few problems: 16 | - `make install` target seems not to do its job, we need to copy libargp.a and 17 | libargp.h manually. 18 | - libargp.h depends on few macros that are defined in the generated config.h. 19 | To work around that we have a wrapper header that defines minimalistic 20 | versions of these macros and includes the actual header 21 | - configure script modifies Makefile.in (in some environments). To avoid having 22 | to deal with that we copy all the sources to the build directory before 23 | invoking configure 24 | -------------------------------------------------------------------------------- /projects/argp/build.mk: -------------------------------------------------------------------------------- 1 | # Copyright (c) Meta Platforms, Inc. and affiliates. 2 | 3 | $(eval $(call project-define,argp)) 4 | 5 | $(ARGP_ANDROID): 6 | cd $(ARGP_ANDROID_BUILD_DIR) && make -j $(THREADS) 7 | cp $(ARGP_ANDROID_BUILD_DIR)/gllib/libargp.a $(ANDROID_OUT_DIR)/lib/. 8 | cp projects/argp/headers/argp-wrapper.h $(ANDROID_OUT_DIR)/include/argp.h 9 | cp $(ARGP_SRCS)/gllib/argp.h $(ANDROID_OUT_DIR)/include/argp-real.h 10 | $(call fetch-license,argp,LGPL) 11 | touch $@ 12 | 13 | $(ARGP_ANDROID_BUILD_DIR): $(ANDROID_CONFIG_SITE) 14 | -mkdir $@ 15 | cd $@ && $(ARGP_SRCS)/configure $(ANDROID_EXTRA_CONFIGURE_FLAGS) 16 | 17 | projects/argp/sources: $(call project-optional-sources-target,gnulib) 18 | cd $(call project-sources,gnulib) && ./gnulib-tool --create-testdir \ 19 | --lgpl --lib="libargp" --dir=$(abspath $@) argp 20 | -------------------------------------------------------------------------------- /projects/argp/headers/argp-wrapper.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Meta Platforms, Inc. and affiliates. 2 | 3 | #ifndef ARGP_WRAPPER_H 4 | #define ARGP_WRAPPER_H 5 | 6 | #ifndef ARGP_EI 7 | # define ARGP_EI inline 8 | #endif 9 | 10 | // since ece81a73b64483a68f5157420836d84beb3a1680 argp.h as distributed with 11 | // gnulib requires _GL_INLINE_HEADER_BEGIN macro to be defined. 12 | #ifndef _GL_INLINE_HEADER_BEGIN 13 | # define _GL_INLINE_HEADER_BEGIN 14 | # define _GL_INLINE_HEADER_END 15 | #endif 16 | 17 | #ifndef _GL_ATTRIBUTE_FORMAT 18 | # define _GL_ATTRIBUTE_FORMAT(spec) __attribute__ ((__format__ spec)) 19 | #endif 20 | 21 | #ifndef _GL_ATTRIBUTE_SPEC_PRINTF_SYSTEM 22 | # define _GL_ATTRIBUTE_SPEC_PRINTF_SYSTEM __printf__ 23 | #endif 24 | 25 | #include "argp-real.h" 26 | #endif 27 | -------------------------------------------------------------------------------- /projects/bcc/README: -------------------------------------------------------------------------------- 1 | BPF Compiler Collection (BCC) 2 | Toolkit for creating BPF based tracing tools. 3 | 4 | github: https://github.com/iovisor/bcc 5 | license: Apache 2.0 6 | license url: https://github.com/iovisor/bcc/blob/master/LICENSE.txt 7 | 8 | Default version: v0.29.1 9 | 10 | Building: 11 | - bcc depends on flex binary, which needs to stay in sync with flex header 12 | and library we built for Android (using host flex won't work). We build 13 | flex for host from the same sources as we do for android and we override 14 | the binary used by cmake with -DFLEX_EXECUTABLE 15 | - bps is linked against librt, which on Android is not available and instead 16 | librt functions are provided by bionic 17 | -------------------------------------------------------------------------------- /projects/bcc/build.mk: -------------------------------------------------------------------------------- 1 | # Copyright (c) Meta Platforms, Inc. and affiliates. 2 | 3 | BCC_ANDROID_DEPS = llvm libbpf flex elfutils python xz 4 | BCC_HOST_DEPS = cmake flex python 5 | $(eval $(call project-define,bcc)) 6 | 7 | BCC_EXTRA_CFLAGS += "-I$(abspath $(ANDROID_OUT_DIR))/include" -include strings.h 8 | BCC_EXTRA_LDFLAGS = "-L$(abspath $(ANDROID_OUT_DIR))/lib" 9 | 10 | $(BCC_ANDROID): 11 | ifeq ($(BUILD_TYPE), Debug) 12 | cd $(ANDROID_BUILD_DIR)/bcc && $(MAKE) install -j $(THREADS) 13 | else 14 | cd $(ANDROID_BUILD_DIR)/bcc && $(MAKE) install/strip -j $(THREADS) 15 | endif 16 | cp $(BCC_SRCS)/LICENSE.txt $(ANDROID_OUT_DIR)/licenses/bcc 17 | touch $@ 18 | 19 | # generates bcc build files for Android 20 | $(BCC_ANDROID_BUILD_DIR): $(HOST_OUT_DIR)/bin/flex 21 | -mkdir $@ 22 | cd $@ && CFLAGS="$(BCC_EXTRA_CFLAGS)" CXXFLAGS="$(BCC_EXTRA_CFLAGS)" LDFLAGS="$(BCC_EXTRA_LDFLAGS)" \ 23 | $(CMAKE) $(BCC_SRCS) \ 24 | $(ANDROID_EXTRA_CMAKE_FLAGS) \ 25 | -DFLEX_EXECUTABLE=$(abspath $(HOST_OUT_DIR)/bin/flex) \ 26 | -DBPS_LINK_RT=OFF \ 27 | -DENABLE_TESTS=OFF \ 28 | -DCMAKE_USE_LIBBPF_PACKAGE=ON \ 29 | -DPYTHON_CMD=$(abspath $(HOST_OUT_DIR)/bin/python.xinstall) 30 | 31 | BCC_COMMIT = eb8ede2d70b17350757f2570ef76ea4c2e1dbff8 32 | BCC_REPO = https://github.com/iovisor/bcc 33 | projects/bcc/sources: 34 | git clone $(BCC_REPO) $@ 35 | cd $@ && git checkout $(BCC_COMMIT) 36 | -------------------------------------------------------------------------------- /projects/black/README: -------------------------------------------------------------------------------- 1 | Black 2 | Black is the uncompromising Python code formatter. 3 | 4 | github: https://github.com/psf/black 5 | license url: https://github.com/psf/black#license 6 | -------------------------------------------------------------------------------- /projects/black/build.mk: -------------------------------------------------------------------------------- 1 | # Copyright (c) Meta Platforms, Inc. and affiliates. 2 | 3 | $(eval $(call pip-project,black)) 4 | -------------------------------------------------------------------------------- /projects/bpftrace/README: -------------------------------------------------------------------------------- 1 | bpftrace 2 | High-level tracing language for Linux eBPF 3 | 4 | github: https://github.com/iovisor/bpftrace 5 | license: Apache 2.0 6 | license url: https://github.com/iovisor/bpftrace/blob/master/LICENSE 7 | 8 | Building: 9 | - we need to tell cmake to use flex version that matches the lib and 10 | headers we have for Android. We set FLEX_EXECUTABLE to point to 11 | host executable built from the same sources as we use for Android. 12 | - bpftrace links against stdc++fs which is not available in NDK as a standalone 13 | library. We provide an empty stub for linking purposes. 14 | -------------------------------------------------------------------------------- /projects/bpftrace/build.mk: -------------------------------------------------------------------------------- 1 | # Copyright (c) Meta Platforms, Inc. and affiliates. 2 | 3 | BPFTRACE_ANDROID_DEPS = bcc cereal elfutils flex libbpf llvm stdc++fs xz 4 | BPFTRACE_HOST_DEPS = cmake flex 5 | $(eval $(call project-define,bpftrace)) 6 | 7 | BPFTRACE_EXTRA_LDFLAGS = "-L$(abspath $(ANDROID_OUT_DIR))/lib" 8 | 9 | ifeq ($(STATIC_LINKING),true) 10 | BPFTRACE_EXTRA_CMAKE_FLAGS = -DSTATIC_LINKING=ON 11 | 12 | # XXX: As od 925127c5 ("Make bcc depend on liblzma") we're building libbcc 13 | # with lzma support, but bpftrace currently doesn't have a way to detect this 14 | # dependency, which causes undefined symbol errors when linking statically. 15 | # This fixes it by adding liblzma to the link line. 16 | BPFTRACE_EXTRA_LDFLAGS += "$(abspath $(ANDROID_OUT_DIR))/lib/liblzma.a" 17 | endif 18 | 19 | STRIP_THUNK = $(HOST_OUT_DIR)/bpftrace-strip-thunk 20 | 21 | $(BPFTRACE_ANDROID): $(ANDROID_OUT_DIR)/lib/libc++_shared.so 22 | ifeq ($(BUILD_TYPE), Debug) 23 | cd $(BPFTRACE_ANDROID_BUILD_DIR) && $(MAKE) install -j $(THREADS) 24 | else 25 | cd $(BPFTRACE_ANDROID_BUILD_DIR) && $(MAKE) install/strip -j $(THREADS) 26 | endif 27 | cp $(BPFTRACE_SRCS)/LICENSE $(ANDROID_OUT_DIR)/licenses/bpftrace 28 | touch $@ 29 | 30 | $(BPFTRACE_ANDROID_BUILD_DIR): $(HOST_OUT_DIR)/bin/flex $(STRIP_THUNK) 31 | -mkdir $@ 32 | cd $@ && LDFLAGS="$(BPFTRACE_EXTRA_LDFLAGS)" $(CMAKE) $(BPFTRACE_SRCS) \ 33 | $(ANDROID_EXTRA_CMAKE_FLAGS) \ 34 | $(BPFTRACE_EXTRA_CMAKE_FLAGS) \ 35 | -DBUILD_TESTING=OFF \ 36 | -DENABLE_MAN=OFF \ 37 | -DFLEX_EXECUTABLE=$(abspath $(HOST_OUT_DIR)/bin/flex) \ 38 | -DUSE_SYSTEM_BPF_BCC=ON \ 39 | -DALLOW_UNSAFE_PROBE=ON \ 40 | -DCMAKE_STRIP=$(abspath $(STRIP_THUNK)) 41 | 42 | $(STRIP_THUNK): projects/bpftrace/strip-thunk | $(HOST_OUT_DIR) 43 | @sed -e "s++$(ANDROID_TOOLCHAIN_STRIP_PATH)+g" $< > $@ 44 | chmod +x $@ 45 | 46 | BPFTRACE_COMMIT = v0.23.4 47 | BPFTRACE_REPO = https://github.com/iovisor/bpftrace.git/ 48 | projects/bpftrace/sources: 49 | git clone $(BPFTRACE_REPO) $@ && \ 50 | cd $@ && \ 51 | git checkout $(BPFTRACE_COMMIT) && \ 52 | git cherry-pick 4b5cbe120f581846d5397fa4b2a0cbd34e15c77a --no-commit 53 | -------------------------------------------------------------------------------- /projects/bpftrace/strip-thunk: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | # Copyright (c) Meta Platforms, Inc. and affiliates. 3 | 4 | --keep-symbol BEGIN_trigger --keep-symbol END_trigger "$@" 5 | -------------------------------------------------------------------------------- /projects/buck2/README: -------------------------------------------------------------------------------- 1 | buck2 2 | 3 | github: https://github.com/facebook/buck2 4 | license url: https://github.com/facebook/buck2/blob/main/LICENSE-MIT 5 | 6 | Default version: v2023-09-01 7 | -------------------------------------------------------------------------------- /projects/buck2/REDME: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookexperimental/ExtendedAndroidTools/1a3601739d5fbcb6e272d8425d8e3b099e16523f/projects/buck2/REDME -------------------------------------------------------------------------------- /projects/buck2/build.mk: -------------------------------------------------------------------------------- 1 | # Copyright (c) Meta Platforms, Inc. and affiliates. 2 | 3 | BUCK2_VERSION := 2023-10-01 4 | 5 | ifeq ($(HOST_OS),GNU/Linux) 6 | BUCK2_ARCHIVE_SUFFIX := unknown-linux-gnu 7 | else 8 | BUCK2_ARCHIVE_SUFFIX := apple-darwin 9 | endif 10 | 11 | ifeq ($(HOST_MACHINE),arm64) 12 | BUCK2_ARCHIVE_INFIX := aarch64 13 | else 14 | BUCK2_ARCHIVE_INFIX := $(HOST_MACHINE) 15 | endif 16 | 17 | BUCK2_ARCHIVE := buck2-$(BUCK2_ARCHIVE_INFIX)-$(BUCK2_ARCHIVE_SUFFIX).zst 18 | BUCK2_URL := https://github.com/facebook/buck2/releases/download/$(BUCK2_VERSION)/$(BUCK2_ARCHIVE) 19 | 20 | $(HOST_OUT_DIR)/bin/buck2: $(DOWNLOADS_DIR)/$(BUCK2_ARCHIVE) | $(HOST_OUT_DIR) 21 | # commands to unpack $(BUCK2_ARCHIVE) and set the executable flag 22 | zstd -d $(DOWNLOADS_DIR)/$(BUCK2_ARCHIVE) -o $@ 23 | touch $@ 24 | chmod +x $@ 25 | 26 | $(DOWNLOADS_DIR)/$(BUCK2_ARCHIVE): | $(DOWNLOADS_DIR) 27 | # instructions to download the archive 28 | curl -L -s -o $@ $(BUCK2_URL) 29 | 30 | # Phony target for host 31 | .PHONY: buck2-host 32 | buck2-host: $(HOST_OUT_DIR)/bin/buck2 33 | -------------------------------------------------------------------------------- /projects/cereal/README: -------------------------------------------------------------------------------- 1 | cereal 2 | A C++11 library for serialization 3 | 4 | github: https://github.com/USCiLab/cereal 5 | license: BSD 3-clause 6 | license url: https://github.com/USCiLab/cereal/blob/master/LICENSE 7 | 8 | Default version: v1.3.2 9 | -------------------------------------------------------------------------------- /projects/cereal/build.mk: -------------------------------------------------------------------------------- 1 | # Copyright (c) Meta Platforms, Inc. and affiliates. 2 | 3 | CEREAL_HOST_DEPS = cmake 4 | $(eval $(call project-define,cereal)) 5 | 6 | $(CEREAL_ANDROID): 7 | cd $(CEREAL_ANDROID_BUILD_DIR) && make install -j $(THREADS) 8 | cp $(CEREAL_SRCS)/LICENSE $(ANDROID_OUT_DIR)/licenses/cereal 9 | touch $@ 10 | 11 | $(CEREAL_ANDROID_BUILD_DIR): 12 | -mkdir $@ 13 | cd $@ && $(CMAKE) $(CEREAL_SRCS) \ 14 | $(ANDROID_EXTRA_CMAKE_FLAGS) \ 15 | -DBUILD_TESTS=OFF \ 16 | -DBUILD_DOC=OFF \ 17 | -DBUILD_SANDBOX=OFF \ 18 | -DSKIP_PERFORMANCE_COMPARISON=ON 19 | 20 | CEREAL_TAG = v1.3.2 21 | CEREAL_REPO = https://github.com/USCiLab/cereal 22 | projects/cereal/sources: 23 | git clone $(CEREAL_REPO) -b $(CEREAL_TAG) $@ 24 | -------------------------------------------------------------------------------- /projects/cmake/README: -------------------------------------------------------------------------------- 1 | cmake 2 | https://cmake.org/ 3 | 4 | license: BSD 3-clause 5 | license url: https://cmake.org/licensing/ 6 | 7 | Default version: 3.22.2 8 | -------------------------------------------------------------------------------- /projects/cmake/build.mk: -------------------------------------------------------------------------------- 1 | # Copyright (c) Meta Platforms, Inc. and affiliates. 2 | 3 | $(eval $(call project-define,cmake)) 4 | 5 | $(CMAKE_HOST): 6 | cd $(CMAKE_HOST_BUILD_DIR) && make install -j $(THREADS) 7 | touch $@ 8 | 9 | $(CMAKE_HOST_BUILD_DIR): 10 | -mkdir $@ 11 | cd $@ && $(CMAKE_SRCS)/bootstrap --prefix=$(abspath $(HOST_OUT_DIR)) 12 | 13 | CMAKE_VERSION = 3.22.2 14 | CMAKE_URL = https://github.com/Kitware/CMake/releases/download/v$(CMAKE_VERSION)/cmake-$(CMAKE_VERSION).tar.gz 15 | $(DOWNLOADS_DIR)/cmake-$(CMAKE_VERSION).tar.gz: | $(DOWNLOADS_DIR) 16 | cd $(DOWNLOADS_DIR) && curl -L -O $(CMAKE_URL) 17 | 18 | projects/cmake/sources: $(DOWNLOADS_DIR)/cmake-$(CMAKE_VERSION).tar.gz 19 | -mkdir $@ 20 | tar xf $(DOWNLOADS_DIR)/cmake-$(CMAKE_VERSION).tar.gz -C $@ \ 21 | --transform="s|^cmake-$(CMAKE_VERSION)/||" 22 | -------------------------------------------------------------------------------- /projects/elfutils/README: -------------------------------------------------------------------------------- 1 | elfutils 2 | elfutils can be found here: https://www.sourceware.org/elfutils/ 3 | It provides utils for working with elf files and includes bpf specific backed. 4 | 5 | license: GPLv2+/LGPLv3+ for libs, GPLv3+ for utils 6 | license url: https://sourceware.org/elfutils/ 7 | 8 | Default version: 0.191 9 | Most recent elfutils release available here: 10 | http://sourceware.org/pub/elfutils/0.186/elfutils-0.186.tar.bz2 11 | 12 | Building: 13 | Elfutils is packaged with autotools, you need to run included configure script 14 | and then delegate to make. Issues we need to work around: 15 | - elfutils depends on argp and obstack (or gnulibc) and configure scripts 16 | enforces this dependency. We build libargp.a/libobstack.a exactly for this 17 | reason 18 | - elfutils depend on a number of gnu extensions. libelf requires only a few 19 | though and we're able to provide necessary "compatibility layer" for it 20 | without building gnulib or glibc: 21 | - few functions from `libint.h` header 22 | android_fixups/libint.h provides no-op versions of those functions 23 | - `program_invocation_short_name` variable 24 | we define macro named `program_invocation_short_name` which resolves to 25 | "no-program_invocation_short_name" 26 | We don't bother with remaining dependencies, so utils like readelf are not 27 | compiled. 28 | -------------------------------------------------------------------------------- /projects/elfutils/android_fixups/libintl.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Meta Platforms, Inc. and affiliates. 2 | 3 | #ifndef LIBINTL_H 4 | #define LIBINTL_H 5 | 6 | // libintl.h is included in a lot of sources in efutils, but provided 7 | // functionalities are not really necessary. Because of that we follow 8 | // the AOSP example and provide a fake header turning some functions into 9 | // nops with macros 10 | 11 | #define gettext(x) (x) 12 | #define dgettext(x,y) (y) 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /projects/elfutils/build.mk: -------------------------------------------------------------------------------- 1 | # Copyright (c) Meta Platforms, Inc. and affiliates. 2 | 3 | ELFUTILS_ANDROID_DEPS = argp obstack 4 | $(eval $(call project-define,elfutils)) 5 | 6 | ELFUTILS_EXTRA_CFLAGS += -I$(abspath projects/elfutils/android_fixups) 7 | ELFUTILS_EXTRA_CFLAGS += -Dprogram_invocation_short_name=\\\"no-program_invocation_short_name\\\" 8 | 9 | $(ELFUTILS_ANDROID): 10 | cd $(ELFUTILS_ANDROID_BUILD_DIR)/lib && make -j $(THREADS) 11 | cd $(ELFUTILS_ANDROID_BUILD_DIR)/libelf && make install -j $(THREADS) 12 | cd $(ELFUTILS_ANDROID_BUILD_DIR)/config && make 13 | cp $(ELFUTILS_ANDROID_BUILD_DIR)/config/libelf.pc $(ANDROID_OUT_DIR)/lib/pkgconfig 14 | cp $(ELFUTILS_SRCS)/COPYING-LGPLV3 $(ANDROID_OUT_DIR)/licenses/elfutils-libs 15 | touch $@ 16 | 17 | $(ANDROID_BUILD_DIR)/elfutils: $(ANDROID_CONFIG_SITE) 18 | $(ANDROID_BUILD_DIR)/elfutils: $(ANDROID_OUT_DIR)/lib/pkgconfig/zlib.pc 19 | -mkdir $@ 20 | cd $@ && EXTRA_CFLAGS="$(ELFUTILS_EXTRA_CFLAGS)" $(ELFUTILS_SRCS)/configure \ 21 | $(ANDROID_EXTRA_CONFIGURE_FLAGS) \ 22 | --disable-debuginfod \ 23 | --disable-libdebuginfod \ 24 | --enable-install-elfh 25 | 26 | ELFUTILS_VERSION = 0.191 27 | ELFUTILS_URL = http://sourceware.org/pub/elfutils/$(ELFUTILS_VERSION)/elfutils-$(ELFUTILS_VERSION).tar.bz2 28 | projects/elfutils/sources: | $(DOWNLOADS_DIR) 29 | curl -L $(ELFUTILS_URL) -o $(DOWNLOADS_DIR)/elfutils-$(ELFUTILS_VERSION).tar.bz2 30 | -mkdir $@ 31 | tar xf $(DOWNLOADS_DIR)/elfutils-$(ELFUTILS_VERSION).tar.bz2 -C $@ \ 32 | --transform="s|^elfutils-$(ELFUTILS_VERSION)||" 33 | -------------------------------------------------------------------------------- /projects/ffi/README: -------------------------------------------------------------------------------- 1 | libffi 2 | 3 | github: https://github.com/libffi/libffi 4 | license url: https://github.com/libffi/libffi/blob/master/LICENSE 5 | 6 | Default version: v3.3-rc0 7 | https://github.com/libffi/libffi/tree/v3.3-rc0 8 | First (to be) release which fixes behavior on Android: malloc should not be used 9 | to acquire memory for executable code, and if it is we need to call mprotect 10 | to make it executeble. 11 | -------------------------------------------------------------------------------- /projects/ffi/build.mk: -------------------------------------------------------------------------------- 1 | # Copyright (c) Meta Platforms, Inc. and affiliates. 2 | 3 | $(eval $(call project-define,ffi)) 4 | 5 | FFI_EXTRA_LDFLAGS = -Wl,--undefined-version 6 | 7 | $(FFI_ANDROID): 8 | cd $(FFI_ANDROID_BUILD_DIR) && make install -j $(THREADS) 9 | cp $(FFI_SRCS)/LICENSE $(ANDROID_OUT_DIR)/licenses/ffi 10 | touch $@ 11 | 12 | $(FFI_HOST): 13 | cd $(FFI_HOST_BUILD_DIR) && make install -j $(THREADS) 14 | touch $@ 15 | 16 | $(FFI_ANDROID_BUILD_DIR): $(ANDROID_CONFIG_SITE) 17 | mkdir -p $@ 18 | cd $@ && EXTRA_LDFLAGS=$(FFI_EXTRA_LDFLAGS) $(FFI_SRCS)/configure $(ANDROID_EXTRA_CONFIGURE_FLAGS) 19 | 20 | $(FFI_HOST_BUILD_DIR): $(HOST_CONFIG_SITE) 21 | mkdir -p $@ 22 | cd $@ && $(FFI_SRCS)/configure $(HOST_EXTRA_CONFIGURE_FLAGS) 23 | 24 | FFI_BRANCH_OR_TAG = v3.3-rc0 25 | FFI_REPO = https://github.com/libffi/libffi 26 | projects/ffi/sources: 27 | git clone $(FFI_REPO) $@ --depth=1 -b $(FFI_BRANCH_OR_TAG) 28 | cd $@ && autoreconf -i -f 29 | -------------------------------------------------------------------------------- /projects/flex/README: -------------------------------------------------------------------------------- 1 | flex 2 | flex is the fast lexical analyzer generator 3 | 4 | github: https://github.com/westes/flex 5 | license: modified BSD 6 | license url: https://github.com/westes/flex/blob/master/COPYING 7 | 8 | Default version: 98018e3f58d79e082216d406866942841d4bdf8a 9 | 10 | Building 11 | flex is packaged with autoconf and builds without major problems. The only catch 12 | is that autoreconf is required. 13 | -------------------------------------------------------------------------------- /projects/flex/build.mk: -------------------------------------------------------------------------------- 1 | # Copyright (c) Meta Platforms, Inc. and affiliates. 2 | 3 | $(eval $(call project-define,flex)) 4 | 5 | $(FLEX_ANDROID): 6 | cd $(FLEX_ANDROID_BUILD_DIR) && make -j $(THREADS) 7 | cd $(FLEX_ANDROID_BUILD_DIR)/src && make install-libLTLIBRARIES install-binPROGRAMS install-includeHEADERS 8 | cp $(FLEX_SRCS)/COPYING $(ANDROID_OUT_DIR)/licenses/flex 9 | touch $@ 10 | 11 | $(FLEX_ANDROID_BUILD_DIR): $(ANDROID_CONFIG_SITE) 12 | -mkdir $@ 13 | cd $@ && $(FLEX_SRCS)/configure $(ANDROID_EXTRA_CONFIGURE_FLAGS) 14 | 15 | $(HOST_OUT_DIR)/bin/flex: $(FLEX_HOST) 16 | 17 | $(FLEX_HOST): 18 | cd $(FLEX_HOST_BUILD_DIR) && make install -j $(THREADS) 19 | touch $@ 20 | 21 | $(FLEX_HOST_BUILD_DIR): 22 | -mkdir $@ 23 | cd $@ && $(FLEX_SRCS)/configure --prefix=$(abspath $(HOST_OUT_DIR)) 24 | 25 | FLEX_COMMIT_HASH = 98018e3f58d79e082216d406866942841d4bdf8a 26 | FLEX_REPO = https://github.com/westes/flex.git 27 | projects/flex/sources: 28 | ifeq ($(shell whoami), vagrant) 29 | git clone $(FLEX_REPO) /tmp/flex_sources 30 | cd /tmp/flex_sources && git checkout $(FLEX_COMMIT_HASH) 31 | cd /tmp/flex_sources && ./autogen.sh 32 | mv /tmp/flex_sources $@ 33 | else 34 | git clone $(FLEX_REPO) $@ 35 | cd $@ && git checkout $(FLEX_COMMIT_HASH) 36 | cd $@ && autoreconf -i -f 37 | endif 38 | -------------------------------------------------------------------------------- /projects/gnulib/README: -------------------------------------------------------------------------------- 1 | Gnulib - The GNU Portability Library 2 | https://www.gnu.org/software/gnulib/ 3 | 4 | license: https://git.savannah.gnu.org/gitweb/?p=gnulib.git;a=blob_plain;f=COPYING;hb=HEAD 5 | -------------------------------------------------------------------------------- /projects/gnulib/build.mk: -------------------------------------------------------------------------------- 1 | # Copyright (c) Meta Platforms, Inc. and affiliates. 2 | 3 | $(eval $(call project-define,gnulib)) 4 | 5 | $(GNULIB_ANDROID): 6 | echo "gnulib build is not supported" 7 | false 8 | 9 | GNULIB_COMMIT_HASH = 044bf893acee0a55b22b4be0ede0e3ce010c480a 10 | GNULIB_REPO = https://github.com/simpleton/gnulib-mirror 11 | projects/gnulib/sources: 12 | git clone $(GNULIB_REPO) $@ 13 | cd $@ && git checkout $(GNULIB_COMMIT_HASH) 14 | -------------------------------------------------------------------------------- /projects/jdwp/BUCK: -------------------------------------------------------------------------------- 1 | # Copyright (c) Meta Platforms, Inc. and affiliates. 2 | 3 | python_binary( 4 | name = "main", 5 | main = "main.py", 6 | deps = [], 7 | ) 8 | 9 | 10 | python_library( 11 | name = "lib", 12 | srcs = glob(["**/*.py"]), 13 | visibility = ["PUBLIC"], 14 | ) 15 | -------------------------------------------------------------------------------- /projects/jdwp/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookexperimental/ExtendedAndroidTools/1a3601739d5fbcb6e272d8425d8e3b099e16523f/projects/jdwp/__init__.py -------------------------------------------------------------------------------- /projects/jdwp/build.mk: -------------------------------------------------------------------------------- 1 | # Copyright (c) Meta Platforms, Inc. and affiliates. 2 | 3 | jdwp-host-prepare: \ 4 | black-host \ 5 | buck2-host \ 6 | python-host \ 7 | pyre-host 8 | 9 | jdwp-check: jdwp-host-prepare 10 | buck2 run //projects/jdwp:main 11 | buck2 test //projects/jdwp/... 12 | pyre check 13 | black projects/jdwp --check 14 | 15 | jdwp-format: black-host 16 | black projects/jdwp 17 | -------------------------------------------------------------------------------- /projects/jdwp/codegen/BUCK: -------------------------------------------------------------------------------- 1 | # Copyright (c) Meta Platforms, Inc. and affiliates. 2 | 3 | python_binary( 4 | name="generate-new-types", 5 | main_module="projects.jdwp.codegen.new_type_generator", 6 | deps=[ 7 | ":codegen", 8 | ], 9 | visibility=["//projects/jdwp/runtime/..."], 10 | ) 11 | 12 | python_binary( 13 | name="generate-dataclasses", 14 | main_module="projects.jdwp.codegen.dataclass_generator", 15 | deps=[ 16 | ":codegen", 17 | ], 18 | visibility=["//projects/jdwp/runtime/..."], 19 | ) 20 | 21 | python_library( 22 | name="codegen", 23 | srcs=glob(["**/*.py"]), 24 | deps=["//projects/jdwp/defs:defs"], 25 | visibility=[ 26 | "PUBLIC", 27 | ], 28 | ) 29 | -------------------------------------------------------------------------------- /projects/jdwp/codegen/dataclass_generator.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Meta Platforms, Inc. and affiliates. 2 | 3 | import enum 4 | from textwrap import dedent 5 | from projects.jdwp.codegen.types import python_type_for 6 | import typing 7 | 8 | from projects.jdwp.defs.schema import ( 9 | Array, 10 | ArrayLength, 11 | Command, 12 | CommandSet, 13 | Field, 14 | Struct, 15 | TaggedUnion, 16 | UnionTag, 17 | ) 18 | 19 | 20 | StructLink = typing.Tuple[Struct, Field, Struct] 21 | 22 | 23 | class StructGenerator: 24 | def __init__(self, root: Struct, name: str): 25 | self.__root = root 26 | self.__struct_to_name = compute_struct_names(root, name) 27 | 28 | def __get_python_type_for(self, struct: Struct, field: Field) -> str: 29 | type = field.type 30 | match type: 31 | case Struct(): 32 | return self.__struct_to_name[type] 33 | case Array(): 34 | array_type = typing.cast(Array, type) 35 | return f"typing.List[{self.__struct_to_name[array_type.element_type]}]" 36 | case TaggedUnion(): 37 | tagged_union_type = typing.cast(TaggedUnion, type) 38 | union_types = [ 39 | self.__struct_to_name[case_struct] 40 | for (_, case_struct) in tagged_union_type.cases 41 | ] 42 | union_types_str = ", ".join(union_types) 43 | return f"typing.Union[{union_types_str}]" 44 | case _: 45 | return python_type_for(type) 46 | 47 | def __is_explicit_field(self, field: Field) -> bool: 48 | return not isinstance(field.type, (ArrayLength, UnionTag)) 49 | 50 | def __get_field_name(self, field: Field) -> str: 51 | words = field.name.split(" ") 52 | words = [words[0]] + [word.capitalize() for word in words[1:]] 53 | return "".join(words) 54 | 55 | def __generate_dataclass(self, struct: Struct) -> str: 56 | name = self.__struct_to_name[struct] 57 | fields_def = "\n".join( 58 | f" {self.__get_field_name(field)}: {self.__get_python_type_for(struct, field)}" 59 | for field in struct.fields 60 | if self.__is_explicit_field(field) 61 | ) 62 | class_def = f"@dataclasses.dataclass(frozen=True)\nclass {name}:\n{fields_def}" 63 | return dedent(class_def) 64 | 65 | def generate(self) -> typing.Generator[str, None, None]: 66 | for _, _, nested in reversed(list(nested_structs(self.__root))): 67 | yield self.__generate_dataclass(nested) 68 | yield self.__generate_dataclass(self.__root) 69 | 70 | 71 | def format_enum_name(enum_value: enum.Enum) -> str: 72 | words = enum_value.name.split("_") 73 | formatted_name = "".join(word.capitalize() for word in words) 74 | return f"{formatted_name}Type" 75 | 76 | 77 | def nested_structs(root: Struct) -> typing.Generator[StructLink, None, None]: 78 | for field in root.fields: 79 | field_type = field.type 80 | match field_type: 81 | case Array(): 82 | array_type = typing.cast(Array, field_type) 83 | yield root, field, array_type.element_type 84 | yield from nested_structs(array_type.element_type) 85 | case TaggedUnion(): 86 | tagged_union_type = typing.cast(TaggedUnion, field_type) 87 | for _, struct in tagged_union_type.cases: 88 | yield root, field, struct 89 | yield from nested_structs(struct) 90 | case Struct(): 91 | yield root, field, field_type 92 | yield from nested_structs(field_type) 93 | 94 | 95 | def compute_struct_names(root: Struct, name: str) -> typing.Mapping[Struct, str]: 96 | names = {root: name} 97 | for parent, field, nested in nested_structs(root): 98 | sanitized_field_name = "".join( 99 | word.capitalize() for word in field.name.split(" ") 100 | ) 101 | type = field.type 102 | match type: 103 | case Struct(): 104 | names[nested] = f"{names[parent]}{sanitized_field_name}" 105 | case Array(): 106 | names[nested] = f"{names[parent]}{sanitized_field_name}Element" 107 | case TaggedUnion(): 108 | tagged_union_type = typing.cast(TaggedUnion, type) 109 | for case_value, case_struct in tagged_union_type.cases: 110 | case_name = format_enum_name(case_value) 111 | names[case_struct] = ( 112 | f"{names[parent]}{sanitized_field_name}Case{case_name}" 113 | ) 114 | return names 115 | 116 | 117 | def generate_for_command(command: Command) -> typing.Generator[str, None, None]: 118 | if command.out: 119 | yield from StructGenerator(command.out, f"{command.name}Out").generate() 120 | if command.reply: 121 | yield from StructGenerator(command.reply, f"{command.name}Reply").generate() 122 | 123 | 124 | def generate_for_command_set( 125 | command_set: CommandSet, 126 | ) -> typing.Generator[str, None, None]: 127 | for command in command_set.commands: 128 | yield from generate_for_command(command) 129 | 130 | 131 | def generate_for_all_command_sets() -> typing.Generator[str, None, None]: 132 | # TODO: refactor this once PR90 is merged 133 | from projects.jdwp.defs.command_sets.virtual_machine import VirtualMachine 134 | from projects.jdwp.defs.command_sets.reference_type import ReferenceType 135 | from projects.jdwp.defs.command_sets.event_request import EventRequest 136 | 137 | yield from generate_for_command_set(VirtualMachine) 138 | yield from generate_for_command_set(ReferenceType) 139 | yield from generate_for_command_set(EventRequest) 140 | 141 | 142 | def main(): 143 | print("import dataclasses") 144 | print("import typing") 145 | print("from projects.jdwp.runtime.type_aliases import *") 146 | 147 | for struct_definition in generate_for_all_command_sets(): 148 | print() 149 | print(struct_definition) 150 | 151 | 152 | if __name__ == "__main__": 153 | main() 154 | -------------------------------------------------------------------------------- /projects/jdwp/codegen/new_type_generator.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Meta Platforms, Inc. and affiliates. 2 | 3 | from projects.jdwp.defs.schema import IdType 4 | from projects.jdwp.codegen.types import python_type_for 5 | 6 | 7 | def get_type_alias_definition(jdwp_type: IdType) -> str: 8 | """Return the type alias definition for a given IdType.""" 9 | python_type = python_type_for(jdwp_type) 10 | return f"{python_type} = typing.NewType('{python_type}', int)" 11 | 12 | 13 | def generate_new_types(): 14 | print("import typing") 15 | for id_type in IdType: 16 | type_alias_definition = get_type_alias_definition(id_type) 17 | print(type_alias_definition) 18 | 19 | 20 | if "__main__" == __name__: 21 | generate_new_types() 22 | -------------------------------------------------------------------------------- /projects/jdwp/codegen/types.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Meta Platforms, Inc. and affiliates. 2 | 3 | from projects.jdwp.defs.schema import ( 4 | ArrayLength, 5 | OpaqueType, 6 | IdType, 7 | IntegralType, 8 | Type, 9 | UnionTag, 10 | ) 11 | import typing 12 | 13 | 14 | __OPAQUE_TYPE_MAPPING = { 15 | OpaqueType.BOOLEAN: "bool", 16 | OpaqueType.LOCATION: "typing.Any", 17 | OpaqueType.STRING: "str", 18 | } 19 | 20 | 21 | def python_type_for(jdwp_type: Type) -> str: 22 | match jdwp_type: 23 | case OpaqueType(): 24 | return __OPAQUE_TYPE_MAPPING[jdwp_type] 25 | case IdType(): 26 | return jdwp_type.value[0].upper() + jdwp_type.value[1:] + "Type" 27 | case IntegralType() | ArrayLength() | UnionTag(): 28 | return "int" 29 | case _: 30 | raise Exception("not implemented") 31 | -------------------------------------------------------------------------------- /projects/jdwp/defs/BUCK: -------------------------------------------------------------------------------- 1 | # Copyright (c) Meta Platforms, Inc. and affiliates. 2 | 3 | python_library( 4 | name = "defs", 5 | srcs = glob(["**/*.py"]), 6 | visibility = ["PUBLIC"], 7 | deps = [], 8 | ) 9 | -------------------------------------------------------------------------------- /projects/jdwp/defs/command_sets/event_request.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Meta Platforms, Inc. and affiliates. 2 | 3 | from projects.jdwp.defs.schema import ( 4 | Command, 5 | Field, 6 | Struct, 7 | CommandSet, 8 | IntegralType, 9 | ArrayLength, 10 | Array, 11 | TaggedUnion, 12 | UnionTag, 13 | IdType, 14 | OpaqueType, 15 | ) 16 | from projects.jdwp.defs.constants import ErrorType, ModifierKind 17 | 18 | 19 | CountModifier = Struct( 20 | [Field("count", IntegralType.INT, "Count before event. One for one-off.")] 21 | ) 22 | 23 | ConditionalModifier = Struct([Field("exprID", IntegralType.INT, "For the future")]) 24 | 25 | ThreadOnlyModifier = Struct([Field("thread", IdType.THREAD_ID, "Required thread")]) 26 | 27 | ClassOnlyModifier = Struct([Field("clazz", IdType.REFERENCE_TYPE_ID, "Required class")]) 28 | 29 | ClassMatchModifier = Struct( 30 | [Field("classPattern", OpaqueType.STRING, "Restricted class pattern")] 31 | ) 32 | 33 | StepModifier = Struct( 34 | [ 35 | Field("thread", IdType.THREAD_ID, "Required thread"), 36 | Field("size", IntegralType.INT, "Size of each step"), 37 | Field("depth", IntegralType.INT, "Relative call stack limit"), 38 | ] 39 | ) 40 | 41 | ClassExcludeModifier = Struct( 42 | [Field("classPattern", OpaqueType.STRING, "Disallowed class pattern")] 43 | ) 44 | 45 | LocationOnlyModifier = Struct([Field("loc", OpaqueType.LOCATION, "Required location")]) 46 | 47 | ExceptionOnlyModifier = Struct( 48 | [ 49 | Field( 50 | "exceptionOrNull", 51 | IdType.REFERENCE_TYPE_ID, 52 | "Exception to report. Null (0) means report exceptions of all types.", 53 | ), 54 | Field("caught", OpaqueType.BOOLEAN, "True if exception was caught"), 55 | Field("uncaught", OpaqueType.BOOLEAN, "True if exception was uncaught"), 56 | ] 57 | ) 58 | 59 | FieldOnlyModifier = Struct( 60 | [ 61 | Field( 62 | "declaring", IdType.REFERENCE_TYPE_ID, "Type in which field is declared." 63 | ), 64 | Field("fieldID", IntegralType.INT, "Required field"), 65 | ] 66 | ) 67 | 68 | InstanceOnlyModifier = Struct( 69 | [Field("instance", IdType.OBJECT_ID, "Required 'this' object")] 70 | ) 71 | 72 | SourceNameMatchModifier = Struct( 73 | [Field("sourceNamePattern", OpaqueType.STRING, "Required source name pattern")] 74 | ) 75 | 76 | __SetCommand_out_modKind = Field( 77 | "modKind", UnionTag(IntegralType.BYTE, ModifierKind), "Modifier kind" 78 | ) 79 | 80 | __SetCommand_outArray_element_modifier = Field( 81 | "Modifier cases", 82 | TaggedUnion( 83 | __SetCommand_out_modKind, 84 | [ 85 | (ModifierKind.COUNT, CountModifier), 86 | (ModifierKind.CONDITIONAL, ConditionalModifier), 87 | (ModifierKind.THREAD_ONLY, ThreadOnlyModifier), 88 | (ModifierKind.CLASS_ONLY, ClassOnlyModifier), 89 | (ModifierKind.CLASS_MATCH, ClassMatchModifier), 90 | (ModifierKind.CLASS_EXCLUDE, ClassExcludeModifier), 91 | (ModifierKind.STEP, StepModifier), 92 | (ModifierKind.LOCATION_ONLY, LocationOnlyModifier), 93 | (ModifierKind.EXCEPTION_ONLY, ExceptionOnlyModifier), 94 | (ModifierKind.FIELD_ONLY, FieldOnlyModifier), 95 | (ModifierKind.INSTANCE_ONLY, InstanceOnlyModifier), 96 | (ModifierKind.SOURCE_NAME_MATCH, SourceNameMatchModifier), 97 | ], 98 | ), 99 | "Modifier cases.", 100 | ) 101 | 102 | __SetCommand_outModifierArray_length = Field( 103 | "modifiers", 104 | ArrayLength(IntegralType.INT), 105 | "Constraints used to control the number of generated events.", 106 | ) 107 | __SetCommand_out = Struct( 108 | [ 109 | Field("eventKind", IntegralType.BYTE, "The kind of event to request."), 110 | Field("suspendPolicy", IntegralType.BYTE, "The suspend policy to use."), 111 | __SetCommand_outModifierArray_length, 112 | Field( 113 | "outModifiers", 114 | Array( 115 | Struct( 116 | [ 117 | __SetCommand_out_modKind, 118 | __SetCommand_outArray_element_modifier, 119 | ] 120 | ), 121 | __SetCommand_outModifierArray_length, 122 | ), 123 | "Modifier Array", 124 | ), 125 | ] 126 | ) 127 | 128 | SetCommand = Command( 129 | name="SetCommand", 130 | id=1, 131 | out=__SetCommand_out, 132 | reply=Struct([Field("requestID", IntegralType.INT, "ID of the request created.")]), 133 | error={ 134 | ErrorType.INVALID_EVENT_TYPE, 135 | ErrorType.INVALID_CLASS, 136 | ErrorType.INVALID_STRING, 137 | ErrorType.INVALID_OBJECT, 138 | ErrorType.INVALID_COUNT, 139 | ErrorType.INVALID_FIELDID, 140 | ErrorType.INVALID_METHODID, 141 | ErrorType.INVALID_LOCATION, 142 | ErrorType.INVALID_EVENT_TYPE, 143 | ErrorType.NOT_IMPLEMENTED, 144 | ErrorType.VM_DEAD, 145 | }, 146 | ) 147 | 148 | EventRequest = CommandSet( 149 | name="EventRequest", 150 | id=1, 151 | commands=[ 152 | SetCommand, 153 | ], 154 | ) 155 | -------------------------------------------------------------------------------- /projects/jdwp/defs/command_sets/reference_type.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Meta Platforms, Inc. and affiliates. 2 | 3 | """Command Set: ReferenceType.""" 4 | 5 | 6 | from projects.jdwp.defs.schema import ( 7 | Command, 8 | Field, 9 | Struct, 10 | CommandSet, 11 | IdType, 12 | OpaqueType, 13 | ) 14 | from projects.jdwp.defs.constants import ErrorType 15 | 16 | 17 | Signature = Command( 18 | name="Signature", 19 | id=1, 20 | out=Struct( 21 | [ 22 | Field("refType", IdType.REFERENCE_TYPE_ID, "The Reference type ID."), 23 | ] 24 | ), 25 | reply=Struct( 26 | [ 27 | Field( 28 | "signature", 29 | OpaqueType.STRING, 30 | "The JNI signature for the reference type.", 31 | ), 32 | ] 33 | ), 34 | error={ 35 | ErrorType.INVALID_CLASS, 36 | ErrorType.INVALID_OBJECT, 37 | ErrorType.VM_DEAD, 38 | }, 39 | ) 40 | 41 | 42 | ReferenceType = CommandSet( 43 | name="ReferenceType", 44 | id=2, 45 | commands=[ 46 | Signature, 47 | ], 48 | ) 49 | -------------------------------------------------------------------------------- /projects/jdwp/defs/command_sets/virtual_machine.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Meta Platforms, Inc. and affiliates. 2 | 3 | """JDWP Commands for ThreadReference Command Set.""" 4 | 5 | from projects.jdwp.defs.schema import ( 6 | Command, 7 | Field, 8 | Struct, 9 | IdType, 10 | OpaqueType, 11 | Array, 12 | CommandSet, 13 | ArrayLength, 14 | IntegralType, 15 | ) 16 | from projects.jdwp.defs.constants import ErrorType 17 | 18 | 19 | __AllClasses_reply_classes = Field( 20 | "classes", 21 | ArrayLength(IntegralType.INT), 22 | "Number of reference type that follow", 23 | ) 24 | 25 | 26 | __AllClasses_reply_classesArray_element = Struct( 27 | [ 28 | Field("refTypeTag", IntegralType.BYTE, "Kind of following reference type"), 29 | Field("typeID", IdType.REFERENCE_TYPE_ID, "Loaded reference type"), 30 | Field( 31 | "signature", 32 | OpaqueType.STRING, 33 | "The JNI signature of the loaded reference type", 34 | ), 35 | Field("status", IntegralType.INT, "The current class status"), 36 | ] 37 | ) 38 | 39 | __AllClasses_reply = Struct( 40 | [ 41 | __AllClasses_reply_classes, 42 | Field( 43 | "classesArray", 44 | Array(__AllClasses_reply_classesArray_element, __AllClasses_reply_classes), 45 | "Array of reference type.", 46 | ), 47 | ] 48 | ) 49 | 50 | AllClasses = Command( 51 | name="AllClasses", 52 | id=3, 53 | out=None, 54 | reply=__AllClasses_reply, 55 | error={ 56 | ErrorType.VM_DEAD, 57 | }, 58 | ) 59 | 60 | __Version_reply = Struct( 61 | [ 62 | Field("description", OpaqueType.STRING, "Text information on the VM version"), 63 | Field("jdwpMajor", IntegralType.INT, "JDWP major version number"), 64 | Field("jdwpMinor", IntegralType.INT, "JDWP minor version number"), 65 | Field( 66 | "vmVersion", 67 | OpaqueType.STRING, 68 | "Target VM JRE version, as in the java.version property", 69 | ), 70 | Field( 71 | "vmName", 72 | OpaqueType.STRING, 73 | "Target VM name, as in the java.vm.name property", 74 | ), 75 | ] 76 | ) 77 | 78 | Version = Command( 79 | name="Version", 80 | id=1, 81 | out=None, 82 | reply=__Version_reply, 83 | error={ErrorType.VM_DEAD}, 84 | ) 85 | 86 | Dispose = Command( 87 | name="Dispose", 88 | id=6, 89 | out=None, 90 | reply=None, 91 | error=set(), 92 | ) 93 | 94 | __IDSizes_reply = Struct( 95 | [ 96 | Field("fieldIDSize", IntegralType.INT, "fieldID size in bytes"), 97 | Field("methodIDSize", IntegralType.INT, "methodID size in bytes"), 98 | Field("objectIDSize", IntegralType.INT, "objectID size in bytes"), 99 | Field("referenceTypeIDSize", IntegralType.INT, "referenceTypeID size in bytes"), 100 | Field("frameIDSize", IntegralType.INT, "frameID size in bytes"), 101 | ] 102 | ) 103 | 104 | IDSizes = Command( 105 | name="IDSizes", 106 | id=7, 107 | out=None, 108 | reply=__IDSizes_reply, 109 | error={ErrorType.VM_DEAD}, 110 | ) 111 | 112 | __ClassPaths_reply_ClassPaths = Field( 113 | "classpaths", 114 | ArrayLength(IntegralType.INT), 115 | "Number of paths in classpath", 116 | ) 117 | 118 | __ClassPaths_replyArray_element = Struct( 119 | [ 120 | Field("classpaths", OpaqueType.STRING, "List of classpath entries"), 121 | ] 122 | ) 123 | 124 | __BootClassPaths_reply_bootClassPaths = Field( 125 | "bootclasspaths", 126 | ArrayLength(IntegralType.INT), 127 | "Number of paths in bootclasspath", 128 | ) 129 | 130 | __BootClassPaths_replyArray_element = Struct( 131 | [ 132 | Field("bootclasspaths", OpaqueType.STRING, "List of bootclasspath entries"), 133 | ] 134 | ) 135 | 136 | __ClassPaths_reply = Struct( 137 | [ 138 | Field( 139 | "baseDir", 140 | OpaqueType.STRING, 141 | "Base directory used to resolve relative paths in either of the following lists.", 142 | ), 143 | __ClassPaths_reply_ClassPaths, 144 | Field( 145 | "classpaths Array", 146 | Array(__ClassPaths_replyArray_element, __ClassPaths_reply_ClassPaths), 147 | "Array of classpath.", 148 | ), 149 | __BootClassPaths_reply_bootClassPaths, 150 | Field( 151 | "bootclasspaths Array", 152 | Array( 153 | __BootClassPaths_replyArray_element, 154 | __BootClassPaths_reply_bootClassPaths, 155 | ), 156 | "Array of bootclasspath.", 157 | ), 158 | ] 159 | ) 160 | 161 | ClassPaths = Command( 162 | name="ClassPaths", 163 | id=13, 164 | out=None, 165 | reply=__ClassPaths_reply, 166 | error={ 167 | ErrorType.VM_DEAD, 168 | }, 169 | ) 170 | 171 | VirtualMachine = CommandSet( 172 | name="VirtualMachine", 173 | id=1, 174 | commands=[ 175 | Version, 176 | AllClasses, 177 | Dispose, 178 | IDSizes, 179 | ClassPaths, 180 | ], 181 | ) 182 | -------------------------------------------------------------------------------- /projects/jdwp/defs/constants.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Meta Platforms, Inc. and affiliates. 2 | 3 | from enum import Enum, Flag 4 | 5 | 6 | class ErrorType(Enum): 7 | """Error constants for JDWP.""" 8 | 9 | NONE = 0 10 | INVALID_THREAD = 10 11 | INVALID_THREAD_GROUP = 11 12 | INVALID_PRIORITY = 12 13 | THREAD_NOT_SUSPENDED = 13 14 | THREAD_SUSPENDED = 14 15 | THREAD_NOT_ALIVE = 15 16 | INVALID_OBJECT = 20 17 | INVALID_CLASS = 21 18 | CLASS_NOT_PREPARED = 22 19 | INVALID_METHODID = 23 20 | INVALID_LOCATION = 24 21 | INVALID_FIELDID = 25 22 | INVALID_FRAMEID = 30 23 | NO_MORE_FRAMES = 31 24 | OPAQUE_FRAME = 32 25 | NOT_CURRENT_FRAME = 33 26 | TYPE_MISMATCH = 34 27 | INVALID_SLOT = 35 28 | DUPLICATE = 40 29 | NOT_FOUND = 41 30 | INVALID_MONITOR = 50 31 | NOT_MONITOR_OWNER = 51 32 | INTERRUPT = 52 33 | INVALID_CLASS_FORMAT = 60 34 | CIRCULAR_CLASS_DEFINITION = 61 35 | FAILS_VERIFICATION = 62 36 | ADD_METHOD_NOT_IMPLEMENTED = 63 37 | SCHEMA_CHANGE_NOT_IMPLEMENTED = 64 38 | INVALID_TYPESTATE = 65 39 | HIERARCHY_CHANGE_NOT_IMPLEMENTED = 66 40 | DELETE_METHOD_NOT_IMPLEMENTED = 67 41 | UNSUPPORTED_VERSION = 68 42 | NAMES_DONT_MATCH = 69 43 | CLASS_MODIFIERS_CHANGE_NOT_IMPLEMENTED = 70 44 | METHOD_MODIFIERS_CHANGE_NOT_IMPLEMENTED = 71 45 | NOT_IMPLEMENTED = 99 46 | NULL_POINTER = 100 47 | ABSENT_INFORMATION = 101 48 | INVALID_EVENT_TYPE = 102 49 | ILLEGAL_ARGUMENT = 103 50 | OUT_OF_MEMORY = 110 51 | ACCESS_DENIED = 111 52 | VM_DEAD = 112 53 | INTERNAL = 113 54 | UNATTACHED_THREAD = 115 55 | INVALID_TAG = 500 56 | ALREADY_INVOKING = 502 57 | INVALID_INDEX = 503 58 | INVALID_LENGTH = 504 59 | INVALID_STRING = 506 60 | INVALID_CLASS_LOADER = 507 61 | INVALID_ARRAY = 508 62 | TRANSPORT_LOAD = 509 63 | TRANSPORT_INIT = 510 64 | NATIVE_METHOD = 511 65 | INVALID_COUNT = 512 66 | 67 | 68 | class ClassStatus(Enum): 69 | """ClassStatus constants for JDWP.""" 70 | 71 | VERIFIED = 1 72 | PREPARED = 2 73 | INITIALIZED = 4 74 | ERROR = 8 75 | 76 | 77 | class EventKind(Enum): 78 | """EventKind constants for JDWP.""" 79 | 80 | SINGLE_STEP = 1 81 | BREAKPOINT = 2 82 | FRAME_POP = 3 83 | EXCEPTION = 4 84 | USER_DEFINED = 5 85 | THREAD_START = 6 86 | THREAD_DEATH = 7 87 | THREAD_END = 7 88 | CLASS_PREPARE = 8 89 | CLASS_UNLOAD = 9 90 | CLASS_LOAD = 10 91 | FIELD_ACCESS = 20 92 | FIELD_MODIFICATION = 21 93 | EXCEPTION_CATCH = 30 94 | METHOD_ENTRY = 40 95 | METHOD_EXIT = 41 96 | METHOD_EXIT_WITH_RETURN_VALUE = 42 97 | MONITOR_CONTENDED_ENTER = 43 98 | MONITOR_CONTENDED_ENTERED = 44 99 | MONITOR_WAIT = 45 100 | MONITOR_WAITED = 46 101 | VM_START = 90 102 | VM_INIT = 90 103 | VM_DEATH = 99 104 | VM_DISCONNECTED = 100 105 | 106 | 107 | class InvokeOptions(Flag): 108 | """Invoke options constants for JDWP.""" 109 | 110 | INVOKE_SINGLE_THREADED = 0x01 111 | INVOKE_NONVIRTUAL = 0x02 112 | 113 | 114 | class StepDepth(Enum): 115 | """StepDepth constants for JDWP.""" 116 | 117 | INTO = 0 118 | OVER = 1 119 | OUT = 2 120 | 121 | 122 | class StepSize(Enum): 123 | """StepSize constants for JDWP.""" 124 | 125 | MIN = 0 126 | LINE = 1 127 | 128 | 129 | class SuspendPolicy(Enum): 130 | """SuspendPolicy constants for JDWP.""" 131 | 132 | NONE = 0 133 | EVENT_THREAD = 1 134 | ALL = 2 135 | 136 | 137 | class SuspendStatus(Enum): 138 | """SuspendStatus constants for JDWP.""" 139 | 140 | SUSPEND_STATUS_SUSPENDED = 0x1 141 | 142 | 143 | class Tag(Enum): 144 | """Tag constants for JDWP.""" 145 | 146 | ARRAY = 91 147 | BYTE = 66 148 | CHAR = 67 149 | OBJECT = 76 150 | FLOAT = 70 151 | DOUBLE = 68 152 | INT = 73 153 | LONG = 74 154 | SHORT = 83 155 | VOID = 86 156 | BOOLEAN = 90 157 | STRING = 115 158 | THREAD = 116 159 | THREAD_GROUP = 103 160 | CLASS_LOADER = 108 161 | CLASS_OBJECT = 99 162 | 163 | 164 | class ThreadStatus(Enum): 165 | """ThreadStatus constants for JDWP.""" 166 | 167 | ZOMBIE = 0 168 | RUNNING = 1 169 | SLEEPING = 2 170 | MONITOR = 3 171 | WAIT = 4 172 | 173 | 174 | class TypeTag(Enum): 175 | """TypeTag constants for JDWP.""" 176 | 177 | CLASS = 1 178 | INTERFACE = 2 179 | ARRAY = 3 180 | 181 | 182 | class ModifierKind(Enum): 183 | COUNT = 1 184 | CONDITIONAL = 2 185 | THREAD_ONLY = 3 186 | CLASS_ONLY = 4 187 | CLASS_MATCH = 5 188 | CLASS_EXCLUDE = 6 189 | LOCATION_ONLY = 7 190 | EXCEPTION_ONLY = 8 191 | FIELD_ONLY = 9 192 | STEP = 10 193 | INSTANCE_ONLY = 11 194 | SOURCE_NAME_MATCH = 12 195 | -------------------------------------------------------------------------------- /projects/jdwp/defs/schema.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Meta Platforms, Inc. and affiliates. 2 | 3 | """Basic types for JDWP messages.""" 4 | 5 | from __future__ import annotations 6 | from dataclasses import dataclass 7 | from typing import Optional, Generic, Tuple, TypeVar, Type as TypeAlias, Union 8 | from collections.abc import Mapping 9 | from enum import Enum 10 | from collections.abc import Set, Sequence 11 | from projects.jdwp.defs.constants import ErrorType 12 | 13 | 14 | Type = Union[ 15 | "Array", 16 | "ArrayLength", 17 | "IdType", 18 | "IntegralType", 19 | "OpaqueType", 20 | "Struct", 21 | "TaggedUnion", 22 | "UnionTag", 23 | ] 24 | 25 | 26 | class OpaqueType(Enum): 27 | """Opaque types whose implementation is provided by debugger runtime library or language.""" 28 | 29 | BOOLEAN = "boolean" 30 | # TAGGED_OBJECT_ID = "tagged-objectID" 31 | LOCATION = "location" 32 | STRING = "string" 33 | # VALUE = "value" 34 | # UNTAGGED_VALUE = "untagged-value" 35 | # ARRAY_REGION = "arrayregion" 36 | 37 | 38 | class IdType(Enum): 39 | """Types representing numeric IDs of internal VM objects.""" 40 | 41 | OBJECT_ID = "objectID" 42 | THREAD_ID = "threadID" 43 | THREAD_GROUP_ID = "threadGroupID" 44 | STRING_ID = "stringID" 45 | CLASS_LOADER_ID = "classLoaderID" 46 | CLASS_OBJECT_ID = "classObjectID" 47 | ARRAY_ID = "arrayID" 48 | REFERENCE_TYPE_ID = "referenceTypeID" 49 | CLASS_ID = "classID" 50 | INTERFACE_ID = "interfaceID" 51 | ARRAY_TYPE_ID = "arrayTypeID" 52 | METHOD_ID = "methodID" 53 | FIELD_ID = "fieldID" 54 | FRAME_ID = "frameID" 55 | 56 | 57 | class IntegralType(Enum): 58 | """Integer types of different precision.""" 59 | 60 | BYTE = "byte" 61 | INT = "int" 62 | LONG = "long" 63 | 64 | 65 | @dataclass(frozen=True) 66 | class ArrayLength: 67 | """Array length class.""" 68 | 69 | type: IntegralType 70 | 71 | 72 | @dataclass(frozen=True) 73 | class Array: 74 | """Array class type.""" 75 | 76 | element_type: Struct 77 | length: Field[ArrayLength] 78 | 79 | 80 | EnumT = TypeVar("EnumT", bound=Enum) 81 | 82 | 83 | @dataclass(frozen=True) 84 | class TaggedUnion(Generic[EnumT]): 85 | """Tagged Union class type""" 86 | 87 | tag: Field[UnionTag[EnumT]] 88 | cases: Sequence[Tuple[EnumT, Struct]] 89 | 90 | def __post_init__(self): 91 | object.__setattr__(self, "cases", tuple(self.cases)) 92 | 93 | 94 | @dataclass(frozen=True) 95 | class UnionTag(Generic[EnumT]): 96 | """Union tag class type.""" 97 | 98 | tag: IntegralType 99 | value: TypeAlias[EnumT] 100 | 101 | 102 | TypeT = TypeVar("TypeT", bound=Type, covariant=True) 103 | 104 | 105 | @dataclass(frozen=True) 106 | class Field(Generic[TypeT]): 107 | """Field class.""" 108 | 109 | name: str 110 | type: TypeT 111 | description: str 112 | 113 | 114 | @dataclass(frozen=True) 115 | class Struct: 116 | """Struct class.""" 117 | 118 | fields: Sequence[Field[Type]] 119 | 120 | def __post_init__(self): 121 | object.__setattr__(self, "fields", tuple(self.fields)) 122 | 123 | 124 | @dataclass(frozen=True) 125 | class Command: 126 | """Command class.""" 127 | 128 | name: str 129 | id: int 130 | out: Optional[Struct] 131 | reply: Optional[Struct] 132 | error: Set[ErrorType] 133 | 134 | def __post_init__(self): 135 | object.__setattr__(self, "error", frozenset(self.error)) 136 | 137 | 138 | @dataclass(frozen=True) 139 | class CommandSet: 140 | """Command set class.""" 141 | 142 | name: str 143 | id: int 144 | commands: Sequence[Command] 145 | 146 | def __post_init__(self): 147 | object.__setattr__(self, "commands", tuple(self.commands)) 148 | -------------------------------------------------------------------------------- /projects/jdwp/main.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Meta Platforms, Inc. and affiliates. 2 | 3 | 4 | def main(): 5 | return None 6 | 7 | 8 | if __name__ == "__main__": 9 | main() 10 | -------------------------------------------------------------------------------- /projects/jdwp/runtime/BUCK: -------------------------------------------------------------------------------- 1 | # Copyright (c) Meta Platforms, Inc. and affiliates. 2 | 3 | genrule( 4 | name = "type-aliases", 5 | out = "type_aliases.py", 6 | cmd = "$(exe //projects/jdwp/codegen:generate-new-types) > $OUT", 7 | ) 8 | 9 | genrule( 10 | name = "structs", 11 | out = "structs.py", 12 | cmd = "$(exe //projects/jdwp/codegen:generate-dataclasses) > $OUT", 13 | ) 14 | 15 | python_library( 16 | name = "runtime", 17 | srcs = [ 18 | ":structs", 19 | ":type-aliases", 20 | "async_streams.py", 21 | "jdwpstruct.py", 22 | ], 23 | visibility = ["PUBLIC", ], 24 | deps = [], 25 | ) 26 | -------------------------------------------------------------------------------- /projects/jdwp/runtime/async_streams.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Meta Platforms, Inc. and affiliates. 2 | 3 | import abc 4 | import typing 5 | 6 | from projects.jdwp.runtime.type_aliases import * 7 | 8 | 9 | class JDWPInputStreamBase(abc.ABC): 10 | # Methods for OpaqueType 11 | @abc.abstractmethod 12 | async def read_boolean(self) -> bool: 13 | pass 14 | 15 | @abc.abstractmethod 16 | async def read_location(self) -> typing.Any: 17 | pass 18 | 19 | @abc.abstractmethod 20 | async def read_string(self) -> str: 21 | pass 22 | 23 | # Methods for IdType 24 | @abc.abstractmethod 25 | async def read_object_id(self) -> ObjectIDType: 26 | pass 27 | 28 | @abc.abstractmethod 29 | async def read_thread_id(self) -> ThreadIDType: 30 | pass 31 | 32 | @abc.abstractmethod 33 | async def read_thread_group_id(self) -> ThreadGroupIDType: 34 | pass 35 | 36 | @abc.abstractmethod 37 | async def read_string_id(self) -> StringIDType: 38 | pass 39 | 40 | @abc.abstractmethod 41 | async def read_class_loader_id(self) -> ClassLoaderIDType: 42 | pass 43 | 44 | @abc.abstractmethod 45 | async def read_class_object_id(self) -> ClassObjectIDType: 46 | pass 47 | 48 | @abc.abstractmethod 49 | async def read_array_id(self) -> ArrayIDType: 50 | pass 51 | 52 | @abc.abstractmethod 53 | async def read_reference_type_id(self) -> ReferenceTypeIDType: 54 | pass 55 | 56 | @abc.abstractmethod 57 | async def read_class_id(self) -> ClassIDType: 58 | pass 59 | 60 | @abc.abstractmethod 61 | async def read_interface_id(self) -> InterfaceIDType: 62 | pass 63 | 64 | @abc.abstractmethod 65 | async def read_array_type_id(self) -> ArrayTypeIDType: 66 | pass 67 | 68 | @abc.abstractmethod 69 | async def read_method_id(self) -> MethodIDType: 70 | pass 71 | 72 | @abc.abstractmethod 73 | async def read_field_id(self) -> FieldIDType: 74 | pass 75 | 76 | @abc.abstractmethod 77 | async def read_frame_id(self) -> FrameIDType: 78 | pass 79 | 80 | # Methods for IntegralType 81 | @abc.abstractmethod 82 | async def read_byte(self) -> int: 83 | pass 84 | 85 | @abc.abstractmethod 86 | async def read_int(self) -> int: 87 | pass 88 | 89 | @abc.abstractmethod 90 | async def read_long( 91 | self, 92 | ) -> int: 93 | pass 94 | 95 | 96 | class JDWPOutputStreamBase(abc.ABC): 97 | # Methods for OpaqueType 98 | @abc.abstractmethod 99 | def write_boolean(self, value: bool) -> None: 100 | pass 101 | 102 | @abc.abstractmethod 103 | def write_location(self, value: typing.Any) -> None: 104 | pass 105 | 106 | @abc.abstractmethod 107 | def write_string(self, value: str) -> None: 108 | pass 109 | 110 | # Methods for IdType 111 | @abc.abstractmethod 112 | def write_object_id(self, value: ObjectIDType) -> None: 113 | pass 114 | 115 | @abc.abstractmethod 116 | def write_thread_id(self, value: ThreadIDType) -> None: 117 | pass 118 | 119 | @abc.abstractmethod 120 | def write_thread_group_id(self, value: ThreadGroupIDType) -> None: 121 | pass 122 | 123 | @abc.abstractmethod 124 | def write_string_id(self, value: StringIDType) -> None: 125 | pass 126 | 127 | @abc.abstractmethod 128 | def write_class_loader_id(self, value: ClassLoaderIDType) -> None: 129 | pass 130 | 131 | @abc.abstractmethod 132 | def write_class_object_id(self, value: ClassObjectIDType) -> None: 133 | pass 134 | 135 | @abc.abstractmethod 136 | def write_array_id(self, value: ArrayIDType) -> None: 137 | pass 138 | 139 | @abc.abstractmethod 140 | def write_reference_type_id(self, value: ReferenceTypeIDType) -> None: 141 | pass 142 | 143 | @abc.abstractmethod 144 | def write_class_id(self, value: ClassIDType) -> None: 145 | pass 146 | 147 | @abc.abstractmethod 148 | def write_interface_id(self, value: InterfaceIDType) -> None: 149 | pass 150 | 151 | @abc.abstractmethod 152 | def write_array_type_id(self, value: ArrayTypeIDType) -> None: 153 | pass 154 | 155 | @abc.abstractmethod 156 | def write_method_id(self, value: MethodIDType) -> None: 157 | pass 158 | 159 | @abc.abstractmethod 160 | def write_field_id(self, value: FieldIDType) -> None: 161 | pass 162 | 163 | @abc.abstractmethod 164 | def write_frame_id(self, value: FrameIDType) -> None: 165 | pass 166 | 167 | # Methods for IntegralType 168 | @abc.abstractmethod 169 | def write_byte(self, value: int) -> None: 170 | pass 171 | 172 | @abc.abstractmethod 173 | def write_int(self, value: int) -> None: 174 | pass 175 | 176 | @abc.abstractmethod 177 | def write_long( 178 | self, 179 | value: int, 180 | ) -> None: 181 | pass 182 | -------------------------------------------------------------------------------- /projects/jdwp/runtime/jdwpstruct.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Meta Platforms, Inc. and affiliates. 2 | 3 | from __future__ import annotations 4 | 5 | import abc 6 | from projects.jdwp.runtime.async_streams import ( 7 | JDWPInputStreamBase, 8 | JDWPOutputStreamBase, 9 | ) 10 | 11 | 12 | class JDWPStruct(abc.ABC): 13 | @abc.abstractmethod 14 | def serialize(self, output: JDWPOutputStreamBase): 15 | pass 16 | 17 | @staticmethod 18 | @abc.abstractmethod 19 | async def parse(input: JDWPInputStreamBase) -> JDWPStruct: 20 | pass 21 | -------------------------------------------------------------------------------- /projects/jdwp/tests/BUCK: -------------------------------------------------------------------------------- 1 | # Copyright (c) Meta Platforms, Inc. and affiliates. 2 | 3 | python_test( 4 | name = "tests", 5 | deps = [ 6 | "//projects/jdwp/defs:defs", 7 | "//projects/jdwp/codegen:codegen", 8 | "//projects/jdwp/runtime:runtime", 9 | ], 10 | srcs = glob(["**/*.py"]), 11 | ) 12 | -------------------------------------------------------------------------------- /projects/jdwp/tests/defs/schema.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Meta Platforms, Inc. and affiliates. 2 | 3 | import unittest 4 | 5 | 6 | class SchemaTests(unittest.TestCase): 7 | def test_schema_can_be_imported(self): 8 | from projects.jdwp.defs.schema import OpaqueType 9 | 10 | def test_command_sets_are_hashable(self): 11 | from projects.jdwp.defs.command_sets import ( 12 | event_request, 13 | reference_type, 14 | virtual_machine, 15 | ) 16 | 17 | hash(event_request.EventRequest) 18 | hash(reference_type.ReferenceType) 19 | hash(event_request.EventRequest) 20 | -------------------------------------------------------------------------------- /projects/jdwp/tests/runtime/import.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Meta Platforms, Inc. and affiliates. 2 | 3 | import unittest 4 | 5 | 6 | class ImportTest(unittest.TestCase): 7 | def test_structs_can_be_imported(self): 8 | from projects.jdwp.runtime.structs import IDSizesReply 9 | 10 | def test_type_aliases_can_be_imported(self): 11 | from projects.jdwp.runtime.type_aliases import ReferenceTypeIDType 12 | 13 | def test_jdwpstruct_can_be_imported(self): 14 | from projects.jdwp.runtime.jdwpstruct import JDWPStruct 15 | 16 | def test_streams_can_be_imported(self): 17 | from projects.jdwp.runtime.async_streams import JDWPInputStreamBase 18 | -------------------------------------------------------------------------------- /projects/jdwp/tests/test_dataclass_generator.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Meta Platforms, Inc. and affiliates. 2 | 3 | import unittest 4 | from projects.jdwp.defs.schema import ArrayLength, IntegralType, Struct, Field, Array 5 | from projects.jdwp.codegen.dataclass_generator import StructGenerator 6 | 7 | 8 | class TestStructGenerator(unittest.TestCase): 9 | def test_simple_struct(self): 10 | simple_struct = Struct( 11 | fields=[ 12 | Field(name="id", type=IntegralType.INT, description="An integer ID") 13 | ] 14 | ) 15 | 16 | generator = StructGenerator(simple_struct, "SimpleStruct") 17 | 18 | result = generator.generate() 19 | 20 | expected = [ 21 | "@dataclasses.dataclass(frozen=True)\n" 22 | "class SimpleStruct:\n" 23 | " id: int" 24 | ] 25 | 26 | self.assertSequenceEqual(list(result), expected) 27 | 28 | def test_nested_struct(self): 29 | inner_struct = Struct( 30 | fields=[ 31 | Field( 32 | name="inner_field", 33 | type=IntegralType.INT, 34 | description="Inner integer field", 35 | ) 36 | ] 37 | ) 38 | outer_struct = Struct( 39 | fields=[ 40 | Field(name="nested", type=inner_struct, description="Nested structure") 41 | ] 42 | ) 43 | 44 | generator = StructGenerator(outer_struct, "OuterStruct") 45 | 46 | result = generator.generate() 47 | 48 | expected = [ 49 | "@dataclasses.dataclass(frozen=True)\n" 50 | "class OuterStructNested:\n" 51 | " inner_field: int", 52 | "@dataclasses.dataclass(frozen=True)\n" 53 | "class OuterStruct:\n" 54 | " nested: OuterStructNested", 55 | ] 56 | 57 | self.assertSequenceEqual(list(result), expected) 58 | 59 | def test_struct_in_array(self): 60 | # Define a structure 61 | element_struct = Struct( 62 | fields=[ 63 | Field( 64 | name="element_field", 65 | type=IntegralType.INT, 66 | description="Element field", 67 | ) 68 | ] 69 | ) 70 | 71 | array_length = Field( 72 | name="length", 73 | type=ArrayLength(type=IntegralType.INT), 74 | description="Array length", 75 | ) 76 | 77 | array_struct = Struct( 78 | fields=[ 79 | array_length, 80 | Field( 81 | name="array of elements", 82 | type=Array( 83 | element_type=element_struct, 84 | length=array_length, 85 | ), 86 | description="Array of structures", 87 | ), 88 | ] 89 | ) 90 | 91 | generator = StructGenerator(array_struct, "ArrayStruct") 92 | 93 | result = generator.generate() 94 | 95 | expected = [ 96 | "@dataclasses.dataclass(frozen=True)\n" 97 | "class ArrayStructArrayOfElementsElement:\n" 98 | " element_field: int", 99 | "@dataclasses.dataclass(frozen=True)\n" 100 | "class ArrayStruct:\n" 101 | " arrayOfElements: typing.List[ArrayStructArrayOfElementsElement]", 102 | ] 103 | 104 | self.assertSequenceEqual(list(result), expected) 105 | -------------------------------------------------------------------------------- /projects/jdwp/tests/test_new_type_generator.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Meta Platforms, Inc. and affiliates. 2 | 3 | import unittest 4 | from projects.jdwp.defs.schema import IdType 5 | from projects.jdwp.codegen.new_type_generator import get_type_alias_definition 6 | 7 | 8 | class TestTypeAliasDefinition(unittest.TestCase): 9 | def test_specific_type_alias_definitions(self): 10 | expected_object_id_type_definition = ( 11 | "ObjectIDType = typing.NewType('ObjectIDType', int)" 12 | ) 13 | self.assertEqual( 14 | get_type_alias_definition(IdType.OBJECT_ID), 15 | expected_object_id_type_definition, 16 | ) 17 | -------------------------------------------------------------------------------- /projects/jdwp/tests/test_types.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Meta Platforms, Inc. and affiliates. 2 | 3 | import unittest 4 | from projects.jdwp.codegen.types import python_type_for 5 | from projects.jdwp.defs.schema import ArrayLength, IdType, IntegralType 6 | 7 | 8 | class TestTypesMapping(unittest.TestCase): 9 | def test_id_type_mapping(self): 10 | for id_type in IdType: 11 | with self.subTest(id_type=id_type): 12 | result = python_type_for(id_type) 13 | self.assertIsInstance( 14 | result, str, f"Mapping for {id_type} is missing or not a string" 15 | ) 16 | 17 | def test_array_length(self): 18 | from projects.jdwp.defs.schema import ArrayLength, IntegralType 19 | 20 | self.assertEqual(python_type_for(ArrayLength(IntegralType.LONG)), "int") 21 | -------------------------------------------------------------------------------- /projects/libbpf/README: -------------------------------------------------------------------------------- 1 | libbpf 2 | 3 | license: LGPL-2.1/BSD-2-Clause 4 | license url: https://github.com/libbpf/libbpf/blob/master/LICENSE 5 | 6 | Default version: 1.4.6 7 | https://github.com/libbpf/libbpf 8 | -------------------------------------------------------------------------------- /projects/libbpf/build.mk: -------------------------------------------------------------------------------- 1 | # Copyright (c) Meta Platforms, Inc. and affiliates. 2 | 3 | LIBBPF_ANDROID_DEPS = elfutils 4 | $(eval $(call project-define,libbpf)) 5 | 6 | LIBBPF_EXTRA_CFLAGS += "-D__user=" 7 | LIBBPF_EXTRA_CFLAGS += "-D__force=" 8 | LIBBPF_EXTRA_CFLAGS += "-D__poll_t=unsigned" 9 | LIBBPF_EXTRA_CFLAGS += "-Wno-tautological-constant-out-of-range-compare" 10 | 11 | $(LIBBPF_ANDROID): \ 12 | export PKG_CONFIG_LIBDIR=$(abspath $(ANDROID_OUT_DIR)/lib/pkgconfig) 13 | $(LIBBPF_ANDROID): $(ANDROID_OUT_DIR)/lib/pkgconfig/zlib.pc 14 | cd $(LIBBPF_SRCS)/src && make install install_uapi_headers \ 15 | -j $(THREADS) \ 16 | LIBSUBDIR=lib \ 17 | PREFIX=$(abspath $(ANDROID_OUT_DIR)) \ 18 | OBJDIR=$(abspath $(LIBBPF_ANDROID_BUILD_DIR)) \ 19 | AR=$(abspath $(ANDROID_TOOLCHAIN_PATH)/llvm-ar) \ 20 | CC=$(abspath $(ANDROID_TOOLCHAIN_PATH)/$(ANDROID_TRIPLE)$(NDK_API)-clang) \ 21 | EXTRA_CFLAGS="$(LIBBPF_EXTRA_CFLAGS)" 22 | cp $(LIBBPF_SRCS)/LICENSE $(ANDROID_OUT_DIR)/licenses/libbpf 23 | touch $@ 24 | 25 | $(LIBBPF_ANDROID_BUILD_DIR): 26 | mkdir -p $@ 27 | 28 | LIBBPF_TAG = v1.5.0 29 | LIBBPF_REPO = https://github.com/libbpf/libbpf 30 | projects/libbpf/sources: 31 | git clone $(LIBBPF_REPO) $@ -b $(LIBBPF_TAG) 32 | -------------------------------------------------------------------------------- /projects/licenses.mk: -------------------------------------------------------------------------------- 1 | # Copyright (c) Meta Platforms, Inc. and affiliates. 2 | 3 | # Definitions of licensing macros 4 | 5 | # https://www.gnu.org/licenses/lgpl-3.0.txt 6 | LGPL_URL := https://raw.githubusercontent.com/facebookexperimental/ExtendedAndroidTools/refs/heads/main/licenses/lgpl-3.0.txt 7 | 8 | fetch-license = curl -L $($(2)_URL) -o $(ANDROID_OUT_DIR)/licenses/$(1) 9 | -------------------------------------------------------------------------------- /projects/llvm/README: -------------------------------------------------------------------------------- 1 | LLVM and Clang sources. 2 | 3 | github: https://github.com/llvm/llvm-project 4 | license: Apache 2.0 5 | license url: https://releases.llvm.org/14.0.0/LICENSE.TXT 6 | 7 | Default version: v14.0.6 8 | 9 | Building: 10 | LLVM uses cmake and builds without major surprises. The only twist is that we 11 | need host versions of llvm-tblgen and clang-tblgen which are not part of llvm 12 | distribution so we need to build them on our own. 13 | -------------------------------------------------------------------------------- /projects/llvm/build.mk: -------------------------------------------------------------------------------- 1 | # Copyright (c) Meta Platforms, Inc. and affiliates. 2 | 3 | LLVM_HOST_DEPS = cmake python 4 | $(eval $(call project-define,llvm)) 5 | 6 | ifeq ($(NDK_ARCH), arm64) 7 | LLVM_DEFAULT_TARGET = AArch64 8 | LLVM_HOST_TRIPLE = aarch64-none-linux-gnu 9 | else ifeq ($(NDK_ARCH), x86_64) 10 | LLVM_DEFAULT_TARGET = X86 11 | LLVM_HOST_TRIPLE = x86_64-none-linux-gnu 12 | else ifeq ($(NDK_ARCH), armv7) 13 | LLVM_DEFAULT_TARGET = ARM 14 | LLVM_HOST_TRIPLE = armv7a-none-linux-gnueabi 15 | else 16 | $(error unknown abi $(NDK_ARCH)) 17 | endif 18 | 19 | LLVM_EXTRA_CMAKE_FLAGS = -DLLVM_ENABLE_PROJECTS="clang;clang-tools-extra" 20 | LLVM_EXTRA_HOST_FLAGS = -DLLVM_TEMPORARILY_ALLOW_OLD_TOOLCHAIN=1 21 | 22 | ifeq ($(STATIC_LINKING),true) 23 | LLVM_EXTRA_CMAKE_FLAGS += -DLIBCLANG_BUILD_STATIC=ON 24 | endif 25 | 26 | ifeq ($(LLVM_BPF_ONLY),true) 27 | LLVM_EXTRA_CMAKE_FLAGS += -DLLVM_TARGETS_TO_BUILD=BPF 28 | else 29 | LLVM_EXTRA_CMAKE_FLAGS += -DLLVM_TARGETS_TO_BUILD="$(LLVM_DEFAULT_TARGET);BPF" 30 | endif 31 | 32 | $(LLVM_ANDROID): 33 | ifeq ($(BUILD_TYPE), Debug) 34 | cd $(LLVM_ANDROID_BUILD_DIR) && $(MAKE) install -j $(THREADS) 35 | else 36 | cd $(LLVM_ANDROID_BUILD_DIR) && $(MAKE) install/strip -j $(THREADS) 37 | endif 38 | cp $(LLVM_SRCS)/clang/LICENSE.TXT $(ANDROID_OUT_DIR)/licenses/clang 39 | cp $(LLVM_SRCS)/llvm/LICENSE.TXT $(ANDROID_OUT_DIR)/licenses/llvm 40 | touch $@ 41 | 42 | $(LLVM_ANDROID_BUILD_DIR): $(HOST_OUT_DIR)/bin/llvm-config 43 | $(LLVM_ANDROID_BUILD_DIR): $(HOST_OUT_DIR)/bin/llvm-tblgen 44 | $(LLVM_ANDROID_BUILD_DIR): $(HOST_OUT_DIR)/bin/clang-tblgen 45 | -mkdir $@ 46 | cd $@ && $(CMAKE) $(LLVM_SRCS)/llvm \ 47 | $(ANDROID_EXTRA_CMAKE_FLAGS) \ 48 | $(LLVM_EXTRA_CMAKE_FLAGS) \ 49 | -DLLVM_CONFIG_PATH=$(abspath $(HOST_OUT_DIR)/bin/llvm-config) \ 50 | -DLLVM_TABLEGEN=$(abspath $(HOST_OUT_DIR)/bin/llvm-tblgen) \ 51 | -DCLANG_TABLEGEN=$(abspath $(HOST_OUT_DIR)/bin/clang-tblgen) \ 52 | -DLLVM_HOST_TRIPLE=$(LLVM_HOST_TRIPLE) \ 53 | -DLLVM_ENABLE_RTTI=yes \ 54 | -DLLVM_INCLUDE_GO_TESTS=OFF \ 55 | -DLLVM_INCLUDE_TESTS=OFF \ 56 | -DLLVM_INCLUDE_UTILS=OFF \ 57 | -DCLANG_BUILD_TOOLS=ON \ 58 | -DLLVM_ENABLE_LIBXML2=OFF \ 59 | -DLLVM_TOOL_LLVM_RTDYLD_BUILD=OFF \ 60 | -DPython3_EXECUTABLE=$(abspath $(HOST_OUT_DIR)/bin/python3.10) 61 | 62 | # rules building host llvm-tblgen and clang-tblgen binaries necessary to 63 | # cross compile llvm and clang for Android 64 | $(HOST_OUT_DIR)/bin/llvm-config: $(LLVM_HOST_BUILD_DIR) | $(HOST_OUT_DIR) 65 | $(HOST_OUT_DIR)/bin/llvm-tblgen: $(LLVM_HOST_BUILD_DIR) | $(HOST_OUT_DIR) 66 | $(HOST_OUT_DIR)/bin/clang-tblgen: $(LLVM_HOST_BUILD_DIR) | $(HOST_OUT_DIR) 67 | $(HOST_OUT_DIR)/bin/llvm-config $(HOST_OUT_DIR)/bin/llvm-tblgen $(HOST_OUT_DIR)/bin/clang-tblgen: 68 | cd $(LLVM_HOST_BUILD_DIR) && $(MAKE) -j $(THREADS) $(notdir $@) 69 | cp $(LLVM_HOST_BUILD_DIR)/bin/$(notdir $@) $@ 70 | 71 | # generates llvm build files for host 72 | $(LLVM_HOST_BUILD_DIR): 73 | -mkdir $@ 74 | cd $@ && $(CMAKE) $(LLVM_SRCS)/llvm \ 75 | $(LLVM_EXTRA_CMAKE_FLAGS) \ 76 | $(LLVM_EXTRA_HOST_FLAGS) \ 77 | -DCMAKE_BUILD_TYPE=Release 78 | 79 | LLVM_BRANCH_OR_TAG = llvmorg-18.1.8 80 | LLVM_REPO = https://github.com/llvm/llvm-project 81 | projects/llvm/sources: 82 | git clone $(LLVM_REPO) $@ --depth=1 -b $(LLVM_BRANCH_OR_TAG) 83 | -------------------------------------------------------------------------------- /projects/obstack/README: -------------------------------------------------------------------------------- 1 | libobstack 2 | 3 | license: LGPLv3 4 | license url: https://www.gnu.org/licenses/lgpl-3.0.txt 5 | 6 | Libobstack is part of gnulib: http://savannah.gnu.org/projects/gnulib. 7 | In order to extract libobsack from gnulib you need to run gnulib-tool tool which 8 | is distributed together with gnulib sources. In order to extract libobstack to 9 | run gnulib-tool like this: 10 | cd 11 | ./gnulib-tool --create-testdir --lib="libobstack" --dir= obstack 12 | -------------------------------------------------------------------------------- /projects/obstack/build.mk: -------------------------------------------------------------------------------- 1 | # Copyright (c) Meta Platforms, Inc. and affiliates. 2 | 3 | $(eval $(call project-define,obstack)) 4 | 5 | $(OBSTACK_ANDROID): 6 | cd $(OBSTACK_ANDROID_BUILD_DIR) && make -j $(THREADS) 7 | cp $(OBSTACK_ANDROID_BUILD_DIR)/gllib/libobstack.a $(ANDROID_OUT_DIR)/lib/. 8 | cp $(OBSTACK_SRCS)/gllib/obstack.h $(ANDROID_OUT_DIR)/include/obstack.h 9 | $(call fetch-license,obstack,LGPL) 10 | touch $@ 11 | 12 | $(OBSTACK_ANDROID_BUILD_DIR): $(ANDROID_CONFIG_SITE) 13 | -mkdir $@ 14 | cd $@ && $(OBSTACK_SRCS)/configure $(ANDROID_EXTRA_CONFIGURE_FLAGS) 15 | 16 | projects/obstack/sources: $(call project-optional-sources-target,gnulib) 17 | cd $(call project-sources,gnulib) && ./gnulib-tool --create-testdir \ 18 | --lgpl --lib="libobstack" --dir=$(abspath $@) obstack 19 | -------------------------------------------------------------------------------- /projects/project.mk: -------------------------------------------------------------------------------- 1 | # Copyright (c) Meta Platforms, Inc. and affiliates. 2 | 3 | # Definitions of macros and functions facilitating creation of build.mk files 4 | # according to the convention used in ExtendedAndroidTools. 5 | # 6 | # Majority of cross-compiled projects use a build files generation tool like 7 | # autotools or cmake. To build them one needs to first generate a build 8 | # directory and then invoke make or other build system from that directory. 9 | # Some of the projects need to be compiled for Android, some for the host 10 | # platform and some for both. For those reasons build.mk files under projects/*/ 11 | # define the following build targets: 12 | # - host build directory 13 | # - host build rule 14 | # - android build directory 15 | # - android build rule 16 | # 17 | # By convention android and host build directories for project "myproject" are 18 | # "$(ANDROID_BUILD_DIR)/myproject" and "$(HOST_BUILD_DIR)/myproject" 19 | # respectively. Corresponding build rules are 20 | # "$(ANDROID_BUILD_DIR)/myproject.done" and "$(HOST_BUILD_DIR)/myproject.done". 21 | # Build rules write built artifacts to $(ANDROID_OUT_DIR) and $(HOST_OUT_DIR) 22 | # and artificial "*.done" files are used only to track successfull runs of the 23 | # compilation step. 24 | # 25 | # project-define macro defined in this file helps set up build targets by 26 | # computing their names and setting up dependencies between them. 27 | # $(eval $(call project-define,myproject)) 28 | # generates the following variables: 29 | # - MYPROJECT_ANDROID: android build target generating myproject.done file 30 | # after successful compilation of myproject for Android 31 | # - MYPROJECT_ANDROID_BUILD_DIR: build directory to be used by android build 32 | # rule 33 | # - MYPROJECT_HOST: host build target generating myproject.done file after 34 | # successful compilation of myproject for the host platform 35 | # - MYPROJECT_HOST_BUILD_DIR: build directory to be used by the host build 36 | # target 37 | # Additionally the call makes the android/host build rule dependent on the 38 | # corresponding build directory. 39 | # 40 | # Intended usage of project-define is shown below: 41 | # $(eval $(call project-define,myproject)) 42 | # 43 | # $(MYPROJECT_ANDROID): 44 | # cd $(MYPROJECT_ANDROID_BUILD_DIR) && make ... 45 | # touch $@ 46 | # 47 | # $(MYPROJECT_ANDROID_BUILD_DIR): 48 | # dir $@ 49 | # cd $@ && $(CMAKE) ... 50 | # cd &@ && ./configure ... 51 | # 52 | # $(MYPROJECT_HOST): 53 | # cd $(MYPROJECT_HOST_BUILD_DIR) && make ... 54 | # touch $@ 55 | # 56 | # $(MYPROJECT_HOST_BUILD_DIR): 57 | # mkdir $@ 58 | # cd $@ && $(CMAKE) ... 59 | # cd &@ && ./configure ... 60 | # 61 | # projects/myproject/sources: 62 | # git clone ... 63 | # 64 | # See project-define and projects/flex/build.mk to see the details and actual 65 | # example of usage. 66 | 67 | # Given a project name computes a variable prefix associated with 68 | # the project. For example: 69 | # $(call project-to-var,bpftrace)_SRC 70 | # resolves to 71 | # BPFTRACE_SRC 72 | project-to-var = $(shell echo $(1) | tr '[:lower:]' '[:upper:]') 73 | 74 | # Resolves to android build target associated with given project. 75 | # For example, when building for arm64: 76 | # $(call project-android-target,python) 77 | # resolves to 78 | # build/android/arm64/python.done 79 | project-android-target = $(ANDROID_BUILD_DIR)/$(1).done 80 | 81 | # Resolves to host build target associated with given project. 82 | # For example: 83 | # $(call project-host-target,flex) 84 | # resolces to 85 | # build/host/flex.done 86 | project-host-target = $(HOST_BUILD_DIR)/$(1).done 87 | 88 | # Resolves to android build directory associated with given project. 89 | # For example, when building for x86_64: 90 | # $(call project-android-build-dir,argp) 91 | # resolves to 92 | # build/android/x86_64/argp 93 | project-android-build-dir = $(ANDROID_BUILD_DIR)/$(1) 94 | 95 | # Resolves to host build directory associated with given project. 96 | # For example: 97 | # $(call project-host-build-dir,ffi) 98 | # resolves to 99 | # build/host/ffi 100 | project-host-build-dir = $(HOST_BUILD_DIR)/$(1) 101 | 102 | _project-android-deps-var = $(call project-to-var,$(1))_ANDROID_DEPS 103 | _project-host-deps-var = $(call project-to-var,$(1))_HOST_DEPS 104 | _project-sources-var = $(call project-to-var,$(1))_SOURCES 105 | 106 | # Resolves to a target generating project's sources, unless appropriate 107 | # PROJECT_SOURCES variable is defined. 108 | project-optional-sources-target = $(call if,\ 109 | $($(call _project-sources-var,$(1))),\ 110 | ,\ 111 | projects/$(1)/sources) 112 | 113 | # Resolves to absolute path to project's sources 114 | project-sources = $(call if,\ 115 | $($(call _project-sources-var,$(1))),\ 116 | $(abspath $($(call _project-sources-var,$(1)))),\ 117 | $(abspath projects/$(1)/sources)) 118 | 119 | # Macro defining project variables and setting up basic dependencies 120 | # between project rules. 121 | # 122 | # The following variables are defined: 123 | # - _ANDROID variable is assigned the name of project's android target 124 | # - _ANDROID_BUILD_DIR is assigned the name of project's android build 125 | # directory 126 | # - _HOST variable is assigned the name of project's host target 127 | # - _HOST_BUILD_DIR is assigned the name of project's host build 128 | # directory 129 | # - _SRCS is assigned the absolute path of project's sources 130 | # 131 | # The following build dependencies are defined: 132 | # - $(_ANDROID): $(_ANDROID_BUILD_DIR) 133 | # - $(_HOST): $(_HOST_BUILD_DIR) 134 | # 135 | # If no _SOURCES is defined then additional dependencies are declared 136 | # - $(_ANDROID_BUILD_DIR): projects//sources 137 | # - $(_HOST_BUILD_DIR): projects//sources 138 | # 139 | # If _ANDROID_DEPS is defined it is treated as list of android projects 140 | # added as build dependencies of $(_ANDROID_BUILD_DIR). 141 | # 142 | # If _HOST_DEPS is defined it is treated as list of host projects added 143 | # as build dependencies of $(_ANDROID_BUILD_DIR) and 144 | # $(_HOST_BUILD_DIR). 145 | # 146 | # Finally, for convenience a number of phony targets are defined: 147 | # - : $(_ANDROID) 148 | # - prepare-: $(_ANDROID_BUILD_DIR) 149 | # - -host: $(_HOST) 150 | # - prepare--host: $(_HOST_BUILD_DIR) 151 | define project-define = 152 | $(call project-to-var,$(1))_ANDROID := \ 153 | $(call project-android-target,$(1)) 154 | $(call project-to-var,$(1))_ANDROID_BUILD_DIR := \ 155 | $(call project-android-build-dir,$(1)) 156 | 157 | $(call project-to-var,$(1))_HOST := \ 158 | $(call project-host-target,$(1)) 159 | $(call project-to-var,$(1))_HOST_BUILD_DIR := \ 160 | $(call project-host-build-dir,$(1)) 161 | 162 | $(call project-to-var,$(1))_SRCS := $(call project-sources,$(1)) 163 | 164 | .PHONY: $(1) prepare-$(1) $(1)-host prepare-$(1)-host 165 | $(1): $(call project-android-target,$(1)) 166 | prepare-$(1): $(call project-android-build-dir,$(1)) ; @echo $$< 167 | $(1)-host: $(call project-host-target,$(1)) 168 | prepare-$(1)-host: $(call project-host-build-dir,$(1)) ; @echo $$< 169 | 170 | $(call project-android-target,$(1)): \ 171 | $(call project-android-build-dir,$(1)) \ 172 | | $(ANDROID_OUT_DIR) 173 | 174 | $(call project-android-build-dir,$(1)): \ 175 | $(call project-optional-sources-target,$(1)) \ 176 | $(foreach dep,\ 177 | $($(call _project-android-deps-var,$(1))),\ 178 | $(call project-android-target,$(dep))) \ 179 | $(foreach dep,\ 180 | $($(call _project-host-deps-var,$(1))),\ 181 | $(call project-host-target,$(dep))) \ 182 | | $(ANDROID_BUILD_DIR) 183 | 184 | $(call project-host-target,$(1)): \ 185 | $(call project-host-build-dir,$(1)) \ 186 | | $(HOST_OUT_DIR) 187 | 188 | $(call project-host-build-dir,$(1)): \ 189 | $(call project-optional-sources-target,$(1)) \ 190 | $(foreach dep,\ 191 | $($(call _project-host-deps-var,$(1))),\ 192 | $(call project-host-target,$(dep))) \ 193 | | $(HOST_BUILD_DIR) 194 | 195 | fetch-sources: projects/$(1)/sources 196 | remove-sources: remove-$(1)-sources 197 | 198 | .PHONY: remove-$(1)-sources 199 | remove-$(1)-sources: ; rm -rf projects/$(1)/sources 200 | endef 201 | 202 | # Macro defining rules installing a python library/tool via pip 203 | define pip-project = 204 | $(call project-to-var,$(1))_HOST := \ 205 | $(call project-host-target,$(1)) 206 | 207 | $(1)-host: $(call project-host-target,$(1)) 208 | 209 | $(call project-host-target,$(1)): \ 210 | $(call project-host-target,python) \ 211 | | $(HOST_BUILD_DIR) 212 | python3 -m pip install $(if $(2),$(2),$(1)) 213 | touch $$@ 214 | endef 215 | -------------------------------------------------------------------------------- /projects/pyre/README: -------------------------------------------------------------------------------- 1 | pyre-check 2 | Home page: https://pyre-check.org/ 3 | -------------------------------------------------------------------------------- /projects/pyre/build.mk: -------------------------------------------------------------------------------- 1 | # Copyright (c) Meta Platforms, Inc. and affiliates. 2 | 3 | $(eval $(call pip-project,pyre,pyre-check)) 4 | -------------------------------------------------------------------------------- /projects/python/README: -------------------------------------------------------------------------------- 1 | python 2 | Home page: https://www.python.org/ 3 | 4 | license: PSFv2 5 | license url: https://github.com/python/cpython/blob/main/LICENSE 6 | 7 | Default version: v3.10.6 8 | https://github.com/python/cpython/tree/v3.10.6 9 | 10 | Building: 11 | - configure scripts needs to be told explicitely what the build environment is 12 | (--build=x86_64) 13 | - due to lack of libs we need to disable ipv6 (--disable-ipv6) 14 | - PKG_CONFIG_LIBDIR needs to be exported so that it is visible in processes 15 | spawned by the configure script 16 | -------------------------------------------------------------------------------- /projects/python/build.mk: -------------------------------------------------------------------------------- 1 | # Copyright (c) Meta Platforms, Inc. and affiliates. 2 | 3 | PYTHON_ANDROID_DEPS = ffi 4 | PYTHON_HOST_DEPS = ffi 5 | $(eval $(call project-define,python)) 6 | 7 | PYTHON_ANDROID_EXTRA_CONFIG_OPTIONS = --build=x86_64 --disable-ipv6 --without-ensurepip --with-system-ffi 8 | PYTHON_ANDROID_EXTRA_CONFIG_OPTIONS += "EXTRA_CPPFLAGS=-I$(ANDROID_SYSROOT_INCLUDE_PATH)" 9 | PYTHON_ANDROID_EXTRA_CONFIG_OPTIONS += "EXTRA_LDFLAGS=-L$(ANDROID_SYSROOT_LIB_PATH)" 10 | PYTHON_ANDROID_EXTRA_CONFIG_OPTIONS += ac_cv_file__dev_ptmx=no 11 | PYTHON_ANDROID_EXTRA_CONFIG_OPTIONS += ac_cv_file__dev_ptc=no 12 | 13 | $(PYTHON_ANDROID): 14 | cd $(PYTHON_ANDROID_BUILD_DIR) && make install -j $(THREADS) 15 | cp $(PYTHON_SRCS)/LICENSE $(ANDROID_OUT_DIR)/licenses/python 16 | touch $@ 17 | 18 | $(PYTHON_HOST): $(HOST_OUT_DIR)/bin/python.xinstall 19 | cd $(PYTHON_HOST_BUILD_DIR) && make install -j $(THREADS) 20 | touch $@ 21 | 22 | $(HOST_OUT_DIR)/bin/python.xinstall: projects/python/python.xinstall.template 23 | $(HOST_OUT_DIR)/bin/python.xinstall: | $(HOST_OUT_DIR) 24 | cp $^ $@ 25 | sed -ibkp -e "s++$(abspath $(HOST_OUT_DIR))+g" $@ 26 | sed -ibkp -e "s++$(abspath $(ANDROID_OUT_DIR))+g" $@ 27 | chmod +x $@ 28 | 29 | $(PYTHON_ANDROID_BUILD_DIR): \ 30 | export PKG_CONFIG_LIBDIR=$(abspath $(ANDROID_OUT_DIR)/lib/pkgconfig) 31 | $(PYTHON_ANDROID_BUILD_DIR): $(ANDROID_CONFIG_SITE) 32 | $(PYTHON_ANDROID_BUILD_DIR): $(PYTHON_HOST) 33 | mkdir -p $@ 34 | cd $@ && $(PYTHON_SRCS)/configure \ 35 | $(ANDROID_EXTRA_CONFIGURE_FLAGS) \ 36 | $(PYTHON_ANDROID_EXTRA_CONFIG_OPTIONS) 37 | 38 | $(PYTHON_HOST_BUILD_DIR): \ 39 | export PKG_CONFIG_LIBDIR=$(abspath $(HOST_OUT_DIR)/lib/pkgconfig) 40 | $(PYTHON_HOST_BUILD_DIR): $(HOST_CONFIG_SITE) 41 | mkdir -p $@ 42 | cd $@ && $(PYTHON_SRCS)/configure \ 43 | $(HOST_EXTRA_CONFIGURE_FLAGS) \ 44 | --with-system-ffi 45 | 46 | PYTHON_BRANCH_OR_TAG = v3.10.6 47 | PYTHON_REPO = https://github.com/python/cpython.git 48 | projects/python/sources: 49 | git clone $(PYTHON_REPO) $@ --depth=1 -b $(PYTHON_BRANCH_OR_TAG) 50 | -------------------------------------------------------------------------------- /projects/python/python.xinstall.template: -------------------------------------------------------------------------------- 1 | #!/bin/python3.10 2 | # Copyright (c) Meta Platforms, Inc. and affiliates. 3 | 4 | import itertools 5 | import os 6 | import sys 7 | import typing 8 | 9 | 10 | INTERPRETER = "/bin/python3.10" 11 | PYTHONPATH = "/lib/python3.10/site-packages/" 12 | INSTALL_LAYOUT = "--install-layout" 13 | 14 | 15 | def filter_install_layout( 16 | args: typing.Sequence[str], 17 | ) -> typing.List[str]: 18 | return [ 19 | arg 20 | for (prev_arg, arg) in zip( 21 | itertools.chain([""], args), 22 | args, 23 | ) 24 | if arg != INSTALL_LAYOUT 25 | if prev_arg != INSTALL_LAYOUT 26 | ] 27 | 28 | 29 | def main(): 30 | match sys.argv: 31 | case [binary, "setup.py", "install", *rest]: 32 | args = [ 33 | INTERPRETER, 34 | "setup.py", 35 | "install", 36 | ] + filter_install_layout(rest) 37 | case _: 38 | args = [INTERPRETER] + sys.argv[1:] 39 | 40 | os.execve(INTERPRETER, args, {"PYTHONPATH": PYTHONPATH}) 41 | 42 | 43 | if __name__ == "__main__": 44 | main() 45 | -------------------------------------------------------------------------------- /projects/stdc++fs/README: -------------------------------------------------------------------------------- 1 | Toy implementation of stdc++fs providing bare minimum allowing other projects 2 | to compile. -------------------------------------------------------------------------------- /projects/stdc++fs/build.mk: -------------------------------------------------------------------------------- 1 | # Copyright (c) Meta Platforms, Inc. and affiliates. 2 | 3 | stdc++fs: $(ANDROID_BUILD_DIR)/stdc++fs.done 4 | 5 | $(ANDROID_BUILD_DIR)/stdc++fs.done: $(ANDROID_BUILD_DIR) $(ANDROID_BUILD_DIR)/stdc++fs 6 | $(ANDROID_TOOLCHAIN_PATH)/clang++ -target $(ANDROID_TRIPLE) -c -std=c++17 projects/stdc++fs/thunks.cpp -o $(ANDROID_BUILD_DIR)/thunks.o 7 | $(ANDROID_TOOLCHAIN_PATH)/llvm-ar rc $(ANDROID_OUT_DIR)/lib/libstdc++fs.a $(ANDROID_BUILD_DIR)/thunks.o 8 | touch $@ 9 | 10 | $(ANDROID_BUILD_DIR)/stdc++fs: 11 | mkdir -p $@ 12 | -------------------------------------------------------------------------------- /projects/stdc++fs/thunks.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) Meta Platforms, Inc. and affiliates. 2 | -------------------------------------------------------------------------------- /projects/xz/README: -------------------------------------------------------------------------------- 1 | XZ Utils 2 | XZ Utils is free general-purpose data compression software with a high compression ratio. 3 | 4 | license: public domain/LGPLv2.1 5 | license url: https://git.tukaani.org/?p=xz.git;a=blob;f=COPYING 6 | 7 | Default version: v5.2.5 8 | 9 | Building 10 | - XZ Utils builds without problems, however autogen runs into problems specific 11 | to VirtualBox's file system for shared directories, so it needs to be run in a 12 | temporary location. 13 | - We need to ensure built executables are position independent 14 | -------------------------------------------------------------------------------- /projects/xz/build.mk: -------------------------------------------------------------------------------- 1 | # Copyright (c) Meta Platforms, Inc. and affiliates. 2 | 3 | $(eval $(call project-define,xz)) 4 | 5 | $(XZ_ANDROID): 6 | cd $(XZ_ANDROID_BUILD_DIR) && make install -j $(THREADS) 7 | cp $(XZ_SRCS)/COPYING $(ANDROID_OUT_DIR)/licenses/xz 8 | touch $@ 9 | 10 | $(XZ_ANDROID_BUILD_DIR): $(ANDROID_CONFIG_SITE) 11 | mkdir -p $@ 12 | cd $@ && $(XZ_SRCS)/configure $(ANDROID_EXTRA_CONFIGURE_FLAGS) 13 | 14 | XZ_BRANCH_OR_TAG = v5.2.5 15 | XZ_REPO = https://git.tukaani.org/xz.git 16 | projects/xz/sources: 17 | ifeq ($(shell whoami), vagrant) 18 | git clone $(XZ_REPO) /tmp/xz_sources -b $(XZ_BRANCH_OR_TAG) 19 | cd /tmp/xz_sources && ./autogen.sh 20 | mv /tmp/xz_sources $@ 21 | else 22 | git clone $(XZ_REPO) $@ -b $(XZ_BRANCH_OR_TAG) 23 | cd $@ && ./autogen.sh 24 | endif 25 | -------------------------------------------------------------------------------- /projects/zlib/build.mk: -------------------------------------------------------------------------------- 1 | # Copyright (c) Meta Platforms, Inc. and affiliates. 2 | 3 | $(ANDROID_OUT_DIR)/lib/pkgconfig/zlib.pc: | $(ANDROID_OUT_DIR) 4 | echo "Name: zlib" >> $@ 5 | echo "Description:" >> $@ 6 | echo "Version: 1.2.11" >> $@ 7 | echo "Libs: -lz" >> $@ 8 | -------------------------------------------------------------------------------- /scripts/build-docker-image.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | # Copyright (c) Meta Platforms, Inc. and affiliates. 3 | 4 | pushd scripts 5 | docker build -t extended-android-tools -f ../docker/Dockerfile . 6 | popd 7 | -------------------------------------------------------------------------------- /scripts/centos-install-deps.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | # Copyright (c) Meta Platforms, Inc. and affiliates. 3 | 4 | echo "installing deps..." 5 | 6 | sudo dnf -y install \ 7 | autoconf \ 8 | automake \ 9 | bison \ 10 | curl \ 11 | flex \ 12 | gcc-c++ \ 13 | gettext \ 14 | gettext-devel \ 15 | git \ 16 | help2man \ 17 | libtool \ 18 | make \ 19 | openssl-devel \ 20 | pkg-config \ 21 | po4a \ 22 | texinfo \ 23 | unzip \ 24 | wget \ 25 | zlib \ 26 | zstd 27 | -------------------------------------------------------------------------------- /scripts/download-ndk.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | # Copyright (c) Meta Platforms, Inc. and affiliates. 3 | 4 | dest="${1:-$(pwd)}" 5 | TMP_NDK="/tmp/android-ndk-r27b-linux.zip" 6 | 7 | echo "downloading ndk to ${dest}..." 8 | 9 | curl -s -o "${TMP_NDK}" https://dl.google.com/android/repository/android-ndk-r27b-linux.zip 10 | unzip -q "${TMP_NDK}" -d "${dest}" 11 | rm /tmp/android-ndk-r27b-linux.zip 12 | 13 | echo "done" 14 | -------------------------------------------------------------------------------- /scripts/jammy-install-deps.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | # Copyright (c) Meta Platforms, Inc. and affiliates. 3 | 4 | echo "installing deps..." 5 | 6 | apt-get update 7 | apt-get install -y \ 8 | autoconf \ 9 | automake \ 10 | autopoint \ 11 | bison \ 12 | curl \ 13 | flex \ 14 | g++ \ 15 | gettext \ 16 | git \ 17 | help2man \ 18 | libssl-dev \ 19 | libtool \ 20 | make \ 21 | pkg-config \ 22 | po4a \ 23 | texinfo \ 24 | unzip \ 25 | wget \ 26 | zlib1g-dev \ 27 | zstd 28 | 29 | echo "done" 30 | -------------------------------------------------------------------------------- /scripts/run-docker-build-env.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | # Copyright (c) Meta Platforms, Inc. and affiliates. 3 | 4 | docker run -it --rm -v "$(pwd):/ExtendedAndroidTools" extended-android-tools 5 | -------------------------------------------------------------------------------- /sysroot/bpftools.mk: -------------------------------------------------------------------------------- 1 | # Copyright (c) Meta Platforms, Inc. and affiliates. 2 | 3 | ifeq ($(NDK_ARCH), arm64) 4 | TARGET_ARCH_ENV_VAR = arm64 5 | else ifeq ($(NDK_ARCH), x86_64) 6 | TARGET_ARCH_ENV_VAR = x86 7 | else ifeq ($(NDK_ARCH), armv7) 8 | TARGET_ARCH_ENV_VAR = arm 9 | else 10 | $(error unknown abi $(NDK_ARCH)) 11 | endif 12 | 13 | GEN_SETUP_SCRIPT = sed -e "s++$(TARGET_ARCH_ENV_VAR)+" sysroot/setup.sh > $@/setup.sh 14 | gen-wrapper = sed -e "s++$(1)+" sysroot/wrapper.sh.template > $@/$(1) && chmod +x $@/$(1) 15 | 16 | BPFTOOLS = $(ANDROID_SYSROOTS_OUT_DIR)/bpftools 17 | BPFTOOLS_TAR = bpftools-$(NDK_ARCH).tar.gz 18 | bpftools: $(BPFTOOLS_TAR) 19 | 20 | BPFTOOLS_MIN = $(ANDROID_SYSROOTS_OUT_DIR)/bpftools-min 21 | BPFTOOLS_MIN_TAR = bpftools-min-$(NDK_ARCH).tar.gz 22 | bpftools-min: $(BPFTOOLS_MIN_TAR) 23 | 24 | $(BPFTOOLS_TAR): $(BPFTOOLS) 25 | $(BPFTOOLS_MIN_TAR): $(BPFTOOLS_MIN) 26 | $(BPFTOOLS_TAR) $(BPFTOOLS_MIN_TAR): 27 | tar -zcf $@ $^ --owner=0 --group=0 \ 28 | --transform="s|^$(ANDROID_SYSROOTS_OUT_DIR)/||" 29 | 30 | $(BPFTOOLS) $(BPFTOOLS_MIN): $(ANDROID_SYSROOTS_OUT_DIR) 31 | $(BPFTOOLS) $(BPFTOOLS_MIN): sysroot/setup.sh 32 | $(BPFTOOLS) $(BPFTOOLS_MIN): sysroot/run.sh 33 | $(BPFTOOLS) $(BPFTOOLS_MIN): sysroot/wrapper.sh.template 34 | $(BPFTOOLS) $(BPFTOOLS_MIN): $(call project-android-target,bcc) 35 | $(BPFTOOLS) $(BPFTOOLS_MIN): $(call project-android-target,bpftrace) 36 | $(BPFTOOLS) $(BPFTOOLS_MIN): $(call project-android-target,xz) 37 | $(BPFTOOLS) $(BPFTOOLS_MIN): $(ANDROID_OUT_DIR)/lib/libc++_shared.so 38 | $(BPFTOOLS): $(call project-android-target,python) 39 | 40 | $(BPFTOOLS): 41 | mkdir -p $@/bin 42 | cp $(ANDROID_OUT_DIR)/bin/bpftrace $@/bin/ 43 | cp $(ANDROID_OUT_DIR)/bin/bpftrace-aotrt $@/bin/ || true 44 | cp -P $(ANDROID_OUT_DIR)/bin/python* $@/bin/ 45 | cp $(ANDROID_OUT_DIR)/bin/xzcat $@/bin/ 46 | 47 | mkdir -p $@/lib 48 | cp $(ANDROID_OUT_DIR)/lib/libbcc.so $@/lib/ 49 | cp $(ANDROID_OUT_DIR)/lib/libbcc_bpf.so $@/lib/ 50 | cp -a $(ANDROID_OUT_DIR)/lib/libbpf.so* $@/lib/ 51 | cp $(ANDROID_OUT_DIR)/lib/libclang.so $@/lib/ 52 | cp $(ANDROID_OUT_DIR)/lib/libc++_shared.so $@/lib/ 53 | cp -a $(ANDROID_OUT_DIR)/lib/libelf*.so* $@/lib/ 54 | cp $(ANDROID_OUT_DIR)/lib/libfl.so $@/lib/ 55 | cp $(ANDROID_OUT_DIR)/lib/liblzma.so $@/lib/ 56 | cp -a $(ANDROID_OUT_DIR)/lib/python3* $@/lib/ 57 | cp $(ANDROID_OUT_DIR)/lib/libffi.so $@/lib/ 58 | 59 | mkdir -p $@/share 60 | cp -a $(ANDROID_OUT_DIR)/share/bcc $@/share/ 61 | cp -a $(ANDROID_OUT_DIR)/share/bpftrace $@/share/ 62 | 63 | cp -r sysroot/run.sh $@/ 64 | $(GEN_SETUP_SCRIPT) 65 | $(call gen-wrapper,bpftrace) 66 | $(call gen-wrapper,bpftrace-aotrt) 67 | $(call gen-wrapper,python3.10) 68 | cp $@/python3.10 $@/python3 69 | $(call gen-wrapper,xzcat) 70 | 71 | cp -r $(ANDROID_OUT_DIR)/licenses $@/licenses 72 | 73 | $(BPFTOOLS_MIN): 74 | mkdir -p $@/bin 75 | cp $(ANDROID_OUT_DIR)/bin/bpftrace $@/bin/ 76 | cp $(ANDROID_OUT_DIR)/bin/xzcat $@/bin/ 77 | 78 | mkdir -p $@/lib 79 | cp $(ANDROID_OUT_DIR)/lib/libbcc_bpf.so $@/lib/ 80 | cp -a $(ANDROID_OUT_DIR)/lib/libbpf.so* $@/lib/ 81 | cp $(ANDROID_OUT_DIR)/lib/libclang.so $@/lib/ 82 | cp $(ANDROID_OUT_DIR)/lib/libc++_shared.so $@/lib/ 83 | cp -a $(ANDROID_OUT_DIR)/lib/libelf*.so* $@/lib/ 84 | cp $(ANDROID_OUT_DIR)/lib/liblzma.so $@/lib/ 85 | 86 | mkdir -p $@/share 87 | cp -a $(ANDROID_OUT_DIR)/share/bpftrace $@/share/ 88 | 89 | cp -r sysroot/run.sh $@/ 90 | $(GEN_SETUP_SCRIPT) 91 | $(call gen-wrapper,bpftrace) 92 | $(call gen-wrapper,xzcat) 93 | 94 | cp -r $(ANDROID_OUT_DIR)/licenses $@/licenses 95 | -------------------------------------------------------------------------------- /sysroot/run.sh: -------------------------------------------------------------------------------- 1 | #!/system/bin/env sh 2 | # Copyright (c) Meta Platforms, Inc. and affiliates. 3 | 4 | SYSROOT=$(realpath $(dirname $0)) 5 | source "${SYSROOT}/setup.sh" > /dev/null 6 | exec "$@" 7 | -------------------------------------------------------------------------------- /sysroot/setup.sh: -------------------------------------------------------------------------------- 1 | #!/system/bin/env sh 2 | # Copyright (c) Meta Platforms, Inc. and affiliates. 3 | 4 | SYSROOT=$(realpath $(dirname $0)) 5 | 6 | echo "setting up sysroot installed at $SYSROOT" 7 | 8 | # links below are required by bcc python library which opens those libs with 9 | # dlopen. Not the best solution but a solution 10 | if [[ ! -e $SYSROOT/lib/libbcc.so.0 ]]; then 11 | ln $SYSROOT/lib/libbcc.so -s $SYSROOT/lib/libbcc.so.0 12 | fi 13 | if [[ ! -e $SYSROOT/lib/libc.so.6 ]]; then 14 | ln /system/lib64/libc.so -s $SYSROOT/lib/libc.so.6 15 | fi 16 | if [[ ! -e $SYSROOT/lib/librt.so.1 ]]; then 17 | ln /system/lib64/libc.so -s $SYSROOT/lib/librt.so.1 18 | fi 19 | 20 | export PATH=$SYSROOT/bin:$PATH 21 | export LD_LIBRARY_PATH=$SYSROOT/lib:$SYSROOT/lib64:$LD_LIBRARY_PATH 22 | 23 | # define environment variables bpftrace and bcc need to determine arch and 24 | # kernel source path 25 | export ARCH="" 26 | 27 | # bpftrace caches symbols per executable name. All java processes fork from 28 | # zygote (and have the same executable name) which results in bad symbol names 29 | # reported if libraries are loaded in different order. 30 | export BPFTRACE_CACHE_USER_SYMBOLS=0 31 | 32 | # tell python where to find bcc in case we built the package on ubuntu/debian 33 | export PYTHONPATH=$SYSROOT/lib/python3.10/site-packages/bcc-0.27.0-py3.10.egg:$PYTHONPATH 34 | 35 | export TMPDIR=/data/local/tmp 36 | 37 | echo "done" 38 | -------------------------------------------------------------------------------- /sysroot/wrapper.sh.template: -------------------------------------------------------------------------------- 1 | #!/system/bin/env sh 2 | # Copyright (c) Meta Platforms, Inc. and affiliates. 3 | 4 | SYSROOT=$(realpath $(dirname $0)) 5 | exec "${SYSROOT}/run.sh" "" "$@" 6 | -------------------------------------------------------------------------------- /toolchains/BUCK: -------------------------------------------------------------------------------- 1 | # Copyright (c) Meta Platforms, Inc. and affiliates. 2 | 3 | load("@prelude//toolchains:python.bzl", "system_python_bootstrap_toolchain", "system_python_toolchain") 4 | load("@prelude//toolchains:cxx.bzl", "system_cxx_toolchain") 5 | load("@prelude//toolchains:genrule.bzl", "system_genrule_toolchain") 6 | 7 | system_cxx_toolchain( 8 | name = "cxx", 9 | visibility = ["PUBLIC"], 10 | ) 11 | 12 | system_python_toolchain( 13 | name = "python", 14 | visibility = ["PUBLIC"], 15 | ) 16 | 17 | system_genrule_toolchain( 18 | name = "genrule", 19 | visibility = ["PUBLIC"], 20 | ) 21 | 22 | system_python_bootstrap_toolchain( 23 | name = "python_bootstrap", 24 | visibility = ["PUBLIC"], 25 | ) 26 | -------------------------------------------------------------------------------- /toolchains/autotools.mk: -------------------------------------------------------------------------------- 1 | # Copyright (c) Meta Platforms, Inc. and affiliates. 2 | 3 | ifeq ($(NDK_ARCH), arm64) 4 | ANDROID_TRIPLE = aarch64-linux-android 5 | else ifeq ($(NDK_ARCH), x86_64) 6 | ANDROID_TRIPLE = x86_64-linux-android 7 | else ifeq ($(NDK_ARCH), armv7) 8 | ANDROID_TRIPLE = armv7a-linux-androideabi 9 | else 10 | $(error unknown abi $(NDK_ARCH)) 11 | endif 12 | 13 | ANDROID_CONFIG_SITE = $(ANDROID_OUT_DIR)/share/config.site 14 | ANDROID_EXTRA_CONFIGURE_FLAGS = --host=$(ANDROID_TRIPLE) --prefix=$(abspath $(ANDROID_OUT_DIR)) 15 | 16 | HOST_CONFIG_SITE = $(HOST_OUT_DIR)/share/config.site 17 | HOST_EXTRA_CONFIGURE_FLAGS = --prefix=$(abspath $(HOST_OUT_DIR)) 18 | 19 | $(ANDROID_CONFIG_SITE): | $(ANDROID_OUT_DIR) 20 | cp toolchains/config.site.template $@ 21 | @sed -ibkp -e "s++$(abspath $(ANDROID_TOOLCHAIN_PATH))+g" $@ 22 | @sed -ibkp -e "s++$(ANDROID_TRIPLE)+g" $@ 23 | @sed -ibkp -e "s++$(abspath $(ANDROID_OUT_DIR))+g" $@ 24 | @sed -ibkp -e "s++$(NDK_API)+g" $@ 25 | 26 | $(HOST_CONFIG_SITE): | $(HOST_OUT_DIR) 27 | cp toolchains/config.site.host.template $@ 28 | @sed -ibkp -e "s++$(abspath $(HOST_OUT_DIR))+g" $@ 29 | -------------------------------------------------------------------------------- /toolchains/cmake.mk: -------------------------------------------------------------------------------- 1 | # Copyright (c) Meta Platforms, Inc. and affiliates. 2 | 3 | CMAKE = $(abspath $(HOST_OUT_DIR)/bin/cmake) 4 | 5 | ifeq ($(NDK_ARCH), arm64) 6 | CMAKE_ABI = arm64-v8a 7 | else ifeq ($(NDK_ARCH), x86_64) 8 | CMAKE_ABI = x86_64 9 | else ifeq ($(NDK_ARCH), armv7) 10 | CMAKE_ABI = armeabi-v7a 11 | else 12 | $(error unknown abi $(NDK_ARCH)) 13 | endif 14 | 15 | ANDROID_CMAKE_TOOLCHAIN_FILE = $(NDK_PATH)/build/cmake/android.toolchain.cmake 16 | ANDROID_EXTRA_CMAKE_FLAGS = -DCMAKE_TOOLCHAIN_FILE=$(abspath $(ANDROID_CMAKE_TOOLCHAIN_FILE)) 17 | ANDROID_EXTRA_CMAKE_FLAGS += -DANDROID_USE_LEGACY_TOOLCHAIN_FILE=FALSE 18 | ANDROID_EXTRA_CMAKE_FLAGS += -DANDROID_ABI=$(CMAKE_ABI) 19 | ANDROID_EXTRA_CMAKE_FLAGS += -DANDROID_PLATFORM=android-$(NDK_API) 20 | ANDROID_EXTRA_CMAKE_FLAGS += -DANDROID_STL=c++_shared 21 | ANDROID_EXTRA_CMAKE_FLAGS += -DANDROID_ALLOW_UNDEFINED_SYMBOLS=TRUE 22 | ANDROID_EXTRA_CMAKE_FLAGS += -DCMAKE_BUILD_TYPE=$(BUILD_TYPE) 23 | 24 | # Install libs/binaries to out directory. Scan the out directory 25 | # in addition to the NDK sysroot when looking up libs and headers. 26 | ANDROID_EXTRA_CMAKE_FLAGS += -DCMAKE_INSTALL_PREFIX=$(abspath $(ANDROID_OUT_DIR)) 27 | ANDROID_EXTRA_CMAKE_FLAGS += -DCMAKE_PREFIX_PATH=$(abspath $(ANDROID_OUT_DIR)) 28 | ANDROID_EXTRA_CMAKE_FLAGS += -DCMAKE_FIND_ROOT_PATH=$(abspath $(ANDROID_OUT_DIR)) 29 | ANDROID_EXTRA_CMAKE_FLAGS += -DCMAKE_FIND_ROOT_PATH_MODE_LIBRARY=ONLY 30 | ANDROID_EXTRA_CMAKE_FLAGS += -DCMAKE_FIND_ROOT_PATH_MODE_INCLUDE=ONLY 31 | ANDROID_EXTRA_CMAKE_FLAGS += -DCMAKE_FIND_ROOT_PATH_MODE_PACKAGE=ONLY 32 | -------------------------------------------------------------------------------- /toolchains/config.site.host.template: -------------------------------------------------------------------------------- 1 | # Copyright (c) Meta Platforms, Inc. and affiliates. 2 | 3 | test -z "$PKG_CONFIG_LIBDIR" && PKG_CONFIG_LIBDIR=/lib/pkgconfig 4 | test -z "$CFLAGS" && CFLAGS="-fPIC -I/include $EXTRA_CFLAGS" 5 | test -z "$LDFLAGS" && LDFLAGS="-L/lib -L/lib64 $EXTRA_LDFLAGS -Wl,-rpath,/lib -Wl,-rpath,/lib64" 6 | -------------------------------------------------------------------------------- /toolchains/config.site.template: -------------------------------------------------------------------------------- 1 | # Copyright (c) Meta Platforms, Inc. and affiliates. 2 | 3 | test -z "$AR" && AR=/llvm-ar 4 | test -z "$AS" && AS=/-clang 5 | test -z "$CC" && CC=/-clang 6 | test -z "$CXX" && CXX=/-clang++ 7 | test -z "$LD" && LD=/ld 8 | test -z "$RANLIB" && RANLIB=/llvm-ranlib 9 | test -z "$READELF" && READELF=/llvm-readelf 10 | test -z "$STRIP" && STRIP=/llvm-strip 11 | 12 | test -z "$PKG_CONFIG_LIBDIR" && PKG_CONFIG_LIBDIR=/lib/pkgconfig 13 | test -z "$CPPFLAGS" && CPPFLAGS="-I/include $EXTRA_CPPFLAGS" 14 | test -z "$CFLAGS" && CFLAGS="-fPIC $EXTRA_CFLAGS" 15 | test -z "$LDFLAGS" && LDFLAGS="-L/lib -L/lib64 $EXTRA_LDFLAGS" 16 | -------------------------------------------------------------------------------- /toolchains/toolchains.mk: -------------------------------------------------------------------------------- 1 | # Copyright (c) Meta Platforms, Inc. and affiliates. 2 | 3 | NDK_API = 28 4 | NDK_PATH = /opt/ndk/android-ndk-r27b 5 | ANDROID_TOOLCHAIN_PATH = \ 6 | $(abspath $(NDK_PATH)/toolchains/llvm/prebuilt/linux-x86_64/bin) 7 | ANDROID_TOOLCHAIN_STRIP_PATH = $(ANDROID_TOOLCHAIN_PATH)/llvm-strip 8 | 9 | include toolchains/autotools.mk 10 | include toolchains/cmake.mk 11 | 12 | ifeq ($(NDK_ARCH), arm64) 13 | ANDROID_SYSROOT_LIB_SUBDIR = aarch64-linux-android 14 | else ifeq ($(NDK_ARCH), x86_64) 15 | ANDROID_SYSROOT_LIB_SUBDIR = x86_64-linux-android 16 | else ifeq ($(NDK_ARCH), armv7) 17 | ANDROID_SYSROOT_LIB_SUBDIR = arm-linux-androideabi 18 | else 19 | $(error unknown abi $(NDK_ARCH)) 20 | endif 21 | 22 | ANDROID_SYSROOT_PATH = \ 23 | $(abspath $(NDK_PATH)/toolchains/llvm/prebuilt/linux-x86_64/sysroot) 24 | ANDROID_SYSROOT_INCLUDE_PATH = \ 25 | $(ANDROID_SYSROOT_PATH)/usr/include/ 26 | ANDROID_SYSROOT_LIB_PATH = \ 27 | $(ANDROID_SYSROOT_PATH)/usr/lib/$(ANDROID_SYSROOT_LIB_SUBDIR)/$(NDK_API)/ 28 | 29 | $(ANDROID_OUT_DIR)/lib/libc++_shared.so: | $(ANDROID_OUT_DIR) 30 | cp $(ANDROID_SYSROOT_PATH)/usr/lib/$(ANDROID_SYSROOT_LIB_SUBDIR)/libc++_shared.so $@ 31 | --------------------------------------------------------------------------------