On Fri, 10 Jul 2020 15:38:41 +0200 Peter Zijlstra <pet...@infradead.org> wrote: > --- a/tools/objtool/check.c > +++ b/tools/objtool/check.c > @@ -16,6 +16,7 @@ > > #include <linux/hashtable.h> > #include <linux/kernel.h> > +#include <linux/static_call_types.h> > > #define FAKE_JUMP_OFFSET -1 > > @@ -433,6 +434,99 @@ static int add_dead_ends(struct objtool_ > return 0; > } > > +static int create_static_call_sections(struct objtool_file *file) > +{ > + struct section *sec, *reloc_sec; > + struct reloc *reloc; > + struct static_call_site *site; > + struct instruction *insn; > + struct symbol *key_sym; > + char *key_name, *tmp; > + int idx; > + > + sec = find_section_by_name(file->elf, ".static_call_sites"); > + if (sec) { > + INIT_LIST_HEAD(&file->static_call_list); > + WARN("file already has .static_call_sites section, skipping"); > + return 0; > + } > + > + if (list_empty(&file->static_call_list)) > + return 0; > + > + idx = 0; > + list_for_each_entry(insn, &file->static_call_list, static_call_node) > + idx++; > + > + sec = elf_create_section(file->elf, ".static_call_sites", SHF_WRITE, > + sizeof(struct static_call_site), idx); > + if (!sec) > + return -1; > + > + reloc_sec = elf_create_reloc_section(file->elf, sec, SHT_RELA); > + if (!reloc_sec) > + return -1; > + > + idx = 0; > + list_for_each_entry(insn, &file->static_call_list, static_call_node) { > + > + site = (struct static_call_site *)sec->data->d_buf + idx; > + memset(site, 0, sizeof(struct static_call_site)); > + > + /* populate reloc for 'addr' */ > + reloc = malloc(sizeof(*reloc)); > + if (!reloc) { > + perror("malloc"); > + return -1; > + } > + memset(reloc, 0, sizeof(*reloc)); > + reloc->sym = insn->sec->sym; > + reloc->addend = insn->offset; > + reloc->type = R_X86_64_PC32; > + reloc->offset = idx * sizeof(struct static_call_site); > + reloc->sec = reloc_sec; > + elf_add_reloc(file->elf, reloc); > + > + /* find key symbol */ > + key_name = strdup(insn->call_dest->name);
Should check for failed allocation of strdup(). > + if (strncmp(key_name, STATIC_CALL_TRAMP_PREFIX_STR, > + strlen(STATIC_CALL_TRAMP_PREFIX_STR))) { > + WARN("static_call: trampoline name malformed: %s", > key_name); > + return -1; > + } > + tmp = key_name + STATIC_CALL_TRAMP_PREFIX_LEN - > STATIC_CALL_KEY_PREFIX_LEN; > + memcpy(tmp, STATIC_CALL_KEY_PREFIX_STR, > STATIC_CALL_KEY_PREFIX_LEN); > + > + key_sym = find_symbol_by_name(file->elf, tmp); > + if (!key_sym) { > + WARN("static_call: can't find static_call_key symbol: > %s", tmp); > + return -1; > + } > + free(key_name); > + > + /* populate reloc for 'key' */ > + reloc = malloc(sizeof(*reloc)); > + if (!reloc) { > + perror("malloc"); > + return -1; > + } > + memset(reloc, 0, sizeof(*reloc)); > + reloc->sym = key_sym; > + reloc->addend = 0; > + reloc->type = R_X86_64_PC32; How easy would this be for other architectures to implement this? That is how much of this function is x86 specific? -- Steve > + reloc->offset = idx * sizeof(struct static_call_site) + 4; > + reloc->sec = reloc_sec; > + elf_add_reloc(file->elf, reloc); > + > + idx++; > + } > + > + if (elf_rebuild_reloc_section(file->elf, reloc_sec)) > + return -1; > + > + return 0; > +} > +