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 /* 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 71 enum kabi_rule_type { 72 KABI_RULE_TYPE_UNKNOWN, 73 KABI_RULE_TYPE_DECLONLY, 74 KABI_RULE_TYPE_ENUMERATOR_IGNORE, 75 KABI_RULE_TYPE_ENUMERATOR_VALUE, 76 KABI_RULE_TYPE_BYTE_SIZE, 77 KABI_RULE_TYPE_TYPE_STRING, 78 }; 79 80 #define RULE_HASH_BITS 7 81 82 struct rule { 83 enum kabi_rule_type type; 84 const char *target; 85 const char *value; 86 struct hlist_node hash; 87 }; 88 89 /* { type, target } -> struct rule */ 90 static HASHTABLE_DEFINE(rules, 1 << RULE_HASH_BITS); 91 92 static inline unsigned int rule_values_hash(enum kabi_rule_type type, 93 const char *target) 94 { 95 return hash_32(type) ^ hash_str(target); 96 } 97 98 static inline unsigned int rule_hash(const struct rule *rule) 99 { 100 return rule_values_hash(rule->type, rule->target); 101 } 102 103 static inline const char *get_rule_field(const char **pos, ssize_t *left) 104 { 105 const char *start = *pos; 106 size_t len; 107 108 if (*left <= 0) 109 error("unexpected end of kABI rules"); 110 111 len = strnlen(start, *left) + 1; 112 *pos += len; 113 *left -= len; 114 115 return start; 116 } 117 118 void kabi_read_rules(int fd) 119 { 120 GElf_Shdr shdr_mem; 121 GElf_Shdr *shdr; 122 Elf_Data *rule_data = NULL; 123 Elf_Scn *scn; 124 Elf *elf; 125 size_t shstrndx; 126 const char *rule_str; 127 ssize_t left; 128 int i; 129 130 const struct { 131 enum kabi_rule_type type; 132 const char *tag; 133 } rule_types[] = { 134 { 135 .type = KABI_RULE_TYPE_DECLONLY, 136 .tag = KABI_RULE_TAG_DECLONLY, 137 }, 138 { 139 .type = KABI_RULE_TYPE_ENUMERATOR_IGNORE, 140 .tag = KABI_RULE_TAG_ENUMERATOR_IGNORE, 141 }, 142 { 143 .type = KABI_RULE_TYPE_ENUMERATOR_VALUE, 144 .tag = KABI_RULE_TAG_ENUMERATOR_VALUE, 145 }, 146 { 147 .type = KABI_RULE_TYPE_BYTE_SIZE, 148 .tag = KABI_RULE_TAG_BYTE_SIZE, 149 }, 150 { 151 .type = KABI_RULE_TYPE_TYPE_STRING, 152 .tag = KABI_RULE_TAG_TYPE_STRING, 153 }, 154 }; 155 156 if (!stable) 157 return; 158 159 if (elf_version(EV_CURRENT) != EV_CURRENT) 160 error("elf_version failed: %s", elf_errmsg(-1)); 161 162 elf = elf_begin(fd, ELF_C_READ_MMAP, NULL); 163 if (!elf) 164 error("elf_begin failed: %s", elf_errmsg(-1)); 165 166 if (elf_getshdrstrndx(elf, &shstrndx) < 0) 167 error("elf_getshdrstrndx failed: %s", elf_errmsg(-1)); 168 169 scn = elf_nextscn(elf, NULL); 170 171 while (scn) { 172 const char *sname; 173 174 shdr = gelf_getshdr(scn, &shdr_mem); 175 if (!shdr) 176 error("gelf_getshdr failed: %s", elf_errmsg(-1)); 177 178 sname = elf_strptr(elf, shstrndx, shdr->sh_name); 179 if (!sname) 180 error("elf_strptr failed: %s", elf_errmsg(-1)); 181 182 if (!strcmp(sname, KABI_RULE_SECTION)) { 183 rule_data = elf_getdata(scn, NULL); 184 if (!rule_data) 185 error("elf_getdata failed: %s", elf_errmsg(-1)); 186 break; 187 } 188 189 scn = elf_nextscn(elf, scn); 190 } 191 192 if (!rule_data) { 193 debug("kABI rules not found"); 194 check(elf_end(elf)); 195 return; 196 } 197 198 rule_str = rule_data->d_buf; 199 left = shdr->sh_size; 200 201 if (left < KABI_RULE_MIN_ENTRY_SIZE) 202 error("kABI rule section too small: %zd bytes", left); 203 204 if (rule_str[left - 1] != '\0') 205 error("kABI rules are not null-terminated"); 206 207 while (left > KABI_RULE_MIN_ENTRY_SIZE) { 208 enum kabi_rule_type type = KABI_RULE_TYPE_UNKNOWN; 209 const char *field; 210 struct rule *rule; 211 212 /* version */ 213 field = get_rule_field(&rule_str, &left); 214 215 if (strcmp(field, KABI_RULE_VERSION)) 216 error("unsupported kABI rule version: '%s'", field); 217 218 /* type */ 219 field = get_rule_field(&rule_str, &left); 220 221 for (i = 0; i < ARRAY_SIZE(rule_types); i++) { 222 if (!strcmp(field, rule_types[i].tag)) { 223 type = rule_types[i].type; 224 break; 225 } 226 } 227 228 if (type == KABI_RULE_TYPE_UNKNOWN) 229 error("unsupported kABI rule type: '%s'", field); 230 231 rule = xmalloc(sizeof(*rule)); 232 233 rule->type = type; 234 rule->target = xstrdup(get_rule_field(&rule_str, &left)); 235 rule->value = xstrdup(get_rule_field(&rule_str, &left)); 236 237 hash_add(rules, &rule->hash, rule_hash(rule)); 238 239 debug("kABI rule: type: '%s', target: '%s', value: '%s'", field, 240 rule->target, rule->value); 241 } 242 243 if (left > 0) 244 warn("unexpected data at the end of the kABI rules section"); 245 246 check(elf_end(elf)); 247 } 248 249 static char *get_enumerator_target(const char *fqn, const char *field) 250 { 251 char *target = NULL; 252 253 if (asprintf(&target, "%s %s", fqn, field) < 0) 254 error("asprintf failed for '%s %s'", fqn, field); 255 256 return target; 257 } 258 259 static struct rule *find_rule(enum kabi_rule_type type, const char *target) 260 { 261 struct rule *rule; 262 263 if (!stable) 264 return NULL; 265 if (!target || !*target) 266 return NULL; 267 268 hash_for_each_possible(rules, rule, hash, 269 rule_values_hash(type, target)) { 270 if (rule->type == type && !strcmp(target, rule->target)) 271 return rule; 272 } 273 274 return NULL; 275 } 276 277 static struct rule *find_enumerator_rule(enum kabi_rule_type type, 278 const char *fqn, const char *field) 279 { 280 struct rule *rule; 281 char *target; 282 283 if (!stable) 284 return NULL; 285 if (!fqn || !*fqn || !field || !*field) 286 return NULL; 287 288 target = get_enumerator_target(fqn, field); 289 rule = find_rule(type, target); 290 291 free(target); 292 return rule; 293 } 294 295 bool kabi_is_declonly(const char *fqn) 296 { 297 return !!find_rule(KABI_RULE_TYPE_DECLONLY, fqn); 298 } 299 300 static unsigned long get_ulong_value(const char *value) 301 { 302 unsigned long result = 0; 303 char *endptr = NULL; 304 305 errno = 0; 306 result = strtoul(value, &endptr, 10); 307 308 if (errno || *endptr) 309 error("invalid unsigned value '%s'", value); 310 311 return result; 312 } 313 314 bool kabi_is_enumerator_ignored(const char *fqn, const char *field) 315 { 316 return !!find_enumerator_rule(KABI_RULE_TYPE_ENUMERATOR_IGNORE, fqn, 317 field); 318 } 319 320 bool kabi_get_enumerator_value(const char *fqn, const char *field, 321 unsigned long *value) 322 { 323 struct rule *rule; 324 325 rule = find_enumerator_rule(KABI_RULE_TYPE_ENUMERATOR_VALUE, fqn, 326 field); 327 if (rule) { 328 *value = get_ulong_value(rule->value); 329 return true; 330 } 331 332 return false; 333 } 334 335 bool kabi_get_byte_size(const char *fqn, unsigned long *value) 336 { 337 struct rule *rule; 338 339 rule = find_rule(KABI_RULE_TYPE_BYTE_SIZE, fqn); 340 if (rule) { 341 *value = get_ulong_value(rule->value); 342 return true; 343 } 344 345 return false; 346 } 347 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 361 void kabi_free(void) 362 { 363 struct hlist_node *tmp; 364 struct rule *rule; 365 366 hash_for_each_safe(rules, rule, tmp, hash) { 367 free((void *)rule->target); 368 free((void *)rule->value); 369 free(rule); 370 } 371 372 hash_init(rules); 373 } 374