builtin-check.c 28 KB

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