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.

gendwarfksyms: Add a kABI rule to override type strings

In rare situations where distributions must make significant
changes to otherwise opaque data structures that have
inadvertently been included in the published ABI, keeping
symbol versions stable using the existing kABI macros can
become tedious.

For example, Android decided to switch to a newer io_uring
implementation in the 5.10 GKI kernel "to resolve a huge number
of potential, and known, problems with the codebase," requiring
"horrible hacks" with genksyms:

"A number of the io_uring structures get used in other core
kernel structures, only as "opaque" pointers, so there is
not any real ABI breakage. But, due to the visibility of
the structures going away, the CRC values of many scheduler
variables and functions were changed."
-- https://r.android.com/2425293

While these specific changes probably could have been hidden
from gendwarfksyms using the existing kABI macros, this may not
always be the case.

Add a last resort kABI rule that allows distribution
maintainers to fully override a type string for a symbol or a
type. Also add a more informative error message in case we find
a non-existent type references when calculating versions.

Suggested-by: Giuliano Procida <gprocida@google.com>
Signed-off-by: Sami Tolvanen <samitolvanen@google.com>
Reviewed-by: Petr Pavlu <petr.pavlu@suse.com>
Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>

authored by

Sami Tolvanen and committed by
Masahiro Yamada
c9083467 db59d74e

