Skip to content

Commit 668a93c

Browse files
committed
objtool: Add option to generate prefix symbols
JIRA: https://issues.redhat.com/browse/RHEL-255 commit 9f2899f Author: Peter Zijlstra <peterz@infradead.org> Date: Fri Oct 28 15:50:42 2022 +0200 objtool: Add option to generate prefix symbols When code is compiled with: -fpatchable-function-entry=${PADDING_BYTES},${PADDING_BYTES} functions will have PADDING_BYTES of NOP in front of them. Unwinders and other things that symbolize code locations will typically attribute these bytes to the preceding function. Given that these bytes nominally belong to the following symbol this mis-attribution is confusing. Inspired by the fact that CFI_CLANG emits __cfi_##name symbols to claim these bytes, allow objtool to emit __pfx_##name symbols to do the same. Therefore add the objtool --prefix=N argument, to conditionally place a __pfx_##name symbol at N bytes ahead of symbol 'name' when: all these preceding bytes are NOP and name-N is an instruction boundary. Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Tested-by: Yujie Liu <yujie.liu@intel.com> Link: https://lkml.kernel.org/r/20221028194453.526899822@infradead.org Signed-off-by: Joe Lawrence <joe.lawrence@redhat.com>
1 parent 17dde51 commit 668a93c

File tree

5 files changed

+67
-1
lines changed

5 files changed

+67
-1
lines changed

tools/objtool/builtin-check.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ const struct option check_options[] = {
7070
OPT_BOOLEAN('r', "retpoline", &opts.retpoline, "validate and annotate retpoline usage"),
7171
OPT_BOOLEAN(0, "rethunk", &opts.rethunk, "validate and annotate rethunk usage"),
7272
OPT_BOOLEAN(0, "unret", &opts.unret, "validate entry unret placement"),
73+
OPT_INTEGER(0, "prefix", &opts.prefix, "generate prefix symbols"),
7374
OPT_BOOLEAN('l', "sls", &opts.sls, "validate straight-line-speculation mitigations"),
7475
OPT_BOOLEAN('s', "stackval", &opts.stackval, "validate frame pointer rules"),
7576
OPT_BOOLEAN('t', "static-call", &opts.static_call, "annotate static calls"),

tools/objtool/check.c

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3348,7 +3348,8 @@ static int validate_branch(struct objtool_file *file, struct symbol *func,
33483348

33493349
if (func && insn->func && func != insn->func->pfunc) {
33503350
/* Ignore KCFI type preambles, which always fall through */
3351-
if (!strncmp(func->name, "__cfi_", 6))
3351+
if (!strncmp(func->name, "__cfi_", 6) ||
3352+
!strncmp(func->name, "__pfx_", 6))
33523353
return 0;
33533354

33543355
WARN("%s() falls through to next function %s()",
@@ -3909,6 +3910,34 @@ static bool ignore_unreachable_insn(struct objtool_file *file, struct instructio
39093910
return false;
39103911
}
39113912

3913+
static int add_prefix_symbol(struct objtool_file *file, struct symbol *func,
3914+
struct instruction *insn)
3915+
{
3916+
if (!opts.prefix)
3917+
return 0;
3918+
3919+
for (;;) {
3920+
struct instruction *prev = list_prev_entry(insn, list);
3921+
u64 offset;
3922+
3923+
if (&prev->list == &file->insn_list)
3924+
break;
3925+
3926+
if (prev->type != INSN_NOP)
3927+
break;
3928+
3929+
offset = func->offset - prev->offset;
3930+
if (offset >= opts.prefix) {
3931+
if (offset == opts.prefix)
3932+
elf_create_prefix_symbol(file->elf, func, opts.prefix);
3933+
break;
3934+
}
3935+
insn = prev;
3936+
}
3937+
3938+
return 0;
3939+
}
3940+
39123941
static int validate_symbol(struct objtool_file *file, struct section *sec,
39133942
struct symbol *sym, struct insn_state *state)
39143943
{
@@ -3927,6 +3956,8 @@ static int validate_symbol(struct objtool_file *file, struct section *sec,
39273956
if (!insn || insn->ignore || insn->visited)
39283957
return 0;
39293958

3959+
add_prefix_symbol(file, sym, insn);
3960+
39303961
state->uaccess = sym->uaccess_safe;
39313962

39323963
ret = validate_branch(file, insn->func, insn, *state);

tools/objtool/elf.c

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -832,6 +832,37 @@ elf_create_section_symbol(struct elf *elf, struct section *sec)
832832
return sym;
833833
}
834834

835+
static int elf_add_string(struct elf *elf, struct section *strtab, char *str);
836+
837+
struct symbol *
838+
elf_create_prefix_symbol(struct elf *elf, struct symbol *orig, long size)
839+
{
840+
struct symbol *sym = calloc(1, sizeof(*sym));
841+
size_t namelen = strlen(orig->name) + sizeof("__pfx_");
842+
char *name = malloc(namelen);
843+
844+
if (!sym || !name) {
845+
perror("malloc");
846+
return NULL;
847+
}
848+
849+
snprintf(name, namelen, "__pfx_%s", orig->name);
850+
851+
sym->name = name;
852+
sym->sec = orig->sec;
853+
854+
sym->sym.st_name = elf_add_string(elf, NULL, name);
855+
sym->sym.st_info = orig->sym.st_info;
856+
sym->sym.st_value = orig->sym.st_value - size;
857+
sym->sym.st_size = size;
858+
859+
sym = __elf_create_symbol(elf, sym);
860+
if (sym)
861+
elf_add_symbol(elf, sym);
862+
863+
return sym;
864+
}
865+
835866
int elf_add_reloc_to_insn(struct elf *elf, struct section *sec,
836867
unsigned long offset, unsigned int type,
837868
struct section *insn_sec, unsigned long insn_off)

tools/objtool/include/objtool/builtin.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ struct opts {
2424
bool stackval;
2525
bool static_call;
2626
bool uaccess;
27+
int prefix;
2728

2829
/* options: */
2930
bool backtrace;

tools/objtool/include/objtool/elf.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,8 @@ static inline bool has_multiple_files(struct elf *elf)
145145
struct elf *elf_open_read(const char *name, int flags);
146146
struct section *elf_create_section(struct elf *elf, const char *name, unsigned int sh_flags, size_t entsize, int nr);
147147

148+
struct symbol *elf_create_prefix_symbol(struct elf *elf, struct symbol *orig, long size);
149+
148150
int elf_add_reloc(struct elf *elf, struct section *sec, unsigned long offset,
149151
unsigned int type, struct symbol *sym, s64 addend);
150152
int elf_add_reloc_to_insn(struct elf *elf, struct section *sec,

0 commit comments

Comments
 (0)