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