+246 -18
+12 -2
scripts/gendwarfksyms/examples/kabi.h
··· 37 37 #define __stringify(x...) __stringify_1(x) 38 38 #endif 39 39 40 - #define __KABI_RULE(hint, target, value) \ 40 + #define ___KABI_RULE(hint, target, value) \ 41 41 static const char __PASTE(__gendwarfksyms_rule_, \ 42 42 __COUNTER__)[] __used __aligned(1) \ 43 43 __section(".discard.gendwarfksyms.kabi_rules") = \ 44 - "1\0" #hint "\0" #target "\0" #value 44 + "1\0" #hint "\0" target "\0" value 45 + 46 + #define __KABI_RULE(hint, target, value) \ 47 + ___KABI_RULE(hint, #target, #value) 45 48 46 49 #define __KABI_NORMAL_SIZE_ALIGN(_orig, _new) \ 47 50 union { \ ··· 98 95 * value bytes. 99 96 */ 100 97 #define KABI_BYTE_SIZE(fqn, value) __KABI_RULE(byte_size, fqn, value) 98 + 99 + /* 100 + * KABI_TYPE_STRING(type, str) 101 + * For the given type, override the type string used in symtypes 102 + * output and version calculation with str. 103 + */ 104 + #define KABI_TYPE_STRING(type, str) ___KABI_RULE(type_string, type, str) 101 105 102 106 /* 103 107 * KABI_RESERVE
+5
scripts/gendwarfksyms/examples/kabi_ex.c
··· 30 30 struct ex3c ex3c; 31 31 32 32 struct ex4a ex4a; 33 + 34 + struct ex5a ex5a; 35 + struct ex5b ex5b; 36 + 37 + int ex6a;
+77 -2
scripts/gendwarfksyms/examples/kabi_ex.h
··· 21 21 * ./gendwarfksyms --stable --dump-dies \ 22 22 * examples/kabi_ex.o 2>&1 >/dev/null | \ 23 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 24 30 */ 25 31 26 32 #ifndef __KABI_EX_H__ ··· 176 170 /* 177 171 * STABLE: variable structure_type ex2a { 178 172 * STABLE-NEXT: member base_type int byte_size(4) encoding(5) a data_member_location(0) , 179 - * STABLE-NEXT: member base_type [[ULONG:long unsigned int|unsigned long]] byte_size(8) encoding(7) b data_member_location(8) 173 + * STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) b data_member_location(8) 180 174 * STABLE-NEXT: member base_type int byte_size(4) encoding(5) c data_member_location(16) , 181 175 * STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) d data_member_location(24) 182 176 * STABLE-NEXT: } byte_size(32) ··· 233 227 234 228 /* 235 229 * STABLE: variable structure_type ex3a { 236 - * STABLE-NEXT: member base_type [[ULONG:long unsigned int|unsigned long]] byte_size(8) encoding(7) a data_member_location(0) 230 + * STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) a data_member_location(0) 237 231 * STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) unused data_member_location(8) 238 232 * STABLE-NEXT: } byte_size(16) 239 233 */ ··· 288 282 * STABLE-NEXT: } byte_size(8) 289 283 */ 290 284 285 + /* 286 + * Example: A type string override. 287 + */ 288 + 289 + struct ex5a { 290 + unsigned long a; 291 + }; 292 + 293 + /* 294 + * This may be safe if the structure is fully opaque to modules, even though 295 + * its definition has inadvertently become part of the ABI. 296 + */ 297 + KABI_TYPE_STRING( 298 + "s#ex5a", 299 + "structure_type ex5a { member pointer_type { s#ex4a } byte_size(8) p data_member_location(0) } byte_size(8)"); 300 + 301 + /* 302 + * Make sure the fully expanded type string includes ex4a. 303 + * 304 + * VERSIONS: ex5a variable structure_type ex5a { 305 + * VERSIONS-SAME: member pointer_type { 306 + * VERSIONS-SAME: structure_type ex4a { 307 + * VERSIONS-SAME: member base_type [[ULONG:long unsigned int|unsigned long]] byte_size(8) encoding(7) a data_member_location(0) 308 + * VERSIONS-SAME: } byte_size(8) 309 + * VERSIONS-SAME: } byte_size(8) p data_member_location(0) 310 + * VERSIONS-SAME: } byte_size(8) 311 + */ 312 + 313 + /* 314 + * Example: A type string definition for a non-existent type. 315 + */ 316 + 317 + struct ex5b { 318 + unsigned long a; 319 + }; 320 + 321 + /* Replace the type string for struct ex5b */ 322 + KABI_TYPE_STRING( 323 + "s#ex5b", 324 + "structure_type ex5b { member pointer_type { s#ex5c } byte_size(8) p data_member_location(0) } byte_size(8)"); 325 + 326 + /* Define a type string for a non-existent struct ex5c */ 327 + KABI_TYPE_STRING( 328 + "s#ex5c", 329 + "structure_type ex5c { member base_type int byte_size(4) encoding(5) n data_member_location(0) } byte_size(8)"); 330 + 331 + /* 332 + * Make sure the fully expanded type string includes the definition for ex5c. 333 + * 334 + * VERSIONS: ex5b variable structure_type ex5b { 335 + * VERSIONS-SAME: member pointer_type { 336 + * VERSIONS-SAME: structure_type ex5c { 337 + * VERSIONS-SAME: member base_type int byte_size(4) encoding(5) n data_member_location(0) 338 + * VERSIONS-SAME: } byte_size(8) 339 + * VERSIONS-SAME: } byte_size(8) p data_member_location(0) 340 + * VERSIONS-SAME: } byte_size(8) 341 + */ 342 + 343 + /* 344 + * Example: A type string override for a symbol. 345 + */ 346 + 347 + KABI_TYPE_STRING("ex6a", "variable s#ex5c"); 348 + 349 + /* 350 + * VERSIONS: ex6a variable structure_type ex5c { 351 + * VERSIONS-SAME: member base_type int byte_size(4) encoding(5) n data_member_location(0) 352 + * VERSIONS-SAME: } byte_size(8) 353 + */ 291 354 #endif /* __KABI_EX_H__ */
+1
scripts/gendwarfksyms/gendwarfksyms.h
··· 292 292 bool kabi_get_enumerator_value(const char *fqn, const char *field, 293 293 unsigned long *value); 294 294 bool kabi_is_declonly(const char *fqn); 295 + bool kabi_get_type_string(const char *type, const char **str); 295 296 296 297 void kabi_read_rules(int fd); 297 298 void kabi_free(void);
+25
scripts/gendwarfksyms/kabi.c
··· 61 61 */ 62 62 #define KABI_RULE_TAG_BYTE_SIZE "byte_size" 63 63 64 + /* 65 + * Rule: type_string 66 + * - For the type reference in the fqn field, use the type string 67 + * in the value field. 68 + */ 69 + #define KABI_RULE_TAG_TYPE_STRING "type_string" 70 + 64 71 enum kabi_rule_type { 65 72 KABI_RULE_TYPE_UNKNOWN, 66 73 KABI_RULE_TYPE_DECLONLY, 67 74 KABI_RULE_TYPE_ENUMERATOR_IGNORE, 68 75 KABI_RULE_TYPE_ENUMERATOR_VALUE, 69 76 KABI_RULE_TYPE_BYTE_SIZE, 77 + KABI_RULE_TYPE_TYPE_STRING, 70 78 }; 71 79 72 80 #define RULE_HASH_BITS 7 ··· 146 138 { 147 139 .type = KABI_RULE_TYPE_BYTE_SIZE, 148 140 .tag = KABI_RULE_TAG_BYTE_SIZE, 141 + }, 142 + { 143 + .type = KABI_RULE_TYPE_TYPE_STRING, 144 + .tag = KABI_RULE_TAG_TYPE_STRING, 149 145 }, 150 146 }; 151 147 ··· 339 327 rule = find_rule(KABI_RULE_TYPE_BYTE_SIZE, fqn); 340 328 if (rule) { 341 329 *value = get_ulong_value(rule->value); 330 + return true; 331 + } 332 + 333 + return false; 334 + } 335 + 336 + bool kabi_get_type_string(const char *type, const char **str) 337 + { 338 + struct rule *rule; 339 + 340 + rule = find_rule(KABI_RULE_TYPE_TYPE_STRING, type); 341 + if (rule) { 342 + *str = rule->value; 342 343 return true; 343 344 } 344 345
+126 -14
scripts/gendwarfksyms/types.c
··· 100 100 #define TYPE_HASH_BITS 12 101 101 static HASHTABLE_DEFINE(type_map, 1 << TYPE_HASH_BITS); 102 102 103 - static int type_map_get(const char *name, struct type_expansion **res) 103 + static int __type_map_get(const char *name, struct type_expansion **res) 104 104 { 105 105 struct type_expansion *e; 106 106 ··· 114 114 return -1; 115 115 } 116 116 117 - static void type_map_add(const char *name, struct type_expansion *type) 117 + static struct type_expansion *type_map_add(const char *name, 118 + struct type_expansion *type) 118 119 { 119 120 struct type_expansion *e; 120 121 121 - if (type_map_get(name, &e)) { 122 + if (__type_map_get(name, &e)) { 122 123 e = xmalloc(sizeof(struct type_expansion)); 123 124 type_expansion_init(e); 124 125 e->name = xstrdup(name); ··· 131 130 } else { 132 131 /* Use the longest available expansion */ 133 132 if (type->len <= e->len) 134 - return; 133 + return e; 135 134 136 135 type_list_free(&e->expanded); 137 136 ··· 149 148 type_list_write(&e->expanded, stderr); 150 149 checkp(fputs("\n", stderr)); 151 150 } 151 + 152 + return e; 153 + } 154 + 155 + static void type_parse(const char *name, const char *str, 156 + struct type_expansion *type); 157 + 158 + static int type_map_get(const char *name, struct type_expansion **res) 159 + { 160 + struct type_expansion type; 161 + const char *override; 162 + 163 + if (!__type_map_get(name, res)) 164 + return 0; 165 + 166 + /* 167 + * If die_map didn't contain a type, we might still have 168 + * a type_string kABI rule that defines it. 169 + */ 170 + if (stable && kabi_get_type_string(name, &override)) { 171 + type_expansion_init(&type); 172 + type_parse(name, override, &type); 173 + *res = type_map_add(name, &type); 174 + type_expansion_free(&type); 175 + return 0; 176 + } 177 + 178 + return -1; 152 179 } 153 180 154 181 static void type_map_write(FILE *file) ··· 296 267 return name; 297 268 } 298 269 299 - static void __calculate_version(struct version *version, struct list_head *list) 270 + static void __calculate_version(struct version *version, 271 + struct type_expansion *type) 300 272 { 301 273 struct type_list_entry *entry; 302 274 struct type_expansion *e; 303 275 304 276 /* Calculate a CRC over an expanded type string */ 305 - list_for_each_entry(entry, list, list) { 277 + list_for_each_entry(entry, &type->expanded, list) { 306 278 if (is_type_prefix(entry->str)) { 307 - check(type_map_get(entry->str, &e)); 279 + if (type_map_get(entry->str, &e)) 280 + error("unknown type reference to '%s' when expanding '%s'", 281 + entry->str, type->name); 308 282 309 283 /* 310 284 * It's sufficient to expand each type reference just ··· 317 285 version_add(version, entry->str); 318 286 } else { 319 287 cache_mark_expanded(&expansion_cache, e); 320 - __calculate_version(version, &e->expanded); 288 + __calculate_version(version, e); 321 289 } 322 290 } else { 323 291 version_add(version, entry->str); ··· 325 293 } 326 294 } 327 295 328 - static void calculate_version(struct version *version, struct list_head *list) 296 + static void calculate_version(struct version *version, 297 + struct type_expansion *type) 329 298 { 330 299 version_init(version); 331 - __calculate_version(version, list); 300 + __calculate_version(version, type); 332 301 cache_free(&expansion_cache); 333 302 } 334 303 ··· 405 372 cache_free(&expansion_cache); 406 373 } 407 374 375 + static void type_parse(const char *name, const char *str, 376 + struct type_expansion *type) 377 + { 378 + char *fragment; 379 + size_t start = 0; 380 + size_t end; 381 + size_t pos; 382 + 383 + if (!*str) 384 + error("empty type string override for '%s'", name); 385 + 386 + type_expansion_init(type); 387 + 388 + for (pos = 0; str[pos]; ++pos) { 389 + bool empty; 390 + char marker = ' '; 391 + 392 + if (!is_type_prefix(&str[pos])) 393 + continue; 394 + 395 + end = pos + 2; 396 + 397 + /* 398 + * Find the end of the type reference. If the type name contains 399 + * spaces, it must be in single quotes. 400 + */ 401 + if (str[end] == '\'') { 402 + marker = '\''; 403 + ++end; 404 + } 405 + while (str[end] && str[end] != marker) 406 + ++end; 407 + 408 + /* Check that we have a non-empty type name */ 409 + if (marker == '\'') { 410 + if (str[end] != marker) 411 + error("incomplete %c# type reference for '%s' (string : '%s')", 412 + str[pos], name, str); 413 + empty = end == pos + 3; 414 + ++end; 415 + } else { 416 + empty = end == pos + 2; 417 + } 418 + if (empty) 419 + error("empty %c# type name for '%s' (string: '%s')", 420 + str[pos], name, str); 421 + 422 + /* Append the part of the string before the type reference */ 423 + if (pos > start) { 424 + fragment = xstrndup(&str[start], pos - start); 425 + type_expansion_append(type, fragment, fragment); 426 + } 427 + 428 + /* 429 + * Append the type reference -- note that if the reference 430 + * is invalid, i.e. points to a non-existent type, we will 431 + * print out an error when calculating versions. 432 + */ 433 + fragment = xstrndup(&str[pos], end - pos); 434 + type_expansion_append(type, fragment, fragment); 435 + 436 + start = end; 437 + pos = end - 1; 438 + } 439 + 440 + /* Append the rest of the type string, if there's any left */ 441 + if (str[start]) 442 + type_expansion_append(type, &str[start], NULL); 443 + } 444 + 408 445 static void expand_type(struct die *cache, void *arg) 409 446 { 410 447 struct type_expansion type; 448 + const char *override; 411 449 char *name; 412 450 413 451 if (cache->mapped) ··· 503 399 return; 504 400 505 401 debug("%s", name); 506 - type_expand(cache, &type, true); 507 - type_map_add(name, &type); 508 402 403 + if (stable && kabi_get_type_string(name, &override)) 404 + type_parse(name, override, &type); 405 + else 406 + type_expand(cache, &type, true); 407 + 408 + type_map_add(name, &type); 509 409 type_expansion_free(&type); 510 410 free(name); 511 411 } ··· 518 410 { 519 411 struct type_expansion type; 520 412 struct version version; 413 + const char *override; 521 414 struct die *cache; 522 415 523 416 /* ··· 532 423 if (__die_map_get(sym->die_addr, DIE_SYMBOL, &cache)) 533 424 return; /* We'll warn about missing CRCs later. */ 534 425 535 - type_expand(cache, &type, false); 426 + if (stable && kabi_get_type_string(sym->name, &override)) 427 + type_parse(sym->name, override, &type); 428 + else 429 + type_expand(cache, &type, false); 536 430 537 431 /* If the symbol already has a version, don't calculate it again. */ 538 432 if (sym->state != SYMBOL_PROCESSED) { 539 - calculate_version(&version, &type.expanded); 433 + calculate_version(&version, &type); 540 434 symbol_set_crc(sym, version.crc); 541 435 debug("%s = %lx", sym->name, version.crc); 542 436