This source file includes following definitions.
- find_insn
- next_insn_same_sec
- next_insn_same_func
- is_sibling_call
- __dead_end_function
- dead_end_function
- clear_insn_state
- decode_instructions
- add_dead_ends
- add_ignores
- add_uaccess_safe
- add_ignore_alternatives
- add_jump_destinations
- add_call_destinations
- handle_group_alt
- handle_jump_alt
- add_special_section_alts
- add_jump_table
- find_jump_table
- mark_func_jump_tables
- add_func_jump_tables
- add_jump_table_alts
- read_unwind_hints
- read_retpoline_hints
- mark_rodata
- decode_sections
- is_fentry_call
- has_modified_stack_frame
- has_valid_stack_frame
- update_insn_state_regs
- save_reg
- restore_reg
- update_insn_state
- insn_state_match
- func_uaccess_safe
- call_dest_name
- validate_call
- validate_sibling_call
- validate_branch
- validate_unwind_hints
- validate_retpoline
- is_kasan_insn
- is_ubsan_insn
- ignore_unreachable_insn
- validate_functions
- validate_reachable_instructions
- cleanup
- check
1
2
3
4
5
6 #include <string.h>
7 #include <stdlib.h>
8
9 #include "builtin.h"
10 #include "check.h"
11 #include "elf.h"
12 #include "special.h"
13 #include "arch.h"
14 #include "warn.h"
15
16 #include <linux/hashtable.h>
17 #include <linux/kernel.h>
18
19 #define FAKE_JUMP_OFFSET -1
20
21 #define C_JUMP_TABLE_SECTION ".rodata..c_jump_table"
22
23 struct alternative {
24 struct list_head list;
25 struct instruction *insn;
26 bool skip_orig;
27 };
28
29 const char *objname;
30 struct cfi_state initial_func_cfi;
31
32 struct instruction *find_insn(struct objtool_file *file,
33 struct section *sec, unsigned long offset)
34 {
35 struct instruction *insn;
36
37 hash_for_each_possible(file->insn_hash, insn, hash, offset)
38 if (insn->sec == sec && insn->offset == offset)
39 return insn;
40
41 return NULL;
42 }
43
44 static struct instruction *next_insn_same_sec(struct objtool_file *file,
45 struct instruction *insn)
46 {
47 struct instruction *next = list_next_entry(insn, list);
48
49 if (!next || &next->list == &file->insn_list || next->sec != insn->sec)
50 return NULL;
51
52 return next;
53 }
54
55 static struct instruction *next_insn_same_func(struct objtool_file *file,
56 struct instruction *insn)
57 {
58 struct instruction *next = list_next_entry(insn, list);
59 struct symbol *func = insn->func;
60
61 if (!func)
62 return NULL;
63
64 if (&next->list != &file->insn_list && next->func == func)
65 return next;
66
67
68 if (func == func->cfunc)
69 return NULL;
70
71
72 return find_insn(file, func->cfunc->sec, func->cfunc->offset);
73 }
74
75 #define func_for_each_insn_all(file, func, insn) \
76 for (insn = find_insn(file, func->sec, func->offset); \
77 insn; \
78 insn = next_insn_same_func(file, insn))
79
80 #define func_for_each_insn(file, func, insn) \
81 for (insn = find_insn(file, func->sec, func->offset); \
82 insn && &insn->list != &file->insn_list && \
83 insn->sec == func->sec && \
84 insn->offset < func->offset + func->len; \
85 insn = list_next_entry(insn, list))
86
87 #define func_for_each_insn_continue_reverse(file, func, insn) \
88 for (insn = list_prev_entry(insn, list); \
89 &insn->list != &file->insn_list && \
90 insn->sec == func->sec && insn->offset >= func->offset; \
91 insn = list_prev_entry(insn, list))
92
93 #define sec_for_each_insn_from(file, insn) \
94 for (; insn; insn = next_insn_same_sec(file, insn))
95
96 #define sec_for_each_insn_continue(file, insn) \
97 for (insn = next_insn_same_sec(file, insn); insn; \
98 insn = next_insn_same_sec(file, insn))
99
100 static bool is_sibling_call(struct instruction *insn)
101 {
102
103 if (insn->type == INSN_JUMP_DYNAMIC)
104 return list_empty(&insn->alts);
105
106 if (insn->type != INSN_JUMP_CONDITIONAL &&
107 insn->type != INSN_JUMP_UNCONDITIONAL)
108 return false;
109
110
111 return !!insn->call_dest;
112 }
113
114
115
116
117
118
119
120
121
122
123 static bool __dead_end_function(struct objtool_file *file, struct symbol *func,
124 int recursion)
125 {
126 int i;
127 struct instruction *insn;
128 bool empty = true;
129
130
131
132
133
134 static const char * const global_noreturns[] = {
135 "__stack_chk_fail",
136 "panic",
137 "do_exit",
138 "do_task_dead",
139 "__module_put_and_exit",
140 "complete_and_exit",
141 "__reiserfs_panic",
142 "lbug_with_loc",
143 "fortify_panic",
144 "usercopy_abort",
145 "machine_real_restart",
146 "rewind_stack_do_exit",
147 };
148
149 if (!func)
150 return false;
151
152 if (func->bind == STB_WEAK)
153 return false;
154
155 if (func->bind == STB_GLOBAL)
156 for (i = 0; i < ARRAY_SIZE(global_noreturns); i++)
157 if (!strcmp(func->name, global_noreturns[i]))
158 return true;
159
160 if (!func->len)
161 return false;
162
163 insn = find_insn(file, func->sec, func->offset);
164 if (!insn->func)
165 return false;
166
167 func_for_each_insn_all(file, func, insn) {
168 empty = false;
169
170 if (insn->type == INSN_RETURN)
171 return false;
172 }
173
174 if (empty)
175 return false;
176
177
178
179
180
181
182 func_for_each_insn_all(file, func, insn) {
183 if (is_sibling_call(insn)) {
184 struct instruction *dest = insn->jump_dest;
185
186 if (!dest)
187
188 return false;
189
190
191 if (recursion == 5) {
192
193
194
195
196
197 return false;
198 }
199
200 return __dead_end_function(file, dest->func, recursion+1);
201 }
202 }
203
204 return true;
205 }
206
207 static bool dead_end_function(struct objtool_file *file, struct symbol *func)
208 {
209 return __dead_end_function(file, func, 0);
210 }
211
212 static void clear_insn_state(struct insn_state *state)
213 {
214 int i;
215
216 memset(state, 0, sizeof(*state));
217 state->cfa.base = CFI_UNDEFINED;
218 for (i = 0; i < CFI_NUM_REGS; i++) {
219 state->regs[i].base = CFI_UNDEFINED;
220 state->vals[i].base = CFI_UNDEFINED;
221 }
222 state->drap_reg = CFI_UNDEFINED;
223 state->drap_offset = -1;
224 }
225
226
227
228
229
230 static int decode_instructions(struct objtool_file *file)
231 {
232 struct section *sec;
233 struct symbol *func;
234 unsigned long offset;
235 struct instruction *insn;
236 int ret;
237
238 for_each_sec(file, sec) {
239
240 if (!(sec->sh.sh_flags & SHF_EXECINSTR))
241 continue;
242
243 if (strcmp(sec->name, ".altinstr_replacement") &&
244 strcmp(sec->name, ".altinstr_aux") &&
245 strncmp(sec->name, ".discard.", 9))
246 sec->text = true;
247
248 for (offset = 0; offset < sec->len; offset += insn->len) {
249 insn = malloc(sizeof(*insn));
250 if (!insn) {
251 WARN("malloc failed");
252 return -1;
253 }
254 memset(insn, 0, sizeof(*insn));
255 INIT_LIST_HEAD(&insn->alts);
256 clear_insn_state(&insn->state);
257
258 insn->sec = sec;
259 insn->offset = offset;
260
261 ret = arch_decode_instruction(file->elf, sec, offset,
262 sec->len - offset,
263 &insn->len, &insn->type,
264 &insn->immediate,
265 &insn->stack_op);
266 if (ret)
267 goto err;
268
269 hash_add(file->insn_hash, &insn->hash, insn->offset);
270 list_add_tail(&insn->list, &file->insn_list);
271 }
272
273 list_for_each_entry(func, &sec->symbol_list, list) {
274 if (func->type != STT_FUNC || func->alias != func)
275 continue;
276
277 if (!find_insn(file, sec, func->offset)) {
278 WARN("%s(): can't find starting instruction",
279 func->name);
280 return -1;
281 }
282
283 func_for_each_insn(file, func, insn)
284 insn->func = func;
285 }
286 }
287
288 return 0;
289
290 err:
291 free(insn);
292 return ret;
293 }
294
295
296
297
298 static int add_dead_ends(struct objtool_file *file)
299 {
300 struct section *sec;
301 struct rela *rela;
302 struct instruction *insn;
303 bool found;
304
305
306
307
308
309 for_each_insn(file, insn)
310 if (insn->type == INSN_BUG)
311 insn->dead_end = true;
312
313
314
315
316 sec = find_section_by_name(file->elf, ".rela.discard.unreachable");
317 if (!sec)
318 goto reachable;
319
320 list_for_each_entry(rela, &sec->rela_list, list) {
321 if (rela->sym->type != STT_SECTION) {
322 WARN("unexpected relocation symbol type in %s", sec->name);
323 return -1;
324 }
325 insn = find_insn(file, rela->sym->sec, rela->addend);
326 if (insn)
327 insn = list_prev_entry(insn, list);
328 else if (rela->addend == rela->sym->sec->len) {
329 found = false;
330 list_for_each_entry_reverse(insn, &file->insn_list, list) {
331 if (insn->sec == rela->sym->sec) {
332 found = true;
333 break;
334 }
335 }
336
337 if (!found) {
338 WARN("can't find unreachable insn at %s+0x%x",
339 rela->sym->sec->name, rela->addend);
340 return -1;
341 }
342 } else {
343 WARN("can't find unreachable insn at %s+0x%x",
344 rela->sym->sec->name, rela->addend);
345 return -1;
346 }
347
348 insn->dead_end = true;
349 }
350
351 reachable:
352
353
354
355
356
357
358 sec = find_section_by_name(file->elf, ".rela.discard.reachable");
359 if (!sec)
360 return 0;
361
362 list_for_each_entry(rela, &sec->rela_list, list) {
363 if (rela->sym->type != STT_SECTION) {
364 WARN("unexpected relocation symbol type in %s", sec->name);
365 return -1;
366 }
367 insn = find_insn(file, rela->sym->sec, rela->addend);
368 if (insn)
369 insn = list_prev_entry(insn, list);
370 else if (rela->addend == rela->sym->sec->len) {
371 found = false;
372 list_for_each_entry_reverse(insn, &file->insn_list, list) {
373 if (insn->sec == rela->sym->sec) {
374 found = true;
375 break;
376 }
377 }
378
379 if (!found) {
380 WARN("can't find reachable insn at %s+0x%x",
381 rela->sym->sec->name, rela->addend);
382 return -1;
383 }
384 } else {
385 WARN("can't find reachable insn at %s+0x%x",
386 rela->sym->sec->name, rela->addend);
387 return -1;
388 }
389
390 insn->dead_end = false;
391 }
392
393 return 0;
394 }
395
396
397
398
399 static void add_ignores(struct objtool_file *file)
400 {
401 struct instruction *insn;
402 struct section *sec;
403 struct symbol *func;
404 struct rela *rela;
405
406 sec = find_section_by_name(file->elf, ".rela.discard.func_stack_frame_non_standard");
407 if (!sec)
408 return;
409
410 list_for_each_entry(rela, &sec->rela_list, list) {
411 switch (rela->sym->type) {
412 case STT_FUNC:
413 func = rela->sym;
414 break;
415
416 case STT_SECTION:
417 func = find_symbol_by_offset(rela->sym->sec, rela->addend);
418 if (!func || func->type != STT_FUNC)
419 continue;
420 break;
421
422 default:
423 WARN("unexpected relocation symbol type in %s: %d", sec->name, rela->sym->type);
424 continue;
425 }
426
427 func_for_each_insn_all(file, func, insn)
428 insn->ignore = true;
429 }
430 }
431
432
433
434
435
436
437
438
439 static const char *uaccess_safe_builtin[] = {
440
441 "kasan_report",
442 "check_memory_region",
443
444 "__asan_loadN_noabort",
445 "__asan_load1_noabort",
446 "__asan_load2_noabort",
447 "__asan_load4_noabort",
448 "__asan_load8_noabort",
449 "__asan_load16_noabort",
450 "__asan_storeN_noabort",
451 "__asan_store1_noabort",
452 "__asan_store2_noabort",
453 "__asan_store4_noabort",
454 "__asan_store8_noabort",
455 "__asan_store16_noabort",
456
457 "__asan_report_load_n_noabort",
458 "__asan_report_load1_noabort",
459 "__asan_report_load2_noabort",
460 "__asan_report_load4_noabort",
461 "__asan_report_load8_noabort",
462 "__asan_report_load16_noabort",
463 "__asan_report_store_n_noabort",
464 "__asan_report_store1_noabort",
465 "__asan_report_store2_noabort",
466 "__asan_report_store4_noabort",
467 "__asan_report_store8_noabort",
468 "__asan_report_store16_noabort",
469
470 "write_comp_data",
471 "__sanitizer_cov_trace_pc",
472 "__sanitizer_cov_trace_const_cmp1",
473 "__sanitizer_cov_trace_const_cmp2",
474 "__sanitizer_cov_trace_const_cmp4",
475 "__sanitizer_cov_trace_const_cmp8",
476 "__sanitizer_cov_trace_cmp1",
477 "__sanitizer_cov_trace_cmp2",
478 "__sanitizer_cov_trace_cmp4",
479 "__sanitizer_cov_trace_cmp8",
480
481 "ubsan_type_mismatch_common",
482 "__ubsan_handle_type_mismatch",
483 "__ubsan_handle_type_mismatch_v1",
484 "__ubsan_handle_shift_out_of_bounds",
485
486 "csum_partial_copy_generic",
487 "__memcpy_mcsafe",
488 "mcsafe_handle_tail",
489 "ftrace_likely_update",
490 NULL
491 };
492
493 static void add_uaccess_safe(struct objtool_file *file)
494 {
495 struct symbol *func;
496 const char **name;
497
498 if (!uaccess)
499 return;
500
501 for (name = uaccess_safe_builtin; *name; name++) {
502 func = find_symbol_by_name(file->elf, *name);
503 if (!func)
504 continue;
505
506 func->uaccess_safe = true;
507 }
508 }
509
510
511
512
513
514
515
516 static int add_ignore_alternatives(struct objtool_file *file)
517 {
518 struct section *sec;
519 struct rela *rela;
520 struct instruction *insn;
521
522 sec = find_section_by_name(file->elf, ".rela.discard.ignore_alts");
523 if (!sec)
524 return 0;
525
526 list_for_each_entry(rela, &sec->rela_list, list) {
527 if (rela->sym->type != STT_SECTION) {
528 WARN("unexpected relocation symbol type in %s", sec->name);
529 return -1;
530 }
531
532 insn = find_insn(file, rela->sym->sec, rela->addend);
533 if (!insn) {
534 WARN("bad .discard.ignore_alts entry");
535 return -1;
536 }
537
538 insn->ignore_alts = true;
539 }
540
541 return 0;
542 }
543
544
545
546
547 static int add_jump_destinations(struct objtool_file *file)
548 {
549 struct instruction *insn;
550 struct rela *rela;
551 struct section *dest_sec;
552 unsigned long dest_off;
553
554 for_each_insn(file, insn) {
555 if (insn->type != INSN_JUMP_CONDITIONAL &&
556 insn->type != INSN_JUMP_UNCONDITIONAL)
557 continue;
558
559 if (insn->ignore || insn->offset == FAKE_JUMP_OFFSET)
560 continue;
561
562 rela = find_rela_by_dest_range(insn->sec, insn->offset,
563 insn->len);
564 if (!rela) {
565 dest_sec = insn->sec;
566 dest_off = insn->offset + insn->len + insn->immediate;
567 } else if (rela->sym->type == STT_SECTION) {
568 dest_sec = rela->sym->sec;
569 dest_off = rela->addend + 4;
570 } else if (rela->sym->sec->idx) {
571 dest_sec = rela->sym->sec;
572 dest_off = rela->sym->sym.st_value + rela->addend + 4;
573 } else if (strstr(rela->sym->name, "_indirect_thunk_")) {
574
575
576
577
578 if (insn->type == INSN_JUMP_UNCONDITIONAL)
579 insn->type = INSN_JUMP_DYNAMIC;
580 else
581 insn->type = INSN_JUMP_DYNAMIC_CONDITIONAL;
582
583 insn->retpoline_safe = true;
584 continue;
585 } else {
586
587 insn->call_dest = rela->sym;
588 continue;
589 }
590
591 insn->jump_dest = find_insn(file, dest_sec, dest_off);
592 if (!insn->jump_dest) {
593
594
595
596
597
598
599 if (!strcmp(insn->sec->name, ".altinstr_replacement"))
600 continue;
601
602 WARN_FUNC("can't find jump dest instruction at %s+0x%lx",
603 insn->sec, insn->offset, dest_sec->name,
604 dest_off);
605 return -1;
606 }
607
608
609
610
611 if (insn->func && insn->jump_dest->func &&
612 insn->func != insn->jump_dest->func) {
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629 if (!strstr(insn->func->name, ".cold.") &&
630 strstr(insn->jump_dest->func->name, ".cold.")) {
631 insn->func->cfunc = insn->jump_dest->func;
632 insn->jump_dest->func->pfunc = insn->func;
633
634 } else if (insn->jump_dest->func->pfunc != insn->func->pfunc &&
635 insn->jump_dest->offset == insn->jump_dest->func->offset) {
636
637
638 insn->call_dest = insn->jump_dest->func;
639 }
640 }
641 }
642
643 return 0;
644 }
645
646
647
648
649 static int add_call_destinations(struct objtool_file *file)
650 {
651 struct instruction *insn;
652 unsigned long dest_off;
653 struct rela *rela;
654
655 for_each_insn(file, insn) {
656 if (insn->type != INSN_CALL)
657 continue;
658
659 rela = find_rela_by_dest_range(insn->sec, insn->offset,
660 insn->len);
661 if (!rela) {
662 dest_off = insn->offset + insn->len + insn->immediate;
663 insn->call_dest = find_symbol_by_offset(insn->sec,
664 dest_off);
665
666 if (!insn->call_dest && !insn->ignore) {
667 WARN_FUNC("unsupported intra-function call",
668 insn->sec, insn->offset);
669 if (retpoline)
670 WARN("If this is a retpoline, please patch it in with alternatives and annotate it with ANNOTATE_NOSPEC_ALTERNATIVE.");
671 return -1;
672 }
673
674 } else if (rela->sym->type == STT_SECTION) {
675 insn->call_dest = find_symbol_by_offset(rela->sym->sec,
676 rela->addend+4);
677 if (!insn->call_dest ||
678 insn->call_dest->type != STT_FUNC) {
679 WARN_FUNC("can't find call dest symbol at %s+0x%x",
680 insn->sec, insn->offset,
681 rela->sym->sec->name,
682 rela->addend + 4);
683 return -1;
684 }
685 } else
686 insn->call_dest = rela->sym;
687 }
688
689 return 0;
690 }
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709 static int handle_group_alt(struct objtool_file *file,
710 struct special_alt *special_alt,
711 struct instruction *orig_insn,
712 struct instruction **new_insn)
713 {
714 struct instruction *last_orig_insn, *last_new_insn, *insn, *fake_jump = NULL;
715 unsigned long dest_off;
716
717 last_orig_insn = NULL;
718 insn = orig_insn;
719 sec_for_each_insn_from(file, insn) {
720 if (insn->offset >= special_alt->orig_off + special_alt->orig_len)
721 break;
722
723 insn->alt_group = true;
724 last_orig_insn = insn;
725 }
726
727 if (next_insn_same_sec(file, last_orig_insn)) {
728 fake_jump = malloc(sizeof(*fake_jump));
729 if (!fake_jump) {
730 WARN("malloc failed");
731 return -1;
732 }
733 memset(fake_jump, 0, sizeof(*fake_jump));
734 INIT_LIST_HEAD(&fake_jump->alts);
735 clear_insn_state(&fake_jump->state);
736
737 fake_jump->sec = special_alt->new_sec;
738 fake_jump->offset = FAKE_JUMP_OFFSET;
739 fake_jump->type = INSN_JUMP_UNCONDITIONAL;
740 fake_jump->jump_dest = list_next_entry(last_orig_insn, list);
741 fake_jump->func = orig_insn->func;
742 }
743
744 if (!special_alt->new_len) {
745 if (!fake_jump) {
746 WARN("%s: empty alternative at end of section",
747 special_alt->orig_sec->name);
748 return -1;
749 }
750
751 *new_insn = fake_jump;
752 return 0;
753 }
754
755 last_new_insn = NULL;
756 insn = *new_insn;
757 sec_for_each_insn_from(file, insn) {
758 if (insn->offset >= special_alt->new_off + special_alt->new_len)
759 break;
760
761 last_new_insn = insn;
762
763 insn->ignore = orig_insn->ignore_alts;
764 insn->func = orig_insn->func;
765
766 if (insn->type != INSN_JUMP_CONDITIONAL &&
767 insn->type != INSN_JUMP_UNCONDITIONAL)
768 continue;
769
770 if (!insn->immediate)
771 continue;
772
773 dest_off = insn->offset + insn->len + insn->immediate;
774 if (dest_off == special_alt->new_off + special_alt->new_len) {
775 if (!fake_jump) {
776 WARN("%s: alternative jump to end of section",
777 special_alt->orig_sec->name);
778 return -1;
779 }
780 insn->jump_dest = fake_jump;
781 }
782
783 if (!insn->jump_dest) {
784 WARN_FUNC("can't find alternative jump destination",
785 insn->sec, insn->offset);
786 return -1;
787 }
788 }
789
790 if (!last_new_insn) {
791 WARN_FUNC("can't find last new alternative instruction",
792 special_alt->new_sec, special_alt->new_off);
793 return -1;
794 }
795
796 if (fake_jump)
797 list_add(&fake_jump->list, &last_new_insn->list);
798
799 return 0;
800 }
801
802
803
804
805
806
807 static int handle_jump_alt(struct objtool_file *file,
808 struct special_alt *special_alt,
809 struct instruction *orig_insn,
810 struct instruction **new_insn)
811 {
812 if (orig_insn->type == INSN_NOP)
813 return 0;
814
815 if (orig_insn->type != INSN_JUMP_UNCONDITIONAL) {
816 WARN_FUNC("unsupported instruction at jump label",
817 orig_insn->sec, orig_insn->offset);
818 return -1;
819 }
820
821 *new_insn = list_next_entry(orig_insn, list);
822 return 0;
823 }
824
825
826
827
828
829
830
831 static int add_special_section_alts(struct objtool_file *file)
832 {
833 struct list_head special_alts;
834 struct instruction *orig_insn, *new_insn;
835 struct special_alt *special_alt, *tmp;
836 struct alternative *alt;
837 int ret;
838
839 ret = special_get_alts(file->elf, &special_alts);
840 if (ret)
841 return ret;
842
843 list_for_each_entry_safe(special_alt, tmp, &special_alts, list) {
844
845 orig_insn = find_insn(file, special_alt->orig_sec,
846 special_alt->orig_off);
847 if (!orig_insn) {
848 WARN_FUNC("special: can't find orig instruction",
849 special_alt->orig_sec, special_alt->orig_off);
850 ret = -1;
851 goto out;
852 }
853
854 new_insn = NULL;
855 if (!special_alt->group || special_alt->new_len) {
856 new_insn = find_insn(file, special_alt->new_sec,
857 special_alt->new_off);
858 if (!new_insn) {
859 WARN_FUNC("special: can't find new instruction",
860 special_alt->new_sec,
861 special_alt->new_off);
862 ret = -1;
863 goto out;
864 }
865 }
866
867 if (special_alt->group) {
868 ret = handle_group_alt(file, special_alt, orig_insn,
869 &new_insn);
870 if (ret)
871 goto out;
872 } else if (special_alt->jump_or_nop) {
873 ret = handle_jump_alt(file, special_alt, orig_insn,
874 &new_insn);
875 if (ret)
876 goto out;
877 }
878
879 alt = malloc(sizeof(*alt));
880 if (!alt) {
881 WARN("malloc failed");
882 ret = -1;
883 goto out;
884 }
885
886 alt->insn = new_insn;
887 alt->skip_orig = special_alt->skip_orig;
888 orig_insn->ignore_alts |= special_alt->skip_alt;
889 list_add_tail(&alt->list, &orig_insn->alts);
890
891 list_del(&special_alt->list);
892 free(special_alt);
893 }
894
895 out:
896 return ret;
897 }
898
899 static int add_jump_table(struct objtool_file *file, struct instruction *insn,
900 struct rela *table)
901 {
902 struct rela *rela = table;
903 struct instruction *dest_insn;
904 struct alternative *alt;
905 struct symbol *pfunc = insn->func->pfunc;
906 unsigned int prev_offset = 0;
907
908
909
910
911
912 list_for_each_entry_from(rela, &table->sec->rela_list, list) {
913
914
915 if (rela != table && rela->jump_table_start)
916 break;
917
918
919 if (prev_offset && rela->offset != prev_offset + 8)
920 break;
921
922
923 if (rela->sym->sec == pfunc->sec &&
924 rela->addend == pfunc->offset)
925 break;
926
927 dest_insn = find_insn(file, rela->sym->sec, rela->addend);
928 if (!dest_insn)
929 break;
930
931
932 if (!dest_insn->func || dest_insn->func->pfunc != pfunc)
933 break;
934
935 alt = malloc(sizeof(*alt));
936 if (!alt) {
937 WARN("malloc failed");
938 return -1;
939 }
940
941 alt->insn = dest_insn;
942 list_add_tail(&alt->list, &insn->alts);
943 prev_offset = rela->offset;
944 }
945
946 if (!prev_offset) {
947 WARN_FUNC("can't find switch jump table",
948 insn->sec, insn->offset);
949 return -1;
950 }
951
952 return 0;
953 }
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998 static struct rela *find_jump_table(struct objtool_file *file,
999 struct symbol *func,
1000 struct instruction *insn)
1001 {
1002 struct rela *text_rela, *table_rela;
1003 struct instruction *orig_insn = insn;
1004 struct section *table_sec;
1005 unsigned long table_offset;
1006
1007
1008
1009
1010
1011
1012 for (;
1013 &insn->list != &file->insn_list && insn->func && insn->func->pfunc == func;
1014 insn = insn->first_jump_src ?: list_prev_entry(insn, list)) {
1015
1016 if (insn != orig_insn && insn->type == INSN_JUMP_DYNAMIC)
1017 break;
1018
1019
1020 if (insn->type == INSN_JUMP_UNCONDITIONAL &&
1021 insn->jump_dest &&
1022 (insn->jump_dest->offset <= insn->offset ||
1023 insn->jump_dest->offset > orig_insn->offset))
1024 break;
1025
1026
1027 text_rela = find_rela_by_dest_range(insn->sec, insn->offset,
1028 insn->len);
1029 if (!text_rela || text_rela->sym->type != STT_SECTION ||
1030 !text_rela->sym->sec->rodata)
1031 continue;
1032
1033 table_offset = text_rela->addend;
1034 table_sec = text_rela->sym->sec;
1035
1036 if (text_rela->type == R_X86_64_PC32)
1037 table_offset += 4;
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048 if (find_symbol_containing(table_sec, table_offset) &&
1049 strcmp(table_sec->name, C_JUMP_TABLE_SECTION))
1050 continue;
1051
1052
1053 table_rela = find_rela_by_dest(table_sec, table_offset);
1054 if (!table_rela)
1055 continue;
1056
1057
1058
1059
1060
1061
1062 if (text_rela->type == R_X86_64_PC32)
1063 file->ignore_unreachables = true;
1064
1065 return table_rela;
1066 }
1067
1068 return NULL;
1069 }
1070
1071
1072
1073
1074
1075 static void mark_func_jump_tables(struct objtool_file *file,
1076 struct symbol *func)
1077 {
1078 struct instruction *insn, *last = NULL;
1079 struct rela *rela;
1080
1081 func_for_each_insn_all(file, func, insn) {
1082 if (!last)
1083 last = insn;
1084
1085
1086
1087
1088
1089
1090 if (insn->type == INSN_JUMP_UNCONDITIONAL && insn->jump_dest &&
1091 insn->offset > last->offset &&
1092 insn->jump_dest->offset > insn->offset &&
1093 !insn->jump_dest->first_jump_src) {
1094
1095 insn->jump_dest->first_jump_src = insn;
1096 last = insn->jump_dest;
1097 }
1098
1099 if (insn->type != INSN_JUMP_DYNAMIC)
1100 continue;
1101
1102 rela = find_jump_table(file, func, insn);
1103 if (rela) {
1104 rela->jump_table_start = true;
1105 insn->jump_table = rela;
1106 }
1107 }
1108 }
1109
1110 static int add_func_jump_tables(struct objtool_file *file,
1111 struct symbol *func)
1112 {
1113 struct instruction *insn;
1114 int ret;
1115
1116 func_for_each_insn_all(file, func, insn) {
1117 if (!insn->jump_table)
1118 continue;
1119
1120 ret = add_jump_table(file, insn, insn->jump_table);
1121 if (ret)
1122 return ret;
1123 }
1124
1125 return 0;
1126 }
1127
1128
1129
1130
1131
1132
1133 static int add_jump_table_alts(struct objtool_file *file)
1134 {
1135 struct section *sec;
1136 struct symbol *func;
1137 int ret;
1138
1139 if (!file->rodata)
1140 return 0;
1141
1142 for_each_sec(file, sec) {
1143 list_for_each_entry(func, &sec->symbol_list, list) {
1144 if (func->type != STT_FUNC)
1145 continue;
1146
1147 mark_func_jump_tables(file, func);
1148 ret = add_func_jump_tables(file, func);
1149 if (ret)
1150 return ret;
1151 }
1152 }
1153
1154 return 0;
1155 }
1156
1157 static int read_unwind_hints(struct objtool_file *file)
1158 {
1159 struct section *sec, *relasec;
1160 struct rela *rela;
1161 struct unwind_hint *hint;
1162 struct instruction *insn;
1163 struct cfi_reg *cfa;
1164 int i;
1165
1166 sec = find_section_by_name(file->elf, ".discard.unwind_hints");
1167 if (!sec)
1168 return 0;
1169
1170 relasec = sec->rela;
1171 if (!relasec) {
1172 WARN("missing .rela.discard.unwind_hints section");
1173 return -1;
1174 }
1175
1176 if (sec->len % sizeof(struct unwind_hint)) {
1177 WARN("struct unwind_hint size mismatch");
1178 return -1;
1179 }
1180
1181 file->hints = true;
1182
1183 for (i = 0; i < sec->len / sizeof(struct unwind_hint); i++) {
1184 hint = (struct unwind_hint *)sec->data->d_buf + i;
1185
1186 rela = find_rela_by_dest(sec, i * sizeof(*hint));
1187 if (!rela) {
1188 WARN("can't find rela for unwind_hints[%d]", i);
1189 return -1;
1190 }
1191
1192 insn = find_insn(file, rela->sym->sec, rela->addend);
1193 if (!insn) {
1194 WARN("can't find insn for unwind_hints[%d]", i);
1195 return -1;
1196 }
1197
1198 cfa = &insn->state.cfa;
1199
1200 if (hint->type == UNWIND_HINT_TYPE_SAVE) {
1201 insn->save = true;
1202 continue;
1203
1204 } else if (hint->type == UNWIND_HINT_TYPE_RESTORE) {
1205 insn->restore = true;
1206 insn->hint = true;
1207 continue;
1208 }
1209
1210 insn->hint = true;
1211
1212 switch (hint->sp_reg) {
1213 case ORC_REG_UNDEFINED:
1214 cfa->base = CFI_UNDEFINED;
1215 break;
1216 case ORC_REG_SP:
1217 cfa->base = CFI_SP;
1218 break;
1219 case ORC_REG_BP:
1220 cfa->base = CFI_BP;
1221 break;
1222 case ORC_REG_SP_INDIRECT:
1223 cfa->base = CFI_SP_INDIRECT;
1224 break;
1225 case ORC_REG_R10:
1226 cfa->base = CFI_R10;
1227 break;
1228 case ORC_REG_R13:
1229 cfa->base = CFI_R13;
1230 break;
1231 case ORC_REG_DI:
1232 cfa->base = CFI_DI;
1233 break;
1234 case ORC_REG_DX:
1235 cfa->base = CFI_DX;
1236 break;
1237 default:
1238 WARN_FUNC("unsupported unwind_hint sp base reg %d",
1239 insn->sec, insn->offset, hint->sp_reg);
1240 return -1;
1241 }
1242
1243 cfa->offset = hint->sp_offset;
1244 insn->state.type = hint->type;
1245 insn->state.end = hint->end;
1246 }
1247
1248 return 0;
1249 }
1250
1251 static int read_retpoline_hints(struct objtool_file *file)
1252 {
1253 struct section *sec;
1254 struct instruction *insn;
1255 struct rela *rela;
1256
1257 sec = find_section_by_name(file->elf, ".rela.discard.retpoline_safe");
1258 if (!sec)
1259 return 0;
1260
1261 list_for_each_entry(rela, &sec->rela_list, list) {
1262 if (rela->sym->type != STT_SECTION) {
1263 WARN("unexpected relocation symbol type in %s", sec->name);
1264 return -1;
1265 }
1266
1267 insn = find_insn(file, rela->sym->sec, rela->addend);
1268 if (!insn) {
1269 WARN("bad .discard.retpoline_safe entry");
1270 return -1;
1271 }
1272
1273 if (insn->type != INSN_JUMP_DYNAMIC &&
1274 insn->type != INSN_CALL_DYNAMIC) {
1275 WARN_FUNC("retpoline_safe hint not an indirect jump/call",
1276 insn->sec, insn->offset);
1277 return -1;
1278 }
1279
1280 insn->retpoline_safe = true;
1281 }
1282
1283 return 0;
1284 }
1285
1286 static void mark_rodata(struct objtool_file *file)
1287 {
1288 struct section *sec;
1289 bool found = false;
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301 for_each_sec(file, sec) {
1302 if ((!strncmp(sec->name, ".rodata", 7) && !strstr(sec->name, ".str1.")) ||
1303 !strcmp(sec->name, C_JUMP_TABLE_SECTION)) {
1304 sec->rodata = true;
1305 found = true;
1306 }
1307 }
1308
1309 file->rodata = found;
1310 }
1311
1312 static int decode_sections(struct objtool_file *file)
1313 {
1314 int ret;
1315
1316 mark_rodata(file);
1317
1318 ret = decode_instructions(file);
1319 if (ret)
1320 return ret;
1321
1322 ret = add_dead_ends(file);
1323 if (ret)
1324 return ret;
1325
1326 add_ignores(file);
1327 add_uaccess_safe(file);
1328
1329 ret = add_ignore_alternatives(file);
1330 if (ret)
1331 return ret;
1332
1333 ret = add_jump_destinations(file);
1334 if (ret)
1335 return ret;
1336
1337 ret = add_special_section_alts(file);
1338 if (ret)
1339 return ret;
1340
1341 ret = add_call_destinations(file);
1342 if (ret)
1343 return ret;
1344
1345 ret = add_jump_table_alts(file);
1346 if (ret)
1347 return ret;
1348
1349 ret = read_unwind_hints(file);
1350 if (ret)
1351 return ret;
1352
1353 ret = read_retpoline_hints(file);
1354 if (ret)
1355 return ret;
1356
1357 return 0;
1358 }
1359
1360 static bool is_fentry_call(struct instruction *insn)
1361 {
1362 if (insn->type == INSN_CALL &&
1363 insn->call_dest->type == STT_NOTYPE &&
1364 !strcmp(insn->call_dest->name, "__fentry__"))
1365 return true;
1366
1367 return false;
1368 }
1369
1370 static bool has_modified_stack_frame(struct insn_state *state)
1371 {
1372 int i;
1373
1374 if (state->cfa.base != initial_func_cfi.cfa.base ||
1375 state->cfa.offset != initial_func_cfi.cfa.offset ||
1376 state->stack_size != initial_func_cfi.cfa.offset ||
1377 state->drap)
1378 return true;
1379
1380 for (i = 0; i < CFI_NUM_REGS; i++)
1381 if (state->regs[i].base != initial_func_cfi.regs[i].base ||
1382 state->regs[i].offset != initial_func_cfi.regs[i].offset)
1383 return true;
1384
1385 return false;
1386 }
1387
1388 static bool has_valid_stack_frame(struct insn_state *state)
1389 {
1390 if (state->cfa.base == CFI_BP && state->regs[CFI_BP].base == CFI_CFA &&
1391 state->regs[CFI_BP].offset == -16)
1392 return true;
1393
1394 if (state->drap && state->regs[CFI_BP].base == CFI_BP)
1395 return true;
1396
1397 return false;
1398 }
1399
1400 static int update_insn_state_regs(struct instruction *insn, struct insn_state *state)
1401 {
1402 struct cfi_reg *cfa = &state->cfa;
1403 struct stack_op *op = &insn->stack_op;
1404
1405 if (cfa->base != CFI_SP && cfa->base != CFI_SP_INDIRECT)
1406 return 0;
1407
1408
1409 if (op->dest.type == OP_DEST_PUSH || op->dest.type == OP_DEST_PUSHF)
1410 cfa->offset += 8;
1411
1412
1413 if (op->src.type == OP_SRC_POP || op->src.type == OP_SRC_POPF)
1414 cfa->offset -= 8;
1415
1416
1417 if (op->dest.type == OP_DEST_REG && op->src.type == OP_SRC_ADD &&
1418 op->dest.reg == CFI_SP && op->src.reg == CFI_SP)
1419 cfa->offset -= op->src.offset;
1420
1421 return 0;
1422 }
1423
1424 static void save_reg(struct insn_state *state, unsigned char reg, int base,
1425 int offset)
1426 {
1427 if (arch_callee_saved_reg(reg) &&
1428 state->regs[reg].base == CFI_UNDEFINED) {
1429 state->regs[reg].base = base;
1430 state->regs[reg].offset = offset;
1431 }
1432 }
1433
1434 static void restore_reg(struct insn_state *state, unsigned char reg)
1435 {
1436 state->regs[reg].base = CFI_UNDEFINED;
1437 state->regs[reg].offset = 0;
1438 }
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493 static int update_insn_state(struct instruction *insn, struct insn_state *state)
1494 {
1495 struct stack_op *op = &insn->stack_op;
1496 struct cfi_reg *cfa = &state->cfa;
1497 struct cfi_reg *regs = state->regs;
1498
1499
1500 if (cfa->base == CFI_UNDEFINED) {
1501 if (insn->func) {
1502 WARN_FUNC("undefined stack state", insn->sec, insn->offset);
1503 return -1;
1504 }
1505 return 0;
1506 }
1507
1508 if (state->type == ORC_TYPE_REGS || state->type == ORC_TYPE_REGS_IRET)
1509 return update_insn_state_regs(insn, state);
1510
1511 switch (op->dest.type) {
1512
1513 case OP_DEST_REG:
1514 switch (op->src.type) {
1515
1516 case OP_SRC_REG:
1517 if (op->src.reg == CFI_SP && op->dest.reg == CFI_BP &&
1518 cfa->base == CFI_SP &&
1519 regs[CFI_BP].base == CFI_CFA &&
1520 regs[CFI_BP].offset == -cfa->offset) {
1521
1522
1523 cfa->base = op->dest.reg;
1524 state->bp_scratch = false;
1525 }
1526
1527 else if (op->src.reg == CFI_SP &&
1528 op->dest.reg == CFI_BP && state->drap) {
1529
1530
1531 regs[CFI_BP].base = CFI_BP;
1532 regs[CFI_BP].offset = -state->stack_size;
1533 state->bp_scratch = false;
1534 }
1535
1536 else if (op->src.reg == CFI_SP && cfa->base == CFI_SP) {
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548 state->vals[op->dest.reg].base = CFI_CFA;
1549 state->vals[op->dest.reg].offset = -state->stack_size;
1550 }
1551
1552 else if (op->src.reg == CFI_BP && op->dest.reg == CFI_SP &&
1553 cfa->base == CFI_BP) {
1554
1555
1556
1557
1558
1559
1560 state->stack_size = -state->regs[CFI_BP].offset;
1561 }
1562
1563 else if (op->dest.reg == cfa->base) {
1564
1565
1566 if (cfa->base == CFI_SP &&
1567 state->vals[op->src.reg].base == CFI_CFA) {
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577 cfa->offset = -state->vals[op->src.reg].offset;
1578 state->stack_size = cfa->offset;
1579
1580 } else {
1581 cfa->base = CFI_UNDEFINED;
1582 cfa->offset = 0;
1583 }
1584 }
1585
1586 break;
1587
1588 case OP_SRC_ADD:
1589 if (op->dest.reg == CFI_SP && op->src.reg == CFI_SP) {
1590
1591
1592 state->stack_size -= op->src.offset;
1593 if (cfa->base == CFI_SP)
1594 cfa->offset -= op->src.offset;
1595 break;
1596 }
1597
1598 if (op->dest.reg == CFI_SP && op->src.reg == CFI_BP) {
1599
1600
1601 state->stack_size = -(op->src.offset + regs[CFI_BP].offset);
1602 break;
1603 }
1604
1605 if (op->src.reg == CFI_SP && cfa->base == CFI_SP) {
1606
1607
1608 state->drap_reg = op->dest.reg;
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620 state->vals[op->dest.reg].base = CFI_CFA;
1621 state->vals[op->dest.reg].offset = \
1622 -state->stack_size + op->src.offset;
1623
1624 break;
1625 }
1626
1627 if (state->drap && op->dest.reg == CFI_SP &&
1628 op->src.reg == state->drap_reg) {
1629
1630
1631 cfa->base = CFI_SP;
1632 cfa->offset = state->stack_size = -op->src.offset;
1633 state->drap_reg = CFI_UNDEFINED;
1634 state->drap = false;
1635 break;
1636 }
1637
1638 if (op->dest.reg == state->cfa.base) {
1639 WARN_FUNC("unsupported stack register modification",
1640 insn->sec, insn->offset);
1641 return -1;
1642 }
1643
1644 break;
1645
1646 case OP_SRC_AND:
1647 if (op->dest.reg != CFI_SP ||
1648 (state->drap_reg != CFI_UNDEFINED && cfa->base != CFI_SP) ||
1649 (state->drap_reg == CFI_UNDEFINED && cfa->base != CFI_BP)) {
1650 WARN_FUNC("unsupported stack pointer realignment",
1651 insn->sec, insn->offset);
1652 return -1;
1653 }
1654
1655 if (state->drap_reg != CFI_UNDEFINED) {
1656
1657 cfa->base = state->drap_reg;
1658 cfa->offset = state->stack_size = 0;
1659 state->drap = true;
1660 }
1661
1662
1663
1664
1665
1666
1667 break;
1668
1669 case OP_SRC_POP:
1670 case OP_SRC_POPF:
1671 if (!state->drap && op->dest.type == OP_DEST_REG &&
1672 op->dest.reg == cfa->base) {
1673
1674
1675 cfa->base = CFI_SP;
1676 }
1677
1678 if (state->drap && cfa->base == CFI_BP_INDIRECT &&
1679 op->dest.type == OP_DEST_REG &&
1680 op->dest.reg == state->drap_reg &&
1681 state->drap_offset == -state->stack_size) {
1682
1683
1684 cfa->base = state->drap_reg;
1685 cfa->offset = 0;
1686 state->drap_offset = -1;
1687
1688 } else if (regs[op->dest.reg].offset == -state->stack_size) {
1689
1690
1691 restore_reg(state, op->dest.reg);
1692 }
1693
1694 state->stack_size -= 8;
1695 if (cfa->base == CFI_SP)
1696 cfa->offset -= 8;
1697
1698 break;
1699
1700 case OP_SRC_REG_INDIRECT:
1701 if (state->drap && op->src.reg == CFI_BP &&
1702 op->src.offset == state->drap_offset) {
1703
1704
1705 cfa->base = state->drap_reg;
1706 cfa->offset = 0;
1707 state->drap_offset = -1;
1708 }
1709
1710 if (state->drap && op->src.reg == CFI_BP &&
1711 op->src.offset == regs[op->dest.reg].offset) {
1712
1713
1714 restore_reg(state, op->dest.reg);
1715
1716 } else if (op->src.reg == cfa->base &&
1717 op->src.offset == regs[op->dest.reg].offset + cfa->offset) {
1718
1719
1720
1721 restore_reg(state, op->dest.reg);
1722 }
1723
1724 break;
1725
1726 default:
1727 WARN_FUNC("unknown stack-related instruction",
1728 insn->sec, insn->offset);
1729 return -1;
1730 }
1731
1732 break;
1733
1734 case OP_DEST_PUSH:
1735 case OP_DEST_PUSHF:
1736 state->stack_size += 8;
1737 if (cfa->base == CFI_SP)
1738 cfa->offset += 8;
1739
1740 if (op->src.type != OP_SRC_REG)
1741 break;
1742
1743 if (state->drap) {
1744 if (op->src.reg == cfa->base && op->src.reg == state->drap_reg) {
1745
1746
1747 cfa->base = CFI_BP_INDIRECT;
1748 cfa->offset = -state->stack_size;
1749
1750
1751 state->drap_offset = -state->stack_size;
1752
1753 } else if (op->src.reg == CFI_BP && cfa->base == state->drap_reg) {
1754
1755
1756 state->stack_size = 0;
1757
1758 } else if (regs[op->src.reg].base == CFI_UNDEFINED) {
1759
1760
1761 save_reg(state, op->src.reg, CFI_BP, -state->stack_size);
1762 }
1763
1764 } else {
1765
1766
1767 save_reg(state, op->src.reg, CFI_CFA, -state->stack_size);
1768 }
1769
1770
1771 if (!no_fp && insn->func && op->src.reg == CFI_BP &&
1772 cfa->base != CFI_BP)
1773 state->bp_scratch = true;
1774 break;
1775
1776 case OP_DEST_REG_INDIRECT:
1777
1778 if (state->drap) {
1779 if (op->src.reg == cfa->base && op->src.reg == state->drap_reg) {
1780
1781
1782 cfa->base = CFI_BP_INDIRECT;
1783 cfa->offset = op->dest.offset;
1784
1785
1786 state->drap_offset = op->dest.offset;
1787 }
1788
1789 else if (regs[op->src.reg].base == CFI_UNDEFINED) {
1790
1791
1792 save_reg(state, op->src.reg, CFI_BP, op->dest.offset);
1793 }
1794
1795 } else if (op->dest.reg == cfa->base) {
1796
1797
1798
1799 save_reg(state, op->src.reg, CFI_CFA,
1800 op->dest.offset - state->cfa.offset);
1801 }
1802
1803 break;
1804
1805 case OP_DEST_LEAVE:
1806 if ((!state->drap && cfa->base != CFI_BP) ||
1807 (state->drap && cfa->base != state->drap_reg)) {
1808 WARN_FUNC("leave instruction with modified stack frame",
1809 insn->sec, insn->offset);
1810 return -1;
1811 }
1812
1813
1814
1815 state->stack_size = -state->regs[CFI_BP].offset - 8;
1816 restore_reg(state, CFI_BP);
1817
1818 if (!state->drap) {
1819 cfa->base = CFI_SP;
1820 cfa->offset -= 8;
1821 }
1822
1823 break;
1824
1825 case OP_DEST_MEM:
1826 if (op->src.type != OP_SRC_POP && op->src.type != OP_SRC_POPF) {
1827 WARN_FUNC("unknown stack-related memory operation",
1828 insn->sec, insn->offset);
1829 return -1;
1830 }
1831
1832
1833 state->stack_size -= 8;
1834 if (cfa->base == CFI_SP)
1835 cfa->offset -= 8;
1836
1837 break;
1838
1839 default:
1840 WARN_FUNC("unknown stack-related instruction",
1841 insn->sec, insn->offset);
1842 return -1;
1843 }
1844
1845 return 0;
1846 }
1847
1848 static bool insn_state_match(struct instruction *insn, struct insn_state *state)
1849 {
1850 struct insn_state *state1 = &insn->state, *state2 = state;
1851 int i;
1852
1853 if (memcmp(&state1->cfa, &state2->cfa, sizeof(state1->cfa))) {
1854 WARN_FUNC("stack state mismatch: cfa1=%d%+d cfa2=%d%+d",
1855 insn->sec, insn->offset,
1856 state1->cfa.base, state1->cfa.offset,
1857 state2->cfa.base, state2->cfa.offset);
1858
1859 } else if (memcmp(&state1->regs, &state2->regs, sizeof(state1->regs))) {
1860 for (i = 0; i < CFI_NUM_REGS; i++) {
1861 if (!memcmp(&state1->regs[i], &state2->regs[i],
1862 sizeof(struct cfi_reg)))
1863 continue;
1864
1865 WARN_FUNC("stack state mismatch: reg1[%d]=%d%+d reg2[%d]=%d%+d",
1866 insn->sec, insn->offset,
1867 i, state1->regs[i].base, state1->regs[i].offset,
1868 i, state2->regs[i].base, state2->regs[i].offset);
1869 break;
1870 }
1871
1872 } else if (state1->type != state2->type) {
1873 WARN_FUNC("stack state mismatch: type1=%d type2=%d",
1874 insn->sec, insn->offset, state1->type, state2->type);
1875
1876 } else if (state1->drap != state2->drap ||
1877 (state1->drap && state1->drap_reg != state2->drap_reg) ||
1878 (state1->drap && state1->drap_offset != state2->drap_offset)) {
1879 WARN_FUNC("stack state mismatch: drap1=%d(%d,%d) drap2=%d(%d,%d)",
1880 insn->sec, insn->offset,
1881 state1->drap, state1->drap_reg, state1->drap_offset,
1882 state2->drap, state2->drap_reg, state2->drap_offset);
1883
1884 } else
1885 return true;
1886
1887 return false;
1888 }
1889
1890 static inline bool func_uaccess_safe(struct symbol *func)
1891 {
1892 if (func)
1893 return func->uaccess_safe;
1894
1895 return false;
1896 }
1897
1898 static inline const char *call_dest_name(struct instruction *insn)
1899 {
1900 if (insn->call_dest)
1901 return insn->call_dest->name;
1902
1903 return "{dynamic}";
1904 }
1905
1906 static int validate_call(struct instruction *insn, struct insn_state *state)
1907 {
1908 if (state->uaccess && !func_uaccess_safe(insn->call_dest)) {
1909 WARN_FUNC("call to %s() with UACCESS enabled",
1910 insn->sec, insn->offset, call_dest_name(insn));
1911 return 1;
1912 }
1913
1914 if (state->df) {
1915 WARN_FUNC("call to %s() with DF set",
1916 insn->sec, insn->offset, call_dest_name(insn));
1917 return 1;
1918 }
1919
1920 return 0;
1921 }
1922
1923 static int validate_sibling_call(struct instruction *insn, struct insn_state *state)
1924 {
1925 if (has_modified_stack_frame(state)) {
1926 WARN_FUNC("sibling call from callable instruction with modified stack frame",
1927 insn->sec, insn->offset);
1928 return 1;
1929 }
1930
1931 return validate_call(insn, state);
1932 }
1933
1934
1935
1936
1937
1938
1939
1940 static int validate_branch(struct objtool_file *file, struct symbol *func,
1941 struct instruction *first, struct insn_state state)
1942 {
1943 struct alternative *alt;
1944 struct instruction *insn, *next_insn;
1945 struct section *sec;
1946 u8 visited;
1947 int ret;
1948
1949 insn = first;
1950 sec = insn->sec;
1951
1952 if (insn->alt_group && list_empty(&insn->alts)) {
1953 WARN_FUNC("don't know how to handle branch to middle of alternative instruction group",
1954 sec, insn->offset);
1955 return 1;
1956 }
1957
1958 while (1) {
1959 next_insn = next_insn_same_sec(file, insn);
1960
1961 if (file->c_file && func && insn->func && func != insn->func->pfunc) {
1962 WARN("%s() falls through to next function %s()",
1963 func->name, insn->func->name);
1964 return 1;
1965 }
1966
1967 if (func && insn->ignore) {
1968 WARN_FUNC("BUG: why am I validating an ignored function?",
1969 sec, insn->offset);
1970 return 1;
1971 }
1972
1973 visited = 1 << state.uaccess;
1974 if (insn->visited) {
1975 if (!insn->hint && !insn_state_match(insn, &state))
1976 return 1;
1977
1978 if (insn->visited & visited)
1979 return 0;
1980 }
1981
1982 if (insn->hint) {
1983 if (insn->restore) {
1984 struct instruction *save_insn, *i;
1985
1986 i = insn;
1987 save_insn = NULL;
1988 func_for_each_insn_continue_reverse(file, func, i) {
1989 if (i->save) {
1990 save_insn = i;
1991 break;
1992 }
1993 }
1994
1995 if (!save_insn) {
1996 WARN_FUNC("no corresponding CFI save for CFI restore",
1997 sec, insn->offset);
1998 return 1;
1999 }
2000
2001 if (!save_insn->visited) {
2002
2003
2004
2005
2006
2007
2008
2009 if (insn == first)
2010 return 0;
2011
2012 WARN_FUNC("objtool isn't smart enough to handle this CFI save/restore combo",
2013 sec, insn->offset);
2014 return 1;
2015 }
2016
2017 insn->state = save_insn->state;
2018 }
2019
2020 state = insn->state;
2021
2022 } else
2023 insn->state = state;
2024
2025 insn->visited |= visited;
2026
2027 if (!insn->ignore_alts) {
2028 bool skip_orig = false;
2029
2030 list_for_each_entry(alt, &insn->alts, list) {
2031 if (alt->skip_orig)
2032 skip_orig = true;
2033
2034 ret = validate_branch(file, func, alt->insn, state);
2035 if (ret) {
2036 if (backtrace)
2037 BT_FUNC("(alt)", insn);
2038 return ret;
2039 }
2040 }
2041
2042 if (skip_orig)
2043 return 0;
2044 }
2045
2046 switch (insn->type) {
2047
2048 case INSN_RETURN:
2049 if (state.uaccess && !func_uaccess_safe(func)) {
2050 WARN_FUNC("return with UACCESS enabled", sec, insn->offset);
2051 return 1;
2052 }
2053
2054 if (!state.uaccess && func_uaccess_safe(func)) {
2055 WARN_FUNC("return with UACCESS disabled from a UACCESS-safe function", sec, insn->offset);
2056 return 1;
2057 }
2058
2059 if (state.df) {
2060 WARN_FUNC("return with DF set", sec, insn->offset);
2061 return 1;
2062 }
2063
2064 if (func && has_modified_stack_frame(&state)) {
2065 WARN_FUNC("return with modified stack frame",
2066 sec, insn->offset);
2067 return 1;
2068 }
2069
2070 if (state.bp_scratch) {
2071 WARN("%s uses BP as a scratch register",
2072 func->name);
2073 return 1;
2074 }
2075
2076 return 0;
2077
2078 case INSN_CALL:
2079 case INSN_CALL_DYNAMIC:
2080 ret = validate_call(insn, &state);
2081 if (ret)
2082 return ret;
2083
2084 if (!no_fp && func && !is_fentry_call(insn) &&
2085 !has_valid_stack_frame(&state)) {
2086 WARN_FUNC("call without frame pointer save/setup",
2087 sec, insn->offset);
2088 return 1;
2089 }
2090
2091 if (dead_end_function(file, insn->call_dest))
2092 return 0;
2093
2094 break;
2095
2096 case INSN_JUMP_CONDITIONAL:
2097 case INSN_JUMP_UNCONDITIONAL:
2098 if (func && is_sibling_call(insn)) {
2099 ret = validate_sibling_call(insn, &state);
2100 if (ret)
2101 return ret;
2102
2103 } else if (insn->jump_dest) {
2104 ret = validate_branch(file, func,
2105 insn->jump_dest, state);
2106 if (ret) {
2107 if (backtrace)
2108 BT_FUNC("(branch)", insn);
2109 return ret;
2110 }
2111 }
2112
2113 if (insn->type == INSN_JUMP_UNCONDITIONAL)
2114 return 0;
2115
2116 break;
2117
2118 case INSN_JUMP_DYNAMIC:
2119 case INSN_JUMP_DYNAMIC_CONDITIONAL:
2120 if (func && is_sibling_call(insn)) {
2121 ret = validate_sibling_call(insn, &state);
2122 if (ret)
2123 return ret;
2124 }
2125
2126 if (insn->type == INSN_JUMP_DYNAMIC)
2127 return 0;
2128
2129 break;
2130
2131 case INSN_CONTEXT_SWITCH:
2132 if (func && (!next_insn || !next_insn->hint)) {
2133 WARN_FUNC("unsupported instruction in callable function",
2134 sec, insn->offset);
2135 return 1;
2136 }
2137 return 0;
2138
2139 case INSN_STACK:
2140 if (update_insn_state(insn, &state))
2141 return 1;
2142
2143 if (insn->stack_op.dest.type == OP_DEST_PUSHF) {
2144 if (!state.uaccess_stack) {
2145 state.uaccess_stack = 1;
2146 } else if (state.uaccess_stack >> 31) {
2147 WARN_FUNC("PUSHF stack exhausted", sec, insn->offset);
2148 return 1;
2149 }
2150 state.uaccess_stack <<= 1;
2151 state.uaccess_stack |= state.uaccess;
2152 }
2153
2154 if (insn->stack_op.src.type == OP_SRC_POPF) {
2155 if (state.uaccess_stack) {
2156 state.uaccess = state.uaccess_stack & 1;
2157 state.uaccess_stack >>= 1;
2158 if (state.uaccess_stack == 1)
2159 state.uaccess_stack = 0;
2160 }
2161 }
2162
2163 break;
2164
2165 case INSN_STAC:
2166 if (state.uaccess) {
2167 WARN_FUNC("recursive UACCESS enable", sec, insn->offset);
2168 return 1;
2169 }
2170
2171 state.uaccess = true;
2172 break;
2173
2174 case INSN_CLAC:
2175 if (!state.uaccess && func) {
2176 WARN_FUNC("redundant UACCESS disable", sec, insn->offset);
2177 return 1;
2178 }
2179
2180 if (func_uaccess_safe(func) && !state.uaccess_stack) {
2181 WARN_FUNC("UACCESS-safe disables UACCESS", sec, insn->offset);
2182 return 1;
2183 }
2184
2185 state.uaccess = false;
2186 break;
2187
2188 case INSN_STD:
2189 if (state.df)
2190 WARN_FUNC("recursive STD", sec, insn->offset);
2191
2192 state.df = true;
2193 break;
2194
2195 case INSN_CLD:
2196 if (!state.df && func)
2197 WARN_FUNC("redundant CLD", sec, insn->offset);
2198
2199 state.df = false;
2200 break;
2201
2202 default:
2203 break;
2204 }
2205
2206 if (insn->dead_end)
2207 return 0;
2208
2209 if (!next_insn) {
2210 if (state.cfa.base == CFI_UNDEFINED)
2211 return 0;
2212 WARN("%s: unexpected end of section", sec->name);
2213 return 1;
2214 }
2215
2216 insn = next_insn;
2217 }
2218
2219 return 0;
2220 }
2221
2222 static int validate_unwind_hints(struct objtool_file *file)
2223 {
2224 struct instruction *insn;
2225 int ret, warnings = 0;
2226 struct insn_state state;
2227
2228 if (!file->hints)
2229 return 0;
2230
2231 clear_insn_state(&state);
2232
2233 for_each_insn(file, insn) {
2234 if (insn->hint && !insn->visited) {
2235 ret = validate_branch(file, insn->func, insn, state);
2236 if (ret && backtrace)
2237 BT_FUNC("<=== (hint)", insn);
2238 warnings += ret;
2239 }
2240 }
2241
2242 return warnings;
2243 }
2244
2245 static int validate_retpoline(struct objtool_file *file)
2246 {
2247 struct instruction *insn;
2248 int warnings = 0;
2249
2250 for_each_insn(file, insn) {
2251 if (insn->type != INSN_JUMP_DYNAMIC &&
2252 insn->type != INSN_CALL_DYNAMIC)
2253 continue;
2254
2255 if (insn->retpoline_safe)
2256 continue;
2257
2258
2259
2260
2261
2262
2263
2264 if (!strcmp(insn->sec->name, ".init.text") && !module)
2265 continue;
2266
2267 WARN_FUNC("indirect %s found in RETPOLINE build",
2268 insn->sec, insn->offset,
2269 insn->type == INSN_JUMP_DYNAMIC ? "jump" : "call");
2270
2271 warnings++;
2272 }
2273
2274 return warnings;
2275 }
2276
2277 static bool is_kasan_insn(struct instruction *insn)
2278 {
2279 return (insn->type == INSN_CALL &&
2280 !strcmp(insn->call_dest->name, "__asan_handle_no_return"));
2281 }
2282
2283 static bool is_ubsan_insn(struct instruction *insn)
2284 {
2285 return (insn->type == INSN_CALL &&
2286 !strcmp(insn->call_dest->name,
2287 "__ubsan_handle_builtin_unreachable"));
2288 }
2289
2290 static bool ignore_unreachable_insn(struct instruction *insn)
2291 {
2292 int i;
2293
2294 if (insn->ignore || insn->type == INSN_NOP)
2295 return true;
2296
2297
2298
2299
2300
2301
2302
2303
2304 if (!strcmp(insn->sec->name, ".fixup") ||
2305 !strcmp(insn->sec->name, ".altinstr_replacement") ||
2306 !strcmp(insn->sec->name, ".altinstr_aux"))
2307 return true;
2308
2309 if (!insn->func)
2310 return false;
2311
2312
2313
2314
2315
2316
2317
2318 if (list_prev_entry(insn, list)->dead_end &&
2319 (insn->type == INSN_BUG ||
2320 (insn->type == INSN_JUMP_UNCONDITIONAL &&
2321 insn->jump_dest && insn->jump_dest->type == INSN_BUG)))
2322 return true;
2323
2324
2325
2326
2327
2328
2329
2330 for (i = 0; i < 5; i++) {
2331
2332 if (is_kasan_insn(insn) || is_ubsan_insn(insn))
2333 return true;
2334
2335 if (insn->type == INSN_JUMP_UNCONDITIONAL) {
2336 if (insn->jump_dest &&
2337 insn->jump_dest->func == insn->func) {
2338 insn = insn->jump_dest;
2339 continue;
2340 }
2341
2342 break;
2343 }
2344
2345 if (insn->offset + insn->len >= insn->func->offset + insn->func->len)
2346 break;
2347
2348 insn = list_next_entry(insn, list);
2349 }
2350
2351 return false;
2352 }
2353
2354 static int validate_functions(struct objtool_file *file)
2355 {
2356 struct section *sec;
2357 struct symbol *func;
2358 struct instruction *insn;
2359 struct insn_state state;
2360 int ret, warnings = 0;
2361
2362 clear_insn_state(&state);
2363
2364 state.cfa = initial_func_cfi.cfa;
2365 memcpy(&state.regs, &initial_func_cfi.regs,
2366 CFI_NUM_REGS * sizeof(struct cfi_reg));
2367 state.stack_size = initial_func_cfi.cfa.offset;
2368
2369 for_each_sec(file, sec) {
2370 list_for_each_entry(func, &sec->symbol_list, list) {
2371 if (func->type != STT_FUNC)
2372 continue;
2373
2374 if (!func->len) {
2375 WARN("%s() is missing an ELF size annotation",
2376 func->name);
2377 warnings++;
2378 }
2379
2380 if (func->pfunc != func || func->alias != func)
2381 continue;
2382
2383 insn = find_insn(file, sec, func->offset);
2384 if (!insn || insn->ignore || insn->visited)
2385 continue;
2386
2387 state.uaccess = func->uaccess_safe;
2388
2389 ret = validate_branch(file, func, insn, state);
2390 if (ret && backtrace)
2391 BT_FUNC("<=== (func)", insn);
2392 warnings += ret;
2393 }
2394 }
2395
2396 return warnings;
2397 }
2398
2399 static int validate_reachable_instructions(struct objtool_file *file)
2400 {
2401 struct instruction *insn;
2402
2403 if (file->ignore_unreachables)
2404 return 0;
2405
2406 for_each_insn(file, insn) {
2407 if (insn->visited || ignore_unreachable_insn(insn))
2408 continue;
2409
2410 WARN_FUNC("unreachable instruction", insn->sec, insn->offset);
2411 return 1;
2412 }
2413
2414 return 0;
2415 }
2416
2417 static void cleanup(struct objtool_file *file)
2418 {
2419 struct instruction *insn, *tmpinsn;
2420 struct alternative *alt, *tmpalt;
2421
2422 list_for_each_entry_safe(insn, tmpinsn, &file->insn_list, list) {
2423 list_for_each_entry_safe(alt, tmpalt, &insn->alts, list) {
2424 list_del(&alt->list);
2425 free(alt);
2426 }
2427 list_del(&insn->list);
2428 hash_del(&insn->hash);
2429 free(insn);
2430 }
2431 elf_close(file->elf);
2432 }
2433
2434 static struct objtool_file file;
2435
2436 int check(const char *_objname, bool orc)
2437 {
2438 int ret, warnings = 0;
2439
2440 objname = _objname;
2441
2442 file.elf = elf_read(objname, orc ? O_RDWR : O_RDONLY);
2443 if (!file.elf)
2444 return 1;
2445
2446 INIT_LIST_HEAD(&file.insn_list);
2447 hash_init(file.insn_hash);
2448 file.c_file = find_section_by_name(file.elf, ".comment");
2449 file.ignore_unreachables = no_unreachable;
2450 file.hints = false;
2451
2452 arch_initial_func_cfi_state(&initial_func_cfi);
2453
2454 ret = decode_sections(&file);
2455 if (ret < 0)
2456 goto out;
2457 warnings += ret;
2458
2459 if (list_empty(&file.insn_list))
2460 goto out;
2461
2462 if (retpoline) {
2463 ret = validate_retpoline(&file);
2464 if (ret < 0)
2465 return ret;
2466 warnings += ret;
2467 }
2468
2469 ret = validate_functions(&file);
2470 if (ret < 0)
2471 goto out;
2472 warnings += ret;
2473
2474 ret = validate_unwind_hints(&file);
2475 if (ret < 0)
2476 goto out;
2477 warnings += ret;
2478
2479 if (!warnings) {
2480 ret = validate_reachable_instructions(&file);
2481 if (ret < 0)
2482 goto out;
2483 warnings += ret;
2484 }
2485
2486 if (orc) {
2487 ret = create_orc(&file);
2488 if (ret < 0)
2489 goto out;
2490
2491 ret = create_orc_sections(&file);
2492 if (ret < 0)
2493 goto out;
2494
2495 ret = elf_write(file.elf);
2496 if (ret < 0)
2497 goto out;
2498 }
2499
2500 out:
2501 cleanup(&file);
2502
2503
2504 if (ret || warnings)
2505 return 0;
2506 return 0;
2507 }