| /* SPDX-License-Identifier: GPL-2.0 */ |
| /* |
| * kabi_ex.h |
| * |
| * Copyright (C) 2024 Google LLC |
| * |
| * Examples for kABI stability features with --stable. |
| */ |
| |
| /* |
| * The comments below each example contain the expected gendwarfksyms |
| * output, which can be verified using LLVM's FileCheck tool: |
| * |
| * https://llvm.org/docs/CommandGuide/FileCheck.html |
| * |
| * Usage: |
| * |
| * $ gcc -g -c examples/kabi_ex.c -o examples/kabi_ex.o |
| * |
| * $ nm examples/kabi_ex.o | awk '{ print $NF }' | \ |
| * ./gendwarfksyms --stable --dump-dies \ |
| * examples/kabi_ex.o 2>&1 >/dev/null | \ |
| * FileCheck examples/kabi_ex.h --check-prefix=STABLE |
| */ |
| |
| #ifndef __KABI_EX_H__ |
| #define __KABI_EX_H__ |
| |
| #include "kabi.h" |
| |
| /* |
| * Example: kABI rules |
| */ |
| |
| struct s { |
| int a; |
| }; |
| |
| KABI_DECLONLY(s); |
| |
| /* |
| * STABLE: variable structure_type s { |
| * STABLE-NEXT: } |
| */ |
| |
| enum e { |
| A, |
| B, |
| C, |
| D, |
| }; |
| |
| KABI_ENUMERATOR_IGNORE(e, B); |
| KABI_ENUMERATOR_IGNORE(e, C); |
| KABI_ENUMERATOR_VALUE(e, D, 123456789); |
| |
| /* |
| * STABLE: variable enumeration_type e { |
| * STABLE-NEXT: enumerator A = 0 , |
| * STABLE-NEXT: enumerator D = 123456789 |
| * STABLE-NEXT: } byte_size(4) |
| */ |
| |
| /* |
| * Example: Reserved fields |
| */ |
| struct ex0a { |
| int a; |
| KABI_RESERVE(0); |
| KABI_RESERVE(1); |
| }; |
| |
| /* |
| * STABLE: variable structure_type ex0a { |
| * STABLE-NEXT: member base_type int byte_size(4) encoding(5) a data_member_location(0) , |
| * STABLE-NEXT: member base_type [[ULONG:long unsigned int|unsigned long]] byte_size(8) encoding(7) data_member_location(8) , |
| * STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) data_member_location(16) |
| * STABLE-NEXT: } byte_size(24) |
| */ |
| |
| struct ex0b { |
| int a; |
| KABI_RESERVE(0); |
| KABI_USE2(1, int b, int c); |
| }; |
| |
| /* |
| * STABLE: variable structure_type ex0b { |
| * STABLE-NEXT: member base_type int byte_size(4) encoding(5) a data_member_location(0) , |
| * STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) data_member_location(8) , |
| * STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) data_member_location(16) |
| * STABLE-NEXT: } byte_size(24) |
| */ |
| |
| struct ex0c { |
| int a; |
| KABI_USE(0, void *p); |
| KABI_USE2(1, int b, int c); |
| }; |
| |
| /* |
| * STABLE: variable structure_type ex0c { |
| * STABLE-NEXT: member base_type int byte_size(4) encoding(5) a data_member_location(0) , |
| * STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) data_member_location(8) , |
| * STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) data_member_location(16) |
| * STABLE-NEXT: } byte_size(24) |
| */ |
| |
| /* |
| * Example: A reserved array |
| */ |
| |
| struct ex1a { |
| unsigned int a; |
| KABI_RESERVE_ARRAY(0, 64); |
| }; |
| |
| /* |
| * STABLE: variable structure_type ex1a { |
| * STABLE-NEXT: member base_type unsigned int byte_size(4) encoding(7) a data_member_location(0) , |
| * STABLE-NEXT: member array_type[64] { |
| * STABLE-NEXT: base_type unsigned char byte_size(1) encoding(8) |
| * STABLE-NEXT: } data_member_location(8) |
| * STABLE-NEXT: } byte_size(72) |
| */ |
| |
| struct ex1b { |
| unsigned int a; |
| KABI_USE_ARRAY( |
| 0, 64, struct { |
| void *p; |
| KABI_RESERVE_ARRAY(1, 56); |
| }); |
| }; |
| |
| /* |
| * STABLE: variable structure_type ex1b { |
| * STABLE-NEXT: member base_type unsigned int byte_size(4) encoding(7) a data_member_location(0) , |
| * STABLE-NEXT: member array_type[64] { |
| * STABLE-NEXT: base_type unsigned char byte_size(1) encoding(8) |
| * STABLE-NEXT: } data_member_location(8) |
| * STABLE-NEXT: } byte_size(72) |
| */ |
| |
| struct ex1c { |
| unsigned int a; |
| KABI_USE_ARRAY(0, 64, void *p[8]); |
| }; |
| |
| /* |
| * STABLE: variable structure_type ex1c { |
| * STABLE-NEXT: member base_type unsigned int byte_size(4) encoding(7) a data_member_location(0) , |
| * STABLE-NEXT: member array_type[64] { |
| * STABLE-NEXT: base_type unsigned char byte_size(1) encoding(8) |
| * STABLE-NEXT: } data_member_location(8) |
| * STABLE-NEXT: } byte_size(72) |
| */ |
| |
| /* |
| * Example: An ignored field added to an alignment hole |
| */ |
| |
| struct ex2a { |
| int a; |
| unsigned long b; |
| int c; |
| unsigned long d; |
| }; |
| |
| /* |
| * STABLE: variable structure_type ex2a { |
| * STABLE-NEXT: member base_type int byte_size(4) encoding(5) a data_member_location(0) , |
| * STABLE-NEXT: member base_type [[ULONG:long unsigned int|unsigned long]] byte_size(8) encoding(7) b data_member_location(8) |
| * STABLE-NEXT: member base_type int byte_size(4) encoding(5) c data_member_location(16) , |
| * STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) d data_member_location(24) |
| * STABLE-NEXT: } byte_size(32) |
| */ |
| |
| struct ex2b { |
| int a; |
| KABI_IGNORE(0, unsigned int n); |
| unsigned long b; |
| int c; |
| unsigned long d; |
| }; |
| |
| _Static_assert(sizeof(struct ex2a) == sizeof(struct ex2b), "ex2a size doesn't match ex2b"); |
| |
| /* |
| * STABLE: variable structure_type ex2b { |
| * STABLE-NEXT: member base_type int byte_size(4) encoding(5) a data_member_location(0) , |
| * STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) b data_member_location(8) |
| * STABLE-NEXT: member base_type int byte_size(4) encoding(5) c data_member_location(16) , |
| * STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) d data_member_location(24) |
| * STABLE-NEXT: } byte_size(32) |
| */ |
| |
| struct ex2c { |
| int a; |
| KABI_IGNORE(0, unsigned int n); |
| unsigned long b; |
| int c; |
| KABI_IGNORE(1, unsigned int m); |
| unsigned long d; |
| }; |
| |
| _Static_assert(sizeof(struct ex2a) == sizeof(struct ex2c), "ex2a size doesn't match ex2c"); |
| |
| /* |
| * STABLE: variable structure_type ex2c { |
| * STABLE-NEXT: member base_type int byte_size(4) encoding(5) a data_member_location(0) , |
| * STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) b data_member_location(8) |
| * STABLE-NEXT: member base_type int byte_size(4) encoding(5) c data_member_location(16) , |
| * STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) d data_member_location(24) |
| * STABLE-NEXT: } byte_size(32) |
| */ |
| |
| |
| /* |
| * Example: A replaced field |
| */ |
| |
| struct ex3a { |
| unsigned long a; |
| unsigned long unused; |
| }; |
| |
| /* |
| * STABLE: variable structure_type ex3a { |
| * STABLE-NEXT: member base_type [[ULONG:long unsigned int|unsigned long]] byte_size(8) encoding(7) a data_member_location(0) |
| * STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) unused data_member_location(8) |
| * STABLE-NEXT: } byte_size(16) |
| */ |
| |
| struct ex3b { |
| unsigned long a; |
| KABI_REPLACE(unsigned long, unused, unsigned long renamed); |
| }; |
| |
| _Static_assert(sizeof(struct ex3a) == sizeof(struct ex3b), "ex3a size doesn't match ex3b"); |
| |
| /* |
| * STABLE: variable structure_type ex3b { |
| * STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) a data_member_location(0) |
| * STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) unused data_member_location(8) |
| * STABLE-NEXT: } byte_size(16) |
| */ |
| |
| struct ex3c { |
| unsigned long a; |
| KABI_REPLACE(unsigned long, unused, long replaced); |
| }; |
| |
| _Static_assert(sizeof(struct ex3a) == sizeof(struct ex3c), "ex3a size doesn't match ex3c"); |
| |
| /* |
| * STABLE: variable structure_type ex3c { |
| * STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) a data_member_location(0) |
| * STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) unused data_member_location(8) |
| * STABLE-NEXT: } byte_size(16) |
| */ |
| |
| #endif /* __KABI_EX_H__ */ |