Skip to content

Commit db59d74

Browse files
samitolvanenmasahir0y
authored andcommitted
gendwarfksyms: Add a kABI rule to override byte_size attributes
A data structure can be partially opaque to modules if its allocation is handled by the core kernel, and modules only need to access some of its members. In this situation, it's possible to append new members to the structure without breaking the ABI, as long as the layout for the original members remains unchanged. For example, consider the following struct: struct s { unsigned long a; void *p; }; gendwarfksyms --stable --dump-dies produces the following type expansion: variable structure_type s { member base_type long unsigned int byte_size(8) encoding(7) a data_member_location(0) , member pointer_type { base_type void } byte_size(8) p data_member_location(8) } byte_size(16) To append new members, we can use the KABI_IGNORE() macro to hide them from gendwarfksyms --stable: struct s { /* old members with unchanged layout */ unsigned long a; void *p; /* new members not accessed by modules */ KABI_IGNORE(0, unsigned long n); }; However, we can't hide the fact that adding new members changes the struct size, as seen in the updated type string: variable structure_type s { member base_type long unsigned int byte_size(8) encoding(7) a data_member_location(0) , member pointer_type { base_type void } byte_size(8) p data_member_location(8) } byte_size(24) In order to support this use case, add a kABI rule that makes it possible to override the byte_size attribute for types: /* * struct s allocation is handled by the kernel, so * appending new members without changing the original * layout won't break the ABI. */ KABI_BYTE_SIZE(s, 16); This results in a type string that's unchanged from the original and therefore, won't change versions for symbols that reference the changed structure. Signed-off-by: Sami Tolvanen <[email protected]> Reviewed-by: Petr Pavlu <[email protected]> Signed-off-by: Masahiro Yamada <[email protected]>
1 parent ff2c5f5 commit db59d74

File tree

6 files changed

+70
-1
lines changed

6 files changed

+70
-1
lines changed

scripts/gendwarfksyms/dwarf.c

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -228,12 +228,24 @@ static void process_fqn(struct die *cache, Dwarf_Die *die)
228228
DEFINE_PROCESS_UDATA_ATTRIBUTE(accessibility)
229229
DEFINE_PROCESS_UDATA_ATTRIBUTE(alignment)
230230
DEFINE_PROCESS_UDATA_ATTRIBUTE(bit_size)
231-
DEFINE_PROCESS_UDATA_ATTRIBUTE(byte_size)
232231
DEFINE_PROCESS_UDATA_ATTRIBUTE(encoding)
233232
DEFINE_PROCESS_UDATA_ATTRIBUTE(data_bit_offset)
234233
DEFINE_PROCESS_UDATA_ATTRIBUTE(data_member_location)
235234
DEFINE_PROCESS_UDATA_ATTRIBUTE(discr_value)
236235

236+
static void process_byte_size_attr(struct die *cache, Dwarf_Die *die)
237+
{
238+
Dwarf_Word value;
239+
unsigned long override;
240+
241+
if (get_udata_attr(die, DW_AT_byte_size, &value)) {
242+
if (stable && kabi_get_byte_size(cache->fqn, &override))
243+
value = override;
244+
245+
process_fmt(cache, " byte_size(%" PRIu64 ")", value);
246+
}
247+
}
248+
237249
/* Match functions -- die_match_callback_t */
238250
#define DEFINE_MATCH(type) \
239251
static bool match_##type##_type(Dwarf_Die *die) \

scripts/gendwarfksyms/examples/kabi.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,13 @@
8989
#define KABI_ENUMERATOR_VALUE(fqn, field, value) \
9090
__KABI_RULE(enumerator_value, fqn field, value)
9191

