Commit 00abd384 authored by Peter Zijlstra's avatar Peter Zijlstra

objtool: Add .call_sites section

In preparation for call depth tracking provide a section which collects all
direct calls.
Signed-off-by: default avatarPeter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
Signed-off-by: default avatarPeter Zijlstra (Intel) <peterz@infradead.org>
Link: https://lore.kernel.org/r/20220915111146.016511961@infradead.org
parent 6644ee84
......@@ -291,6 +291,13 @@ SECTIONS
*(.return_sites)
__return_sites_end = .;
}
. = ALIGN(8);
.call_sites : AT(ADDR(.call_sites) - LOAD_OFFSET) {
__call_sites = .;
*(.call_sites)
__call_sites_end = .;
}
#endif
#ifdef CONFIG_X86_KERNEL_IBT
......
......@@ -902,6 +902,49 @@ static int create_mcount_loc_sections(struct objtool_file *file)
return 0;
}
static int create_direct_call_sections(struct objtool_file *file)
{
struct instruction *insn;
struct section *sec;
unsigned int *loc;
int idx;
sec = find_section_by_name(file->elf, ".call_sites");
if (sec) {
INIT_LIST_HEAD(&file->call_list);
WARN("file already has .call_sites section, skipping");
return 0;
}
if (list_empty(&file->call_list))
return 0;
idx = 0;
list_for_each_entry(insn, &file->call_list, call_node)
idx++;
sec = elf_create_section(file->elf, ".call_sites", 0, sizeof(unsigned int), idx);
if (!sec)
return -1;
idx = 0;
list_for_each_entry(insn, &file->call_list, call_node) {
loc = (unsigned int *)sec->data->d_buf + idx;
memset(loc, 0, sizeof(unsigned int));
if (elf_add_reloc_to_insn(file->elf, sec,
idx * sizeof(unsigned int),
R_X86_64_PC32,
insn->sec, insn->offset))
return -1;
idx++;
}
return 0;
}
/*
* Warnings shouldn't be reported for ignored functions.
*/
......@@ -1279,6 +1322,9 @@ static void annotate_call_site(struct objtool_file *file,
return;
}
if (insn->type == INSN_CALL && !insn->sec->init)
list_add_tail(&insn->call_node, &file->call_list);
if (!sibling && dead_end_function(file, sym))
insn->dead_end = true;
}
......@@ -4305,6 +4351,11 @@ int check(struct objtool_file *file)
if (ret < 0)
goto out;
warnings += ret;
ret = create_direct_call_sections(file);
if (ret < 0)
goto out;
warnings += ret;
}
if (opts.mcount) {
......
......@@ -28,6 +28,7 @@ struct objtool_file {
struct list_head static_call_list;
struct list_head mcount_loc_list;
struct list_head endbr_list;
struct list_head call_list;
bool ignore_unreachables, hints, rodata;
unsigned int nr_endbr;
......
......@@ -106,6 +106,7 @@ struct objtool_file *objtool_open_read(const char *_objname)
INIT_LIST_HEAD(&file.static_call_list);
INIT_LIST_HEAD(&file.mcount_loc_list);
INIT_LIST_HEAD(&file.endbr_list);
INIT_LIST_HEAD(&file.call_list);
file.ignore_unreachables = opts.no_unreachable;
file.hints = false;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment