Skip to content

Commit c908346

Browse files
samitolvanenmasahir0y
authored andcommitted
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 <[email protected]> Signed-off-by: Sami Tolvanen <[email protected]> Reviewed-by: Petr Pavlu <[email protected]> Signed-off-by: Masahiro Yamada <[email protected]>
1 parent db59d74 commit c908346

File tree

6 files changed

+246
-18
lines changed

6 files changed

+246
-18
lines changed

scripts/gendwarfksyms/examples/kabi.h

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,14 @@
3737
#define __stringify(x...) __stringify_1(x)
3838
#endif
3939

40-
#define __KABI_RULE(hint, target, value) \
40+
#define ___KABI_RULE(hint, target, value) \
4141
static const char __PASTE(__gendwarfksyms_rule_, \
4242
__COUNTER__)[] __used __aligned(1) \
4343
__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)
4548

4649
#define __KABI_NORMAL_SIZE_ALIGN(_orig, _new) \
4750
union { \
@@ -96,6 +99,13 @@
9699
*/
97100
#define KABI_BYTE_SIZE(fqn, value) __KABI_RULE(byte_size, fqn, value)
98101

102+
/*
103+
* KABI_TYPE_STRING(type, str)
104+
* For the given type, override the type string used in symtypes
105+
* output and version calculation with str.
106+
*/
107+
#define KABI_TYPE_STRING(type, str) ___KABI_RULE(type_string, type, str)
108+
99109
/*
100110
* KABI_RESERVE
101111
* Reserve some "padding" in a structure for use by LTS backports.

scripts/gendwarfksyms/examples/kabi_ex.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,8 @@ struct ex3b ex3b;
3030
struct ex3c ex3c;
3131

3232
struct ex4a ex4a;
33+
34+
struct ex5a ex5a;
35+
struct ex5b ex5b;
36+
37+
int ex6a;

scripts/gendwarfksyms/examples/kabi_ex.h

Lines changed: 77 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,12 @@
2121
* ./gendwarfksyms --stable --dump-dies \
2222
* examples/kabi_ex.o 2>&1 >/dev/null | \
2323
* 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
2430
*/
2531

2632
#ifndef __KABI_EX_H__
@@ -170,7 +176,7 @@ struct ex2a {
170176
/*
171177
* STABLE: variable structure_type ex2a {
172178
* 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)
179+
* STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) b data_member_location(8)
174180
* STABLE-NEXT: member base_type int byte_size(4) encoding(5) c data_member_location(16) ,
175181
* STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) d data_member_location(24)
176182
* STABLE-NEXT: } byte_size(32)
@@ -227,7 +233,7 @@ struct ex3a {
227233

228234
/*
229235
* 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)
236+
* STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) a data_member_location(0)
231237
* STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) unused data_member_location(8)
232238
* STABLE-NEXT: } byte_size(16)
233239
*/
@@ -282,4 +288,73 @@ KABI_BYTE_SIZE(ex4a, 8);
282288
* STABLE-NEXT: } byte_size(8)
283289
*/
284290

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+
*/
285360
#endif /* __KABI_EX_H__ */

scripts/gendwarfksyms/gendwarfksyms.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,7 @@ bool kabi_is_enumerator_ignored(const char *fqn, const char *field);
292292
bool kabi_get_enumerator_value(const char *fqn, const char *field,
293293
unsigned long *value);
294294
bool kabi_is_declonly(const char *fqn);
295+
bool kabi_get_type_string(const char *type, const char **str);
295296

296297
void kabi_read_rules(int fd);
297298
void kabi_free(void);

scripts/gendwarfksyms/kabi.c

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,12 +61,20 @@
6161
*/
6262
#define KABI_RULE_TAG_BYTE_SIZE "byte_size"
6363

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+
6471
enum kabi_rule_type {
6572
KABI_RULE_TYPE_UNKNOWN,
6673
KABI_RULE_TYPE_DECLONLY,
6774
KABI_RULE_TYPE_ENUMERATOR_IGNORE,
6875
KABI_RULE_TYPE_ENUMERATOR_VALUE,
6976
KABI_RULE_TYPE_BYTE_SIZE,
77+
KABI_RULE_TYPE_TYPE_STRING,
7078
};
7179

7280
#define RULE_HASH_BITS 7
@@ -139,6 +147,10 @@ void kabi_read_rules(int fd)
139147
.type = KABI_RULE_TYPE_BYTE_SIZE,
140148
.tag = KABI_RULE_TAG_BYTE_SIZE,
141149
},
150+
{
151+
.type = KABI_RULE_TYPE_TYPE_STRING,
152+
.tag = KABI_RULE_TAG_TYPE_STRING,
153+
},
142154
};
143155

144156
if (!stable)
@@ -333,6 +345,19 @@ bool kabi_get_byte_size(const char *fqn, unsigned long *value)
333345
return false;
334346
}
335347

348+
bool kabi_get_type_string(const char *type, const char **str)
349+
{
350+
struct rule *rule;
351+
352+
rule = find_rule(KABI_RULE_TYPE_TYPE_STRING, type);
353+
if (rule) {
354+
*str = rule->value;
355+
return true;
356+
}
357+
358+
return false;
359+
}
360+
336361
void kabi_free(void)
337362
{
338363
struct hlist_node *tmp;

0 commit comments

Comments
 (0)