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__ */ 264