Commit 1e11f3fd authored by Peter Zijlstra's avatar Peter Zijlstra

objtool: Add a statistics mode

Have it print a few numbers which can be used to size the hashtables.
Signed-off-by: default avatarPeter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: default avatarMiroslav Benes <mbenes@suse.cz>
Acked-by: default avatarJosh Poimboeuf <jpoimboe@redhat.com>
Link: https://lkml.kernel.org/r/20200324160924.321381240@infradead.org
parent 65fb11a7
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
#include "builtin.h" #include "builtin.h"
#include "check.h" #include "check.h"
bool no_fp, no_unreachable, retpoline, module, backtrace, uaccess; bool no_fp, no_unreachable, retpoline, module, backtrace, uaccess, stats;
static const char * const check_usage[] = { static const char * const check_usage[] = {
"objtool check [<options>] file.o", "objtool check [<options>] file.o",
...@@ -31,6 +31,7 @@ const struct option check_options[] = { ...@@ -31,6 +31,7 @@ const struct option check_options[] = {
OPT_BOOLEAN('m', "module", &module, "Indicates the object will be part of a kernel module"), OPT_BOOLEAN('m', "module", &module, "Indicates the object will be part of a kernel module"),
OPT_BOOLEAN('b', "backtrace", &backtrace, "unwind on error"), OPT_BOOLEAN('b', "backtrace", &backtrace, "unwind on error"),
OPT_BOOLEAN('a', "uaccess", &uaccess, "enable uaccess checking"), OPT_BOOLEAN('a', "uaccess", &uaccess, "enable uaccess checking"),
OPT_BOOLEAN('s', "stats", &stats, "print statistics"),
OPT_END(), OPT_END(),
}; };
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
#include <subcmd/parse-options.h> #include <subcmd/parse-options.h>
extern const struct option check_options[]; extern const struct option check_options[];
extern bool no_fp, no_unreachable, retpoline, module, backtrace, uaccess; extern bool no_fp, no_unreachable, retpoline, module, backtrace, uaccess, stats;
extern int cmd_check(int argc, const char **argv); extern int cmd_check(int argc, const char **argv);
extern int cmd_orc(int argc, const char **argv); extern int cmd_orc(int argc, const char **argv);
......
...@@ -239,6 +239,7 @@ static int decode_instructions(struct objtool_file *file) ...@@ -239,6 +239,7 @@ static int decode_instructions(struct objtool_file *file)
struct symbol *func; struct symbol *func;
unsigned long offset; unsigned long offset;
struct instruction *insn; struct instruction *insn;
unsigned long nr_insns = 0;
int ret; int ret;
for_each_sec(file, sec) { for_each_sec(file, sec) {
...@@ -274,6 +275,7 @@ static int decode_instructions(struct objtool_file *file) ...@@ -274,6 +275,7 @@ static int decode_instructions(struct objtool_file *file)
hash_add(file->insn_hash, &insn->hash, insn->offset); hash_add(file->insn_hash, &insn->hash, insn->offset);
list_add_tail(&insn->list, &file->insn_list); list_add_tail(&insn->list, &file->insn_list);
nr_insns++;
} }
list_for_each_entry(func, &sec->symbol_list, list) { list_for_each_entry(func, &sec->symbol_list, list) {
...@@ -291,6 +293,9 @@ static int decode_instructions(struct objtool_file *file) ...@@ -291,6 +293,9 @@ static int decode_instructions(struct objtool_file *file)
} }
} }
if (stats)
printf("nr_insns: %lu\n", nr_insns);
return 0; return 0;
err: err:
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#include <errno.h> #include <errno.h>
#include "builtin.h"
#include "elf.h" #include "elf.h"
#include "warn.h" #include "warn.h"
...@@ -202,6 +203,9 @@ static int read_sections(struct elf *elf) ...@@ -202,6 +203,9 @@ static int read_sections(struct elf *elf)
sec->len = sec->sh.sh_size; sec->len = sec->sh.sh_size;
} }
if (stats)
printf("nr_sections: %lu\n", (unsigned long)sections_nr);
/* sanity check, one more call to elf_nextscn() should return NULL */ /* sanity check, one more call to elf_nextscn() should return NULL */
if (elf_nextscn(elf->elf, s)) { if (elf_nextscn(elf->elf, s)) {
WARN("section entry mismatch"); WARN("section entry mismatch");
...@@ -299,6 +303,9 @@ static int read_symbols(struct elf *elf) ...@@ -299,6 +303,9 @@ static int read_symbols(struct elf *elf)
hash_add(elf->symbol_hash, &sym->hash, sym->idx); hash_add(elf->symbol_hash, &sym->hash, sym->idx);
} }
if (stats)
printf("nr_symbols: %lu\n", (unsigned long)symbols_nr);
/* Create parent/child links for any cold subfunctions */ /* Create parent/child links for any cold subfunctions */
list_for_each_entry(sec, &elf->sections, list) { list_for_each_entry(sec, &elf->sections, list) {
list_for_each_entry(sym, &sec->symbol_list, list) { list_for_each_entry(sym, &sec->symbol_list, list) {
...@@ -360,6 +367,7 @@ static int read_relas(struct elf *elf) ...@@ -360,6 +367,7 @@ static int read_relas(struct elf *elf)
struct rela *rela; struct rela *rela;
int i; int i;
unsigned int symndx; unsigned int symndx;
unsigned long nr_rela, max_rela = 0, tot_rela = 0;
list_for_each_entry(sec, &elf->sections, list) { list_for_each_entry(sec, &elf->sections, list) {
if (sec->sh.sh_type != SHT_RELA) if (sec->sh.sh_type != SHT_RELA)
...@@ -374,6 +382,7 @@ static int read_relas(struct elf *elf) ...@@ -374,6 +382,7 @@ static int read_relas(struct elf *elf)
sec->base->rela = sec; sec->base->rela = sec;
nr_rela = 0;
for (i = 0; i < sec->sh.sh_size / sec->sh.sh_entsize; i++) { for (i = 0; i < sec->sh.sh_size / sec->sh.sh_entsize; i++) {
rela = malloc(sizeof(*rela)); rela = malloc(sizeof(*rela));
if (!rela) { if (!rela) {
...@@ -401,8 +410,15 @@ static int read_relas(struct elf *elf) ...@@ -401,8 +410,15 @@ static int read_relas(struct elf *elf)
list_add_tail(&rela->list, &sec->rela_list); list_add_tail(&rela->list, &sec->rela_list);
hash_add(sec->rela_hash, &rela->hash, rela->offset); hash_add(sec->rela_hash, &rela->hash, rela->offset);
nr_rela++;
} }
max_rela = max(max_rela, nr_rela);
tot_rela += nr_rela;
}
if (stats) {
printf("max_rela: %lu\n", max_rela);
printf("tot_rela: %lu\n", tot_rela);
} }
return 0; return 0;
......
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