mirror of
https://github.com/Fishwaldo/linux-bl808.git
synced 2025-06-17 20:25:19 +00:00
objtool,x86: Replace alternatives with .retpoline_sites
Instead of writing complete alternatives, simply provide a list of all the retpoline thunk calls. Then the kernel is free to do with them as it pleases. Simpler code all-round. Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Reviewed-by: Borislav Petkov <bp@suse.de> Acked-by: Josh Poimboeuf <jpoimboe@redhat.com> Tested-by: Alexei Starovoitov <ast@kernel.org> Link: https://lore.kernel.org/r/20211026120309.850007165@infradead.org
This commit is contained in:
parent
c509331b41
commit
134ab5bd18
6 changed files with 107 additions and 252 deletions
|
@ -711,126 +711,6 @@ const char *arch_ret_insn(int len)
|
|||
return ret[len-1];
|
||||
}
|
||||
|
||||
/* asm/alternative.h ? */
|
||||
|
||||
#define ALTINSTR_FLAG_INV (1 << 15)
|
||||
#define ALT_NOT(feat) ((feat) | ALTINSTR_FLAG_INV)
|
||||
|
||||
struct alt_instr {
|
||||
s32 instr_offset; /* original instruction */
|
||||
s32 repl_offset; /* offset to replacement instruction */
|
||||
u16 cpuid; /* cpuid bit set for replacement */
|
||||
u8 instrlen; /* length of original instruction */
|
||||
u8 replacementlen; /* length of new instruction */
|
||||
} __packed;
|
||||
|
||||
static int elf_add_alternative(struct elf *elf,
|
||||
struct instruction *orig, struct symbol *sym,
|
||||
int cpuid, u8 orig_len, u8 repl_len)
|
||||
{
|
||||
const int size = sizeof(struct alt_instr);
|
||||
struct alt_instr *alt;
|
||||
struct section *sec;
|
||||
Elf_Scn *s;
|
||||
|
||||
sec = find_section_by_name(elf, ".altinstructions");
|
||||
if (!sec) {
|
||||
sec = elf_create_section(elf, ".altinstructions",
|
||||
SHF_ALLOC, 0, 0);
|
||||
|
||||
if (!sec) {
|
||||
WARN_ELF("elf_create_section");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
s = elf_getscn(elf->elf, sec->idx);
|
||||
if (!s) {
|
||||
WARN_ELF("elf_getscn");
|
||||
return -1;
|
||||
}
|
||||
|
||||
sec->data = elf_newdata(s);
|
||||
if (!sec->data) {
|
||||
WARN_ELF("elf_newdata");
|
||||
return -1;
|
||||
}
|
||||
|
||||
sec->data->d_size = size;
|
||||
sec->data->d_align = 1;
|
||||
|
||||
alt = sec->data->d_buf = malloc(size);
|
||||
if (!sec->data->d_buf) {
|
||||
perror("malloc");
|
||||
return -1;
|
||||
}
|
||||
memset(sec->data->d_buf, 0, size);
|
||||
|
||||
if (elf_add_reloc_to_insn(elf, sec, sec->sh.sh_size,
|
||||
R_X86_64_PC32, orig->sec, orig->offset)) {
|
||||
WARN("elf_create_reloc: alt_instr::instr_offset");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (elf_add_reloc(elf, sec, sec->sh.sh_size + 4,
|
||||
R_X86_64_PC32, sym, 0)) {
|
||||
WARN("elf_create_reloc: alt_instr::repl_offset");
|
||||
return -1;
|
||||
}
|
||||
|
||||
alt->cpuid = bswap_if_needed(cpuid);
|
||||
alt->instrlen = orig_len;
|
||||
alt->replacementlen = repl_len;
|
||||
|
||||
sec->sh.sh_size += size;
|
||||
sec->changed = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define X86_FEATURE_RETPOLINE ( 7*32+12)
|
||||
|
||||
int arch_rewrite_retpolines(struct objtool_file *file)
|
||||
{
|
||||
struct instruction *insn;
|
||||
struct reloc *reloc;
|
||||
struct symbol *sym;
|
||||
char name[32] = "";
|
||||
|
||||
list_for_each_entry(insn, &file->retpoline_call_list, call_node) {
|
||||
|
||||
if (insn->type != INSN_JUMP_DYNAMIC &&
|
||||
insn->type != INSN_CALL_DYNAMIC)
|
||||
continue;
|
||||
|
||||
if (!strcmp(insn->sec->name, ".text.__x86.indirect_thunk"))
|
||||
continue;
|
||||
|
||||
reloc = insn->reloc;
|
||||
|
||||
sprintf(name, "__x86_indirect_alt_%s_%s",
|
||||
insn->type == INSN_JUMP_DYNAMIC ? "jmp" : "call",
|
||||
reloc->sym->name + 21);
|
||||
|
||||
sym = find_symbol_by_name(file->elf, name);
|
||||
if (!sym) {
|
||||
sym = elf_create_undef_symbol(file->elf, name);
|
||||
if (!sym) {
|
||||
WARN("elf_create_undef_symbol");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (elf_add_alternative(file->elf, insn, sym,
|
||||
ALT_NOT(X86_FEATURE_RETPOLINE), 5, 5)) {
|
||||
WARN("elf_add_alternative");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int arch_decode_hint_reg(u8 sp_reg, int *base)
|
||||
{
|
||||
switch (sp_reg) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue