Skip to content

Commit

Permalink
objtool: Fix gcov check for older versions of GCC
Browse files Browse the repository at this point in the history
Objtool tries to silence 'unreachable instruction' warnings when it
detects gcov is enabled, because gcov produces a lot of unreachable
instructions and they don't really matter.

However, the 0-day bot is still reporting some unreachable instruction
warnings with CONFIG_GCOV_KERNEL=y on GCC 4.6.4.

As it turns out, objtool's gcov detection doesn't work with older
versions of GCC because they don't create a bunch of symbols with the
'gcov.' prefix like newer versions of GCC do.

Move the gcov check out of objtool and instead just create a new
'--no-unreachable' flag which can be passed in by the kernel Makefile
when CONFIG_GCOV_KERNEL is defined.

Also rename the 'nofp' variable to 'no_fp' for consistency with the new
'no_unreachable' variable.

Reported-by: kbuild test robot <[email protected]>
Signed-off-by: Josh Poimboeuf <[email protected]>
Cc: Linus Torvalds <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Thomas Gleixner <[email protected]>
Fixes: 9cfffb1 ("objtool: Skip all "unreachable instruction" warnings for gcov kernels")
Link: http://lkml.kernel.org/r/c243dc78eb2ffdabb6e927844dea39b6033cd395.1500939244.git.jpoimboe@redhat.com
Signed-off-by: Ingo Molnar <[email protected]>
  • Loading branch information
jpoimboe authored and Ingo Molnar committed Jul 25, 2017
1 parent 9683a64 commit 867ac9d
Show file tree
Hide file tree
Showing 5 changed files with 17 additions and 35 deletions.
3 changes: 3 additions & 0 deletions scripts/Makefile.build
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,9 @@ objtool_args = check
ifndef CONFIG_FRAME_POINTER
objtool_args += --no-fp
endif
ifdef CONFIG_GCOV_KERNEL
objtool_args += --no-unreachable
endif

# 'OBJECT_FILES_NON_STANDARD := y': skip objtool checking for a directory
# 'OBJECT_FILES_NON_STANDARD_foo.o := 'y': skip objtool checking for a file
Expand Down
7 changes: 4 additions & 3 deletions tools/objtool/builtin-check.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,16 @@
#include "builtin.h"
#include "check.h"

bool nofp;
bool no_fp, no_unreachable;

static const char * const check_usage[] = {
"objtool check [<options>] file.o",
NULL,
};

const struct option check_options[] = {
OPT_BOOLEAN('f', "no-fp", &nofp, "Skip frame pointer validation"),
OPT_BOOLEAN('f', "no-fp", &no_fp, "Skip frame pointer validation"),
OPT_BOOLEAN('u', "no-unreachable", &no_unreachable, "Skip 'unreachable instruction' warnings"),
OPT_END(),
};

Expand All @@ -52,5 +53,5 @@ int cmd_check(int argc, const char **argv)

objname = argv[0];

return check(objname, nofp, false);
return check(objname, no_fp, no_unreachable, false);
}
4 changes: 2 additions & 2 deletions tools/objtool/builtin-orc.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ static const char *orc_usage[] = {
};

extern const struct option check_options[];
extern bool nofp;
extern bool no_fp, no_unreachable;

int cmd_orc(int argc, const char **argv)
{
Expand All @@ -51,7 +51,7 @@ int cmd_orc(int argc, const char **argv)

objname = argv[0];

return check(objname, nofp, true);
return check(objname, no_fp, no_unreachable, true);

}

Expand Down
36 changes: 7 additions & 29 deletions tools/objtool/check.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ struct alternative {
};

const char *objname;
static bool nofp;
static bool no_fp;
struct cfi_state initial_func_cfi;

struct instruction *find_insn(struct objtool_file *file,
Expand All @@ -59,19 +59,6 @@ static struct instruction *next_insn_same_sec(struct objtool_file *file,
return next;
}

static bool gcov_enabled(struct objtool_file *file)
{
struct section *sec;
struct symbol *sym;

for_each_sec(file, sec)
list_for_each_entry(sym, &sec->symbol_list, list)
if (!strncmp(sym->name, "__gcov_.", 8))
return true;

return false;
}

#define func_for_each_insn(file, func, insn) \
for (insn = find_insn(file, func->sec, func->offset); \
insn && &insn->list != &file->insn_list && \
Expand Down Expand Up @@ -1174,7 +1161,7 @@ static int update_insn_state(struct instruction *insn, struct insn_state *state)
regs[CFI_BP].base = CFI_BP;
regs[CFI_BP].offset = -state->stack_size;
state->bp_scratch = false;
} else if (!nofp) {
} else if (!no_fp) {

WARN_FUNC("unknown stack-related register move",
insn->sec, insn->offset);
Expand Down Expand Up @@ -1345,7 +1332,7 @@ static int update_insn_state(struct instruction *insn, struct insn_state *state)
}

/* detect when asm code uses rbp as a scratch register */
if (!nofp && insn->func && op->src.reg == CFI_BP &&
if (!no_fp && insn->func && op->src.reg == CFI_BP &&
cfa->base != CFI_BP)
state->bp_scratch = true;
break;
Expand Down Expand Up @@ -1593,7 +1580,7 @@ static int validate_branch(struct objtool_file *file, struct instruction *first,

/* fallthrough */
case INSN_CALL_DYNAMIC:
if (!nofp && func && !has_valid_stack_frame(&state)) {
if (!no_fp && func && !has_valid_stack_frame(&state)) {
WARN_FUNC("call without frame pointer save/setup",
sec, insn->offset);
return 1;
Expand Down Expand Up @@ -1779,15 +1766,6 @@ static int validate_reachable_instructions(struct objtool_file *file)
if (insn->visited || ignore_unreachable_insn(insn))
continue;

/*
* gcov produces a lot of unreachable instructions. If we get
* an unreachable warning and the file has gcov enabled, just
* ignore it, and all other such warnings for the file. Do
* this here because this is an expensive function.
*/
if (gcov_enabled(file))
return 0;

WARN_FUNC("unreachable instruction", insn->sec, insn->offset);
return 1;
}
Expand All @@ -1812,13 +1790,13 @@ static void cleanup(struct objtool_file *file)
elf_close(file->elf);
}

int check(const char *_objname, bool _nofp, bool orc)
int check(const char *_objname, bool _no_fp, bool no_unreachable, bool orc)
{
struct objtool_file file;
int ret, warnings = 0;

objname = _objname;
nofp = _nofp;
no_fp = _no_fp;

file.elf = elf_open(objname, orc ? O_RDWR : O_RDONLY);
if (!file.elf)
Expand All @@ -1829,7 +1807,7 @@ int check(const char *_objname, bool _nofp, bool orc)
file.whitelist = find_section_by_name(file.elf, ".discard.func_stack_frame_non_standard");
file.rodata = find_section_by_name(file.elf, ".rodata");
file.c_file = find_section_by_name(file.elf, ".comment");
file.ignore_unreachables = false;
file.ignore_unreachables = no_unreachable;
file.hints = false;

arch_initial_func_cfi_state(&initial_func_cfi);
Expand Down
2 changes: 1 addition & 1 deletion tools/objtool/check.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ struct objtool_file {
bool ignore_unreachables, c_file, hints;
};

int check(const char *objname, bool nofp, bool orc);
int check(const char *objname, bool no_fp, bool no_unreachable, bool orc);

struct instruction *find_insn(struct objtool_file *file,
struct section *sec, unsigned long offset);
Expand Down

0 comments on commit 867ac9d

Please sign in to comment.