diff --git a/install_base.sh b/install_base.sh index 56945549d46f2c264b9bde6281ed2362c6e4f140..3659f6d93eceb92432b6c38e1daebc84f9d900e6 100755 --- a/install_base.sh +++ b/install_base.sh @@ -247,7 +247,10 @@ else fi usage() { - echo "Usage: $0 [--help] [--cleanup-android-sdk] [--install-android-tools] [--install-android-platform-tools] [--install-doc-extras] [--install-bisector-dbus] [--install-toolchains] [--install-vagrant] [--install-all]" + echo "Usage: $0 [--help] [--cleanup-android-sdk] [--install-android-tools] + [--install-android-platform-tools] [--install-doc-extras] + [--install-tests-extra] [--install-bisector-dbus] [--install-toolchains] + [--install-vagrant] [--install-all]" cat << EOF Install distribution packages and other bits that don't fit in the Python @@ -307,6 +310,14 @@ for arg in "${args[@]}"; do handled=1; ;;& + # Requirement for LISA's self tests (in tests/ folder), not the synthetic + # kernel tests. + "--install-tests-extras" | "--install-all") + apt_packages+=(clang) + pacman_packages+=(clang) + handled=1; + ;;& + "--install-toolchains" | "--install-all") apt_packages+=(build-essential gcc-arm-linux-gnueabi gcc-aarch64-linux-gnu) # arm-linux-gnueabihf-gcc can be installed from the AUR diff --git a/lisa/_assets/binaries/arm64/README.pahole b/lisa/_assets/binaries/arm64/README.pahole deleted file mode 100644 index d83386be1bac18dfcb0149743e9a7d3bbb4522a4..0000000000000000000000000000000000000000 --- a/lisa/_assets/binaries/arm64/README.pahole +++ /dev/null @@ -1,597 +0,0 @@ -Sources of pahole available at: -Git commit: 718a2f32255f1514406d080798c667956d76bc88 -Git repository: https://github.com/douglas-raillard-arm/pahole.git - - -Build host info: - -NAME="Alpine Linux" -ID=alpine -VERSION_ID=3.18.3 -PRETTY_NAME="Alpine Linux v3.18" -HOME_URL="https://alpinelinux.org/" -BUG_REPORT_URL="https://gitlab.alpinelinux.org/alpine/aports/-/issues" - - -Build recipe: - -export ARCH=arm64 -export LISA_ARCH_ASSETS=/lisa/_assets/binaries/arm64 -export LISA_HOME='' -#! /bin/bash - -ALPINE_VERSION=v3.18 -ALPINE_BUILD_DEPENDENCIES=(bash gcc git make cmake musl-dev zlib-static bzip2-static libelf-static libbpf-dev musl-obstack-dev argp-standalone linux-headers xz-static zstd-static) -BROKEN_CROSS_COMPILATION=1 - - -# See $LISA_HOME/tools/recipes/pahole.manifest.yaml for instructions on how to build the "lisa" branch - -download() { - #git clone https://git.kernel.org/pub/scm/devel/pahole/pahole.git - git clone https://github.com/douglas-raillard-arm/pahole.git - git -C pahole checkout lisa -} - -build() { - cd pahole - - mkdir build - ( - cd build - cmake \ - -DSTATIC_LINK=ON \ - -DCMAKE_BUILD_TYPE=Release \ - .. \ - && - make pahole - ) && - strip build/pahole -} - -install() { - cp -v pahole/build/pahole "$LISA_ARCH_ASSETS/pahole" - - source "$LISA_HOME/tools/recipes/utils.sh" - install_readme pahole pahole COPYING -} - - -The sources were distributed under the following licence (content of pahole/COPYING): - - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Lesser General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. - - -The sources were compiled with musl-libc (content of COPYRIGHT): - -musl as a whole is licensed under the following standard MIT license: - ----------------------------------------------------------------------- -Copyright © 2005-2020 Rich Felker, et al. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ----------------------------------------------------------------------- - -Authors/contributors include: - -A. Wilcox -Ada Worcester -Alex Dowad -Alex Suykov -Alexander Monakov -Andre McCurdy -Andrew Kelley -Anthony G. Basile -Aric Belsito -Arvid Picciani -Bartosz Brachaczek -Benjamin Peterson -Bobby Bingham -Boris Brezillon -Brent Cook -Chris Spiegel -Clément Vasseur -Daniel Micay -Daniel Sabogal -Daurnimator -David Carlier -David Edelsohn -Denys Vlasenko -Dmitry Ivanov -Dmitry V. Levin -Drew DeVault -Emil Renner Berthing -Fangrui Song -Felix Fietkau -Felix Janda -Gianluca Anzolin -Hauke Mehrtens -He X -Hiltjo Posthuma -Isaac Dunham -Jaydeep Patil -Jens Gustedt -Jeremy Huntwork -Jo-Philipp Wich -Joakim Sindholt -John Spencer -Julien Ramseier -Justin Cormack -Kaarle Ritvanen -Khem Raj -Kylie McClain -Leah Neukirchen -Luca Barbato -Luka Perkov -M Farkas-Dyck (Strake) -Mahesh Bodapati -Markus Wichmann -Masanori Ogino -Michael Clark -Michael Forney -Mikhail Kremnyov -Natanael Copa -Nicholas J. Kain -orc -Pascal Cuoq -Patrick Oppenlander -Petr Hosek -Petr Skocik -Pierre Carrier -Reini Urban -Rich Felker -Richard Pennington -Ryan Fairfax -Samuel Holland -Segev Finer -Shiz -sin -Solar Designer -Stefan Kristiansson -Stefan O'Rear -Szabolcs Nagy -Timo Teräs -Trutz Behn -Valentin Ochs -Will Dietz -William Haddon -William Pitcock - -Portions of this software are derived from third-party works licensed -under terms compatible with the above MIT license: - -The TRE regular expression implementation (src/regex/reg* and -src/regex/tre*) is Copyright © 2001-2008 Ville Laurikari and licensed -under a 2-clause BSD license (license text in the source files). The -included version has been heavily modified by Rich Felker in 2012, in -the interests of size, simplicity, and namespace cleanliness. - -Much of the math library code (src/math/* and src/complex/*) is -Copyright © 1993,2004 Sun Microsystems or -Copyright © 2003-2011 David Schultz or -Copyright © 2003-2009 Steven G. Kargl or -Copyright © 2003-2009 Bruce D. Evans or -Copyright © 2008 Stephen L. Moshier or -Copyright © 2017-2018 Arm Limited -and labelled as such in comments in the individual source files. All -have been licensed under extremely permissive terms. - -The ARM memcpy code (src/string/arm/memcpy.S) is Copyright © 2008 -The Android Open Source Project and is licensed under a two-clause BSD -license. It was taken from Bionic libc, used on Android. - -The AArch64 memcpy and memset code (src/string/aarch64/*) are -Copyright © 1999-2019, Arm Limited. - -The implementation of DES for crypt (src/crypt/crypt_des.c) is -Copyright © 1994 David Burren. It is licensed under a BSD license. - -The implementation of blowfish crypt (src/crypt/crypt_blowfish.c) was -originally written by Solar Designer and placed into the public -domain. The code also comes with a fallback permissive license for use -in jurisdictions that may not recognize the public domain. - -The smoothsort implementation (src/stdlib/qsort.c) is Copyright © 2011 -Valentin Ochs and is licensed under an MIT-style license. - -The x86_64 port was written by Nicholas J. Kain and is licensed under -the standard MIT terms. - -The mips and microblaze ports were originally written by Richard -Pennington for use in the ellcc project. The original code was adapted -by Rich Felker for build system and code conventions during upstream -integration. It is licensed under the standard MIT terms. - -The mips64 port was contributed by Imagination Technologies and is -licensed under the standard MIT terms. - -The powerpc port was also originally written by Richard Pennington, -and later supplemented and integrated by John Spencer. It is licensed -under the standard MIT terms. - -All other files which have no copyright comments are original works -produced specifically for use as part of this library, written either -by Rich Felker, the main author of the library, or by one or more -contibutors listed above. Details on authorship of individual files -can be found in the git version control history of the project. The -omission of copyright and license comments in each file is in the -interest of source tree size. - -In addition, permission is hereby granted for all public header files -(include/* and arch/*/bits/*) and crt files intended to be linked into -applications (crt/*, ldso/dlstart.c, and arch/*/crt_arch.h) to omit -the copyright notice and permission notice otherwise required by the -license, and to use these files without any requirement of -attribution. These files include substantial contributions from: - -Bobby Bingham -John Spencer -Nicholas J. Kain -Rich Felker -Richard Pennington -Stefan Kristiansson -Szabolcs Nagy - -all of whom have explicitly granted such permission. - -This file previously contained text expressing a belief that most of -the files covered by the above exception were sufficiently trivial not -to be subject to copyright, resulting in confusion over whether it -negated the permissions granted in the license. In the spirit of -permissive licensing, and of not having licensing issues being an -obstacle to adoption, that text has been removed. diff --git a/lisa/_assets/binaries/arm64/pahole b/lisa/_assets/binaries/arm64/pahole deleted file mode 100755 index 38f9b5fb3c884714bd896470173bb43cea5a05ce..0000000000000000000000000000000000000000 Binary files a/lisa/_assets/binaries/arm64/pahole and /dev/null differ diff --git a/lisa/_assets/binaries/armeabi/README.pahole b/lisa/_assets/binaries/armeabi/README.pahole deleted file mode 100644 index 7ef4a0fb2d1771208f2c42be1e2adb9bd6d43fe9..0000000000000000000000000000000000000000 --- a/lisa/_assets/binaries/armeabi/README.pahole +++ /dev/null @@ -1,597 +0,0 @@ -Sources of pahole available at: -Git commit: 718a2f32255f1514406d080798c667956d76bc88 -Git repository: https://github.com/douglas-raillard-arm/pahole.git - - -Build host info: - -NAME="Alpine Linux" -ID=alpine -VERSION_ID=3.18.3 -PRETTY_NAME="Alpine Linux v3.18" -HOME_URL="https://alpinelinux.org/" -BUG_REPORT_URL="https://gitlab.alpinelinux.org/alpine/aports/-/issues" - - -Build recipe: - -export ARCH=armeabi -export LISA_ARCH_ASSETS=/lisa/_assets/binaries/armeabi -export LISA_HOME='' -#! /bin/bash - -ALPINE_VERSION=v3.18 -ALPINE_BUILD_DEPENDENCIES=(bash gcc git make cmake musl-dev zlib-static bzip2-static libelf-static libbpf-dev musl-obstack-dev argp-standalone linux-headers xz-static zstd-static) -BROKEN_CROSS_COMPILATION=1 - - -# See $LISA_HOME/tools/recipes/pahole.manifest.yaml for instructions on how to build the "lisa" branch - -download() { - #git clone https://git.kernel.org/pub/scm/devel/pahole/pahole.git - git clone https://github.com/douglas-raillard-arm/pahole.git - git -C pahole checkout lisa -} - -build() { - cd pahole - - mkdir build - ( - cd build - cmake \ - -DSTATIC_LINK=ON \ - -DCMAKE_BUILD_TYPE=Release \ - .. \ - && - make pahole - ) && - strip build/pahole -} - -install() { - cp -v pahole/build/pahole "$LISA_ARCH_ASSETS/pahole" - - source "$LISA_HOME/tools/recipes/utils.sh" - install_readme pahole pahole COPYING -} - - -The sources were distributed under the following licence (content of pahole/COPYING): - - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Lesser General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. - - -The sources were compiled with musl-libc (content of COPYRIGHT): - -musl as a whole is licensed under the following standard MIT license: - ----------------------------------------------------------------------- -Copyright © 2005-2020 Rich Felker, et al. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ----------------------------------------------------------------------- - -Authors/contributors include: - -A. Wilcox -Ada Worcester -Alex Dowad -Alex Suykov -Alexander Monakov -Andre McCurdy -Andrew Kelley -Anthony G. Basile -Aric Belsito -Arvid Picciani -Bartosz Brachaczek -Benjamin Peterson -Bobby Bingham -Boris Brezillon -Brent Cook -Chris Spiegel -Clément Vasseur -Daniel Micay -Daniel Sabogal -Daurnimator -David Carlier -David Edelsohn -Denys Vlasenko -Dmitry Ivanov -Dmitry V. Levin -Drew DeVault -Emil Renner Berthing -Fangrui Song -Felix Fietkau -Felix Janda -Gianluca Anzolin -Hauke Mehrtens -He X -Hiltjo Posthuma -Isaac Dunham -Jaydeep Patil -Jens Gustedt -Jeremy Huntwork -Jo-Philipp Wich -Joakim Sindholt -John Spencer -Julien Ramseier -Justin Cormack -Kaarle Ritvanen -Khem Raj -Kylie McClain -Leah Neukirchen -Luca Barbato -Luka Perkov -M Farkas-Dyck (Strake) -Mahesh Bodapati -Markus Wichmann -Masanori Ogino -Michael Clark -Michael Forney -Mikhail Kremnyov -Natanael Copa -Nicholas J. Kain -orc -Pascal Cuoq -Patrick Oppenlander -Petr Hosek -Petr Skocik -Pierre Carrier -Reini Urban -Rich Felker -Richard Pennington -Ryan Fairfax -Samuel Holland -Segev Finer -Shiz -sin -Solar Designer -Stefan Kristiansson -Stefan O'Rear -Szabolcs Nagy -Timo Teräs -Trutz Behn -Valentin Ochs -Will Dietz -William Haddon -William Pitcock - -Portions of this software are derived from third-party works licensed -under terms compatible with the above MIT license: - -The TRE regular expression implementation (src/regex/reg* and -src/regex/tre*) is Copyright © 2001-2008 Ville Laurikari and licensed -under a 2-clause BSD license (license text in the source files). The -included version has been heavily modified by Rich Felker in 2012, in -the interests of size, simplicity, and namespace cleanliness. - -Much of the math library code (src/math/* and src/complex/*) is -Copyright © 1993,2004 Sun Microsystems or -Copyright © 2003-2011 David Schultz or -Copyright © 2003-2009 Steven G. Kargl or -Copyright © 2003-2009 Bruce D. Evans or -Copyright © 2008 Stephen L. Moshier or -Copyright © 2017-2018 Arm Limited -and labelled as such in comments in the individual source files. All -have been licensed under extremely permissive terms. - -The ARM memcpy code (src/string/arm/memcpy.S) is Copyright © 2008 -The Android Open Source Project and is licensed under a two-clause BSD -license. It was taken from Bionic libc, used on Android. - -The AArch64 memcpy and memset code (src/string/aarch64/*) are -Copyright © 1999-2019, Arm Limited. - -The implementation of DES for crypt (src/crypt/crypt_des.c) is -Copyright © 1994 David Burren. It is licensed under a BSD license. - -The implementation of blowfish crypt (src/crypt/crypt_blowfish.c) was -originally written by Solar Designer and placed into the public -domain. The code also comes with a fallback permissive license for use -in jurisdictions that may not recognize the public domain. - -The smoothsort implementation (src/stdlib/qsort.c) is Copyright © 2011 -Valentin Ochs and is licensed under an MIT-style license. - -The x86_64 port was written by Nicholas J. Kain and is licensed under -the standard MIT terms. - -The mips and microblaze ports were originally written by Richard -Pennington for use in the ellcc project. The original code was adapted -by Rich Felker for build system and code conventions during upstream -integration. It is licensed under the standard MIT terms. - -The mips64 port was contributed by Imagination Technologies and is -licensed under the standard MIT terms. - -The powerpc port was also originally written by Richard Pennington, -and later supplemented and integrated by John Spencer. It is licensed -under the standard MIT terms. - -All other files which have no copyright comments are original works -produced specifically for use as part of this library, written either -by Rich Felker, the main author of the library, or by one or more -contibutors listed above. Details on authorship of individual files -can be found in the git version control history of the project. The -omission of copyright and license comments in each file is in the -interest of source tree size. - -In addition, permission is hereby granted for all public header files -(include/* and arch/*/bits/*) and crt files intended to be linked into -applications (crt/*, ldso/dlstart.c, and arch/*/crt_arch.h) to omit -the copyright notice and permission notice otherwise required by the -license, and to use these files without any requirement of -attribution. These files include substantial contributions from: - -Bobby Bingham -John Spencer -Nicholas J. Kain -Rich Felker -Richard Pennington -Stefan Kristiansson -Szabolcs Nagy - -all of whom have explicitly granted such permission. - -This file previously contained text expressing a belief that most of -the files covered by the above exception were sufficiently trivial not -to be subject to copyright, resulting in confusion over whether it -negated the permissions granted in the license. In the spirit of -permissive licensing, and of not having licensing issues being an -obstacle to adoption, that text has been removed. diff --git a/lisa/_assets/binaries/armeabi/pahole b/lisa/_assets/binaries/armeabi/pahole deleted file mode 100755 index d7d71daf1c98a6b16a64ec3574159c063ce839ad..0000000000000000000000000000000000000000 Binary files a/lisa/_assets/binaries/armeabi/pahole and /dev/null differ diff --git a/lisa/_assets/binaries/x86_64/README.pahole b/lisa/_assets/binaries/x86_64/README.pahole deleted file mode 100644 index ce25a29104b1124397df6d86b2c642465b6d6c7c..0000000000000000000000000000000000000000 --- a/lisa/_assets/binaries/x86_64/README.pahole +++ /dev/null @@ -1,597 +0,0 @@ -Sources of pahole available at: -Git commit: 718a2f32255f1514406d080798c667956d76bc88 -Git repository: https://github.com/douglas-raillard-arm/pahole.git - - -Build host info: - -NAME="Alpine Linux" -ID=alpine -VERSION_ID=3.18.3 -PRETTY_NAME="Alpine Linux v3.18" -HOME_URL="https://alpinelinux.org/" -BUG_REPORT_URL="https://gitlab.alpinelinux.org/alpine/aports/-/issues" - - -Build recipe: - -export ARCH=x86_64 -export LISA_ARCH_ASSETS=/lisa/_assets/binaries/x86_64 -export LISA_HOME='' -#! /bin/bash - -ALPINE_VERSION=v3.18 -ALPINE_BUILD_DEPENDENCIES=(bash gcc git make cmake musl-dev zlib-static bzip2-static libelf-static libbpf-dev musl-obstack-dev argp-standalone linux-headers xz-static zstd-static) -BROKEN_CROSS_COMPILATION=1 - - -# See $LISA_HOME/tools/recipes/pahole.manifest.yaml for instructions on how to build the "lisa" branch - -download() { - #git clone https://git.kernel.org/pub/scm/devel/pahole/pahole.git - git clone https://github.com/douglas-raillard-arm/pahole.git - git -C pahole checkout lisa -} - -build() { - cd pahole - - mkdir build - ( - cd build - cmake \ - -DSTATIC_LINK=ON \ - -DCMAKE_BUILD_TYPE=Release \ - .. \ - && - make pahole - ) && - strip build/pahole -} - -install() { - cp -v pahole/build/pahole "$LISA_ARCH_ASSETS/pahole" - - source "$LISA_HOME/tools/recipes/utils.sh" - install_readme pahole pahole COPYING -} - - -The sources were distributed under the following licence (content of pahole/COPYING): - - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Lesser General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. - - -The sources were compiled with musl-libc (content of COPYRIGHT): - -musl as a whole is licensed under the following standard MIT license: - ----------------------------------------------------------------------- -Copyright © 2005-2020 Rich Felker, et al. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ----------------------------------------------------------------------- - -Authors/contributors include: - -A. Wilcox -Ada Worcester -Alex Dowad -Alex Suykov -Alexander Monakov -Andre McCurdy -Andrew Kelley -Anthony G. Basile -Aric Belsito -Arvid Picciani -Bartosz Brachaczek -Benjamin Peterson -Bobby Bingham -Boris Brezillon -Brent Cook -Chris Spiegel -Clément Vasseur -Daniel Micay -Daniel Sabogal -Daurnimator -David Carlier -David Edelsohn -Denys Vlasenko -Dmitry Ivanov -Dmitry V. Levin -Drew DeVault -Emil Renner Berthing -Fangrui Song -Felix Fietkau -Felix Janda -Gianluca Anzolin -Hauke Mehrtens -He X -Hiltjo Posthuma -Isaac Dunham -Jaydeep Patil -Jens Gustedt -Jeremy Huntwork -Jo-Philipp Wich -Joakim Sindholt -John Spencer -Julien Ramseier -Justin Cormack -Kaarle Ritvanen -Khem Raj -Kylie McClain -Leah Neukirchen -Luca Barbato -Luka Perkov -M Farkas-Dyck (Strake) -Mahesh Bodapati -Markus Wichmann -Masanori Ogino -Michael Clark -Michael Forney -Mikhail Kremnyov -Natanael Copa -Nicholas J. Kain -orc -Pascal Cuoq -Patrick Oppenlander -Petr Hosek -Petr Skocik -Pierre Carrier -Reini Urban -Rich Felker -Richard Pennington -Ryan Fairfax -Samuel Holland -Segev Finer -Shiz -sin -Solar Designer -Stefan Kristiansson -Stefan O'Rear -Szabolcs Nagy -Timo Teräs -Trutz Behn -Valentin Ochs -Will Dietz -William Haddon -William Pitcock - -Portions of this software are derived from third-party works licensed -under terms compatible with the above MIT license: - -The TRE regular expression implementation (src/regex/reg* and -src/regex/tre*) is Copyright © 2001-2008 Ville Laurikari and licensed -under a 2-clause BSD license (license text in the source files). The -included version has been heavily modified by Rich Felker in 2012, in -the interests of size, simplicity, and namespace cleanliness. - -Much of the math library code (src/math/* and src/complex/*) is -Copyright © 1993,2004 Sun Microsystems or -Copyright © 2003-2011 David Schultz or -Copyright © 2003-2009 Steven G. Kargl or -Copyright © 2003-2009 Bruce D. Evans or -Copyright © 2008 Stephen L. Moshier or -Copyright © 2017-2018 Arm Limited -and labelled as such in comments in the individual source files. All -have been licensed under extremely permissive terms. - -The ARM memcpy code (src/string/arm/memcpy.S) is Copyright © 2008 -The Android Open Source Project and is licensed under a two-clause BSD -license. It was taken from Bionic libc, used on Android. - -The AArch64 memcpy and memset code (src/string/aarch64/*) are -Copyright © 1999-2019, Arm Limited. - -The implementation of DES for crypt (src/crypt/crypt_des.c) is -Copyright © 1994 David Burren. It is licensed under a BSD license. - -The implementation of blowfish crypt (src/crypt/crypt_blowfish.c) was -originally written by Solar Designer and placed into the public -domain. The code also comes with a fallback permissive license for use -in jurisdictions that may not recognize the public domain. - -The smoothsort implementation (src/stdlib/qsort.c) is Copyright © 2011 -Valentin Ochs and is licensed under an MIT-style license. - -The x86_64 port was written by Nicholas J. Kain and is licensed under -the standard MIT terms. - -The mips and microblaze ports were originally written by Richard -Pennington for use in the ellcc project. The original code was adapted -by Rich Felker for build system and code conventions during upstream -integration. It is licensed under the standard MIT terms. - -The mips64 port was contributed by Imagination Technologies and is -licensed under the standard MIT terms. - -The powerpc port was also originally written by Richard Pennington, -and later supplemented and integrated by John Spencer. It is licensed -under the standard MIT terms. - -All other files which have no copyright comments are original works -produced specifically for use as part of this library, written either -by Rich Felker, the main author of the library, or by one or more -contibutors listed above. Details on authorship of individual files -can be found in the git version control history of the project. The -omission of copyright and license comments in each file is in the -interest of source tree size. - -In addition, permission is hereby granted for all public header files -(include/* and arch/*/bits/*) and crt files intended to be linked into -applications (crt/*, ldso/dlstart.c, and arch/*/crt_arch.h) to omit -the copyright notice and permission notice otherwise required by the -license, and to use these files without any requirement of -attribution. These files include substantial contributions from: - -Bobby Bingham -John Spencer -Nicholas J. Kain -Rich Felker -Richard Pennington -Stefan Kristiansson -Szabolcs Nagy - -all of whom have explicitly granted such permission. - -This file previously contained text expressing a belief that most of -the files covered by the above exception were sufficiently trivial not -to be subject to copyright, resulting in confusion over whether it -negated the permissions granted in the license. In the spirit of -permissive licensing, and of not having licensing issues being an -obstacle to adoption, that text has been removed. diff --git a/lisa/_assets/binaries/x86_64/pahole b/lisa/_assets/binaries/x86_64/pahole deleted file mode 100755 index ca5cadba1c27ecf702b2bf024cfe76e0b0389a62..0000000000000000000000000000000000000000 Binary files a/lisa/_assets/binaries/x86_64/pahole and /dev/null differ diff --git a/lisa/_assets/kmodules/lisa/Makefile b/lisa/_assets/kmodules/lisa/Makefile index f1a1937bcfb42941a4e699f2a91bd4464455e30f..9a2c4610fddb549888aad76ed98d5060b56af8b8 100644 --- a/lisa/_assets/kmodules/lisa/Makefile +++ b/lisa/_assets/kmodules/lisa/Makefile @@ -99,7 +99,6 @@ ldflags-y += -T $(SYMBOLS_LDS) endif INTROSPECTION_DATA_H := $(GENERATED)/introspection_data.h -PRIVATE_TYPES_TXT := $(MODULE_SRC)/private_types.txt # Can be either a kernel image built with DWARF debug info, or the BTF blob # found at /sys/kernel/btf/vmlinux @@ -107,6 +106,8 @@ _BTF_VMLINUX := $(MODULE_SRC)/vmlinux _REAL_VMLINUX := $(KERNEL_SRC)/vmlinux _SYNTHETIC_VMLINUX := $(MODULE_OBJ)/introspection_data.o +BTF_BLOB := $(GENERATED)/btf.blob + ifeq ("$(wildcard $(_BTF_VMLINUX))","") ifeq ($(IN_TREE_BUILD),1) VMLINUX := $(_SYNTHETIC_VMLINUX) @@ -117,18 +118,28 @@ else VMLINUX := $(_BTF_VMLINUX) endif -UNUSED_KERNEL_PRIVATE_TYPES_PREFIX := KERNEL_PRIVATE_ - -VENV := $(MODULE_OBJ)/venv -$(VENV): - python3 -m venv $(VENV) - . $(VENV)/bin/activate && python3 -m pip install --upgrade pip setuptools wheel && python3 -m pip install -r $(MODULE_SRC)/requirements.txt - -$(INTROSPECTION_DATA_H): $(GENERATED) $(KALLSYMS) $(PRIVATE_TYPES_TXT) $(VMLINUX) $(VENV) - sh "$(MODULE_SRC)/make_introspection_header.sh" "$@" "$(MODULE_SRC)" "$(MODULE_OBJ)" "$(VENV)" "$(CC)" "$(PRIVATE_TYPES_TXT)" "$(VMLINUX)" "$(UNUSED_KERNEL_PRIVATE_TYPES_PREFIX)" "$(KALLSYMS)" - -$(SYMBOLS_LDS): $(GENERATED) $(KALLSYMS) $(VENV) - . $(VENV)/bin/activate && python3 $(MODULE_SRC)/introspect_header.py --kallsyms $(KALLSYMS) --symbols-lds >> $@ +# Ensure we have a BTF blob regardless of vmlinux format (ELF with .BTF +# section, ELF with DWARF debug info and no BTF, BTF blob). +$(BTF_BLOB): $(GENERATED) $(VMLINUX) + # If file is ELF, objcopy will succeed (and possibly create an empty + # file if the section does not exist). + # Otherwise, we assume it is a BTF blob and copy it over to the output. + # Extracting this way avoids the costly pahole --btf_encode step that + # would convert DWARF to BTF even if .BTF section is already present. + # It also avoids calling pahole in the happy path, since + # --btf_encode_detached option might not be available on older + # versions. + $(OBJCOPY) -O binary --only-section=.BTF "$(VMLINUX)" "$@" || cp "$(VMLINUX)" "$@" + # If the file was empty, the ELF file was missing BTF info so we generate it. + [ -s "$@" ] || pahole --btf_gen_all --btf_encode_detached "$@" "$(VMLINUX)" + +$(INTROSPECTION_DATA_H): $(GENERATED) $(KALLSYMS) $(BTF_BLOB) + printf '#pragma once\n' > "$@" + # Create type introspection macros + python3 "$(MODULE_SRC)/introspect_header.py" --introspect --btf "$(BTF_BLOB)" --internal-type-prefix KERNEL_PRIVATE_ --kallsyms "$(KALLSYMS)" --conf "$(MODULE_SRC)/introspection.json" >> "$@" + +$(SYMBOLS_LDS): $(GENERATED) $(KALLSYMS) + python3 $(MODULE_SRC)/introspect_header.py --kallsyms $(KALLSYMS) --symbols-lds >> "$@" # Some kernels require the use of MODULE_IMPORT_NS() before using symbols that are part of the given namespace: # https://docs.kernel.org/core-api/symbol-namespaces.html diff --git a/lisa/_assets/kmodules/lisa/introspect_header.py b/lisa/_assets/kmodules/lisa/introspect_header.py index 766d96dc149d4b063548ad86c677806724ff8255..eedd77ac064710cc9ca50f083d15a188a705d3d4 100755 --- a/lisa/_assets/kmodules/lisa/introspect_header.py +++ b/lisa/_assets/kmodules/lisa/introspect_header.py @@ -19,302 +19,82 @@ import abc -import copy +import sys import itertools import argparse -import subprocess -from collections import namedtuple +from collections import namedtuple, deque import functools import json import re -from pycparser import c_ast -from pycparserext.ext_c_parser import GnuCParser -from pycparserext.ext_c_generator import GnuCGenerator +import lisa._btf as btf -class Record(abc.ABC): - @abc.abstractmethod - def make_entry(self): - pass +def process_btf(out, path, introspect, internal_type_prefix, define_typ_names): + with open(path, 'rb') as f: + data = f.read() + # TODO: this will dedup enumerators without trying to "elect" one to + # preserve its original name. We need to make it so that types reachable + # from define_typs don't have renamed enumerators if possible. -class TypeMemberRecord(namedtuple('TypeMemberRecord', ['type_kind', 'type_name', 'member_name']), Record): - def make_entry(self): - return f'#define _TYPE_HAS_MEMBER_{self.type_kind}_{self.type_name}_LISA_SEPARATOR_{self.member_name} 1' + # This will rename all types that have the same name. If it turns out that + # one of those type is a type we asked for in define_typs, there is not + # much we can do since we would not be able to know which one is to elect + # as the one we want. + typs = btf.parse_btf(data) - -class TypeExistsRecord(namedtuple('TypeExistsRecord', ['type_kind', 'type_name']), Record): - def make_entry(self): - return f'#define _TYPE_EXISTS_{self.type_kind}_{self.type_name} 1' - - -class TypedefMemo: - def __init__(self, types): - self.complete_memo = {} - self.resolved = {} - - # Seed the memo so that we know complete type defintions when typedef - # is created based on a forward definition. - def walk(typ): - self.register_complete(typ) - self.resolve_typ(typ) - - for typ in types: - walk(typ) - - @staticmethod - def _get_key(typ): - if isinstance(typ, (c_ast.Struct, c_ast.Union, c_ast.Enum)): - return (typ.__class__, typ.name) - else: - raise ValueError('unhandled type') - - @staticmethod - def _is_complete(typ): - if isinstance(typ, (c_ast.Struct, c_ast.Union)): - return typ.decls is not None - elif isinstance(typ, c_ast.Enum): - return typ.values is not None - else: - return True - - def register_complete(self, typ): - try: - key = self._get_key(typ) - except ValueError: - return - else: - # Only memoize complete definitions, i.e. not forward definitions - if self._is_complete(typ): - self.complete_memo[key] = typ - - def get_complete(self, typ): - try: - key = self._get_key(typ) - except ValueError: - return typ - else: - return self.complete_memo.get(key, typ) - - - def resolve_typ(self, typ): - try: - return self.resolved[typ] - except KeyError: - pass - - recurse = self.resolve_typ - - if isinstance(typ, (c_ast.Struct, c_ast.Union)): - def expand_child(decl): - typ = decl.type - # An struct/union anonymous member inside a struct/union is - # expanded in its parent. - if decl.name is None: - _, _, children, children_typs = recurse(typ) - return (children, list(children_typs) + [typ]) - else: - return ([decl], [typ.type]) - - name = typ.name - children = typ.decls - - if children: - children, children_typs = map(itertools.chain.from_iterable, zip(*map(expand_child, children))) - else: - children = [] - children_typs = [] - - if isinstance(typ, c_ast.Struct): - kind = 'struct' - elif isinstance(typ, c_ast.Union): - kind = 'union' - else: - raise ValueError(f'Unhandled type: {typ}') - - elif isinstance(typ, c_ast.Enum): - children = typ.values or [] - children_typs = [] - name = typ.name - kind = 'enum' - elif isinstance(typ, c_ast.Typedef): - name = typ.name - # Typedef is refering to a type by name, so look the full definition of - # that type - child_typ = self.get_complete(typ.type.type) - _, _, children, children_typs = recurse(child_typ) - kind = 'typedef' - else: - return (None, None, [], []) - - res = (kind, name, tuple(children), tuple(children_typs)) - self.resolved[typ] = res - return res - - -def make_records(memo, types): - - def recurse_multi(types): - return itertools.chain.from_iterable( - map(recurse, types) - ) - - visited = set() - def recurse(typ): - if typ in visited: - return tuple() - else: - visited.add(typ) - - kind, name, children, children_typs = memo.resolve_typ(typ) - return itertools.chain( - ( - TypeExistsRecord(type_kind=kind, type_name=name), - ) if name else tuple(), - ( - TypeMemberRecord(type_kind=kind, type_name=name, member_name=child.name) - for child in children - if name and child.name - ), - recurse_multi(children_typs) - ) - - return recurse_multi(types) - - -def introspect_header(ast): - assert isinstance(ast, c_ast.FileAST) - - def expand_decl(node): - if isinstance(node, c_ast.Decl): - return node.type - else: - return node - - types = [ - expand_decl(node) - for node in ast - ] - - memo = TypedefMemo(types) - records = make_records(memo, types) - return itertools.chain( - ( - '#define _TYPE_INTROSPECTION_INFO_AVAILABLE 1', - ), - ( - record.make_entry() - for record in records - ), - ) - - -class TypeRenameVisitor(c_ast.NodeVisitor): - def __init__(self, type_prefix, non_renamed): - self.type_prefix = type_prefix - self.names = { - name: name - for name in (non_renamed or []) - } - - def _rename(self, name): - if name: - try: - return self.names[name] - except KeyError: - new = f'{self.type_prefix}{name}' - self.names[name] = new - return new - else: - return name - - def visit_IdentifierType(self, node): - node.names = [ - self.names.get(name, name) - for name in node.names - ] - - def visit_Typedef(self, node): - def rename_decl(node, name): - if isinstance(node, c_ast.TypeDecl): - node.declname = name + if define_typ_names: + define_typ_names = set(define_typ_names) + def select(typ): + if isinstance(typ, (btf.BTFStruct, btf.BTFUnion, btf.BTFEnum, btf.BTFTypedef)): + return typ.name in define_typ_names else: - # Go through layers of PtrDecl, ArrayDecl etc - return rename_decl(node.type, name) - - new = self._rename(node.name) - node.name = new - rename_decl(node.type, new) - self.visit(node.type) - - def visit_Enum(self, node): - node.name = self._rename(node.name) - if node.values is not None: - self.visit(node.values) - - def visit_Enumerator(self, node): - node.name = self._rename(node.name) - - def _visit_StructUnion(self, node): - node.name = self._rename(node.name) - # Not a forward decl - if node.decls is not None: - self.visit(node.decls) + return False - def visit_Struct(self, node): - self._visit_StructUnion(node) - - def visit_Union(self, node): - self._visit_StructUnion(node) - - # pycparserext types added by: - # https://github.com/inducer/pycparserext/pull/76 - visit_EnumExt = visit_Enum - visit_StructExt = visit_Struct - visit_UnionExt = visit_Union - visit_EnumeratorExt = visit_Enumerator - -def rename_types(ast, type_prefix, non_renamed): - ast = copy.deepcopy(ast) - TypeRenameVisitor(type_prefix, non_renamed).visit(ast) - code = GnuCGenerator().visit(ast) - return code - - -def process_header(path, introspect, type_prefix, non_renamed_types): - with open(path, 'r') as f: - header = f.read() - - if non_renamed_types: - with open(non_renamed_types, 'r') as f: - non_renamed_types = [name.strip() for name in f.read().splitlines()] + define_typs = list(filter(select, typs)) else: - non_renamed_types = [] + define_typs = set() - # Remove comments and the non-standard GNU C extensions that pycparser cannot - # process - cmd = ['cpp', '-P', '-'] - res = subprocess.run(cmd, input=header, capture_output=True, text=True, check=True) - header = res.stdout + # Dump introspection information for all types available in BTF + btf.dump_c(typs, fileobj=out, introspection=introspect, decls=False) - parser = GnuCParser() - ast = parser.parse(header, filename=path) + # Rename internal typs so we don't clash with included kernel headers + reachable_typs = btf.BTFType.reachable_from(define_typs) - return itertools.chain( - introspect_header(ast) if introspect else [], - [rename_types(ast, type_prefix, non_renamed_types)] if type_prefix else [], + named_classes = ( + btf.BTFStruct, + btf.BTFUnion, + btf.BTFEnum, + btf.BTFTypedef, + btf.BTFFunc, + btf.BTFForwardDecl ) + def rename(name): + return f'{internal_type_prefix}{name}' + def rename_internal_typ(typ): + name = typ.name + if name in define_typ_names: + return name + else: + return rename(name) -class SymbolRecord(namedtuple('SymbolRecord', ['name']), Record): - def make_entry(self): - return f'#define _SYMBOL_EXISTS_{self.name} 1' - + for typ in reachable_typs: + if isinstance(typ, btf.BTFEnum): + typ.enumerators = { + ( + name + if typ.name in define_typ_names else + rename(name) + ): value + for name, value in typ.enumerators.items() + } + if isinstance(typ, named_classes) and typ.name: + typ.name = rename_internal_typ(typ) -class LinkerSymbolRecord(namedtuple('LinkerSymbolRecord', ['name', 'addr']), Record): - def make_entry(self): - return f'PROVIDE({self.name} = 0x{self.addr});' + # Dump declaration for all the types we are interested in + btf.dump_c(define_typs, fileobj=out, introspection=False, decls=True) def is_exported_symbol(code): @@ -330,6 +110,7 @@ def is_exported_symbol(code): # not global in the first place, so if we see it we can use it. return True or code.isupper() + def open_kallsyms(path): with open(path, 'r') as f: yield from ( @@ -340,10 +121,14 @@ def open_kallsyms(path): def process_kallsyms_introspection(path): + has_records = False def make_record(addr, code, name): + nonlocal has_records + # Uppercase codes are for STB_GLOBAL symbols, i.e. exported symbols. if name.isidentifier() and is_exported_symbol(code): - return SymbolRecord(name=name).make_entry() + has_records = True + return f'#define _SYMBOL_EXISTS_{name} 1\n' else: return None @@ -351,39 +136,35 @@ def process_kallsyms_introspection(path): make_record, open_kallsyms(path), ) - records = set(record for record in records if record) - - if records: - return itertools.chain( - records, - ( - '#define _SYMBOL_INTROSPECTION_INFO_AVAILABLE 1', - ), - ) - # If the file is empty, we assume there is no kallsyms available - else: - return [] + return itertools.chain( + filter(bool, records), + # Make a lazy generator so that "has_records" is evaluated after the + # records have been dumped. + ( + rec + for rec in ('#define _SYMBOL_INTROSPECTION_INFO_AVAILABLE 1\n',) + if has_records + ), + ) def process_kallsyms_lds(path): def make_record(addr, code, name): if name.isidentifier(): - return LinkerSymbolRecord(name=name, addr=addr).make_entry() + return f'PROVIDE({name} = 0x{addr});\n' else: return None - records = itertools.starmap( - make_record, - open_kallsyms(path), + return filter( + bool, + itertools.starmap( + make_record, + open_kallsyms(path), + ) ) - records = sorted(set(record for record in records if record)) - return records -def process_kernel_features(path): - with open(path, 'r') as f: - features = json.load(f) - +def process_kernel_features(features): # Macros cannot be recursive, so we expand them manually. def expand(value): def replace(m): @@ -407,18 +188,21 @@ def process_kernel_features(path): f'"{name}"' for name in names ) - names = f'#define __KERNEL_FEATURE_NAMES {names}' + names = f'#define __KERNEL_FEATURE_NAMES {names}\n' values = ', '.join( f'({value})' for value in values ) - values = f'#define __KERNEL_FEATURE_VALUES {values}' + values = f'#define __KERNEL_FEATURE_VALUES {values}\n' return itertools.chain( - (names, values), ( - f'#define _KERNEL_HAS_FEATURE_{name} ({value})' + names, + values + ), + ( + f'#define _KERNEL_HAS_FEATURE_{name} ({value})\n' for name, value in features ) ) @@ -426,39 +210,50 @@ def process_kernel_features(path): def main(): parser = argparse.ArgumentParser(""" - Parse a header file and generate macros to allow compile-time introspection + Parse a BTF blob and generate macros to allow compile-time introspection of types. """) - parser.add_argument('--header', help='C header file to parse') - parser.add_argument('--introspect', action='store_true', help='Create introspection macros for the given --header or --kallsyms') + parser.add_argument('--btf', help='BTF blob to parse') + + parser.add_argument('--introspect', action='store_true', help='Create introspection macros for the given --btf or --kallsyms') + parser.add_argument('--internal-type-prefix', help='Add the given prefix to the types found in --btf and dump the resulting renamed C header') - parser.add_argument('--type-prefix', help='Add the given prefix to the types found in --header and dump the resulting renamed header') - parser.add_argument('--non-renamed-types', help='File containing list of type names that will not be renamed by --type-prefix') parser.add_argument('--kallsyms', help='kallsyms content to parse') - parser.add_argument('--kernel-features', help='JSON list of kernel features') + parser.add_argument('--conf', help='JSON configuration') parser.add_argument('--symbols-lds', action='store_true', help='Create a linker script with the content of --kallsyms') args = parser.parse_args() - if args.type_prefix and not args.header: - parser.error('--header is required if --type-prefix is used') + if args.internal_type_prefix and not args.btf: + parser.error('--btf is required if --type-prefix is used') + + + if args.conf: + with open(args.conf, 'r') as f: + conf = json.load(f) + else: + conf = dict() - out = [] - if args.header: - out.append(process_header(args.header, args.introspect, args.type_prefix, args.non_renamed_types)) + out = sys.stdout + def dump_records(records): + # Fastest way to consume an iterator + deque(map(out.write, records), maxlen=0) - if args.kallsyms and args.introspect: - out.append(process_kallsyms_introspection(args.kallsyms)) + try: + if args.btf: + process_btf(out, args.btf, args.introspect, args.internal_type_prefix, conf.get('btf-types', [])) - if args.kernel_features: - out.append(process_kernel_features(args.kernel_features)) + if args.kallsyms and args.introspect: + dump_records(process_kallsyms_introspection(args.kallsyms)) - if args.kallsyms and args.symbols_lds: - out.append(process_kallsyms_lds(args.kallsyms)) + if kernel_features := conf.get('kernel-features'): + dump_records(process_kernel_features(kernel_features)) - for rec in sorted(set(itertools.chain.from_iterable(out))): - print(rec) + if args.kallsyms and args.symbols_lds: + dump_records(process_kallsyms_lds(args.kallsyms)) + finally: + out.flush() if __name__ == '__main__': main() diff --git a/lisa/_assets/kmodules/lisa/introspection.json b/lisa/_assets/kmodules/lisa/introspection.json new file mode 100644 index 0000000000000000000000000000000000000000..fdef05c67513c824960da45a8e9027c85650c61a --- /dev/null +++ b/lisa/_assets/kmodules/lisa/introspection.json @@ -0,0 +1,34 @@ +{ + "btf-types": [ + "cfs_rq", + "rq", + "root_domain", + "task_group", + "autogroup" + ], + "kernel-features": { + "RQ_CAPACITY": "HAS_MEMBER(struct, rq, cpu_capacity)", + "RQ_NR_RUNNING": "HAS_MEMBER(struct, rq, nr_running)", + + "CFS_PELT": "HAS_MEMBER(struct, cfs_rq, avg) && HAS_TYPE(struct, sched_avg)", + "CFS_UTIL_EST": "HAS_KERNEL_FEATURE(CFS_PELT) && HAS_MEMBER(struct, sched_avg, util_est)", + "CFS_UCLAMP": "IS_ENABLED(CONFIG_UCLAMP_TASK) && HAS_MEMBER(struct, rq, uclamp)", + + "SE_PELT": "HAS_TYPE(struct, sched_avg) && HAS_MEMBER(struct, sched_entity, avg)", + "SE_UCLAMP": "HAS_KERNEL_FEATURE(SE_PELT) && HAS_MEMBER(struct, uclamp_se, value)", + "SE_UTIL_EST": "HAS_KERNEL_FEATURE(SE_PELT) && HAS_MEMBER(struct, sched_avg, util_est)", + + "DL_PELT": "HAS_MEMBER(struct, rq, avg_dl)", + + "IRQ_PELT": "IS_ENABLED(CONFIG_HAVE_SCHED_AVG_IRQ) && HAS_MEMBER(struct, rq, avg_irq)", + + "RT_PELT": "HAS_MEMBER(struct, rq, avg_rt)", + + "SCHED_OVERUTILIZED": "HAS_MEMBER(struct, rq, rd) && HAS_MEMBER(struct, root_domain, overutilized)", + "SCHED_AUTOGROUP": "IS_ENABLED(CONFIG_SCHED_AUTOGROUP) && HAS_MEMBER(struct, task_group, autogroup)", + "SCHED_AVG_RBL": "HAS_MEMBER(struct, sched_avg, runnable_load_avg) || HAS_MEMBER(struct, sched_avg, runnable_avg)", + + "FILE_IO": "HAS_SYMBOL(kernel_read) && HAS_SYMBOL(kernel_write) && HAS_SYMBOL(filp_open)", + "FREQ_INVARIANCE": "HAS_SYMBOL(arch_freq_scale) && HAS_MEMBER(struct, rq, cpu_capacity_orig)" + } +} diff --git a/lisa/_assets/kmodules/lisa/introspection_data.c b/lisa/_assets/kmodules/lisa/introspection_data.c index a8bb89b58259de09eeebbd92abbf5a16b11fd8ce..4ab7f3745f77820c04cf0d4eef6985b5a26fe2cc 100644 --- a/lisa/_assets/kmodules/lisa/introspection_data.c +++ b/lisa/_assets/kmodules/lisa/introspection_data.c @@ -1,10 +1,10 @@ /* SPDX-License-Identifier: GPL-2.0 */ -/* Include here headers containing the types listed in private_types.txt. * We -process the debug info of the compiled object file like we would do * with the -BTF blob and generate the introspection_data.h header, which is then consumed the -exact * same way as an out-of-tree build. This allows controlling the format of -that * header for introspect_header.py. +/* Include here headers containing the types listed in intropsection.json. + * We process the debug info of the compiled object file like we would do with + * the BTF blob and generate the introspection_data.h header, which is then + * consumed the exact same way as an out-of-tree build. This allows controlling + * the format ofthat header for introspect_header.py. */ #ifdef _IN_TREE_BUILD diff --git a/lisa/_assets/kmodules/lisa/kernel_features.json b/lisa/_assets/kmodules/lisa/kernel_features.json deleted file mode 100644 index 89ea45d537f58c414c22d0607d636a510028e68d..0000000000000000000000000000000000000000 --- a/lisa/_assets/kmodules/lisa/kernel_features.json +++ /dev/null @@ -1,26 +0,0 @@ - -{ - "RQ_CAPACITY": "HAS_MEMBER(struct, rq, cpu_capacity)", - "RQ_NR_RUNNING": "HAS_MEMBER(struct, rq, nr_running)", - - "CFS_PELT": "HAS_MEMBER(struct, cfs_rq, avg) && HAS_TYPE(struct, sched_avg)", - "CFS_UTIL_EST": "HAS_KERNEL_FEATURE(CFS_PELT) && HAS_MEMBER(struct, sched_avg, util_est)", - "CFS_UCLAMP": "IS_ENABLED(CONFIG_UCLAMP_TASK) && HAS_MEMBER(struct, rq, uclamp)", - - "SE_PELT": "HAS_TYPE(struct, sched_avg) && HAS_MEMBER(struct, sched_entity, avg)", - "SE_UCLAMP": "HAS_KERNEL_FEATURE(SE_PELT) && HAS_MEMBER(struct, uclamp_se, value)", - "SE_UTIL_EST": "HAS_KERNEL_FEATURE(SE_PELT) && HAS_MEMBER(struct, sched_avg, util_est)", - - "DL_PELT": "HAS_MEMBER(struct, rq, avg_dl)", - - "IRQ_PELT": "IS_ENABLED(CONFIG_HAVE_SCHED_AVG_IRQ) && HAS_MEMBER(struct, rq, avg_irq)", - - "RT_PELT": "HAS_MEMBER(struct, rq, avg_rt)", - - "SCHED_OVERUTILIZED": "HAS_MEMBER(struct, rq, rd) && HAS_MEMBER(struct, root_domain, overutilized)", - "SCHED_AUTOGROUP": "IS_ENABLED(CONFIG_SCHED_AUTOGROUP) && HAS_MEMBER(struct, task_group, autogroup)", - "SCHED_AVG_RBL": "HAS_MEMBER(struct, sched_avg, runnable_load_avg) || HAS_MEMBER(struct, sched_avg, runnable_avg)", - - "FILE_IO": "HAS_SYMBOL(kernel_read) && HAS_SYMBOL(kernel_write) && HAS_SYMBOL(filp_open)", - "FREQ_INVARIANCE": "HAS_SYMBOL(arch_freq_scale) && HAS_MEMBER(struct, rq, cpu_capacity_orig)" -} diff --git a/lisa/_assets/kmodules/lisa/lisa/_btf.py b/lisa/_assets/kmodules/lisa/lisa/_btf.py new file mode 120000 index 0000000000000000000000000000000000000000..8ffe70b86e82dc72d6abfa40673e67e0417faa4a --- /dev/null +++ b/lisa/_assets/kmodules/lisa/lisa/_btf.py @@ -0,0 +1 @@ +../../../../_btf.py \ No newline at end of file diff --git a/lisa/_assets/kmodules/lisa/make_introspection_header.sh b/lisa/_assets/kmodules/lisa/make_introspection_header.sh deleted file mode 100755 index 2618e6c1d9d14bf6225d1f5f915f19e036a84afb..0000000000000000000000000000000000000000 --- a/lisa/_assets/kmodules/lisa/make_introspection_header.sh +++ /dev/null @@ -1,55 +0,0 @@ -#! /bin/sh - -set -e - -OUT=$1 -MODULE_SRC=$2 -MODULE_OBJ=$3 -VENV=$4 -CC=$5 -PRIVATE_TYPES_TXT=$6 -VMLINUX=$7 -UNUSED_KERNEL_PRIVATE_TYPES_PREFIX=$8 -KALLSYMS=$9 - -# Some options are not upstream (yet) but they have all be published on the -# dwarves mailing list -# -# Options: -# -F btf,dwarf: Use BTF first -# -E: Expand nested type definitions -# --suppress_force_paddings: Remove the "artificial" padding members pahole adds -# to make padding more visible. They are not always valid C syntax and can -# break build -# --skip_missing: Keep going if one of the types is not found -# --expand_types_once (non upstream): Only expand a given type once, to avoid type redefinition -# (C does not care about nesting types, there is a single namespace). -# -# We then post-process the header to add a prefix to each type expanded by -E -# that was not explicitly asked for. This avoids conflicting with type -# definitions that would come from public kernel headers, while still allowing -# easy attribute access. -pahole -F btf,dwarf -E --compile --suppress_force_paddings --show_only_data_members --skip_missing --expand_types_once -C "file://$PRIVATE_TYPES_TXT" "$VMLINUX" > "$MODULE_OBJ/_header" - -# Create a header with all the types we can for introspection purposes. This -# will not be included in any of the module sources, so all we care about is -# that pycparser can parse it. Specifically, some types may be re-defined with -# incompatible definitions. This is expected as various drivers use the same -# struct names. -pahole -F btf,dwarf -E --expand_types_once --suppress_force_paddings --suppress_aligned_attribute --suppress_packed --show_only_data_members --compile --fixup_silly_bitfields "$VMLINUX" > "$MODULE_OBJ/_full_header" - -# Strip comments to avoid matching them with the sed regex. -"$CC" -P -E - < "$MODULE_OBJ/_header" > "$MODULE_OBJ/_header_no_comment" -# Create forward declaration of every type to ensure the header can be parsed correctly. -sed -r -n 's/.*(struct|union|enum) ([0-9a-zA-Z_]*) .*/\1 \2;/p' "$MODULE_OBJ/_header_no_comment" | sort -u > "$MODULE_OBJ/_fwd_decl" - -# Rename all the kernel private types we are not directly interested in to avoid any clash -cat "$MODULE_OBJ/_fwd_decl" "$MODULE_OBJ/_header_no_comment" > "$MODULE_OBJ/_header" -. "$VENV/bin/activate" && python3 "$MODULE_SRC/introspect_header.py" --header "$MODULE_OBJ/_header" --type-prefix "$UNUSED_KERNEL_PRIVATE_TYPES_PREFIX" --non-renamed-types "$PRIVATE_TYPES_TXT" > "$MODULE_OBJ/_renamed_header" - -# Create type introspection macros -. "$VENV/bin/activate" && python3 "$MODULE_SRC/introspect_header.py" --header "$MODULE_OBJ/_full_header" --introspect --kallsyms "$KALLSYMS" --kernel-features "$MODULE_SRC/kernel_features.json" >> "$MODULE_OBJ/_introspection_header" - -# Build the final header -printf '#pragma once\n' > "$OUT" -cat "$MODULE_OBJ/_introspection_header" "$MODULE_OBJ/_renamed_header" >> "$OUT" diff --git a/lisa/_assets/kmodules/lisa/private_types.txt b/lisa/_assets/kmodules/lisa/private_types.txt deleted file mode 100644 index 10777f2a54f194664a81577b8b3e7be6b3c2889b..0000000000000000000000000000000000000000 --- a/lisa/_assets/kmodules/lisa/private_types.txt +++ /dev/null @@ -1,5 +0,0 @@ -cfs_rq -rq -root_domain -task_group -autogroup diff --git a/lisa/_assets/kmodules/lisa/requirements.txt b/lisa/_assets/kmodules/lisa/requirements.txt deleted file mode 100644 index 302be7e56f602cf0fbd40b4bcd3a8f882bbfeacf..0000000000000000000000000000000000000000 --- a/lisa/_assets/kmodules/lisa/requirements.txt +++ /dev/null @@ -1,3 +0,0 @@ -# We need the __attribute__(()) support implemented in that pull request: -# https://github.com/inducer/pycparserext/pull/76 -https://github.com/douglas-raillard-arm/pycparserext/archive/lisa.zip diff --git a/lisa/_assets/kmodules/lisa/sched_helpers.h b/lisa/_assets/kmodules/lisa/sched_helpers.h index 0ee4ce3ba0a86ec648a09b651415c7410a06f93f..ff0ddc8107e96ea6480e7a48f5795f00dbc3a1b2 100644 --- a/lisa/_assets/kmodules/lisa/sched_helpers.h +++ b/lisa/_assets/kmodules/lisa/sched_helpers.h @@ -9,7 +9,6 @@ #include #include "introspection.h" -#include "generated/introspection_data.h" #if HAS_TYPE(struct, cfs_rq) diff --git a/lisa/_btf.py b/lisa/_btf.py new file mode 100644 index 0000000000000000000000000000000000000000..2295054dfc678c64407c95de5242a1316527f8a8 --- /dev/null +++ b/lisa/_btf.py @@ -0,0 +1,1796 @@ +# SPDX-License-Identifier: Apache-2.0 +# +# Copyright (C) 2023, ARM Limited and contributors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +""" +This module implements a BTF debug info parser as described by: +https://www.kernel.org/doc/html/latest/bpf/btf.html +""" + + +import itertools +import struct +import enum +import functools +import io +import copy +import re +import contextlib +from operator import attrgetter +import inspect + + +def _next_multiple(x, n): + if n: + remainder = x % n + if remainder: + return x + n - remainder + else: + return x + else: + return x + + +def _scan(buf, f): + xs = [] + while buf: + buf, x = f(buf) + xs.append(x) + return xs + + +class BTFSignedness(enum.Enum): + SIGNED = 1 + UNSIGNED = 0 + + @classmethod + def from_int(cls, v): + if v: + return cls.SIGNED + else: + return cls.UNSIGNED + + +class BTFIntEncoding(enum.Enum): + NONE = 0 + SIGNED = 1 + CHAR = 2 + BOOL = 3 + + @classmethod + def from_int(cls, v): + #define BTF_INT_SIGNED (1 << 0) + #define BTF_INT_CHAR (1 << 1) + #define BTF_INT_BOOL (1 << 2) + + if v == 0: + return cls.NONE + elif v == 1 << 0: + return cls.SIGNED + elif v == 1 << 1: + return cls.CHAR + elif v == 1 << 2: + return cls.BOOL + else: + raise ValueError(f'Unknown int encoding: {v}') + + +class _TypeRef: + __slots__ = ('index',) + def __init__(self, index): + self.index = index + + @classmethod + def fixup(cls, v, typs): + if isinstance(v, cls): + v = typs[v.index] + return v + + +class _BTFTypeMeta(type): + def __new__(metacls, name, bases, dct, **kwargs): + new = super().__new__(metacls, name, bases, dct, **kwargs) + mro = inspect.getmro(new) + new._TYP_ATTRS = tuple(sorted(set( + attr + for cls in mro + for attr in cls.__dict__.get('_TYP_ATTRS', ()) + ))) + new._ITERABLE_TYP_ATTRS = tuple(sorted(set( + attr + for cls in mro + for attr in cls.__dict__.get('_ITERABLE_TYP_ATTRS', ()) + ))) + + return new + + +class BTFType(metaclass=_BTFTypeMeta): + __slots__ = ('id',) + _TYP_ATTRS = () + _ITERABLE_TYP_ATTRS = () + + def __init__(self): + self.id = None + + @classmethod + def reachable_from(cls, typs): + reachable_typs = set() + for typ in typs: + typ._map_typs(lambda x: x, visited=reachable_typs) + return reachable_typs + + def _map_typs(self, f, visited): + if self in visited: + return + else: + visited.add(self) + for attr in self._TYP_ATTRS: + x = getattr(self, attr) + x = f(x) + setattr(self, attr, x) + if isinstance(x, BTFType): + x._map_typs(f, visited) + + for attr in self._ITERABLE_TYP_ATTRS: + for x in getattr(self, attr): + f(x) + x._map_typs(f, visited) + + def _unwrap(self, classinfo): + typ = self + while isinstance(typ, classinfo): + typ = typ.typ + return typ + + @property + def unspecified(self): + return self._unwrap(_CDeclSpecifier) + + @property + def underlying(self): + return self._unwrap((BTFTypedef, _CDeclSpecifier)) + + @property + def is_incomplete(self): + return False + + def _dump_c_introspection(self, ctx): + return + + +class _CDecl: + def _do_dump_c_decls(self, ctx): + pass + + def _dump_c_decls(self, ctx, memoize=True, **kwargs): + if memoize: + try: + x = ctx._memo[self] + except KeyError: + x = self._do_dump_c_decls(ctx, **kwargs) + ctx._memo[self] = x + else: + x = self._do_dump_c_decls(ctx, **kwargs) + + return x + + +class _CBuiltin(_CDecl): + def _do_dump_c_decls(self, ctx): + return self.name + + +class _CSizedBuiltin(_CBuiltin): + def _do_dump_c_decls(self, ctx): + name = self.name + size = self.size + ctx.write( + f'_Static_assert(sizeof({name}) == {size}ull, "{name} does not have expected size: {size}");\n' + ) + return name + + +class _FixupTyp: + _TYP_ATTRS = ('typ',) + + +class _TransparentType(_FixupTyp): + @property + def bits(self): + return self.typ.bits + + @property + def size(self): + return self.typ.size + + @property + def alignment(self): + return self.typ.alignment + + @property + def is_incomplete(self): + return self.typ.is_incomplete + + def _dump_c_introspection(self, ctx): + return self.typ._dump_c_introspection(ctx) + + +class _CQualifier: + pass + + +class _CDeclSpecifier(_TransparentType, _CDecl, BTFType): + __slots__ = ('typ',) + + def __init__(self, typ): + super().__init__() + self.typ = typ + + def __str__(self): + return self._c_specifier + + def _do_dump_c_decls(self, ctx, anonymous=False, memoize=True): + typ = self.typ + + # It is important to dump anonymous struct/union as an inline + # definition rather than adding a typedef, since inline anonymous + # struct/unions are expanded in their parent struct union (which would + # not happen if we added a typedef layer). + if anonymous: + typename = typ._dump_c_decls( + ctx, + anonymous=anonymous, + memoize=memoize + ) + return f'{self._c_specifier} {typename}' + # Qualifying a function type is forbidden by C spec. For some reason, + # some kernel seem to include that in BTF, but maybe it's a bug in + # pahole. + elif isinstance(typ, BTFFuncProto) and isinstance(self, _CQualifier): + return typ._dump_c_decls(ctx) + else: + name = ctx.make_name() + typename = typ._dump_c_decls(ctx) + ctx.write( + f'typedef {self._c_specifier} {typename} {name};\n', + ) + return name + + +class BTFVoid(_CBuiltin, BTFType): + name = 'void' + + +class BTFInt(_CSizedBuiltin, BTFType): + __slots__ = ('name', 'size', 'encoding', 'bit_offset', 'bits') + + def __init__(self, name, size, encoding, bit_offset, bits): + super().__init__() + self.name = name + self.encoding = encoding + self.bit_offset = bit_offset + self.size = size + self.bits = bits + + @property + def is_bitfield(self): + return self.bits != (self.size * 8) + + @property + def alignment(self): + return self.size + + +class BTFFloat(_CSizedBuiltin, BTFType): + __slots__ = ('name', 'size') + + def __init__(self, name, size): + super().__init__() + self.name = name + self.size = size + + @property + def bits(self): + return self.size * 8 + + @property + def alignment(self): + return self.size + + +class BTFPtr(_FixupTyp, _CDecl, BTFType): + __slots__ = ('typ', 'size') + + def __init__(self, typ, size): + super().__init__() + self.typ = typ + self.size = size + + def _do_dump_c_decls(self, ctx): + size = self.size + name = ctx.make_name() + + # Turn a struct/union pointee into a forward reference, so that we + # break any circular references. + typ = self._break_loop() + typename = typ._dump_c_decls(ctx) + ctx.write( + f'typedef {typename} *{name};\n' + ) + + if size is not None: + ctx.write( + f'_Static_assert(sizeof({name}) == {size}ull, "Pointer to {typename} does not have expected size: {size}");\n' + ) + return name + + def _break_loop(self): + underlying = self.typ.underlying + + # If we are pointing at a struct/union, make a new pointee chain that: + # * ends up on a forward reference instead of the struct/union + # * does not contain any typedef + # + # This breaks any loop in self-referential structs, and removing the + # typedefs avoid creating a typedef to an incomplete type (the forward + # declaration), which would be unusable for some non-pointer consumers. + if isinstance(underlying, _BTFStructUnion) and underlying.fwd_decl is not None: + root = copy.copy(self) + parent = root + while True: + child = parent.typ + # Get rid of typedefs, since we don't want to dump types that + # will be possibly dumped later by something else depending on + # it, as we are creating copies of the beginning of the pointee + # chain. + while isinstance(child, BTFTypedef): + child = child.typ + + if isinstance(child, _BTFStructUnion): + parent.typ = child.fwd_decl + break + else: + child = copy.copy(child) + parent.typ = child + parent = child + return root.typ + else: + return self.typ + + @property + def bits(self): + return self.size * 8 + + @property + def alignment(self): + return self.size + + +class BTFEnum(_CDecl, BTFType): + __slots__ = ('name', 'signed', 'size', 'enumerators', 'int_typ') + _KIND = 'enum' + _TYP_ATTRS = ('int_typ',) + + def __init__(self, name, signed, size, enumerators, int_typ): + super().__init__() + self.name = name + self.signed = signed + self.size = size + self.enumerators = enumerators + self.int_typ = int_typ + + def __str__(self): + name = self.name or '' + return f'enum {name}' + + @property + def bits(self): + return self.size * 8 + + @property + def alignment(self): + return self.size + + def _dump_c_introspection(self, ctx): + ctx.typ_exists(self) + with ctx.with_parent(self) as ctx: + for enumerator in self.enumerators.keys(): + ctx.typ_member(enumerator) + + def _do_dump_c_decls(self, ctx): + enumerators = self.enumerators + size = self.size + int_typ = self.int_typ + + def format_enumerator(name, value): + value = '' if value is None else f'={value}{"ull" if value >= 0 else "ll"}' + return f'{name}{value}' + + enumerators_str = ', '.join( + format_enumerator(name, value) + for name, value in enumerators.items() + ) + + mode = 'packed' if size < 4 else None + attrs = f'__attribute__(({mode}))' if mode else '' + + name = self.name or ctx.make_name() + ctx.write( + f'enum {name} {{ {enumerators_str} }} {attrs};\n', + ) + + # Old pahole version emit a BTF_KIND_ENUM instead of + # BTF_KIND_ENUM64, leading to "0" values in enumerators with high + # values. This prevents creating an enum of the right size, so in order + # to avoid broken structs layout we just pretend they are an integer of + # the correct size. + if size < 8 or not int_typ: + ctx.write( + f'_Static_assert(sizeof(enum {name}) == {size}ull, "enum {name} does not have expected size: {size}");\n' + ) + return f'enum {name}' + elif int_typ: + return int_typ._dump_c_decls(ctx) + else: + raise ValueError(f'Could not dump enum {name} as its size is {size} and no integer type of the right size has been detected') + + +class _BTFStructUnion(_CDecl, BTFType): + __slots__ = ('name', 'size', 'members', 'fwd_decl') + _ITERABLE_TYP_ATTRS = ('members',) + + def __init__(self, name, size, members): + super().__init__() + self.name = name + self.size = size + self.members = [] + self.fwd_decl = _LinkedForwardDecl(self) if name else None + + for member in members: + # Avoid modifying the existing member in case it is shared with + # another struct. + member = copy.copy(member) + member.parent = self + self.members.append(member) + + def __str__(self): + name = self.name or '' + return f'{self._KIND} {name}' + + def _dump_c_introspection(self, ctx): + ctx.typ_exists(self) + with ctx.with_parent(self) as ctx: + for member in self.members: + member._dump_c_introspection(ctx) + + def _do_dump_c_decls(self, ctx, anonymous=False): + members = self._all_members + size = self.size + kind = self._KIND + name = self.name or ctx.make_name() + fwd_decl = f'{kind} {name}' + + def format_member(member): + name = member.name + typ = member.typ + if name: + typename = typ._dump_c_decls(ctx) + is_bitfield = member.is_bitfield + assert member.bits or not is_bitfield + bitfield = f': {member.bits}' if is_bitfield else '' + aligned = is_bitfield or not (member.bit_offset % (member.alignment * 8)) + packed = '' if aligned else ' __attribute__((packed))' + return f'{typename} {name}{bitfield}{packed}' + # ISO C allows anonymous structs/union inside a struct/union. + elif isinstance(typ.unspecified, _BTFStructUnion): + # Bypass the caching since we absolutely do not want to get + # back an internal typedef, which would break the layout of the + # parent struct. Anonymous union/struct are only useful if + # their declaration are expanded in the parent. + return typ._dump_c_decls(ctx, anonymous=True, memoize=False) + else: + raise ValueError(f'Unsupported anonymous member in {self}') + + def format_assert(fwd_decl, member): + name = member.name + assert name + bit_offset = member.bit_offset + byte_offset = bit_offset // 8 + assert byte_offset >= 0 + return f'_Static_assert(__builtin_offsetof({fwd_decl}, {name}) == {byte_offset}ull, "{fwd_decl}.{name} does not have the expected offset: {byte_offset}")' + + attrs, last_padding = self._align_attribute + if last_padding: + members = (*members, last_padding) + attrs = attrs or '' + + members_str = '; '.join(map(format_member, members)) + members_str = f'{members_str};' if members_str else '' + + if anonymous: + return f'{kind} {{ {members_str} }} {attrs}' + else: + ctx.write( + f'{fwd_decl} {{ {members_str} }} {attrs};\n', + ) + sep = ';\n' + asserts = sep.join( + format_assert(fwd_decl, member) + for member in members + if member.name and not member.is_bitfield + ) + if asserts: + ctx.write(f'{asserts}{sep}') + + ctx.write( + f'_Static_assert(sizeof({fwd_decl}) == {size}ull, "{fwd_decl} does not have expected size: {size}");\n' + ) + return fwd_decl + + @property + def bits(self): + return self.size * 8 + + @property + def _min_alignment(self): + members = self.members + if members: + return max(member.alignment for member in members) + else: + return 1 + + @property + def is_incomplete(self): + return any(member.typ.is_incomplete for member in self.members) + + @property + def _min_size(self): + members = self.members + size = self.size + min_alignment = self._min_alignment + + if members: + last = members[-1] + return _next_multiple(last.bit_offset + last.bits, 8) // 8 + else: + return 0 + + +class BTFMember(_FixupTyp, BTFType): + __slots__ = ('name', 'typ', 'bit_offset', '_bits', 'parent') + _TYP_ATTRS = ('typ',) + + def __init__(self, name, typ, bits, bit_offset): + super().__init__() + self.name = name + self.typ = typ + self.bit_offset = bit_offset + # bits could be 0 un a variety of circumsances, but it always means the + # value is to be taken from somewhere else since a bitfield of size 0 + # is not allowed in C. + self._bits = bits or None + self.parent = None + + @property + def _prev_member(self): + i = self._index + if i: + return self.parent.members[i - 1] + else: + return None + + @property + def _index(self): + members = self.parent.members + return members.index(self) + + @property + def alignment(self): + return self.typ.alignment + + @property + def bits(self): + typ = self.typ + if isinstance(typ.underlying, (BTFInt, BTFEnum)): + # If the member had a bitsize defined directly, we use that, + # otherwise the bitsize is "inherited" from the type. + return self._bits or typ.bits + else: + return typ.bits + + @property + def is_bitfield(self): + typ = self.typ + if self.bits != typ.bits: + return True + else: + underlying = typ.underlying + return isinstance(underlying, BTFInt) and underlying.is_bitfield + + @property + def pre_padding(self): + bit_offset = self.bit_offset + # If the bit_offset is not a multiple of 8, it means we are in the + # middle of a bitfield block and there is no padding to be added. + # + # Note that anonymous bitfield of size 0 can be used to force + # allocation of the next bitfield in another block, so if that's the + # case we very much want to insert the appropriate padding. + if (bit_offset % 8) or isinstance(self.parent, BTFUnion): + return () + else: + bits = self.bits + # Could be a bitfield, in which case we round up to the next byte + size = _next_multiple(bits, 8) // 8 + + prev_member = self._prev_member + if prev_member: + # The previous member might be a bitfield. In that case, we + # round up the end of the bitfield to the next byte, like clang + # and GCC do. + first_bit_offset = _next_multiple( + prev_member.bit_offset + prev_member.bits, + 8, + ) + assert first_bit_offset <= bit_offset + padding = abs(bit_offset - first_bit_offset) + assert not (padding % 8) + padding = padding // 8 + + if padding: + padding = BTFPaddingMember( + # The name must be unique inside the struct + # (self._index) but also unique among sibling structs, + # as ISO C allows anonymous structs inside a top-level + # struct, behaving as if their content was inlined in + # the parent struct. + name=f'____PADDING_{self.parent.id}_{self._index}', + size=padding, + bit_offset=first_bit_offset, + ) + return (padding,) + else: + return () + else: + # We are the first member, nothing to align + return () + + def _dump_c_introspection(self, ctx): + typ = self.typ + + ctx.typ_member(self.name) + + # If the member type is a named struct/union, it is to be treated just + # like any other top-level type, so we need reset the parent chain. + if isinstance(typ, _BTFStructUnion) and typ.name: + ctx_mgr = ctx.with_parent(None) + else: + ctx_mgr = contextlib.nullcontext(ctx) + + with ctx_mgr as ctx: + self.typ._dump_c_introspection(ctx) + + +class BTFStruct(_BTFStructUnion): + __slots__ = ('_alignment',) + _KIND = 'struct' + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self._alignment = None + + @property + def _all_members(self): + members = self.members + if members: + return [ + _member + for member in self.members + for _member in (*member.pre_padding, member) + ] + # Some structs only contain anonymous bitfields, so they have a + # non-zero size but no member recorded in BTF + elif size := self.size: + return [ + BTFPaddingMember( + name=f'____PADDING_{self.id}_0', + size=size, + bit_offset=0, + ) + ] + else: + return [] + + @property + def _max_alignment(self): + members = self.members + if members: + min_alignment = self._min_alignment + size = self.size + min_size = self._min_size + + assert size >= min_size + last_padding = abs(size - min_size) + max_alignment = 1 << last_padding.bit_length() + return max(max_alignment, min_alignment) + else: + return 1 + + @property + def alignment(self): + alignment = self._alignment + if alignment is None: + max_alignment = self._max_alignment + # We have something weird going on, like a struct manually padded using + # anonymous bitfields at the end. + self._alignment = self._min_alignment if self.size % max_alignment else max_alignment + return self._alignment + else: + return alignment + + @property + def _align_attribute(self): + members = self.members + size = self.size + alignment = self.alignment + min_alignment = self._min_alignment + max_alignment = self._max_alignment + + # We have something weird going on, like a struct manually padded using + # anonymous bitfields at the end. + if size % max_alignment: + packed = 'packed' + last = members[-1] if members else None + min_size = self._min_size + # We cannot add padding if the last member is a flexible array (or + # any struct/typedef containing one). + if last and last.is_incomplete: + raise ValueError(f'Cannot add necessary padding to {self.fwd_decl}') + else: + assert size >= min_size + last_padding = abs(size - min_size) + + padding = BTFPaddingMember( + # The name must be unique inside the struct + # (self._index) but also unique among sibling structs, + # as ISO C allows anonymous structs inside a top-level + # struct, behaving as if their content was inlined in + # the parent struct. + name=f'____PADDING_{self.id}_{len(members) + 1}', + size=last_padding, + bit_offset=min_size * 8, + ) + align = None + else: + padding = None + align = f'aligned({alignment})' if alignment > min_alignment else '' + packed = '' + + attrs = ','.join(attr for attr in (packed, align) if attr) + return ( + f'__attribute__(({attrs}))' if attrs else None, + padding + ) + + +class BTFUnion(_BTFStructUnion): + _KIND = 'union' + pre_padding = () + + @property + def _all_members(self): + return self.members + + @property + def alignment(self): + return self._min_alignment + + @property + def _align_attribute(self): + size = self.size + return ( + '__attribute__((packed))' if size % self._min_alignment else None, + # Always add a padding member in unions since some unions are + # sometimes wrongly reported as having 0 members (vlen=0), probably + # due to a pahole bug. When that is the case, the padding member + # ensures the size of the type will be correct. + BTFPaddingMember( + # The name must be unique inside the struct + # (self._index) but also unique among sibling structs, + # as ISO C allows anonymous structs inside a top-level + # struct, behaving as if their content was inlined in + # the parent struct. + name=f'__ENSURE_UNION_SIZE_{self.id}_{len(self.members) + 1}', + size=size, + bit_offset=0, + ) + ) + + +class BTFTypedef(_TransparentType, _CDecl, BTFType): + __slots__ = ('name', 'typ') + _KIND = 'typedef' + _TYP_ATTRS = ('typ',) + + def __init__(self, name, typ): + super().__init__() + self.name = name + self.typ = typ + + def _dump_c_introspection(self, ctx): + ctx.typ_exists(self) + with ctx.with_parent(self) as ctx: + self.typ._dump_c_introspection(ctx) + + def _do_dump_c_decls(self, ctx): + name = self.name + typ = self.typ + typename = typ._dump_c_decls(ctx) + + # Some types are special for the compiler and it hates it being + # re-typedefed, such as __builtin_va_list + if not name.startswith('__builtin_'): + ctx.write( + f'typedef {typename} {name};\n' + ) + return name + + +class BTFConst(_CDeclSpecifier, _CQualifier): + _c_specifier = 'const' + + +class BTFVolatile(_CDeclSpecifier, _CQualifier): + _c_specifier = 'volatile' + + +class BTFRestrict(_CDeclSpecifier, _CQualifier): + _c_specifier = 'restrict' + + +class BTFArray(_FixupTyp, _CDecl, BTFType): + __slots__ = ('typ', 'index_typ', 'nelems') + _TYP_ATTRS = ('typ', 'index_typ') + + def __init__(self, typ, index_typ, nelems): + super().__init__() + self.typ = typ + self.index_typ = index_typ + self.nelems = nelems + + def _do_dump_c_decls(self, ctx): + size = self.size + name = ctx.make_name() + typename = self.typ._dump_c_decls(ctx) + # We can never emit flexible array member (e.g. int arr[]) but instead + # we always emit zero-length-array (e.g. int arr[0]). Flexible array + # members are part of the standard while zero-length-arrays are not, + # but unfortunately they are encoded the same way, and it is forbidden + # by the standard to have a flexible array member in a struct anywhere + # else than the last position. Annoyingly, some structs in the kernel + # use ZLA, which do not have this restriction (in GCC at least). + array_size = self.nelems or 0 + ctx.write( + f'typedef {typename} {name}[{array_size}];\n' + ) + + ctx.write( + f'_Static_assert(sizeof({name}) == {size}ull, "{typename}[{array_size}] does not have expected size: {size}");\n' + ) + return name + + def _dump_c_introspection(self, ctx): + self.typ._dump_c_introspection(ctx) + self.index_typ._dump_c_introspection(ctx) + + @property + def size(self): + return self.typ.size * self.nelems + + @property + def bits(self): + return self.size * 8 + + @property + def alignment(self): + return self.typ.alignment + + @property + def is_incomplete(self): + # Technically this is not incomplete in the context of a BTFFuncProto + # parameter, but we just made BTFFuncProto.is_complete always return + # False + return not self.nelems + + +class BTFPaddingMember(BTFMember): + _ITEM_TYP = BTFInt( + name='unsigned char', + size=1, + encoding=BTFIntEncoding.NONE, + bit_offset=0, + bits=8, + ) + + _INDEX_TYP = BTFInt( + name='unsigned long long', + size=8, + encoding=BTFIntEncoding.NONE, + bit_offset=0, + bits=64, + ) + + @property + def pre_padding(self): + return () + + def __init__(self, name, bit_offset, size): + super().__init__( + name=name, + typ=self._array_typ(size), + bits=size * 8, + bit_offset=bit_offset, + ) + + @classmethod + # Cache so that we don't re-emit thousands of times the exact same typedef, + # since padding types would otherwise represent ~20% of the other types + @functools.lru_cache(maxsize=1024) + def _array_typ(cls, size): + return BTFArray( + typ=cls._ITEM_TYP, + index_typ=cls._INDEX_TYP, + nelems=size, + ) + + +class BTFFuncProto(_FixupTyp, _CDecl, BTFType): + __slots__ = ('typ', '_params') + _ITERABLE_TYP_ATTRS = ('_params',) + + def __init__(self, typ, params): + super().__init__() + self.typ = typ + self._params = params + + def _do_dump_c_decls(self, ctx): + ret_typ = self.typ + params = self.params + name = ctx.make_name() + + ret_typename = ret_typ._dump_c_decls(ctx) + params = ', '.join( + str(param.typ._dump_c_decls(ctx)) + for param in params + ) + + ctx.write( + f'typedef {ret_typename} ({name})({params});\n' + ) + + return name + + def _dump_c_introspection(self, ctx): + self.typ._dump_c_introspection(ctx) + for param in self._params: + param.typ._dump_c_introspection(ctx) + + @property + def params(self): + return self._params or [ + BTFParam(name=None, typ=BTFVoid()) + ] + + +class BTFParam(_TransparentType, BTFType): + __slots__ = ('name', 'typ') + + def __init__(self, name, typ): + super().__init__() + self.name = name + self.typ = typ + + +class _BTFEllipsis(_CBuiltin, BTFType): + name = '...' + + +class BTFVarArgParam(BTFParam): + def __init__(self): + super().__init__( + name='...', + typ=_BTFEllipsis() + ) + + +class BTFForwardDecl(_CDecl, BTFType): + __slots__ = ('name', 'typ_cls') + + def __init__(self, name, typ_cls): + super().__init__() + self.name = name + self.typ_cls = typ_cls + + def _do_dump_c_decls(self, ctx): + name = self.name + kind = self.typ_cls._KIND + fwd_decl = f'{kind} {name}' + ctx.write(f'{fwd_decl};\n') + return fwd_decl + + +class _LinkedForwardDecl(BTFForwardDecl): + __slots__ = ('parent',) + def __init__(self, parent): + self.parent = parent + + @property + def name(self): + return self.parent.name + + @property + def typ_cls(self): + return self.parent.__class__ + + +class BTFFunc(_FixupTyp, BTFType): + __slots__ = ('name', 'typ', 'linkage') + + def __init__(self, name, typ, linkage): + super().__init__() + self.name = name + self.typ = typ + self.linkage = linkage + + def _dump_c_introspection(self, ctx): + self.typ._dump_c_introspection(ctx) + + +class BTFFuncLinkage(enum.Enum): + STATIC = 0 + GLOBAL = 1 + EXTERN = 2 + + @classmethod + def from_int(cls, v): + if v == 0: + return cls.STATIC + elif v == 1: + return cls.GLOBAL + elif v == 2: + return cls.EXTERN + else: + raise ValueError(f'Unknown BTF function linkage: {v}') + + +class BTFVar(_TransparentType, BTFType): + __slots__ = ('name', 'typ', 'linkage') + + def __init__(self, name, typ, linkage): + super().__init__() + self.name = name + self.typ = typ + self.linkage = linkage + + +class BTFVarLinkage(enum.Enum): + STATIC = 0 + GLOBAL = 1 + + @classmethod + def from_int(cls, v): + if v == 0: + return cls.STATIC + elif v == 1: + return cls.GLOBAL + else: + raise ValueError(f'Unknown BTF variable linkage: {v}') + + +class BTFDataSec(BTFType): + __slots__ = ('name', 'size', 'variables') + _ITERABLE_TYP_ATTRS = ('variables',) + + def __init__(self, name, size, variables): + super().__init__() + self.name = name + self.size = size + self.variables = variables + + @property + def bits(self): + return self.size * 8 + + +class BTFVarSecInfo(_FixupTyp, BTFType): + __slots__ = ('typ', 'offset', 'size') + + def __init__(self, typ, offset, size): + super().__init__() + self.typ = typ + self.size = size + self.offset = offset + + @property + def bits(self): + return self.size * 8 + + +class BTFAttribute: + __slots__ = ('name', 'value') + + def __init__(self, name, value): + self.name = name + self.value = value + + def __str__(self): + value = self.value + + if value is None: + value = '' + elif isinstance(value, str): + value = f'("{value}")' + else: + value = f'({value})' + + return f'{self.name}{value}' + + +class BTFDeclTag(_TransparentType, _CDecl, BTFType): + __slots__ = ('attribute', 'typ', 'component_idx') + + def __init__(self, typ, tag, component_idx): + super().__init__() + self.attribute = BTFAttribute( + name='btf_decl_tag', + value=tag, + ) + self.typ = typ + self.component_idx = component_idx + + def _do_dump_c_decls(self, ctx): + # TODO: actually add __attribute__((the btf_decl_tag())) + return self.typ._do_dump_c_decls(ctx) + + +class BTFTypeTag(_CDeclSpecifier): + __slots__ = ('attribute', 'typ') + + def __init__(self, typ, tag): + super().__init__(typ=typ) + self.attribute = BTFAttribute( + name='btf_type_tag', + value=tag, + ) + + @property + def _c_specifier(self): + return f'__attribute__(({self.attribute}))' + + +def _parse_btf(buf): + # Creating a memoryview() allows a copy-less slicing operation, so we can + # manipulate slices just as buffers without having to pay the astronomical + # cost of copying data every time (which would otherwise make this parser + # O(N^2) with the input size). + buf = memoryview(buf).toreadonly() + + magic, = struct.unpack_from('{fmt}' + + decoder = struct.Struct(fmt) + size = decoder.size + + if array: + decoder = decoder.iter_unpack + def decode(buf, vlen): + total_size = size * vlen + _buf = buf[:total_size] + return ( + buf[total_size:], + decoder(_buf) + ) + else: + decoder = decoder.unpack_from + def decode(buf): + return ( + buf[size:], + decoder(buf) + ) + return decode + + decode_B = make_decode('B', array=False) + decode_BI = make_decode('BI', array=False) + decode_I = make_decode('I', array=False) + decode_III = make_decode('III', array=False) + decode_IIII = make_decode('IIII', array=False) + + decode_array_II = make_decode('II', array=True) + decode_array_III = make_decode('III', array=True) + decode_array_Ii = make_decode('II', array=True) + + + buf, (version,) = decode_B(buf) + if version != 1: + raise ValueError(f'BTF version {version} not supported') + + + buf, (flags, hdr_len) = decode_BI(buf) + + _, (type_off, type_len, str_off, str_len) = decode_IIII(buf) + + # We already parsed 8 bytes of the header + assert hdr_len >= 8 + data = buf[hdr_len - 8:] + + string_section = data[str_off:str_off + str_len] + _strings = string_section.tobytes().split(b'\x00') + + + i = 0 + strings = {} + for s in _strings: + strings[i] = s.decode('utf-8') + i += len(s) + 1 + + assert strings[0] == '' + + def resolve_name(i): + return strings[i] or None + + def parse_type(buf): + buf, (name_off, info, size_or_type) = decode_III(buf) + + name = resolve_name(name_off) + + vlen = info & 0xffff + # The doc is wrong: it states that bits 24-28 encode the BTF_KIND_*, + # but the values go beyond 16 these days so they effectively used the 2 + # subsequent bits. + kind = (info & (0b111111 << 24)) >> 24 + kind_flag = (info & (0b1 << 31)) >> 31 + + if kind == 0: + typ = BTFVoid() + + #define BTF_KIND_INT 1 /* Integer */ + elif kind == 1: + assert kind_flag == 0 + assert vlen == 0 + + buf, (meta,) = decode_I(buf) + + #define BTF_INT_ENCODING(VAL) (((VAL) & 0x0f000000) >> 24) + encoding = (meta & 0x0f000000) >> 24 + #define BTF_INT_OFFSET(VAL) (((VAL) & 0x00ff0000) >> 16) + offset = (meta & 0x00ff0000) >> 16 + #define BTF_INT_BITS(VAL) ((VAL) & 0x000000ff) + bits = meta & 0x000000ff + + encoding = BTFIntEncoding.from_int(encoding) + + typ = BTFInt( + name=name, + size=size_or_type, + encoding=encoding, + bit_offset=offset, + bits=bits + ) + + #define BTF_KIND_PTR 2 /* Pointer */ + elif kind == 2: + assert kind_flag == 0 + assert vlen == 0 + assert name is None + + typ = BTFPtr( + typ=_TypeRef(size_or_type), + size=None, + ) + + #define BTF_KIND_ARRAY 3 /* Array */ + elif kind == 3: + assert name is None + assert kind_flag == 0 + assert vlen == 0 + assert size_or_type == 0 + + buf, (typ, index_typ, nelems) = decode_III(buf) + + typ = BTFArray( + typ=_TypeRef(typ), + index_typ=_TypeRef(index_typ), + nelems=nelems, + ) + + #define BTF_KIND_STRUCT 4 /* Struct */ + #define BTF_KIND_UNION 5 /* Union */ + elif kind == 4 or kind == 5: + + if kind_flag == 0: + decode_offset = lambda offset: offset + decode_bits = lambda offset: 0 + elif kind_flag == 1: + #define BTF_MEMBER_BIT_OFFSET(val) ((val) & 0xffffff) + decode_offset = lambda offset: offset & 0xffffff + #define BTF_MEMBER_BITFIELD_SIZE(val) ((val) >> 24) + decode_bits = lambda offset: offset >> 24 + else: + raise ValueError(f'Unknown info.kind_flag == {kind_flag} for BTF_KIND_STRUCT/BTF_KIND_UNION') + + buf, members = decode_array_III(buf, vlen) + members = [ + BTFMember( + name=resolve_name(name_off), + typ=_TypeRef(typ), + bit_offset=decode_offset(offset), + bits=decode_bits(offset), + ) + for name_off, typ, offset in members + ] + + typ = (BTFStruct if kind == 4 else BTFUnion)( + name=name, + size=size_or_type, + members=members, + ) + + #define BTF_KIND_ENUM64 19 /* Enumeration up to 64-bit values */ + elif kind == 19: + size = size_or_type + signed = BTFSignedness.from_int(kind_flag) + nr_enumerators = vlen + assert size in (1, 2, 4, 8) + + def cast_value(v_low, v_high): + v = (v_high << 32) | v_low + + if signed == BTFSignedness.SIGNED and (v & (1 << (64 - 1))): + v = v - (1 << 64) + + return v + + buf, enumerators = decode_array_III(buf, vlen) + enumerators = { + resolve_name(name_off): cast_value(v_low, v_high) + for name_off, v_low, v_high in enumerators + } + + if enumerators: + typ = BTFEnum( + name=name, + signed=signed, + size=size, + enumerators=enumerators, + int_typ=None, + ) + # Forward decl of enum is a GNU extension, and seems to be encoded + # with an enum with vlen == 0 + else: + typ = BTFForwardDecl( + name=name, + typ_cls=BTFEnum, + ) + + #define BTF_KIND_ENUM 6 /* Enumeration up to 32-bit values */ + elif kind == 6: + size = size_or_type + signed = BTFSignedness.from_int(kind_flag) + nr_enumerators = vlen + assert size in (1, 2, 4, 8) + + buf, enumerators = decode_array_Ii(buf, vlen) + enumerators = { + resolve_name(name_off): v + for name_off, v in enumerators + } + + if enumerators: + typ = BTFEnum( + name=name, + signed=signed, + size=size, + enumerators=enumerators, + int_typ=None, + ) + # Forward decl of enum is a GNU extension, and seems to be encoded + # with an enum with vlen == 0 + else: + typ = BTFForwardDecl( + name=name, + typ_cls=BTFEnum, + ) + + #define BTF_KIND_FWD 7 /* Forward */ + elif kind == 7: + assert vlen == 0 + assert size_or_type == 0 + + if kind_flag == 0: + typ_cls = BTFStruct + elif kind_flag == 1: + typ_cls = BTFUnion + else: + raise ValueError(f'Unknown info.kind_flag value for BTF_KIND_FWD: {kind_flag}') + + typ = BTFForwardDecl(name=name, typ_cls=typ_cls) + + #define BTF_KIND_TYPEDEF 8 /* Typedef */ + elif kind == 8: + assert kind_flag == 0 + assert vlen == 0 + typ = BTFTypedef( + name=name, + typ=_TypeRef(size_or_type), + ) + + #define BTF_KIND_VOLATILE 9 /* Volatile */ + elif kind == 9: + assert name is None + assert kind_flag == 0 + assert vlen == 0 + typ = BTFVolatile(typ=_TypeRef(size_or_type)) + + #define BTF_KIND_CONST 10 /* Const */ + elif kind == 10: + assert name is None + assert kind_flag == 0 + assert vlen == 0 + typ = BTFConst(typ=_TypeRef(size_or_type)) + + #define BTF_KIND_RESTRICT 11 /* Restrict */ + elif kind == 11: + assert name is None + assert kind_flag == 0 + assert vlen == 0 + typ = BTFRestrict(typ=_TypeRef(size_or_type)) + + #define BTF_KIND_FUNC 12 /* Function */ + elif kind == 12: + assert kind_flag == 0 + assert vlen == 0 + + typ = BTFFunc( + name=name, + linkage=BTFFuncLinkage.from_int(vlen), + typ=_TypeRef(size_or_type), + ) + + #define BTF_KIND_FUNC_PROTO 13 /* Function Proto */ + elif kind == 13: + assert name is None + assert kind_flag == 0 + + buf, params = decode_array_II(buf, vlen) + params = [ + BTFParam( + name=resolve_name(name_off), + typ=_TypeRef(typ), + ) + for name_off, typ in params + ] + + if params and params[-1].name is None and params[-1].typ.index == 0: + params[-1] = BTFVarArgParam() + + typ = BTFFuncProto( + typ=_TypeRef(size_or_type), + params=params, + ) + + #define BTF_KIND_VAR 14 /* Variable */ + elif kind == 14: + assert kind_flag == 0 + assert vlen == 0 + + buf, (linkage,) = decode_I(buf) + + typ = BTFVar( + name=name, + typ=_TypeRef(size_or_type), + linkage=BTFVarLinkage.from_int(linkage), + ) + + #define BTF_KIND_DATASEC 15 /* Section */ + elif kind == 15: + assert kind_flag == 0 + + buf, variables = decode_array_III(buf, vlen) + variables = [ + BTFVarSecInfo( + typ=_TypeRef(typ), + offset=offset, + size=size, + ) + for typ, offset, size in variables + ] + + typ = BTFDataSec( + name=name, + size=size_or_type, + variables=variables, + ) + + #define BTF_KIND_FLOAT 16 /* Floating point */ + elif kind == 16: + size = size_or_type + assert kind_flag == 0 + assert vlen == 0 + assert size in (2, 4, 8, 12, 16) + + typ = BTFFloat( + name=name, + size=size, + ) + + #define BTF_KIND_DECL_TAG 17 /* Decl Tag */ + elif kind == 17: + assert kind_flag == 0 + assert vlen == 0 + + buf, (component_idx,) = decode_I(buf) + component_idx = None if component_idx == -1 else component_idx + + typ = BTFDeclTag( + tag=name, + typ=_TypeRef(size_or_type), + component_idx=component_idx, + ) + + #define BTF_KIND_TYPE_TAG 18 /* Type Tag */ + elif kind == 18: + assert name + assert kind_flag == 0 + assert vlen == 0 + + typ = BTFTypeTag( + tag=name, + typ=_TypeRef(size_or_type), + ) + + else: + raise ValueError(f'Unknown BTF kind: {kind}') + + return (buf, typ) + + + type_section = data[type_off:type_off + type_len] + typs = _scan(type_section, parse_type) + + # The type at index 0 is by definition void, and all indices are shifted by + # this. + typs.insert(0, BTFVoid()) + + fixup_refs = lambda typ: _TypeRef.fixup(typ, typs) + fixup_visited = set() + for i, typ in enumerate(typs): + typ.id = i + typ._map_typs(fixup_refs, visited=fixup_visited) + + def is_ptr_sized(typ): + if isinstance(typ, BTFTypedef): + return typ.name in ('intptr_t', 'uintptr_t', 'ptrdiff_t') + elif isinstance(typ, BTFInt): + return typ.name in ('long int', 'long unsigned int', 'long', 'unsigned long', 'long unsigned') + else: + return False + + uintptr_t = None + int_sizes = {} + for typ in typs: + # Look for typedefs of int types. Something like "uint16_t" should show up in that list + if isinstance(typ, BTFTypedef) and isinstance(underlying := typ.underlying, BTFInt) and not underlying.is_bitfield: + int_sizes.setdefault(typ.size, []).append(typ) + + if is_ptr_sized(typ): + uintptr_t = typ + + # Give priority to standard types + fixed_size_re = re.compile(r'u?int[0-9]+_t$') + def select_int(typs): + for typ in typs: + if fixed_size_re.match(typ.name): + return typ + + return typs[0] + + int_sizes = { + size: select_int(typs) + for size, typs in int_sizes.items() + } + + if uintptr_t: + ptr_size = uintptr_t.size + else: + raise ValueError(f'Could not find pointer-sized type in BTF types') + + for typ in typs: + if isinstance(typ, BTFPtr): + typ.size = ptr_size + elif isinstance(typ, BTFEnum): + typ.int_typ = int_sizes.get(typ.size, None) + + return typs + + +def parse_btf(buf, select_typ=None, rename_typ=None): + typs = _parse_btf(buf) + + if select_typ: + typs = list(filter(select_typ, typs)) + + reachable_typs = BTFType.reachable_from(typs) + else: + reachable_typs = set(typs) + + if rename_typ: + for typ in reachable_typs: + if isinstance(typ, (BTFStruct, BTFUnion, BTFEnum, BTFTypedef, BTFFunc, BTFForwardDecl)) and typ.name: + typ.name = rename_typ(typ) + + _dedup_names(reachable_typs) + + return typs + + +class _DeclCtx: + def __init__(self, fileobj): + self._i = 0 + self._memo = {} + self._fileobj = fileobj + + def write(self, x): + self._fileobj.write(x) + + def make_name(self): + self._i += 1 + return f'___BTF_HEADER_INTERNAL_TYPE_{self._i}' + + +class _IntrospectionCtx: + def __init__(self, fileobj): + self._exists_memo = set() + self._members_memo = set() + self._fileobj = fileobj + self._parent_typs = tuple() + + @contextlib.contextmanager + def with_parent(self, typ): + old = self._parent_typs + try: + if typ is None: + self._parent_typs = () + else: + self._parent_typs = (*self._parent_typs, typ) + + yield self + finally: + self._parent_typs = old + + def typ_exists(self, typ): + name = typ.name + key = typ + memo = self._exists_memo + + if name and key not in memo: + memo.add(key) + self._write(f'#define _TYPE_EXISTS_{typ._KIND}_{typ.name} 1\n') + + def typ_member(self, member_name): + if member_name: + memo = self._members_memo + + for typ in self._parent_typs: + key = (typ, member_name) + if key not in memo: + memo.add(key) + if (typ_name := typ.name): + self._write(f'#define _TYPE_HAS_MEMBER_{typ._KIND}_{typ_name}_LISA_SEPARATOR_{member_name} 1\n') + + def _write(self, x): + self._fileobj.write(x) + + +def _dedup_names(typs): + def dedup_typ_names(name, typs): + for typ in sorted(typs, key=attrgetter('id')): + typ.name = f'___DEDUP_{typ.id}_{name}' + + def dedup_enumerator_names(name, typs): + for typ in sorted(typs, key=attrgetter('id')): + # Preserving the enumerator orders is not necessary since we have + # explicit value for all of them in BTF + value = typ.enumerators.pop(name) + new_name = f'___DEDUP_{typ.id}_{name}' + typ.enumerators[new_name] = value + + typedef_names = {} + tagged_names = {} + enumerators = dict() + for typ in typs: + if isinstance(typ, BTFTypedef): + cat = typedef_names + elif isinstance(typ, (BTFStruct, BTFUnion, BTFEnum, BTFForwardDecl)): + cat = tagged_names + else: + continue + + name = typ.name + + if name: + try: + _typs = cat[name] + except KeyError: + _typs = [] + cat[name] = _typs + + _typs.append(typ) + + if isinstance(typ, BTFEnum): + for enumerator in typ.enumerators: + try: + _typs = enumerators[enumerator] + except KeyError: + _typs = [] + enumerators[enumerator] = _typs + + _typs.append(typ) + + for dup_names in (typedef_names, tagged_names): + for name, _typs in dup_names.items(): + if len(_typs) > 1: + dedup_typ_names(name, _typs) + + for enumerator, _typs in enumerators.items(): + if len(_typs) > 1: + dedup_enumerator_names(enumerator, _typs) + + +def dump_c(typs, fileobj=None, decls=True, introspection=True): + fileobj = fileobj or io.StringIO() + + introspection_ctx = _IntrospectionCtx(fileobj) + decl_ctx = _DeclCtx(fileobj) + + for typ in typs: + # Dump type declarations + if decls and isinstance(typ, _CDecl) and not isinstance(typ, _CBuiltin): + typ._dump_c_decls(decl_ctx) + + # Dump introspection macros + if introspection: + typ._dump_c_introspection(introspection_ctx) + + + if introspection: + fileobj.write('#define _TYPE_INTROSPECTION_INFO_AVAILABLE 1\n') + + fileobj.write('\n') + + return fileobj + +# vim :set tabstop=4 shiftwidth=4 expandtab textwidth=80 diff --git a/lisa/_kmod.py b/lisa/_kmod.py index 9e45366c3c56e5e50693f612c3f316490c3a7a4c..edf1055a5e6b00e8ce1d0dce24797c7a96a35195 100644 --- a/lisa/_kmod.py +++ b/lisa/_kmod.py @@ -352,6 +352,7 @@ def _make_build_chroot(cc, cross_compile, abi, bind_paths=None, version=None, ov 'python3', 'py3-pip', 'perl', + 'pahole', ] if is_clang(cc): @@ -2227,7 +2228,7 @@ class KmodSrc(Loggable): """ def get_files(root, dirs, files): for f in files: - yield (Path(root) / f).resolve() + yield (Path(root) / f) path = Path(path).resolve() src = { diff --git a/tests/assets/btf/1.btf.xz b/tests/assets/btf/1.btf.xz new file mode 100644 index 0000000000000000000000000000000000000000..e740b323f718d780cf0b7e5b905bbd25df032f98 Binary files /dev/null and b/tests/assets/btf/1.btf.xz differ diff --git a/tests/assets/btf/10.btf.xz b/tests/assets/btf/10.btf.xz new file mode 100644 index 0000000000000000000000000000000000000000..8091be210f3ae27f9232ebf15a2439296938d625 Binary files /dev/null and b/tests/assets/btf/10.btf.xz differ diff --git a/tests/assets/btf/2.btf.xz b/tests/assets/btf/2.btf.xz new file mode 100644 index 0000000000000000000000000000000000000000..419676db34edb723bd60fd0d280ec903c64bfc74 Binary files /dev/null and b/tests/assets/btf/2.btf.xz differ diff --git a/tests/assets/btf/3.btf.xz b/tests/assets/btf/3.btf.xz new file mode 100644 index 0000000000000000000000000000000000000000..adcc894bb040c591787bfcbdd189719c10b82564 Binary files /dev/null and b/tests/assets/btf/3.btf.xz differ diff --git a/tests/assets/btf/4.btf.xz b/tests/assets/btf/4.btf.xz new file mode 100644 index 0000000000000000000000000000000000000000..57bbb09fce765b72afae830ea3bdd92aff2f26ea Binary files /dev/null and b/tests/assets/btf/4.btf.xz differ diff --git a/tests/assets/btf/5.btf.xz b/tests/assets/btf/5.btf.xz new file mode 100644 index 0000000000000000000000000000000000000000..f97ea7ed703eb671494422c460ef04f444a33025 Binary files /dev/null and b/tests/assets/btf/5.btf.xz differ diff --git a/tests/assets/btf/6.btf.xz b/tests/assets/btf/6.btf.xz new file mode 100644 index 0000000000000000000000000000000000000000..5111a04f9172ff253251205f89fa505f69e40f79 Binary files /dev/null and b/tests/assets/btf/6.btf.xz differ diff --git a/tests/assets/btf/7.btf.xz b/tests/assets/btf/7.btf.xz new file mode 100644 index 0000000000000000000000000000000000000000..418e14379eb1232908ee17cf9a5d74f5934c6cfd Binary files /dev/null and b/tests/assets/btf/7.btf.xz differ diff --git a/tests/assets/btf/8.btf.xz b/tests/assets/btf/8.btf.xz new file mode 100644 index 0000000000000000000000000000000000000000..81c38b6eb8d7672db708f9c562441b196c92788d Binary files /dev/null and b/tests/assets/btf/8.btf.xz differ diff --git a/tests/assets/btf/9.btf.xz b/tests/assets/btf/9.btf.xz new file mode 100644 index 0000000000000000000000000000000000000000..e740b323f718d780cf0b7e5b905bbd25df032f98 Binary files /dev/null and b/tests/assets/btf/9.btf.xz differ diff --git a/tests/test_btf.py b/tests/test_btf.py new file mode 100644 index 0000000000000000000000000000000000000000..2ad12a3d3ecd29584b6341531d6ef1fc9ea9a784 --- /dev/null +++ b/tests/test_btf.py @@ -0,0 +1,83 @@ +# SPDX-License-Identifier: Apache-2.0 +# +# Copyright (C) 2023, Arm Limited and contributors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +from unittest import TestCase +from pathlib import Path +import os +import io +import subprocess +import lzma +import logging + +from lisa._btf import parse_btf, dump_c + +from .utils import ASSET_DIR + +def _test_btf(btf_path): + """ + Compile-test the dumped C header. Since this header contains + _Static_assert() to check member offsets and type sizes, this is almost + equivalent to a roundtrip test. + """ + with lzma.open(btf_path, 'rb') as f: + buf = f.read() + + typs = parse_btf(buf) + with io.StringIO() as header: + dump_c(typs, fileobj=header) + header.flush() + header = header.getvalue() + + header = header.encode('utf-8') + + cmd = ( + 'clang', + '--target=aarch64-linux-gnu-', + '-xc', + + '-std=gnu11', + '-pedantic', + '-fshort-wchar', + + '-Wall', + '-Wextra', + '-Wno-attributes', + '-Wno-zero-length-array', + '-Wno-pedantic', + + '-c', + '-o', '/dev/null', + '/dev/stdin', + ) + + subprocess.check_output(cmd, input=header) + + +class BTFDump(TestCase): + def test_c_dump(self): + btf_folder = Path(ASSET_DIR) / 'btf' + + paths = sorted( + Path(root) / filename + for (root, dirs, files) in os.walk(btf_folder) + for filename in files + ) + for btf_path in paths: + logging.info(f'Checking BTF blob: {btf_path}') + _test_btf(btf_path) + + diff --git a/tools/kmodules/lisa/introspection.json b/tools/kmodules/lisa/introspection.json new file mode 120000 index 0000000000000000000000000000000000000000..b9acba9a724f8daa3399ee34105680e761f41dc9 --- /dev/null +++ b/tools/kmodules/lisa/introspection.json @@ -0,0 +1 @@ +../../../lisa/_assets/kmodules/lisa/introspection.json \ No newline at end of file diff --git a/tools/kmodules/lisa/kernel_features.json b/tools/kmodules/lisa/kernel_features.json deleted file mode 120000 index ba08761b4d830f5d79ee248edd1fc869cdd4d07c..0000000000000000000000000000000000000000 --- a/tools/kmodules/lisa/kernel_features.json +++ /dev/null @@ -1 +0,0 @@ -../../../lisa/_assets/kmodules/lisa/kernel_features.json \ No newline at end of file diff --git a/tools/kmodules/lisa/lisa b/tools/kmodules/lisa/lisa new file mode 120000 index 0000000000000000000000000000000000000000..bc9aaba04213387df121db043b115bce662e89d0 --- /dev/null +++ b/tools/kmodules/lisa/lisa @@ -0,0 +1 @@ +../../../lisa/_assets/kmodules/lisa/lisa/ \ No newline at end of file diff --git a/tools/kmodules/lisa/make_introspection_header.sh b/tools/kmodules/lisa/make_introspection_header.sh deleted file mode 120000 index f1625b4e6ebad72b5ae3a52f1895b0fa923aeb05..0000000000000000000000000000000000000000 --- a/tools/kmodules/lisa/make_introspection_header.sh +++ /dev/null @@ -1 +0,0 @@ -../../../lisa/_assets/kmodules/lisa/make_introspection_header.sh \ No newline at end of file diff --git a/tools/kmodules/lisa/private_types.txt b/tools/kmodules/lisa/private_types.txt deleted file mode 120000 index b988b089ee4fa3226ae723c3e94c1dd6f423bd9a..0000000000000000000000000000000000000000 --- a/tools/kmodules/lisa/private_types.txt +++ /dev/null @@ -1 +0,0 @@ -../../../lisa/_assets/kmodules/lisa/private_types.txt \ No newline at end of file diff --git a/tools/kmodules/lisa/requirements.txt b/tools/kmodules/lisa/requirements.txt deleted file mode 120000 index 6e79167a5c2eb756203aef47c443f9cccc0257d1..0000000000000000000000000000000000000000 --- a/tools/kmodules/lisa/requirements.txt +++ /dev/null @@ -1 +0,0 @@ -../../../lisa/_assets/kmodules/lisa/requirements.txt \ No newline at end of file