Skip to content

Commit f88dc31

Browse files
jgross1bp3tk0v
authored andcommitted
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
1 parent 7aef17f commit f88dc31

3 files changed

Lines changed: 65 additions & 18 deletions

File tree

tools/objtool/arch/x86/decode.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -711,10 +711,14 @@ int arch_decode_instruction(struct objtool_file *file, const struct section *sec
711711
immr = find_reloc_by_dest(elf, (void *)sec, offset+3);
712712
disp = find_reloc_by_dest(elf, (void *)sec, offset+7);
713713

714-
if (!immr || strcmp(immr->sym->name, "pv_ops"))
714+
if (!immr || strncmp(immr->sym->name, "pv_ops", 6))
715715
break;
716716

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 *);
718722

719723
func = disp->sym;
720724
if (disp->sym->type == STT_SECTION)

tools/objtool/check.c

Lines changed: 58 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -520,21 +520,57 @@ static int decode_instructions(struct objtool_file *file)
520520
}
521521

522522
/*
523-
* Read the pv_ops[] .data table to find the static initialized values.
523+
* Known pv_ops*[] arrays.
524524
*/
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)
526552
{
527553
struct symbol *sym, *func;
528554
unsigned long off, end;
529555
struct reloc *reloc;
530-
int idx;
556+
int idx, idx_off;
557+
const char *symname;
531558

559+
symname = pv_ops_tables[pv_ops_idx].name;
532560
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+
}
535565

536566
off = sym->offset;
537567
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+
538574
for (;;) {
539575
reloc = find_reloc_by_dest_range(file->elf, sym->sec, off, end - off);
540576
if (!reloc)
@@ -552,7 +588,7 @@ static int add_pv_ops(struct objtool_file *file, const char *symname)
552588
return -1;
553589
}
554590

555-
if (objtool_pv_add(file, idx, func))
591+
if (objtool_pv_add(file, idx + idx_off, func))
556592
return -1;
557593

558594
off = reloc_offset(reloc) + 1;
@@ -568,11 +604,6 @@ static int add_pv_ops(struct objtool_file *file, const char *symname)
568604
*/
569605
static int init_pv_ops(struct objtool_file *file)
570606
{
571-
static const char *pv_ops_tables[] = {
572-
"pv_ops",
573-
NULL,
574-
};
575-
const char *pv_ops;
576607
struct symbol *sym;
577608
int idx, nr;
578609

@@ -581,11 +612,20 @@ static int init_pv_ops(struct objtool_file *file)
581612

582613
file->pv_ops = NULL;
583614

584-
sym = find_symbol_by_name(file->elf, "pv_ops");
585-
if (!sym)
615+
nr = 0;
616+
for (idx = 0; pv_ops_tables[idx].name; idx++) {
617+
sym = find_symbol_by_name(file->elf, pv_ops_tables[idx].name);
618+
if (!sym) {
619+
pv_ops_tables[idx].idx_off = -1;
620+
continue;
621+
}
622+
pv_ops_tables[idx].idx_off = nr;
623+
nr += sym->len / sizeof(unsigned long);
624+
}
625+
626+
if (nr == 0)
586627
return 0;
587628

588-
nr = sym->len / sizeof(unsigned long);
589629
file->pv_ops = calloc(nr, sizeof(struct pv_state));
590630
if (!file->pv_ops) {
591631
ERROR_GLIBC("calloc");
@@ -595,8 +635,10 @@ static int init_pv_ops(struct objtool_file *file)
595635
for (idx = 0; idx < nr; idx++)
596636
INIT_LIST_HEAD(&file->pv_ops[idx].targets);
597637

598-
for (idx = 0; (pv_ops = pv_ops_tables[idx]); idx++) {
599-
if (add_pv_ops(file, pv_ops))
638+
for (idx = 0; pv_ops_tables[idx].name; idx++) {
639+
if (pv_ops_tables[idx].idx_off < 0)
640+
continue;
641+
if (add_pv_ops(file, idx))
600642
return -1;
601643
}
602644

tools/objtool/include/objtool/check.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,5 +159,6 @@ const char *objtool_disas_insn(struct instruction *insn);
159159

160160
extern size_t sym_name_max_len;
161161
extern struct disas_context *objtool_disas_ctx;
162+
int pv_ops_idx_off(const char *symname);
162163

163164
#endif /* _CHECK_H */

0 commit comments

Comments
 (0)