Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'kbuild-v6.14' of git://git.kernel.org/pub/scm/linux/kernel/git/masahiroy/linux-kbuild

Pull Kbuild updates from Masahiro Yamada:

- Support multiple hook locations for maint scripts of Debian package

- Remove 'cpio' from the build tool requirement

- Introduce gendwarfksyms tool, which computes CRCs for export symbols
based on the DWARF information

- Support CONFIG_MODVERSIONS for Rust

- Resolve all conflicts in the genksyms parser

- Fix several syntax errors in genksyms

* tag 'kbuild-v6.14' of git://git.kernel.org/pub/scm/linux/kernel/git/masahiroy/linux-kbuild: (64 commits)
kbuild: fix Clang LTO with CONFIG_OBJTOOL=n
kbuild: Strip runtime const RELA sections correctly
kconfig: fix memory leak in sym_warn_unmet_dep()
kconfig: fix file name in warnings when loading KCONFIG_DEFCONFIG_LIST
genksyms: fix syntax error for attribute before init-declarator
genksyms: fix syntax error for builtin (u)int*x*_t types
genksyms: fix syntax error for attribute after 'union'
genksyms: fix syntax error for attribute after 'struct'
genksyms: fix syntax error for attribute after abstact_declarator
genksyms: fix syntax error for attribute before nested_declarator
genksyms: fix syntax error for attribute before abstract_declarator
genksyms: decouple ATTRIBUTE_PHRASE from type-qualifier
genksyms: record attributes consistently for init-declarator
genksyms: restrict direct-declarator to take one parameter-type-list
genksyms: restrict direct-abstract-declarator to take one parameter-type-list
genksyms: remove Makefile hack
genksyms: fix last 3 shift/reduce conflicts
genksyms: fix 6 shift/reduce conflicts and 5 reduce/reduce conflicts
genksyms: reduce type_qualifier directly to decl_specifier
genksyms: rename cvar_qualifier to type_qualifier
...

