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 * $ nm examples/kabi_ex.o | awk '{ print $NF }' | \ 26 * ./gendwarfksyms --stable --dump-versions \ 27 * examples/kabi_ex.o 2>&1 >/dev/null | \ 28 * sort | \ 29 * FileCheck examples/kabi_ex.h --check-prefix=VERSIONS 30 */ 31 32 #ifndef __KABI_EX_H__ 33 #define __KABI_EX_H__ 34 35 #include "kabi.h" 36 37 /* 38 * Example: kABI rules 39 */ 40 41 struct s { 42 int a; 43 }; 44 45 KABI_DECLONLY(s); 46 47 /* 48 * STABLE: variable structure_type s { 49 * STABLE-NEXT: } 50 */ 51 52 enum e { 53 A, 54 B, 55 C, 56 D, 57 }; 58 59 KABI_ENUMERATOR_IGNORE(e, B); 60 KABI_ENUMERATOR_IGNORE(e, C); 61 KABI_ENUMERATOR_VALUE(e, D, 123456789); 62 63 /* 64 * STABLE: variable enumeration_type e { 65 * STABLE-NEXT: enumerator A = 0 , 66 * STABLE-NEXT: enumerator D = 123456789 67 * STABLE-NEXT: } byte_size(4) 68 */ 69 70 /* 71 * Example: Reserved fields 72 */ 73 struct ex0a { 74 int a; 75 KABI_RESERVE(0); 76 KABI_RESERVE(1); 77 }; 78 79 /* 80 * STABLE: variable structure_type ex0a { 81 * STABLE-NEXT: member base_type int byte_size(4) encoding(5) a data_member_location(0) , 82 * STABLE-NEXT: member base_type [[ULONG:long unsigned int|unsigned long]] byte_size(8) encoding(7) data_member_location(8) , 83 * STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) data_member_location(16) 84 * STABLE-NEXT: } byte_size(24) 85 */ 86 87 struct ex0b { 88 int a; 89 KABI_RESERVE(0); 90 KABI_USE2(1, int b, int c); 91 }; 92 93 /* 94 * STABLE: variable structure_type ex0b { 95 * STABLE-NEXT: member base_type int byte_size(4) encoding(5) a data_member_location(0) , 96 * STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) data_member_location(8) , 97 * STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) data_member_location(16) 98 * STABLE-NEXT: } byte_size(24) 99 */ 100 101 struct ex0c { 102 int a; 103 KABI_USE(0, void *p); 104 KABI_USE2(1, int b, int c); 105 }; 106 107 /* 108 * STABLE: variable structure_type ex0c { 109 * STABLE-NEXT: member base_type int byte_size(4) encoding(5) a data_member_location(0) , 110 * STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) data_member_location(8) , 111 * STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) data_member_location(16) 112 * STABLE-NEXT: } byte_size(24) 113 */ 114 115 /* 116 * Example: A reserved array 117 */ 118 119 struct ex1a { 120 unsigned int a; 121 KABI_RESERVE_ARRAY(0, 64); 122 }; 123 124 /* 125 * STABLE: variable structure_type ex1a { 126 * STABLE-NEXT: member base_type unsigned int byte_size(4) encoding(7) a data_member_location(0) , 127 * STABLE-NEXT: member array_type[64] { 128 * STABLE-NEXT: base_type unsigned char byte_size(1) encoding(8) 129 * STABLE-NEXT: } data_member_location(8) 130 * STABLE-NEXT: } byte_size(72) 131 */ 132 133 struct ex1b { 134 unsigned int a; 135 KABI_USE_ARRAY( 136 0, 64, struct { 137 void *p; 138 KABI_RESERVE_ARRAY(1, 56); 139 }); 140 }; 141 142 /* 143 * STABLE: variable structure_type ex1b { 144 * STABLE-NEXT: member base_type unsigned int byte_size(4) encoding(7) a data_member_location(0) , 145 * STABLE-NEXT: member array_type[64] { 146 * STABLE-NEXT: base_type unsigned char byte_size(1) encoding(8) 147 * STABLE-NEXT: } data_member_location(8) 148 * STABLE-NEXT: } byte_size(72) 149 */ 150 151 struct ex1c { 152 unsigned int a; 153 KABI_USE_ARRAY(0, 64, void *p[8]); 154 }; 155 156 /* 157 * STABLE: variable structure_type ex1c { 158 * STABLE-NEXT: member base_type unsigned int byte_size(4) encoding(7) a data_member_location(0) , 159 * STABLE-NEXT: member array_type[64] { 160 * STABLE-NEXT: base_type unsigned char byte_size(1) encoding(8) 161 * STABLE-NEXT: } data_member_location(8) 162 * STABLE-NEXT: } byte_size(72) 163 */ 164 165 /* 166 * Example: An ignored field added to an alignment hole 167 */ 168 169 struct ex2a { 170 int a; 171 unsigned long b; 172 int c; 173 unsigned long d; 174 }; 175 176 /* 177 * STABLE: variable structure_type ex2a { 178 * STABLE-NEXT: member base_type int byte_size(4) encoding(5) a data_member_location(0) , 179 * STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) b data_member_location(8) 180 * STABLE-NEXT: member base_type int byte_size(4) encoding(5) c data_member_location(16) , 181 * STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) d data_member_location(24) 182 * STABLE-NEXT: } byte_size(32) 183 */ 184 185 struct ex2b { 186 int a; 187 KABI_IGNORE(0, unsigned int n); 188 unsigned long b; 189 int c; 190 unsigned long d; 191 }; 192 193 _Static_assert(sizeof(struct ex2a) == sizeof(struct ex2b), "ex2a size doesn't match ex2b"); 194 195 /* 196 * STABLE: variable structure_type ex2b { 197 * STABLE-NEXT: member base_type int byte_size(4) encoding(5) a data_member_location(0) , 198 * STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) b data_member_location(8) 199 * STABLE-NEXT: member base_type int byte_size(4) encoding(5) c data_member_location(16) , 200 * STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) d data_member_location(24) 201 * STABLE-NEXT: } byte_size(32) 202 */ 203 204 struct ex2c { 205 int a; 206 KABI_IGNORE(0, unsigned int n); 207 unsigned long b; 208 int c; 209 KABI_IGNORE(1, unsigned int m); 210 unsigned long d; 211 }; 212 213 _Static_assert(sizeof(struct ex2a) == sizeof(struct ex2c), "ex2a size doesn't match ex2c"); 214 215 /* 216 * STABLE: variable structure_type ex2c { 217 * STABLE-NEXT: member base_type int byte_size(4) encoding(5) a data_member_location(0) , 218 * STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) b data_member_location(8) 219 * STABLE-NEXT: member base_type int byte_size(4) encoding(5) c data_member_location(16) , 220 * STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) d data_member_location(24) 221 * STABLE-NEXT: } byte_size(32) 222 */ 223 224 225 /* 226 * Example: A replaced field 227 */ 228 229 struct ex3a { 230 unsigned long a; 231 unsigned long unused; 232 }; 233 234 /* 235 * STABLE: variable structure_type ex3a { 236 * STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) a data_member_location(0) 237 * STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) unused data_member_location(8) 238 * STABLE-NEXT: } byte_size(16) 239 */ 240 241 struct ex3b { 242 unsigned long a; 243 KABI_REPLACE(unsigned long, unused, unsigned long renamed); 244 }; 245 246 _Static_assert(sizeof(struct ex3a) == sizeof(struct ex3b), "ex3a size doesn't match ex3b"); 247 248 /* 249 * STABLE: variable structure_type ex3b { 250 * STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) a data_member_location(0) 251 * STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) unused data_member_location(8) 252 * STABLE-NEXT: } byte_size(16) 253 */ 254 255 struct ex3c { 256 unsigned long a; 257 KABI_REPLACE(unsigned long, unused, long replaced); 258 }; 259 260 _Static_assert(sizeof(struct ex3a) == sizeof(struct ex3c), "ex3a size doesn't match ex3c"); 261 262 /* 263 * STABLE: variable structure_type ex3c { 264 * STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) a data_member_location(0) 265 * STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) unused data_member_location(8) 266 * STABLE-NEXT: } byte_size(16) 267 */ 268 269 /* 270 * Example: An ignored field added to an end of a partially opaque struct, 271 * while keeping the byte_size attribute unchanged. 272 */ 273 274 struct ex4a { 275 unsigned long a; 276 KABI_IGNORE(0, unsigned long b); 277 }; 278 279 /* 280 * This may be safe if the structure allocation is managed by the core kernel 281 * and the layout remains unchanged except for appended new members. 282 */ 283 KABI_BYTE_SIZE(ex4a, 8); 284 285 /* 286 * STABLE: variable structure_type ex4a { 287 * STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) a data_member_location(0) 288 * STABLE-NEXT: } byte_size(8) 289 */ 290 291 /* 292 * Example: A type string override. 293 */ 294 295 struct ex5a { 296 unsigned long a; 297 }; 298 299 /* 300 * This may be safe if the structure is fully opaque to modules, even though 301 * its definition has inadvertently become part of the ABI. 302 */ 303 KABI_TYPE_STRING( 304 "s#ex5a", 305 "structure_type ex5a { member pointer_type { s#ex4a } byte_size(8) p data_member_location(0) } byte_size(8)"); 306 307 /* 308 * Make sure the fully expanded type string includes ex4a. 309 * 310 * VERSIONS: ex5a variable structure_type ex5a { 311 * VERSIONS-SAME: member pointer_type { 312 * VERSIONS-SAME: structure_type ex4a { 313 * VERSIONS-SAME: member base_type [[ULONG:long unsigned int|unsigned long]] byte_size(8) encoding(7) a data_member_location(0) 314 * VERSIONS-SAME: } byte_size(8) 315 * VERSIONS-SAME: } byte_size(8) p data_member_location(0) 316 * VERSIONS-SAME: } byte_size(8) 317 */ 318 319 /* 320 * Example: A type string definition for a non-existent type. 321 */ 322 323 struct ex5b { 324 unsigned long a; 325 }; 326 327 /* Replace the type string for struct ex5b */ 328 KABI_TYPE_STRING( 329 "s#ex5b", 330 "structure_type ex5b { member pointer_type { s#ex5c } byte_size(8) p data_member_location(0) } byte_size(8)"); 331 332 /* Define a type string for a non-existent struct ex5c */ 333 KABI_TYPE_STRING( 334 "s#ex5c", 335 "structure_type ex5c { member base_type int byte_size(4) encoding(5) n data_member_location(0) } byte_size(8)"); 336 337 /* 338 * Make sure the fully expanded type string includes the definition for ex5c. 339 * 340 * VERSIONS: ex5b variable structure_type ex5b { 341 * VERSIONS-SAME: member pointer_type { 342 * VERSIONS-SAME: structure_type ex5c { 343 * VERSIONS-SAME: member base_type int byte_size(4) encoding(5) n data_member_location(0) 344 * VERSIONS-SAME: } byte_size(8) 345 * VERSIONS-SAME: } byte_size(8) p data_member_location(0) 346 * VERSIONS-SAME: } byte_size(8) 347 */ 348 349 /* 350 * Example: A type string override for a symbol. 351 */ 352 353 KABI_TYPE_STRING("ex6a", "variable s#ex5c"); 354 355 /* 356 * VERSIONS: ex6a variable structure_type ex5c { 357 * VERSIONS-SAME: member base_type int byte_size(4) encoding(5) n data_member_location(0) 358 * VERSIONS-SAME: } byte_size(8) 359 */ 360 #endif /* __KABI_EX_H__ */ 361