| .. | .. |
|---|
| 168 | 168 | "panic", |
|---|
| 169 | 169 | "do_exit", |
|---|
| 170 | 170 | "do_task_dead", |
|---|
| 171 | + "make_task_dead", |
|---|
| 171 | 172 | "__module_put_and_exit", |
|---|
| 172 | 173 | "complete_and_exit", |
|---|
| 173 | 174 | "__reiserfs_panic", |
|---|
| .. | .. |
|---|
| 175 | 176 | "fortify_panic", |
|---|
| 176 | 177 | "usercopy_abort", |
|---|
| 177 | 178 | "machine_real_restart", |
|---|
| 178 | | - "rewind_stack_do_exit", |
|---|
| 179 | + "rewind_stack_and_make_dead", |
|---|
| 179 | 180 | "kunit_try_catch_throw", |
|---|
| 180 | 181 | "xen_start_kernel", |
|---|
| 181 | 182 | "cpu_bringup_and_idle", |
|---|
| 183 | + "stop_this_cpu", |
|---|
| 182 | 184 | }; |
|---|
| 183 | 185 | |
|---|
| 184 | 186 | if (!func) |
|---|
| .. | .. |
|---|
| 196 | 198 | return false; |
|---|
| 197 | 199 | |
|---|
| 198 | 200 | insn = find_insn(file, func->sec, func->offset); |
|---|
| 199 | | - if (!insn->func) |
|---|
| 201 | + if (!insn || !insn->func) |
|---|
| 200 | 202 | return false; |
|---|
| 201 | 203 | |
|---|
| 202 | 204 | func_for_each_insn(file, func, insn) { |
|---|
| .. | .. |
|---|
| 367 | 369 | |
|---|
| 368 | 370 | if (!strcmp(sec->name, ".noinstr.text") || |
|---|
| 369 | 371 | !strcmp(sec->name, ".entry.text") || |
|---|
| 370 | | - !strncmp(sec->name, ".text.__x86.", 12)) |
|---|
| 372 | + !strncmp(sec->name, ".text..__x86.", 13)) |
|---|
| 371 | 373 | sec->noinstr = true; |
|---|
| 372 | 374 | |
|---|
| 373 | 375 | for (offset = 0; offset < sec->len; offset += insn->len) { |
|---|
| .. | .. |
|---|
| 570 | 572 | if (strncmp(key_name, STATIC_CALL_TRAMP_PREFIX_STR, |
|---|
| 571 | 573 | STATIC_CALL_TRAMP_PREFIX_LEN)) { |
|---|
| 572 | 574 | WARN("static_call: trampoline name malformed: %s", key_name); |
|---|
| 575 | + free(key_name); |
|---|
| 573 | 576 | return -1; |
|---|
| 574 | 577 | } |
|---|
| 575 | 578 | tmp = key_name + STATIC_CALL_TRAMP_PREFIX_LEN - STATIC_CALL_KEY_PREFIX_LEN; |
|---|
| .. | .. |
|---|
| 579 | 582 | if (!key_sym) { |
|---|
| 580 | 583 | if (!module) { |
|---|
| 581 | 584 | WARN("static_call: can't find static_call_key symbol: %s", tmp); |
|---|
| 585 | + free(key_name); |
|---|
| 582 | 586 | return -1; |
|---|
| 583 | 587 | } |
|---|
| 584 | 588 | |
|---|
| .. | .. |
|---|
| 845 | 849 | "__tsan_read_write4", |
|---|
| 846 | 850 | "__tsan_read_write8", |
|---|
| 847 | 851 | "__tsan_read_write16", |
|---|
| 852 | + "__tsan_volatile_read1", |
|---|
| 853 | + "__tsan_volatile_read2", |
|---|
| 854 | + "__tsan_volatile_read4", |
|---|
| 855 | + "__tsan_volatile_read8", |
|---|
| 856 | + "__tsan_volatile_read16", |
|---|
| 857 | + "__tsan_volatile_write1", |
|---|
| 858 | + "__tsan_volatile_write2", |
|---|
| 859 | + "__tsan_volatile_write4", |
|---|
| 860 | + "__tsan_volatile_write8", |
|---|
| 861 | + "__tsan_volatile_write16", |
|---|
| 848 | 862 | "__tsan_atomic8_load", |
|---|
| 849 | 863 | "__tsan_atomic16_load", |
|---|
| 850 | 864 | "__tsan_atomic32_load", |
|---|
| .. | .. |
|---|
| 895 | 909 | "__tsan_atomic64_compare_exchange_val", |
|---|
| 896 | 910 | "__tsan_atomic_thread_fence", |
|---|
| 897 | 911 | "__tsan_atomic_signal_fence", |
|---|
| 912 | + "__tsan_unaligned_read16", |
|---|
| 913 | + "__tsan_unaligned_write16", |
|---|
| 898 | 914 | /* KCOV */ |
|---|
| 899 | 915 | "write_comp_data", |
|---|
| 900 | 916 | "check_kcov_mode", |
|---|
| .. | .. |
|---|
| 973 | 989 | return 0; |
|---|
| 974 | 990 | } |
|---|
| 975 | 991 | |
|---|
| 992 | +/* |
|---|
| 993 | + * Symbols that replace INSN_CALL_DYNAMIC, every (tail) call to such a symbol |
|---|
| 994 | + * will be added to the .retpoline_sites section. |
|---|
| 995 | + */ |
|---|
| 976 | 996 | __weak bool arch_is_retpoline(struct symbol *sym) |
|---|
| 977 | 997 | { |
|---|
| 978 | 998 | return false; |
|---|
| 979 | 999 | } |
|---|
| 980 | 1000 | |
|---|
| 1001 | +/* |
|---|
| 1002 | + * Symbols that replace INSN_RETURN, every (tail) call to such a symbol |
|---|
| 1003 | + * will be added to the .return_sites section. |
|---|
| 1004 | + */ |
|---|
| 981 | 1005 | __weak bool arch_is_rethunk(struct symbol *sym) |
|---|
| 1006 | +{ |
|---|
| 1007 | + return false; |
|---|
| 1008 | +} |
|---|
| 1009 | + |
|---|
| 1010 | +/* |
|---|
| 1011 | + * Symbols that are embedded inside other instructions, because sometimes crazy |
|---|
| 1012 | + * code exists. These are mostly ignored for validation purposes. |
|---|
| 1013 | + */ |
|---|
| 1014 | +__weak bool arch_is_embedded_insn(struct symbol *sym) |
|---|
| 982 | 1015 | { |
|---|
| 983 | 1016 | return false; |
|---|
| 984 | 1017 | } |
|---|
| .. | .. |
|---|
| 1230 | 1263 | continue; |
|---|
| 1231 | 1264 | |
|---|
| 1232 | 1265 | /* |
|---|
| 1233 | | - * This is a special case for zen_untrain_ret(). |
|---|
| 1266 | + * This is a special case for retbleed_untrain_ret(). |
|---|
| 1234 | 1267 | * It jumps to __x86_return_thunk(), but objtool |
|---|
| 1235 | 1268 | * can't find the thunk's starting RET |
|---|
| 1236 | 1269 | * instruction, because the RET is also in the |
|---|
| 1237 | 1270 | * middle of another instruction. Objtool only |
|---|
| 1238 | 1271 | * knows about the outer instruction. |
|---|
| 1239 | 1272 | */ |
|---|
| 1240 | | - if (sym && sym->return_thunk) { |
|---|
| 1273 | + if (sym && sym->embedded_insn) { |
|---|
| 1241 | 1274 | add_return_call(file, insn, false); |
|---|
| 1242 | 1275 | continue; |
|---|
| 1243 | 1276 | } |
|---|
| .. | .. |
|---|
| 2039 | 2072 | if (arch_is_rethunk(func)) |
|---|
| 2040 | 2073 | func->return_thunk = true; |
|---|
| 2041 | 2074 | |
|---|
| 2075 | + if (arch_is_embedded_insn(func)) |
|---|
| 2076 | + func->embedded_insn = true; |
|---|
| 2077 | + |
|---|
| 2042 | 2078 | if (!strcmp(func->name, "__fentry__")) |
|---|
| 2043 | 2079 | func->fentry = true; |
|---|
| 2044 | 2080 | |
|---|
| .. | .. |
|---|
| 2148 | 2184 | return 0; |
|---|
| 2149 | 2185 | } |
|---|
| 2150 | 2186 | |
|---|
| 2151 | | -static bool is_fentry_call(struct instruction *insn) |
|---|
| 2187 | +static bool is_special_call(struct instruction *insn) |
|---|
| 2152 | 2188 | { |
|---|
| 2153 | | - if (insn->type == INSN_CALL && |
|---|
| 2154 | | - insn->call_dest && |
|---|
| 2155 | | - insn->call_dest->fentry) |
|---|
| 2156 | | - return true; |
|---|
| 2189 | + if (insn->type == INSN_CALL) { |
|---|
| 2190 | + struct symbol *dest = insn->call_dest; |
|---|
| 2191 | + |
|---|
| 2192 | + if (!dest) |
|---|
| 2193 | + return false; |
|---|
| 2194 | + |
|---|
| 2195 | + if (dest->fentry) |
|---|
| 2196 | + return true; |
|---|
| 2197 | + } |
|---|
| 2157 | 2198 | |
|---|
| 2158 | 2199 | return false; |
|---|
| 2159 | 2200 | } |
|---|
| .. | .. |
|---|
| 3027 | 3068 | if (ret) |
|---|
| 3028 | 3069 | return ret; |
|---|
| 3029 | 3070 | |
|---|
| 3030 | | - if (!no_fp && func && !is_fentry_call(insn) && |
|---|
| 3071 | + if (!no_fp && func && !is_special_call(insn) && |
|---|
| 3031 | 3072 | !has_valid_stack_frame(&state)) { |
|---|
| 3032 | 3073 | WARN_FUNC("call without frame pointer save/setup", |
|---|
| 3033 | 3074 | sec, insn->offset); |
|---|