Assume ALTERNATIVE()s know what they're doing and do not change, or cause to change, instructions in .altinstr_replacement sections.
Unified · Split
| @@ -993,18 +993,27 @@ static void remove_insn_ops(struct instruction *insn) · 992 unmodified lines | ||
| 993 | 993 | } |
| 994 | 994 | } |
| 995 | 995 | |
| 996 | −static void add_call_dest(struct objtool_file *file, struct instruction *insn, | |
| 997 | − struct symbol *dest, bool sibling) | |
| 996 | +static void annotate_call_site(struct objtool_file *file, | |
| 997 | + struct instruction *insn, bool sibling) | |
| 998 | 998 | { |
| 999 | 999 | struct reloc *reloc = insn_reloc(file, insn); |
| 1000 | + struct symbol *sym = insn->call_dest; | |
| 1000 | 1001 | |
| 1001 | − insn->call_dest = dest; | |
| 1002 | − if (!dest) | |
| 1002 | + if (!sym) | |
| 1003 | + sym = reloc->sym; | |
| 1004 | + | |
| 1005 | + /* | |
| 1006 | + * Alternative replacement code is just template code which is | |
| 1007 | + * sometimes copied to the original instruction. For now, don't | |
| 1008 | + * annotate it. (In the future we might consider annotating the | |
| 1009 | + * original instruction if/when it ever makes sense to do so.) | |
| 1010 | + */ | |
| 1011 | + if (!strcmp(insn->sec->name, ".altinstr_replacement")) | |
| 1003 | 1012 | return; |
| 1004 | 1013 | |
| 1005 | − if (insn->call_dest->static_call_tramp) { | |
| 1006 | − list_add_tail(&insn->call_node, | |
| 1007 | − &file->static_call_list); | |
| 1014 | + if (sym->static_call_tramp) { | |
| 1015 | + list_add_tail(&insn->call_node, &file->static_call_list); | |
| 1016 | + return; | |
| 1008 | 1017 | } |
| 1009 | 1018 | |
| 1010 | 1019 | /* |
| @@ -1012,7 +1021,7 @@ static void add_call_dest(struct objtool_file *file, struct instruction *insn, · 1 unmodified line | ||
| 1012 | 1021 | * so they need a little help, NOP out any KCOV calls from noinstr |
| 1013 | 1022 | * text. |
| 1014 | 1023 | */ |
| 1015 | − if (insn->sec->noinstr && insn->call_dest->kcov) { | |
| 1024 | + if (insn->sec->noinstr && sym->kcov) { | |
| 1016 | 1025 | if (reloc) { |
| 1017 | 1026 | reloc->type = R_NONE; |
| 1018 | 1027 | elf_write_reloc(file->elf, reloc); |
| @@ -1024,9 +1033,10 @@ static void add_call_dest(struct objtool_file *file, struct instruction *insn, · 5 unmodified lines | ||
| 1024 | 1033 | : arch_nop_insn(insn->len)); |
| 1025 | 1034 | |
| 1026 | 1035 | insn->type = sibling ? INSN_RETURN : INSN_NOP; |
| 1036 | + return; | |
| 1027 | 1037 | } |
| 1028 | 1038 | |
| 1029 | − if (mcount && insn->call_dest->fentry) { | |
| 1039 | + if (mcount && sym->fentry) { | |
| 1030 | 1040 | if (sibling) |
| 1031 | 1041 | WARN_FUNC("Tail call to __fentry__ !?!?", insn->sec, insn->offset); |
| 1032 | 1042 | |
| @@ -1041,9 +1051,17 @@ static void add_call_dest(struct objtool_file *file, struct instruction *insn, · 8 unmodified lines | ||
| 1041 | 1051 | |
| 1042 | 1052 | insn->type = INSN_NOP; |
| 1043 | 1053 | |
| 1044 | − list_add_tail(&insn->mcount_loc_node, | |
| 1045 | − &file->mcount_loc_list); | |
| 1054 | + list_add_tail(&insn->mcount_loc_node, &file->mcount_loc_list); | |
| 1055 | + return; | |
| 1046 | 1056 | } |
| 1057 | +} | |
| 1058 | + | |
| 1059 | +static void add_call_dest(struct objtool_file *file, struct instruction *insn, | |
| 1060 | + struct symbol *dest, bool sibling) | |
| 1061 | +{ | |
| 1062 | + insn->call_dest = dest; | |
| 1063 | + if (!dest) | |
| 1064 | + return; | |
| 1047 | 1065 | |
| 1048 | 1066 | /* |
| 1049 | 1067 | * Whatever stack impact regular CALLs have, should be undone |
| @@ -1053,6 +1071,8 @@ static void add_call_dest(struct objtool_file *file, struct instruction *insn, · 3 unmodified lines | ||
| 1053 | 1071 | * are converted to JUMP, see read_intra_function_calls(). |
| 1054 | 1072 | */ |
| 1055 | 1073 | remove_insn_ops(insn); |
| 1074 | + | |
| 1075 | + annotate_call_site(file, insn, sibling); | |
| 1056 | 1076 | } |
| 1057 | 1077 | |
| 1058 | 1078 | /* |