|
@@ -543,18 +543,14 @@ static int add_call_destinations(struct objtool_file *file)
|
|
|
dest_off = insn->offset + insn->len + insn->immediate;
|
|
|
insn->call_dest = find_symbol_by_offset(insn->sec,
|
|
|
dest_off);
|
|
|
- /*
|
|
|
- * FIXME: Thanks to retpolines, it's now considered
|
|
|
- * normal for a function to call within itself. So
|
|
|
- * disable this warning for now.
|
|
|
- */
|
|
|
-#if 0
|
|
|
- if (!insn->call_dest) {
|
|
|
- WARN_FUNC("can't find call dest symbol at offset 0x%lx",
|
|
|
- insn->sec, insn->offset, dest_off);
|
|
|
+
|
|
|
+ if (!insn->call_dest && !insn->ignore) {
|
|
|
+ WARN_FUNC("unsupported intra-function call",
|
|
|
+ insn->sec, insn->offset);
|
|
|
+ WARN("If this is a retpoline, please patch it in with alternatives and annotate it with ANNOTATE_NOSPEC_ALTERNATIVE.");
|
|
|
return -1;
|
|
|
}
|
|
|
-#endif
|
|
|
+
|
|
|
} else if (rela->sym->type == STT_SECTION) {
|
|
|
insn->call_dest = find_symbol_by_offset(rela->sym->sec,
|
|
|
rela->addend+4);
|
|
@@ -648,6 +644,8 @@ static int handle_group_alt(struct objtool_file *file,
|
|
|
|
|
|
last_new_insn = insn;
|
|
|
|
|
|
+ insn->ignore = orig_insn->ignore_alts;
|
|
|
+
|
|
|
if (insn->type != INSN_JUMP_CONDITIONAL &&
|
|
|
insn->type != INSN_JUMP_UNCONDITIONAL)
|
|
|
continue;
|
|
@@ -729,10 +727,6 @@ static int add_special_section_alts(struct objtool_file *file)
|
|
|
goto out;
|
|
|
}
|
|
|
|
|
|
- /* Ignore retpoline alternatives. */
|
|
|
- if (orig_insn->ignore_alts)
|
|
|
- continue;
|
|
|
-
|
|
|
new_insn = NULL;
|
|
|
if (!special_alt->group || special_alt->new_len) {
|
|
|
new_insn = find_insn(file, special_alt->new_sec,
|
|
@@ -1089,11 +1083,11 @@ static int decode_sections(struct objtool_file *file)
|
|
|
if (ret)
|
|
|
return ret;
|
|
|
|
|
|
- ret = add_call_destinations(file);
|
|
|
+ ret = add_special_section_alts(file);
|
|
|
if (ret)
|
|
|
return ret;
|
|
|
|
|
|
- ret = add_special_section_alts(file);
|
|
|
+ ret = add_call_destinations(file);
|
|
|
if (ret)
|
|
|
return ret;
|
|
|
|
|
@@ -1720,10 +1714,12 @@ static int validate_branch(struct objtool_file *file, struct instruction *first,
|
|
|
|
|
|
insn->visited = true;
|
|
|
|
|
|
- list_for_each_entry(alt, &insn->alts, list) {
|
|
|
- ret = validate_branch(file, alt->insn, state);
|
|
|
- if (ret)
|
|
|
- return 1;
|
|
|
+ if (!insn->ignore_alts) {
|
|
|
+ list_for_each_entry(alt, &insn->alts, list) {
|
|
|
+ ret = validate_branch(file, alt->insn, state);
|
|
|
+ if (ret)
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
switch (insn->type) {
|