xref: /linux/scripts/gendwarfksyms/kabi.c (revision db59d74e5da144111fc133fb1bf72e6392bdb04e)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (C) 2024 Google LLC
4  */
5 
6 #define _GNU_SOURCE
7 #include <errno.h>
8 #include <stdio.h>
9 
10 #include "gendwarfksyms.h"
11 
12 #define KABI_RULE_SECTION ".discard.gendwarfksyms.kabi_rules"
13 #define KABI_RULE_VERSION "1"
14 
15 /*
16  * The rule section consists of four null-terminated strings per
17  * entry:
18  *
19  *   1. version
20  *      Entry format version. Must match KABI_RULE_VERSION.
21  *
22  *   2. type
23  *      Type of the kABI rule. Must be one of the tags defined below.
24  *
25  *   3. target
26  *      Rule-dependent target, typically the fully qualified name of
27  *      the target DIE.
28  *
29  *   4. value
30  *      Rule-dependent value.
31  */
32 #define KABI_RULE_MIN_ENTRY_SIZE                                  \
33 	(/* version\0 */ 2 + /* type\0 */ 2 + /* target\0" */ 1 + \
34 	 /* value\0 */ 1)
35 #define KABI_RULE_EMPTY_VALUE ""
36 
37 /*
38  * Rule: declonly
39  * - For the struct/enum/union in the target field, treat it as a
40  *   declaration only even if a definition is available.
41  */
42 #define KABI_RULE_TAG_DECLONLY "declonly"
43 
44 /*
45  * Rule: enumerator_ignore
46  * - For the enum_field in the target field, ignore the enumerator.
47  */
48 #define KABI_RULE_TAG_ENUMERATOR_IGNORE "enumerator_ignore"
49 
50 /*
51  * Rule: enumerator_value
52  * - For the fqn_field in the target field, set the value to the
53  *   unsigned integer in the value field.
54  */
55 #define KABI_RULE_TAG_ENUMERATOR_VALUE "enumerator_value"
56 
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 
64 enum kabi_rule_type {
65 	KABI_RULE_TYPE_UNKNOWN,
66 	KABI_RULE_TYPE_DECLONLY,
67 	KABI_RULE_TYPE_ENUMERATOR_IGNORE,
68 	KABI_RULE_TYPE_ENUMERATOR_VALUE,
69 	KABI_RULE_TYPE_BYTE_SIZE,
70 };
71 
72 #define RULE_HASH_BITS 7
73 
74 struct rule {
75 	enum kabi_rule_type type;
76 	const char *target;
77 	const char *value;
78 	struct hlist_node hash;
79 };
80 
81 /* { type, target } -> struct rule */
82 static HASHTABLE_DEFINE(rules, 1 << RULE_HASH_BITS);
83 
84 static inline unsigned int rule_values_hash(enum kabi_rule_type type,
85 					    const char *target)
86 {
87 	return hash_32(type) ^ hash_str(target);
88 }
89 
90 static inline unsigned int rule_hash(const struct rule *rule)
91 {
92 	return rule_values_hash(rule->type, rule->target);
93 }
94 
95 static inline const char *get_rule_field(const char **pos, ssize_t *left)
96 {
97 	const char *start = *pos;
98 	size_t len;
99 
100 	if (*left <= 0)
101 		error("unexpected end of kABI rules");
102 
103 	len = strnlen(start, *left) + 1;
104 	*pos += len;
105 	*left -= len;
106 
107 	return start;
108 }
109 
110 void kabi_read_rules(int fd)
111 {
112 	GElf_Shdr shdr_mem;
113 	GElf_Shdr *shdr;
114 	Elf_Data *rule_data = NULL;
115 	Elf_Scn *scn;
116 	Elf *elf;
117 	size_t shstrndx;
118 	const char *rule_str;
119 	ssize_t left;
120 	int i;
121 
122 	const struct {
123 		enum kabi_rule_type type;
124 		const char *tag;
125 	} rule_types[] = {
126 		{
127 			.type = KABI_RULE_TYPE_DECLONLY,
128 			.tag = KABI_RULE_TAG_DECLONLY,
129 		},
130 		{
131 			.type = KABI_RULE_TYPE_ENUMERATOR_IGNORE,
132 			.tag = KABI_RULE_TAG_ENUMERATOR_IGNORE,
133 		},
134 		{
135 			.type = KABI_RULE_TYPE_ENUMERATOR_VALUE,
136 			.tag = KABI_RULE_TAG_ENUMERATOR_VALUE,
137 		},
138 		{
139 			.type = KABI_RULE_TYPE_BYTE_SIZE,
140 			.tag = KABI_RULE_TAG_BYTE_SIZE,
141 		},
142 	};
143 
144 	if (!stable)
145 		return;
146 
147 	if (elf_version(EV_CURRENT) != EV_CURRENT)
148 		error("elf_version failed: %s", elf_errmsg(-1));
149 
150 	elf = elf_begin(fd, ELF_C_READ_MMAP, NULL);
151 	if (!elf)
152 		error("elf_begin failed: %s", elf_errmsg(-1));
153 
154 	if (elf_getshdrstrndx(elf, &shstrndx) < 0)
155 		error("elf_getshdrstrndx failed: %s", elf_errmsg(-1));
156 
157 	scn = elf_nextscn(elf, NULL);
158 
159 	while (scn) {
160 		const char *sname;
161 
162 		shdr = gelf_getshdr(scn, &shdr_mem);
163 		if (!shdr)
164 			error("gelf_getshdr failed: %s", elf_errmsg(-1));
165 
166 		sname = elf_strptr(elf, shstrndx, shdr->sh_name);
167 		if (!sname)
168 			error("elf_strptr failed: %s", elf_errmsg(-1));
169 
170 		if (!strcmp(sname, KABI_RULE_SECTION)) {
171 			rule_data = elf_getdata(scn, NULL);
172 			if (!rule_data)
173 				error("elf_getdata failed: %s", elf_errmsg(-1));
174 			break;
175 		}
176 
177 		scn = elf_nextscn(elf, scn);
178 	}
179 
180 	if (!rule_data) {
181 		debug("kABI rules not found");
182 		check(elf_end(elf));
183 		return;
184 	}
185 
186 	rule_str = rule_data->d_buf;
187 	left = shdr->sh_size;
188 
189 	if (left < KABI_RULE_MIN_ENTRY_SIZE)
190 		error("kABI rule section too small: %zd bytes", left);
191 
192 	if (rule_str[left - 1] != '\0')
193 		error("kABI rules are not null-terminated");
194 
195 	while (left > KABI_RULE_MIN_ENTRY_SIZE) {
196 		enum kabi_rule_type type = KABI_RULE_TYPE_UNKNOWN;
197 		const char *field;
198 		struct rule *rule;
199 
200 		/* version */
201 		field = get_rule_field(&rule_str, &left);
202 
203 		if (strcmp(field, KABI_RULE_VERSION))
204 			error("unsupported kABI rule version: '%s'", field);
205 
206 		/* type */
207 		field = get_rule_field(&rule_str, &left);
208 
209 		for (i = 0; i < ARRAY_SIZE(rule_types); i++) {
210 			if (!strcmp(field, rule_types[i].tag)) {
211 				type = rule_types[i].type;
212 				break;
213 			}
214 		}
215 
216 		if (type == KABI_RULE_TYPE_UNKNOWN)
217 			error("unsupported kABI rule type: '%s'", field);
218 
219 		rule = xmalloc(sizeof(struct rule));
220 
221 		rule->type = type;
222 		rule->target = xstrdup(get_rule_field(&rule_str, &left));
223 		rule->value = xstrdup(get_rule_field(&rule_str, &left));
224 
225 		hash_add(rules, &rule->hash, rule_hash(rule));
226 
227 		debug("kABI rule: type: '%s', target: '%s', value: '%s'", field,
228 		      rule->target, rule->value);
229 	}
230 
231 	if (left > 0)
232 		warn("unexpected data at the end of the kABI rules section");
233 
234 	check(elf_end(elf));
235 }
236 
237 static char *get_enumerator_target(const char *fqn, const char *field)
238 {
239 	char *target = NULL;
240 
241 	if (asprintf(&target, "%s %s", fqn, field) < 0)
242 		error("asprintf failed for '%s %s'", fqn, field);
243 
244 	return target;
245 }
246 
247 static struct rule *find_rule(enum kabi_rule_type type, const char *target)
248 {
249 	struct rule *rule;
250 
251 	if (!stable)
252 		return NULL;
253 	if (!target || !*target)
254 		return NULL;
255 
256 	hash_for_each_possible(rules, rule, hash,
257 			       rule_values_hash(type, target)) {
258 		if (rule->type == type && !strcmp(target, rule->target))
259 			return rule;
260 	}
261 
262 	return NULL;
263 }
264 
265 static struct rule *find_enumerator_rule(enum kabi_rule_type type,
266 					 const char *fqn, const char *field)
267 {
268 	struct rule *rule;
269 	char *target;
270 
271 	if (!stable)
272 		return NULL;
273 	if (!fqn || !*fqn || !field || !*field)
274 		return NULL;
275 
276 	target = get_enumerator_target(fqn, field);
277 	rule = find_rule(type, target);
278 
279 	free(target);
280 	return rule;
281 }
282 
283 bool kabi_is_declonly(const char *fqn)
284 {
285 	return !!find_rule(KABI_RULE_TYPE_DECLONLY, fqn);
286 }
287 
288 static unsigned long get_ulong_value(const char *value)
289 {
290 	unsigned long result = 0;
291 	char *endptr = NULL;
292 
293 	errno = 0;
294 	result = strtoul(value, &endptr, 10);
295 
296 	if (errno || *endptr)
297 		error("invalid unsigned value '%s'", value);
298 
299 	return result;
300 }
301 
302 bool kabi_is_enumerator_ignored(const char *fqn, const char *field)
303 {
304 	return !!find_enumerator_rule(KABI_RULE_TYPE_ENUMERATOR_IGNORE, fqn,
305 				      field);
306 }
307 
308 bool kabi_get_enumerator_value(const char *fqn, const char *field,
309 			       unsigned long *value)
310 {
311 	struct rule *rule;
312 
313 	rule = find_enumerator_rule(KABI_RULE_TYPE_ENUMERATOR_VALUE, fqn,
314 				    field);
315 	if (rule) {
316 		*value = get_ulong_value(rule->value);
317 		return true;
318 	}
319 
320 	return false;
321 }
322 
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 
336 void kabi_free(void)
337 {
338 	struct hlist_node *tmp;
339 	struct rule *rule;
340 
341 	hash_for_each_safe(rules, rule, tmp, hash) {
342 		free((void *)rule->target);
343 		free((void *)rule->value);
344 		free(rule);
345 	}
346 
347 	hash_init(rules);
348 }
349