builtin-check.c 30 KB

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