xref: /linux/tools/objtool/builtin-check.c (revision 1698872b5c772aebc5c43ca445cc0a79f12b9fcc)
1 /*
2  * Copyright (C) 2015 Josh Poimboeuf <jpoimboe@redhat.com>
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 /*
19  * objtool check:
20  *
21  * This command analyzes every .o file and ensures the validity of its stack
22  * trace metadata.  It enforces a set of rules on asm code and C inline
23  * assembly code so that stack traces can be reliable.
24  *
25  * For more information, see tools/objtool/Documentation/stack-validation.txt.
26  */
27 
28 #include <string.h>
29 #include <subcmd/parse-options.h>
30 
31 #include "builtin.h"
32 #include "elf.h"
33 #include "special.h"
34 #include "arch.h"
35 #include "warn.h"
36 
37 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
38 
39 #define STATE_FP_SAVED		0x1
40 #define STATE_FP_SETUP		0x2
41 #define STATE_FENTRY		0x4
42 
43 struct instruction {
44 	struct list_head list;
45 	struct section *sec;
46 	unsigned long offset;
47 	unsigned int len, state;
48 	unsigned char type;
49 	unsigned long immediate;
50 	bool alt_group, visited;
51 	struct symbol *call_dest;
52 	struct instruction *jump_dest;
53 	struct list_head alts;
54 };
55 
56 struct alternative {
57 	struct list_head list;
58 	struct instruction *insn;
59 };
60 
61 struct objtool_file {
62 	struct elf *elf;
63 	struct list_head insn_list;
64 	struct section *rodata;
65 };
66 
67 const char *objname;
68 static bool nofp;
69 
70 static struct instruction *find_insn(struct objtool_file *file,
71 				     struct section *sec, unsigned long offset)
72 {
73 	struct instruction *insn;
74 
75 	list_for_each_entry(insn, &file->insn_list, list)
76 		if (insn->sec == sec && insn->offset == offset)
77 			return insn;
78 
79 	return NULL;
80 }
81 
82 static struct instruction *next_insn_same_sec(struct objtool_file *file,
83 					      struct instruction *insn)
84 {
85 	struct instruction *next = list_next_entry(insn, list);
86 
87 	if (&next->list == &file->insn_list || next->sec != insn->sec)
88 		return NULL;
89 
90 	return next;
91 }
92 
93 #define for_each_insn(file, insn)					\
94 	list_for_each_entry(insn, &file->insn_list, list)
95 
96 #define func_for_each_insn(file, func, insn)				\
97 	for (insn = find_insn(file, func->sec, func->offset);		\
98 	     insn && &insn->list != &file->insn_list &&			\
99 		insn->sec == func->sec &&				\
100 		insn->offset < func->offset + func->len;		\
101 	     insn = list_next_entry(insn, list))
102 
103 #define sec_for_each_insn_from(file, insn)				\
104 	for (; insn; insn = next_insn_same_sec(file, insn))
105 
106 
107 /*
108  * Check if the function has been manually whitelisted with the
109  * STACK_FRAME_NON_STANDARD macro, or if it should be automatically whitelisted
110  * due to its use of a context switching instruction.
111  */
112 static bool ignore_func(struct objtool_file *file, struct symbol *func)
113 {
114 	struct section *macro_sec;
115 	struct rela *rela;
116 	struct instruction *insn;
117 
118 	/* check for STACK_FRAME_NON_STANDARD */
119 	macro_sec = find_section_by_name(file->elf, "__func_stack_frame_non_standard");
120 	if (macro_sec && macro_sec->rela)
121 		list_for_each_entry(rela, &macro_sec->rela->rela_list, list)
122 			if (rela->sym->sec == func->sec &&
123 			    rela->addend == func->offset)
124 				return true;
125 
126 	/* check if it has a context switching instruction */
127 	func_for_each_insn(file, func, insn)
128 		if (insn->type == INSN_CONTEXT_SWITCH)
129 			return true;
130 
131 	return false;
132 }
133 
134 /*
135  * This checks to see if the given function is a "noreturn" function.
136  *
137  * For global functions which are outside the scope of this object file, we
138  * have to keep a manual list of them.
139  *
140  * For local functions, we have to detect them manually by simply looking for
141  * the lack of a return instruction.
142  *
143  * Returns:
144  *  -1: error
145  *   0: no dead end
146  *   1: dead end
147  */
148 static int __dead_end_function(struct objtool_file *file, struct symbol *func,
149 			       int recursion)
150 {
151 	int i;
152 	struct instruction *insn;
153 	bool empty = true;
154 
155 	/*
156 	 * Unfortunately these have to be hard coded because the noreturn
157 	 * attribute isn't provided in ELF data.
158 	 */
159 	static const char * const global_noreturns[] = {
160 		"__stack_chk_fail",
161 		"panic",
162 		"do_exit",
163 		"__module_put_and_exit",
164 		"complete_and_exit",
165 		"kvm_spurious_fault",
166 		"__reiserfs_panic",
167 		"lbug_with_loc"
168 	};
169 
170 	if (func->bind == STB_WEAK)
171 		return 0;
172 
173 	if (func->bind == STB_GLOBAL)
174 		for (i = 0; i < ARRAY_SIZE(global_noreturns); i++)
175 			if (!strcmp(func->name, global_noreturns[i]))
176 				return 1;
177 
178 	if (!func->sec)
179 		return 0;
180 
181 	func_for_each_insn(file, func, insn) {
182 		empty = false;
183 
184 		if (insn->type == INSN_RETURN)
185 			return 0;
186 	}
187 
188 	if (empty)
189 		return 0;
190 
191 	/*
192 	 * A function can have a sibling call instead of a return.  In that
193 	 * case, the function's dead-end status depends on whether the target
194 	 * of the sibling call returns.
195 	 */
196 	func_for_each_insn(file, func, insn) {
197 		if (insn->sec != func->sec ||
198 		    insn->offset >= func->offset + func->len)
199 			break;
200 
201 		if (insn->type == INSN_JUMP_UNCONDITIONAL) {
202 			struct instruction *dest = insn->jump_dest;
203 			struct symbol *dest_func;
204 
205 			if (!dest)
206 				/* sibling call to another file */
207 				return 0;
208 
209 			if (dest->sec != func->sec ||
210 			    dest->offset < func->offset ||
211 			    dest->offset >= func->offset + func->len) {
212 				/* local sibling call */
213 				dest_func = find_symbol_by_offset(dest->sec,
214 								  dest->offset);
215 				if (!dest_func)
216 					continue;
217 
218 				if (recursion == 5) {
219 					WARN_FUNC("infinite recursion (objtool bug!)",
220 						  dest->sec, dest->offset);
221 					return -1;
222 				}
223 
224 				return __dead_end_function(file, dest_func,
225 							   recursion + 1);
226 			}
227 		}
228 
229 		if (insn->type == INSN_JUMP_DYNAMIC)
230 			/* sibling call */
231 			return 0;
232 	}
233 
234 	return 1;
235 }
236 
237 static int dead_end_function(struct objtool_file *file, struct symbol *func)
238 {
239 	return __dead_end_function(file, func, 0);
240 }
241 
242 /*
243  * Call the arch-specific instruction decoder for all the instructions and add
244  * them to the global instruction list.
245  */
246 static int decode_instructions(struct objtool_file *file)
247 {
248 	struct section *sec;
249 	unsigned long offset;
250 	struct instruction *insn;
251 	int ret;
252 
253 	list_for_each_entry(sec, &file->elf->sections, list) {
254 
255 		if (!(sec->sh.sh_flags & SHF_EXECINSTR))
256 			continue;
257 
258 		for (offset = 0; offset < sec->len; offset += insn->len) {
259 			insn = malloc(sizeof(*insn));
260 			memset(insn, 0, sizeof(*insn));
261 
262 			INIT_LIST_HEAD(&insn->alts);
263 			insn->sec = sec;
264 			insn->offset = offset;
265 
266 			ret = arch_decode_instruction(file->elf, sec, offset,
267 						      sec->len - offset,
268 						      &insn->len, &insn->type,
269 						      &insn->immediate);
270 			if (ret)
271 				return ret;
272 
273 			if (!insn->type || insn->type > INSN_LAST) {
274 				WARN_FUNC("invalid instruction type %d",
275 					  insn->sec, insn->offset, insn->type);
276 				return -1;
277 			}
278 
279 			list_add_tail(&insn->list, &file->insn_list);
280 		}
281 	}
282 
283 	return 0;
284 }
285 
286 /*
287  * Warnings shouldn't be reported for ignored functions.
288  */
289 static void add_ignores(struct objtool_file *file)
290 {
291 	struct instruction *insn;
292 	struct section *sec;
293 	struct symbol *func;
294 
295 	list_for_each_entry(sec, &file->elf->sections, list) {
296 		list_for_each_entry(func, &sec->symbol_list, list) {
297 			if (func->type != STT_FUNC)
298 				continue;
299 
300 			if (!ignore_func(file, func))
301 				continue;
302 
303 			func_for_each_insn(file, func, insn)
304 				insn->visited = true;
305 		}
306 	}
307 }
308 
309 /*
310  * Find the destination instructions for all jumps.
311  */
312 static int add_jump_destinations(struct objtool_file *file)
313 {
314 	struct instruction *insn;
315 	struct rela *rela;
316 	struct section *dest_sec;
317 	unsigned long dest_off;
318 
319 	for_each_insn(file, insn) {
320 		if (insn->type != INSN_JUMP_CONDITIONAL &&
321 		    insn->type != INSN_JUMP_UNCONDITIONAL)
322 			continue;
323 
324 		/* skip ignores */
325 		if (insn->visited)
326 			continue;
327 
328 		rela = find_rela_by_dest_range(insn->sec, insn->offset,
329 					       insn->len);
330 		if (!rela) {
331 			dest_sec = insn->sec;
332 			dest_off = insn->offset + insn->len + insn->immediate;
333 		} else if (rela->sym->type == STT_SECTION) {
334 			dest_sec = rela->sym->sec;
335 			dest_off = rela->addend + 4;
336 		} else if (rela->sym->sec->idx) {
337 			dest_sec = rela->sym->sec;
338 			dest_off = rela->sym->sym.st_value + rela->addend + 4;
339 		} else {
340 			/* sibling call */
341 			insn->jump_dest = 0;
342 			continue;
343 		}
344 
345 		insn->jump_dest = find_insn(file, dest_sec, dest_off);
346 		if (!insn->jump_dest) {
347 
348 			/*
349 			 * This is a special case where an alt instruction
350 			 * jumps past the end of the section.  These are
351 			 * handled later in handle_group_alt().
352 			 */
353 			if (!strcmp(insn->sec->name, ".altinstr_replacement"))
354 				continue;
355 
356 			WARN_FUNC("can't find jump dest instruction at %s+0x%lx",
357 				  insn->sec, insn->offset, dest_sec->name,
358 				  dest_off);
359 			return -1;
360 		}
361 	}
362 
363 	return 0;
364 }
365 
366 /*
367  * Find the destination instructions for all calls.
368  */
369 static int add_call_destinations(struct objtool_file *file)
370 {
371 	struct instruction *insn;
372 	unsigned long dest_off;
373 	struct rela *rela;
374 
375 	for_each_insn(file, insn) {
376 		if (insn->type != INSN_CALL)
377 			continue;
378 
379 		rela = find_rela_by_dest_range(insn->sec, insn->offset,
380 					       insn->len);
381 		if (!rela) {
382 			dest_off = insn->offset + insn->len + insn->immediate;
383 			insn->call_dest = find_symbol_by_offset(insn->sec,
384 								dest_off);
385 			if (!insn->call_dest) {
386 				WARN_FUNC("can't find call dest symbol at offset 0x%lx",
387 					  insn->sec, insn->offset, dest_off);
388 				return -1;
389 			}
390 		} else if (rela->sym->type == STT_SECTION) {
391 			insn->call_dest = find_symbol_by_offset(rela->sym->sec,
392 								rela->addend+4);
393 			if (!insn->call_dest ||
394 			    insn->call_dest->type != STT_FUNC) {
395 				WARN_FUNC("can't find call dest symbol at %s+0x%x",
396 					  insn->sec, insn->offset,
397 					  rela->sym->sec->name,
398 					  rela->addend + 4);
399 				return -1;
400 			}
401 		} else
402 			insn->call_dest = rela->sym;
403 	}
404 
405 	return 0;
406 }
407 
408 /*
409  * The .alternatives section requires some extra special care, over and above
410  * what other special sections require:
411  *
412  * 1. Because alternatives are patched in-place, we need to insert a fake jump
413  *    instruction at the end so that validate_branch() skips all the original
414  *    replaced instructions when validating the new instruction path.
415  *
416  * 2. An added wrinkle is that the new instruction length might be zero.  In
417  *    that case the old instructions are replaced with noops.  We simulate that
418  *    by creating a fake jump as the only new instruction.
419  *
420  * 3. In some cases, the alternative section includes an instruction which
421  *    conditionally jumps to the _end_ of the entry.  We have to modify these
422  *    jumps' destinations to point back to .text rather than the end of the
423  *    entry in .altinstr_replacement.
424  *
425  * 4. It has been requested that we don't validate the !POPCNT feature path
426  *    which is a "very very small percentage of machines".
427  */
428 static int handle_group_alt(struct objtool_file *file,
429 			    struct special_alt *special_alt,
430 			    struct instruction *orig_insn,
431 			    struct instruction **new_insn)
432 {
433 	struct instruction *last_orig_insn, *last_new_insn, *insn, *fake_jump;
434 	unsigned long dest_off;
435 
436 	last_orig_insn = NULL;
437 	insn = orig_insn;
438 	sec_for_each_insn_from(file, insn) {
439 		if (insn->offset >= special_alt->orig_off + special_alt->orig_len)
440 			break;
441 
442 		if (special_alt->skip_orig)
443 			insn->type = INSN_NOP;
444 
445 		insn->alt_group = true;
446 		last_orig_insn = insn;
447 	}
448 
449 	if (!next_insn_same_sec(file, last_orig_insn)) {
450 		WARN("%s: don't know how to handle alternatives at end of section",
451 		     special_alt->orig_sec->name);
452 		return -1;
453 	}
454 
455 	fake_jump = malloc(sizeof(*fake_jump));
456 	if (!fake_jump) {
457 		WARN("malloc failed");
458 		return -1;
459 	}
460 	memset(fake_jump, 0, sizeof(*fake_jump));
461 	INIT_LIST_HEAD(&fake_jump->alts);
462 	fake_jump->sec = special_alt->new_sec;
463 	fake_jump->offset = -1;
464 	fake_jump->type = INSN_JUMP_UNCONDITIONAL;
465 	fake_jump->jump_dest = list_next_entry(last_orig_insn, list);
466 
467 	if (!special_alt->new_len) {
468 		*new_insn = fake_jump;
469 		return 0;
470 	}
471 
472 	last_new_insn = NULL;
473 	insn = *new_insn;
474 	sec_for_each_insn_from(file, insn) {
475 		if (insn->offset >= special_alt->new_off + special_alt->new_len)
476 			break;
477 
478 		last_new_insn = insn;
479 
480 		if (insn->type != INSN_JUMP_CONDITIONAL &&
481 		    insn->type != INSN_JUMP_UNCONDITIONAL)
482 			continue;
483 
484 		if (!insn->immediate)
485 			continue;
486 
487 		dest_off = insn->offset + insn->len + insn->immediate;
488 		if (dest_off == special_alt->new_off + special_alt->new_len)
489 			insn->jump_dest = fake_jump;
490 
491 		if (!insn->jump_dest) {
492 			WARN_FUNC("can't find alternative jump destination",
493 				  insn->sec, insn->offset);
494 			return -1;
495 		}
496 	}
497 
498 	if (!last_new_insn) {
499 		WARN_FUNC("can't find last new alternative instruction",
500 			  special_alt->new_sec, special_alt->new_off);
501 		return -1;
502 	}
503 
504 	list_add(&fake_jump->list, &last_new_insn->list);
505 
506 	return 0;
507 }
508 
509 /*
510  * A jump table entry can either convert a nop to a jump or a jump to a nop.
511  * If the original instruction is a jump, make the alt entry an effective nop
512  * by just skipping the original instruction.
513  */
514 static int handle_jump_alt(struct objtool_file *file,
515 			   struct special_alt *special_alt,
516 			   struct instruction *orig_insn,
517 			   struct instruction **new_insn)
518 {
519 	if (orig_insn->type == INSN_NOP)
520 		return 0;
521 
522 	if (orig_insn->type != INSN_JUMP_UNCONDITIONAL) {
523 		WARN_FUNC("unsupported instruction at jump label",
524 			  orig_insn->sec, orig_insn->offset);
525 		return -1;
526 	}
527 
528 	*new_insn = list_next_entry(orig_insn, list);
529 	return 0;
530 }
531 
532 /*
533  * Read all the special sections which have alternate instructions which can be
534  * patched in or redirected to at runtime.  Each instruction having alternate
535  * instruction(s) has them added to its insn->alts list, which will be
536  * traversed in validate_branch().
537  */
538 static int add_special_section_alts(struct objtool_file *file)
539 {
540 	struct list_head special_alts;
541 	struct instruction *orig_insn, *new_insn;
542 	struct special_alt *special_alt, *tmp;
543 	struct alternative *alt;
544 	int ret;
545 
546 	ret = special_get_alts(file->elf, &special_alts);
547 	if (ret)
548 		return ret;
549 
550 	list_for_each_entry_safe(special_alt, tmp, &special_alts, list) {
551 		alt = malloc(sizeof(*alt));
552 		if (!alt) {
553 			WARN("malloc failed");
554 			ret = -1;
555 			goto out;
556 		}
557 
558 		orig_insn = find_insn(file, special_alt->orig_sec,
559 				      special_alt->orig_off);
560 		if (!orig_insn) {
561 			WARN_FUNC("special: can't find orig instruction",
562 				  special_alt->orig_sec, special_alt->orig_off);
563 			ret = -1;
564 			goto out;
565 		}
566 
567 		new_insn = NULL;
568 		if (!special_alt->group || special_alt->new_len) {
569 			new_insn = find_insn(file, special_alt->new_sec,
570 					     special_alt->new_off);
571 			if (!new_insn) {
572 				WARN_FUNC("special: can't find new instruction",
573 					  special_alt->new_sec,
574 					  special_alt->new_off);
575 				ret = -1;
576 				goto out;
577 			}
578 		}
579 
580 		if (special_alt->group) {
581 			ret = handle_group_alt(file, special_alt, orig_insn,
582 					       &new_insn);
583 			if (ret)
584 				goto out;
585 		} else if (special_alt->jump_or_nop) {
586 			ret = handle_jump_alt(file, special_alt, orig_insn,
587 					      &new_insn);
588 			if (ret)
589 				goto out;
590 		}
591 
592 		alt->insn = new_insn;
593 		list_add_tail(&alt->list, &orig_insn->alts);
594 
595 		list_del(&special_alt->list);
596 		free(special_alt);
597 	}
598 
599 out:
600 	return ret;
601 }
602 
603 static int add_switch_table(struct objtool_file *file, struct symbol *func,
604 			    struct instruction *insn, struct rela *table,
605 			    struct rela *next_table)
606 {
607 	struct rela *rela = table;
608 	struct instruction *alt_insn;
609 	struct alternative *alt;
610 
611 	list_for_each_entry_from(rela, &file->rodata->rela->rela_list, list) {
612 		if (rela == next_table)
613 			break;
614 
615 		if (rela->sym->sec != insn->sec ||
616 		    rela->addend <= func->offset ||
617 		    rela->addend >= func->offset + func->len)
618 			break;
619 
620 		alt_insn = find_insn(file, insn->sec, rela->addend);
621 		if (!alt_insn) {
622 			WARN("%s: can't find instruction at %s+0x%x",
623 			     file->rodata->rela->name, insn->sec->name,
624 			     rela->addend);
625 			return -1;
626 		}
627 
628 		alt = malloc(sizeof(*alt));
629 		if (!alt) {
630 			WARN("malloc failed");
631 			return -1;
632 		}
633 
634 		alt->insn = alt_insn;
635 		list_add_tail(&alt->list, &insn->alts);
636 	}
637 
638 	return 0;
639 }
640 
641 static int add_func_switch_tables(struct objtool_file *file,
642 				  struct symbol *func)
643 {
644 	struct instruction *insn, *prev_jump;
645 	struct rela *text_rela, *rodata_rela, *prev_rela;
646 	int ret;
647 
648 	prev_jump = NULL;
649 
650 	func_for_each_insn(file, func, insn) {
651 		if (insn->type != INSN_JUMP_DYNAMIC)
652 			continue;
653 
654 		text_rela = find_rela_by_dest_range(insn->sec, insn->offset,
655 						    insn->len);
656 		if (!text_rela || text_rela->sym != file->rodata->sym)
657 			continue;
658 
659 		/* common case: jmpq *[addr](,%rax,8) */
660 		rodata_rela = find_rela_by_dest(file->rodata,
661 						text_rela->addend);
662 
663 		/*
664 		 * TODO: Document where this is needed, or get rid of it.
665 		 *
666 		 * rare case:   jmpq *[addr](%rip)
667 		 */
668 		if (!rodata_rela)
669 			rodata_rela = find_rela_by_dest(file->rodata,
670 							text_rela->addend + 4);
671 
672 		if (!rodata_rela)
673 			continue;
674 
675 		/*
676 		 * We found a switch table, but we don't know yet how big it
677 		 * is.  Don't add it until we reach the end of the function or
678 		 * the beginning of another switch table in the same function.
679 		 */
680 		if (prev_jump) {
681 			ret = add_switch_table(file, func, prev_jump, prev_rela,
682 					       rodata_rela);
683 			if (ret)
684 				return ret;
685 		}
686 
687 		prev_jump = insn;
688 		prev_rela = rodata_rela;
689 	}
690 
691 	if (prev_jump) {
692 		ret = add_switch_table(file, func, prev_jump, prev_rela, NULL);
693 		if (ret)
694 			return ret;
695 	}
696 
697 	return 0;
698 }
699 
700 /*
701  * For some switch statements, gcc generates a jump table in the .rodata
702  * section which contains a list of addresses within the function to jump to.
703  * This finds these jump tables and adds them to the insn->alts lists.
704  */
705 static int add_switch_table_alts(struct objtool_file *file)
706 {
707 	struct section *sec;
708 	struct symbol *func;
709 	int ret;
710 
711 	if (!file->rodata || !file->rodata->rela)
712 		return 0;
713 
714 	list_for_each_entry(sec, &file->elf->sections, list) {
715 		list_for_each_entry(func, &sec->symbol_list, list) {
716 			if (func->type != STT_FUNC)
717 				continue;
718 
719 			ret = add_func_switch_tables(file, func);
720 			if (ret)
721 				return ret;
722 		}
723 	}
724 
725 	return 0;
726 }
727 
728 static int decode_sections(struct objtool_file *file)
729 {
730 	int ret;
731 
732 	file->rodata = find_section_by_name(file->elf, ".rodata");
733 
734 	ret = decode_instructions(file);
735 	if (ret)
736 		return ret;
737 
738 	add_ignores(file);
739 
740 	ret = add_jump_destinations(file);
741 	if (ret)
742 		return ret;
743 
744 	ret = add_call_destinations(file);
745 	if (ret)
746 		return ret;
747 
748 	ret = add_special_section_alts(file);
749 	if (ret)
750 		return ret;
751 
752 	ret = add_switch_table_alts(file);
753 	if (ret)
754 		return ret;
755 
756 	return 0;
757 }
758 
759 static bool is_fentry_call(struct instruction *insn)
760 {
761 	if (insn->type == INSN_CALL &&
762 	    insn->call_dest->type == STT_NOTYPE &&
763 	    !strcmp(insn->call_dest->name, "__fentry__"))
764 		return true;
765 
766 	return false;
767 }
768 
769 static bool has_modified_stack_frame(struct instruction *insn)
770 {
771 	return (insn->state & STATE_FP_SAVED) ||
772 	       (insn->state & STATE_FP_SETUP);
773 }
774 
775 static bool has_valid_stack_frame(struct instruction *insn)
776 {
777 	return (insn->state & STATE_FP_SAVED) &&
778 	       (insn->state & STATE_FP_SETUP);
779 }
780 
781 static unsigned int frame_state(unsigned long state)
782 {
783 	return (state & (STATE_FP_SAVED | STATE_FP_SETUP));
784 }
785 
786 /*
787  * Follow the branch starting at the given instruction, and recursively follow
788  * any other branches (jumps).  Meanwhile, track the frame pointer state at
789  * each instruction and validate all the rules described in
790  * tools/objtool/Documentation/stack-validation.txt.
791  */
792 static int validate_branch(struct objtool_file *file,
793 			   struct instruction *first, unsigned char first_state)
794 {
795 	struct alternative *alt;
796 	struct instruction *insn;
797 	struct section *sec;
798 	unsigned char state;
799 	int ret, warnings = 0;
800 
801 	insn = first;
802 	sec = insn->sec;
803 	state = first_state;
804 
805 	if (insn->alt_group && list_empty(&insn->alts)) {
806 		WARN_FUNC("don't know how to handle branch to middle of alternative instruction group",
807 			  sec, insn->offset);
808 		warnings++;
809 	}
810 
811 	while (1) {
812 		if (insn->visited) {
813 			if (frame_state(insn->state) != frame_state(state)) {
814 				WARN_FUNC("frame pointer state mismatch",
815 					  sec, insn->offset);
816 				warnings++;
817 			}
818 
819 			return warnings;
820 		}
821 
822 		/*
823 		 * Catch a rare case where a noreturn function falls through to
824 		 * the next function.
825 		 */
826 		if (is_fentry_call(insn) && (state & STATE_FENTRY))
827 			return warnings;
828 
829 		insn->visited = true;
830 		insn->state = state;
831 
832 		list_for_each_entry(alt, &insn->alts, list) {
833 			ret = validate_branch(file, alt->insn, state);
834 			warnings += ret;
835 		}
836 
837 		switch (insn->type) {
838 
839 		case INSN_FP_SAVE:
840 			if (!nofp) {
841 				if (state & STATE_FP_SAVED) {
842 					WARN_FUNC("duplicate frame pointer save",
843 						  sec, insn->offset);
844 					warnings++;
845 				}
846 				state |= STATE_FP_SAVED;
847 			}
848 			break;
849 
850 		case INSN_FP_SETUP:
851 			if (!nofp) {
852 				if (state & STATE_FP_SETUP) {
853 					WARN_FUNC("duplicate frame pointer setup",
854 						  sec, insn->offset);
855 					warnings++;
856 				}
857 				state |= STATE_FP_SETUP;
858 			}
859 			break;
860 
861 		case INSN_FP_RESTORE:
862 			if (!nofp) {
863 				if (has_valid_stack_frame(insn))
864 					state &= ~STATE_FP_SETUP;
865 
866 				state &= ~STATE_FP_SAVED;
867 			}
868 			break;
869 
870 		case INSN_RETURN:
871 			if (!nofp && has_modified_stack_frame(insn)) {
872 				WARN_FUNC("return without frame pointer restore",
873 					  sec, insn->offset);
874 				warnings++;
875 			}
876 			return warnings;
877 
878 		case INSN_CALL:
879 			if (is_fentry_call(insn)) {
880 				state |= STATE_FENTRY;
881 				break;
882 			}
883 
884 			ret = dead_end_function(file, insn->call_dest);
885 			if (ret == 1)
886 				return warnings;
887 			if (ret == -1)
888 				warnings++;
889 
890 			/* fallthrough */
891 		case INSN_CALL_DYNAMIC:
892 			if (!nofp && !has_valid_stack_frame(insn)) {
893 				WARN_FUNC("call without frame pointer save/setup",
894 					  sec, insn->offset);
895 				warnings++;
896 			}
897 			break;
898 
899 		case INSN_JUMP_CONDITIONAL:
900 		case INSN_JUMP_UNCONDITIONAL:
901 			if (insn->jump_dest) {
902 				ret = validate_branch(file, insn->jump_dest,
903 						      state);
904 				warnings += ret;
905 			} else if (has_modified_stack_frame(insn)) {
906 				WARN_FUNC("sibling call from callable instruction with changed frame pointer",
907 					  sec, insn->offset);
908 				warnings++;
909 			} /* else it's a sibling call */
910 
911 			if (insn->type == INSN_JUMP_UNCONDITIONAL)
912 				return warnings;
913 
914 			break;
915 
916 		case INSN_JUMP_DYNAMIC:
917 			if (list_empty(&insn->alts) &&
918 			    has_modified_stack_frame(insn)) {
919 				WARN_FUNC("sibling call from callable instruction with changed frame pointer",
920 					  sec, insn->offset);
921 				warnings++;
922 			}
923 
924 			return warnings;
925 
926 		case INSN_BUG:
927 			return warnings;
928 
929 		default:
930 			break;
931 		}
932 
933 		insn = next_insn_same_sec(file, insn);
934 		if (!insn) {
935 			WARN("%s: unexpected end of section", sec->name);
936 			warnings++;
937 			return warnings;
938 		}
939 	}
940 
941 	return warnings;
942 }
943 
944 static bool is_gcov_insn(struct instruction *insn)
945 {
946 	struct rela *rela;
947 	struct section *sec;
948 	struct symbol *sym;
949 	unsigned long offset;
950 
951 	rela = find_rela_by_dest_range(insn->sec, insn->offset, insn->len);
952 	if (!rela)
953 		return false;
954 
955 	if (rela->sym->type != STT_SECTION)
956 		return false;
957 
958 	sec = rela->sym->sec;
959 	offset = rela->addend + insn->offset + insn->len - rela->offset;
960 
961 	list_for_each_entry(sym, &sec->symbol_list, list) {
962 		if (sym->type != STT_OBJECT)
963 			continue;
964 
965 		if (offset >= sym->offset && offset < sym->offset + sym->len)
966 			return (!memcmp(sym->name, "__gcov0.", 8));
967 	}
968 
969 	return false;
970 }
971 
972 static bool is_kasan_insn(struct instruction *insn)
973 {
974 	return (insn->type == INSN_CALL &&
975 		!strcmp(insn->call_dest->name, "__asan_handle_no_return"));
976 }
977 
978 static bool is_ubsan_insn(struct instruction *insn)
979 {
980 	return (insn->type == INSN_CALL &&
981 		!strcmp(insn->call_dest->name,
982 			"__ubsan_handle_builtin_unreachable"));
983 }
984 
985 static bool ignore_unreachable_insn(struct symbol *func,
986 				    struct instruction *insn)
987 {
988 	int i;
989 
990 	if (insn->type == INSN_NOP)
991 		return true;
992 
993 	if (is_gcov_insn(insn))
994 		return true;
995 
996 	/*
997 	 * Check if this (or a subsequent) instruction is related to
998 	 * CONFIG_UBSAN or CONFIG_KASAN.
999 	 *
1000 	 * End the search at 5 instructions to avoid going into the weeds.
1001 	 */
1002 	for (i = 0; i < 5; i++) {
1003 
1004 		if (is_kasan_insn(insn) || is_ubsan_insn(insn))
1005 			return true;
1006 
1007 		if (insn->type == INSN_JUMP_UNCONDITIONAL && insn->jump_dest) {
1008 			insn = insn->jump_dest;
1009 			continue;
1010 		}
1011 
1012 		if (insn->offset + insn->len >= func->offset + func->len)
1013 			break;
1014 		insn = list_next_entry(insn, list);
1015 	}
1016 
1017 	return false;
1018 }
1019 
1020 static int validate_functions(struct objtool_file *file)
1021 {
1022 	struct section *sec;
1023 	struct symbol *func;
1024 	struct instruction *insn;
1025 	int ret, warnings = 0;
1026 
1027 	list_for_each_entry(sec, &file->elf->sections, list) {
1028 		list_for_each_entry(func, &sec->symbol_list, list) {
1029 			if (func->type != STT_FUNC)
1030 				continue;
1031 
1032 			insn = find_insn(file, sec, func->offset);
1033 			if (!insn) {
1034 				WARN("%s(): can't find starting instruction",
1035 				     func->name);
1036 				warnings++;
1037 				continue;
1038 			}
1039 
1040 			ret = validate_branch(file, insn, 0);
1041 			warnings += ret;
1042 		}
1043 	}
1044 
1045 	list_for_each_entry(sec, &file->elf->sections, list) {
1046 		list_for_each_entry(func, &sec->symbol_list, list) {
1047 			if (func->type != STT_FUNC)
1048 				continue;
1049 
1050 			func_for_each_insn(file, func, insn) {
1051 				if (insn->visited)
1052 					continue;
1053 
1054 				if (!ignore_unreachable_insn(func, insn)) {
1055 					WARN_FUNC("function has unreachable instruction", insn->sec, insn->offset);
1056 					warnings++;
1057 				}
1058 
1059 				insn->visited = true;
1060 			}
1061 		}
1062 	}
1063 
1064 	return warnings;
1065 }
1066 
1067 static int validate_uncallable_instructions(struct objtool_file *file)
1068 {
1069 	struct instruction *insn;
1070 	int warnings = 0;
1071 
1072 	for_each_insn(file, insn) {
1073 		if (!insn->visited && insn->type == INSN_RETURN) {
1074 			WARN_FUNC("return instruction outside of a callable function",
1075 				  insn->sec, insn->offset);
1076 			warnings++;
1077 		}
1078 	}
1079 
1080 	return warnings;
1081 }
1082 
1083 static void cleanup(struct objtool_file *file)
1084 {
1085 	struct instruction *insn, *tmpinsn;
1086 	struct alternative *alt, *tmpalt;
1087 
1088 	list_for_each_entry_safe(insn, tmpinsn, &file->insn_list, list) {
1089 		list_for_each_entry_safe(alt, tmpalt, &insn->alts, list) {
1090 			list_del(&alt->list);
1091 			free(alt);
1092 		}
1093 		list_del(&insn->list);
1094 		free(insn);
1095 	}
1096 	elf_close(file->elf);
1097 }
1098 
1099 const char * const check_usage[] = {
1100 	"objtool check [<options>] file.o",
1101 	NULL,
1102 };
1103 
1104 int cmd_check(int argc, const char **argv)
1105 {
1106 	struct objtool_file file;
1107 	int ret, warnings = 0;
1108 
1109 	const struct option options[] = {
1110 		OPT_BOOLEAN('f', "no-fp", &nofp, "Skip frame pointer validation"),
1111 		OPT_END(),
1112 	};
1113 
1114 	argc = parse_options(argc, argv, options, check_usage, 0);
1115 
1116 	if (argc != 1)
1117 		usage_with_options(check_usage, options);
1118 
1119 	objname = argv[0];
1120 
1121 	file.elf = elf_open(objname);
1122 	if (!file.elf) {
1123 		fprintf(stderr, "error reading elf file %s\n", objname);
1124 		return 1;
1125 	}
1126 
1127 	INIT_LIST_HEAD(&file.insn_list);
1128 
1129 	ret = decode_sections(&file);
1130 	if (ret < 0)
1131 		goto out;
1132 	warnings += ret;
1133 
1134 	ret = validate_functions(&file);
1135 	if (ret < 0)
1136 		goto out;
1137 	warnings += ret;
1138 
1139 	ret = validate_uncallable_instructions(&file);
1140 	if (ret < 0)
1141 		goto out;
1142 	warnings += ret;
1143 
1144 out:
1145 	cleanup(&file);
1146 
1147 	/* ignore warnings for now until we get all the code cleaned up */
1148 	if (ret || warnings)
1149 		return 0;
1150 	return 0;
1151 }
1152