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