1936cf61cSSami Tolvanen /* SPDX-License-Identifier: GPL-2.0 */ 2936cf61cSSami Tolvanen /* 3936cf61cSSami Tolvanen * kabi_ex.h 4936cf61cSSami Tolvanen * 5936cf61cSSami Tolvanen * Copyright (C) 2024 Google LLC 6936cf61cSSami Tolvanen * 7936cf61cSSami Tolvanen * Examples for kABI stability features with --stable. 8936cf61cSSami Tolvanen */ 9936cf61cSSami Tolvanen 10936cf61cSSami Tolvanen /* 11936cf61cSSami Tolvanen * The comments below each example contain the expected gendwarfksyms 12936cf61cSSami Tolvanen * output, which can be verified using LLVM's FileCheck tool: 13936cf61cSSami Tolvanen * 14936cf61cSSami Tolvanen * https://llvm.org/docs/CommandGuide/FileCheck.html 15936cf61cSSami Tolvanen * 16936cf61cSSami Tolvanen * Usage: 17936cf61cSSami Tolvanen * 18936cf61cSSami Tolvanen * $ gcc -g -c examples/kabi_ex.c -o examples/kabi_ex.o 19936cf61cSSami Tolvanen * 20936cf61cSSami Tolvanen * $ nm examples/kabi_ex.o | awk '{ print $NF }' | \ 21936cf61cSSami Tolvanen * ./gendwarfksyms --stable --dump-dies \ 22936cf61cSSami Tolvanen * examples/kabi_ex.o 2>&1 >/dev/null | \ 23936cf61cSSami Tolvanen * FileCheck examples/kabi_ex.h --check-prefix=STABLE 24936cf61cSSami Tolvanen */ 25936cf61cSSami Tolvanen 26936cf61cSSami Tolvanen #ifndef __KABI_EX_H__ 27936cf61cSSami Tolvanen #define __KABI_EX_H__ 28936cf61cSSami Tolvanen 29936cf61cSSami Tolvanen #include "kabi.h" 30936cf61cSSami Tolvanen 31936cf61cSSami Tolvanen /* 32936cf61cSSami Tolvanen * Example: kABI rules 33936cf61cSSami Tolvanen */ 34936cf61cSSami Tolvanen 35936cf61cSSami Tolvanen struct s { 36936cf61cSSami Tolvanen int a; 37936cf61cSSami Tolvanen }; 38936cf61cSSami Tolvanen 39936cf61cSSami Tolvanen KABI_DECLONLY(s); 40936cf61cSSami Tolvanen 41936cf61cSSami Tolvanen /* 42936cf61cSSami Tolvanen * STABLE: variable structure_type s { 43936cf61cSSami Tolvanen * STABLE-NEXT: } 44936cf61cSSami Tolvanen */ 45936cf61cSSami Tolvanen 46936cf61cSSami Tolvanen enum e { 47936cf61cSSami Tolvanen A, 48936cf61cSSami Tolvanen B, 49936cf61cSSami Tolvanen C, 50936cf61cSSami Tolvanen D, 51936cf61cSSami Tolvanen }; 52936cf61cSSami Tolvanen 53936cf61cSSami Tolvanen KABI_ENUMERATOR_IGNORE(e, B); 54936cf61cSSami Tolvanen KABI_ENUMERATOR_IGNORE(e, C); 55936cf61cSSami Tolvanen KABI_ENUMERATOR_VALUE(e, D, 123456789); 56936cf61cSSami Tolvanen 57936cf61cSSami Tolvanen /* 58936cf61cSSami Tolvanen * STABLE: variable enumeration_type e { 59936cf61cSSami Tolvanen * STABLE-NEXT: enumerator A = 0 , 60936cf61cSSami Tolvanen * STABLE-NEXT: enumerator D = 123456789 61936cf61cSSami Tolvanen * STABLE-NEXT: } byte_size(4) 62*a9369418SSami Tolvanen */ 63*a9369418SSami Tolvanen 64*a9369418SSami Tolvanen /* 65*a9369418SSami Tolvanen * Example: Reserved fields 66*a9369418SSami Tolvanen */ 67*a9369418SSami Tolvanen struct ex0a { 68*a9369418SSami Tolvanen int a; 69*a9369418SSami Tolvanen KABI_RESERVE(0); 70*a9369418SSami Tolvanen KABI_RESERVE(1); 71*a9369418SSami Tolvanen }; 72*a9369418SSami Tolvanen 73*a9369418SSami Tolvanen /* 74*a9369418SSami Tolvanen * STABLE: variable structure_type ex0a { 75*a9369418SSami Tolvanen * STABLE-NEXT: member base_type int byte_size(4) encoding(5) a data_member_location(0) , 76*a9369418SSami Tolvanen * STABLE-NEXT: member base_type [[ULONG:long unsigned int|unsigned long]] byte_size(8) encoding(7) data_member_location(8) , 77*a9369418SSami Tolvanen * STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) data_member_location(16) 78*a9369418SSami Tolvanen * STABLE-NEXT: } byte_size(24) 79*a9369418SSami Tolvanen */ 80*a9369418SSami Tolvanen 81*a9369418SSami Tolvanen struct ex0b { 82*a9369418SSami Tolvanen int a; 83*a9369418SSami Tolvanen KABI_RESERVE(0); 84*a9369418SSami Tolvanen KABI_USE2(1, int b, int c); 85*a9369418SSami Tolvanen }; 86*a9369418SSami Tolvanen 87*a9369418SSami Tolvanen /* 88*a9369418SSami Tolvanen * STABLE: variable structure_type ex0b { 89*a9369418SSami Tolvanen * STABLE-NEXT: member base_type int byte_size(4) encoding(5) a data_member_location(0) , 90*a9369418SSami Tolvanen * STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) data_member_location(8) , 91*a9369418SSami Tolvanen * STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) data_member_location(16) 92*a9369418SSami Tolvanen * STABLE-NEXT: } byte_size(24) 93*a9369418SSami Tolvanen */ 94*a9369418SSami Tolvanen 95*a9369418SSami Tolvanen struct ex0c { 96*a9369418SSami Tolvanen int a; 97*a9369418SSami Tolvanen KABI_USE(0, void *p); 98*a9369418SSami Tolvanen KABI_USE2(1, int b, int c); 99*a9369418SSami Tolvanen }; 100*a9369418SSami Tolvanen 101*a9369418SSami Tolvanen /* 102*a9369418SSami Tolvanen * STABLE: variable structure_type ex0c { 103*a9369418SSami Tolvanen * STABLE-NEXT: member base_type int byte_size(4) encoding(5) a data_member_location(0) , 104*a9369418SSami Tolvanen * STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) data_member_location(8) , 105*a9369418SSami Tolvanen * STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) data_member_location(16) 106*a9369418SSami Tolvanen * STABLE-NEXT: } byte_size(24) 107*a9369418SSami Tolvanen */ 108*a9369418SSami Tolvanen 109*a9369418SSami Tolvanen /* 110*a9369418SSami Tolvanen * Example: A reserved array 111*a9369418SSami Tolvanen */ 112*a9369418SSami Tolvanen 113*a9369418SSami Tolvanen struct ex1a { 114*a9369418SSami Tolvanen unsigned int a; 115*a9369418SSami Tolvanen KABI_RESERVE_ARRAY(0, 64); 116*a9369418SSami Tolvanen }; 117*a9369418SSami Tolvanen 118*a9369418SSami Tolvanen /* 119*a9369418SSami Tolvanen * STABLE: variable structure_type ex1a { 120*a9369418SSami Tolvanen * STABLE-NEXT: member base_type unsigned int byte_size(4) encoding(7) a data_member_location(0) , 121*a9369418SSami Tolvanen * STABLE-NEXT: member array_type[64] { 122*a9369418SSami Tolvanen * STABLE-NEXT: base_type unsigned char byte_size(1) encoding(8) 123*a9369418SSami Tolvanen * STABLE-NEXT: } data_member_location(8) 124*a9369418SSami Tolvanen * STABLE-NEXT: } byte_size(72) 125*a9369418SSami Tolvanen */ 126*a9369418SSami Tolvanen 127*a9369418SSami Tolvanen struct ex1b { 128*a9369418SSami Tolvanen unsigned int a; 129*a9369418SSami Tolvanen KABI_USE_ARRAY( 130*a9369418SSami Tolvanen 0, 64, struct { 131*a9369418SSami Tolvanen void *p; 132*a9369418SSami Tolvanen KABI_RESERVE_ARRAY(1, 56); 133*a9369418SSami Tolvanen }); 134*a9369418SSami Tolvanen }; 135*a9369418SSami Tolvanen 136*a9369418SSami Tolvanen /* 137*a9369418SSami Tolvanen * STABLE: variable structure_type ex1b { 138*a9369418SSami Tolvanen * STABLE-NEXT: member base_type unsigned int byte_size(4) encoding(7) a data_member_location(0) , 139*a9369418SSami Tolvanen * STABLE-NEXT: member array_type[64] { 140*a9369418SSami Tolvanen * STABLE-NEXT: base_type unsigned char byte_size(1) encoding(8) 141*a9369418SSami Tolvanen * STABLE-NEXT: } data_member_location(8) 142*a9369418SSami Tolvanen * STABLE-NEXT: } byte_size(72) 143*a9369418SSami Tolvanen */ 144*a9369418SSami Tolvanen 145*a9369418SSami Tolvanen struct ex1c { 146*a9369418SSami Tolvanen unsigned int a; 147*a9369418SSami Tolvanen KABI_USE_ARRAY(0, 64, void *p[8]); 148*a9369418SSami Tolvanen }; 149*a9369418SSami Tolvanen 150*a9369418SSami Tolvanen /* 151*a9369418SSami Tolvanen * STABLE: variable structure_type ex1c { 152*a9369418SSami Tolvanen * STABLE-NEXT: member base_type unsigned int byte_size(4) encoding(7) a data_member_location(0) , 153*a9369418SSami Tolvanen * STABLE-NEXT: member array_type[64] { 154*a9369418SSami Tolvanen * STABLE-NEXT: base_type unsigned char byte_size(1) encoding(8) 155*a9369418SSami Tolvanen * STABLE-NEXT: } data_member_location(8) 156*a9369418SSami Tolvanen * STABLE-NEXT: } byte_size(72) 157*a9369418SSami Tolvanen */ 158*a9369418SSami Tolvanen 159*a9369418SSami Tolvanen /* 160*a9369418SSami Tolvanen * Example: An ignored field added to an alignment hole 161*a9369418SSami Tolvanen */ 162*a9369418SSami Tolvanen 163*a9369418SSami Tolvanen struct ex2a { 164*a9369418SSami Tolvanen int a; 165*a9369418SSami Tolvanen unsigned long b; 166*a9369418SSami Tolvanen int c; 167*a9369418SSami Tolvanen unsigned long d; 168*a9369418SSami Tolvanen }; 169*a9369418SSami Tolvanen 170*a9369418SSami Tolvanen /* 171*a9369418SSami Tolvanen * STABLE: variable structure_type ex2a { 172*a9369418SSami Tolvanen * STABLE-NEXT: member base_type int byte_size(4) encoding(5) a data_member_location(0) , 173*a9369418SSami Tolvanen * STABLE-NEXT: member base_type [[ULONG:long unsigned int|unsigned long]] byte_size(8) encoding(7) b data_member_location(8) 174*a9369418SSami Tolvanen * STABLE-NEXT: member base_type int byte_size(4) encoding(5) c data_member_location(16) , 175*a9369418SSami Tolvanen * STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) d data_member_location(24) 176*a9369418SSami Tolvanen * STABLE-NEXT: } byte_size(32) 177*a9369418SSami Tolvanen */ 178*a9369418SSami Tolvanen 179*a9369418SSami Tolvanen struct ex2b { 180*a9369418SSami Tolvanen int a; 181*a9369418SSami Tolvanen KABI_IGNORE(0, unsigned int n); 182*a9369418SSami Tolvanen unsigned long b; 183*a9369418SSami Tolvanen int c; 184*a9369418SSami Tolvanen unsigned long d; 185*a9369418SSami Tolvanen }; 186*a9369418SSami Tolvanen 187*a9369418SSami Tolvanen _Static_assert(sizeof(struct ex2a) == sizeof(struct ex2b), "ex2a size doesn't match ex2b"); 188*a9369418SSami Tolvanen 189*a9369418SSami Tolvanen /* 190*a9369418SSami Tolvanen * STABLE: variable structure_type ex2b { 191*a9369418SSami Tolvanen * STABLE-NEXT: member base_type int byte_size(4) encoding(5) a data_member_location(0) , 192*a9369418SSami Tolvanen * STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) b data_member_location(8) 193*a9369418SSami Tolvanen * STABLE-NEXT: member base_type int byte_size(4) encoding(5) c data_member_location(16) , 194*a9369418SSami Tolvanen * STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) d data_member_location(24) 195*a9369418SSami Tolvanen * STABLE-NEXT: } byte_size(32) 196*a9369418SSami Tolvanen */ 197*a9369418SSami Tolvanen 198*a9369418SSami Tolvanen struct ex2c { 199*a9369418SSami Tolvanen int a; 200*a9369418SSami Tolvanen KABI_IGNORE(0, unsigned int n); 201*a9369418SSami Tolvanen unsigned long b; 202*a9369418SSami Tolvanen int c; 203*a9369418SSami Tolvanen KABI_IGNORE(1, unsigned int m); 204*a9369418SSami Tolvanen unsigned long d; 205*a9369418SSami Tolvanen }; 206*a9369418SSami Tolvanen 207*a9369418SSami Tolvanen _Static_assert(sizeof(struct ex2a) == sizeof(struct ex2c), "ex2a size doesn't match ex2c"); 208*a9369418SSami Tolvanen 209*a9369418SSami Tolvanen /* 210*a9369418SSami Tolvanen * STABLE: variable structure_type ex2c { 211*a9369418SSami Tolvanen * STABLE-NEXT: member base_type int byte_size(4) encoding(5) a data_member_location(0) , 212*a9369418SSami Tolvanen * STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) b data_member_location(8) 213*a9369418SSami Tolvanen * STABLE-NEXT: member base_type int byte_size(4) encoding(5) c data_member_location(16) , 214*a9369418SSami Tolvanen * STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) d data_member_location(24) 215*a9369418SSami Tolvanen * STABLE-NEXT: } byte_size(32) 216*a9369418SSami Tolvanen */ 217*a9369418SSami Tolvanen 218*a9369418SSami Tolvanen 219*a9369418SSami Tolvanen /* 220*a9369418SSami Tolvanen * Example: A replaced field 221*a9369418SSami Tolvanen */ 222*a9369418SSami Tolvanen 223*a9369418SSami Tolvanen struct ex3a { 224*a9369418SSami Tolvanen unsigned long a; 225*a9369418SSami Tolvanen unsigned long unused; 226*a9369418SSami Tolvanen }; 227*a9369418SSami Tolvanen 228*a9369418SSami Tolvanen /* 229*a9369418SSami Tolvanen * STABLE: variable structure_type ex3a { 230*a9369418SSami Tolvanen * STABLE-NEXT: member base_type [[ULONG:long unsigned int|unsigned long]] byte_size(8) encoding(7) a data_member_location(0) 231*a9369418SSami Tolvanen * STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) unused data_member_location(8) 232*a9369418SSami Tolvanen * STABLE-NEXT: } byte_size(16) 233*a9369418SSami Tolvanen */ 234*a9369418SSami Tolvanen 235*a9369418SSami Tolvanen struct ex3b { 236*a9369418SSami Tolvanen unsigned long a; 237*a9369418SSami Tolvanen KABI_REPLACE(unsigned long, unused, unsigned long renamed); 238*a9369418SSami Tolvanen }; 239*a9369418SSami Tolvanen 240*a9369418SSami Tolvanen _Static_assert(sizeof(struct ex3a) == sizeof(struct ex3b), "ex3a size doesn't match ex3b"); 241*a9369418SSami Tolvanen 242*a9369418SSami Tolvanen /* 243*a9369418SSami Tolvanen * STABLE: variable structure_type ex3b { 244*a9369418SSami Tolvanen * STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) a data_member_location(0) 245*a9369418SSami Tolvanen * STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) unused data_member_location(8) 246*a9369418SSami Tolvanen * STABLE-NEXT: } byte_size(16) 247*a9369418SSami Tolvanen */ 248*a9369418SSami Tolvanen 249*a9369418SSami Tolvanen struct ex3c { 250*a9369418SSami Tolvanen unsigned long a; 251*a9369418SSami Tolvanen KABI_REPLACE(unsigned long, unused, long replaced); 252*a9369418SSami Tolvanen }; 253*a9369418SSami Tolvanen 254*a9369418SSami Tolvanen _Static_assert(sizeof(struct ex3a) == sizeof(struct ex3c), "ex3a size doesn't match ex3c"); 255*a9369418SSami Tolvanen 256*a9369418SSami Tolvanen /* 257*a9369418SSami Tolvanen * STABLE: variable structure_type ex3c { 258*a9369418SSami Tolvanen * STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) a data_member_location(0) 259*a9369418SSami Tolvanen * STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) unused data_member_location(8) 260*a9369418SSami Tolvanen * STABLE-NEXT: } byte_size(16) 261936cf61cSSami Tolvanen */ 262936cf61cSSami Tolvanen 263936cf61cSSami Tolvanen #endif /* __KABI_EX_H__ */ 264