blob: 3ff025b645278fbf29a33e8a9a18d715a74b62ea [file] [log] [blame]
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -05001/*
2 * Copyright (C) 2015-2017 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#include <string.h>
19#include <stdlib.h>
20
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +020021#include "builtin.h"
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -050022#include "check.h"
23#include "elf.h"
24#include "special.h"
25#include "arch.h"
26#include "warn.h"
27
28#include <linux/hashtable.h>
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +020029#include <linux/kernel.h>
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -050030
31struct alternative {
32 struct list_head list;
33 struct instruction *insn;
34};
35
36const char *objname;
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +020037struct cfi_state initial_func_cfi;
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -050038
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +020039struct instruction *find_insn(struct objtool_file *file,
40 struct section *sec, unsigned long offset)
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -050041{
42 struct instruction *insn;
43
44 hash_for_each_possible(file->insn_hash, insn, hash, offset)
45 if (insn->sec == sec && insn->offset == offset)
46 return insn;
47
48 return NULL;
49}
50
51static struct instruction *next_insn_same_sec(struct objtool_file *file,
52 struct instruction *insn)
53{
54 struct instruction *next = list_next_entry(insn, list);
55
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +020056 if (!next || &next->list == &file->insn_list || next->sec != insn->sec)
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -050057 return NULL;
58
59 return next;
60}
61
Josh Poimboeuf1f7f88a2018-05-09 22:39:15 -050062static struct instruction *next_insn_same_func(struct objtool_file *file,
63 struct instruction *insn)
64{
65 struct instruction *next = list_next_entry(insn, list);
66 struct symbol *func = insn->func;
67
68 if (!func)
69 return NULL;
70
71 if (&next->list != &file->insn_list && next->func == func)
72 return next;
73
74 /* Check if we're already in the subfunction: */
75 if (func == func->cfunc)
76 return NULL;
77
78 /* Move to the subfunction: */
79 return find_insn(file, func->cfunc->sec, func->cfunc->offset);
80}
81
82#define func_for_each_insn_all(file, func, insn) \
83 for (insn = find_insn(file, func->sec, func->offset); \
84 insn; \
85 insn = next_insn_same_func(file, insn))
86
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -050087#define func_for_each_insn(file, func, insn) \
88 for (insn = find_insn(file, func->sec, func->offset); \
89 insn && &insn->list != &file->insn_list && \
90 insn->sec == func->sec && \
91 insn->offset < func->offset + func->len; \
92 insn = list_next_entry(insn, list))
93
94#define func_for_each_insn_continue_reverse(file, func, insn) \
95 for (insn = list_prev_entry(insn, list); \
96 &insn->list != &file->insn_list && \
97 insn->sec == func->sec && insn->offset >= func->offset; \
98 insn = list_prev_entry(insn, list))
99
100#define sec_for_each_insn_from(file, insn) \
101 for (; insn; insn = next_insn_same_sec(file, insn))
102
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +0200103#define sec_for_each_insn_continue(file, insn) \
104 for (insn = next_insn_same_sec(file, insn); insn; \
105 insn = next_insn_same_sec(file, insn))
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -0500106
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 */
112static bool ignore_func(struct objtool_file *file, struct symbol *func)
113{
114 struct rela *rela;
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -0500115
116 /* check for STACK_FRAME_NON_STANDARD */
117 if (file->whitelist && file->whitelist->rela)
118 list_for_each_entry(rela, &file->whitelist->rela->rela_list, list) {
119 if (rela->sym->type == STT_SECTION &&
120 rela->sym->sec == func->sec &&
121 rela->addend == func->offset)
122 return true;
123 if (rela->sym->type == STT_FUNC && rela->sym == func)
124 return true;
125 }
126
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -0500127 return false;
128}
129
130/*
131 * This checks to see if the given function is a "noreturn" function.
132 *
133 * For global functions which are outside the scope of this object file, we
134 * have to keep a manual list of them.
135 *
136 * For local functions, we have to detect them manually by simply looking for
137 * the lack of a return instruction.
138 *
139 * Returns:
140 * -1: error
141 * 0: no dead end
142 * 1: dead end
143 */
144static int __dead_end_function(struct objtool_file *file, struct symbol *func,
145 int recursion)
146{
147 int i;
148 struct instruction *insn;
149 bool empty = true;
150
151 /*
152 * Unfortunately these have to be hard coded because the noreturn
153 * attribute isn't provided in ELF data.
154 */
155 static const char * const global_noreturns[] = {
156 "__stack_chk_fail",
157 "panic",
158 "do_exit",
159 "do_task_dead",
160 "__module_put_and_exit",
161 "complete_and_exit",
162 "kvm_spurious_fault",
163 "__reiserfs_panic",
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +0200164 "lbug_with_loc",
165 "fortify_panic",
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -0500166 };
167
168 if (func->bind == STB_WEAK)
169 return 0;
170
171 if (func->bind == STB_GLOBAL)
172 for (i = 0; i < ARRAY_SIZE(global_noreturns); i++)
173 if (!strcmp(func->name, global_noreturns[i]))
174 return 1;
175
Josh Poimboeuf1f7f88a2018-05-09 22:39:15 -0500176 if (!func->len)
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -0500177 return 0;
178
Josh Poimboeuf1f7f88a2018-05-09 22:39:15 -0500179 insn = find_insn(file, func->sec, func->offset);
180 if (!insn->func)
181 return 0;
182
183 func_for_each_insn_all(file, func, insn) {
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -0500184 empty = false;
185
186 if (insn->type == INSN_RETURN)
187 return 0;
188 }
189
190 if (empty)
191 return 0;
192
193 /*
194 * A function can have a sibling call instead of a return. In that
195 * case, the function's dead-end status depends on whether the target
196 * of the sibling call returns.
197 */
Josh Poimboeuf1f7f88a2018-05-09 22:39:15 -0500198 func_for_each_insn_all(file, func, insn) {
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -0500199 if (insn->type == INSN_JUMP_UNCONDITIONAL) {
200 struct instruction *dest = insn->jump_dest;
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -0500201
202 if (!dest)
203 /* sibling call to another file */
204 return 0;
205
Josh Poimboeuf1f7f88a2018-05-09 22:39:15 -0500206 if (dest->func && dest->func->pfunc != insn->func->pfunc) {
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -0500207
Josh Poimboeuf1f7f88a2018-05-09 22:39:15 -0500208 /* local sibling call */
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -0500209 if (recursion == 5) {
Josh Poimboeuf9aebb3d2018-05-09 22:39:14 -0500210 /*
211 * Infinite recursion: two functions
212 * have sibling calls to each other.
213 * This is a very rare case. It means
214 * they aren't dead ends.
215 */
216 return 0;
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -0500217 }
218
Josh Poimboeuf1f7f88a2018-05-09 22:39:15 -0500219 return __dead_end_function(file, dest->func,
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -0500220 recursion + 1);
221 }
222 }
223
224 if (insn->type == INSN_JUMP_DYNAMIC && list_empty(&insn->alts))
225 /* sibling call */
226 return 0;
227 }
228
229 return 1;
230}
231
232static int dead_end_function(struct objtool_file *file, struct symbol *func)
233{
234 return __dead_end_function(file, func, 0);
235}
236
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +0200237static void clear_insn_state(struct insn_state *state)
238{
239 int i;
240
241 memset(state, 0, sizeof(*state));
242 state->cfa.base = CFI_UNDEFINED;
243 for (i = 0; i < CFI_NUM_REGS; i++) {
244 state->regs[i].base = CFI_UNDEFINED;
245 state->vals[i].base = CFI_UNDEFINED;
246 }
247 state->drap_reg = CFI_UNDEFINED;
248 state->drap_offset = -1;
249}
250
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -0500251/*
252 * Call the arch-specific instruction decoder for all the instructions and add
253 * them to the global instruction list.
254 */
255static int decode_instructions(struct objtool_file *file)
256{
257 struct section *sec;
258 struct symbol *func;
259 unsigned long offset;
260 struct instruction *insn;
261 int ret;
262
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +0200263 for_each_sec(file, sec) {
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -0500264
265 if (!(sec->sh.sh_flags & SHF_EXECINSTR))
266 continue;
267
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +0200268 if (strcmp(sec->name, ".altinstr_replacement") &&
269 strcmp(sec->name, ".altinstr_aux") &&
270 strncmp(sec->name, ".discard.", 9))
271 sec->text = true;
272
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -0500273 for (offset = 0; offset < sec->len; offset += insn->len) {
274 insn = malloc(sizeof(*insn));
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +0200275 if (!insn) {
276 WARN("malloc failed");
277 return -1;
278 }
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -0500279 memset(insn, 0, sizeof(*insn));
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -0500280 INIT_LIST_HEAD(&insn->alts);
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +0200281 clear_insn_state(&insn->state);
282
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -0500283 insn->sec = sec;
284 insn->offset = offset;
285
286 ret = arch_decode_instruction(file->elf, sec, offset,
287 sec->len - offset,
288 &insn->len, &insn->type,
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +0200289 &insn->immediate,
290 &insn->stack_op);
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -0500291 if (ret)
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +0200292 goto err;
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -0500293
294 if (!insn->type || insn->type > INSN_LAST) {
295 WARN_FUNC("invalid instruction type %d",
296 insn->sec, insn->offset, insn->type);
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +0200297 ret = -1;
298 goto err;
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -0500299 }
300
301 hash_add(file->insn_hash, &insn->hash, insn->offset);
302 list_add_tail(&insn->list, &file->insn_list);
303 }
304
305 list_for_each_entry(func, &sec->symbol_list, list) {
306 if (func->type != STT_FUNC)
307 continue;
308
309 if (!find_insn(file, sec, func->offset)) {
310 WARN("%s(): can't find starting instruction",
311 func->name);
312 return -1;
313 }
314
315 func_for_each_insn(file, func, insn)
316 if (!insn->func)
317 insn->func = func;
318 }
319 }
320
321 return 0;
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +0200322
323err:
324 free(insn);
325 return ret;
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -0500326}
327
328/*
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +0200329 * Mark "ud2" instructions and manually annotated dead ends.
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -0500330 */
331static int add_dead_ends(struct objtool_file *file)
332{
333 struct section *sec;
334 struct rela *rela;
335 struct instruction *insn;
336 bool found;
337
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +0200338 /*
339 * By default, "ud2" is a dead end unless otherwise annotated, because
340 * GCC 7 inserts it for certain divide-by-zero cases.
341 */
342 for_each_insn(file, insn)
343 if (insn->type == INSN_BUG)
344 insn->dead_end = true;
345
346 /*
347 * Check for manually annotated dead ends.
348 */
349 sec = find_section_by_name(file->elf, ".rela.discard.unreachable");
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -0500350 if (!sec)
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +0200351 goto reachable;
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -0500352
353 list_for_each_entry(rela, &sec->rela_list, list) {
354 if (rela->sym->type != STT_SECTION) {
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +0200355 WARN("unexpected relocation symbol type in %s", sec->name);
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -0500356 return -1;
357 }
358 insn = find_insn(file, rela->sym->sec, rela->addend);
359 if (insn)
360 insn = list_prev_entry(insn, list);
361 else if (rela->addend == rela->sym->sec->len) {
362 found = false;
363 list_for_each_entry_reverse(insn, &file->insn_list, list) {
364 if (insn->sec == rela->sym->sec) {
365 found = true;
366 break;
367 }
368 }
369
370 if (!found) {
371 WARN("can't find unreachable insn at %s+0x%x",
372 rela->sym->sec->name, rela->addend);
373 return -1;
374 }
375 } else {
376 WARN("can't find unreachable insn at %s+0x%x",
377 rela->sym->sec->name, rela->addend);
378 return -1;
379 }
380
381 insn->dead_end = true;
382 }
383
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +0200384reachable:
385 /*
386 * These manually annotated reachable checks are needed for GCC 4.4,
387 * where the Linux unreachable() macro isn't supported. In that case
388 * GCC doesn't know the "ud2" is fatal, so it generates code as if it's
389 * not a dead end.
390 */
391 sec = find_section_by_name(file->elf, ".rela.discard.reachable");
392 if (!sec)
393 return 0;
394
395 list_for_each_entry(rela, &sec->rela_list, list) {
396 if (rela->sym->type != STT_SECTION) {
397 WARN("unexpected relocation symbol type in %s", sec->name);
398 return -1;
399 }
400 insn = find_insn(file, rela->sym->sec, rela->addend);
401 if (insn)
402 insn = list_prev_entry(insn, list);
403 else if (rela->addend == rela->sym->sec->len) {
404 found = false;
405 list_for_each_entry_reverse(insn, &file->insn_list, list) {
406 if (insn->sec == rela->sym->sec) {
407 found = true;
408 break;
409 }
410 }
411
412 if (!found) {
413 WARN("can't find reachable insn at %s+0x%x",
414 rela->sym->sec->name, rela->addend);
415 return -1;
416 }
417 } else {
418 WARN("can't find reachable insn at %s+0x%x",
419 rela->sym->sec->name, rela->addend);
420 return -1;
421 }
422
423 insn->dead_end = false;
424 }
425
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -0500426 return 0;
427}
428
429/*
430 * Warnings shouldn't be reported for ignored functions.
431 */
432static void add_ignores(struct objtool_file *file)
433{
434 struct instruction *insn;
435 struct section *sec;
436 struct symbol *func;
437
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +0200438 for_each_sec(file, sec) {
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -0500439 list_for_each_entry(func, &sec->symbol_list, list) {
440 if (func->type != STT_FUNC)
441 continue;
442
443 if (!ignore_func(file, func))
444 continue;
445
Josh Poimboeuf1f7f88a2018-05-09 22:39:15 -0500446 func_for_each_insn_all(file, func, insn)
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +0200447 insn->ignore = true;
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -0500448 }
449 }
450}
451
452/*
453 * FIXME: For now, just ignore any alternatives which add retpolines. This is
454 * a temporary hack, as it doesn't allow ORC to unwind from inside a retpoline.
455 * But it at least allows objtool to understand the control flow *around* the
456 * retpoline.
457 */
458static int add_nospec_ignores(struct objtool_file *file)
459{
460 struct section *sec;
461 struct rela *rela;
462 struct instruction *insn;
463
464 sec = find_section_by_name(file->elf, ".rela.discard.nospec");
465 if (!sec)
466 return 0;
467
468 list_for_each_entry(rela, &sec->rela_list, list) {
469 if (rela->sym->type != STT_SECTION) {
470 WARN("unexpected relocation symbol type in %s", sec->name);
471 return -1;
472 }
473
474 insn = find_insn(file, rela->sym->sec, rela->addend);
475 if (!insn) {
476 WARN("bad .discard.nospec entry");
477 return -1;
478 }
479
480 insn->ignore_alts = true;
481 }
482
483 return 0;
484}
485
486/*
487 * Find the destination instructions for all jumps.
488 */
489static int add_jump_destinations(struct objtool_file *file)
490{
491 struct instruction *insn;
492 struct rela *rela;
493 struct section *dest_sec;
494 unsigned long dest_off;
495
496 for_each_insn(file, insn) {
497 if (insn->type != INSN_JUMP_CONDITIONAL &&
498 insn->type != INSN_JUMP_UNCONDITIONAL)
499 continue;
500
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +0200501 if (insn->ignore)
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -0500502 continue;
503
504 rela = find_rela_by_dest_range(insn->sec, insn->offset,
505 insn->len);
506 if (!rela) {
507 dest_sec = insn->sec;
508 dest_off = insn->offset + insn->len + insn->immediate;
509 } else if (rela->sym->type == STT_SECTION) {
510 dest_sec = rela->sym->sec;
511 dest_off = rela->addend + 4;
512 } else if (rela->sym->sec->idx) {
513 dest_sec = rela->sym->sec;
514 dest_off = rela->sym->sym.st_value + rela->addend + 4;
515 } else if (strstr(rela->sym->name, "_indirect_thunk_")) {
516 /*
517 * Retpoline jumps are really dynamic jumps in
518 * disguise, so convert them accordingly.
519 */
520 insn->type = INSN_JUMP_DYNAMIC;
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +0200521 insn->retpoline_safe = true;
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -0500522 continue;
523 } else {
524 /* sibling call */
525 insn->jump_dest = 0;
526 continue;
527 }
528
529 insn->jump_dest = find_insn(file, dest_sec, dest_off);
530 if (!insn->jump_dest) {
531
532 /*
533 * This is a special case where an alt instruction
534 * jumps past the end of the section. These are
535 * handled later in handle_group_alt().
536 */
537 if (!strcmp(insn->sec->name, ".altinstr_replacement"))
538 continue;
539
540 WARN_FUNC("can't find jump dest instruction at %s+0x%lx",
541 insn->sec, insn->offset, dest_sec->name,
542 dest_off);
543 return -1;
544 }
545 }
546
547 return 0;
548}
549
550/*
551 * Find the destination instructions for all calls.
552 */
553static int add_call_destinations(struct objtool_file *file)
554{
555 struct instruction *insn;
556 unsigned long dest_off;
557 struct rela *rela;
558
559 for_each_insn(file, insn) {
560 if (insn->type != INSN_CALL)
561 continue;
562
563 rela = find_rela_by_dest_range(insn->sec, insn->offset,
564 insn->len);
565 if (!rela) {
566 dest_off = insn->offset + insn->len + insn->immediate;
567 insn->call_dest = find_symbol_by_offset(insn->sec,
568 dest_off);
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +0200569
570 if (!insn->call_dest && !insn->ignore) {
571 WARN_FUNC("unsupported intra-function call",
572 insn->sec, insn->offset);
573 if (retpoline)
574 WARN("If this is a retpoline, please patch it in with alternatives and annotate it with ANNOTATE_NOSPEC_ALTERNATIVE.");
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -0500575 return -1;
576 }
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +0200577
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -0500578 } else if (rela->sym->type == STT_SECTION) {
579 insn->call_dest = find_symbol_by_offset(rela->sym->sec,
580 rela->addend+4);
581 if (!insn->call_dest ||
582 insn->call_dest->type != STT_FUNC) {
583 WARN_FUNC("can't find call dest symbol at %s+0x%x",
584 insn->sec, insn->offset,
585 rela->sym->sec->name,
586 rela->addend + 4);
587 return -1;
588 }
589 } else
590 insn->call_dest = rela->sym;
591 }
592
593 return 0;
594}
595
596/*
597 * The .alternatives section requires some extra special care, over and above
598 * what other special sections require:
599 *
600 * 1. Because alternatives are patched in-place, we need to insert a fake jump
601 * instruction at the end so that validate_branch() skips all the original
602 * replaced instructions when validating the new instruction path.
603 *
604 * 2. An added wrinkle is that the new instruction length might be zero. In
605 * that case the old instructions are replaced with noops. We simulate that
606 * by creating a fake jump as the only new instruction.
607 *
608 * 3. In some cases, the alternative section includes an instruction which
609 * conditionally jumps to the _end_ of the entry. We have to modify these
610 * jumps' destinations to point back to .text rather than the end of the
611 * entry in .altinstr_replacement.
612 *
613 * 4. It has been requested that we don't validate the !POPCNT feature path
614 * which is a "very very small percentage of machines".
615 */
616static int handle_group_alt(struct objtool_file *file,
617 struct special_alt *special_alt,
618 struct instruction *orig_insn,
619 struct instruction **new_insn)
620{
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +0200621 struct instruction *last_orig_insn, *last_new_insn, *insn, *fake_jump = NULL;
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -0500622 unsigned long dest_off;
623
624 last_orig_insn = NULL;
625 insn = orig_insn;
626 sec_for_each_insn_from(file, insn) {
627 if (insn->offset >= special_alt->orig_off + special_alt->orig_len)
628 break;
629
630 if (special_alt->skip_orig)
631 insn->type = INSN_NOP;
632
633 insn->alt_group = true;
634 last_orig_insn = insn;
635 }
636
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +0200637 if (next_insn_same_sec(file, last_orig_insn)) {
638 fake_jump = malloc(sizeof(*fake_jump));
639 if (!fake_jump) {
640 WARN("malloc failed");
641 return -1;
642 }
643 memset(fake_jump, 0, sizeof(*fake_jump));
644 INIT_LIST_HEAD(&fake_jump->alts);
645 clear_insn_state(&fake_jump->state);
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -0500646
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +0200647 fake_jump->sec = special_alt->new_sec;
648 fake_jump->offset = -1;
649 fake_jump->type = INSN_JUMP_UNCONDITIONAL;
650 fake_jump->jump_dest = list_next_entry(last_orig_insn, list);
651 fake_jump->ignore = true;
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -0500652 }
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -0500653
654 if (!special_alt->new_len) {
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +0200655 if (!fake_jump) {
656 WARN("%s: empty alternative at end of section",
657 special_alt->orig_sec->name);
658 return -1;
659 }
660
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -0500661 *new_insn = fake_jump;
662 return 0;
663 }
664
665 last_new_insn = NULL;
666 insn = *new_insn;
667 sec_for_each_insn_from(file, insn) {
668 if (insn->offset >= special_alt->new_off + special_alt->new_len)
669 break;
670
671 last_new_insn = insn;
672
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +0200673 insn->ignore = orig_insn->ignore_alts;
674
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -0500675 if (insn->type != INSN_JUMP_CONDITIONAL &&
676 insn->type != INSN_JUMP_UNCONDITIONAL)
677 continue;
678
679 if (!insn->immediate)
680 continue;
681
682 dest_off = insn->offset + insn->len + insn->immediate;
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +0200683 if (dest_off == special_alt->new_off + special_alt->new_len) {
684 if (!fake_jump) {
685 WARN("%s: alternative jump to end of section",
686 special_alt->orig_sec->name);
687 return -1;
688 }
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -0500689 insn->jump_dest = fake_jump;
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +0200690 }
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -0500691
692 if (!insn->jump_dest) {
693 WARN_FUNC("can't find alternative jump destination",
694 insn->sec, insn->offset);
695 return -1;
696 }
697 }
698
699 if (!last_new_insn) {
700 WARN_FUNC("can't find last new alternative instruction",
701 special_alt->new_sec, special_alt->new_off);
702 return -1;
703 }
704
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +0200705 if (fake_jump)
706 list_add(&fake_jump->list, &last_new_insn->list);
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -0500707
708 return 0;
709}
710
711/*
712 * A jump table entry can either convert a nop to a jump or a jump to a nop.
713 * If the original instruction is a jump, make the alt entry an effective nop
714 * by just skipping the original instruction.
715 */
716static int handle_jump_alt(struct objtool_file *file,
717 struct special_alt *special_alt,
718 struct instruction *orig_insn,
719 struct instruction **new_insn)
720{
721 if (orig_insn->type == INSN_NOP)
722 return 0;
723
724 if (orig_insn->type != INSN_JUMP_UNCONDITIONAL) {
725 WARN_FUNC("unsupported instruction at jump label",
726 orig_insn->sec, orig_insn->offset);
727 return -1;
728 }
729
730 *new_insn = list_next_entry(orig_insn, list);
731 return 0;
732}
733
734/*
735 * Read all the special sections which have alternate instructions which can be
736 * patched in or redirected to at runtime. Each instruction having alternate
737 * instruction(s) has them added to its insn->alts list, which will be
738 * traversed in validate_branch().
739 */
740static int add_special_section_alts(struct objtool_file *file)
741{
742 struct list_head special_alts;
743 struct instruction *orig_insn, *new_insn;
744 struct special_alt *special_alt, *tmp;
745 struct alternative *alt;
746 int ret;
747
748 ret = special_get_alts(file->elf, &special_alts);
749 if (ret)
750 return ret;
751
752 list_for_each_entry_safe(special_alt, tmp, &special_alts, list) {
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +0200753
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -0500754 orig_insn = find_insn(file, special_alt->orig_sec,
755 special_alt->orig_off);
756 if (!orig_insn) {
757 WARN_FUNC("special: can't find orig instruction",
758 special_alt->orig_sec, special_alt->orig_off);
759 ret = -1;
760 goto out;
761 }
762
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -0500763 new_insn = NULL;
764 if (!special_alt->group || special_alt->new_len) {
765 new_insn = find_insn(file, special_alt->new_sec,
766 special_alt->new_off);
767 if (!new_insn) {
768 WARN_FUNC("special: can't find new instruction",
769 special_alt->new_sec,
770 special_alt->new_off);
771 ret = -1;
772 goto out;
773 }
774 }
775
776 if (special_alt->group) {
777 ret = handle_group_alt(file, special_alt, orig_insn,
778 &new_insn);
779 if (ret)
780 goto out;
781 } else if (special_alt->jump_or_nop) {
782 ret = handle_jump_alt(file, special_alt, orig_insn,
783 &new_insn);
784 if (ret)
785 goto out;
786 }
787
788 alt = malloc(sizeof(*alt));
789 if (!alt) {
790 WARN("malloc failed");
791 ret = -1;
792 goto out;
793 }
794
795 alt->insn = new_insn;
796 list_add_tail(&alt->list, &orig_insn->alts);
797
798 list_del(&special_alt->list);
799 free(special_alt);
800 }
801
802out:
803 return ret;
804}
805
Josh Poimboeuf1f7f88a2018-05-09 22:39:15 -0500806static int add_switch_table(struct objtool_file *file, struct instruction *insn,
807 struct rela *table, struct rela *next_table)
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -0500808{
809 struct rela *rela = table;
810 struct instruction *alt_insn;
811 struct alternative *alt;
Josh Poimboeuf7cd91852018-05-10 17:48:49 -0500812 struct symbol *pfunc = insn->func->pfunc;
813 unsigned int prev_offset = 0;
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -0500814
815 list_for_each_entry_from(rela, &file->rodata->rela->rela_list, list) {
816 if (rela == next_table)
817 break;
818
Josh Poimboeuf7cd91852018-05-10 17:48:49 -0500819 /* Make sure the switch table entries are consecutive: */
820 if (prev_offset && rela->offset != prev_offset + 8)
821 break;
822
823 /* Detect function pointers from contiguous objects: */
824 if (rela->sym->sec == pfunc->sec &&
825 rela->addend == pfunc->offset)
826 break;
827
Josh Poimboeuf1f7f88a2018-05-09 22:39:15 -0500828 alt_insn = find_insn(file, rela->sym->sec, rela->addend);
829 if (!alt_insn)
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -0500830 break;
831
Josh Poimboeuf1f7f88a2018-05-09 22:39:15 -0500832 /* Make sure the jmp dest is in the function or subfunction: */
Josh Poimboeuf7cd91852018-05-10 17:48:49 -0500833 if (alt_insn->func->pfunc != pfunc)
Josh Poimboeuf1f7f88a2018-05-09 22:39:15 -0500834 break;
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -0500835
836 alt = malloc(sizeof(*alt));
837 if (!alt) {
838 WARN("malloc failed");
839 return -1;
840 }
841
842 alt->insn = alt_insn;
843 list_add_tail(&alt->list, &insn->alts);
Josh Poimboeuf7cd91852018-05-10 17:48:49 -0500844 prev_offset = rela->offset;
845 }
846
847 if (!prev_offset) {
848 WARN_FUNC("can't find switch jump table",
849 insn->sec, insn->offset);
850 return -1;
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -0500851 }
852
853 return 0;
854}
855
856/*
857 * find_switch_table() - Given a dynamic jump, find the switch jump table in
858 * .rodata associated with it.
859 *
860 * There are 3 basic patterns:
861 *
862 * 1. jmpq *[rodata addr](,%reg,8)
863 *
864 * This is the most common case by far. It jumps to an address in a simple
865 * jump table which is stored in .rodata.
866 *
867 * 2. jmpq *[rodata addr](%rip)
868 *
869 * This is caused by a rare GCC quirk, currently only seen in three driver
870 * functions in the kernel, only with certain obscure non-distro configs.
871 *
872 * As part of an optimization, GCC makes a copy of an existing switch jump
873 * table, modifies it, and then hard-codes the jump (albeit with an indirect
874 * jump) to use a single entry in the table. The rest of the jump table and
875 * some of its jump targets remain as dead code.
876 *
877 * In such a case we can just crudely ignore all unreachable instruction
878 * warnings for the entire object file. Ideally we would just ignore them
879 * for the function, but that would require redesigning the code quite a
880 * bit. And honestly that's just not worth doing: unreachable instruction
881 * warnings are of questionable value anyway, and this is such a rare issue.
882 *
883 * 3. mov [rodata addr],%reg1
884 * ... some instructions ...
885 * jmpq *(%reg1,%reg2,8)
886 *
887 * This is a fairly uncommon pattern which is new for GCC 6. As of this
888 * writing, there are 11 occurrences of it in the allmodconfig kernel.
889 *
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +0200890 * As of GCC 7 there are quite a few more of these and the 'in between' code
891 * is significant. Esp. with KASAN enabled some of the code between the mov
892 * and jmpq uses .rodata itself, which can confuse things.
893 *
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -0500894 * TODO: Once we have DWARF CFI and smarter instruction decoding logic,
895 * ensure the same register is used in the mov and jump instructions.
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +0200896 *
897 * NOTE: RETPOLINE made it harder still to decode dynamic jumps.
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -0500898 */
899static struct rela *find_switch_table(struct objtool_file *file,
900 struct symbol *func,
901 struct instruction *insn)
902{
903 struct rela *text_rela, *rodata_rela;
904 struct instruction *orig_insn = insn;
Josh Poimboeuf48dc5372018-05-14 08:53:24 -0500905 unsigned long table_offset;
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -0500906
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +0200907 /*
908 * Backward search using the @first_jump_src links, these help avoid
909 * much of the 'in between' code. Which avoids us getting confused by
910 * it.
911 */
Josh Poimboeuf603a2cd2018-05-18 15:10:34 -0500912 for (;
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +0200913 &insn->list != &file->insn_list &&
914 insn->sec == func->sec &&
915 insn->offset >= func->offset;
916
917 insn = insn->first_jump_src ?: list_prev_entry(insn, list)) {
918
Josh Poimboeuf603a2cd2018-05-18 15:10:34 -0500919 if (insn != orig_insn && insn->type == INSN_JUMP_DYNAMIC)
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -0500920 break;
921
922 /* allow small jumps within the range */
923 if (insn->type == INSN_JUMP_UNCONDITIONAL &&
924 insn->jump_dest &&
925 (insn->jump_dest->offset <= insn->offset ||
926 insn->jump_dest->offset > orig_insn->offset))
927 break;
928
929 /* look for a relocation which references .rodata */
930 text_rela = find_rela_by_dest_range(insn->sec, insn->offset,
931 insn->len);
932 if (!text_rela || text_rela->sym != file->rodata->sym)
933 continue;
934
Josh Poimboeuf48dc5372018-05-14 08:53:24 -0500935 table_offset = text_rela->addend;
936 if (text_rela->type == R_X86_64_PC32)
937 table_offset += 4;
938
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -0500939 /*
940 * Make sure the .rodata address isn't associated with a
941 * symbol. gcc jump tables are anonymous data.
942 */
Josh Poimboeuf48dc5372018-05-14 08:53:24 -0500943 if (find_symbol_containing(file->rodata, table_offset))
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -0500944 continue;
945
Josh Poimboeuf48dc5372018-05-14 08:53:24 -0500946 rodata_rela = find_rela_by_dest(file->rodata, table_offset);
Josh Poimboeuf603a2cd2018-05-18 15:10:34 -0500947 if (rodata_rela) {
948 /*
949 * Use of RIP-relative switch jumps is quite rare, and
950 * indicates a rare GCC quirk/bug which can leave dead
951 * code behind.
952 */
953 if (text_rela->type == R_X86_64_PC32)
954 file->ignore_unreachables = true;
955
Josh Poimboeuf48dc5372018-05-14 08:53:24 -0500956 return rodata_rela;
Josh Poimboeuf603a2cd2018-05-18 15:10:34 -0500957 }
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -0500958 }
959
960 return NULL;
961}
962
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +0200963
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -0500964static int add_func_switch_tables(struct objtool_file *file,
965 struct symbol *func)
966{
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +0200967 struct instruction *insn, *last = NULL, *prev_jump = NULL;
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -0500968 struct rela *rela, *prev_rela = NULL;
969 int ret;
970
Josh Poimboeuf1f7f88a2018-05-09 22:39:15 -0500971 func_for_each_insn_all(file, func, insn) {
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +0200972 if (!last)
973 last = insn;
974
975 /*
976 * Store back-pointers for unconditional forward jumps such
977 * that find_switch_table() can back-track using those and
978 * avoid some potentially confusing code.
979 */
980 if (insn->type == INSN_JUMP_UNCONDITIONAL && insn->jump_dest &&
981 insn->offset > last->offset &&
982 insn->jump_dest->offset > insn->offset &&
983 !insn->jump_dest->first_jump_src) {
984
985 insn->jump_dest->first_jump_src = insn;
986 last = insn->jump_dest;
987 }
988
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -0500989 if (insn->type != INSN_JUMP_DYNAMIC)
990 continue;
991
992 rela = find_switch_table(file, func, insn);
993 if (!rela)
994 continue;
995
996 /*
997 * We found a switch table, but we don't know yet how big it
998 * is. Don't add it until we reach the end of the function or
999 * the beginning of another switch table in the same function.
1000 */
1001 if (prev_jump) {
Josh Poimboeuf1f7f88a2018-05-09 22:39:15 -05001002 ret = add_switch_table(file, prev_jump, prev_rela, rela);
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -05001003 if (ret)
1004 return ret;
1005 }
1006
1007 prev_jump = insn;
1008 prev_rela = rela;
1009 }
1010
1011 if (prev_jump) {
Josh Poimboeuf1f7f88a2018-05-09 22:39:15 -05001012 ret = add_switch_table(file, prev_jump, prev_rela, NULL);
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -05001013 if (ret)
1014 return ret;
1015 }
1016
1017 return 0;
1018}
1019
1020/*
1021 * For some switch statements, gcc generates a jump table in the .rodata
1022 * section which contains a list of addresses within the function to jump to.
1023 * This finds these jump tables and adds them to the insn->alts lists.
1024 */
1025static int add_switch_table_alts(struct objtool_file *file)
1026{
1027 struct section *sec;
1028 struct symbol *func;
1029 int ret;
1030
1031 if (!file->rodata || !file->rodata->rela)
1032 return 0;
1033
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +02001034 for_each_sec(file, sec) {
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -05001035 list_for_each_entry(func, &sec->symbol_list, list) {
1036 if (func->type != STT_FUNC)
1037 continue;
1038
1039 ret = add_func_switch_tables(file, func);
1040 if (ret)
1041 return ret;
1042 }
1043 }
1044
1045 return 0;
1046}
1047
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +02001048static int read_unwind_hints(struct objtool_file *file)
1049{
1050 struct section *sec, *relasec;
1051 struct rela *rela;
1052 struct unwind_hint *hint;
1053 struct instruction *insn;
1054 struct cfi_reg *cfa;
1055 int i;
1056
1057 sec = find_section_by_name(file->elf, ".discard.unwind_hints");
1058 if (!sec)
1059 return 0;
1060
1061 relasec = sec->rela;
1062 if (!relasec) {
1063 WARN("missing .rela.discard.unwind_hints section");
1064 return -1;
1065 }
1066
1067 if (sec->len % sizeof(struct unwind_hint)) {
1068 WARN("struct unwind_hint size mismatch");
1069 return -1;
1070 }
1071
1072 file->hints = true;
1073
1074 for (i = 0; i < sec->len / sizeof(struct unwind_hint); i++) {
1075 hint = (struct unwind_hint *)sec->data->d_buf + i;
1076
1077 rela = find_rela_by_dest(sec, i * sizeof(*hint));
1078 if (!rela) {
1079 WARN("can't find rela for unwind_hints[%d]", i);
1080 return -1;
1081 }
1082
1083 insn = find_insn(file, rela->sym->sec, rela->addend);
1084 if (!insn) {
1085 WARN("can't find insn for unwind_hints[%d]", i);
1086 return -1;
1087 }
1088
1089 cfa = &insn->state.cfa;
1090
1091 if (hint->type == UNWIND_HINT_TYPE_SAVE) {
1092 insn->save = true;
1093 continue;
1094
1095 } else if (hint->type == UNWIND_HINT_TYPE_RESTORE) {
1096 insn->restore = true;
1097 insn->hint = true;
1098 continue;
1099 }
1100
1101 insn->hint = true;
1102
1103 switch (hint->sp_reg) {
1104 case ORC_REG_UNDEFINED:
1105 cfa->base = CFI_UNDEFINED;
1106 break;
1107 case ORC_REG_SP:
1108 cfa->base = CFI_SP;
1109 break;
1110 case ORC_REG_BP:
1111 cfa->base = CFI_BP;
1112 break;
1113 case ORC_REG_SP_INDIRECT:
1114 cfa->base = CFI_SP_INDIRECT;
1115 break;
1116 case ORC_REG_R10:
1117 cfa->base = CFI_R10;
1118 break;
1119 case ORC_REG_R13:
1120 cfa->base = CFI_R13;
1121 break;
1122 case ORC_REG_DI:
1123 cfa->base = CFI_DI;
1124 break;
1125 case ORC_REG_DX:
1126 cfa->base = CFI_DX;
1127 break;
1128 default:
1129 WARN_FUNC("unsupported unwind_hint sp base reg %d",
1130 insn->sec, insn->offset, hint->sp_reg);
1131 return -1;
1132 }
1133
1134 cfa->offset = hint->sp_offset;
1135 insn->state.type = hint->type;
1136 }
1137
1138 return 0;
1139}
1140
1141static int read_retpoline_hints(struct objtool_file *file)
1142{
1143 struct section *sec;
1144 struct instruction *insn;
1145 struct rela *rela;
1146
1147 sec = find_section_by_name(file->elf, ".rela.discard.retpoline_safe");
1148 if (!sec)
1149 return 0;
1150
1151 list_for_each_entry(rela, &sec->rela_list, list) {
1152 if (rela->sym->type != STT_SECTION) {
1153 WARN("unexpected relocation symbol type in %s", sec->name);
1154 return -1;
1155 }
1156
1157 insn = find_insn(file, rela->sym->sec, rela->addend);
1158 if (!insn) {
1159 WARN("bad .discard.retpoline_safe entry");
1160 return -1;
1161 }
1162
1163 if (insn->type != INSN_JUMP_DYNAMIC &&
1164 insn->type != INSN_CALL_DYNAMIC) {
1165 WARN_FUNC("retpoline_safe hint not an indirect jump/call",
1166 insn->sec, insn->offset);
1167 return -1;
1168 }
1169
1170 insn->retpoline_safe = true;
1171 }
1172
1173 return 0;
1174}
1175
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -05001176static int decode_sections(struct objtool_file *file)
1177{
1178 int ret;
1179
1180 ret = decode_instructions(file);
1181 if (ret)
1182 return ret;
1183
1184 ret = add_dead_ends(file);
1185 if (ret)
1186 return ret;
1187
1188 add_ignores(file);
1189
1190 ret = add_nospec_ignores(file);
1191 if (ret)
1192 return ret;
1193
1194 ret = add_jump_destinations(file);
1195 if (ret)
1196 return ret;
1197
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -05001198 ret = add_special_section_alts(file);
1199 if (ret)
1200 return ret;
1201
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +02001202 ret = add_call_destinations(file);
1203 if (ret)
1204 return ret;
1205
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -05001206 ret = add_switch_table_alts(file);
1207 if (ret)
1208 return ret;
1209
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +02001210 ret = read_unwind_hints(file);
1211 if (ret)
1212 return ret;
1213
1214 ret = read_retpoline_hints(file);
1215 if (ret)
1216 return ret;
1217
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -05001218 return 0;
1219}
1220
1221static bool is_fentry_call(struct instruction *insn)
1222{
1223 if (insn->type == INSN_CALL &&
1224 insn->call_dest->type == STT_NOTYPE &&
1225 !strcmp(insn->call_dest->name, "__fentry__"))
1226 return true;
1227
1228 return false;
1229}
1230
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +02001231static bool has_modified_stack_frame(struct insn_state *state)
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -05001232{
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +02001233 int i;
1234
1235 if (state->cfa.base != initial_func_cfi.cfa.base ||
1236 state->cfa.offset != initial_func_cfi.cfa.offset ||
1237 state->stack_size != initial_func_cfi.cfa.offset ||
1238 state->drap)
1239 return true;
1240
1241 for (i = 0; i < CFI_NUM_REGS; i++)
1242 if (state->regs[i].base != initial_func_cfi.regs[i].base ||
1243 state->regs[i].offset != initial_func_cfi.regs[i].offset)
1244 return true;
1245
1246 return false;
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -05001247}
1248
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +02001249static bool has_valid_stack_frame(struct insn_state *state)
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -05001250{
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +02001251 if (state->cfa.base == CFI_BP && state->regs[CFI_BP].base == CFI_CFA &&
1252 state->regs[CFI_BP].offset == -16)
1253 return true;
1254
1255 if (state->drap && state->regs[CFI_BP].base == CFI_BP)
1256 return true;
1257
1258 return false;
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -05001259}
1260
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +02001261static int update_insn_state_regs(struct instruction *insn, struct insn_state *state)
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -05001262{
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +02001263 struct cfi_reg *cfa = &state->cfa;
1264 struct stack_op *op = &insn->stack_op;
1265
1266 if (cfa->base != CFI_SP)
1267 return 0;
1268
1269 /* push */
1270 if (op->dest.type == OP_DEST_PUSH)
1271 cfa->offset += 8;
1272
1273 /* pop */
1274 if (op->src.type == OP_SRC_POP)
1275 cfa->offset -= 8;
1276
1277 /* add immediate to sp */
1278 if (op->dest.type == OP_DEST_REG && op->src.type == OP_SRC_ADD &&
1279 op->dest.reg == CFI_SP && op->src.reg == CFI_SP)
1280 cfa->offset -= op->src.offset;
1281
1282 return 0;
1283}
1284
1285static void save_reg(struct insn_state *state, unsigned char reg, int base,
1286 int offset)
1287{
1288 if (arch_callee_saved_reg(reg) &&
1289 state->regs[reg].base == CFI_UNDEFINED) {
1290 state->regs[reg].base = base;
1291 state->regs[reg].offset = offset;
1292 }
1293}
1294
1295static void restore_reg(struct insn_state *state, unsigned char reg)
1296{
1297 state->regs[reg].base = CFI_UNDEFINED;
1298 state->regs[reg].offset = 0;
1299}
1300
1301/*
1302 * A note about DRAP stack alignment:
1303 *
1304 * GCC has the concept of a DRAP register, which is used to help keep track of
1305 * the stack pointer when aligning the stack. r10 or r13 is used as the DRAP
1306 * register. The typical DRAP pattern is:
1307 *
1308 * 4c 8d 54 24 08 lea 0x8(%rsp),%r10
1309 * 48 83 e4 c0 and $0xffffffffffffffc0,%rsp
1310 * 41 ff 72 f8 pushq -0x8(%r10)
1311 * 55 push %rbp
1312 * 48 89 e5 mov %rsp,%rbp
1313 * (more pushes)
1314 * 41 52 push %r10
1315 * ...
1316 * 41 5a pop %r10
1317 * (more pops)
1318 * 5d pop %rbp
1319 * 49 8d 62 f8 lea -0x8(%r10),%rsp
1320 * c3 retq
1321 *
1322 * There are some variations in the epilogues, like:
1323 *
1324 * 5b pop %rbx
1325 * 41 5a pop %r10
1326 * 41 5c pop %r12
1327 * 41 5d pop %r13
1328 * 41 5e pop %r14
1329 * c9 leaveq
1330 * 49 8d 62 f8 lea -0x8(%r10),%rsp
1331 * c3 retq
1332 *
1333 * and:
1334 *
1335 * 4c 8b 55 e8 mov -0x18(%rbp),%r10
1336 * 48 8b 5d e0 mov -0x20(%rbp),%rbx
1337 * 4c 8b 65 f0 mov -0x10(%rbp),%r12
1338 * 4c 8b 6d f8 mov -0x8(%rbp),%r13
1339 * c9 leaveq
1340 * 49 8d 62 f8 lea -0x8(%r10),%rsp
1341 * c3 retq
1342 *
1343 * Sometimes r13 is used as the DRAP register, in which case it's saved and
1344 * restored beforehand:
1345 *
1346 * 41 55 push %r13
1347 * 4c 8d 6c 24 10 lea 0x10(%rsp),%r13
1348 * 48 83 e4 f0 and $0xfffffffffffffff0,%rsp
1349 * ...
1350 * 49 8d 65 f0 lea -0x10(%r13),%rsp
1351 * 41 5d pop %r13
1352 * c3 retq
1353 */
1354static int update_insn_state(struct instruction *insn, struct insn_state *state)
1355{
1356 struct stack_op *op = &insn->stack_op;
1357 struct cfi_reg *cfa = &state->cfa;
1358 struct cfi_reg *regs = state->regs;
1359
1360 /* stack operations don't make sense with an undefined CFA */
1361 if (cfa->base == CFI_UNDEFINED) {
1362 if (insn->func) {
1363 WARN_FUNC("undefined stack state", insn->sec, insn->offset);
1364 return -1;
1365 }
1366 return 0;
1367 }
1368
1369 if (state->type == ORC_TYPE_REGS || state->type == ORC_TYPE_REGS_IRET)
1370 return update_insn_state_regs(insn, state);
1371
1372 switch (op->dest.type) {
1373
1374 case OP_DEST_REG:
1375 switch (op->src.type) {
1376
1377 case OP_SRC_REG:
1378 if (op->src.reg == CFI_SP && op->dest.reg == CFI_BP &&
1379 cfa->base == CFI_SP &&
1380 regs[CFI_BP].base == CFI_CFA &&
1381 regs[CFI_BP].offset == -cfa->offset) {
1382
1383 /* mov %rsp, %rbp */
1384 cfa->base = op->dest.reg;
1385 state->bp_scratch = false;
1386 }
1387
1388 else if (op->src.reg == CFI_SP &&
1389 op->dest.reg == CFI_BP && state->drap) {
1390
1391 /* drap: mov %rsp, %rbp */
1392 regs[CFI_BP].base = CFI_BP;
1393 regs[CFI_BP].offset = -state->stack_size;
1394 state->bp_scratch = false;
1395 }
1396
1397 else if (op->src.reg == CFI_SP && cfa->base == CFI_SP) {
1398
1399 /*
1400 * mov %rsp, %reg
1401 *
1402 * This is needed for the rare case where GCC
1403 * does:
1404 *
1405 * mov %rsp, %rax
1406 * ...
1407 * mov %rax, %rsp
1408 */
1409 state->vals[op->dest.reg].base = CFI_CFA;
1410 state->vals[op->dest.reg].offset = -state->stack_size;
1411 }
1412
1413 else if (op->src.reg == CFI_BP && op->dest.reg == CFI_SP &&
1414 cfa->base == CFI_BP) {
1415
1416 /*
1417 * mov %rbp, %rsp
1418 *
1419 * Restore the original stack pointer (Clang).
1420 */
1421 state->stack_size = -state->regs[CFI_BP].offset;
1422 }
1423
1424 else if (op->dest.reg == cfa->base) {
1425
1426 /* mov %reg, %rsp */
1427 if (cfa->base == CFI_SP &&
1428 state->vals[op->src.reg].base == CFI_CFA) {
1429
1430 /*
1431 * This is needed for the rare case
1432 * where GCC does something dumb like:
1433 *
1434 * lea 0x8(%rsp), %rcx
1435 * ...
1436 * mov %rcx, %rsp
1437 */
1438 cfa->offset = -state->vals[op->src.reg].offset;
1439 state->stack_size = cfa->offset;
1440
1441 } else {
1442 cfa->base = CFI_UNDEFINED;
1443 cfa->offset = 0;
1444 }
1445 }
1446
1447 break;
1448
1449 case OP_SRC_ADD:
1450 if (op->dest.reg == CFI_SP && op->src.reg == CFI_SP) {
1451
1452 /* add imm, %rsp */
1453 state->stack_size -= op->src.offset;
1454 if (cfa->base == CFI_SP)
1455 cfa->offset -= op->src.offset;
1456 break;
1457 }
1458
1459 if (op->dest.reg == CFI_SP && op->src.reg == CFI_BP) {
1460
1461 /* lea disp(%rbp), %rsp */
1462 state->stack_size = -(op->src.offset + regs[CFI_BP].offset);
1463 break;
1464 }
1465
1466 if (op->src.reg == CFI_SP && cfa->base == CFI_SP) {
1467
1468 /* drap: lea disp(%rsp), %drap */
1469 state->drap_reg = op->dest.reg;
1470
1471 /*
1472 * lea disp(%rsp), %reg
1473 *
1474 * This is needed for the rare case where GCC
1475 * does something dumb like:
1476 *
1477 * lea 0x8(%rsp), %rcx
1478 * ...
1479 * mov %rcx, %rsp
1480 */
1481 state->vals[op->dest.reg].base = CFI_CFA;
1482 state->vals[op->dest.reg].offset = \
1483 -state->stack_size + op->src.offset;
1484
1485 break;
1486 }
1487
1488 if (state->drap && op->dest.reg == CFI_SP &&
1489 op->src.reg == state->drap_reg) {
1490
1491 /* drap: lea disp(%drap), %rsp */
1492 cfa->base = CFI_SP;
1493 cfa->offset = state->stack_size = -op->src.offset;
1494 state->drap_reg = CFI_UNDEFINED;
1495 state->drap = false;
1496 break;
1497 }
1498
1499 if (op->dest.reg == state->cfa.base) {
1500 WARN_FUNC("unsupported stack register modification",
1501 insn->sec, insn->offset);
1502 return -1;
1503 }
1504
1505 break;
1506
1507 case OP_SRC_AND:
1508 if (op->dest.reg != CFI_SP ||
1509 (state->drap_reg != CFI_UNDEFINED && cfa->base != CFI_SP) ||
1510 (state->drap_reg == CFI_UNDEFINED && cfa->base != CFI_BP)) {
1511 WARN_FUNC("unsupported stack pointer realignment",
1512 insn->sec, insn->offset);
1513 return -1;
1514 }
1515
1516 if (state->drap_reg != CFI_UNDEFINED) {
1517 /* drap: and imm, %rsp */
1518 cfa->base = state->drap_reg;
1519 cfa->offset = state->stack_size = 0;
1520 state->drap = true;
1521 }
1522
1523 /*
1524 * Older versions of GCC (4.8ish) realign the stack
1525 * without DRAP, with a frame pointer.
1526 */
1527
1528 break;
1529
1530 case OP_SRC_POP:
1531 if (!state->drap && op->dest.type == OP_DEST_REG &&
1532 op->dest.reg == cfa->base) {
1533
1534 /* pop %rbp */
1535 cfa->base = CFI_SP;
1536 }
1537
1538 if (state->drap && cfa->base == CFI_BP_INDIRECT &&
1539 op->dest.type == OP_DEST_REG &&
1540 op->dest.reg == state->drap_reg &&
1541 state->drap_offset == -state->stack_size) {
1542
1543 /* drap: pop %drap */
1544 cfa->base = state->drap_reg;
1545 cfa->offset = 0;
1546 state->drap_offset = -1;
1547
1548 } else if (regs[op->dest.reg].offset == -state->stack_size) {
1549
1550 /* pop %reg */
1551 restore_reg(state, op->dest.reg);
1552 }
1553
1554 state->stack_size -= 8;
1555 if (cfa->base == CFI_SP)
1556 cfa->offset -= 8;
1557
1558 break;
1559
1560 case OP_SRC_REG_INDIRECT:
1561 if (state->drap && op->src.reg == CFI_BP &&
1562 op->src.offset == state->drap_offset) {
1563
1564 /* drap: mov disp(%rbp), %drap */
1565 cfa->base = state->drap_reg;
1566 cfa->offset = 0;
1567 state->drap_offset = -1;
1568 }
1569
1570 if (state->drap && op->src.reg == CFI_BP &&
1571 op->src.offset == regs[op->dest.reg].offset) {
1572
1573 /* drap: mov disp(%rbp), %reg */
1574 restore_reg(state, op->dest.reg);
1575
1576 } else if (op->src.reg == cfa->base &&
1577 op->src.offset == regs[op->dest.reg].offset + cfa->offset) {
1578
1579 /* mov disp(%rbp), %reg */
1580 /* mov disp(%rsp), %reg */
1581 restore_reg(state, op->dest.reg);
1582 }
1583
1584 break;
1585
1586 default:
1587 WARN_FUNC("unknown stack-related instruction",
1588 insn->sec, insn->offset);
1589 return -1;
1590 }
1591
1592 break;
1593
1594 case OP_DEST_PUSH:
1595 state->stack_size += 8;
1596 if (cfa->base == CFI_SP)
1597 cfa->offset += 8;
1598
1599 if (op->src.type != OP_SRC_REG)
1600 break;
1601
1602 if (state->drap) {
1603 if (op->src.reg == cfa->base && op->src.reg == state->drap_reg) {
1604
1605 /* drap: push %drap */
1606 cfa->base = CFI_BP_INDIRECT;
1607 cfa->offset = -state->stack_size;
1608
1609 /* save drap so we know when to restore it */
1610 state->drap_offset = -state->stack_size;
1611
1612 } else if (op->src.reg == CFI_BP && cfa->base == state->drap_reg) {
1613
1614 /* drap: push %rbp */
1615 state->stack_size = 0;
1616
1617 } else if (regs[op->src.reg].base == CFI_UNDEFINED) {
1618
1619 /* drap: push %reg */
1620 save_reg(state, op->src.reg, CFI_BP, -state->stack_size);
1621 }
1622
1623 } else {
1624
1625 /* push %reg */
1626 save_reg(state, op->src.reg, CFI_CFA, -state->stack_size);
1627 }
1628
1629 /* detect when asm code uses rbp as a scratch register */
1630 if (!no_fp && insn->func && op->src.reg == CFI_BP &&
1631 cfa->base != CFI_BP)
1632 state->bp_scratch = true;
1633 break;
1634
1635 case OP_DEST_REG_INDIRECT:
1636
1637 if (state->drap) {
1638 if (op->src.reg == cfa->base && op->src.reg == state->drap_reg) {
1639
1640 /* drap: mov %drap, disp(%rbp) */
1641 cfa->base = CFI_BP_INDIRECT;
1642 cfa->offset = op->dest.offset;
1643
1644 /* save drap offset so we know when to restore it */
1645 state->drap_offset = op->dest.offset;
1646 }
1647
1648 else if (regs[op->src.reg].base == CFI_UNDEFINED) {
1649
1650 /* drap: mov reg, disp(%rbp) */
1651 save_reg(state, op->src.reg, CFI_BP, op->dest.offset);
1652 }
1653
1654 } else if (op->dest.reg == cfa->base) {
1655
1656 /* mov reg, disp(%rbp) */
1657 /* mov reg, disp(%rsp) */
1658 save_reg(state, op->src.reg, CFI_CFA,
1659 op->dest.offset - state->cfa.offset);
1660 }
1661
1662 break;
1663
1664 case OP_DEST_LEAVE:
1665 if ((!state->drap && cfa->base != CFI_BP) ||
1666 (state->drap && cfa->base != state->drap_reg)) {
1667 WARN_FUNC("leave instruction with modified stack frame",
1668 insn->sec, insn->offset);
1669 return -1;
1670 }
1671
1672 /* leave (mov %rbp, %rsp; pop %rbp) */
1673
1674 state->stack_size = -state->regs[CFI_BP].offset - 8;
1675 restore_reg(state, CFI_BP);
1676
1677 if (!state->drap) {
1678 cfa->base = CFI_SP;
1679 cfa->offset -= 8;
1680 }
1681
1682 break;
1683
1684 case OP_DEST_MEM:
1685 if (op->src.type != OP_SRC_POP) {
1686 WARN_FUNC("unknown stack-related memory operation",
1687 insn->sec, insn->offset);
1688 return -1;
1689 }
1690
1691 /* pop mem */
1692 state->stack_size -= 8;
1693 if (cfa->base == CFI_SP)
1694 cfa->offset -= 8;
1695
1696 break;
1697
1698 default:
1699 WARN_FUNC("unknown stack-related instruction",
1700 insn->sec, insn->offset);
1701 return -1;
1702 }
1703
1704 return 0;
1705}
1706
1707static bool insn_state_match(struct instruction *insn, struct insn_state *state)
1708{
1709 struct insn_state *state1 = &insn->state, *state2 = state;
1710 int i;
1711
1712 if (memcmp(&state1->cfa, &state2->cfa, sizeof(state1->cfa))) {
1713 WARN_FUNC("stack state mismatch: cfa1=%d%+d cfa2=%d%+d",
1714 insn->sec, insn->offset,
1715 state1->cfa.base, state1->cfa.offset,
1716 state2->cfa.base, state2->cfa.offset);
1717
1718 } else if (memcmp(&state1->regs, &state2->regs, sizeof(state1->regs))) {
1719 for (i = 0; i < CFI_NUM_REGS; i++) {
1720 if (!memcmp(&state1->regs[i], &state2->regs[i],
1721 sizeof(struct cfi_reg)))
1722 continue;
1723
1724 WARN_FUNC("stack state mismatch: reg1[%d]=%d%+d reg2[%d]=%d%+d",
1725 insn->sec, insn->offset,
1726 i, state1->regs[i].base, state1->regs[i].offset,
1727 i, state2->regs[i].base, state2->regs[i].offset);
1728 break;
1729 }
1730
1731 } else if (state1->type != state2->type) {
1732 WARN_FUNC("stack state mismatch: type1=%d type2=%d",
1733 insn->sec, insn->offset, state1->type, state2->type);
1734
1735 } else if (state1->drap != state2->drap ||
1736 (state1->drap && state1->drap_reg != state2->drap_reg) ||
1737 (state1->drap && state1->drap_offset != state2->drap_offset)) {
1738 WARN_FUNC("stack state mismatch: drap1=%d(%d,%d) drap2=%d(%d,%d)",
1739 insn->sec, insn->offset,
1740 state1->drap, state1->drap_reg, state1->drap_offset,
1741 state2->drap, state2->drap_reg, state2->drap_offset);
1742
1743 } else
1744 return true;
1745
1746 return false;
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -05001747}
1748
1749/*
1750 * Follow the branch starting at the given instruction, and recursively follow
1751 * any other branches (jumps). Meanwhile, track the frame pointer state at
1752 * each instruction and validate all the rules described in
1753 * tools/objtool/Documentation/stack-validation.txt.
1754 */
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +02001755static int validate_branch(struct objtool_file *file, struct instruction *first,
1756 struct insn_state state)
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -05001757{
1758 struct alternative *alt;
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +02001759 struct instruction *insn, *next_insn;
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -05001760 struct section *sec;
1761 struct symbol *func = NULL;
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -05001762 int ret;
1763
1764 insn = first;
1765 sec = insn->sec;
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -05001766
1767 if (insn->alt_group && list_empty(&insn->alts)) {
1768 WARN_FUNC("don't know how to handle branch to middle of alternative instruction group",
1769 sec, insn->offset);
1770 return 1;
1771 }
1772
1773 while (1) {
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +02001774 next_insn = next_insn_same_sec(file, insn);
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -05001775
Josh Poimboeuf1f7f88a2018-05-09 22:39:15 -05001776 if (file->c_file && func && insn->func && func != insn->func->pfunc) {
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +02001777 WARN("%s() falls through to next function %s()",
1778 func->name, insn->func->name);
1779 return 1;
1780 }
1781
Josh Poimboeuf1f7f88a2018-05-09 22:39:15 -05001782 func = insn->func ? insn->func->pfunc : NULL;
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +02001783
1784 if (func && insn->ignore) {
1785 WARN_FUNC("BUG: why am I validating an ignored function?",
1786 sec, insn->offset);
1787 return 1;
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -05001788 }
1789
1790 if (insn->visited) {
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +02001791 if (!insn->hint && !insn_state_match(insn, &state))
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -05001792 return 1;
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -05001793
1794 return 0;
1795 }
1796
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +02001797 if (insn->hint) {
1798 if (insn->restore) {
1799 struct instruction *save_insn, *i;
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -05001800
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +02001801 i = insn;
1802 save_insn = NULL;
Josh Poimboeuf1f7f88a2018-05-09 22:39:15 -05001803 func_for_each_insn_continue_reverse(file, insn->func, i) {
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +02001804 if (i->save) {
1805 save_insn = i;
1806 break;
1807 }
1808 }
1809
1810 if (!save_insn) {
1811 WARN_FUNC("no corresponding CFI save for CFI restore",
1812 sec, insn->offset);
1813 return 1;
1814 }
1815
1816 if (!save_insn->visited) {
1817 /*
1818 * Oops, no state to copy yet.
1819 * Hopefully we can reach this
1820 * instruction from another branch
1821 * after the save insn has been
1822 * visited.
1823 */
1824 if (insn == first)
1825 return 0;
1826
1827 WARN_FUNC("objtool isn't smart enough to handle this CFI save/restore combo",
1828 sec, insn->offset);
1829 return 1;
1830 }
1831
1832 insn->state = save_insn->state;
1833 }
1834
1835 state = insn->state;
1836
1837 } else
1838 insn->state = state;
1839
1840 insn->visited = true;
1841
1842 if (!insn->ignore_alts) {
1843 list_for_each_entry(alt, &insn->alts, list) {
1844 ret = validate_branch(file, alt->insn, state);
1845 if (ret)
1846 return 1;
1847 }
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -05001848 }
1849
1850 switch (insn->type) {
1851
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -05001852 case INSN_RETURN:
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +02001853 if (func && has_modified_stack_frame(&state)) {
1854 WARN_FUNC("return with modified stack frame",
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -05001855 sec, insn->offset);
1856 return 1;
1857 }
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +02001858
1859 if (state.bp_scratch) {
1860 WARN("%s uses BP as a scratch register",
1861 insn->func->name);
1862 return 1;
1863 }
1864
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -05001865 return 0;
1866
1867 case INSN_CALL:
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +02001868 if (is_fentry_call(insn))
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -05001869 break;
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -05001870
1871 ret = dead_end_function(file, insn->call_dest);
1872 if (ret == 1)
1873 return 0;
1874 if (ret == -1)
1875 return 1;
1876
1877 /* fallthrough */
1878 case INSN_CALL_DYNAMIC:
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +02001879 if (!no_fp && func && !has_valid_stack_frame(&state)) {
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -05001880 WARN_FUNC("call without frame pointer save/setup",
1881 sec, insn->offset);
1882 return 1;
1883 }
1884 break;
1885
1886 case INSN_JUMP_CONDITIONAL:
1887 case INSN_JUMP_UNCONDITIONAL:
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +02001888 if (insn->jump_dest &&
1889 (!func || !insn->jump_dest->func ||
Josh Poimboeuf1f7f88a2018-05-09 22:39:15 -05001890 insn->jump_dest->func->pfunc == func)) {
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -05001891 ret = validate_branch(file, insn->jump_dest,
1892 state);
1893 if (ret)
1894 return 1;
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +02001895
1896 } else if (func && has_modified_stack_frame(&state)) {
1897 WARN_FUNC("sibling call from callable instruction with modified stack frame",
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -05001898 sec, insn->offset);
1899 return 1;
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +02001900 }
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -05001901
1902 if (insn->type == INSN_JUMP_UNCONDITIONAL)
1903 return 0;
1904
1905 break;
1906
1907 case INSN_JUMP_DYNAMIC:
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +02001908 if (func && list_empty(&insn->alts) &&
1909 has_modified_stack_frame(&state)) {
1910 WARN_FUNC("sibling call from callable instruction with modified stack frame",
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -05001911 sec, insn->offset);
1912 return 1;
1913 }
1914
1915 return 0;
1916
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +02001917 case INSN_CONTEXT_SWITCH:
1918 if (func && (!next_insn || !next_insn->hint)) {
1919 WARN_FUNC("unsupported instruction in callable function",
1920 sec, insn->offset);
1921 return 1;
1922 }
1923 return 0;
1924
1925 case INSN_STACK:
1926 if (update_insn_state(insn, &state))
1927 return 1;
1928
1929 break;
1930
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -05001931 default:
1932 break;
1933 }
1934
1935 if (insn->dead_end)
1936 return 0;
1937
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +02001938 if (!next_insn) {
1939 if (state.cfa.base == CFI_UNDEFINED)
1940 return 0;
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -05001941 WARN("%s: unexpected end of section", sec->name);
1942 return 1;
1943 }
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +02001944
1945 insn = next_insn;
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -05001946 }
1947
1948 return 0;
1949}
1950
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +02001951static int validate_unwind_hints(struct objtool_file *file)
1952{
1953 struct instruction *insn;
1954 int ret, warnings = 0;
1955 struct insn_state state;
1956
1957 if (!file->hints)
1958 return 0;
1959
1960 clear_insn_state(&state);
1961
1962 for_each_insn(file, insn) {
1963 if (insn->hint && !insn->visited) {
1964 ret = validate_branch(file, insn, state);
1965 warnings += ret;
1966 }
1967 }
1968
1969 return warnings;
1970}
1971
1972static int validate_retpoline(struct objtool_file *file)
1973{
1974 struct instruction *insn;
1975 int warnings = 0;
1976
1977 for_each_insn(file, insn) {
1978 if (insn->type != INSN_JUMP_DYNAMIC &&
1979 insn->type != INSN_CALL_DYNAMIC)
1980 continue;
1981
1982 if (insn->retpoline_safe)
1983 continue;
1984
1985 /*
1986 * .init.text code is ran before userspace and thus doesn't
1987 * strictly need retpolines, except for modules which are
1988 * loaded late, they very much do need retpoline in their
1989 * .init.text
1990 */
1991 if (!strcmp(insn->sec->name, ".init.text") && !module)
1992 continue;
1993
1994 WARN_FUNC("indirect %s found in RETPOLINE build",
1995 insn->sec, insn->offset,
1996 insn->type == INSN_JUMP_DYNAMIC ? "jump" : "call");
1997
1998 warnings++;
1999 }
2000
2001 return warnings;
2002}
2003
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -05002004static bool is_kasan_insn(struct instruction *insn)
2005{
2006 return (insn->type == INSN_CALL &&
2007 !strcmp(insn->call_dest->name, "__asan_handle_no_return"));
2008}
2009
2010static bool is_ubsan_insn(struct instruction *insn)
2011{
2012 return (insn->type == INSN_CALL &&
2013 !strcmp(insn->call_dest->name,
2014 "__ubsan_handle_builtin_unreachable"));
2015}
2016
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +02002017static bool ignore_unreachable_insn(struct instruction *insn)
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -05002018{
2019 int i;
2020
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +02002021 if (insn->ignore || insn->type == INSN_NOP)
2022 return true;
2023
2024 /*
2025 * Ignore any unused exceptions. This can happen when a whitelisted
2026 * function has an exception table entry.
2027 *
2028 * Also ignore alternative replacement instructions. This can happen
2029 * when a whitelisted function uses one of the ALTERNATIVE macros.
2030 */
2031 if (!strcmp(insn->sec->name, ".fixup") ||
2032 !strcmp(insn->sec->name, ".altinstr_replacement") ||
2033 !strcmp(insn->sec->name, ".altinstr_aux"))
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -05002034 return true;
2035
2036 /*
2037 * Check if this (or a subsequent) instruction is related to
2038 * CONFIG_UBSAN or CONFIG_KASAN.
2039 *
2040 * End the search at 5 instructions to avoid going into the weeds.
2041 */
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +02002042 if (!insn->func)
2043 return false;
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -05002044 for (i = 0; i < 5; i++) {
2045
2046 if (is_kasan_insn(insn) || is_ubsan_insn(insn))
2047 return true;
2048
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +02002049 if (insn->type == INSN_JUMP_UNCONDITIONAL) {
2050 if (insn->jump_dest &&
2051 insn->jump_dest->func == insn->func) {
2052 insn = insn->jump_dest;
2053 continue;
2054 }
2055
2056 break;
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -05002057 }
2058
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +02002059 if (insn->offset + insn->len >= insn->func->offset + insn->func->len)
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -05002060 break;
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +02002061
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -05002062 insn = list_next_entry(insn, list);
2063 }
2064
2065 return false;
2066}
2067
2068static int validate_functions(struct objtool_file *file)
2069{
2070 struct section *sec;
2071 struct symbol *func;
2072 struct instruction *insn;
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +02002073 struct insn_state state;
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -05002074 int ret, warnings = 0;
2075
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +02002076 clear_insn_state(&state);
2077
2078 state.cfa = initial_func_cfi.cfa;
2079 memcpy(&state.regs, &initial_func_cfi.regs,
2080 CFI_NUM_REGS * sizeof(struct cfi_reg));
2081 state.stack_size = initial_func_cfi.cfa.offset;
2082
2083 for_each_sec(file, sec) {
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -05002084 list_for_each_entry(func, &sec->symbol_list, list) {
Josh Poimboeuf1f7f88a2018-05-09 22:39:15 -05002085 if (func->type != STT_FUNC || func->pfunc != func)
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -05002086 continue;
2087
2088 insn = find_insn(file, sec, func->offset);
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +02002089 if (!insn || insn->ignore)
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -05002090 continue;
2091
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +02002092 ret = validate_branch(file, insn, state);
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -05002093 warnings += ret;
2094 }
2095 }
2096
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -05002097 return warnings;
2098}
2099
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +02002100static int validate_reachable_instructions(struct objtool_file *file)
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -05002101{
2102 struct instruction *insn;
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +02002103
2104 if (file->ignore_unreachables)
2105 return 0;
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -05002106
2107 for_each_insn(file, insn) {
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +02002108 if (insn->visited || ignore_unreachable_insn(insn))
2109 continue;
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -05002110
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +02002111 WARN_FUNC("unreachable instruction", insn->sec, insn->offset);
2112 return 1;
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -05002113 }
2114
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +02002115 return 0;
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -05002116}
2117
2118static void cleanup(struct objtool_file *file)
2119{
2120 struct instruction *insn, *tmpinsn;
2121 struct alternative *alt, *tmpalt;
2122
2123 list_for_each_entry_safe(insn, tmpinsn, &file->insn_list, list) {
2124 list_for_each_entry_safe(alt, tmpalt, &insn->alts, list) {
2125 list_del(&alt->list);
2126 free(alt);
2127 }
2128 list_del(&insn->list);
2129 hash_del(&insn->hash);
2130 free(insn);
2131 }
2132 elf_close(file->elf);
2133}
2134
Josh Poimboeufc818b2f2019-03-18 19:09:38 -05002135static struct objtool_file file;
2136
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +02002137int check(const char *_objname, bool orc)
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -05002138{
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -05002139 int ret, warnings = 0;
2140
2141 objname = _objname;
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -05002142
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +02002143 file.elf = elf_open(objname, orc ? O_RDWR : O_RDONLY);
2144 if (!file.elf)
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -05002145 return 1;
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -05002146
2147 INIT_LIST_HEAD(&file.insn_list);
2148 hash_init(file.insn_hash);
2149 file.whitelist = find_section_by_name(file.elf, ".discard.func_stack_frame_non_standard");
2150 file.rodata = find_section_by_name(file.elf, ".rodata");
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -05002151 file.c_file = find_section_by_name(file.elf, ".comment");
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +02002152 file.ignore_unreachables = no_unreachable;
2153 file.hints = false;
2154
2155 arch_initial_func_cfi_state(&initial_func_cfi);
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -05002156
2157 ret = decode_sections(&file);
2158 if (ret < 0)
2159 goto out;
2160 warnings += ret;
2161
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +02002162 if (list_empty(&file.insn_list))
2163 goto out;
2164
2165 if (retpoline) {
2166 ret = validate_retpoline(&file);
2167 if (ret < 0)
2168 return ret;
2169 warnings += ret;
2170 }
2171
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -05002172 ret = validate_functions(&file);
2173 if (ret < 0)
2174 goto out;
2175 warnings += ret;
2176
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +02002177 ret = validate_unwind_hints(&file);
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -05002178 if (ret < 0)
2179 goto out;
2180 warnings += ret;
2181
Greg Kroah-Hartmanb790b4f2018-06-03 12:35:15 +02002182 if (!warnings) {
2183 ret = validate_reachable_instructions(&file);
2184 if (ret < 0)
2185 goto out;
2186 warnings += ret;
2187 }
2188
2189 if (orc) {
2190 ret = create_orc(&file);
2191 if (ret < 0)
2192 goto out;
2193
2194 ret = create_orc_sections(&file);
2195 if (ret < 0)
2196 goto out;
2197
2198 ret = elf_write(file.elf);
2199 if (ret < 0)
2200 goto out;
2201 }
2202
Josh Poimboeuf24ac7a42017-06-28 10:11:05 -05002203out:
2204 cleanup(&file);
2205
2206 /* ignore warnings for now until we get all the code cleaned up */
2207 if (ret || warnings)
2208 return 0;
2209 return 0;
2210}