+4492 -307
+308
Documentation/kbuild/gendwarfksyms.rst
··· 1 + ======================= 2 + DWARF module versioning 3 + ======================= 4 + 5 + 1. Introduction 6 + =============== 7 + 8 + When CONFIG_MODVERSIONS is enabled, symbol versions for modules 9 + are typically calculated from preprocessed source code using the 10 + **genksyms** tool. However, this is incompatible with languages such 11 + as Rust, where the source code has insufficient information about 12 + the resulting ABI. With CONFIG_GENDWARFKSYMS (and CONFIG_DEBUG_INFO) 13 + selected, **gendwarfksyms** is used instead to calculate symbol versions 14 + from the DWARF debugging information, which contains the necessary 15 + details about the final module ABI. 16 + 17 + 1.1. Usage 18 + ========== 19 + 20 + gendwarfksyms accepts a list of object files on the command line, and a 21 + list of symbol names (one per line) in standard input:: 22 + 23 + Usage: gendwarfksyms [options] elf-object-file ... < symbol-list 24 + 25 + Options: 26 + -d, --debug Print debugging information 27 + --dump-dies Dump DWARF DIE contents 28 + --dump-die-map Print debugging information about die_map changes 29 + --dump-types Dump type strings 30 + --dump-versions Dump expanded type strings used for symbol versions 31 + -s, --stable Support kABI stability features 32 + -T, --symtypes file Write a symtypes file 33 + -h, --help Print this message 34 + 35 + 36 + 2. Type information availability 37 + ================================ 38 + 39 + While symbols are typically exported in the same translation unit (TU) 40 + where they're defined, it's also perfectly fine for a TU to export 41 + external symbols. For example, this is done when calculating symbol 42 + versions for exports in stand-alone assembly code. 43 + 44 + To ensure the compiler emits the necessary DWARF type information in the 45 + TU where symbols are actually exported, gendwarfksyms adds a pointer 46 + to exported symbols in the `EXPORT_SYMBOL()` macro using the following 47 + macro:: 48 + 49 + #define __GENDWARFKSYMS_EXPORT(sym) \ 50 + static typeof(sym) *__gendwarfksyms_ptr_##sym __used \ 51 + __section(".discard.gendwarfksyms") = &sym; 52 + 53 + 54 + When a symbol pointer is found in DWARF, gendwarfksyms can use its 55 + type for calculating symbol versions even if the symbol is defined 56 + elsewhere. The name of the symbol pointer is expected to start with 57 + `__gendwarfksyms_ptr_`, followed by the name of the exported symbol. 58 + 59 + 3. Symtypes output format 60 + ========================= 61 + 62 + Similarly to genksyms, gendwarfksyms supports writing a symtypes 63 + file for each processed object that contain types for exported 64 + symbols and each referenced type that was used in calculating symbol 65 + versions. These files can be useful when trying to determine what 66 + exactly caused symbol versions to change between builds. To generate 67 + symtypes files during a kernel build, set `KBUILD_SYMTYPES=1`. 68 + 69 + Matching the existing format, the first column of each line contains 70 + either a type reference or a symbol name. Type references have a 71 + one-letter prefix followed by "#" and the name of the type. Four 72 + reference types are supported:: 73 + 74 + e#<type> = enum 75 + s#<type> = struct 76 + t#<type> = typedef 77 + u#<type> = union 78 + 79 + Type names with spaces in them are wrapped in single quotes, e.g.:: 80 + 81 + s#'core::result::Result<u8, core::num::error::ParseIntError>' 82 + 83 + The rest of the line contains a type string. Unlike with genksyms that 84 + produces C-style type strings, gendwarfksyms uses the same simple parsed 85 + DWARF format produced by **--dump-dies**, but with type references 86 + instead of fully expanded strings. 87 + 88 + 4. Maintaining a stable kABI 89 + ============================ 90 + 91 + Distribution maintainers often need the ability to make ABI compatible 92 + changes to kernel data structures due to LTS updates or backports. Using 93 + the traditional `#ifndef __GENKSYMS__` to hide these changes from symbol 94 + versioning won't work when processing object files. To support this 95 + use case, gendwarfksyms provides kABI stability features designed to 96 + hide changes that won't affect the ABI when calculating versions. These 97 + features are all gated behind the **--stable** command line flag and are 98 + not used in the mainline kernel. To use stable features during a kernel 99 + build, set `KBUILD_GENDWARFKSYMS_STABLE=1`. 100 + 101 + Examples for using these features are provided in the 102 + **scripts/gendwarfksyms/examples** directory, including helper macros 103 + for source code annotation. Note that as these features are only used to 104 + transform the inputs for symbol versioning, the user is responsible for 105 + ensuring that their changes actually won't break the ABI. 106 + 107 + 4.1. kABI rules 108 + =============== 109 + 110 + kABI rules allow distributions to fine-tune certain parts 111 + of gendwarfksyms output and thus control how symbol 112 + versions are calculated. These rules are defined in the 113 + `.discard.gendwarfksyms.kabi_rules` section of the object file and 114 + consist of simple null-terminated strings with the following structure:: 115 + 116 + version\0type\0target\0value\0 117 + 118 + This string sequence is repeated as many times as needed to express all 119 + the rules. The fields are as follows: 120 + 121 + - `version`: Ensures backward compatibility for future changes to the 122 + structure. Currently expected to be "1". 123 + - `type`: Indicates the type of rule being applied. 124 + - `target`: Specifies the target of the rule, typically the fully 125 + qualified name of the DWARF Debugging Information Entry (DIE). 126 + - `value`: Provides rule-specific data. 127 + 128 + The following helper macro, for example, can be used to specify rules 129 + in the source code:: 130 + 131 + #define __KABI_RULE(hint, target, value) \ 132 + static const char __PASTE(__gendwarfksyms_rule_, \ 133 + __COUNTER__)[] __used __aligned(1) \ 134 + __section(".discard.gendwarfksyms.kabi_rules") = \ 135 + "1\0" #hint "\0" #target "\0" #value 136 + 137 + 138 + Currently, only the rules discussed in this section are supported, but 139 + the format is extensible enough to allow further rules to be added as 140 + need arises. 141 + 142 + 4.1.1. Managing definition visibility 143 + ===================================== 144 + 145 + A declaration can change into a full definition when additional includes 146 + are pulled into the translation unit. This changes the versions of any 147 + symbol that references the type even if the ABI remains unchanged. As 148 + it may not be possible to drop includes without breaking the build, the 149 + `declonly` rule can be used to specify a type as declaration-only, even 150 + if the debugging information contains the full definition. 151 + 152 + The rule fields are expected to be as follows: 153 + 154 + - `type`: "declonly" 155 + - `target`: The fully qualified name of the target data structure 156 + (as shown in **--dump-dies** output). 157 + - `value`: This field is ignored. 158 + 159 + Using the `__KABI_RULE` macro, this rule can be defined as:: 160 + 161 + #define KABI_DECLONLY(fqn) __KABI_RULE(declonly, fqn, ) 162 + 163 + Example usage:: 164 + 165 + struct s { 166 + /* definition */ 167 + }; 168 + 169 + KABI_DECLONLY(s); 170 + 171 + 4.1.2. Adding enumerators 172 + ========================= 173 + 174 + For enums, all enumerators and their values are included in calculating 175 + symbol versions, which becomes a problem if we later need to add more 176 + enumerators without changing symbol versions. The `enumerator_ignore` 177 + rule allows us to hide named enumerators from the input. 178 + 179 + The rule fields are expected to be as follows: 180 + 181 + - `type`: "enumerator_ignore" 182 + - `target`: The fully qualified name of the target enum 183 + (as shown in **--dump-dies** output) and the name of the 184 + enumerator field separated by a space. 185 + - `value`: This field is ignored. 186 + 187 + Using the `__KABI_RULE` macro, this rule can be defined as:: 188 + 189 + #define KABI_ENUMERATOR_IGNORE(fqn, field) \ 190 + __KABI_RULE(enumerator_ignore, fqn field, ) 191 + 192 + Example usage:: 193 + 194 + enum e { 195 + A, B, C, D, 196 + }; 197 + 198 + KABI_ENUMERATOR_IGNORE(e, B); 199 + KABI_ENUMERATOR_IGNORE(e, C); 200 + 201 + If the enum additionally includes an end marker and new values must 202 + be added in the middle, we may need to use the old value for the last 203 + enumerator when calculating versions. The `enumerator_value` rule allows 204 + us to override the value of an enumerator for version calculation: 205 + 206 + - `type`: "enumerator_value" 207 + - `target`: The fully qualified name of the target enum 208 + (as shown in **--dump-dies** output) and the name of the 209 + enumerator field separated by a space. 210 + - `value`: Integer value used for the field. 211 + 212 + Using the `__KABI_RULE` macro, this rule can be defined as:: 213 + 214 + #define KABI_ENUMERATOR_VALUE(fqn, field, value) \ 215 + __KABI_RULE(enumerator_value, fqn field, value) 216 + 217 + Example usage:: 218 + 219 + enum e { 220 + A, B, C, LAST, 221 + }; 222 + 223 + KABI_ENUMERATOR_IGNORE(e, C); 224 + KABI_ENUMERATOR_VALUE(e, LAST, 2); 225 + 226 + 4.3. Adding structure members 227 + ============================= 228 + 229 + Perhaps the most common ABI compatible change is adding a member to a 230 + kernel data structure. When changes to a structure are anticipated, 231 + distribution maintainers can pre-emptively reserve space in the 232 + structure and take it into use later without breaking the ABI. If 233 + changes are needed to data structures without reserved space, existing 234 + alignment holes can potentially be used instead. While kABI rules could 235 + be added for these type of changes, using unions is typically a more 236 + natural method. This section describes gendwarfksyms support for using 237 + reserved space in data structures and hiding members that don't change 238 + the ABI when calculating symbol versions. 239 + 240 + 4.3.1. Reserving space and replacing members 241 + ============================================ 242 + 243 + Space is typically reserved for later use by appending integer types, or 244 + arrays, to the end of the data structure, but any type can be used. Each 245 + reserved member needs a unique name, but as the actual purpose is usually 246 + not known at the time the space is reserved, for convenience, names that 247 + start with `__kabi_` are left out when calculating symbol versions:: 248 + 249 + struct s { 250 + long a; 251 + long __kabi_reserved_0; /* reserved for future use */ 252 + }; 253 + 254 + The reserved space can be taken into use by wrapping the member in a 255 + union, which includes the original type and the replacement member:: 256 + 257 + struct s { 258 + long a; 259 + union { 260 + long __kabi_reserved_0; /* original type */ 261 + struct b b; /* replaced field */ 262 + }; 263 + }; 264 + 265 + If the `__kabi_` naming scheme was used when reserving space, the name 266 + of the first member of the union must start with `__kabi_reserved`. This 267 + ensures the original type is used when calculating versions, but the name 268 + is again left out. The rest of the union is ignored. 269 + 270 + If we're replacing a member that doesn't follow this naming convention, 271 + we also need to preserve the original name to avoid changing versions, 272 + which we can do by changing the first union member's name to start with 273 + `__kabi_renamed` followed by the original name. 274 + 275 + The examples include `KABI_(RESERVE|USE|REPLACE)*` macros that help 276 + simplify the process and also ensure the replacement member is correctly 277 + aligned and its size won't exceed the reserved space. 278 + 279 + 4.3.2. Hiding members 280 + ===================== 281 + 282 + Predicting which structures will require changes during the support 283 + timeframe isn't always possible, in which case one might have to resort 284 + to placing new members into existing alignment holes:: 285 + 286 + struct s { 287 + int a; 288 + /* a 4-byte alignment hole */ 289 + unsigned long b; 290 + }; 291 + 292 + 293 + While this won't change the size of the data structure, one needs to 294 + be able to hide the added members from symbol versioning. Similarly 295 + to reserved fields, this can be accomplished by wrapping the added 296 + member to a union where one of the fields has a name starting with 297 + `__kabi_ignored`:: 298 + 299 + struct s { 300 + int a; 301 + union { 302 + char __kabi_ignored_0; 303 + int n; 304 + }; 305 + unsigned long b; 306 + }; 307 + 308 + With **--stable**, both versions produce the same symbol version.
+1
Documentation/kbuild/index.rst
··· 21 21 reproducible-builds 22 22 gcc-plugins 23 23 llvm 24 + gendwarfksyms 24 25 25 26 .. only:: subproject and html 26 27
+20
Documentation/kbuild/modules.rst
··· 423 423 1) It lists all exported symbols from vmlinux and all modules. 424 424 2) It lists the CRC if CONFIG_MODVERSIONS is enabled. 425 425 426 + Version Information Formats 427 + --------------------------- 428 + 429 + Exported symbols have information stored in __ksymtab or __ksymtab_gpl 430 + sections. Symbol names and namespaces are stored in __ksymtab_strings, 431 + using a format similar to the string table used for ELF. If 432 + CONFIG_MODVERSIONS is enabled, the CRCs corresponding to exported 433 + symbols will be added to the __kcrctab or __kcrctab_gpl. 434 + 435 + If CONFIG_BASIC_MODVERSIONS is enabled (default with 436 + CONFIG_MODVERSIONS), imported symbols will have their symbol name and 437 + CRC stored in the __versions section of the importing module. This 438 + mode only supports symbols of length up to 64 bytes. 439 + 440 + If CONFIG_EXTENDED_MODVERSIONS is enabled (required to enable both 441 + CONFIG_MODVERSIONS and CONFIG_RUST at the same time), imported symbols 442 + will have their symbol name recorded in the __version_ext_names 443 + section as a series of concatenated, null-terminated strings. CRCs for 444 + these symbols will be recorded in the __version_ext_crcs section. 445 + 426 446 Symbols and External Modules 427 447 ---------------------------- 428 448
-6
Documentation/process/changes.rst
··· 59 59 openssl & libcrypto 1.0.0 openssl version 60 60 bc 1.06.95 bc --version 61 61 Sphinx\ [#f1]_ 2.4.4 sphinx-build --version 62 - cpio any cpio --version 63 62 GNU tar 1.28 tar --version 64 63 gtags (optional) 6.6.5 gtags --version 65 64 mkimage (optional) 2017.01 mkimage --version ··· 534 535 ------ 535 536 536 537 - <https://www.mcelog.org/> 537 - 538 - cpio 539 - ---- 540 - 541 - - <https://www.gnu.org/software/cpio/> 542 538 543 539 Networking 544 540 **********
+7
MAINTAINERS
··· 9641 9641 T: git git://linuxtv.org/media.git 9642 9642 F: drivers/media/radio/radio-gemtek* 9643 9643 9644 + GENDWARFKSYMS 9645 + M: Sami Tolvanen <samitolvanen@google.com> 9646 + L: linux-modules@vger.kernel.org 9647 + L: linux-kbuild@vger.kernel.org 9648 + S: Maintained 9649 + F: scripts/gendwarfksyms/ 9650 + 9644 9651 GENERIC ARCHITECTURE TOPOLOGY 9645 9652 M: Sudeep Holla <sudeep.holla@arm.com> 9646 9653 L: linux-kernel@vger.kernel.org
+4 -3
arch/arc/Kconfig
··· 18 18 select ARCH_SUPPORTS_ATOMIC_RMW if ARC_HAS_LLSC 19 19 select ARCH_32BIT_OFF_T 20 20 select BUILDTIME_TABLE_SORT 21 + select GENERIC_BUILTIN_DTB 21 22 select CLONE_BACKWARDS 22 23 select COMMON_CLK 23 24 select DMA_DIRECT_REMAP ··· 551 550 part of static keys (jump labels) related code. 552 551 endif 553 552 554 - config ARC_BUILTIN_DTB_NAME 553 + config BUILTIN_DTB_NAME 555 554 string "Built in DTB" 555 + default "nsim_700" 556 556 help 557 - Set the name of the DTB to embed in the vmlinux binary 558 - Leaving it blank selects the "nsim_700" dtb. 557 + Set the name of the DTB to embed in the vmlinux binary. 559 558 560 559 endmenu # "ARC Architecture Configuration" 561 560
-3
arch/arc/Makefile
··· 82 82 KBUILD_AFLAGS += $(KBUILD_CFLAGS) 83 83 KBUILD_LDFLAGS += $(ldflags-y) 84 84 85 - # w/o this dtb won't embed into kernel binary 86 - core-y += arch/arc/boot/dts/ 87 - 88 85 core-y += arch/arc/plat-sim/ 89 86 core-$(CONFIG_ARC_PLAT_TB10X) += arch/arc/plat-tb10x/ 90 87 core-$(CONFIG_ARC_PLAT_AXS10X) += arch/arc/plat-axs10x/
+1 -8
arch/arc/boot/dts/Makefile
··· 1 1 # SPDX-License-Identifier: GPL-2.0 2 - # Built-in dtb 3 - builtindtb-y := nsim_700 4 2 5 - ifneq ($(CONFIG_ARC_BUILTIN_DTB_NAME),) 6 - builtindtb-y := $(CONFIG_ARC_BUILTIN_DTB_NAME) 7 - endif 8 - 9 - obj-y += $(builtindtb-y).dtb.o 10 - dtb-y := $(builtindtb-y).dtb 3 + dtb-y := $(addsuffix .dtb, $(CONFIG_BUILTIN_DTB_NAME)) 11 4 12 5 # for CONFIG_OF_ALL_DTBS test 13 6 dtb- := $(patsubst $(src)/%.dts,%.dtb, $(wildcard $(src)/*.dts))
+1 -1
arch/arc/configs/axs101_defconfig
··· 23 23 CONFIG_ARC_PLAT_AXS10X=y 24 24 CONFIG_AXS101=y 25 25 CONFIG_ARC_CACHE_LINE_SHIFT=5 26 - CONFIG_ARC_BUILTIN_DTB_NAME="axs101" 26 + CONFIG_BUILTIN_DTB_NAME="axs101" 27 27 CONFIG_PREEMPT=y 28 28 # CONFIG_COMPACTION is not set 29 29 CONFIG_NET=y
+1 -1
arch/arc/configs/axs103_defconfig
··· 22 22 CONFIG_ARC_PLAT_AXS10X=y 23 23 CONFIG_AXS103=y 24 24 CONFIG_ISA_ARCV2=y 25 - CONFIG_ARC_BUILTIN_DTB_NAME="axs103" 25 + CONFIG_BUILTIN_DTB_NAME="axs103" 26 26 CONFIG_PREEMPT=y 27 27 # CONFIG_COMPACTION is not set 28 28 CONFIG_NET=y
+1 -1
arch/arc/configs/axs103_smp_defconfig
··· 22 22 CONFIG_AXS103=y 23 23 CONFIG_ISA_ARCV2=y 24 24 CONFIG_SMP=y 25 - CONFIG_ARC_BUILTIN_DTB_NAME="axs103_idu" 25 + CONFIG_BUILTIN_DTB_NAME="axs103_idu" 26 26 CONFIG_PREEMPT=y 27 27 # CONFIG_COMPACTION is not set 28 28 CONFIG_NET=y
+1 -1
arch/arc/configs/haps_hs_defconfig
··· 14 14 CONFIG_EXPERT=y 15 15 CONFIG_PERF_EVENTS=y 16 16 # CONFIG_COMPAT_BRK is not set 17 - CONFIG_ARC_BUILTIN_DTB_NAME="haps_hs" 17 + CONFIG_BUILTIN_DTB_NAME="haps_hs" 18 18 CONFIG_MODULES=y 19 19 # CONFIG_BLK_DEV_BSG is not set 20 20 # CONFIG_COMPACTION is not set
+1 -1
arch/arc/configs/haps_hs_smp_defconfig
··· 16 16 # CONFIG_VM_EVENT_COUNTERS is not set 17 17 # CONFIG_COMPAT_BRK is not set 18 18 CONFIG_SMP=y 19 - CONFIG_ARC_BUILTIN_DTB_NAME="haps_hs_idu" 19 + CONFIG_BUILTIN_DTB_NAME="haps_hs_idu" 20 20 CONFIG_KPROBES=y 21 21 CONFIG_MODULES=y 22 22 # CONFIG_BLK_DEV_BSG is not set
+1 -1
arch/arc/configs/hsdk_defconfig
··· 20 20 CONFIG_SMP=y 21 21 CONFIG_LINUX_LINK_BASE=0x90000000 22 22 CONFIG_LINUX_RAM_BASE=0x80000000 23 - CONFIG_ARC_BUILTIN_DTB_NAME="hsdk" 23 + CONFIG_BUILTIN_DTB_NAME="hsdk" 24 24 CONFIG_PREEMPT=y 25 25 # CONFIG_COMPACTION is not set 26 26 CONFIG_NET=y
+1 -1
arch/arc/configs/nsim_700_defconfig
··· 17 17 # CONFIG_SLUB_DEBUG is not set 18 18 # CONFIG_COMPAT_BRK is not set 19 19 CONFIG_ISA_ARCOMPACT=y 20 - CONFIG_ARC_BUILTIN_DTB_NAME="nsim_700" 20 + CONFIG_BUILTIN_DTB_NAME="nsim_700" 21 21 CONFIG_KPROBES=y 22 22 CONFIG_MODULES=y 23 23 # CONFIG_BLK_DEV_BSG is not set
+1 -1
arch/arc/configs/nsimosci_defconfig
··· 19 19 CONFIG_KPROBES=y 20 20 CONFIG_MODULES=y 21 21 # CONFIG_BLK_DEV_BSG is not set 22 - CONFIG_ARC_BUILTIN_DTB_NAME="nsimosci" 22 + CONFIG_BUILTIN_DTB_NAME="nsimosci" 23 23 # CONFIG_COMPACTION is not set 24 24 CONFIG_NET=y 25 25 CONFIG_PACKET=y
+1 -1
arch/arc/configs/nsimosci_hs_defconfig
··· 19 19 CONFIG_MODULES=y 20 20 # CONFIG_BLK_DEV_BSG is not set 21 21 CONFIG_ISA_ARCV2=y 22 - CONFIG_ARC_BUILTIN_DTB_NAME="nsimosci_hs" 22 + CONFIG_BUILTIN_DTB_NAME="nsimosci_hs" 23 23 # CONFIG_COMPACTION is not set 24 24 CONFIG_NET=y 25 25 CONFIG_PACKET=y
+1 -1
arch/arc/configs/nsimosci_hs_smp_defconfig
··· 16 16 CONFIG_ISA_ARCV2=y 17 17 CONFIG_SMP=y 18 18 # CONFIG_ARC_TIMERS_64BIT is not set 19 - CONFIG_ARC_BUILTIN_DTB_NAME="nsimosci_hs_idu" 19 + CONFIG_BUILTIN_DTB_NAME="nsimosci_hs_idu" 20 20 CONFIG_PREEMPT=y 21 21 # CONFIG_COMPACTION is not set 22 22 CONFIG_NET=y
+1 -1
arch/arc/configs/tb10x_defconfig
··· 26 26 CONFIG_ARC_PLAT_TB10X=y 27 27 CONFIG_ARC_CACHE_LINE_SHIFT=5 28 28 CONFIG_HZ=250 29 - CONFIG_ARC_BUILTIN_DTB_NAME="abilis_tb100_dvk" 29 + CONFIG_BUILTIN_DTB_NAME="abilis_tb100_dvk" 30 30 CONFIG_PREEMPT_VOLUNTARY=y 31 31 # CONFIG_COMPACTION is not set 32 32 CONFIG_NET=y
+1 -1
arch/arc/configs/vdk_hs38_defconfig
··· 13 13 CONFIG_ARC_PLAT_AXS10X=y 14 14 CONFIG_AXS103=y 15 15 CONFIG_ISA_ARCV2=y 16 - CONFIG_ARC_BUILTIN_DTB_NAME="vdk_hs38" 16 + CONFIG_BUILTIN_DTB_NAME="vdk_hs38" 17 17 CONFIG_PREEMPT=y 18 18 CONFIG_NET=y 19 19 CONFIG_PACKET=y
+1 -1
arch/arc/configs/vdk_hs38_smp_defconfig
··· 15 15 CONFIG_ISA_ARCV2=y 16 16 CONFIG_SMP=y 17 17 # CONFIG_ARC_TIMERS_64BIT is not set 18 - CONFIG_ARC_BUILTIN_DTB_NAME="vdk_hs38_smp" 18 + CONFIG_BUILTIN_DTB_NAME="vdk_hs38_smp" 19 19 CONFIG_PREEMPT=y 20 20 CONFIG_NET=y 21 21 CONFIG_PACKET=y
+22 -2
arch/powerpc/kernel/module_64.c
··· 369 369 } 370 370 } 371 371 372 + /* Same as normal versions, remove a leading dot if present. */ 373 + static void dedotify_ext_version_names(char *str_seq, unsigned long size) 374 + { 375 + unsigned long out = 0; 376 + unsigned long in; 377 + char last = '\0'; 378 + 379 + for (in = 0; in < size; in++) { 380 + /* Skip one leading dot */ 381 + if (last == '\0' && str_seq[in] == '.') 382 + in++; 383 + last = str_seq[in]; 384 + str_seq[out++] = last; 385 + } 386 + /* Zero the trailing portion of the names table for robustness */ 387 + memset(&str_seq[out], 0, size - out); 388 + } 389 + 372 390 /* 373 391 * Undefined symbols which refer to .funcname, hack to funcname. Make .TOC. 374 392 * seem to be defined (value set later). ··· 456 438 me->arch.toc_section = i; 457 439 if (sechdrs[i].sh_addralign < 8) 458 440 sechdrs[i].sh_addralign = 8; 459 - } 460 - else if (strcmp(secstrings+sechdrs[i].sh_name,"__versions")==0) 441 + } else if (strcmp(secstrings + sechdrs[i].sh_name, "__versions") == 0) 461 442 dedotify_versions((void *)hdr + sechdrs[i].sh_offset, 462 443 sechdrs[i].sh_size); 444 + else if (strcmp(secstrings + sechdrs[i].sh_name, "__version_ext_names") == 0) 445 + dedotify_ext_version_names((void *)hdr + sechdrs[i].sh_offset, 446 + sechdrs[i].sh_size); 463 447 464 448 if (sechdrs[i].sh_type == SHT_SYMTAB) 465 449 dedotify((void *)hdr + sechdrs[i].sh_offset,
+15
include/linux/export.h
··· 52 52 53 53 #else 54 54 55 + #ifdef CONFIG_GENDWARFKSYMS 56 + /* 57 + * With CONFIG_GENDWARFKSYMS, ensure the compiler emits debugging 58 + * information for all exported symbols, including those defined in 59 + * different TUs, by adding a __gendwarfksyms_ptr_<symbol> pointer 60 + * that's discarded during the final link. 61 + */ 62 + #define __GENDWARFKSYMS_EXPORT(sym) \ 63 + static typeof(sym) *__gendwarfksyms_ptr_##sym __used \ 64 + __section(".discard.gendwarfksyms") = &sym; 65 + #else 66 + #define __GENDWARFKSYMS_EXPORT(sym) 67 + #endif 68 + 55 69 #define __EXPORT_SYMBOL(sym, license, ns) \ 56 70 extern typeof(sym) sym; \ 57 71 __ADDRESSABLE(sym) \ 72 + __GENDWARFKSYMS_EXPORT(sym) \ 58 73 asm(__stringify(___EXPORT_SYMBOL(sym, license, ns))) 59 74 60 75 #endif
+2 -2
include/linux/module.h
··· 430 430 431 431 /* Exported symbols */ 432 432 const struct kernel_symbol *syms; 433 - const s32 *crcs; 433 + const u32 *crcs; 434 434 unsigned int num_syms; 435 435 436 436 #ifdef CONFIG_ARCH_USES_CFI_TRAPS ··· 448 448 /* GPL-only exported symbols. */ 449 449 unsigned int num_gpl_syms; 450 450 const struct kernel_symbol *gpl_syms; 451 - const s32 *gpl_crcs; 451 + const u32 *gpl_crcs; 452 452 bool using_gplonly_symbols; 453 453 454 454 #ifdef CONFIG_MODULE_SIG
+2 -1
init/Kconfig
··· 1969 1969 bool "Rust support" 1970 1970 depends on HAVE_RUST 1971 1971 depends on RUST_IS_AVAILABLE 1972 - depends on !MODVERSIONS 1972 + select EXTENDED_MODVERSIONS if MODVERSIONS 1973 + depends on !MODVERSIONS || GENDWARFKSYMS 1973 1974 depends on !GCC_PLUGIN_RANDSTRUCT 1974 1975 depends on !RANDSTRUCT 1975 1976 depends on !DEBUG_INFO_BTF || PAHOLE_HAS_LANG_EXCLUDE
+21 -21
kernel/gen_kheaders.sh
··· 7 7 sfile="$(readlink -f "$0")" 8 8 outdir="$(pwd)" 9 9 tarfile=$1 10 - cpio_dir=$outdir/${tarfile%/*}/.tmp_cpio_dir 10 + tmpdir=$outdir/${tarfile%/*}/.tmp_dir 11 11 12 12 dir_list=" 13 13 include/ 14 14 arch/$SRCARCH/include/ 15 15 " 16 - 17 - if ! command -v cpio >/dev/null; then 18 - echo >&2 "***" 19 - echo >&2 "*** 'cpio' could not be found." 20 - echo >&2 "***" 21 - exit 1 22 - fi 23 16 24 17 # Support incremental builds by skipping archive generation 25 18 # if timestamps of files being archived are not changed. ··· 41 48 # check include/generated/autoconf.h explicitly. 42 49 # 43 50 # Ignore them for md5 calculation to avoid pointless regeneration. 44 - headers_md5="$(find $all_dirs -name "*.h" | 45 - grep -v "include/generated/utsversion.h" | 46 - grep -v "include/generated/autoconf.h" | 51 + headers_md5="$(find $all_dirs -name "*.h" -a \ 52 + ! -path include/generated/utsversion.h -a \ 53 + ! -path include/generated/autoconf.h | 47 54 xargs ls -l | md5sum | cut -d ' ' -f1)" 48 55 49 56 # Any changes to this script will also cause a rebuild of the archive. ··· 58 65 59 66 echo " GEN $tarfile" 60 67 61 - rm -rf $cpio_dir 62 - mkdir $cpio_dir 68 + rm -rf "${tmpdir}" 69 + mkdir "${tmpdir}" 63 70 64 71 if [ "$building_out_of_srctree" ]; then 65 72 ( 66 73 cd $srctree 67 74 for f in $dir_list 68 75 do find "$f" -name "*.h"; 69 - done | cpio --quiet -pd $cpio_dir 76 + done | tar -c -f - -T - | tar -xf - -C "${tmpdir}" 70 77 ) 71 78 fi 72 79 73 - # The second CPIO can complain if files already exist which can happen with out 74 - # of tree builds having stale headers in srctree. Just silence CPIO for now. 75 80 for f in $dir_list; 76 81 do find "$f" -name "*.h"; 77 - done | cpio --quiet -pdu $cpio_dir >/dev/null 2>&1 82 + done | tar -c -f - -T - | tar -xf - -C "${tmpdir}" 83 + 84 + # Always exclude include/generated/utsversion.h 85 + # Otherwise, the contents of the tarball may vary depending on the build steps. 86 + rm -f "${tmpdir}/include/generated/utsversion.h" 78 87 79 88 # Remove comments except SDPX lines 80 - find $cpio_dir -type f -print0 | 81 - xargs -0 -P8 -n1 perl -pi -e 'BEGIN {undef $/;}; s/\/\*((?!SPDX).)*?\*\///smg;' 89 + # Use a temporary file to store directory contents to prevent find/xargs from 90 + # seeing temporary files created by perl. 91 + find "${tmpdir}" -type f -print0 > "${tmpdir}.contents.txt" 92 + xargs -0 -P8 -n1 \ 93 + perl -pi -e 'BEGIN {undef $/;}; s/\/\*((?!SPDX).)*?\*\///smg;' \ 94 + < "${tmpdir}.contents.txt" 95 + rm -f "${tmpdir}.contents.txt" 82 96 83 97 # Create archive and try to normalize metadata for reproducibility. 84 98 tar "${KBUILD_BUILD_TIMESTAMP:+--mtime=$KBUILD_BUILD_TIMESTAMP}" \ 85 99 --exclude=".__afs*" --exclude=".nfs*" \ 86 100 --owner=0 --group=0 --sort=name --numeric-owner --mode=u=rw,go=r,a+X \ 87 - -I $XZ -cf $tarfile -C $cpio_dir/ . > /dev/null 101 + -I $XZ -cf $tarfile -C "${tmpdir}/" . > /dev/null 88 102 89 103 echo $headers_md5 > kernel/kheaders.md5 90 104 echo "$this_file_md5" >> kernel/kheaders.md5 91 105 echo "$(md5sum $tarfile | cut -d ' ' -f1)" >> kernel/kheaders.md5 92 106 93 - rm -rf $cpio_dir 107 + rm -rf "${tmpdir}"
+55
kernel/module/Kconfig
··· 169 169 make them incompatible with the kernel you are running. If 170 170 unsure, say N. 171 171 172 + choice 173 + prompt "Module versioning implementation" 174 + depends on MODVERSIONS 175 + help 176 + Select the tool used to calculate symbol versions for modules. 177 + 178 + If unsure, select GENKSYMS. 179 + 180 + config GENKSYMS 181 + bool "genksyms (from source code)" 182 + help 183 + Calculate symbol versions from pre-processed source code using 184 + genksyms. 185 + 186 + If unsure, say Y. 187 + 188 + config GENDWARFKSYMS 189 + bool "gendwarfksyms (from debugging information)" 190 + depends on DEBUG_INFO 191 + # Requires full debugging information, split DWARF not supported. 192 + depends on !DEBUG_INFO_REDUCED && !DEBUG_INFO_SPLIT 193 + # Requires ELF object files. 194 + depends on !LTO 195 + help 196 + Calculate symbol versions from DWARF debugging information using 197 + gendwarfksyms. Requires DEBUG_INFO to be enabled. 198 + 199 + If unsure, say N. 200 + endchoice 201 + 172 202 config ASM_MODVERSIONS 173 203 bool 174 204 default HAVE_ASM_MODVERSIONS && MODVERSIONS ··· 206 176 This enables module versioning for exported symbols also from 207 177 assembly. This can be enabled only when the target architecture 208 178 supports it. 179 + 180 + config EXTENDED_MODVERSIONS 181 + bool "Extended Module Versioning Support" 182 + depends on MODVERSIONS 183 + help 184 + This enables extended MODVERSIONs support, allowing long symbol 185 + names to be versioned. 186 + 187 + The most likely reason you would enable this is to enable Rust 188 + support. If unsure, say N. 189 + 190 + config BASIC_MODVERSIONS 191 + bool "Basic Module Versioning Support" 192 + depends on MODVERSIONS 193 + default y 194 + help 195 + This enables basic MODVERSIONS support, allowing older tools or 196 + kernels to potentially load modules. 197 + 198 + Disabling this may cause older `modprobe` or `kmod` to be unable 199 + to read MODVERSIONS information from built modules. With this 200 + disabled, older kernels may treat this module as unversioned. 201 + 202 + This is enabled by default when MODVERSIONS are enabled. 203 + If unsure, say Y. 209 204 210 205 config MODULE_SRCVERSION_ALL 211 206 bool "Source checksum for all modules"
+16 -5
kernel/module/internal.h
··· 55 55 extern const struct kernel_symbol __stop___ksymtab[]; 56 56 extern const struct kernel_symbol __start___ksymtab_gpl[]; 57 57 extern const struct kernel_symbol __stop___ksymtab_gpl[]; 58 - extern const s32 __start___kcrctab[]; 59 - extern const s32 __start___kcrctab_gpl[]; 58 + extern const u32 __start___kcrctab[]; 59 + extern const u32 __start___kcrctab_gpl[]; 60 60 61 61 struct load_info { 62 62 const char *name; ··· 86 86 unsigned int vers; 87 87 unsigned int info; 88 88 unsigned int pcpu; 89 + unsigned int vers_ext_crc; 90 + unsigned int vers_ext_name; 89 91 } index; 90 92 }; 91 93 ··· 104 102 105 103 /* Output */ 106 104 struct module *owner; 107 - const s32 *crc; 105 + const u32 *crc; 108 106 const struct kernel_symbol *sym; 109 107 enum mod_license license; 110 108 }; ··· 387 385 388 386 #ifdef CONFIG_MODVERSIONS 389 387 int check_version(const struct load_info *info, 390 - const char *symname, struct module *mod, const s32 *crc); 388 + const char *symname, struct module *mod, const u32 *crc); 391 389 void module_layout(struct module *mod, struct modversion_info *ver, struct kernel_param *kp, 392 390 struct kernel_symbol *ks, struct tracepoint * const *tp); 393 391 int check_modstruct_version(const struct load_info *info, struct module *mod); 394 392 int same_magic(const char *amagic, const char *bmagic, bool has_crcs); 393 + struct modversion_info_ext { 394 + size_t remaining; 395 + const u32 *crc; 396 + const char *name; 397 + }; 398 + void modversion_ext_start(const struct load_info *info, struct modversion_info_ext *ver); 399 + void modversion_ext_advance(struct modversion_info_ext *ver); 400 + #define for_each_modversion_info_ext(ver, info) \ 401 + for (modversion_ext_start(info, &ver); ver.remaining > 0; modversion_ext_advance(&ver)) 395 402 #else /* !CONFIG_MODVERSIONS */ 396 403 static inline int check_version(const struct load_info *info, 397 404 const char *symname, 398 405 struct module *mod, 399 - const s32 *crc) 406 + const u32 *crc) 400 407 { 401 408 return 1; 402 409 }
+85 -9
kernel/module/main.c
··· 86 86 87 87 struct symsearch { 88 88 const struct kernel_symbol *start, *stop; 89 - const s32 *crcs; 89 + const u32 *crcs; 90 90 enum mod_license license; 91 91 }; 92 92 ··· 2074 2074 } 2075 2075 2076 2076 /** 2077 + * elf_validity_cache_index_versions() - Validate and cache version indices 2078 + * @info: Load info to cache version indices in. 2079 + * Must have &load_info->sechdrs and &load_info->secstrings populated. 2080 + * @flags: Load flags, relevant to suppress version loading, see 2081 + * uapi/linux/module.h 2082 + * 2083 + * If we're ignoring modversions based on @flags, zero all version indices 2084 + * and return validity. Othewrise check: 2085 + * 2086 + * * If "__version_ext_crcs" is present, "__version_ext_names" is present 2087 + * * There is a name present for every crc 2088 + * 2089 + * Then populate: 2090 + * 2091 + * * &load_info->index.vers 2092 + * * &load_info->index.vers_ext_crc 2093 + * * &load_info->index.vers_ext_names 2094 + * 2095 + * if present. 2096 + * 2097 + * Return: %0 if valid, %-ENOEXEC on failure. 2098 + */ 2099 + static int elf_validity_cache_index_versions(struct load_info *info, int flags) 2100 + { 2101 + unsigned int vers_ext_crc; 2102 + unsigned int vers_ext_name; 2103 + size_t crc_count; 2104 + size_t remaining_len; 2105 + size_t name_size; 2106 + char *name; 2107 + 2108 + /* If modversions were suppressed, pretend we didn't find any */ 2109 + if (flags & MODULE_INIT_IGNORE_MODVERSIONS) { 2110 + info->index.vers = 0; 2111 + info->index.vers_ext_crc = 0; 2112 + info->index.vers_ext_name = 0; 2113 + return 0; 2114 + } 2115 + 2116 + vers_ext_crc = find_sec(info, "__version_ext_crcs"); 2117 + vers_ext_name = find_sec(info, "__version_ext_names"); 2118 + 2119 + /* If we have one field, we must have the other */ 2120 + if (!!vers_ext_crc != !!vers_ext_name) { 2121 + pr_err("extended version crc+name presence does not match"); 2122 + return -ENOEXEC; 2123 + } 2124 + 2125 + /* 2126 + * If we have extended version information, we should have the same 2127 + * number of entries in every section. 2128 + */ 2129 + if (vers_ext_crc) { 2130 + crc_count = info->sechdrs[vers_ext_crc].sh_size / sizeof(u32); 2131 + name = (void *)info->hdr + 2132 + info->sechdrs[vers_ext_name].sh_offset; 2133 + remaining_len = info->sechdrs[vers_ext_name].sh_size; 2134 + 2135 + while (crc_count--) { 2136 + name_size = strnlen(name, remaining_len) + 1; 2137 + if (name_size > remaining_len) { 2138 + pr_err("more extended version crcs than names"); 2139 + return -ENOEXEC; 2140 + } 2141 + remaining_len -= name_size; 2142 + name += name_size; 2143 + } 2144 + } 2145 + 2146 + info->index.vers = find_sec(info, "__versions"); 2147 + info->index.vers_ext_crc = vers_ext_crc; 2148 + info->index.vers_ext_name = vers_ext_name; 2149 + return 0; 2150 + } 2151 + 2152 + /** 2077 2153 * elf_validity_cache_index() - Resolve, validate, cache section indices 2078 2154 * @info: Load info to read from and update. 2079 2155 * &load_info->sechdrs and &load_info->secstrings must be populated. ··· 2163 2087 * * elf_validity_cache_index_mod() 2164 2088 * * elf_validity_cache_index_sym() 2165 2089 * * elf_validity_cache_index_str() 2166 - * 2167 - * If versioning is not suppressed via flags, load the version index from 2168 - * a section called "__versions" with no validation. 2090 + * * elf_validity_cache_index_versions() 2169 2091 * 2170 2092 * If CONFIG_SMP is enabled, load the percpu section by name with no 2171 2093 * validation. ··· 2186 2112 err = elf_validity_cache_index_str(info); 2187 2113 if (err < 0) 2188 2114 return err; 2189 - 2190 - if (flags & MODULE_INIT_IGNORE_MODVERSIONS) 2191 - info->index.vers = 0; /* Pretend no __versions section! */ 2192 - else 2193 - info->index.vers = find_sec(info, "__versions"); 2115 + err = elf_validity_cache_index_versions(info, flags); 2116 + if (err < 0) 2117 + return err; 2194 2118 2195 2119 info->index.pcpu = find_pcpusec(info); 2196 2120 ··· 2399 2327 2400 2328 /* Track but don't keep modinfo and version sections. */ 2401 2329 info->sechdrs[info->index.vers].sh_flags &= ~(unsigned long)SHF_ALLOC; 2330 + info->sechdrs[info->index.vers_ext_crc].sh_flags &= 2331 + ~(unsigned long)SHF_ALLOC; 2332 + info->sechdrs[info->index.vers_ext_name].sh_flags &= 2333 + ~(unsigned long)SHF_ALLOC; 2402 2334 info->sechdrs[info->index.info].sh_flags &= ~(unsigned long)SHF_ALLOC; 2403 2335 2404 2336 return 0;
+46 -1
kernel/module/version.c
··· 13 13 int check_version(const struct load_info *info, 14 14 const char *symname, 15 15 struct module *mod, 16 - const s32 *crc) 16 + const u32 *crc) 17 17 { 18 18 Elf_Shdr *sechdrs = info->sechdrs; 19 19 unsigned int versindex = info->index.vers; 20 20 unsigned int i, num_versions; 21 21 struct modversion_info *versions; 22 + struct modversion_info_ext version_ext; 22 23 23 24 /* Exporting module didn't supply crcs? OK, we're already tainted. */ 24 25 if (!crc) 25 26 return 1; 27 + 28 + /* If we have extended version info, rely on it */ 29 + if (info->index.vers_ext_crc) { 30 + for_each_modversion_info_ext(version_ext, info) { 31 + if (strcmp(version_ext.name, symname) != 0) 32 + continue; 33 + if (*version_ext.crc == *crc) 34 + return 1; 35 + pr_debug("Found checksum %X vs module %X\n", 36 + *crc, *version_ext.crc); 37 + goto bad_version; 38 + } 39 + pr_warn_once("%s: no extended symbol version for %s\n", 40 + info->name, symname); 41 + return 1; 42 + } 26 43 27 44 /* No versions at all? modprobe --force does this. */ 28 45 if (versindex == 0) ··· 102 85 bmagic += strcspn(bmagic, " "); 103 86 } 104 87 return strcmp(amagic, bmagic) == 0; 88 + } 89 + 90 + void modversion_ext_start(const struct load_info *info, 91 + struct modversion_info_ext *start) 92 + { 93 + unsigned int crc_idx = info->index.vers_ext_crc; 94 + unsigned int name_idx = info->index.vers_ext_name; 95 + Elf_Shdr *sechdrs = info->sechdrs; 96 + 97 + /* 98 + * Both of these fields are needed for this to be useful 99 + * Any future fields should be initialized to NULL if absent. 100 + */ 101 + if (crc_idx == 0 || name_idx == 0) { 102 + start->remaining = 0; 103 + return; 104 + } 105 + 106 + start->crc = (const u32 *)sechdrs[crc_idx].sh_addr; 107 + start->name = (const char *)sechdrs[name_idx].sh_addr; 108 + start->remaining = sechdrs[crc_idx].sh_size / sizeof(*start->crc); 109 + } 110 + 111 + void modversion_ext_advance(struct modversion_info_ext *vers) 112 + { 113 + vers->remaining--; 114 + vers->crc++; 115 + vers->name += strlen(vers->name) + 1; 105 116 } 106 117 107 118 /*
+32 -2
rust/Makefile
··· 331 331 $(obj)/bindings/bindings_helpers_generated.rs: $(src)/helpers/helpers.c FORCE 332 332 $(call if_changed_dep,bindgen) 333 333 334 + rust_exports = $(NM) -p --defined-only $(1) | awk '$$2~/(T|R|D|B)/ && $$3!~/__cfi/ { printf $(2),$$3 }' 335 + 334 336 quiet_cmd_exports = EXPORTS $@ 335 337 cmd_exports = \ 336 - $(NM) -p --defined-only $< \ 337 - | awk '$$2~/(T|R|D|B)/ && $$3!~/__cfi/ {printf "EXPORT_SYMBOL_RUST_GPL(%s);\n",$$3}' > $@ 338 + $(call rust_exports,$<,"EXPORT_SYMBOL_RUST_GPL(%s);\n") > $@ 338 339 339 340 $(obj)/exports_core_generated.h: $(obj)/core.o FORCE 340 341 $(call if_changed,exports) ··· 404 403 __ashlti3 __lshrti3 405 404 endif 406 405 406 + ifdef CONFIG_MODVERSIONS 407 + cmd_gendwarfksyms = $(if $(skip_gendwarfksyms),, \ 408 + $(call rust_exports,$@,"%s\n") | \ 409 + scripts/gendwarfksyms/gendwarfksyms \ 410 + $(if $(KBUILD_GENDWARFKSYMS_STABLE), --stable) \ 411 + $(if $(KBUILD_SYMTYPES), --symtypes $(@:.o=.symtypes),) \ 412 + $@ >> $(dot-target).cmd) 413 + endif 414 + 407 415 define rule_rustc_library 408 416 $(call cmd_and_fixdep,rustc_library) 409 417 $(call cmd,gen_objtooldep) 418 + $(call cmd,gendwarfksyms) 410 419 endef 420 + 421 + define rule_rust_cc_library 422 + $(call if_changed_rule,cc_o_c) 423 + $(call cmd,force_checksrc) 424 + $(call cmd,gendwarfksyms) 425 + endef 426 + 427 + # helpers.o uses the same export mechanism as Rust libraries, so ensure symbol 428 + # versions are calculated for the helpers too. 429 + $(obj)/helpers/helpers.o: $(src)/helpers/helpers.c $(recordmcount_source) FORCE 430 + +$(call if_changed_rule,rust_cc_library) 431 + 432 + # Disable symbol versioning for exports.o to avoid conflicts with the actual 433 + # symbol versions generated from Rust objects. 434 + $(obj)/exports.o: private skip_gendwarfksyms = 1 411 435 412 436 $(obj)/core.o: private skip_clippy = 1 413 437 $(obj)/core.o: private skip_flags = -Wunreachable_pub ··· 445 419 $(obj)/core.o: scripts/target.json 446 420 endif 447 421 422 + $(obj)/compiler_builtins.o: private skip_gendwarfksyms = 1 448 423 $(obj)/compiler_builtins.o: private rustc_objcopy = -w -W '__*' 449 424 $(obj)/compiler_builtins.o: $(src)/compiler_builtins.rs $(obj)/core.o FORCE 450 425 +$(call if_changed_rule,rustc_library) 451 426 427 + $(obj)/build_error.o: private skip_gendwarfksyms = 1 452 428 $(obj)/build_error.o: $(src)/build_error.rs $(obj)/compiler_builtins.o FORCE 453 429 +$(call if_changed_rule,rustc_library) 454 430 431 + $(obj)/ffi.o: private skip_gendwarfksyms = 1 455 432 $(obj)/ffi.o: $(src)/ffi.rs $(obj)/compiler_builtins.o FORCE 456 433 +$(call if_changed_rule,rustc_library) 457 434 ··· 466 437 +$(call if_changed_rule,rustc_library) 467 438 468 439 $(obj)/uapi.o: private rustc_target_flags = --extern ffi 440 + $(obj)/uapi.o: private skip_gendwarfksyms = 1 469 441 $(obj)/uapi.o: $(src)/uapi/lib.rs \ 470 442 $(obj)/ffi.o \ 471 443 $(obj)/uapi/uapi_generated.rs FORCE
+2 -1
scripts/Makefile
··· 53 53 targets += module.lds 54 54 55 55 subdir-$(CONFIG_GCC_PLUGINS) += gcc-plugins 56 - subdir-$(CONFIG_MODVERSIONS) += genksyms 56 + subdir-$(CONFIG_GENKSYMS) += genksyms 57 + subdir-$(CONFIG_GENDWARFKSYMS) += gendwarfksyms 57 58 subdir-$(CONFIG_SECURITY_SELINUX) += selinux 58 59 subdir-$(CONFIG_SECURITY_IPE) += ipe 59 60
+31 -6
scripts/Makefile.build
··· 107 107 $(obj)/%.i: $(obj)/%.c FORCE 108 108 $(call if_changed_dep,cpp_i_c) 109 109 110 + getexportsymbols = $(NM) $@ | sed -n 's/.* __export_symbol_\(.*\)/$(1)/p' 111 + 112 + gendwarfksyms = $(objtree)/scripts/gendwarfksyms/gendwarfksyms \ 113 + $(if $(KBUILD_SYMTYPES), --symtypes $(@:.o=.symtypes)) \ 114 + $(if $(KBUILD_GENDWARFKSYMS_STABLE), --stable) 115 + 110 116 genksyms = $(objtree)/scripts/genksyms/genksyms \ 111 117 $(if $(KBUILD_SYMTYPES), -T $(@:.o=.symtypes)) \ 112 118 $(if $(KBUILD_PRESERVE), -p) \ 113 119 $(addprefix -r , $(wildcard $(@:.o=.symref))) 114 120 115 121 # These mirror gensymtypes_S and co below, keep them in synch. 122 + ifdef CONFIG_GENDWARFKSYMS 123 + cmd_gensymtypes_c = $(if $(skip_gendwarfksyms),, \ 124 + $(call getexportsymbols,\1) | $(gendwarfksyms) $@) 125 + else 116 126 cmd_gensymtypes_c = $(CPP) -D__GENKSYMS__ $(c_flags) $< | $(genksyms) 127 + endif # CONFIG_GENDWARFKSYMS 117 128 118 129 # LLVM assembly 119 130 # Generate .ll files from .c ··· 194 183 195 184 is-standard-object = $(if $(filter-out y%, $(OBJECT_FILES_NON_STANDARD_$(target-stem).o)$(OBJECT_FILES_NON_STANDARD)n),$(is-kernel-object)) 196 185 186 + ifdef CONFIG_OBJTOOL 197 187 $(obj)/%.o: private objtool-enabled = $(if $(is-standard-object),$(if $(delay-objtool),$(is-single-obj-m),y)) 188 + endif 198 189 199 190 ifneq ($(findstring 1, $(KBUILD_EXTRA_WARN)),) 200 191 cmd_warn_shared_object = $(if $(word 2, $(modname-multi)),$(warning $(kbuild-file): $*.o is added to multiple modules: $(modname-multi))) ··· 299 286 # This is convoluted. The .S file must first be preprocessed to run guards and 300 287 # expand names, then the resulting exports must be constructed into plain 301 288 # EXPORT_SYMBOL(symbol); to build our dummy C file, and that gets preprocessed 302 - # to make the genksyms input. 289 + # to make the genksyms input or compiled into an object for gendwarfksyms. 303 290 # 304 291 # These mirror gensymtypes_c and co above, keep them in synch. 305 - cmd_gensymtypes_S = \ 306 - { echo "\#include <linux/kernel.h>" ; \ 307 - echo "\#include <asm/asm-prototypes.h>" ; \ 308 - $(NM) $@ | sed -n 's/.* __export_symbol_\(.*\)/EXPORT_SYMBOL(\1);/p' ; } | \ 309 - $(CPP) -D__GENKSYMS__ $(c_flags) -xc - | $(genksyms) 292 + getasmexports = \ 293 + { echo "\#include <linux/kernel.h>" ; \ 294 + echo "\#include <linux/string.h>" ; \ 295 + echo "\#include <asm/asm-prototypes.h>" ; \ 296 + $(call getexportsymbols,EXPORT_SYMBOL(\1);) ; } 297 + 298 + ifdef CONFIG_GENDWARFKSYMS 299 + cmd_gensymtypes_S = \ 300 + $(getasmexports) | \ 301 + $(CC) $(c_flags) -c -o $(@:.o=.gendwarfksyms.o) -xc -; \ 302 + $(call getexportsymbols,\1) | \ 303 + $(gendwarfksyms) $(@:.o=.gendwarfksyms.o) 304 + else 305 + cmd_gensymtypes_S = \ 306 + $(getasmexports) | \ 307 + $(CPP) -D__GENKSYMS__ $(c_flags) -xc - | $(genksyms) 308 + endif # CONFIG_GENDWARFKSYMS 310 309 311 310 quiet_cmd_cpp_s_S = CPP $(quiet_modtag) $@ 312 311 cmd_cpp_s_S = $(CPP) $(a_flags) -o $@ $<
+7 -6
scripts/Makefile.defconf
··· 1 1 # SPDX-License-Identifier: GPL-2.0 2 2 # Configuration heplers 3 3 4 + cmd_merge_fragments = \ 5 + $(srctree)/scripts/kconfig/merge_config.sh \ 6 + $4 -m -O $(objtree) $(srctree)/arch/$(SRCARCH)/configs/$2 \ 7 + $(foreach config,$3,$(srctree)/arch/$(SRCARCH)/configs/$(config).config) 8 + 4 9 # Creates 'merged defconfigs' 5 10 # --------------------------------------------------------------------------- 6 11 # Usage: ··· 13 8 # 14 9 # Input config fragments without '.config' suffix 15 10 define merge_into_defconfig 16 - $(Q)$(CONFIG_SHELL) $(srctree)/scripts/kconfig/merge_config.sh \ 17 - -m -O $(objtree) $(srctree)/arch/$(SRCARCH)/configs/$(1) \ 18 - $(foreach config,$(2),$(srctree)/arch/$(SRCARCH)/configs/$(config).config) 11 + $(call cmd,merge_fragments,$1,$2) 19 12 +$(Q)$(MAKE) -f $(srctree)/Makefile olddefconfig 20 13 endef 21 14 ··· 25 22 # 26 23 # Input config fragments without '.config' suffix 27 24 define merge_into_defconfig_override 28 - $(Q)$(CONFIG_SHELL) $(srctree)/scripts/kconfig/merge_config.sh \ 29 - -Q -m -O $(objtree) $(srctree)/arch/$(SRCARCH)/configs/$(1) \ 30 - $(foreach config,$(2),$(srctree)/arch/$(SRCARCH)/configs/$(config).config) 25 + $(call cmd,merge_fragments,$1,$2,-Q) 31 26 +$(Q)$(MAKE) -f $(srctree)/Makefile olddefconfig 32 27 endef
+9 -4
scripts/Makefile.lib
··· 287 287 cmd_objtool = $(if $(objtool-enabled), ; $(objtool) $(objtool-args) $@) 288 288 cmd_gen_objtooldep = $(if $(objtool-enabled), { echo ; echo '$@: $$(wildcard $(objtool))' ; } >> $(dot-target).cmd) 289 289 290 + objtool-enabled := y 291 + 290 292 endif # CONFIG_OBJTOOL 291 293 292 294 # Useful for describing the dependency of composite objects ··· 304 302 # =========================================================================== 305 303 # These are shared by some Makefile.* files. 306 304 307 - objtool-enabled := y 308 - 309 305 ifdef CONFIG_LTO_CLANG 310 - # objtool cannot process LLVM IR. Make $(LD) covert LLVM IR to ELF here. 311 - cmd_ld_single = $(if $(objtool-enabled), ; $(LD) $(ld_flags) -r -o $(tmp-target) $@; mv $(tmp-target) $@) 306 + # Run $(LD) here to covert LLVM IR to ELF in the following cases: 307 + # - when this object needs objtool processing, as objtool cannot process LLVM IR 308 + # - when this is a single-object module, as modpost cannot process LLVM IR 309 + cmd_ld_single = $(if $(objtool-enabled)$(is-single-obj-m), ; $(LD) $(ld_flags) -r -o $(tmp-target) $@; mv $(tmp-target) $@) 312 310 endif 313 311 314 312 quiet_cmd_cc_o_c = CC $(quiet_modtag) $@ ··· 375 373 376 374 quiet_cmd_objcopy = OBJCOPY $@ 377 375 cmd_objcopy = $(OBJCOPY) $(OBJCOPYFLAGS) $(OBJCOPYFLAGS_$(@F)) $< $@ 376 + 377 + quiet_cmd_strip_relocs = RSTRIP $@ 378 + cmd_strip_relocs = $(OBJCOPY) --remove-section='.rel*' $@ 378 379 379 380 # Gzip 380 381 # ---------------------------------------------------------------------------
+1 -1
scripts/Makefile.modinst
··· 105 105 sig-key := $(CONFIG_MODULE_SIG_KEY) 106 106 endif 107 107 quiet_cmd_sign = SIGN $@ 108 - cmd_sign = scripts/sign-file $(CONFIG_MODULE_SIG_HASH) "$(sig-key)" certs/signing_key.x509 $@ \ 108 + cmd_sign = $(objtree)/scripts/sign-file $(CONFIG_MODULE_SIG_HASH) "$(sig-key)" $(objtree)/certs/signing_key.x509 $@ \ 109 109 $(if $(KBUILD_EXTMOD),|| true) 110 110 111 111 ifeq ($(sign-only),)
+2
scripts/Makefile.modpost
··· 43 43 modpost-args = \ 44 44 $(if $(CONFIG_MODULES),-M) \ 45 45 $(if $(CONFIG_MODVERSIONS),-m) \ 46 + $(if $(CONFIG_BASIC_MODVERSIONS),-b) \ 47 + $(if $(CONFIG_EXTENDED_MODVERSIONS),-x) \ 46 48 $(if $(CONFIG_MODULE_SRCVERSION_ALL),-a) \ 47 49 $(if $(CONFIG_SECTION_MISMATCH_WARN_ONLY),,-E) \ 48 50 $(if $(KBUILD_MODPOST_WARN),-w) \
+2
scripts/gendwarfksyms/.gitignore
··· 1 + # SPDX-License-Identifier: GPL-2.0 2 + /gendwarfksyms
+12
scripts/gendwarfksyms/Makefile
··· 1 + # SPDX-License-Identifier: GPL-2.0 2 + hostprogs-always-y += gendwarfksyms 3 + 4 + gendwarfksyms-objs += gendwarfksyms.o 5 + gendwarfksyms-objs += cache.o 6 + gendwarfksyms-objs += die.o 7 + gendwarfksyms-objs += dwarf.o 8 + gendwarfksyms-objs += kabi.o 9 + gendwarfksyms-objs += symbols.o 10 + gendwarfksyms-objs += types.o 11 + 12 + HOSTLDLIBS_gendwarfksyms := -ldw -lelf -lz
+51
scripts/gendwarfksyms/cache.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Copyright (C) 2024 Google LLC 4 + */ 5 + 6 + #include "gendwarfksyms.h" 7 + 8 + struct cache_item { 9 + unsigned long key; 10 + int value; 11 + struct hlist_node hash; 12 + }; 13 + 14 + void cache_set(struct cache *cache, unsigned long key, int value) 15 + { 16 + struct cache_item *ci; 17 + 18 + ci = xmalloc(sizeof(struct cache_item)); 19 + ci->key = key; 20 + ci->value = value; 21 + hash_add(cache->cache, &ci->hash, hash_32(key)); 22 + } 23 + 24 + int cache_get(struct cache *cache, unsigned long key) 25 + { 26 + struct cache_item *ci; 27 + 28 + hash_for_each_possible(cache->cache, ci, hash, hash_32(key)) { 29 + if (ci->key == key) 30 + return ci->value; 31 + } 32 + 33 + return -1; 34 + } 35 + 36 + void cache_init(struct cache *cache) 37 + { 38 + hash_init(cache->cache); 39 + } 40 + 41 + void cache_free(struct cache *cache) 42 + { 43 + struct hlist_node *tmp; 44 + struct cache_item *ci; 45 + 46 + hash_for_each_safe(cache->cache, ci, tmp, hash) { 47 + free(ci); 48 + } 49 + 50 + hash_init(cache->cache); 51 + }
+166
scripts/gendwarfksyms/die.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Copyright (C) 2024 Google LLC 4 + */ 5 + 6 + #include <string.h> 7 + #include "gendwarfksyms.h" 8 + 9 + #define DIE_HASH_BITS 15 10 + 11 + /* {die->addr, state} -> struct die * */ 12 + static HASHTABLE_DEFINE(die_map, 1 << DIE_HASH_BITS); 13 + 14 + static unsigned int map_hits; 15 + static unsigned int map_misses; 16 + 17 + static inline unsigned int die_hash(uintptr_t addr, enum die_state state) 18 + { 19 + return hash_32(addr_hash(addr) ^ (unsigned int)state); 20 + } 21 + 22 + static void init_die(struct die *cd) 23 + { 24 + cd->state = DIE_INCOMPLETE; 25 + cd->mapped = false; 26 + cd->fqn = NULL; 27 + cd->tag = -1; 28 + cd->addr = 0; 29 + INIT_LIST_HEAD(&cd->fragments); 30 + } 31 + 32 + static struct die *create_die(Dwarf_Die *die, enum die_state state) 33 + { 34 + struct die *cd; 35 + 36 + cd = xmalloc(sizeof(struct die)); 37 + init_die(cd); 38 + cd->addr = (uintptr_t)die->addr; 39 + 40 + hash_add(die_map, &cd->hash, die_hash(cd->addr, state)); 41 + return cd; 42 + } 43 + 44 + int __die_map_get(uintptr_t addr, enum die_state state, struct die **res) 45 + { 46 + struct die *cd; 47 + 48 + hash_for_each_possible(die_map, cd, hash, die_hash(addr, state)) { 49 + if (cd->addr == addr && cd->state == state) { 50 + *res = cd; 51 + return 0; 52 + } 53 + } 54 + 55 + return -1; 56 + } 57 + 58 + struct die *die_map_get(Dwarf_Die *die, enum die_state state) 59 + { 60 + struct die *cd; 61 + 62 + if (__die_map_get((uintptr_t)die->addr, state, &cd) == 0) { 63 + map_hits++; 64 + return cd; 65 + } 66 + 67 + map_misses++; 68 + return create_die(die, state); 69 + } 70 + 71 + static void reset_die(struct die *cd) 72 + { 73 + struct die_fragment *tmp; 74 + struct die_fragment *df; 75 + 76 + list_for_each_entry_safe(df, tmp, &cd->fragments, list) { 77 + if (df->type == FRAGMENT_STRING) 78 + free(df->data.str); 79 + free(df); 80 + } 81 + 82 + if (cd->fqn && *cd->fqn) 83 + free(cd->fqn); 84 + init_die(cd); 85 + } 86 + 87 + void die_map_for_each(die_map_callback_t func, void *arg) 88 + { 89 + struct hlist_node *tmp; 90 + struct die *cd; 91 + 92 + hash_for_each_safe(die_map, cd, tmp, hash) { 93 + func(cd, arg); 94 + } 95 + } 96 + 97 + void die_map_free(void) 98 + { 99 + struct hlist_node *tmp; 100 + unsigned int stats[DIE_LAST + 1]; 101 + struct die *cd; 102 + int i; 103 + 104 + memset(stats, 0, sizeof(stats)); 105 + 106 + hash_for_each_safe(die_map, cd, tmp, hash) { 107 + stats[cd->state]++; 108 + reset_die(cd); 109 + free(cd); 110 + } 111 + hash_init(die_map); 112 + 113 + if (map_hits + map_misses > 0) 114 + debug("hits %u, misses %u (hit rate %.02f%%)", map_hits, 115 + map_misses, 116 + (100.0f * map_hits) / (map_hits + map_misses)); 117 + 118 + for (i = 0; i <= DIE_LAST; i++) 119 + debug("%s: %u entries", die_state_name(i), stats[i]); 120 + } 121 + 122 + static struct die_fragment *append_item(struct die *cd) 123 + { 124 + struct die_fragment *df; 125 + 126 + df = xmalloc(sizeof(struct die_fragment)); 127 + df->type = FRAGMENT_EMPTY; 128 + list_add_tail(&df->list, &cd->fragments); 129 + return df; 130 + } 131 + 132 + void die_map_add_string(struct die *cd, const char *str) 133 + { 134 + struct die_fragment *df; 135 + 136 + if (!cd) 137 + return; 138 + 139 + df = append_item(cd); 140 + df->data.str = xstrdup(str); 141 + df->type = FRAGMENT_STRING; 142 + } 143 + 144 + void die_map_add_linebreak(struct die *cd, int linebreak) 145 + { 146 + struct die_fragment *df; 147 + 148 + if (!cd) 149 + return; 150 + 151 + df = append_item(cd); 152 + df->data.linebreak = linebreak; 153 + df->type = FRAGMENT_LINEBREAK; 154 + } 155 + 156 + void die_map_add_die(struct die *cd, struct die *child) 157 + { 158 + struct die_fragment *df; 159 + 160 + if (!cd) 161 + return; 162 + 163 + df = append_item(cd); 164 + df->data.addr = child->addr; 165 + df->type = FRAGMENT_DIE; 166 + }
+1159
scripts/gendwarfksyms/dwarf.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Copyright (C) 2024 Google LLC 4 + */ 5 + 6 + #include <assert.h> 7 + #include <inttypes.h> 8 + #include <stdarg.h> 9 + #include "gendwarfksyms.h" 10 + 11 + /* See get_union_kabi_status */ 12 + #define KABI_PREFIX "__kabi_" 13 + #define KABI_PREFIX_LEN (sizeof(KABI_PREFIX) - 1) 14 + #define KABI_RESERVED_PREFIX "reserved" 15 + #define KABI_RESERVED_PREFIX_LEN (sizeof(KABI_RESERVED_PREFIX) - 1) 16 + #define KABI_RENAMED_PREFIX "renamed" 17 + #define KABI_RENAMED_PREFIX_LEN (sizeof(KABI_RENAMED_PREFIX) - 1) 18 + #define KABI_IGNORED_PREFIX "ignored" 19 + #define KABI_IGNORED_PREFIX_LEN (sizeof(KABI_IGNORED_PREFIX) - 1) 20 + 21 + static inline bool is_kabi_prefix(const char *name) 22 + { 23 + return name && !strncmp(name, KABI_PREFIX, KABI_PREFIX_LEN); 24 + } 25 + 26 + enum kabi_status { 27 + /* >0 to stop DIE processing */ 28 + KABI_NORMAL = 1, 29 + KABI_RESERVED, 30 + KABI_IGNORED, 31 + }; 32 + 33 + static bool do_linebreak; 34 + static int indentation_level; 35 + 36 + /* Line breaks and indentation for pretty-printing */ 37 + static void process_linebreak(struct die *cache, int n) 38 + { 39 + indentation_level += n; 40 + do_linebreak = true; 41 + die_map_add_linebreak(cache, n); 42 + } 43 + 44 + #define DEFINE_GET_ATTR(attr, type) \ 45 + static bool get_##attr##_attr(Dwarf_Die *die, unsigned int id, \ 46 + type *value) \ 47 + { \ 48 + Dwarf_Attribute da; \ 49 + return dwarf_attr(die, id, &da) && \ 50 + !dwarf_form##attr(&da, value); \ 51 + } 52 + 53 + DEFINE_GET_ATTR(flag, bool) 54 + DEFINE_GET_ATTR(udata, Dwarf_Word) 55 + 56 + static bool get_ref_die_attr(Dwarf_Die *die, unsigned int id, Dwarf_Die *value) 57 + { 58 + Dwarf_Attribute da; 59 + 60 + /* dwarf_formref_die returns a pointer instead of an error value. */ 61 + return dwarf_attr(die, id, &da) && dwarf_formref_die(&da, value); 62 + } 63 + 64 + #define DEFINE_GET_STRING_ATTR(attr) \ 65 + static const char *get_##attr##_attr(Dwarf_Die *die) \ 66 + { \ 67 + Dwarf_Attribute da; \ 68 + if (dwarf_attr(die, DW_AT_##attr, &da)) \ 69 + return dwarf_formstring(&da); \ 70 + return NULL; \ 71 + } 72 + 73 + DEFINE_GET_STRING_ATTR(name) 74 + DEFINE_GET_STRING_ATTR(linkage_name) 75 + 76 + static const char *get_symbol_name(Dwarf_Die *die) 77 + { 78 + const char *name; 79 + 80 + /* rustc uses DW_AT_linkage_name for exported symbols */ 81 + name = get_linkage_name_attr(die); 82 + if (!name) 83 + name = get_name_attr(die); 84 + 85 + return name; 86 + } 87 + 88 + static bool match_export_symbol(struct state *state, Dwarf_Die *die) 89 + { 90 + Dwarf_Die *source = die; 91 + Dwarf_Die origin; 92 + 93 + /* If the DIE has an abstract origin, use it for type information. */ 94 + if (get_ref_die_attr(die, DW_AT_abstract_origin, &origin)) 95 + source = &origin; 96 + 97 + state->sym = symbol_get(get_symbol_name(die)); 98 + 99 + /* Look up using the origin name if there are no matches. */ 100 + if (!state->sym && source != die) 101 + state->sym = symbol_get(get_symbol_name(source)); 102 + 103 + state->die = *source; 104 + return !!state->sym; 105 + } 106 + 107 + /* DW_AT_decl_file -> struct srcfile */ 108 + static struct cache srcfile_cache; 109 + 110 + static bool is_definition_private(Dwarf_Die *die) 111 + { 112 + Dwarf_Word filenum; 113 + Dwarf_Files *files; 114 + Dwarf_Die cudie; 115 + const char *s; 116 + int res; 117 + 118 + /* 119 + * Definitions in .c files cannot change the public ABI, 120 + * so consider them private. 121 + */ 122 + if (!get_udata_attr(die, DW_AT_decl_file, &filenum)) 123 + return false; 124 + 125 + res = cache_get(&srcfile_cache, filenum); 126 + if (res >= 0) 127 + return !!res; 128 + 129 + if (!dwarf_cu_die(die->cu, &cudie, NULL, NULL, NULL, NULL, NULL, NULL)) 130 + error("dwarf_cu_die failed: '%s'", dwarf_errmsg(-1)); 131 + 132 + if (dwarf_getsrcfiles(&cudie, &files, NULL)) 133 + error("dwarf_getsrcfiles failed: '%s'", dwarf_errmsg(-1)); 134 + 135 + s = dwarf_filesrc(files, filenum, NULL, NULL); 136 + if (!s) 137 + error("dwarf_filesrc failed: '%s'", dwarf_errmsg(-1)); 138 + 139 + s = strrchr(s, '.'); 140 + res = s && !strcmp(s, ".c"); 141 + cache_set(&srcfile_cache, filenum, res); 142 + 143 + return !!res; 144 + } 145 + 146 + static bool is_kabi_definition(struct die *cache, Dwarf_Die *die) 147 + { 148 + bool value; 149 + 150 + if (get_flag_attr(die, DW_AT_declaration, &value) && value) 151 + return false; 152 + 153 + if (kabi_is_declonly(cache->fqn)) 154 + return false; 155 + 156 + return !is_definition_private(die); 157 + } 158 + 159 + /* 160 + * Type string processing 161 + */ 162 + static void process(struct die *cache, const char *s) 163 + { 164 + s = s ?: "<null>"; 165 + 166 + if (dump_dies && do_linebreak) { 167 + fputs("\n", stderr); 168 + for (int i = 0; i < indentation_level; i++) 169 + fputs(" ", stderr); 170 + do_linebreak = false; 171 + } 172 + if (dump_dies) 173 + fputs(s, stderr); 174 + 175 + if (cache) 176 + die_debug_r("cache %p string '%s'", cache, s); 177 + die_map_add_string(cache, s); 178 + } 179 + 180 + #define MAX_FMT_BUFFER_SIZE 128 181 + 182 + static void process_fmt(struct die *cache, const char *fmt, ...) 183 + { 184 + char buf[MAX_FMT_BUFFER_SIZE]; 185 + va_list args; 186 + 187 + va_start(args, fmt); 188 + 189 + if (checkp(vsnprintf(buf, sizeof(buf), fmt, args)) >= sizeof(buf)) 190 + error("vsnprintf overflow: increase MAX_FMT_BUFFER_SIZE"); 191 + 192 + process(cache, buf); 193 + va_end(args); 194 + } 195 + 196 + #define MAX_FQN_SIZE 64 197 + 198 + /* Get a fully qualified name from DWARF scopes */ 199 + static char *get_fqn(Dwarf_Die *die) 200 + { 201 + const char *list[MAX_FQN_SIZE]; 202 + Dwarf_Die *scopes = NULL; 203 + bool has_name = false; 204 + char *fqn = NULL; 205 + char *p; 206 + int count = 0; 207 + int len = 0; 208 + int res; 209 + int i; 210 + 211 + res = checkp(dwarf_getscopes_die(die, &scopes)); 212 + if (!res) { 213 + list[count] = get_name_attr(die); 214 + 215 + if (!list[count]) 216 + return NULL; 217 + 218 + len += strlen(list[count]); 219 + count++; 220 + 221 + goto done; 222 + } 223 + 224 + for (i = res - 1; i >= 0 && count < MAX_FQN_SIZE; i--) { 225 + if (dwarf_tag(&scopes[i]) == DW_TAG_compile_unit) 226 + continue; 227 + 228 + list[count] = get_name_attr(&scopes[i]); 229 + 230 + if (list[count]) { 231 + has_name = true; 232 + } else { 233 + list[count] = "<anonymous>"; 234 + has_name = false; 235 + } 236 + 237 + len += strlen(list[count]); 238 + count++; 239 + 240 + if (i > 0) { 241 + list[count++] = "::"; 242 + len += 2; 243 + } 244 + } 245 + 246 + free(scopes); 247 + 248 + if (count == MAX_FQN_SIZE) 249 + warn("increase MAX_FQN_SIZE: reached the maximum"); 250 + 251 + /* Consider the DIE unnamed if the last scope doesn't have a name */ 252 + if (!has_name) 253 + return NULL; 254 + done: 255 + fqn = xmalloc(len + 1); 256 + *fqn = '\0'; 257 + 258 + p = fqn; 259 + for (i = 0; i < count; i++) 260 + p = stpcpy(p, list[i]); 261 + 262 + return fqn; 263 + } 264 + 265 + static void update_fqn(struct die *cache, Dwarf_Die *die) 266 + { 267 + if (!cache->fqn) 268 + cache->fqn = get_fqn(die) ?: ""; 269 + } 270 + 271 + static void process_fqn(struct die *cache, Dwarf_Die *die) 272 + { 273 + update_fqn(cache, die); 274 + if (*cache->fqn) 275 + process(cache, " "); 276 + process(cache, cache->fqn); 277 + } 278 + 279 + #define DEFINE_PROCESS_UDATA_ATTRIBUTE(attribute) \ 280 + static void process_##attribute##_attr(struct die *cache, \ 281 + Dwarf_Die *die) \ 282 + { \ 283 + Dwarf_Word value; \ 284 + if (get_udata_attr(die, DW_AT_##attribute, &value)) \ 285 + process_fmt(cache, " " #attribute "(%" PRIu64 ")", \ 286 + value); \ 287 + } 288 + 289 + DEFINE_PROCESS_UDATA_ATTRIBUTE(accessibility) 290 + DEFINE_PROCESS_UDATA_ATTRIBUTE(alignment) 291 + DEFINE_PROCESS_UDATA_ATTRIBUTE(bit_size) 292 + DEFINE_PROCESS_UDATA_ATTRIBUTE(byte_size) 293 + DEFINE_PROCESS_UDATA_ATTRIBUTE(encoding) 294 + DEFINE_PROCESS_UDATA_ATTRIBUTE(data_bit_offset) 295 + DEFINE_PROCESS_UDATA_ATTRIBUTE(data_member_location) 296 + DEFINE_PROCESS_UDATA_ATTRIBUTE(discr_value) 297 + 298 + /* Match functions -- die_match_callback_t */ 299 + #define DEFINE_MATCH(type) \ 300 + static bool match_##type##_type(Dwarf_Die *die) \ 301 + { \ 302 + return dwarf_tag(die) == DW_TAG_##type##_type; \ 303 + } 304 + 305 + DEFINE_MATCH(enumerator) 306 + DEFINE_MATCH(formal_parameter) 307 + DEFINE_MATCH(member) 308 + DEFINE_MATCH(subrange) 309 + 310 + bool match_all(Dwarf_Die *die) 311 + { 312 + return true; 313 + } 314 + 315 + int process_die_container(struct state *state, struct die *cache, 316 + Dwarf_Die *die, die_callback_t func, 317 + die_match_callback_t match) 318 + { 319 + Dwarf_Die current; 320 + int res; 321 + 322 + /* Track the first item in lists. */ 323 + if (state) 324 + state->first_list_item = true; 325 + 326 + res = checkp(dwarf_child(die, &current)); 327 + while (!res) { 328 + if (match(&current)) { 329 + /* <0 = error, 0 = continue, >0 = stop */ 330 + res = checkp(func(state, cache, &current)); 331 + if (res) 332 + goto out; 333 + } 334 + 335 + res = checkp(dwarf_siblingof(&current, &current)); 336 + } 337 + 338 + res = 0; 339 + out: 340 + if (state) 341 + state->first_list_item = false; 342 + 343 + return res; 344 + } 345 + 346 + static int process_type(struct state *state, struct die *parent, 347 + Dwarf_Die *die); 348 + 349 + static void process_type_attr(struct state *state, struct die *cache, 350 + Dwarf_Die *die) 351 + { 352 + Dwarf_Die type; 353 + 354 + if (get_ref_die_attr(die, DW_AT_type, &type)) { 355 + check(process_type(state, cache, &type)); 356 + return; 357 + } 358 + 359 + /* Compilers can omit DW_AT_type -- print out 'void' to clarify */ 360 + process(cache, "base_type void"); 361 + } 362 + 363 + static void process_list_comma(struct state *state, struct die *cache) 364 + { 365 + if (state->first_list_item) { 366 + state->first_list_item = false; 367 + } else { 368 + process(cache, " ,"); 369 + process_linebreak(cache, 0); 370 + } 371 + } 372 + 373 + /* Comma-separated with DW_AT_type */ 374 + static void __process_list_type(struct state *state, struct die *cache, 375 + Dwarf_Die *die, const char *type) 376 + { 377 + const char *name = get_name_attr(die); 378 + 379 + if (stable) { 380 + if (is_kabi_prefix(name)) 381 + name = NULL; 382 + state->kabi.orig_name = NULL; 383 + } 384 + 385 + process_list_comma(state, cache); 386 + process(cache, type); 387 + process_type_attr(state, cache, die); 388 + 389 + if (stable && state->kabi.orig_name) 390 + name = state->kabi.orig_name; 391 + if (name) { 392 + process(cache, " "); 393 + process(cache, name); 394 + } 395 + 396 + process_accessibility_attr(cache, die); 397 + process_bit_size_attr(cache, die); 398 + process_data_bit_offset_attr(cache, die); 399 + process_data_member_location_attr(cache, die); 400 + } 401 + 402 + #define DEFINE_PROCESS_LIST_TYPE(type) \ 403 + static void process_##type##_type(struct state *state, \ 404 + struct die *cache, Dwarf_Die *die) \ 405 + { \ 406 + __process_list_type(state, cache, die, #type " "); \ 407 + } 408 + 409 + DEFINE_PROCESS_LIST_TYPE(formal_parameter) 410 + DEFINE_PROCESS_LIST_TYPE(member) 411 + 412 + /* Container types with DW_AT_type */ 413 + static void __process_type(struct state *state, struct die *cache, 414 + Dwarf_Die *die, const char *type) 415 + { 416 + process(cache, type); 417 + process_fqn(cache, die); 418 + process(cache, " {"); 419 + process_linebreak(cache, 1); 420 + process_type_attr(state, cache, die); 421 + process_linebreak(cache, -1); 422 + process(cache, "}"); 423 + process_byte_size_attr(cache, die); 424 + process_alignment_attr(cache, die); 425 + } 426 + 427 + #define DEFINE_PROCESS_TYPE(type) \ 428 + static void process_##type##_type(struct state *state, \ 429 + struct die *cache, Dwarf_Die *die) \ 430 + { \ 431 + __process_type(state, cache, die, #type "_type"); \ 432 + } 433 + 434 + DEFINE_PROCESS_TYPE(atomic) 435 + DEFINE_PROCESS_TYPE(const) 436 + DEFINE_PROCESS_TYPE(immutable) 437 + DEFINE_PROCESS_TYPE(packed) 438 + DEFINE_PROCESS_TYPE(pointer) 439 + DEFINE_PROCESS_TYPE(reference) 440 + DEFINE_PROCESS_TYPE(restrict) 441 + DEFINE_PROCESS_TYPE(rvalue_reference) 442 + DEFINE_PROCESS_TYPE(shared) 443 + DEFINE_PROCESS_TYPE(template_type_parameter) 444 + DEFINE_PROCESS_TYPE(volatile) 445 + DEFINE_PROCESS_TYPE(typedef) 446 + 447 + static void process_subrange_type(struct state *state, struct die *cache, 448 + Dwarf_Die *die) 449 + { 450 + Dwarf_Word count = 0; 451 + 452 + if (get_udata_attr(die, DW_AT_count, &count)) 453 + process_fmt(cache, "[%" PRIu64 "]", count); 454 + else if (get_udata_attr(die, DW_AT_upper_bound, &count)) 455 + process_fmt(cache, "[%" PRIu64 "]", count + 1); 456 + else 457 + process(cache, "[]"); 458 + } 459 + 460 + static void process_array_type(struct state *state, struct die *cache, 461 + Dwarf_Die *die) 462 + { 463 + process(cache, "array_type"); 464 + /* Array size */ 465 + check(process_die_container(state, cache, die, process_type, 466 + match_subrange_type)); 467 + process(cache, " {"); 468 + process_linebreak(cache, 1); 469 + process_type_attr(state, cache, die); 470 + process_linebreak(cache, -1); 471 + process(cache, "}"); 472 + } 473 + 474 + static void __process_subroutine_type(struct state *state, struct die *cache, 475 + Dwarf_Die *die, const char *type) 476 + { 477 + process(cache, type); 478 + process(cache, " ("); 479 + process_linebreak(cache, 1); 480 + /* Parameters */ 481 + check(process_die_container(state, cache, die, process_type, 482 + match_formal_parameter_type)); 483 + process_linebreak(cache, -1); 484 + process(cache, ")"); 485 + process_linebreak(cache, 0); 486 + /* Return type */ 487 + process(cache, "-> "); 488 + process_type_attr(state, cache, die); 489 + } 490 + 491 + static void process_subroutine_type(struct state *state, struct die *cache, 492 + Dwarf_Die *die) 493 + { 494 + __process_subroutine_type(state, cache, die, "subroutine_type"); 495 + } 496 + 497 + static void process_variant_type(struct state *state, struct die *cache, 498 + Dwarf_Die *die) 499 + { 500 + process_list_comma(state, cache); 501 + process(cache, "variant {"); 502 + process_linebreak(cache, 1); 503 + check(process_die_container(state, cache, die, process_type, 504 + match_member_type)); 505 + process_linebreak(cache, -1); 506 + process(cache, "}"); 507 + process_discr_value_attr(cache, die); 508 + } 509 + 510 + static void process_variant_part_type(struct state *state, struct die *cache, 511 + Dwarf_Die *die) 512 + { 513 + process_list_comma(state, cache); 514 + process(cache, "variant_part {"); 515 + process_linebreak(cache, 1); 516 + check(process_die_container(state, cache, die, process_type, 517 + match_all)); 518 + process_linebreak(cache, -1); 519 + process(cache, "}"); 520 + } 521 + 522 + static int get_kabi_status(Dwarf_Die *die, const char **suffix) 523 + { 524 + const char *name = get_name_attr(die); 525 + 526 + if (suffix) 527 + *suffix = NULL; 528 + 529 + if (is_kabi_prefix(name)) { 530 + name += KABI_PREFIX_LEN; 531 + 532 + if (!strncmp(name, KABI_RESERVED_PREFIX, 533 + KABI_RESERVED_PREFIX_LEN)) 534 + return KABI_RESERVED; 535 + if (!strncmp(name, KABI_IGNORED_PREFIX, 536 + KABI_IGNORED_PREFIX_LEN)) 537 + return KABI_IGNORED; 538 + 539 + if (!strncmp(name, KABI_RENAMED_PREFIX, 540 + KABI_RENAMED_PREFIX_LEN)) { 541 + if (suffix) { 542 + name += KABI_RENAMED_PREFIX_LEN; 543 + *suffix = name; 544 + } 545 + return KABI_RESERVED; 546 + } 547 + } 548 + 549 + return KABI_NORMAL; 550 + } 551 + 552 + static int check_struct_member_kabi_status(struct state *state, 553 + struct die *__unused, Dwarf_Die *die) 554 + { 555 + int res; 556 + 557 + assert(dwarf_tag(die) == DW_TAG_member_type); 558 + 559 + /* 560 + * If the union member is a struct, expect the __kabi field to 561 + * be the first member of the structure, i.e..: 562 + * 563 + * union { 564 + * type new_member; 565 + * struct { 566 + * type __kabi_field; 567 + * } 568 + * }; 569 + */ 570 + res = get_kabi_status(die, &state->kabi.orig_name); 571 + 572 + if (res == KABI_RESERVED && 573 + !get_ref_die_attr(die, DW_AT_type, &state->kabi.placeholder)) 574 + error("structure member missing a type?"); 575 + 576 + return res; 577 + } 578 + 579 + static int check_union_member_kabi_status(struct state *state, 580 + struct die *__unused, Dwarf_Die *die) 581 + { 582 + Dwarf_Die type; 583 + int res; 584 + 585 + assert(dwarf_tag(die) == DW_TAG_member_type); 586 + 587 + if (!get_ref_die_attr(die, DW_AT_type, &type)) 588 + error("union member missing a type?"); 589 + 590 + /* 591 + * We expect a union with two members. Check if either of them 592 + * has a __kabi name prefix, i.e.: 593 + * 594 + * union { 595 + * ... 596 + * type memberN; // <- type, N = {0,1} 597 + * ... 598 + * }; 599 + * 600 + * The member can also be a structure type, in which case we'll 601 + * check the first structure member. 602 + * 603 + * In any case, stop processing after we've seen two members. 604 + */ 605 + res = get_kabi_status(die, &state->kabi.orig_name); 606 + 607 + if (res == KABI_RESERVED) 608 + state->kabi.placeholder = type; 609 + if (res != KABI_NORMAL) 610 + return res; 611 + 612 + if (dwarf_tag(&type) == DW_TAG_structure_type) 613 + res = checkp(process_die_container( 614 + state, NULL, &type, check_struct_member_kabi_status, 615 + match_member_type)); 616 + 617 + if (res <= KABI_NORMAL && ++state->kabi.members < 2) 618 + return 0; /* Continue */ 619 + 620 + return res; 621 + } 622 + 623 + static int get_union_kabi_status(Dwarf_Die *die, Dwarf_Die *placeholder, 624 + const char **orig_name) 625 + { 626 + struct state state; 627 + int res; 628 + 629 + if (!stable) 630 + return KABI_NORMAL; 631 + 632 + /* 633 + * To maintain a stable kABI, distributions may choose to reserve 634 + * space in structs for later use by adding placeholder members, 635 + * for example: 636 + * 637 + * struct s { 638 + * u32 a; 639 + * // an 8-byte placeholder for future use 640 + * u64 __kabi_reserved_0; 641 + * }; 642 + * 643 + * When the reserved member is taken into use, the type change 644 + * would normally cause the symbol version to change as well, but 645 + * if the replacement uses the following convention, gendwarfksyms 646 + * continues to use the placeholder type for versioning instead, 647 + * thus maintaining the same symbol version: 648 + * 649 + * struct s { 650 + * u32 a; 651 + * union { 652 + * // placeholder replaced with a new member `b` 653 + * struct t b; 654 + * struct { 655 + * // the placeholder type that is still 656 + * // used for versioning 657 + * u64 __kabi_reserved_0; 658 + * }; 659 + * }; 660 + * }; 661 + * 662 + * I.e., as long as the replaced member is in a union, and the 663 + * placeholder has a __kabi_reserved name prefix, we'll continue 664 + * to use the placeholder type (here u64) for version calculation 665 + * instead of the union type. 666 + * 667 + * It's also possible to ignore new members from versioning if 668 + * they've been added to alignment holes, for example, by 669 + * including them in a union with another member that uses the 670 + * __kabi_ignored name prefix: 671 + * 672 + * struct s { 673 + * u32 a; 674 + * // an alignment hole is used to add `n` 675 + * union { 676 + * u32 n; 677 + * // hide the entire union member from versioning 678 + * u8 __kabi_ignored_0; 679 + * }; 680 + * u64 b; 681 + * }; 682 + * 683 + * Note that the user of this feature is responsible for ensuring 684 + * that the structure actually remains ABI compatible. 685 + */ 686 + memset(&state.kabi, 0, sizeof(struct kabi_state)); 687 + 688 + res = checkp(process_die_container(&state, NULL, die, 689 + check_union_member_kabi_status, 690 + match_member_type)); 691 + 692 + if (res == KABI_RESERVED) { 693 + if (placeholder) 694 + *placeholder = state.kabi.placeholder; 695 + if (orig_name) 696 + *orig_name = state.kabi.orig_name; 697 + } 698 + 699 + return res; 700 + } 701 + 702 + static bool is_kabi_ignored(Dwarf_Die *die) 703 + { 704 + Dwarf_Die type; 705 + 706 + if (!stable) 707 + return false; 708 + 709 + if (!get_ref_die_attr(die, DW_AT_type, &type)) 710 + error("member missing a type?"); 711 + 712 + return dwarf_tag(&type) == DW_TAG_union_type && 713 + checkp(get_union_kabi_status(&type, NULL, NULL)) == KABI_IGNORED; 714 + } 715 + 716 + static int ___process_structure_type(struct state *state, struct die *cache, 717 + Dwarf_Die *die) 718 + { 719 + switch (dwarf_tag(die)) { 720 + case DW_TAG_member: 721 + if (is_kabi_ignored(die)) 722 + return 0; 723 + return check(process_type(state, cache, die)); 724 + case DW_TAG_variant_part: 725 + return check(process_type(state, cache, die)); 726 + case DW_TAG_class_type: 727 + case DW_TAG_enumeration_type: 728 + case DW_TAG_structure_type: 729 + case DW_TAG_template_type_parameter: 730 + case DW_TAG_union_type: 731 + case DW_TAG_subprogram: 732 + /* Skip non-member types, including member functions */ 733 + return 0; 734 + default: 735 + error("unexpected structure_type child: %x", dwarf_tag(die)); 736 + } 737 + } 738 + 739 + static void __process_structure_type(struct state *state, struct die *cache, 740 + Dwarf_Die *die, const char *type, 741 + die_callback_t process_func, 742 + die_match_callback_t match_func) 743 + { 744 + bool expand; 745 + 746 + process(cache, type); 747 + process_fqn(cache, die); 748 + process(cache, " {"); 749 + process_linebreak(cache, 1); 750 + 751 + expand = state->expand.expand && is_kabi_definition(cache, die); 752 + 753 + if (expand) { 754 + state->expand.current_fqn = cache->fqn; 755 + check(process_die_container(state, cache, die, process_func, 756 + match_func)); 757 + } 758 + 759 + process_linebreak(cache, -1); 760 + process(cache, "}"); 761 + 762 + if (expand) { 763 + process_byte_size_attr(cache, die); 764 + process_alignment_attr(cache, die); 765 + } 766 + } 767 + 768 + #define DEFINE_PROCESS_STRUCTURE_TYPE(structure) \ 769 + static void process_##structure##_type( \ 770 + struct state *state, struct die *cache, Dwarf_Die *die) \ 771 + { \ 772 + __process_structure_type(state, cache, die, \ 773 + #structure "_type", \ 774 + ___process_structure_type, \ 775 + match_all); \ 776 + } 777 + 778 + DEFINE_PROCESS_STRUCTURE_TYPE(class) 779 + DEFINE_PROCESS_STRUCTURE_TYPE(structure) 780 + 781 + static void process_union_type(struct state *state, struct die *cache, 782 + Dwarf_Die *die) 783 + { 784 + Dwarf_Die placeholder; 785 + 786 + int res = checkp(get_union_kabi_status(die, &placeholder, 787 + &state->kabi.orig_name)); 788 + 789 + if (res == KABI_RESERVED) 790 + check(process_type(state, cache, &placeholder)); 791 + if (res > KABI_NORMAL) 792 + return; 793 + 794 + __process_structure_type(state, cache, die, "union_type", 795 + ___process_structure_type, match_all); 796 + } 797 + 798 + static void process_enumerator_type(struct state *state, struct die *cache, 799 + Dwarf_Die *die) 800 + { 801 + bool overridden = false; 802 + Dwarf_Word value; 803 + 804 + if (stable) { 805 + /* Get the fqn before we process anything */ 806 + update_fqn(cache, die); 807 + 808 + if (kabi_is_enumerator_ignored(state->expand.current_fqn, 809 + cache->fqn)) 810 + return; 811 + 812 + overridden = kabi_get_enumerator_value( 813 + state->expand.current_fqn, cache->fqn, &value); 814 + } 815 + 816 + process_list_comma(state, cache); 817 + process(cache, "enumerator"); 818 + process_fqn(cache, die); 819 + 820 + if (overridden || get_udata_attr(die, DW_AT_const_value, &value)) { 821 + process(cache, " = "); 822 + process_fmt(cache, "%" PRIu64, value); 823 + } 824 + } 825 + 826 + static void process_enumeration_type(struct state *state, struct die *cache, 827 + Dwarf_Die *die) 828 + { 829 + __process_structure_type(state, cache, die, "enumeration_type", 830 + process_type, match_enumerator_type); 831 + } 832 + 833 + static void process_base_type(struct state *state, struct die *cache, 834 + Dwarf_Die *die) 835 + { 836 + process(cache, "base_type"); 837 + process_fqn(cache, die); 838 + process_byte_size_attr(cache, die); 839 + process_encoding_attr(cache, die); 840 + process_alignment_attr(cache, die); 841 + } 842 + 843 + static void process_unspecified_type(struct state *state, struct die *cache, 844 + Dwarf_Die *die) 845 + { 846 + /* 847 + * These can be emitted for stand-alone assembly code, which means we 848 + * might run into them in vmlinux.o. 849 + */ 850 + process(cache, "unspecified_type"); 851 + } 852 + 853 + static void process_cached(struct state *state, struct die *cache, 854 + Dwarf_Die *die) 855 + { 856 + struct die_fragment *df; 857 + Dwarf_Die child; 858 + 859 + list_for_each_entry(df, &cache->fragments, list) { 860 + switch (df->type) { 861 + case FRAGMENT_STRING: 862 + die_debug_b("cache %p STRING '%s'", cache, 863 + df->data.str); 864 + process(NULL, df->data.str); 865 + break; 866 + case FRAGMENT_LINEBREAK: 867 + process_linebreak(NULL, df->data.linebreak); 868 + break; 869 + case FRAGMENT_DIE: 870 + if (!dwarf_die_addr_die(dwarf_cu_getdwarf(die->cu), 871 + (void *)df->data.addr, &child)) 872 + error("dwarf_die_addr_die failed"); 873 + die_debug_b("cache %p DIE addr %" PRIxPTR " tag %x", 874 + cache, df->data.addr, dwarf_tag(&child)); 875 + check(process_type(state, NULL, &child)); 876 + break; 877 + default: 878 + error("empty die_fragment"); 879 + } 880 + } 881 + } 882 + 883 + static void state_init(struct state *state) 884 + { 885 + state->expand.expand = true; 886 + state->expand.current_fqn = NULL; 887 + cache_init(&state->expansion_cache); 888 + } 889 + 890 + static void expansion_state_restore(struct expansion_state *state, 891 + struct expansion_state *saved) 892 + { 893 + state->expand = saved->expand; 894 + state->current_fqn = saved->current_fqn; 895 + } 896 + 897 + static void expansion_state_save(struct expansion_state *state, 898 + struct expansion_state *saved) 899 + { 900 + expansion_state_restore(saved, state); 901 + } 902 + 903 + static bool is_expanded_type(int tag) 904 + { 905 + return tag == DW_TAG_class_type || tag == DW_TAG_structure_type || 906 + tag == DW_TAG_union_type || tag == DW_TAG_enumeration_type; 907 + } 908 + 909 + #define PROCESS_TYPE(type) \ 910 + case DW_TAG_##type##_type: \ 911 + process_##type##_type(state, cache, die); \ 912 + break; 913 + 914 + static int process_type(struct state *state, struct die *parent, Dwarf_Die *die) 915 + { 916 + enum die_state want_state = DIE_COMPLETE; 917 + struct die *cache; 918 + struct expansion_state saved; 919 + int tag = dwarf_tag(die); 920 + 921 + expansion_state_save(&state->expand, &saved); 922 + 923 + /* 924 + * Structures and enumeration types are expanded only once per 925 + * exported symbol. This is sufficient for detecting ABI changes 926 + * within the structure. 927 + */ 928 + if (is_expanded_type(tag)) { 929 + if (cache_was_expanded(&state->expansion_cache, die->addr)) 930 + state->expand.expand = false; 931 + 932 + if (state->expand.expand) 933 + cache_mark_expanded(&state->expansion_cache, die->addr); 934 + else 935 + want_state = DIE_UNEXPANDED; 936 + } 937 + 938 + /* 939 + * If we have want_state already cached, use it instead of walking 940 + * through DWARF. 941 + */ 942 + cache = die_map_get(die, want_state); 943 + 944 + if (cache->state == want_state) { 945 + die_debug_g("cached addr %p tag %x -- %s", die->addr, tag, 946 + die_state_name(cache->state)); 947 + 948 + process_cached(state, cache, die); 949 + die_map_add_die(parent, cache); 950 + 951 + expansion_state_restore(&state->expand, &saved); 952 + return 0; 953 + } 954 + 955 + die_debug_g("addr %p tag %x -- %s -> %s", die->addr, tag, 956 + die_state_name(cache->state), die_state_name(want_state)); 957 + 958 + switch (tag) { 959 + /* Type modifiers */ 960 + PROCESS_TYPE(atomic) 961 + PROCESS_TYPE(const) 962 + PROCESS_TYPE(immutable) 963 + PROCESS_TYPE(packed) 964 + PROCESS_TYPE(pointer) 965 + PROCESS_TYPE(reference) 966 + PROCESS_TYPE(restrict) 967 + PROCESS_TYPE(rvalue_reference) 968 + PROCESS_TYPE(shared) 969 + PROCESS_TYPE(volatile) 970 + /* Container types */ 971 + PROCESS_TYPE(class) 972 + PROCESS_TYPE(structure) 973 + PROCESS_TYPE(union) 974 + PROCESS_TYPE(enumeration) 975 + /* Subtypes */ 976 + PROCESS_TYPE(enumerator) 977 + PROCESS_TYPE(formal_parameter) 978 + PROCESS_TYPE(member) 979 + PROCESS_TYPE(subrange) 980 + PROCESS_TYPE(template_type_parameter) 981 + PROCESS_TYPE(variant) 982 + PROCESS_TYPE(variant_part) 983 + /* Other types */ 984 + PROCESS_TYPE(array) 985 + PROCESS_TYPE(base) 986 + PROCESS_TYPE(subroutine) 987 + PROCESS_TYPE(typedef) 988 + PROCESS_TYPE(unspecified) 989 + default: 990 + error("unexpected type: %x", tag); 991 + } 992 + 993 + die_debug_r("parent %p cache %p die addr %p tag %x", parent, cache, 994 + die->addr, tag); 995 + 996 + /* Update cache state and append to the parent (if any) */ 997 + cache->tag = tag; 998 + cache->state = want_state; 999 + die_map_add_die(parent, cache); 1000 + 1001 + expansion_state_restore(&state->expand, &saved); 1002 + return 0; 1003 + } 1004 + 1005 + /* 1006 + * Exported symbol processing 1007 + */ 1008 + static struct die *get_symbol_cache(struct state *state, Dwarf_Die *die) 1009 + { 1010 + struct die *cache; 1011 + 1012 + cache = die_map_get(die, DIE_SYMBOL); 1013 + 1014 + if (cache->state != DIE_INCOMPLETE) 1015 + return NULL; /* We already processed a symbol for this DIE */ 1016 + 1017 + cache->tag = dwarf_tag(die); 1018 + return cache; 1019 + } 1020 + 1021 + static void process_symbol(struct state *state, Dwarf_Die *die, 1022 + die_callback_t process_func) 1023 + { 1024 + struct die *cache; 1025 + 1026 + symbol_set_die(state->sym, die); 1027 + 1028 + cache = get_symbol_cache(state, die); 1029 + if (!cache) 1030 + return; 1031 + 1032 + debug("%s", state->sym->name); 1033 + check(process_func(state, cache, die)); 1034 + cache->state = DIE_SYMBOL; 1035 + if (dump_dies) 1036 + fputs("\n", stderr); 1037 + } 1038 + 1039 + static int __process_subprogram(struct state *state, struct die *cache, 1040 + Dwarf_Die *die) 1041 + { 1042 + __process_subroutine_type(state, cache, die, "subprogram"); 1043 + return 0; 1044 + } 1045 + 1046 + static void process_subprogram(struct state *state, Dwarf_Die *die) 1047 + { 1048 + process_symbol(state, die, __process_subprogram); 1049 + } 1050 + 1051 + static int __process_variable(struct state *state, struct die *cache, 1052 + Dwarf_Die *die) 1053 + { 1054 + process(cache, "variable "); 1055 + process_type_attr(state, cache, die); 1056 + return 0; 1057 + } 1058 + 1059 + static void process_variable(struct state *state, Dwarf_Die *die) 1060 + { 1061 + process_symbol(state, die, __process_variable); 1062 + } 1063 + 1064 + static void save_symbol_ptr(struct state *state) 1065 + { 1066 + Dwarf_Die ptr_type; 1067 + Dwarf_Die type; 1068 + 1069 + if (!get_ref_die_attr(&state->die, DW_AT_type, &ptr_type) || 1070 + dwarf_tag(&ptr_type) != DW_TAG_pointer_type) 1071 + error("%s must be a pointer type!", 1072 + get_symbol_name(&state->die)); 1073 + 1074 + if (!get_ref_die_attr(&ptr_type, DW_AT_type, &type)) 1075 + error("%s pointer missing a type attribute?", 1076 + get_symbol_name(&state->die)); 1077 + 1078 + /* 1079 + * Save the symbol pointer DIE in case the actual symbol is 1080 + * missing from the DWARF. Clang, for example, intentionally 1081 + * omits external symbols from the debugging information. 1082 + */ 1083 + if (dwarf_tag(&type) == DW_TAG_subroutine_type) 1084 + symbol_set_ptr(state->sym, &type); 1085 + else 1086 + symbol_set_ptr(state->sym, &ptr_type); 1087 + } 1088 + 1089 + static int process_exported_symbols(struct state *unused, struct die *cache, 1090 + Dwarf_Die *die) 1091 + { 1092 + int tag = dwarf_tag(die); 1093 + 1094 + switch (tag) { 1095 + /* Possible containers of exported symbols */ 1096 + case DW_TAG_namespace: 1097 + case DW_TAG_class_type: 1098 + case DW_TAG_structure_type: 1099 + return check(process_die_container( 1100 + NULL, cache, die, process_exported_symbols, match_all)); 1101 + 1102 + /* Possible exported symbols */ 1103 + case DW_TAG_subprogram: 1104 + case DW_TAG_variable: { 1105 + struct state state; 1106 + 1107 + if (!match_export_symbol(&state, die)) 1108 + return 0; 1109 + 1110 + state_init(&state); 1111 + 1112 + if (is_symbol_ptr(get_symbol_name(&state.die))) 1113 + save_symbol_ptr(&state); 1114 + else if (tag == DW_TAG_subprogram) 1115 + process_subprogram(&state, &state.die); 1116 + else 1117 + process_variable(&state, &state.die); 1118 + 1119 + cache_free(&state.expansion_cache); 1120 + return 0; 1121 + } 1122 + default: 1123 + return 0; 1124 + } 1125 + } 1126 + 1127 + static void process_symbol_ptr(struct symbol *sym, void *arg) 1128 + { 1129 + struct state state; 1130 + Dwarf *dwarf = arg; 1131 + 1132 + if (sym->state != SYMBOL_UNPROCESSED || !sym->ptr_die_addr) 1133 + return; 1134 + 1135 + debug("%s", sym->name); 1136 + state_init(&state); 1137 + state.sym = sym; 1138 + 1139 + if (!dwarf_die_addr_die(dwarf, (void *)sym->ptr_die_addr, &state.die)) 1140 + error("dwarf_die_addr_die failed for symbol ptr: '%s'", 1141 + sym->name); 1142 + 1143 + if (dwarf_tag(&state.die) == DW_TAG_subroutine_type) 1144 + process_subprogram(&state, &state.die); 1145 + else 1146 + process_variable(&state, &state.die); 1147 + 1148 + cache_free(&state.expansion_cache); 1149 + } 1150 + 1151 + void process_cu(Dwarf_Die *cudie) 1152 + { 1153 + check(process_die_container(NULL, NULL, cudie, process_exported_symbols, 1154 + match_all)); 1155 + 1156 + symbol_for_each(process_symbol_ptr, dwarf_cu_getdwarf(cudie->cu)); 1157 + 1158 + cache_free(&srcfile_cache); 1159 + }
+157
scripts/gendwarfksyms/examples/kabi.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * Copyright (C) 2024 Google LLC 4 + * 5 + * Example macros for maintaining kABI stability. 6 + * 7 + * This file is based on android_kabi.h, which has the following notice: 8 + * 9 + * Heavily influenced by rh_kabi.h which came from the RHEL/CENTOS kernel 10 + * and was: 11 + * Copyright (c) 2014 Don Zickus 12 + * Copyright (c) 2015-2018 Jiri Benc 13 + * Copyright (c) 2015 Sabrina Dubroca, Hannes Frederic Sowa 14 + * Copyright (c) 2016-2018 Prarit Bhargava 15 + * Copyright (c) 2017 Paolo Abeni, Larry Woodman 16 + */ 17 + 18 + #ifndef __KABI_H__ 19 + #define __KABI_H__ 20 + 21 + /* Kernel macros for userspace testing. */ 22 + #ifndef __aligned 23 + #define __aligned(x) __attribute__((__aligned__(x))) 24 + #endif 25 + #ifndef __used 26 + #define __used __attribute__((__used__)) 27 + #endif 28 + #ifndef __section 29 + #define __section(section) __attribute__((__section__(section))) 30 + #endif 31 + #ifndef __PASTE 32 + #define ___PASTE(a, b) a##b 33 + #define __PASTE(a, b) ___PASTE(a, b) 34 + #endif 35 + #ifndef __stringify 36 + #define __stringify_1(x...) #x 37 + #define __stringify(x...) __stringify_1(x) 38 + #endif 39 + 40 + #define __KABI_RULE(hint, target, value) \ 41 + static const char __PASTE(__gendwarfksyms_rule_, \ 42 + __COUNTER__)[] __used __aligned(1) \ 43 + __section(".discard.gendwarfksyms.kabi_rules") = \ 44 + "1\0" #hint "\0" #target "\0" #value 45 + 46 + #define __KABI_NORMAL_SIZE_ALIGN(_orig, _new) \ 47 + union { \ 48 + _Static_assert( \ 49 + sizeof(struct { _new; }) <= sizeof(struct { _orig; }), \ 50 + __FILE__ ":" __stringify(__LINE__) ": " __stringify( \ 51 + _new) " is larger than " __stringify(_orig)); \ 52 + _Static_assert( \ 53 + __alignof__(struct { _new; }) <= \ 54 + __alignof__(struct { _orig; }), \ 55 + __FILE__ ":" __stringify(__LINE__) ": " __stringify( \ 56 + _orig) " is not aligned the same as " __stringify(_new)); \ 57 + } 58 + 59 + #define __KABI_REPLACE(_orig, _new) \ 60 + union { \ 61 + _new; \ 62 + struct { \ 63 + _orig; \ 64 + }; \ 65 + __KABI_NORMAL_SIZE_ALIGN(_orig, _new); \ 66 + } 67 + 68 + /* 69 + * KABI_DECLONLY(fqn) 70 + * Treat the struct/union/enum fqn as a declaration, i.e. even if 71 + * a definition is available, don't expand the contents. 72 + */ 73 + #define KABI_DECLONLY(fqn) __KABI_RULE(declonly, fqn, ) 74 + 75 + /* 76 + * KABI_ENUMERATOR_IGNORE(fqn, field) 77 + * When expanding enum fqn, skip the provided field. This makes it 78 + * possible to hide added enum fields from versioning. 79 + */ 80 + #define KABI_ENUMERATOR_IGNORE(fqn, field) \ 81 + __KABI_RULE(enumerator_ignore, fqn field, ) 82 + 83 + /* 84 + * KABI_ENUMERATOR_VALUE(fqn, field, value) 85 + * When expanding enum fqn, use the provided value for the 86 + * specified field. This makes it possible to override enumerator 87 + * values when calculating versions. 88 + */ 89 + #define KABI_ENUMERATOR_VALUE(fqn, field, value) \ 90 + __KABI_RULE(enumerator_value, fqn field, value) 91 + 92 + /* 93 + * KABI_RESERVE 94 + * Reserve some "padding" in a structure for use by LTS backports. 95 + * This is normally placed at the end of a structure. 96 + * number: the "number" of the padding variable in the structure. Start with 97 + * 1 and go up. 98 + */ 99 + #define KABI_RESERVE(n) unsigned long __kabi_reserved##n 100 + 101 + /* 102 + * KABI_RESERVE_ARRAY 103 + * Same as _BACKPORT_RESERVE but allocates an array with the specified 104 + * size in bytes. 105 + */ 106 + #define KABI_RESERVE_ARRAY(n, s) \ 107 + unsigned char __aligned(8) __kabi_reserved##n[s] 108 + 109 + /* 110 + * KABI_IGNORE 111 + * Add a new field that's ignored in versioning. 112 + */ 113 + #define KABI_IGNORE(n, _new) \ 114 + union { \ 115 + _new; \ 116 + unsigned char __kabi_ignored##n; \ 117 + } 118 + 119 + /* 120 + * KABI_REPLACE 121 + * Replace a field with a compatible new field. 122 + */ 123 + #define KABI_REPLACE(_oldtype, _oldname, _new) \ 124 + __KABI_REPLACE(_oldtype __kabi_renamed##_oldname, struct { _new; }) 125 + 126 + /* 127 + * KABI_USE(number, _new) 128 + * Use a previous padding entry that was defined with KABI_RESERVE 129 + * number: the previous "number" of the padding variable 130 + * _new: the variable to use now instead of the padding variable 131 + */ 132 + #define KABI_USE(number, _new) __KABI_REPLACE(KABI_RESERVE(number), _new) 133 + 134 + /* 135 + * KABI_USE2(number, _new1, _new2) 136 + * Use a previous padding entry that was defined with KABI_RESERVE for 137 + * two new variables that fit into 64 bits. This is good for when you do not 138 + * want to "burn" a 64bit padding variable for a smaller variable size if not 139 + * needed. 140 + */ 141 + #define KABI_USE2(number, _new1, _new2) \ 142 + __KABI_REPLACE( \ 143 + KABI_RESERVE(number), struct { \ 144 + _new1; \ 145 + _new2; \ 146 + }) 147 + /* 148 + * KABI_USE_ARRAY(number, bytes, _new) 149 + * Use a previous padding entry that was defined with KABI_RESERVE_ARRAY 150 + * number: the previous "number" of the padding variable 151 + * bytes: the size in bytes reserved for the array 152 + * _new: the variable to use now instead of the padding variable 153 + */ 154 + #define KABI_USE_ARRAY(number, bytes, _new) \ 155 + __KABI_REPLACE(KABI_RESERVE_ARRAY(number, bytes), _new) 156 + 157 + #endif /* __KABI_H__ */
+30
scripts/gendwarfksyms/examples/kabi_ex.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * kabi_ex.c 4 + * 5 + * Copyright (C) 2024 Google LLC 6 + * 7 + * Examples for kABI stability features with --stable. See kabi_ex.h 8 + * for details. 9 + */ 10 + 11 + #include "kabi_ex.h" 12 + 13 + struct s e0; 14 + enum e e1; 15 + 16 + struct ex0a ex0a; 17 + struct ex0b ex0b; 18 + struct ex0c ex0c; 19 + 20 + struct ex1a ex1a; 21 + struct ex1b ex1b; 22 + struct ex1c ex1c; 23 + 24 + struct ex2a ex2a; 25 + struct ex2b ex2b; 26 + struct ex2c ex2c; 27 + 28 + struct ex3a ex3a; 29 + struct ex3b ex3b; 30 + struct ex3c ex3c;
+263
scripts/gendwarfksyms/examples/kabi_ex.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * kabi_ex.h 4 + * 5 + * Copyright (C) 2024 Google LLC 6 + * 7 + * Examples for kABI stability features with --stable. 8 + */ 9 + 10 + /* 11 + * The comments below each example contain the expected gendwarfksyms 12 + * output, which can be verified using LLVM's FileCheck tool: 13 + * 14 + * https://llvm.org/docs/CommandGuide/FileCheck.html 15 + * 16 + * Usage: 17 + * 18 + * $ gcc -g -c examples/kabi_ex.c -o examples/kabi_ex.o 19 + * 20 + * $ nm examples/kabi_ex.o | awk '{ print $NF }' | \ 21 + * ./gendwarfksyms --stable --dump-dies \ 22 + * examples/kabi_ex.o 2>&1 >/dev/null | \ 23 + * FileCheck examples/kabi_ex.h --check-prefix=STABLE 24 + */ 25 + 26 + #ifndef __KABI_EX_H__ 27 + #define __KABI_EX_H__ 28 + 29 + #include "kabi.h" 30 + 31 + /* 32 + * Example: kABI rules 33 + */ 34 + 35 + struct s { 36 + int a; 37 + }; 38 + 39 + KABI_DECLONLY(s); 40 + 41 + /* 42 + * STABLE: variable structure_type s { 43 + * STABLE-NEXT: } 44 + */ 45 + 46 + enum e { 47 + A, 48 + B, 49 + C, 50 + D, 51 + }; 52 + 53 + KABI_ENUMERATOR_IGNORE(e, B); 54 + KABI_ENUMERATOR_IGNORE(e, C); 55 + KABI_ENUMERATOR_VALUE(e, D, 123456789); 56 + 57 + /* 58 + * STABLE: variable enumeration_type e { 59 + * STABLE-NEXT: enumerator A = 0 , 60 + * STABLE-NEXT: enumerator D = 123456789 61 + * STABLE-NEXT: } byte_size(4) 62 + */ 63 + 64 + /* 65 + * Example: Reserved fields 66 + */ 67 + struct ex0a { 68 + int a; 69 + KABI_RESERVE(0); 70 + KABI_RESERVE(1); 71 + }; 72 + 73 + /* 74 + * STABLE: variable structure_type ex0a { 75 + * STABLE-NEXT: member base_type int byte_size(4) encoding(5) a data_member_location(0) , 76 + * STABLE-NEXT: member base_type [[ULONG:long unsigned int|unsigned long]] byte_size(8) encoding(7) data_member_location(8) , 77 + * STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) data_member_location(16) 78 + * STABLE-NEXT: } byte_size(24) 79 + */ 80 + 81 + struct ex0b { 82 + int a; 83 + KABI_RESERVE(0); 84 + KABI_USE2(1, int b, int c); 85 + }; 86 + 87 + /* 88 + * STABLE: variable structure_type ex0b { 89 + * STABLE-NEXT: member base_type int byte_size(4) encoding(5) a data_member_location(0) , 90 + * STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) data_member_location(8) , 91 + * STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) data_member_location(16) 92 + * STABLE-NEXT: } byte_size(24) 93 + */ 94 + 95 + struct ex0c { 96 + int a; 97 + KABI_USE(0, void *p); 98 + KABI_USE2(1, int b, int c); 99 + }; 100 + 101 + /* 102 + * STABLE: variable structure_type ex0c { 103 + * STABLE-NEXT: member base_type int byte_size(4) encoding(5) a data_member_location(0) , 104 + * STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) data_member_location(8) , 105 + * STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) data_member_location(16) 106 + * STABLE-NEXT: } byte_size(24) 107 + */ 108 + 109 + /* 110 + * Example: A reserved array 111 + */ 112 + 113 + struct ex1a { 114 + unsigned int a; 115 + KABI_RESERVE_ARRAY(0, 64); 116 + }; 117 + 118 + /* 119 + * STABLE: variable structure_type ex1a { 120 + * STABLE-NEXT: member base_type unsigned int byte_size(4) encoding(7) a data_member_location(0) , 121 + * STABLE-NEXT: member array_type[64] { 122 + * STABLE-NEXT: base_type unsigned char byte_size(1) encoding(8) 123 + * STABLE-NEXT: } data_member_location(8) 124 + * STABLE-NEXT: } byte_size(72) 125 + */ 126 + 127 + struct ex1b { 128 + unsigned int a; 129 + KABI_USE_ARRAY( 130 + 0, 64, struct { 131 + void *p; 132 + KABI_RESERVE_ARRAY(1, 56); 133 + }); 134 + }; 135 + 136 + /* 137 + * STABLE: variable structure_type ex1b { 138 + * STABLE-NEXT: member base_type unsigned int byte_size(4) encoding(7) a data_member_location(0) , 139 + * STABLE-NEXT: member array_type[64] { 140 + * STABLE-NEXT: base_type unsigned char byte_size(1) encoding(8) 141 + * STABLE-NEXT: } data_member_location(8) 142 + * STABLE-NEXT: } byte_size(72) 143 + */ 144 + 145 + struct ex1c { 146 + unsigned int a; 147 + KABI_USE_ARRAY(0, 64, void *p[8]); 148 + }; 149 + 150 + /* 151 + * STABLE: variable structure_type ex1c { 152 + * STABLE-NEXT: member base_type unsigned int byte_size(4) encoding(7) a data_member_location(0) , 153 + * STABLE-NEXT: member array_type[64] { 154 + * STABLE-NEXT: base_type unsigned char byte_size(1) encoding(8) 155 + * STABLE-NEXT: } data_member_location(8) 156 + * STABLE-NEXT: } byte_size(72) 157 + */ 158 + 159 + /* 160 + * Example: An ignored field added to an alignment hole 161 + */ 162 + 163 + struct ex2a { 164 + int a; 165 + unsigned long b; 166 + int c; 167 + unsigned long d; 168 + }; 169 + 170 + /* 171 + * STABLE: variable structure_type ex2a { 172 + * STABLE-NEXT: member base_type int byte_size(4) encoding(5) a data_member_location(0) , 173 + * STABLE-NEXT: member base_type [[ULONG:long unsigned int|unsigned long]] byte_size(8) encoding(7) b data_member_location(8) 174 + * STABLE-NEXT: member base_type int byte_size(4) encoding(5) c data_member_location(16) , 175 + * STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) d data_member_location(24) 176 + * STABLE-NEXT: } byte_size(32) 177 + */ 178 + 179 + struct ex2b { 180 + int a; 181 + KABI_IGNORE(0, unsigned int n); 182 + unsigned long b; 183 + int c; 184 + unsigned long d; 185 + }; 186 + 187 + _Static_assert(sizeof(struct ex2a) == sizeof(struct ex2b), "ex2a size doesn't match ex2b"); 188 + 189 + /* 190 + * STABLE: variable structure_type ex2b { 191 + * STABLE-NEXT: member base_type int byte_size(4) encoding(5) a data_member_location(0) , 192 + * STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) b data_member_location(8) 193 + * STABLE-NEXT: member base_type int byte_size(4) encoding(5) c data_member_location(16) , 194 + * STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) d data_member_location(24) 195 + * STABLE-NEXT: } byte_size(32) 196 + */ 197 + 198 + struct ex2c { 199 + int a; 200 + KABI_IGNORE(0, unsigned int n); 201 + unsigned long b; 202 + int c; 203 + KABI_IGNORE(1, unsigned int m); 204 + unsigned long d; 205 + }; 206 + 207 + _Static_assert(sizeof(struct ex2a) == sizeof(struct ex2c), "ex2a size doesn't match ex2c"); 208 + 209 + /* 210 + * STABLE: variable structure_type ex2c { 211 + * STABLE-NEXT: member base_type int byte_size(4) encoding(5) a data_member_location(0) , 212 + * STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) b data_member_location(8) 213 + * STABLE-NEXT: member base_type int byte_size(4) encoding(5) c data_member_location(16) , 214 + * STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) d data_member_location(24) 215 + * STABLE-NEXT: } byte_size(32) 216 + */ 217 + 218 + 219 + /* 220 + * Example: A replaced field 221 + */ 222 + 223 + struct ex3a { 224 + unsigned long a; 225 + unsigned long unused; 226 + }; 227 + 228 + /* 229 + * STABLE: variable structure_type ex3a { 230 + * STABLE-NEXT: member base_type [[ULONG:long unsigned int|unsigned long]] byte_size(8) encoding(7) a data_member_location(0) 231 + * STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) unused data_member_location(8) 232 + * STABLE-NEXT: } byte_size(16) 233 + */ 234 + 235 + struct ex3b { 236 + unsigned long a; 237 + KABI_REPLACE(unsigned long, unused, unsigned long renamed); 238 + }; 239 + 240 + _Static_assert(sizeof(struct ex3a) == sizeof(struct ex3b), "ex3a size doesn't match ex3b"); 241 + 242 + /* 243 + * STABLE: variable structure_type ex3b { 244 + * STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) a data_member_location(0) 245 + * STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) unused data_member_location(8) 246 + * STABLE-NEXT: } byte_size(16) 247 + */ 248 + 249 + struct ex3c { 250 + unsigned long a; 251 + KABI_REPLACE(unsigned long, unused, long replaced); 252 + }; 253 + 254 + _Static_assert(sizeof(struct ex3a) == sizeof(struct ex3c), "ex3a size doesn't match ex3c"); 255 + 256 + /* 257 + * STABLE: variable structure_type ex3c { 258 + * STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) a data_member_location(0) 259 + * STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) unused data_member_location(8) 260 + * STABLE-NEXT: } byte_size(16) 261 + */ 262 + 263 + #endif /* __KABI_EX_H__ */
+33
scripts/gendwarfksyms/examples/symbolptr.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Copyright (C) 2024 Google LLC 4 + * 5 + * Example for symbol pointers. When compiled with Clang, gendwarfkyms 6 + * uses a symbol pointer for `f`. 7 + * 8 + * $ clang -g -c examples/symbolptr.c -o examples/symbolptr.o 9 + * $ echo -e "f\ng\np" | ./gendwarfksyms -d examples/symbolptr.o 10 + */ 11 + 12 + /* Kernel macros for userspace testing. */ 13 + #ifndef __used 14 + #define __used __attribute__((__used__)) 15 + #endif 16 + #ifndef __section 17 + #define __section(section) __attribute__((__section__(section))) 18 + #endif 19 + 20 + #define __GENDWARFKSYMS_EXPORT(sym) \ 21 + static typeof(sym) *__gendwarfksyms_ptr_##sym __used \ 22 + __section(".discard.gendwarfksyms") = &sym; 23 + 24 + extern void f(unsigned int arg); 25 + void g(int *arg); 26 + void g(int *arg) {} 27 + 28 + struct s; 29 + extern struct s *p; 30 + 31 + __GENDWARFKSYMS_EXPORT(f); 32 + __GENDWARFKSYMS_EXPORT(g); 33 + __GENDWARFKSYMS_EXPORT(p);
+187
scripts/gendwarfksyms/gendwarfksyms.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Copyright (C) 2024 Google LLC 4 + */ 5 + 6 + #include <fcntl.h> 7 + #include <getopt.h> 8 + #include <errno.h> 9 + #include <stdarg.h> 10 + #include <string.h> 11 + #include <unistd.h> 12 + #include "gendwarfksyms.h" 13 + 14 + /* 15 + * Options 16 + */ 17 + 18 + /* Print debugging information to stderr */ 19 + int debug; 20 + /* Dump DIE contents */ 21 + int dump_dies; 22 + /* Print debugging information about die_map changes */ 23 + int dump_die_map; 24 + /* Print out type strings (i.e. type_map) */ 25 + int dump_types; 26 + /* Print out expanded type strings used for symbol versions */ 27 + int dump_versions; 28 + /* Support kABI stability features */ 29 + int stable; 30 + /* Write a symtypes file */ 31 + int symtypes; 32 + static const char *symtypes_file; 33 + 34 + static void usage(void) 35 + { 36 + fputs("Usage: gendwarfksyms [options] elf-object-file ... < symbol-list\n\n" 37 + "Options:\n" 38 + " -d, --debug Print debugging information\n" 39 + " --dump-dies Dump DWARF DIE contents\n" 40 + " --dump-die-map Print debugging information about die_map changes\n" 41 + " --dump-types Dump type strings\n" 42 + " --dump-versions Dump expanded type strings used for symbol versions\n" 43 + " -s, --stable Support kABI stability features\n" 44 + " -T, --symtypes file Write a symtypes file\n" 45 + " -h, --help Print this message\n" 46 + "\n", 47 + stderr); 48 + } 49 + 50 + static int process_module(Dwfl_Module *mod, void **userdata, const char *name, 51 + Dwarf_Addr base, void *arg) 52 + { 53 + Dwarf_Addr dwbias; 54 + Dwarf_Die cudie; 55 + Dwarf_CU *cu = NULL; 56 + Dwarf *dbg; 57 + FILE *symfile = arg; 58 + int res; 59 + 60 + debug("%s", name); 61 + dbg = dwfl_module_getdwarf(mod, &dwbias); 62 + 63 + /* 64 + * Look for exported symbols in each CU, follow the DIE tree, and add 65 + * the entries to die_map. 66 + */ 67 + do { 68 + res = dwarf_get_units(dbg, cu, &cu, NULL, NULL, &cudie, NULL); 69 + if (res < 0) 70 + error("dwarf_get_units failed: no debugging information?"); 71 + if (res == 1) 72 + break; /* No more units */ 73 + 74 + process_cu(&cudie); 75 + } while (cu); 76 + 77 + /* 78 + * Use die_map to expand type strings, write them to `symfile`, and 79 + * calculate symbol versions. 80 + */ 81 + generate_symtypes_and_versions(symfile); 82 + die_map_free(); 83 + 84 + return DWARF_CB_OK; 85 + } 86 + 87 + static const Dwfl_Callbacks callbacks = { 88 + .section_address = dwfl_offline_section_address, 89 + .find_debuginfo = dwfl_standard_find_debuginfo, 90 + }; 91 + 92 + int main(int argc, char **argv) 93 + { 94 + FILE *symfile = NULL; 95 + unsigned int n; 96 + int opt; 97 + 98 + static const struct option opts[] = { 99 + { "debug", 0, NULL, 'd' }, 100 + { "dump-dies", 0, &dump_dies, 1 }, 101 + { "dump-die-map", 0, &dump_die_map, 1 }, 102 + { "dump-types", 0, &dump_types, 1 }, 103 + { "dump-versions", 0, &dump_versions, 1 }, 104 + { "stable", 0, NULL, 's' }, 105 + { "symtypes", 1, NULL, 'T' }, 106 + { "help", 0, NULL, 'h' }, 107 + { 0, 0, NULL, 0 } 108 + }; 109 + 110 + while ((opt = getopt_long(argc, argv, "dsT:h", opts, NULL)) != EOF) { 111 + switch (opt) { 112 + case 0: 113 + break; 114 + case 'd': 115 + debug = 1; 116 + break; 117 + case 's': 118 + stable = 1; 119 + break; 120 + case 'T': 121 + symtypes = 1; 122 + symtypes_file = optarg; 123 + break; 124 + case 'h': 125 + usage(); 126 + return 0; 127 + default: 128 + usage(); 129 + return 1; 130 + } 131 + } 132 + 133 + if (dump_die_map) 134 + dump_dies = 1; 135 + 136 + if (optind >= argc) { 137 + usage(); 138 + error("no input files?"); 139 + } 140 + 141 + symbol_read_exports(stdin); 142 + 143 + if (symtypes_file) { 144 + symfile = fopen(symtypes_file, "w"); 145 + if (!symfile) 146 + error("fopen failed for '%s': %s", symtypes_file, 147 + strerror(errno)); 148 + } 149 + 150 + for (n = optind; n < argc; n++) { 151 + Dwfl *dwfl; 152 + int fd; 153 + 154 + fd = open(argv[n], O_RDONLY); 155 + if (fd == -1) 156 + error("open failed for '%s': %s", argv[n], 157 + strerror(errno)); 158 + 159 + symbol_read_symtab(fd); 160 + kabi_read_rules(fd); 161 + 162 + dwfl = dwfl_begin(&callbacks); 163 + if (!dwfl) 164 + error("dwfl_begin failed for '%s': %s", argv[n], 165 + dwarf_errmsg(-1)); 166 + 167 + if (!dwfl_report_offline(dwfl, argv[n], argv[n], fd)) 168 + error("dwfl_report_offline failed for '%s': %s", 169 + argv[n], dwarf_errmsg(-1)); 170 + 171 + dwfl_report_end(dwfl, NULL, NULL); 172 + 173 + if (dwfl_getmodules(dwfl, &process_module, symfile, 0)) 174 + error("dwfl_getmodules failed for '%s'", argv[n]); 175 + 176 + dwfl_end(dwfl); 177 + kabi_free(); 178 + } 179 + 180 + if (symfile) 181 + check(fclose(symfile)); 182 + 183 + symbol_print_versions(); 184 + symbol_free(); 185 + 186 + return 0; 187 + }
+296
scripts/gendwarfksyms/gendwarfksyms.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * Copyright (C) 2024 Google LLC 4 + */ 5 + 6 + #include <dwarf.h> 7 + #include <elfutils/libdw.h> 8 + #include <elfutils/libdwfl.h> 9 + #include <stdlib.h> 10 + #include <stdio.h> 11 + 12 + #include <hash.h> 13 + #include <hashtable.h> 14 + #include <xalloc.h> 15 + 16 + #ifndef __GENDWARFKSYMS_H 17 + #define __GENDWARFKSYMS_H 18 + 19 + /* 20 + * Options -- in gendwarfksyms.c 21 + */ 22 + extern int debug; 23 + extern int dump_dies; 24 + extern int dump_die_map; 25 + extern int dump_types; 26 + extern int dump_versions; 27 + extern int stable; 28 + extern int symtypes; 29 + 30 + /* 31 + * Output helpers 32 + */ 33 + #define __PREFIX "gendwarfksyms: " 34 + #define __println(prefix, format, ...) \ 35 + fprintf(stderr, prefix __PREFIX "%s: " format "\n", __func__, \ 36 + ##__VA_ARGS__) 37 + 38 + #define debug(format, ...) \ 39 + do { \ 40 + if (debug) \ 41 + __println("", format, ##__VA_ARGS__); \ 42 + } while (0) 43 + 44 + #define warn(format, ...) __println("warning: ", format, ##__VA_ARGS__) 45 + #define error(format, ...) \ 46 + do { \ 47 + __println("error: ", format, ##__VA_ARGS__); \ 48 + exit(1); \ 49 + } while (0) 50 + 51 + #define __die_debug(color, format, ...) \ 52 + do { \ 53 + if (dump_dies && dump_die_map) \ 54 + fprintf(stderr, \ 55 + "\033[" #color "m<" format ">\033[39m", \ 56 + __VA_ARGS__); \ 57 + } while (0) 58 + 59 + #define die_debug_r(format, ...) __die_debug(91, format, __VA_ARGS__) 60 + #define die_debug_g(format, ...) __die_debug(92, format, __VA_ARGS__) 61 + #define die_debug_b(format, ...) __die_debug(94, format, __VA_ARGS__) 62 + 63 + /* 64 + * Error handling helpers 65 + */ 66 + #define __check(expr, test) \ 67 + ({ \ 68 + int __res = expr; \ 69 + if (test) \ 70 + error("`%s` failed: %d", #expr, __res); \ 71 + __res; \ 72 + }) 73 + 74 + /* Error == non-zero values */ 75 + #define check(expr) __check(expr, __res) 76 + /* Error == negative values */ 77 + #define checkp(expr) __check(expr, __res < 0) 78 + 79 + /* Consistent aliases (DW_TAG_<type>_type) for DWARF tags */ 80 + #define DW_TAG_enumerator_type DW_TAG_enumerator 81 + #define DW_TAG_formal_parameter_type DW_TAG_formal_parameter 82 + #define DW_TAG_member_type DW_TAG_member 83 + #define DW_TAG_template_type_parameter_type DW_TAG_template_type_parameter 84 + #define DW_TAG_typedef_type DW_TAG_typedef 85 + #define DW_TAG_variant_part_type DW_TAG_variant_part 86 + #define DW_TAG_variant_type DW_TAG_variant 87 + 88 + /* 89 + * symbols.c 90 + */ 91 + 92 + /* See symbols.c:is_symbol_ptr */ 93 + #define SYMBOL_PTR_PREFIX "__gendwarfksyms_ptr_" 94 + #define SYMBOL_PTR_PREFIX_LEN (sizeof(SYMBOL_PTR_PREFIX) - 1) 95 + 96 + static inline unsigned int addr_hash(uintptr_t addr) 97 + { 98 + return hash_ptr((const void *)addr); 99 + } 100 + 101 + enum symbol_state { 102 + SYMBOL_UNPROCESSED, 103 + SYMBOL_MAPPED, 104 + SYMBOL_PROCESSED 105 + }; 106 + 107 + struct symbol_addr { 108 + uint32_t section; 109 + Elf64_Addr address; 110 + }; 111 + 112 + struct symbol { 113 + const char *name; 114 + struct symbol_addr addr; 115 + struct hlist_node addr_hash; 116 + struct hlist_node name_hash; 117 + enum symbol_state state; 118 + uintptr_t die_addr; 119 + uintptr_t ptr_die_addr; 120 + unsigned long crc; 121 + }; 122 + 123 + typedef void (*symbol_callback_t)(struct symbol *, void *arg); 124 + 125 + bool is_symbol_ptr(const char *name); 126 + void symbol_read_exports(FILE *file); 127 + void symbol_read_symtab(int fd); 128 + struct symbol *symbol_get(const char *name); 129 + void symbol_set_ptr(struct symbol *sym, Dwarf_Die *ptr); 130 + void symbol_set_die(struct symbol *sym, Dwarf_Die *die); 131 + void symbol_set_crc(struct symbol *sym, unsigned long crc); 132 + void symbol_for_each(symbol_callback_t func, void *arg); 133 + void symbol_print_versions(void); 134 + void symbol_free(void); 135 + 136 + /* 137 + * die.c 138 + */ 139 + 140 + enum die_state { 141 + DIE_INCOMPLETE, 142 + DIE_UNEXPANDED, 143 + DIE_COMPLETE, 144 + DIE_SYMBOL, 145 + DIE_LAST = DIE_SYMBOL 146 + }; 147 + 148 + enum die_fragment_type { 149 + FRAGMENT_EMPTY, 150 + FRAGMENT_STRING, 151 + FRAGMENT_LINEBREAK, 152 + FRAGMENT_DIE 153 + }; 154 + 155 + struct die_fragment { 156 + enum die_fragment_type type; 157 + union { 158 + char *str; 159 + int linebreak; 160 + uintptr_t addr; 161 + } data; 162 + struct list_head list; 163 + }; 164 + 165 + #define CASE_CONST_TO_STR(name) \ 166 + case name: \ 167 + return #name; 168 + 169 + static inline const char *die_state_name(enum die_state state) 170 + { 171 + switch (state) { 172 + CASE_CONST_TO_STR(DIE_INCOMPLETE) 173 + CASE_CONST_TO_STR(DIE_UNEXPANDED) 174 + CASE_CONST_TO_STR(DIE_COMPLETE) 175 + CASE_CONST_TO_STR(DIE_SYMBOL) 176 + } 177 + 178 + error("unexpected die_state: %d", state); 179 + } 180 + 181 + struct die { 182 + enum die_state state; 183 + bool mapped; 184 + char *fqn; 185 + int tag; 186 + uintptr_t addr; 187 + struct list_head fragments; 188 + struct hlist_node hash; 189 + }; 190 + 191 + typedef void (*die_map_callback_t)(struct die *, void *arg); 192 + 193 + int __die_map_get(uintptr_t addr, enum die_state state, struct die **res); 194 + struct die *die_map_get(Dwarf_Die *die, enum die_state state); 195 + void die_map_add_string(struct die *pd, const char *str); 196 + void die_map_add_linebreak(struct die *pd, int linebreak); 197 + void die_map_for_each(die_map_callback_t func, void *arg); 198 + void die_map_add_die(struct die *pd, struct die *child); 199 + void die_map_free(void); 200 + 201 + /* 202 + * cache.c 203 + */ 204 + 205 + #define CACHE_HASH_BITS 10 206 + 207 + /* A cache for addresses we've already seen. */ 208 + struct cache { 209 + HASHTABLE_DECLARE(cache, 1 << CACHE_HASH_BITS); 210 + }; 211 + 212 + void cache_set(struct cache *cache, unsigned long key, int value); 213 + int cache_get(struct cache *cache, unsigned long key); 214 + void cache_init(struct cache *cache); 215 + void cache_free(struct cache *cache); 216 + 217 + static inline void __cache_mark_expanded(struct cache *cache, uintptr_t addr) 218 + { 219 + cache_set(cache, addr, 1); 220 + } 221 + 222 + static inline bool __cache_was_expanded(struct cache *cache, uintptr_t addr) 223 + { 224 + return cache_get(cache, addr) == 1; 225 + } 226 + 227 + static inline void cache_mark_expanded(struct cache *cache, void *addr) 228 + { 229 + __cache_mark_expanded(cache, (uintptr_t)addr); 230 + } 231 + 232 + static inline bool cache_was_expanded(struct cache *cache, void *addr) 233 + { 234 + return __cache_was_expanded(cache, (uintptr_t)addr); 235 + } 236 + 237 + /* 238 + * dwarf.c 239 + */ 240 + 241 + struct expansion_state { 242 + bool expand; 243 + const char *current_fqn; 244 + }; 245 + 246 + struct kabi_state { 247 + int members; 248 + Dwarf_Die placeholder; 249 + const char *orig_name; 250 + }; 251 + 252 + struct state { 253 + struct symbol *sym; 254 + Dwarf_Die die; 255 + 256 + /* List expansion */ 257 + bool first_list_item; 258 + 259 + /* Structure expansion */ 260 + struct expansion_state expand; 261 + struct cache expansion_cache; 262 + 263 + /* Reserved or ignored members */ 264 + struct kabi_state kabi; 265 + }; 266 + 267 + typedef int (*die_callback_t)(struct state *state, struct die *cache, 268 + Dwarf_Die *die); 269 + typedef bool (*die_match_callback_t)(Dwarf_Die *die); 270 + bool match_all(Dwarf_Die *die); 271 + 272 + int process_die_container(struct state *state, struct die *cache, 273 + Dwarf_Die *die, die_callback_t func, 274 + die_match_callback_t match); 275 + 276 + void process_cu(Dwarf_Die *cudie); 277 + 278 + /* 279 + * types.c 280 + */ 281 + 282 + void generate_symtypes_and_versions(FILE *file); 283 + 284 + /* 285 + * kabi.c 286 + */ 287 + 288 + bool kabi_is_enumerator_ignored(const char *fqn, const char *field); 289 + bool kabi_get_enumerator_value(const char *fqn, const char *field, 290 + unsigned long *value); 291 + bool kabi_is_declonly(const char *fqn); 292 + 293 + void kabi_read_rules(int fd); 294 + void kabi_free(void); 295 + 296 + #endif /* __GENDWARFKSYMS_H */
+336
scripts/gendwarfksyms/kabi.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Copyright (C) 2024 Google LLC 4 + */ 5 + 6 + #define _GNU_SOURCE 7 + #include <errno.h> 8 + #include <stdio.h> 9 + 10 + #include "gendwarfksyms.h" 11 + 12 + #define KABI_RULE_SECTION ".discard.gendwarfksyms.kabi_rules" 13 + #define KABI_RULE_VERSION "1" 14 + 15 + /* 16 + * The rule section consists of four null-terminated strings per 17 + * entry: 18 + * 19 + * 1. version 20 + * Entry format version. Must match KABI_RULE_VERSION. 21 + * 22 + * 2. type 23 + * Type of the kABI rule. Must be one of the tags defined below. 24 + * 25 + * 3. target 26 + * Rule-dependent target, typically the fully qualified name of 27 + * the target DIE. 28 + * 29 + * 4. value 30 + * Rule-dependent value. 31 + */ 32 + #define KABI_RULE_MIN_ENTRY_SIZE \ 33 + (/* version\0 */ 2 + /* type\0 */ 2 + /* target\0" */ 1 + \ 34 + /* value\0 */ 1) 35 + #define KABI_RULE_EMPTY_VALUE "" 36 + 37 + /* 38 + * Rule: declonly 39 + * - For the struct/enum/union in the target field, treat it as a 40 + * declaration only even if a definition is available. 41 + */ 42 + #define KABI_RULE_TAG_DECLONLY "declonly" 43 + 44 + /* 45 + * Rule: enumerator_ignore 46 + * - For the enum_field in the target field, ignore the enumerator. 47 + */ 48 + #define KABI_RULE_TAG_ENUMERATOR_IGNORE "enumerator_ignore" 49 + 50 + /* 51 + * Rule: enumerator_value 52 + * - For the fqn_field in the target field, set the value to the 53 + * unsigned integer in the value field. 54 + */ 55 + #define KABI_RULE_TAG_ENUMERATOR_VALUE "enumerator_value" 56 + 57 + enum kabi_rule_type { 58 + KABI_RULE_TYPE_UNKNOWN, 59 + KABI_RULE_TYPE_DECLONLY, 60 + KABI_RULE_TYPE_ENUMERATOR_IGNORE, 61 + KABI_RULE_TYPE_ENUMERATOR_VALUE, 62 + }; 63 + 64 + #define RULE_HASH_BITS 7 65 + 66 + struct rule { 67 + enum kabi_rule_type type; 68 + const char *target; 69 + const char *value; 70 + struct hlist_node hash; 71 + }; 72 + 73 + /* { type, target } -> struct rule */ 74 + static HASHTABLE_DEFINE(rules, 1 << RULE_HASH_BITS); 75 + 76 + static inline unsigned int rule_values_hash(enum kabi_rule_type type, 77 + const char *target) 78 + { 79 + return hash_32(type) ^ hash_str(target); 80 + } 81 + 82 + static inline unsigned int rule_hash(const struct rule *rule) 83 + { 84 + return rule_values_hash(rule->type, rule->target); 85 + } 86 + 87 + static inline const char *get_rule_field(const char **pos, ssize_t *left) 88 + { 89 + const char *start = *pos; 90 + size_t len; 91 + 92 + if (*left <= 0) 93 + error("unexpected end of kABI rules"); 94 + 95 + len = strnlen(start, *left) + 1; 96 + *pos += len; 97 + *left -= len; 98 + 99 + return start; 100 + } 101 + 102 + void kabi_read_rules(int fd) 103 + { 104 + GElf_Shdr shdr_mem; 105 + GElf_Shdr *shdr; 106 + Elf_Data *rule_data = NULL; 107 + Elf_Scn *scn; 108 + Elf *elf; 109 + size_t shstrndx; 110 + const char *rule_str; 111 + ssize_t left; 112 + int i; 113 + 114 + const struct { 115 + enum kabi_rule_type type; 116 + const char *tag; 117 + } rule_types[] = { 118 + { 119 + .type = KABI_RULE_TYPE_DECLONLY, 120 + .tag = KABI_RULE_TAG_DECLONLY, 121 + }, 122 + { 123 + .type = KABI_RULE_TYPE_ENUMERATOR_IGNORE, 124 + .tag = KABI_RULE_TAG_ENUMERATOR_IGNORE, 125 + }, 126 + { 127 + .type = KABI_RULE_TYPE_ENUMERATOR_VALUE, 128 + .tag = KABI_RULE_TAG_ENUMERATOR_VALUE, 129 + }, 130 + }; 131 + 132 + if (!stable) 133 + return; 134 + 135 + if (elf_version(EV_CURRENT) != EV_CURRENT) 136 + error("elf_version failed: %s", elf_errmsg(-1)); 137 + 138 + elf = elf_begin(fd, ELF_C_READ_MMAP, NULL); 139 + if (!elf) 140 + error("elf_begin failed: %s", elf_errmsg(-1)); 141 + 142 + if (elf_getshdrstrndx(elf, &shstrndx) < 0) 143 + error("elf_getshdrstrndx failed: %s", elf_errmsg(-1)); 144 + 145 + scn = elf_nextscn(elf, NULL); 146 + 147 + while (scn) { 148 + const char *sname; 149 + 150 + shdr = gelf_getshdr(scn, &shdr_mem); 151 + if (!shdr) 152 + error("gelf_getshdr failed: %s", elf_errmsg(-1)); 153 + 154 + sname = elf_strptr(elf, shstrndx, shdr->sh_name); 155 + if (!sname) 156 + error("elf_strptr failed: %s", elf_errmsg(-1)); 157 + 158 + if (!strcmp(sname, KABI_RULE_SECTION)) { 159 + rule_data = elf_getdata(scn, NULL); 160 + if (!rule_data) 161 + error("elf_getdata failed: %s", elf_errmsg(-1)); 162 + break; 163 + } 164 + 165 + scn = elf_nextscn(elf, scn); 166 + } 167 + 168 + if (!rule_data) { 169 + debug("kABI rules not found"); 170 + check(elf_end(elf)); 171 + return; 172 + } 173 + 174 + rule_str = rule_data->d_buf; 175 + left = shdr->sh_size; 176 + 177 + if (left < KABI_RULE_MIN_ENTRY_SIZE) 178 + error("kABI rule section too small: %zd bytes", left); 179 + 180 + if (rule_str[left - 1] != '\0') 181 + error("kABI rules are not null-terminated"); 182 + 183 + while (left > KABI_RULE_MIN_ENTRY_SIZE) { 184 + enum kabi_rule_type type = KABI_RULE_TYPE_UNKNOWN; 185 + const char *field; 186 + struct rule *rule; 187 + 188 + /* version */ 189 + field = get_rule_field(&rule_str, &left); 190 + 191 + if (strcmp(field, KABI_RULE_VERSION)) 192 + error("unsupported kABI rule version: '%s'", field); 193 + 194 + /* type */ 195 + field = get_rule_field(&rule_str, &left); 196 + 197 + for (i = 0; i < ARRAY_SIZE(rule_types); i++) { 198 + if (!strcmp(field, rule_types[i].tag)) { 199 + type = rule_types[i].type; 200 + break; 201 + } 202 + } 203 + 204 + if (type == KABI_RULE_TYPE_UNKNOWN) 205 + error("unsupported kABI rule type: '%s'", field); 206 + 207 + rule = xmalloc(sizeof(struct rule)); 208 + 209 + rule->type = type; 210 + rule->target = xstrdup(get_rule_field(&rule_str, &left)); 211 + rule->value = xstrdup(get_rule_field(&rule_str, &left)); 212 + 213 + hash_add(rules, &rule->hash, rule_hash(rule)); 214 + 215 + debug("kABI rule: type: '%s', target: '%s', value: '%s'", field, 216 + rule->target, rule->value); 217 + } 218 + 219 + if (left > 0) 220 + warn("unexpected data at the end of the kABI rules section"); 221 + 222 + check(elf_end(elf)); 223 + } 224 + 225 + bool kabi_is_declonly(const char *fqn) 226 + { 227 + struct rule *rule; 228 + 229 + if (!stable) 230 + return false; 231 + if (!fqn || !*fqn) 232 + return false; 233 + 234 + hash_for_each_possible(rules, rule, hash, 235 + rule_values_hash(KABI_RULE_TYPE_DECLONLY, fqn)) { 236 + if (rule->type == KABI_RULE_TYPE_DECLONLY && 237 + !strcmp(fqn, rule->target)) 238 + return true; 239 + } 240 + 241 + return false; 242 + } 243 + 244 + static char *get_enumerator_target(const char *fqn, const char *field) 245 + { 246 + char *target = NULL; 247 + 248 + if (asprintf(&target, "%s %s", fqn, field) < 0) 249 + error("asprintf failed for '%s %s'", fqn, field); 250 + 251 + return target; 252 + } 253 + 254 + static unsigned long get_ulong_value(const char *value) 255 + { 256 + unsigned long result = 0; 257 + char *endptr = NULL; 258 + 259 + errno = 0; 260 + result = strtoul(value, &endptr, 10); 261 + 262 + if (errno || *endptr) 263 + error("invalid unsigned value '%s'", value); 264 + 265 + return result; 266 + } 267 + 268 + bool kabi_is_enumerator_ignored(const char *fqn, const char *field) 269 + { 270 + bool match = false; 271 + struct rule *rule; 272 + char *target; 273 + 274 + if (!stable) 275 + return false; 276 + if (!fqn || !*fqn || !field || !*field) 277 + return false; 278 + 279 + target = get_enumerator_target(fqn, field); 280 + 281 + hash_for_each_possible( 282 + rules, rule, hash, 283 + rule_values_hash(KABI_RULE_TYPE_ENUMERATOR_IGNORE, target)) { 284 + if (rule->type == KABI_RULE_TYPE_ENUMERATOR_IGNORE && 285 + !strcmp(target, rule->target)) { 286 + match = true; 287 + break; 288 + } 289 + } 290 + 291 + free(target); 292 + return match; 293 + } 294 + 295 + bool kabi_get_enumerator_value(const char *fqn, const char *field, 296 + unsigned long *value) 297 + { 298 + bool match = false; 299 + struct rule *rule; 300 + char *target; 301 + 302 + if (!stable) 303 + return false; 304 + if (!fqn || !*fqn || !field || !*field) 305 + return false; 306 + 307 + target = get_enumerator_target(fqn, field); 308 + 309 + hash_for_each_possible(rules, rule, hash, 310 + rule_values_hash(KABI_RULE_TYPE_ENUMERATOR_VALUE, 311 + target)) { 312 + if (rule->type == KABI_RULE_TYPE_ENUMERATOR_VALUE && 313 + !strcmp(target, rule->target)) { 314 + *value = get_ulong_value(rule->value); 315 + match = true; 316 + break; 317 + } 318 + } 319 + 320 + free(target); 321 + return match; 322 + } 323 + 324 + void kabi_free(void) 325 + { 326 + struct hlist_node *tmp; 327 + struct rule *rule; 328 + 329 + hash_for_each_safe(rules, rule, tmp, hash) { 330 + free((void *)rule->target); 331 + free((void *)rule->value); 332 + free(rule); 333 + } 334 + 335 + hash_init(rules); 336 + }
+341
scripts/gendwarfksyms/symbols.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Copyright (C) 2024 Google LLC 4 + */ 5 + 6 + #include "gendwarfksyms.h" 7 + 8 + #define SYMBOL_HASH_BITS 12 9 + 10 + /* struct symbol_addr -> struct symbol */ 11 + static HASHTABLE_DEFINE(symbol_addrs, 1 << SYMBOL_HASH_BITS); 12 + /* name -> struct symbol */ 13 + static HASHTABLE_DEFINE(symbol_names, 1 << SYMBOL_HASH_BITS); 14 + 15 + static inline unsigned int symbol_addr_hash(const struct symbol_addr *addr) 16 + { 17 + return hash_32(addr->section ^ addr_hash(addr->address)); 18 + } 19 + 20 + static unsigned int __for_each_addr(struct symbol *sym, symbol_callback_t func, 21 + void *data) 22 + { 23 + struct hlist_node *tmp; 24 + struct symbol *match = NULL; 25 + unsigned int processed = 0; 26 + 27 + hash_for_each_possible_safe(symbol_addrs, match, tmp, addr_hash, 28 + symbol_addr_hash(&sym->addr)) { 29 + if (match == sym) 30 + continue; /* Already processed */ 31 + 32 + if (match->addr.section == sym->addr.section && 33 + match->addr.address == sym->addr.address) { 34 + func(match, data); 35 + ++processed; 36 + } 37 + } 38 + 39 + return processed; 40 + } 41 + 42 + /* 43 + * For symbols without debugging information (e.g. symbols defined in other 44 + * TUs), we also match __gendwarfksyms_ptr_<symbol_name> symbols, which the 45 + * kernel uses to ensure type information is present in the TU that exports 46 + * the symbol. A __gendwarfksyms_ptr pointer must have the same type as the 47 + * exported symbol, e.g.: 48 + * 49 + * typeof(symname) *__gendwarf_ptr_symname = &symname; 50 + */ 51 + bool is_symbol_ptr(const char *name) 52 + { 53 + return name && !strncmp(name, SYMBOL_PTR_PREFIX, SYMBOL_PTR_PREFIX_LEN); 54 + } 55 + 56 + static unsigned int for_each(const char *name, symbol_callback_t func, 57 + void *data) 58 + { 59 + struct hlist_node *tmp; 60 + struct symbol *match; 61 + 62 + if (!name || !*name) 63 + return 0; 64 + if (is_symbol_ptr(name)) 65 + name += SYMBOL_PTR_PREFIX_LEN; 66 + 67 + hash_for_each_possible_safe(symbol_names, match, tmp, name_hash, 68 + hash_str(name)) { 69 + if (strcmp(match->name, name)) 70 + continue; 71 + 72 + /* Call func for the match, and all address matches */ 73 + if (func) 74 + func(match, data); 75 + 76 + if (match->addr.section != SHN_UNDEF) 77 + return __for_each_addr(match, func, data) + 1; 78 + 79 + return 1; 80 + } 81 + 82 + return 0; 83 + } 84 + 85 + static void set_crc(struct symbol *sym, void *data) 86 + { 87 + unsigned long *crc = data; 88 + 89 + if (sym->state == SYMBOL_PROCESSED && sym->crc != *crc) 90 + warn("overriding version for symbol %s (crc %lx vs. %lx)", 91 + sym->name, sym->crc, *crc); 92 + 93 + sym->state = SYMBOL_PROCESSED; 94 + sym->crc = *crc; 95 + } 96 + 97 + void symbol_set_crc(struct symbol *sym, unsigned long crc) 98 + { 99 + if (for_each(sym->name, set_crc, &crc) == 0) 100 + error("no matching symbols: '%s'", sym->name); 101 + } 102 + 103 + static void set_ptr(struct symbol *sym, void *data) 104 + { 105 + sym->ptr_die_addr = (uintptr_t)((Dwarf_Die *)data)->addr; 106 + } 107 + 108 + void symbol_set_ptr(struct symbol *sym, Dwarf_Die *ptr) 109 + { 110 + if (for_each(sym->name, set_ptr, ptr) == 0) 111 + error("no matching symbols: '%s'", sym->name); 112 + } 113 + 114 + static void set_die(struct symbol *sym, void *data) 115 + { 116 + sym->die_addr = (uintptr_t)((Dwarf_Die *)data)->addr; 117 + sym->state = SYMBOL_MAPPED; 118 + } 119 + 120 + void symbol_set_die(struct symbol *sym, Dwarf_Die *die) 121 + { 122 + if (for_each(sym->name, set_die, die) == 0) 123 + error("no matching symbols: '%s'", sym->name); 124 + } 125 + 126 + static bool is_exported(const char *name) 127 + { 128 + return for_each(name, NULL, NULL) > 0; 129 + } 130 + 131 + void symbol_read_exports(FILE *file) 132 + { 133 + struct symbol *sym; 134 + char *line = NULL; 135 + char *name = NULL; 136 + size_t size = 0; 137 + int nsym = 0; 138 + 139 + while (getline(&line, &size, file) > 0) { 140 + if (sscanf(line, "%ms\n", &name) != 1) 141 + error("malformed input line: %s", line); 142 + 143 + if (is_exported(name)) { 144 + /* Ignore duplicates */ 145 + free(name); 146 + continue; 147 + } 148 + 149 + sym = xcalloc(1, sizeof(struct symbol)); 150 + sym->name = name; 151 + sym->addr.section = SHN_UNDEF; 152 + sym->state = SYMBOL_UNPROCESSED; 153 + 154 + hash_add(symbol_names, &sym->name_hash, hash_str(sym->name)); 155 + ++nsym; 156 + 157 + debug("%s", sym->name); 158 + } 159 + 160 + free(line); 161 + debug("%d exported symbols", nsym); 162 + } 163 + 164 + static void get_symbol(struct symbol *sym, void *arg) 165 + { 166 + struct symbol **res = arg; 167 + 168 + if (sym->state == SYMBOL_UNPROCESSED) 169 + *res = sym; 170 + } 171 + 172 + struct symbol *symbol_get(const char *name) 173 + { 174 + struct symbol *sym = NULL; 175 + 176 + for_each(name, get_symbol, &sym); 177 + return sym; 178 + } 179 + 180 + void symbol_for_each(symbol_callback_t func, void *arg) 181 + { 182 + struct hlist_node *tmp; 183 + struct symbol *sym; 184 + 185 + hash_for_each_safe(symbol_names, sym, tmp, name_hash) { 186 + func(sym, arg); 187 + } 188 + } 189 + 190 + typedef void (*elf_symbol_callback_t)(const char *name, GElf_Sym *sym, 191 + Elf32_Word xndx, void *arg); 192 + 193 + static void elf_for_each_global(int fd, elf_symbol_callback_t func, void *arg) 194 + { 195 + size_t sym_size; 196 + GElf_Shdr shdr_mem; 197 + GElf_Shdr *shdr; 198 + Elf_Data *xndx_data = NULL; 199 + Elf_Scn *scn; 200 + Elf *elf; 201 + 202 + if (elf_version(EV_CURRENT) != EV_CURRENT) 203 + error("elf_version failed: %s", elf_errmsg(-1)); 204 + 205 + elf = elf_begin(fd, ELF_C_READ_MMAP, NULL); 206 + if (!elf) 207 + error("elf_begin failed: %s", elf_errmsg(-1)); 208 + 209 + scn = elf_nextscn(elf, NULL); 210 + 211 + while (scn) { 212 + shdr = gelf_getshdr(scn, &shdr_mem); 213 + if (!shdr) 214 + error("gelf_getshdr failed: %s", elf_errmsg(-1)); 215 + 216 + if (shdr->sh_type == SHT_SYMTAB_SHNDX) { 217 + xndx_data = elf_getdata(scn, NULL); 218 + if (!xndx_data) 219 + error("elf_getdata failed: %s", elf_errmsg(-1)); 220 + break; 221 + } 222 + 223 + scn = elf_nextscn(elf, scn); 224 + } 225 + 226 + sym_size = gelf_fsize(elf, ELF_T_SYM, 1, EV_CURRENT); 227 + scn = elf_nextscn(elf, NULL); 228 + 229 + while (scn) { 230 + shdr = gelf_getshdr(scn, &shdr_mem); 231 + if (!shdr) 232 + error("gelf_getshdr failed: %s", elf_errmsg(-1)); 233 + 234 + if (shdr->sh_type == SHT_SYMTAB) { 235 + unsigned int nsyms; 236 + unsigned int n; 237 + Elf_Data *data = elf_getdata(scn, NULL); 238 + 239 + if (!data) 240 + error("elf_getdata failed: %s", elf_errmsg(-1)); 241 + 242 + if (shdr->sh_entsize != sym_size) 243 + error("expected sh_entsize (%lu) to be %zu", 244 + shdr->sh_entsize, sym_size); 245 + 246 + nsyms = shdr->sh_size / shdr->sh_entsize; 247 + 248 + for (n = 1; n < nsyms; ++n) { 249 + const char *name = NULL; 250 + Elf32_Word xndx = 0; 251 + GElf_Sym sym_mem; 252 + GElf_Sym *sym; 253 + 254 + sym = gelf_getsymshndx(data, xndx_data, n, 255 + &sym_mem, &xndx); 256 + if (!sym) 257 + error("gelf_getsymshndx failed: %s", 258 + elf_errmsg(-1)); 259 + 260 + if (GELF_ST_BIND(sym->st_info) == STB_LOCAL) 261 + continue; 262 + 263 + if (sym->st_shndx != SHN_XINDEX) 264 + xndx = sym->st_shndx; 265 + 266 + name = elf_strptr(elf, shdr->sh_link, 267 + sym->st_name); 268 + if (!name) 269 + error("elf_strptr failed: %s", 270 + elf_errmsg(-1)); 271 + 272 + /* Skip empty symbol names */ 273 + if (*name) 274 + func(name, sym, xndx, arg); 275 + } 276 + } 277 + 278 + scn = elf_nextscn(elf, scn); 279 + } 280 + 281 + check(elf_end(elf)); 282 + } 283 + 284 + static void set_symbol_addr(struct symbol *sym, void *arg) 285 + { 286 + struct symbol_addr *addr = arg; 287 + 288 + if (sym->addr.section == SHN_UNDEF) { 289 + sym->addr = *addr; 290 + hash_add(symbol_addrs, &sym->addr_hash, 291 + symbol_addr_hash(&sym->addr)); 292 + 293 + debug("%s -> { %u, %lx }", sym->name, sym->addr.section, 294 + sym->addr.address); 295 + } else if (sym->addr.section != addr->section || 296 + sym->addr.address != addr->address) { 297 + warn("multiple addresses for symbol %s?", sym->name); 298 + } 299 + } 300 + 301 + static void elf_set_symbol_addr(const char *name, GElf_Sym *sym, 302 + Elf32_Word xndx, void *arg) 303 + { 304 + struct symbol_addr addr = { .section = xndx, .address = sym->st_value }; 305 + 306 + /* Set addresses for exported symbols */ 307 + if (addr.section != SHN_UNDEF) 308 + for_each(name, set_symbol_addr, &addr); 309 + } 310 + 311 + void symbol_read_symtab(int fd) 312 + { 313 + elf_for_each_global(fd, elf_set_symbol_addr, NULL); 314 + } 315 + 316 + void symbol_print_versions(void) 317 + { 318 + struct hlist_node *tmp; 319 + struct symbol *sym; 320 + 321 + hash_for_each_safe(symbol_names, sym, tmp, name_hash) { 322 + if (sym->state != SYMBOL_PROCESSED) 323 + warn("no information for symbol %s", sym->name); 324 + 325 + printf("#SYMVER %s 0x%08lx\n", sym->name, sym->crc); 326 + } 327 + } 328 + 329 + void symbol_free(void) 330 + { 331 + struct hlist_node *tmp; 332 + struct symbol *sym; 333 + 334 + hash_for_each_safe(symbol_names, sym, tmp, name_hash) { 335 + free((void *)sym->name); 336 + free(sym); 337 + } 338 + 339 + hash_init(symbol_addrs); 340 + hash_init(symbol_names); 341 + }
+481
scripts/gendwarfksyms/types.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Copyright (C) 2024 Google LLC 4 + */ 5 + 6 + #define _GNU_SOURCE 7 + #include <inttypes.h> 8 + #include <stdio.h> 9 + #include <zlib.h> 10 + 11 + #include "gendwarfksyms.h" 12 + 13 + static struct cache expansion_cache; 14 + 15 + /* 16 + * A simple linked list of shared or owned strings to avoid copying strings 17 + * around when not necessary. 18 + */ 19 + struct type_list_entry { 20 + const char *str; 21 + void *owned; 22 + struct list_head list; 23 + }; 24 + 25 + static void type_list_free(struct list_head *list) 26 + { 27 + struct type_list_entry *entry; 28 + struct type_list_entry *tmp; 29 + 30 + list_for_each_entry_safe(entry, tmp, list, list) { 31 + if (entry->owned) 32 + free(entry->owned); 33 + free(entry); 34 + } 35 + 36 + INIT_LIST_HEAD(list); 37 + } 38 + 39 + static int type_list_append(struct list_head *list, const char *s, void *owned) 40 + { 41 + struct type_list_entry *entry; 42 + 43 + if (!s) 44 + return 0; 45 + 46 + entry = xmalloc(sizeof(struct type_list_entry)); 47 + entry->str = s; 48 + entry->owned = owned; 49 + list_add_tail(&entry->list, list); 50 + 51 + return strlen(entry->str); 52 + } 53 + 54 + static void type_list_write(struct list_head *list, FILE *file) 55 + { 56 + struct type_list_entry *entry; 57 + 58 + list_for_each_entry(entry, list, list) { 59 + if (entry->str) 60 + checkp(fputs(entry->str, file)); 61 + } 62 + } 63 + 64 + /* 65 + * An expanded type string in symtypes format. 66 + */ 67 + struct type_expansion { 68 + char *name; 69 + size_t len; 70 + struct list_head expanded; 71 + struct hlist_node hash; 72 + }; 73 + 74 + static void type_expansion_init(struct type_expansion *type) 75 + { 76 + type->name = NULL; 77 + type->len = 0; 78 + INIT_LIST_HEAD(&type->expanded); 79 + } 80 + 81 + static inline void type_expansion_free(struct type_expansion *type) 82 + { 83 + free(type->name); 84 + type->name = NULL; 85 + type->len = 0; 86 + type_list_free(&type->expanded); 87 + } 88 + 89 + static void type_expansion_append(struct type_expansion *type, const char *s, 90 + void *owned) 91 + { 92 + type->len += type_list_append(&type->expanded, s, owned); 93 + } 94 + 95 + /* 96 + * type_map -- the longest expansions for each type. 97 + * 98 + * const char *name -> struct type_expansion * 99 + */ 100 + #define TYPE_HASH_BITS 12 101 + static HASHTABLE_DEFINE(type_map, 1 << TYPE_HASH_BITS); 102 + 103 + static int type_map_get(const char *name, struct type_expansion **res) 104 + { 105 + struct type_expansion *e; 106 + 107 + hash_for_each_possible(type_map, e, hash, hash_str(name)) { 108 + if (!strcmp(name, e->name)) { 109 + *res = e; 110 + return 0; 111 + } 112 + } 113 + 114 + return -1; 115 + } 116 + 117 + static void type_map_add(const char *name, struct type_expansion *type) 118 + { 119 + struct type_expansion *e; 120 + 121 + if (type_map_get(name, &e)) { 122 + e = xmalloc(sizeof(struct type_expansion)); 123 + type_expansion_init(e); 124 + e->name = xstrdup(name); 125 + 126 + hash_add(type_map, &e->hash, hash_str(e->name)); 127 + 128 + if (dump_types) 129 + debug("adding %s", e->name); 130 + } else { 131 + /* Use the longest available expansion */ 132 + if (type->len <= e->len) 133 + return; 134 + 135 + type_list_free(&e->expanded); 136 + 137 + if (dump_types) 138 + debug("replacing %s", e->name); 139 + } 140 + 141 + /* Take ownership of type->expanded */ 142 + list_replace_init(&type->expanded, &e->expanded); 143 + e->len = type->len; 144 + 145 + if (dump_types) { 146 + checkp(fputs(e->name, stderr)); 147 + checkp(fputs(" ", stderr)); 148 + type_list_write(&e->expanded, stderr); 149 + checkp(fputs("\n", stderr)); 150 + } 151 + } 152 + 153 + static void type_map_write(FILE *file) 154 + { 155 + struct type_expansion *e; 156 + struct hlist_node *tmp; 157 + 158 + if (!file) 159 + return; 160 + 161 + hash_for_each_safe(type_map, e, tmp, hash) { 162 + checkp(fputs(e->name, file)); 163 + checkp(fputs(" ", file)); 164 + type_list_write(&e->expanded, file); 165 + checkp(fputs("\n", file)); 166 + } 167 + } 168 + 169 + static void type_map_free(void) 170 + { 171 + struct type_expansion *e; 172 + struct hlist_node *tmp; 173 + 174 + hash_for_each_safe(type_map, e, tmp, hash) { 175 + type_expansion_free(e); 176 + free(e); 177 + } 178 + 179 + hash_init(type_map); 180 + } 181 + 182 + /* 183 + * CRC for a type, with an optional fully expanded type string for 184 + * debugging. 185 + */ 186 + struct version { 187 + struct type_expansion type; 188 + unsigned long crc; 189 + }; 190 + 191 + static void version_init(struct version *version) 192 + { 193 + version->crc = crc32(0, NULL, 0); 194 + type_expansion_init(&version->type); 195 + } 196 + 197 + static void version_free(struct version *version) 198 + { 199 + type_expansion_free(&version->type); 200 + } 201 + 202 + static void version_add(struct version *version, const char *s) 203 + { 204 + version->crc = crc32(version->crc, (void *)s, strlen(s)); 205 + if (dump_versions) 206 + type_expansion_append(&version->type, s, NULL); 207 + } 208 + 209 + /* 210 + * Type reference format: <prefix>#<name>, where prefix: 211 + * s -> structure 212 + * u -> union 213 + * e -> enum 214 + * t -> typedef 215 + * 216 + * Names with spaces are additionally wrapped in single quotes. 217 + */ 218 + static inline bool is_type_prefix(const char *s) 219 + { 220 + return (s[0] == 's' || s[0] == 'u' || s[0] == 'e' || s[0] == 't') && 221 + s[1] == '#'; 222 + } 223 + 224 + static char get_type_prefix(int tag) 225 + { 226 + switch (tag) { 227 + case DW_TAG_class_type: 228 + case DW_TAG_structure_type: 229 + return 's'; 230 + case DW_TAG_union_type: 231 + return 'u'; 232 + case DW_TAG_enumeration_type: 233 + return 'e'; 234 + case DW_TAG_typedef_type: 235 + return 't'; 236 + default: 237 + return 0; 238 + } 239 + } 240 + 241 + static char *get_type_name(struct die *cache) 242 + { 243 + const char *quote; 244 + char prefix; 245 + char *name; 246 + 247 + if (cache->state == DIE_INCOMPLETE) { 248 + warn("found incomplete cache entry: %p", cache); 249 + return NULL; 250 + } 251 + if (cache->state == DIE_SYMBOL) 252 + return NULL; 253 + if (!cache->fqn || !*cache->fqn) 254 + return NULL; 255 + 256 + prefix = get_type_prefix(cache->tag); 257 + if (!prefix) 258 + return NULL; 259 + 260 + /* Wrap names with spaces in single quotes */ 261 + quote = strstr(cache->fqn, " ") ? "'" : ""; 262 + 263 + /* <prefix>#<type_name>\0 */ 264 + if (asprintf(&name, "%c#%s%s%s", prefix, quote, cache->fqn, quote) < 0) 265 + error("asprintf failed for '%s'", cache->fqn); 266 + 267 + return name; 268 + } 269 + 270 + static void __calculate_version(struct version *version, struct list_head *list) 271 + { 272 + struct type_list_entry *entry; 273 + struct type_expansion *e; 274 + 275 + /* Calculate a CRC over an expanded type string */ 276 + list_for_each_entry(entry, list, list) { 277 + if (is_type_prefix(entry->str)) { 278 + check(type_map_get(entry->str, &e)); 279 + 280 + /* 281 + * It's sufficient to expand each type reference just 282 + * once to detect changes. 283 + */ 284 + if (cache_was_expanded(&expansion_cache, e)) { 285 + version_add(version, entry->str); 286 + } else { 287 + cache_mark_expanded(&expansion_cache, e); 288 + __calculate_version(version, &e->expanded); 289 + } 290 + } else { 291 + version_add(version, entry->str); 292 + } 293 + } 294 + } 295 + 296 + static void calculate_version(struct version *version, struct list_head *list) 297 + { 298 + version_init(version); 299 + __calculate_version(version, list); 300 + cache_free(&expansion_cache); 301 + } 302 + 303 + static void __type_expand(struct die *cache, struct type_expansion *type, 304 + bool recursive); 305 + 306 + static void type_expand_child(struct die *cache, struct type_expansion *type, 307 + bool recursive) 308 + { 309 + struct type_expansion child; 310 + char *name; 311 + 312 + name = get_type_name(cache); 313 + if (!name) { 314 + __type_expand(cache, type, recursive); 315 + return; 316 + } 317 + 318 + if (recursive && !__cache_was_expanded(&expansion_cache, cache->addr)) { 319 + __cache_mark_expanded(&expansion_cache, cache->addr); 320 + type_expansion_init(&child); 321 + __type_expand(cache, &child, true); 322 + type_map_add(name, &child); 323 + type_expansion_free(&child); 324 + } 325 + 326 + type_expansion_append(type, name, name); 327 + } 328 + 329 + static void __type_expand(struct die *cache, struct type_expansion *type, 330 + bool recursive) 331 + { 332 + struct die_fragment *df; 333 + struct die *child; 334 + 335 + list_for_each_entry(df, &cache->fragments, list) { 336 + switch (df->type) { 337 + case FRAGMENT_STRING: 338 + type_expansion_append(type, df->data.str, NULL); 339 + break; 340 + case FRAGMENT_DIE: 341 + /* Use a complete die_map expansion if available */ 342 + if (__die_map_get(df->data.addr, DIE_COMPLETE, 343 + &child) && 344 + __die_map_get(df->data.addr, DIE_UNEXPANDED, 345 + &child)) 346 + error("unknown child: %" PRIxPTR, 347 + df->data.addr); 348 + 349 + type_expand_child(child, type, recursive); 350 + break; 351 + case FRAGMENT_LINEBREAK: 352 + /* 353 + * Keep whitespace in the symtypes format, but avoid 354 + * repeated spaces. 355 + */ 356 + if (list_is_last(&df->list, &cache->fragments) || 357 + list_next_entry(df, list)->type != 358 + FRAGMENT_LINEBREAK) 359 + type_expansion_append(type, " ", NULL); 360 + break; 361 + default: 362 + error("empty die_fragment in %p", cache); 363 + } 364 + } 365 + } 366 + 367 + static void type_expand(struct die *cache, struct type_expansion *type, 368 + bool recursive) 369 + { 370 + type_expansion_init(type); 371 + __type_expand(cache, type, recursive); 372 + cache_free(&expansion_cache); 373 + } 374 + 375 + static void expand_type(struct die *cache, void *arg) 376 + { 377 + struct type_expansion type; 378 + char *name; 379 + 380 + if (cache->mapped) 381 + return; 382 + 383 + cache->mapped = true; 384 + 385 + /* 386 + * Skip unexpanded die_map entries if there's a complete 387 + * expansion available for this DIE. 388 + */ 389 + if (cache->state == DIE_UNEXPANDED && 390 + !__die_map_get(cache->addr, DIE_COMPLETE, &cache)) { 391 + if (cache->mapped) 392 + return; 393 + 394 + cache->mapped = true; 395 + } 396 + 397 + name = get_type_name(cache); 398 + if (!name) 399 + return; 400 + 401 + debug("%s", name); 402 + type_expand(cache, &type, true); 403 + type_map_add(name, &type); 404 + 405 + type_expansion_free(&type); 406 + free(name); 407 + } 408 + 409 + static void expand_symbol(struct symbol *sym, void *arg) 410 + { 411 + struct type_expansion type; 412 + struct version version; 413 + struct die *cache; 414 + 415 + /* 416 + * No need to expand again unless we want a symtypes file entry 417 + * for the symbol. Note that this means `sym` has the same address 418 + * as another symbol that was already processed. 419 + */ 420 + if (!symtypes && sym->state == SYMBOL_PROCESSED) 421 + return; 422 + 423 + if (__die_map_get(sym->die_addr, DIE_SYMBOL, &cache)) 424 + return; /* We'll warn about missing CRCs later. */ 425 + 426 + type_expand(cache, &type, false); 427 + 428 + /* If the symbol already has a version, don't calculate it again. */ 429 + if (sym->state != SYMBOL_PROCESSED) { 430 + calculate_version(&version, &type.expanded); 431 + symbol_set_crc(sym, version.crc); 432 + debug("%s = %lx", sym->name, version.crc); 433 + 434 + if (dump_versions) { 435 + checkp(fputs(sym->name, stderr)); 436 + checkp(fputs(" ", stderr)); 437 + type_list_write(&version.type.expanded, stderr); 438 + checkp(fputs("\n", stderr)); 439 + } 440 + 441 + version_free(&version); 442 + } 443 + 444 + /* These aren't needed in type_map unless we want a symtypes file. */ 445 + if (symtypes) 446 + type_map_add(sym->name, &type); 447 + 448 + type_expansion_free(&type); 449 + } 450 + 451 + void generate_symtypes_and_versions(FILE *file) 452 + { 453 + cache_init(&expansion_cache); 454 + 455 + /* 456 + * die_map processing: 457 + * 458 + * 1. die_map contains all types referenced in exported symbol 459 + * signatures, but can contain duplicates just like the original 460 + * DWARF, and some references may not be fully expanded depending 461 + * on how far we processed the DIE tree for that specific symbol. 462 + * 463 + * For each die_map entry, find the longest available expansion, 464 + * and add it to type_map. 465 + */ 466 + die_map_for_each(expand_type, NULL); 467 + 468 + /* 469 + * 2. For each exported symbol, expand the die_map type, and use 470 + * type_map expansions to calculate a symbol version from the 471 + * fully expanded type string. 472 + */ 473 + symbol_for_each(expand_symbol, NULL); 474 + 475 + /* 476 + * 3. If a symtypes file is requested, write type_map contents to 477 + * the file. 478 + */ 479 + type_map_write(file); 480 + type_map_free(); 481 + }
-18
scripts/genksyms/Makefile
··· 4 4 5 5 genksyms-objs := genksyms.o parse.tab.o lex.lex.o 6 6 7 - # FIXME: fix the ambiguous grammar in parse.y and delete this hack 8 - # 9 - # Suppress shift/reduce, reduce/reduce conflicts warnings 10 - # unless W=1 is specified. 11 - # 12 - # Just in case, run "$(YACC) --version" without suppressing stderr 13 - # so that 'bison: not found' will be displayed if it is missing. 14 - ifeq ($(findstring 1,$(KBUILD_EXTRA_WARN)),) 15 - 16 - quiet_cmd_bison_no_warn = $(quiet_cmd_bison) 17 - cmd_bison_no_warn = $(YACC) --version >/dev/null; \ 18 - $(cmd_bison) 2>/dev/null 19 - 20 - $(obj)/pars%.tab.c $(obj)/pars%.tab.h: $(src)/pars%.y FORCE 21 - $(call if_changed,bison_no_warn) 22 - 23 - endif 24 - 25 7 # -I needed for generated C source to include headers in source tree 26 8 HOSTCFLAGS_parse.tab.o := -I $(src) 27 9 HOSTCFLAGS_lex.lex.o := -I $(src)
+50 -57
scripts/genksyms/genksyms.c
··· 12 12 13 13 #include <stdio.h> 14 14 #include <string.h> 15 + #include <stdint.h> 15 16 #include <stdlib.h> 16 17 #include <unistd.h> 17 18 #include <assert.h> 18 19 #include <stdarg.h> 19 20 #include <getopt.h> 20 21 22 + #include <hashtable.h> 23 + 21 24 #include "genksyms.h" 22 25 /*----------------------------------------------------------------------*/ 23 26 24 - #define HASH_BUCKETS 4096 25 - 26 - static struct symbol *symtab[HASH_BUCKETS]; 27 + static HASHTABLE_DEFINE(symbol_hashtable, 1U << 12); 27 28 static FILE *debugfile; 28 29 29 30 int cur_line = 1; ··· 61 60 62 61 /*----------------------------------------------------------------------*/ 63 62 64 - static const unsigned int crctab32[] = { 63 + static const uint32_t crctab32[] = { 65 64 0x00000000U, 0x77073096U, 0xee0e612cU, 0x990951baU, 0x076dc419U, 66 65 0x706af48fU, 0xe963a535U, 0x9e6495a3U, 0x0edb8832U, 0x79dcb8a4U, 67 66 0xe0d5e91eU, 0x97d2d988U, 0x09b64c2bU, 0x7eb17cbdU, 0xe7b82d07U, ··· 116 115 0x2d02ef8dU 117 116 }; 118 117 119 - static unsigned long partial_crc32_one(unsigned char c, unsigned long crc) 118 + static uint32_t partial_crc32_one(uint8_t c, uint32_t crc) 120 119 { 121 120 return crctab32[(crc ^ c) & 0xff] ^ (crc >> 8); 122 121 } 123 122 124 - static unsigned long partial_crc32(const char *s, unsigned long crc) 123 + static uint32_t partial_crc32(const char *s, uint32_t crc) 125 124 { 126 125 while (*s) 127 126 crc = partial_crc32_one(*s++, crc); 128 127 return crc; 129 128 } 130 129 131 - static unsigned long crc32(const char *s) 130 + static uint32_t crc32(const char *s) 132 131 { 133 132 return partial_crc32(s, 0xffffffff) ^ 0xffffffff; 134 133 } ··· 152 151 153 152 struct symbol *find_symbol(const char *name, enum symbol_type ns, int exact) 154 153 { 155 - unsigned long h = crc32(name) % HASH_BUCKETS; 156 154 struct symbol *sym; 157 155 158 - for (sym = symtab[h]; sym; sym = sym->hash_next) 156 + hash_for_each_possible(symbol_hashtable, sym, hnode, crc32(name)) { 159 157 if (map_to_ns(sym->type) == map_to_ns(ns) && 160 158 strcmp(name, sym->name) == 0 && 161 159 sym->is_declared) 162 160 break; 161 + } 163 162 164 163 if (exact && sym && sym->type != ns) 165 164 return NULL; ··· 225 224 return NULL; 226 225 } 227 226 228 - h = crc32(name) % HASH_BUCKETS; 229 - for (sym = symtab[h]; sym; sym = sym->hash_next) { 230 - if (map_to_ns(sym->type) == map_to_ns(type) && 231 - strcmp(name, sym->name) == 0) { 232 - if (is_reference) 233 - /* fall through */ ; 234 - else if (sym->type == type && 235 - equal_list(sym->defn, defn)) { 236 - if (!sym->is_declared && sym->is_override) { 237 - print_location(); 238 - print_type_name(type, name); 239 - fprintf(stderr, " modversion is " 240 - "unchanged\n"); 241 - } 242 - sym->is_declared = 1; 243 - return sym; 244 - } else if (!sym->is_declared) { 245 - if (sym->is_override && flag_preserve) { 246 - print_location(); 247 - fprintf(stderr, "ignoring "); 248 - print_type_name(type, name); 249 - fprintf(stderr, " modversion change\n"); 250 - sym->is_declared = 1; 251 - return sym; 252 - } else { 253 - status = is_unknown_symbol(sym) ? 254 - STATUS_DEFINED : STATUS_MODIFIED; 255 - } 256 - } else { 257 - error_with_pos("redefinition of %s", name); 258 - return sym; 227 + h = crc32(name); 228 + hash_for_each_possible(symbol_hashtable, sym, hnode, h) { 229 + if (map_to_ns(sym->type) != map_to_ns(type) || 230 + strcmp(name, sym->name)) 231 + continue; 232 + 233 + if (is_reference) { 234 + break; 235 + } else if (sym->type == type && equal_list(sym->defn, defn)) { 236 + if (!sym->is_declared && sym->is_override) { 237 + print_location(); 238 + print_type_name(type, name); 239 + fprintf(stderr, " modversion is unchanged\n"); 259 240 } 241 + sym->is_declared = 1; 242 + } else if (sym->is_declared) { 243 + error_with_pos("redefinition of %s", name); 244 + } else if (sym->is_override && flag_preserve) { 245 + print_location(); 246 + fprintf(stderr, "ignoring "); 247 + print_type_name(type, name); 248 + fprintf(stderr, " modversion change\n"); 249 + sym->is_declared = 1; 250 + } else { 251 + status = is_unknown_symbol(sym) ? 252 + STATUS_DEFINED : STATUS_MODIFIED; 260 253 break; 261 254 } 255 + free_list(defn, NULL); 256 + return sym; 262 257 } 263 258 264 259 if (sym) { 265 - struct symbol **psym; 260 + hash_del(&sym->hnode); 266 261 267 - for (psym = &symtab[h]; *psym; psym = &(*psym)->hash_next) { 268 - if (*psym == sym) { 269 - *psym = sym->hash_next; 270 - break; 271 - } 272 - } 262 + free_list(sym->defn, NULL); 263 + free(sym->name); 264 + free(sym); 273 265 --nsyms; 274 266 } 275 267 276 268 sym = xmalloc(sizeof(*sym)); 277 - sym->name = name; 269 + sym->name = xstrdup(name); 278 270 sym->type = type; 279 271 sym->defn = defn; 280 272 sym->expansion_trail = NULL; 281 273 sym->visited = NULL; 282 274 sym->is_extern = is_extern; 283 275 284 - sym->hash_next = symtab[h]; 285 - symtab[h] = sym; 276 + hash_add(symbol_hashtable, &sym->hnode, h); 286 277 287 278 sym->is_declared = !is_reference; 288 279 sym->status = status; ··· 473 480 defn = def; 474 481 def = read_node(f); 475 482 } 476 - subsym = add_reference_symbol(xstrdup(sym->string), sym->tag, 483 + subsym = add_reference_symbol(sym->string, sym->tag, 477 484 defn, is_extern); 478 485 subsym->is_override = is_override; 479 486 free_node(sym); ··· 518 525 } 519 526 } 520 527 521 - static unsigned long expand_and_crc_sym(struct symbol *sym, unsigned long crc) 528 + static uint32_t expand_and_crc_sym(struct symbol *sym, uint32_t crc) 522 529 { 523 530 struct string_list *list = sym->defn; 524 531 struct string_list **e, **b; ··· 625 632 void export_symbol(const char *name) 626 633 { 627 634 struct symbol *sym; 628 - unsigned long crc; 635 + uint32_t crc; 629 636 int has_changed = 0; 630 637 631 638 sym = find_symbol(name, SYM_NORMAL, 0); ··· 673 680 if (flag_dump_defs) 674 681 fputs(">\n", debugfile); 675 682 676 - printf("#SYMVER %s 0x%08lx\n", name, crc); 683 + printf("#SYMVER %s 0x%08lx\n", name, (unsigned long)crc); 677 684 } 678 685 679 686 /*----------------------------------------------------------------------*/ ··· 825 832 } 826 833 827 834 if (flag_debug) { 828 - fprintf(debugfile, "Hash table occupancy %d/%d = %g\n", 829 - nsyms, HASH_BUCKETS, 830 - (double)nsyms / (double)HASH_BUCKETS); 835 + fprintf(debugfile, "Hash table occupancy %d/%zd = %g\n", 836 + nsyms, HASH_SIZE(symbol_hashtable), 837 + (double)nsyms / HASH_SIZE(symbol_hashtable)); 831 838 } 832 839 833 840 if (dumpfile)
+7 -2
scripts/genksyms/genksyms.h
··· 12 12 #ifndef MODUTILS_GENKSYMS_H 13 13 #define MODUTILS_GENKSYMS_H 1 14 14 15 + #include <stdbool.h> 15 16 #include <stdio.h> 17 + 18 + #include <list_types.h> 16 19 17 20 enum symbol_type { 18 21 SYM_NORMAL, SYM_TYPEDEF, SYM_ENUM, SYM_STRUCT, SYM_UNION, ··· 34 31 }; 35 32 36 33 struct symbol { 37 - struct symbol *hash_next; 38 - const char *name; 34 + struct hlist_node hnode; 35 + char *name; 39 36 enum symbol_type type; 40 37 struct string_list *defn; 41 38 struct symbol *expansion_trail; ··· 66 63 67 64 int yylex(void); 68 65 int yyparse(void); 66 + 67 + extern bool dont_want_type_specifier; 69 68 70 69 void error_with_pos(const char *, ...) __attribute__ ((format(printf, 1, 2))); 71 70
+15 -2
scripts/genksyms/lex.l
··· 12 12 %{ 13 13 14 14 #include <limits.h> 15 + #include <stdbool.h> 15 16 #include <stdlib.h> 16 17 #include <string.h> 17 18 #include <ctype.h> ··· 51 50 52 51 %% 53 52 53 + u?int(8|16|32|64)x(1|2|4|8|16)_t return BUILTIN_INT_KEYW; 54 54 55 55 /* Keep track of our location in the original source files. */ 56 56 ^#[ \t]+{INT}[ \t]+\"[^\"\n]+\".*\n return FILENAME; ··· 114 112 115 113 /* The second stage lexer. Here we incorporate knowledge of the state 116 114 of the parser to tailor the tokens that are returned. */ 115 + 116 + /* 117 + * The lexer cannot distinguish whether a typedef'ed string is a TYPE or an 118 + * IDENT. We need a hint from the parser to handle this accurately. 119 + */ 120 + bool dont_want_type_specifier; 117 121 118 122 int 119 123 yylex(void) ··· 215 207 goto repeat; 216 208 } 217 209 } 218 - if (!suppress_type_lookup) 210 + if (!suppress_type_lookup && !dont_want_type_specifier) 219 211 { 220 212 if (find_symbol(yytext, SYM_TYPEDEF, 1)) 221 213 token = TYPE; ··· 439 431 440 432 if (suppress_type_lookup > 0) 441 433 --suppress_type_lookup; 442 - if (dont_want_brace_phrase > 0) 434 + 435 + /* 436 + * __attribute__() can be placed immediately after the 'struct' keyword. 437 + * e.g.) struct __attribute__((__packed__)) foo { ... }; 438 + */ 439 + if (token != ATTRIBUTE_PHRASE && dont_want_brace_phrase > 0) 443 440 --dont_want_brace_phrase; 444 441 445 442 yylval = &next_node->next;
+97 -71
scripts/genksyms/parse.y
··· 12 12 %{ 13 13 14 14 #include <assert.h> 15 + #include <stdbool.h> 15 16 #include <stdlib.h> 16 17 #include <string.h> 17 18 #include "genksyms.h" ··· 149 148 current_name = NULL; 150 149 } 151 150 $$ = $3; 151 + dont_want_type_specifier = false; 152 152 } 153 153 ; 154 154 155 155 init_declarator_list_opt: 156 - /* empty */ { $$ = NULL; } 157 - | init_declarator_list 156 + /* empty */ { $$ = NULL; } 157 + | init_declarator_list { free_list(decl_spec, NULL); $$ = $1; } 158 158 ; 159 159 160 160 init_declarator_list: 161 161 init_declarator 162 162 { struct string_list *decl = *$1; 163 163 *$1 = NULL; 164 + 165 + /* avoid sharing among multiple init_declarators */ 166 + if (decl_spec) 167 + decl_spec = copy_list_range(decl_spec, NULL); 168 + 164 169 add_symbol(current_name, 165 170 is_typedef ? SYM_TYPEDEF : SYM_NORMAL, decl, is_extern); 166 171 current_name = NULL; 167 172 $$ = $1; 173 + dont_want_type_specifier = true; 168 174 } 169 - | init_declarator_list ',' init_declarator 170 - { struct string_list *decl = *$3; 171 - *$3 = NULL; 175 + | init_declarator_list ',' attribute_opt init_declarator 176 + { struct string_list *decl = *$4; 177 + *$4 = NULL; 172 178 free_list(*$2, NULL); 173 179 *$2 = decl_spec; 180 + 181 + /* avoid sharing among multiple init_declarators */ 182 + if (decl_spec) 183 + decl_spec = copy_list_range(decl_spec, NULL); 184 + 174 185 add_symbol(current_name, 175 186 is_typedef ? SYM_TYPEDEF : SYM_NORMAL, decl, is_extern); 176 187 current_name = NULL; 177 - $$ = $3; 188 + $$ = $4; 189 + dont_want_type_specifier = true; 178 190 } 179 191 ; 180 192 ··· 203 189 ; 204 190 205 191 decl_specifier_seq: 206 - decl_specifier { decl_spec = *$1; } 192 + attribute_opt decl_specifier { decl_spec = *$2; } 207 193 | decl_specifier_seq decl_specifier { decl_spec = *$2; } 194 + | decl_specifier_seq ATTRIBUTE_PHRASE { decl_spec = *$2; } 208 195 ; 209 196 210 197 decl_specifier: ··· 215 200 remove_node($1); 216 201 $$ = $1; 217 202 } 218 - | type_specifier 203 + | type_specifier { dont_want_type_specifier = true; $$ = $1; } 204 + | type_qualifier 219 205 ; 220 206 221 207 storage_class_specifier: ··· 229 213 230 214 type_specifier: 231 215 simple_type_specifier 232 - | cvar_qualifier 233 216 | TYPEOF_KEYW '(' parameter_declaration ')' 234 217 | TYPEOF_PHRASE 235 218 236 219 /* References to s/u/e's defined elsewhere. Rearrange things 237 220 so that it is easier to expand the definition fully later. */ 238 - | STRUCT_KEYW IDENT 239 - { remove_node($1); (*$2)->tag = SYM_STRUCT; $$ = $2; } 240 - | UNION_KEYW IDENT 241 - { remove_node($1); (*$2)->tag = SYM_UNION; $$ = $2; } 221 + | STRUCT_KEYW attribute_opt IDENT 222 + { remove_node($1); (*$3)->tag = SYM_STRUCT; $$ = $3; } 223 + | UNION_KEYW attribute_opt IDENT 224 + { remove_node($1); (*$3)->tag = SYM_UNION; $$ = $3; } 242 225 | ENUM_KEYW IDENT 243 226 { remove_node($1); (*$2)->tag = SYM_ENUM; $$ = $2; } 244 227 245 228 /* Full definitions of an s/u/e. Record it. */ 246 - | STRUCT_KEYW IDENT class_body 247 - { record_compound($1, $2, $3, SYM_STRUCT); $$ = $3; } 248 - | UNION_KEYW IDENT class_body 249 - { record_compound($1, $2, $3, SYM_UNION); $$ = $3; } 229 + | STRUCT_KEYW attribute_opt IDENT class_body 230 + { record_compound($1, $3, $4, SYM_STRUCT); $$ = $4; } 231 + | UNION_KEYW attribute_opt IDENT class_body 232 + { record_compound($1, $3, $4, SYM_UNION); $$ = $4; } 250 233 | ENUM_KEYW IDENT enum_body 251 234 { record_compound($1, $2, $3, SYM_ENUM); $$ = $3; } 252 235 /* ··· 254 239 | ENUM_KEYW enum_body 255 240 { add_symbol(NULL, SYM_ENUM, NULL, 0); $$ = $2; } 256 241 /* Anonymous s/u definitions. Nothing needs doing. */ 257 - | STRUCT_KEYW class_body { $$ = $2; } 258 - | UNION_KEYW class_body { $$ = $2; } 242 + | STRUCT_KEYW attribute_opt class_body { $$ = $3; } 243 + | UNION_KEYW attribute_opt class_body { $$ = $3; } 259 244 ; 260 245 261 246 simple_type_specifier: ··· 275 260 ; 276 261 277 262 ptr_operator: 278 - '*' cvar_qualifier_seq_opt 263 + '*' type_qualifier_seq_opt 279 264 { $$ = $2 ? $2 : $1; } 280 265 ; 281 266 282 - cvar_qualifier_seq_opt: 267 + type_qualifier_seq_opt: 283 268 /* empty */ { $$ = NULL; } 284 - | cvar_qualifier_seq 269 + | type_qualifier_seq 285 270 ; 286 271 287 - cvar_qualifier_seq: 288 - cvar_qualifier 289 - | cvar_qualifier_seq cvar_qualifier { $$ = $2; } 272 + type_qualifier_seq: 273 + type_qualifier 274 + | ATTRIBUTE_PHRASE 275 + | type_qualifier_seq type_qualifier { $$ = $2; } 276 + | type_qualifier_seq ATTRIBUTE_PHRASE { $$ = $2; } 290 277 ; 291 278 292 - cvar_qualifier: 293 - CONST_KEYW | VOLATILE_KEYW | ATTRIBUTE_PHRASE 279 + type_qualifier: 280 + CONST_KEYW | VOLATILE_KEYW 294 281 | RESTRICT_KEYW 295 282 { /* restrict has no effect in prototypes so ignore it */ 296 283 remove_node($1); ··· 314 297 current_name = (*$1)->string; 315 298 $$ = $1; 316 299 } 317 - } 318 - | TYPE 319 - { if (current_name != NULL) { 320 - error_with_pos("unexpected second declaration name"); 321 - YYERROR; 322 - } else { 323 - current_name = (*$1)->string; 324 - $$ = $1; 325 - } 300 + dont_want_type_specifier = false; 326 301 } 327 302 | direct_declarator '(' parameter_declaration_clause ')' 328 303 { $$ = $4; } ··· 334 325 ; 335 326 336 327 direct_nested_declarator: 337 - IDENT 338 - | TYPE 339 - | direct_nested_declarator '(' parameter_declaration_clause ')' 328 + direct_nested_declarator1 329 + | direct_nested_declarator1 '(' parameter_declaration_clause ')' 340 330 { $$ = $4; } 341 - | direct_nested_declarator '(' error ')' 331 + ; 332 + 333 + direct_nested_declarator1: 334 + IDENT { $$ = $1; dont_want_type_specifier = false; } 335 + | direct_nested_declarator1 '(' error ')' 342 336 { $$ = $4; } 343 - | direct_nested_declarator BRACKET_PHRASE 337 + | direct_nested_declarator1 BRACKET_PHRASE 344 338 { $$ = $2; } 345 - | '(' nested_declarator ')' 346 - { $$ = $3; } 339 + | '(' attribute_opt nested_declarator ')' 340 + { $$ = $4; } 347 341 | '(' error ')' 348 342 { $$ = $3; } 349 343 ; ··· 364 352 365 353 parameter_declaration_list: 366 354 parameter_declaration 355 + { $$ = $1; dont_want_type_specifier = false; } 367 356 | parameter_declaration_list ',' parameter_declaration 368 - { $$ = $3; } 357 + { $$ = $3; dont_want_type_specifier = false; } 369 358 ; 370 359 371 360 parameter_declaration: 372 - decl_specifier_seq m_abstract_declarator 361 + decl_specifier_seq abstract_declarator_opt 373 362 { $$ = $2 ? $2 : $1; } 374 363 ; 375 364 376 - m_abstract_declarator: 377 - ptr_operator m_abstract_declarator 378 - { $$ = $2 ? $2 : $1; } 379 - | direct_m_abstract_declarator 365 + abstract_declarator_opt: 366 + /* empty */ { $$ = NULL; } 367 + | abstract_declarator 380 368 ; 381 369 382 - direct_m_abstract_declarator: 383 - /* empty */ { $$ = NULL; } 384 - | IDENT 370 + abstract_declarator: 371 + ptr_operator 372 + | ptr_operator abstract_declarator 373 + { $$ = $2 ? $2 : $1; } 374 + | direct_abstract_declarator attribute_opt 375 + { $$ = $2; dont_want_type_specifier = false; } 376 + ; 377 + 378 + direct_abstract_declarator: 379 + direct_abstract_declarator1 380 + | direct_abstract_declarator1 open_paren parameter_declaration_clause ')' 381 + { $$ = $4; } 382 + | open_paren parameter_declaration_clause ')' 383 + { $$ = $3; } 384 + ; 385 + 386 + direct_abstract_declarator1: 387 + IDENT 385 388 { /* For version 2 checksums, we don't want to remember 386 389 private parameter names. */ 387 390 remove_node($1); 388 391 $$ = $1; 389 392 } 390 - /* This wasn't really a typedef name but an identifier that 391 - shadows one. */ 392 - | TYPE 393 - { remove_node($1); 394 - $$ = $1; 395 - } 396 - | direct_m_abstract_declarator '(' parameter_declaration_clause ')' 393 + | direct_abstract_declarator1 open_paren error ')' 397 394 { $$ = $4; } 398 - | direct_m_abstract_declarator '(' error ')' 399 - { $$ = $4; } 400 - | direct_m_abstract_declarator BRACKET_PHRASE 395 + | direct_abstract_declarator1 BRACKET_PHRASE 401 396 { $$ = $2; } 402 - | '(' m_abstract_declarator ')' 397 + | open_paren attribute_opt abstract_declarator ')' 398 + { $$ = $4; } 399 + | open_paren error ')' 403 400 { $$ = $3; } 404 - | '(' error ')' 405 - { $$ = $3; } 401 + | BRACKET_PHRASE 402 + ; 403 + 404 + open_paren: 405 + '(' { $$ = $1; dont_want_type_specifier = false; } 406 406 ; 407 407 408 408 function_definition: ··· 454 430 455 431 member_declaration: 456 432 decl_specifier_seq_opt member_declarator_list_opt ';' 457 - { $$ = $3; } 433 + { $$ = $3; dont_want_type_specifier = false; } 458 434 | error ';' 459 - { $$ = $2; } 435 + { $$ = $2; dont_want_type_specifier = false; } 460 436 ; 461 437 462 438 member_declarator_list_opt: ··· 466 442 467 443 member_declarator_list: 468 444 member_declarator 469 - | member_declarator_list ',' member_declarator { $$ = $3; } 445 + { $$ = $1; dont_want_type_specifier = true; } 446 + | member_declarator_list ',' member_declarator 447 + { $$ = $3; dont_want_type_specifier = true; } 470 448 ; 471 449 472 450 member_declarator: ··· 483 457 484 458 attribute_opt: 485 459 /* empty */ { $$ = NULL; } 486 - | attribute_opt ATTRIBUTE_PHRASE 460 + | attribute_opt ATTRIBUTE_PHRASE { $$ = $2; } 487 461 ; 488 462 489 463 enum_body: ··· 498 472 enumerator: 499 473 IDENT 500 474 { 501 - const char *name = strdup((*$1)->string); 475 + const char *name = (*$1)->string; 502 476 add_symbol(name, SYM_ENUM_CONST, NULL, 0); 503 477 } 504 478 | IDENT '=' EXPRESSION_PHRASE 505 479 { 506 - const char *name = strdup((*$1)->string); 480 + const char *name = (*$1)->string; 507 481 struct string_list *expr = copy_list_range(*$3, *$2); 508 482 add_symbol(name, SYM_ENUM_CONST, expr, 0); 509 483 }
+3 -1
scripts/kconfig/Makefile
··· 105 105 all-config-fragments = $(call configfiles,*.config) 106 106 config-fragments = $(call configfiles,$@) 107 107 108 + cmd_merge_fragments = $(srctree)/scripts/kconfig/merge_config.sh -m $(KCONFIG_CONFIG) $(config-fragments) 109 + 108 110 %.config: $(obj)/conf 109 111 $(if $(config-fragments),, $(error $@ fragment does not exists on this architecture)) 110 - $(Q)$(CONFIG_SHELL) $(srctree)/scripts/kconfig/merge_config.sh -m $(KCONFIG_CONFIG) $(config-fragments) 112 + $(call cmd,merge_fragments) 111 113 $(Q)$(MAKE) -f $(srctree)/Makefile olddefconfig 112 114 113 115 PHONY += tinyconfig
+4 -2
scripts/kconfig/confdata.c
··· 360 360 361 361 *p = '\0'; 362 362 363 - in = zconf_fopen(env); 363 + name = env; 364 + 365 + in = zconf_fopen(name); 364 366 if (in) { 365 367 conf_message("using defaults found in %s", 366 - env); 368 + name); 367 369 goto load; 368 370 } 369 371
+4 -4
scripts/kconfig/qconf.cc
··· 1464 1464 { 1465 1465 QString str; 1466 1466 1467 - str = QFileDialog::getOpenFileName(this, "", configname); 1468 - if (str.isNull()) 1467 + str = QFileDialog::getOpenFileName(this, QString(), configname); 1468 + if (str.isEmpty()) 1469 1469 return; 1470 1470 1471 1471 if (conf_read(str.toLocal8Bit().constData())) ··· 1491 1491 { 1492 1492 QString str; 1493 1493 1494 - str = QFileDialog::getSaveFileName(this, "", configname); 1495 - if (str.isNull()) 1494 + str = QFileDialog::getSaveFileName(this, QString(), configname); 1495 + if (str.isEmpty()) 1496 1496 return; 1497 1497 1498 1498 if (conf_write(str.toLocal8Bit().constData())) {
+1
scripts/kconfig/symbol.c
··· 388 388 " Selected by [m]:\n"); 389 389 390 390 fputs(str_get(&gs), stderr); 391 + str_free(&gs); 391 392 sym_warnings++; 392 393 } 393 394
+65 -6
scripts/mod/modpost.c
··· 33 33 static bool modversions; 34 34 /* Is CONFIG_MODULE_SRCVERSION_ALL set? */ 35 35 static bool all_versions; 36 + /* Is CONFIG_BASIC_MODVERSIONS set? */ 37 + static bool basic_modversions; 38 + /* Is CONFIG_EXTENDED_MODVERSIONS set? */ 39 + static bool extended_modversions; 36 40 /* If we are modposting external module set to 1 */ 37 41 static bool external_module; 38 42 /* Only warn about unresolved symbols */ ··· 1810 1806 } 1811 1807 1812 1808 /** 1809 + * Record CRCs for unresolved symbols, supporting long names 1810 + */ 1811 + static void add_extended_versions(struct buffer *b, struct module *mod) 1812 + { 1813 + struct symbol *s; 1814 + 1815 + if (!extended_modversions) 1816 + return; 1817 + 1818 + buf_printf(b, "\n"); 1819 + buf_printf(b, "static const u32 ____version_ext_crcs[]\n"); 1820 + buf_printf(b, "__used __section(\"__version_ext_crcs\") = {\n"); 1821 + list_for_each_entry(s, &mod->unresolved_symbols, list) { 1822 + if (!s->module) 1823 + continue; 1824 + if (!s->crc_valid) { 1825 + warn("\"%s\" [%s.ko] has no CRC!\n", 1826 + s->name, mod->name); 1827 + continue; 1828 + } 1829 + buf_printf(b, "\t0x%08x,\n", s->crc); 1830 + } 1831 + buf_printf(b, "};\n"); 1832 + 1833 + buf_printf(b, "static const char ____version_ext_names[]\n"); 1834 + buf_printf(b, "__used __section(\"__version_ext_names\") =\n"); 1835 + list_for_each_entry(s, &mod->unresolved_symbols, list) { 1836 + if (!s->module) 1837 + continue; 1838 + if (!s->crc_valid) 1839 + /* 1840 + * We already warned on this when producing the crc 1841 + * table. 1842 + * We need to skip its name too, as the indexes in 1843 + * both tables need to align. 1844 + */ 1845 + continue; 1846 + buf_printf(b, "\t\"%s\\0\"\n", s->name); 1847 + } 1848 + buf_printf(b, ";\n"); 1849 + } 1850 + 1851 + /** 1813 1852 * Record CRCs for unresolved symbols 1814 1853 **/ 1815 1854 static void add_versions(struct buffer *b, struct module *mod) 1816 1855 { 1817 1856 struct symbol *s; 1818 1857 1819 - if (!modversions) 1858 + if (!basic_modversions) 1820 1859 return; 1821 1860 1822 1861 buf_printf(b, "\n"); ··· 1875 1828 continue; 1876 1829 } 1877 1830 if (strlen(s->name) >= MODULE_NAME_LEN) { 1878 - error("too long symbol \"%s\" [%s.ko]\n", 1879 - s->name, mod->name); 1880 - break; 1831 + if (extended_modversions) { 1832 + /* this symbol will only be in the extended info */ 1833 + continue; 1834 + } else { 1835 + error("too long symbol \"%s\" [%s.ko]\n", 1836 + s->name, mod->name); 1837 + break; 1838 + } 1881 1839 } 1882 - buf_printf(b, "\t{ %#8x, \"%s\" },\n", 1840 + buf_printf(b, "\t{ 0x%08x, \"%s\" },\n", 1883 1841 s->crc, s->name); 1884 1842 } 1885 1843 ··· 2013 1961 add_header(&buf, mod); 2014 1962 add_exported_symbols(&buf, mod); 2015 1963 add_versions(&buf, mod); 1964 + add_extended_versions(&buf, mod); 2016 1965 add_depends(&buf, mod); 2017 1966 2018 1967 buf_printf(&buf, "\n"); ··· 2179 2126 LIST_HEAD(dump_lists); 2180 2127 struct dump_list *dl, *dl2; 2181 2128 2182 - while ((opt = getopt(argc, argv, "ei:MmnT:to:au:WwENd:")) != -1) { 2129 + while ((opt = getopt(argc, argv, "ei:MmnT:to:au:WwENd:xb")) != -1) { 2183 2130 switch (opt) { 2184 2131 case 'e': 2185 2132 external_module = true; ··· 2227 2174 break; 2228 2175 case 'd': 2229 2176 missing_namespace_deps = optarg; 2177 + break; 2178 + case 'b': 2179 + basic_modversions = true; 2180 + break; 2181 + case 'x': 2182 + extended_modversions = true; 2230 2183 break; 2231 2184 default: 2232 2185 exit(1);
-1
scripts/package/PKGBUILD
··· 22 22 makedepends=( 23 23 bc 24 24 bison 25 - cpio 26 25 flex 27 26 gettext 28 27 kmod
+16 -8
scripts/package/builddeb
··· 5 5 # 6 6 # Simple script to generate a deb package for a Linux kernel. All the 7 7 # complexity of what to do with a kernel after it is installed or removed 8 - # is left to other scripts and packages: they can install scripts in the 9 - # /etc/kernel/{pre,post}{inst,rm}.d/ directories (or an alternative location 10 - # specified in KDEB_HOOKDIR) that will be called on package install and 11 - # removal. 8 + # is left to other scripts and packages. Scripts can be placed into the 9 + # preinst, postinst, prerm and postrm directories in /etc/kernel or 10 + # /usr/share/kernel. A different list of search directories can be given 11 + # via KDEB_HOOKDIR. Scripts in directories earlier in the list will 12 + # override scripts of the same name in later directories. The script will 13 + # be called on package installation and removal. 12 14 13 15 set -eu 14 16 ··· 76 74 # kernel packages, as well as kernel packages built using make-kpkg. 77 75 # make-kpkg sets $INITRD to indicate whether an initramfs is wanted, and 78 76 # so do we; recent versions of dracut and initramfs-tools will obey this. 79 - debhookdir=${KDEB_HOOKDIR:-/etc/kernel} 77 + debhookdir=${KDEB_HOOKDIR:-/etc/kernel /usr/share/kernel} 80 78 for script in postinst postrm preinst prerm; do 81 - mkdir -p "${pdir}${debhookdir}/${script}.d" 82 - 83 79 mkdir -p "${pdir}/DEBIAN" 84 80 cat <<-EOF > "${pdir}/DEBIAN/${script}" 85 81 #!/bin/sh ··· 90 90 # Tell initramfs builder whether it's wanted 91 91 export INITRD=$(if_enabled_echo CONFIG_BLK_DEV_INITRD Yes No) 92 92 93 - test -d ${debhookdir}/${script}.d && run-parts --arg="${KERNELRELEASE}" --arg="/${installed_image_path}" ${debhookdir}/${script}.d 93 + # run-parts will error out if one of its directory arguments does not 94 + # exist, so filter the list of hook directories accordingly. 95 + hookdirs= 96 + for dir in ${debhookdir}; do 97 + test -d "\$dir/${script}.d" || continue 98 + hookdirs="\$hookdirs \$dir/${script}.d" 99 + done 100 + hookdirs="\${hookdirs# }" 101 + test -n "\$hookdirs" && run-parts --arg="${KERNELRELEASE}" --arg="/${installed_image_path}" \$hookdirs 94 102 exit 0 95 103 EOF 96 104 chmod 755 "${pdir}/DEBIAN/${script}"
+9 -24
scripts/package/install-extmod-build
··· 49 49 # This caters to host programs that participate in Kbuild. objtool and 50 50 # resolve_btfids are out of scope. 51 51 if [ "${CC}" != "${HOSTCC}" ]; then 52 - echo "Rebuilding host programs with ${CC}..." 53 - 54 - # This leverages external module building. 55 - # - Clear sub_make_done to allow the top-level Makefile to redo sub-make. 56 - # - Filter out --no-print-directory to print "Entering directory" logs 57 - # when Make changes the working directory. 58 - unset sub_make_done 59 - MAKEFLAGS=$(echo "${MAKEFLAGS}" | sed s/--no-print-directory//) 60 - 61 - cat <<-'EOF' > "${destdir}/Kbuild" 62 - subdir-y := scripts 52 + cat "${destdir}/scripts/Makefile" - <<-'EOF' > "${destdir}/scripts/Kbuild" 53 + subdir-y += basic 54 + hostprogs-always-y += mod/modpost 55 + mod/modpost-objs := $(addprefix mod/, modpost.o file2alias.o sumversion.o symsearch.o) 63 56 EOF 64 57 65 58 # HOSTCXX is not overridden. The C++ compiler is used to build: ··· 60 67 # - GCC plugins, which will not work on the installed system even after 61 68 # being rebuilt. 62 69 # 63 - # Use the single-target build to avoid the modpost invocation, which 64 - # would overwrite Module.symvers. 65 - "${MAKE}" HOSTCC="${CC}" KBUILD_OUTPUT=. KBUILD_EXTMOD="${destdir}" scripts/ 70 + # Clear VPATH and srcroot because the source files reside in the output 71 + # directory. 72 + # shellcheck disable=SC2016 # $(MAKE), $(CC), and $(build) will be expanded by Make 73 + "${MAKE}" run-command KBUILD_RUN_COMMAND='+$(MAKE) HOSTCC=$(CC) VPATH= srcroot=. $(build)='"${destdir}"/scripts 66 74 67 - cat <<-'EOF' > "${destdir}/scripts/Kbuild" 68 - subdir-y := basic 69 - hostprogs-always-y := mod/modpost 70 - mod/modpost-objs := $(addprefix mod/, modpost.o file2alias.o sumversion.o symsearch.o) 71 - EOF 72 - 73 - # Run once again to rebuild scripts/basic/ and scripts/mod/modpost. 74 - "${MAKE}" HOSTCC="${CC}" KBUILD_OUTPUT=. KBUILD_EXTMOD="${destdir}" scripts/ 75 - 76 - rm -f "${destdir}/Kbuild" "${destdir}/scripts/Kbuild" 75 + rm -f "${destdir}/scripts/Kbuild" 77 76 fi 78 77 79 78 find "${destdir}" \( -name '.*.cmd' -o -name '*.o' \) -delete
+1 -1
scripts/package/mkdebian
··· 205 205 Maintainer: $maintainer 206 206 Rules-Requires-Root: no 207 207 Build-Depends: debhelper-compat (= 12) 208 - Build-Depends-Arch: bc, bison, cpio, flex, 208 + Build-Depends-Arch: bc, bison, flex, 209 209 gcc-${host_gnu} <!pkg.${sourcename}.nokernelheaders>, 210 210 kmod, libelf-dev:native, 211 211 libssl-dev:native, libssl-dev <!pkg.${sourcename}.nokernelheaders>,