92+
/*
93+
* KABI_BYTE_SIZE(fqn, value)
94+
* Set the byte_size attribute for the struct/union/enum fqn to
95+
* value bytes.
96+
*/
97+
#define KABI_BYTE_SIZE(fqn, value) __KABI_RULE(byte_size, fqn, value)
98+
9299
/*
93100
* KABI_RESERVE
94101
* Reserve some "padding" in a structure for use by LTS backports.

scripts/gendwarfksyms/examples/kabi_ex.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,5 @@ struct ex2c ex2c;
2828
struct ex3a ex3a;
2929
struct ex3b ex3b;
3030
struct ex3c ex3c;
31+
32+
struct ex4a ex4a;

scripts/gendwarfksyms/examples/kabi_ex.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,4 +260,26 @@ _Static_assert(sizeof(struct ex3a) == sizeof(struct ex3c), "ex3a size doesn't ma
260260
* STABLE-NEXT: } byte_size(16)
261261
*/
262262

263+
/*
264+
* Example: An ignored field added to an end of a partially opaque struct,
265+
* while keeping the byte_size attribute unchanged.
266+
*/
267+
268+
struct ex4a {
269+
unsigned long a;
270+
KABI_IGNORE(0, unsigned long b);
271+
};
272+
273+
/*
274+
* This may be safe if the structure allocation is managed by the core kernel
275+
* and the layout remains unchanged except for appended new members.
276+
*/
277+
KABI_BYTE_SIZE(ex4a, 8);
278+
279+
/*
280+
* STABLE: variable structure_type ex4a {
281+
* STABLE-NEXT: member base_type [[ULONG]] byte_size(8) encoding(7) a data_member_location(0)
282+
* STABLE-NEXT: } byte_size(8)
283+
*/
284+
263285
#endif /* __KABI_EX_H__ */

scripts/gendwarfksyms/gendwarfksyms.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,7 @@ void generate_symtypes_and_versions(FILE *file);
287287
* kabi.c
288288
*/
289289

290+
bool kabi_get_byte_size(const char *fqn, unsigned long *value);
290291
bool kabi_is_enumerator_ignored(const char *fqn, const char *field);
291292
bool kabi_get_enumerator_value(const char *fqn, const char *field,
292293
unsigned long *value);

scripts/gendwarfksyms/kabi.c

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,19 @@
5454
*/
5555
#define KABI_RULE_TAG_ENUMERATOR_VALUE "enumerator_value"
5656

57+
/*
58+
* Rule: byte_size
59+
* - For the fqn_field in the target field, set the byte_size
60+
* attribute to the value in the value field.
61+
*/
62+
#define KABI_RULE_TAG_BYTE_SIZE "byte_size"
63+
5764
enum kabi_rule_type {
5865
KABI_RULE_TYPE_UNKNOWN,
5966
KABI_RULE_TYPE_DECLONLY,
6067
KABI_RULE_TYPE_ENUMERATOR_IGNORE,
6168
KABI_RULE_TYPE_ENUMERATOR_VALUE,
69+
KABI_RULE_TYPE_BYTE_SIZE,
6270
};
6371

6472
#define RULE_HASH_BITS 7
@@ -127,6 +135,10 @@ void kabi_read_rules(int fd)
127135
.type = KABI_RULE_TYPE_ENUMERATOR_VALUE,
128136
.tag = KABI_RULE_TAG_ENUMERATOR_VALUE,
129137
},
138+
{
139+
.type = KABI_RULE_TYPE_BYTE_SIZE,
140+
.tag = KABI_RULE_TAG_BYTE_SIZE,
141+
},
130142
};
131143

132144
if (!stable)
@@ -308,6 +320,19 @@ bool kabi_get_enumerator_value(const char *fqn, const char *field,
308320
return false;
309321
}
310322

323+
bool kabi_get_byte_size(const char *fqn, unsigned long *value)
324+
{
325+
struct rule *rule;
326+
327+
rule = find_rule(KABI_RULE_TYPE_BYTE_SIZE, fqn);
328+
if (rule) {
329+
*value = get_ulong_value(rule->value);
330+
return true;
331+
}
332+
333+
return false;
334+
}
335+
311336
void kabi_free(void)
312337
{
313338
struct hlist_node *tmp;

0 commit comments

Comments
 (0)