builtin-check.c 28 KB

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