Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

objtool/klp: Match symbols based on demangled_name for global variables

correlate_symbols() will always try to match full name first. If there is
no match, try match only demangled_name.

In very rare cases, it is possible to have multiple foo.llvm.<hash> in
the same kernel. Whenever there is ambiguity like this, fail the klp diff.

Signed-off-by: Song Liu <song@kernel.org>
Link: https://patch.msgid.link/20260305231531.3847295-7-song@kernel.org
Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>

authored by

Song Liu and committed by
Josh Poimboeuf
cdea5cad 020b71dc

+73
+13
tools/objtool/elf.c
··· 323 323 return NULL; 324 324 } 325 325 326 + void iterate_global_symbol_by_demangled_name(const struct elf *elf, 327 + const char *demangled_name, 328 + void (*process)(struct symbol *sym, void *data), 329 + void *data) 330 + { 331 + struct symbol *sym; 332 + 333 + elf_hash_for_each_possible(symbol_name, sym, name_hash, str_hash(demangled_name)) { 334 + if (!strcmp(sym->demangled_name, demangled_name) && !is_local_sym(sym)) 335 + process(sym, data); 336 + } 337 + } 338 + 326 339 struct reloc *find_reloc_by_dest_range(const struct elf *elf, struct section *sec, 327 340 unsigned long offset, unsigned int len) 328 341 {
+3
tools/objtool/include/objtool/elf.h
··· 186 186 struct symbol *find_symbol_by_offset(struct section *sec, unsigned long offset); 187 187 struct symbol *find_symbol_by_name(const struct elf *elf, const char *name); 188 188 struct symbol *find_global_symbol_by_name(const struct elf *elf, const char *name); 189 + void iterate_global_symbol_by_demangled_name(const struct elf *elf, const char *demangled_name, 190 + void (*process)(struct symbol *sym, void *data), 191 + void *data); 189 192 struct symbol *find_symbol_containing(const struct section *sec, unsigned long offset); 190 193 int find_symbol_hole_containing(const struct section *sec, unsigned long offset); 191 194 struct reloc *find_reloc_by_dest(const struct elf *elf, struct section *sec, unsigned long offset);
+57
tools/objtool/klp-diff.c
··· 355 355 strstarts(sym->name, "__initcall__"); 356 356 } 357 357 358 + struct process_demangled_name_data { 359 + struct symbol *ret; 360 + int count; 361 + }; 362 + 363 + static void process_demangled_name(struct symbol *sym, void *d) 364 + { 365 + struct process_demangled_name_data *data = d; 366 + 367 + if (sym->twin) 368 + return; 369 + 370 + data->count++; 371 + data->ret = sym; 372 + } 373 + 374 + /* 375 + * When there is no full name match, try match demangled_name. This would 376 + * match original foo.llvm.123 to patched foo.llvm.456. 377 + * 378 + * Note that, in very rare cases, it is possible to have multiple 379 + * foo.llvm.<hash> in the same kernel. When this happens, report error and 380 + * fail the diff. 381 + */ 382 + static int find_global_symbol_by_demangled_name(struct elf *elf, struct symbol *sym, 383 + struct symbol **out_sym) 384 + { 385 + struct process_demangled_name_data data = {}; 386 + 387 + iterate_global_symbol_by_demangled_name(elf, sym->demangled_name, 388 + process_demangled_name, 389 + &data); 390 + if (data.count > 1) { 391 + ERROR("Multiple (%d) correlation candidates for %s", data.count, sym->name); 392 + return -1; 393 + } 394 + *out_sym = data.ret; 395 + return 0; 396 + } 397 + 358 398 /* 359 399 * For each symbol in the original kernel, find its corresponding "twin" in the 360 400 * patched kernel. ··· 493 453 continue; 494 454 495 455 sym2 = find_global_symbol_by_name(e->patched, sym1->name); 456 + if (sym2 && !sym2->twin) { 457 + sym1->twin = sym2; 458 + sym2->twin = sym1; 459 + } 460 + } 461 + 462 + /* 463 + * Correlate globals with demangled_name. 464 + * A separate loop is needed because we want to finish all the 465 + * full name correlations first. 466 + */ 467 + for_each_sym(e->orig, sym1) { 468 + if (sym1->bind == STB_LOCAL || sym1->twin) 469 + continue; 470 + 471 + if (find_global_symbol_by_demangled_name(e->patched, sym1, &sym2)) 472 + return -1; 496 473 497 474 if (sym2 && !sym2->twin) { 498 475 sym1->twin = sym2;