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: Allow multiple pv_ops arrays

Having a single large pv_ops array has the main disadvantage of needing all
prototypes of the single array members in one header file. This is adding up
to the need to include lots of otherwise unrelated headers.

In order to allow multiple smaller pv_ops arrays dedicated to one area of the
kernel each, allow multiple arrays in objtool.

For better performance limit the possible names of the arrays to start with
"pv_ops".

Signed-off-by: Juergen Gross <jgross@suse.com>
Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
Link: https://patch.msgid.link/20260105110520.21356-19-jgross@suse.com

authored by

Juergen Gross and committed by
Borislav Petkov (AMD)
f88dc319 7aef17f3

+65 -18
+6 -2
tools/objtool/arch/x86/decode.c
··· 711 711 immr = find_reloc_by_dest(elf, (void *)sec, offset+3); 712 712 disp = find_reloc_by_dest(elf, (void *)sec, offset+7); 713 713 714 - if (!immr || strcmp(immr->sym->name, "pv_ops")) 714 + if (!immr || strncmp(immr->sym->name, "pv_ops", 6)) 715 715 break; 716 716 717 - idx = (reloc_addend(immr) + 8) / sizeof(void *); 717 + idx = pv_ops_idx_off(immr->sym->name); 718 + if (idx < 0) 719 + break; 720 + 721 + idx += (reloc_addend(immr) + 8) / sizeof(void *); 718 722 719 723 func = disp->sym; 720 724 if (disp->sym->type == STT_SECTION)
+58 -16
tools/objtool/check.c
··· 520 520 } 521 521 522 522 /* 523 - * Read the pv_ops[] .data table to find the static initialized values. 523 + * Known pv_ops*[] arrays. 524 524 */ 525 - static int add_pv_ops(struct objtool_file *file, const char *symname) 525 + static struct { 526 + const char *name; 527 + int idx_off; 528 + } pv_ops_tables[] = { 529 + { .name = "pv_ops", }, 530 + { .name = NULL, .idx_off = -1 } 531 + }; 532 + 533 + /* 534 + * Get index offset for a pv_ops* array. 535 + */ 536 + int pv_ops_idx_off(const char *symname) 537 + { 538 + int idx; 539 + 540 + for (idx = 0; pv_ops_tables[idx].name; idx++) { 541 + if (!strcmp(symname, pv_ops_tables[idx].name)) 542 + break; 543 + } 544 + 545 + return pv_ops_tables[idx].idx_off; 546 + } 547 + 548 + /* 549 + * Read a pv_ops*[] .data table to find the static initialized values. 550 + */ 551 + static int add_pv_ops(struct objtool_file *file, int pv_ops_idx) 526 552 { 527 553 struct symbol *sym, *func; 528 554 unsigned long off, end; 529 555 struct reloc *reloc; 530 - int idx; 556 + int idx, idx_off; 557 + const char *symname; 531 558 559 + symname = pv_ops_tables[pv_ops_idx].name; 532 560 sym = find_symbol_by_name(file->elf, symname); 533 - if (!sym) 534 - return 0; 561 + if (!sym) { 562 + ERROR("Unknown pv_ops array %s", symname); 563 + return -1; 564 + } 535 565 536 566 off = sym->offset; 537 567 end = off + sym->len; 568 + idx_off = pv_ops_tables[pv_ops_idx].idx_off; 569 + if (idx_off < 0) { 570 + ERROR("pv_ops array %s has unknown index offset", symname); 571 + return -1; 572 + } 573 + 538 574 for (;;) { 539 575 reloc = find_reloc_by_dest_range(file->elf, sym->sec, off, end - off); 540 576 if (!reloc) ··· 588 552 return -1; 589 553 } 590 554 591 - if (objtool_pv_add(file, idx, func)) 555 + if (objtool_pv_add(file, idx + idx_off, func)) 592 556 return -1; 593 557 594 558 off = reloc_offset(reloc) + 1; ··· 604 568 */ 605 569 static int init_pv_ops(struct objtool_file *file) 606 570 { 607 - static const char *pv_ops_tables[] = { 608 - "pv_ops", 609 - NULL, 610 - }; 611 - const char *pv_ops; 612 571 struct symbol *sym; 613 572 int idx, nr; 614 573 ··· 612 581 613 582 file->pv_ops = NULL; 614 583 615 - sym = find_symbol_by_name(file->elf, "pv_ops"); 616 - if (!sym) 584 + nr = 0; 585 + for (idx = 0; pv_ops_tables[idx].name; idx++) { 586 + sym = find_symbol_by_name(file->elf, pv_ops_tables[idx].name); 587 + if (!sym) { 588 + pv_ops_tables[idx].idx_off = -1; 589 + continue; 590 + } 591 + pv_ops_tables[idx].idx_off = nr; 592 + nr += sym->len / sizeof(unsigned long); 593 + } 594 + 595 + if (nr == 0) 617 596 return 0; 618 597 619 - nr = sym->len / sizeof(unsigned long); 620 598 file->pv_ops = calloc(nr, sizeof(struct pv_state)); 621 599 if (!file->pv_ops) { 622 600 ERROR_GLIBC("calloc"); ··· 635 595 for (idx = 0; idx < nr; idx++) 636 596 INIT_LIST_HEAD(&file->pv_ops[idx].targets); 637 597 638 - for (idx = 0; (pv_ops = pv_ops_tables[idx]); idx++) { 639 - if (add_pv_ops(file, pv_ops)) 598 + for (idx = 0; pv_ops_tables[idx].name; idx++) { 599 + if (pv_ops_tables[idx].idx_off < 0) 600 + continue; 601 + if (add_pv_ops(file, idx)) 640 602 return -1; 641 603 } 642 604
+1
tools/objtool/include/objtool/check.h
··· 159 159 160 160 extern size_t sym_name_max_len; 161 161 extern struct disas_context *objtool_disas_ctx; 162 + int pv_ops_idx_off(const char *symname); 162 163 163 164 #endif /* _CHECK_H */