/contrib/binutils/gas/dw2gencfi.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 1348 lines · 1075 code · 206 blank · 67 comment · 188 complexity · 4452e872817947c9c993b42468f90f16 MD5 · raw file

  1. /* dw2gencfi.c - Support for generating Dwarf2 CFI information.
  2. Copyright 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
  3. Contributed by Michal Ludvig <mludvig@suse.cz>
  4. This file is part of GAS, the GNU Assembler.
  5. GAS is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2, or (at your option)
  8. any later version.
  9. GAS 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. You should have received a copy of the GNU General Public License
  14. along with GAS; see the file COPYING. If not, write to the Free
  15. Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
  16. 02110-1301, USA. */
  17. #include "as.h"
  18. #include "dw2gencfi.h"
  19. #include "subsegs.h"
  20. /* We re-use DWARF2_LINE_MIN_INSN_LENGTH for the code alignment field
  21. of the CIE. Default to 1 if not otherwise specified. */
  22. #ifndef DWARF2_LINE_MIN_INSN_LENGTH
  23. # define DWARF2_LINE_MIN_INSN_LENGTH 1
  24. #endif
  25. /* If TARGET_USE_CFIPOP is defined, it is required that the target
  26. provide the following definitions. Otherwise provide them to
  27. allow compilation to continue. */
  28. #ifndef TARGET_USE_CFIPOP
  29. # ifndef DWARF2_DEFAULT_RETURN_COLUMN
  30. # define DWARF2_DEFAULT_RETURN_COLUMN 0
  31. # endif
  32. # ifndef DWARF2_CIE_DATA_ALIGNMENT
  33. # define DWARF2_CIE_DATA_ALIGNMENT 1
  34. # endif
  35. #endif
  36. #ifndef EH_FRAME_ALIGNMENT
  37. # define EH_FRAME_ALIGNMENT (bfd_get_arch_size (stdoutput) == 64 ? 3 : 2)
  38. #endif
  39. #ifndef tc_cfi_frame_initial_instructions
  40. # define tc_cfi_frame_initial_instructions() ((void)0)
  41. #endif
  42. struct cfi_insn_data
  43. {
  44. struct cfi_insn_data *next;
  45. int insn;
  46. union {
  47. struct {
  48. unsigned reg;
  49. offsetT offset;
  50. } ri;
  51. struct {
  52. unsigned reg1;
  53. unsigned reg2;
  54. } rr;
  55. unsigned r;
  56. offsetT i;
  57. struct {
  58. symbolS *lab1;
  59. symbolS *lab2;
  60. } ll;
  61. struct cfi_escape_data {
  62. struct cfi_escape_data *next;
  63. expressionS exp;
  64. } *esc;
  65. } u;
  66. };
  67. struct fde_entry
  68. {
  69. struct fde_entry *next;
  70. symbolS *start_address;
  71. symbolS *end_address;
  72. struct cfi_insn_data *data;
  73. struct cfi_insn_data **last;
  74. unsigned char per_encoding;
  75. unsigned char lsda_encoding;
  76. expressionS personality;
  77. expressionS lsda;
  78. unsigned int return_column;
  79. unsigned int signal_frame;
  80. };
  81. struct cie_entry
  82. {
  83. struct cie_entry *next;
  84. symbolS *start_address;
  85. unsigned int return_column;
  86. unsigned int signal_frame;
  87. unsigned char per_encoding;
  88. unsigned char lsda_encoding;
  89. expressionS personality;
  90. struct cfi_insn_data *first, *last;
  91. };
  92. /* List of FDE entries. */
  93. static struct fde_entry *all_fde_data;
  94. static struct fde_entry **last_fde_data = &all_fde_data;
  95. /* List of CIEs so that they could be reused. */
  96. static struct cie_entry *cie_root;
  97. /* Stack of old CFI data, for save/restore. */
  98. struct cfa_save_data
  99. {
  100. struct cfa_save_data *next;
  101. offsetT cfa_offset;
  102. };
  103. /* Current open FDE entry. */
  104. struct frch_cfi_data
  105. {
  106. struct fde_entry *cur_fde_data;
  107. symbolS *last_address;
  108. offsetT cur_cfa_offset;
  109. struct cfa_save_data *cfa_save_stack;
  110. };
  111. /* Construct a new FDE structure and add it to the end of the fde list. */
  112. static struct fde_entry *
  113. alloc_fde_entry (void)
  114. {
  115. struct fde_entry *fde = xcalloc (1, sizeof (struct fde_entry));
  116. frchain_now->frch_cfi_data = xcalloc (1, sizeof (struct frch_cfi_data));
  117. frchain_now->frch_cfi_data->cur_fde_data = fde;
  118. *last_fde_data = fde;
  119. last_fde_data = &fde->next;
  120. fde->last = &fde->data;
  121. fde->return_column = DWARF2_DEFAULT_RETURN_COLUMN;
  122. fde->per_encoding = DW_EH_PE_omit;
  123. fde->lsda_encoding = DW_EH_PE_omit;
  124. return fde;
  125. }
  126. /* The following functions are available for a backend to construct its
  127. own unwind information, usually from legacy unwind directives. */
  128. /* Construct a new INSN structure and add it to the end of the insn list
  129. for the currently active FDE. */
  130. static struct cfi_insn_data *
  131. alloc_cfi_insn_data (void)
  132. {
  133. struct cfi_insn_data *insn = xcalloc (1, sizeof (struct cfi_insn_data));
  134. struct fde_entry *cur_fde_data = frchain_now->frch_cfi_data->cur_fde_data;
  135. *cur_fde_data->last = insn;
  136. cur_fde_data->last = &insn->next;
  137. return insn;
  138. }
  139. /* Construct a new FDE structure that begins at LABEL. */
  140. void
  141. cfi_new_fde (symbolS *label)
  142. {
  143. struct fde_entry *fde = alloc_fde_entry ();
  144. fde->start_address = label;
  145. frchain_now->frch_cfi_data->last_address = label;
  146. }
  147. /* End the currently open FDE. */
  148. void
  149. cfi_end_fde (symbolS *label)
  150. {
  151. frchain_now->frch_cfi_data->cur_fde_data->end_address = label;
  152. free (frchain_now->frch_cfi_data);
  153. frchain_now->frch_cfi_data = NULL;
  154. }
  155. /* Set the return column for the current FDE. */
  156. void
  157. cfi_set_return_column (unsigned regno)
  158. {
  159. frchain_now->frch_cfi_data->cur_fde_data->return_column = regno;
  160. }
  161. /* Universal functions to store new instructions. */
  162. static void
  163. cfi_add_CFA_insn(int insn)
  164. {
  165. struct cfi_insn_data *insn_ptr = alloc_cfi_insn_data ();
  166. insn_ptr->insn = insn;
  167. }
  168. static void
  169. cfi_add_CFA_insn_reg (int insn, unsigned regno)
  170. {
  171. struct cfi_insn_data *insn_ptr = alloc_cfi_insn_data ();
  172. insn_ptr->insn = insn;
  173. insn_ptr->u.r = regno;
  174. }
  175. static void
  176. cfi_add_CFA_insn_offset (int insn, offsetT offset)
  177. {
  178. struct cfi_insn_data *insn_ptr = alloc_cfi_insn_data ();
  179. insn_ptr->insn = insn;
  180. insn_ptr->u.i = offset;
  181. }
  182. static void
  183. cfi_add_CFA_insn_reg_reg (int insn, unsigned reg1, unsigned reg2)
  184. {
  185. struct cfi_insn_data *insn_ptr = alloc_cfi_insn_data ();
  186. insn_ptr->insn = insn;
  187. insn_ptr->u.rr.reg1 = reg1;
  188. insn_ptr->u.rr.reg2 = reg2;
  189. }
  190. static void
  191. cfi_add_CFA_insn_reg_offset (int insn, unsigned regno, offsetT offset)
  192. {
  193. struct cfi_insn_data *insn_ptr = alloc_cfi_insn_data ();
  194. insn_ptr->insn = insn;
  195. insn_ptr->u.ri.reg = regno;
  196. insn_ptr->u.ri.offset = offset;
  197. }
  198. /* Add a CFI insn to advance the PC from the last address to LABEL. */
  199. void
  200. cfi_add_advance_loc (symbolS *label)
  201. {
  202. struct cfi_insn_data *insn = alloc_cfi_insn_data ();
  203. insn->insn = DW_CFA_advance_loc;
  204. insn->u.ll.lab1 = frchain_now->frch_cfi_data->last_address;
  205. insn->u.ll.lab2 = label;
  206. frchain_now->frch_cfi_data->last_address = label;
  207. }
  208. /* Add a DW_CFA_offset record to the CFI data. */
  209. void
  210. cfi_add_CFA_offset (unsigned regno, offsetT offset)
  211. {
  212. unsigned int abs_data_align;
  213. assert (DWARF2_CIE_DATA_ALIGNMENT != 0);
  214. cfi_add_CFA_insn_reg_offset (DW_CFA_offset, regno, offset);
  215. abs_data_align = (DWARF2_CIE_DATA_ALIGNMENT < 0
  216. ? -DWARF2_CIE_DATA_ALIGNMENT : DWARF2_CIE_DATA_ALIGNMENT);
  217. if (offset % abs_data_align)
  218. as_bad (_("register save offset not a multiple of %u"), abs_data_align);
  219. }
  220. /* Add a DW_CFA_def_cfa record to the CFI data. */
  221. void
  222. cfi_add_CFA_def_cfa (unsigned regno, offsetT offset)
  223. {
  224. cfi_add_CFA_insn_reg_offset (DW_CFA_def_cfa, regno, offset);
  225. frchain_now->frch_cfi_data->cur_cfa_offset = offset;
  226. }
  227. /* Add a DW_CFA_register record to the CFI data. */
  228. void
  229. cfi_add_CFA_register (unsigned reg1, unsigned reg2)
  230. {
  231. cfi_add_CFA_insn_reg_reg (DW_CFA_register, reg1, reg2);
  232. }
  233. /* Add a DW_CFA_def_cfa_register record to the CFI data. */
  234. void
  235. cfi_add_CFA_def_cfa_register (unsigned regno)
  236. {
  237. cfi_add_CFA_insn_reg (DW_CFA_def_cfa_register, regno);
  238. }
  239. /* Add a DW_CFA_def_cfa_offset record to the CFI data. */
  240. void
  241. cfi_add_CFA_def_cfa_offset (offsetT offset)
  242. {
  243. cfi_add_CFA_insn_offset (DW_CFA_def_cfa_offset, offset);
  244. frchain_now->frch_cfi_data->cur_cfa_offset = offset;
  245. }
  246. void
  247. cfi_add_CFA_restore (unsigned regno)
  248. {
  249. cfi_add_CFA_insn_reg (DW_CFA_restore, regno);
  250. }
  251. void
  252. cfi_add_CFA_undefined (unsigned regno)
  253. {
  254. cfi_add_CFA_insn_reg (DW_CFA_undefined, regno);
  255. }
  256. void
  257. cfi_add_CFA_same_value (unsigned regno)
  258. {
  259. cfi_add_CFA_insn_reg (DW_CFA_same_value, regno);
  260. }
  261. void
  262. cfi_add_CFA_remember_state (void)
  263. {
  264. struct cfa_save_data *p;
  265. cfi_add_CFA_insn (DW_CFA_remember_state);
  266. p = xmalloc (sizeof (*p));
  267. p->cfa_offset = frchain_now->frch_cfi_data->cur_cfa_offset;
  268. p->next = frchain_now->frch_cfi_data->cfa_save_stack;
  269. frchain_now->frch_cfi_data->cfa_save_stack = p;
  270. }
  271. void
  272. cfi_add_CFA_restore_state (void)
  273. {
  274. struct cfa_save_data *p;
  275. cfi_add_CFA_insn (DW_CFA_restore_state);
  276. p = frchain_now->frch_cfi_data->cfa_save_stack;
  277. if (p)
  278. {
  279. frchain_now->frch_cfi_data->cur_cfa_offset = p->cfa_offset;
  280. frchain_now->frch_cfi_data->cfa_save_stack = p->next;
  281. free (p);
  282. }
  283. else
  284. as_bad (_("CFI state restore without previous remember"));
  285. }
  286. /* Parse CFI assembler directives. */
  287. static void dot_cfi (int);
  288. static void dot_cfi_escape (int);
  289. static void dot_cfi_startproc (int);
  290. static void dot_cfi_endproc (int);
  291. static void dot_cfi_personality (int);
  292. static void dot_cfi_lsda (int);
  293. /* Fake CFI type; outside the byte range of any real CFI insn. */
  294. #define CFI_adjust_cfa_offset 0x100
  295. #define CFI_return_column 0x101
  296. #define CFI_rel_offset 0x102
  297. #define CFI_escape 0x103
  298. #define CFI_signal_frame 0x104
  299. const pseudo_typeS cfi_pseudo_table[] =
  300. {
  301. { "cfi_startproc", dot_cfi_startproc, 0 },
  302. { "cfi_endproc", dot_cfi_endproc, 0 },
  303. { "cfi_def_cfa", dot_cfi, DW_CFA_def_cfa },
  304. { "cfi_def_cfa_register", dot_cfi, DW_CFA_def_cfa_register },
  305. { "cfi_def_cfa_offset", dot_cfi, DW_CFA_def_cfa_offset },
  306. { "cfi_adjust_cfa_offset", dot_cfi, CFI_adjust_cfa_offset },
  307. { "cfi_offset", dot_cfi, DW_CFA_offset },
  308. { "cfi_rel_offset", dot_cfi, CFI_rel_offset },
  309. { "cfi_register", dot_cfi, DW_CFA_register },
  310. { "cfi_return_column", dot_cfi, CFI_return_column },
  311. { "cfi_restore", dot_cfi, DW_CFA_restore },
  312. { "cfi_undefined", dot_cfi, DW_CFA_undefined },
  313. { "cfi_same_value", dot_cfi, DW_CFA_same_value },
  314. { "cfi_remember_state", dot_cfi, DW_CFA_remember_state },
  315. { "cfi_restore_state", dot_cfi, DW_CFA_restore_state },
  316. { "cfi_window_save", dot_cfi, DW_CFA_GNU_window_save },
  317. { "cfi_escape", dot_cfi_escape, 0 },
  318. { "cfi_signal_frame", dot_cfi, CFI_signal_frame },
  319. { "cfi_personality", dot_cfi_personality, 0 },
  320. { "cfi_lsda", dot_cfi_lsda, 0 },
  321. { NULL, NULL, 0 }
  322. };
  323. static void
  324. cfi_parse_separator (void)
  325. {
  326. SKIP_WHITESPACE ();
  327. if (*input_line_pointer == ',')
  328. input_line_pointer++;
  329. else
  330. as_bad (_("missing separator"));
  331. }
  332. static unsigned
  333. cfi_parse_reg (void)
  334. {
  335. int regno;
  336. expressionS exp;
  337. #ifdef tc_regname_to_dw2regnum
  338. SKIP_WHITESPACE ();
  339. if (is_name_beginner (*input_line_pointer)
  340. || (*input_line_pointer == '%'
  341. && is_name_beginner (*++input_line_pointer)))
  342. {
  343. char *name, c;
  344. name = input_line_pointer;
  345. c = get_symbol_end ();
  346. if ((regno = tc_regname_to_dw2regnum (name)) < 0)
  347. {
  348. as_bad (_("bad register expression"));
  349. regno = 0;
  350. }
  351. *input_line_pointer = c;
  352. return regno;
  353. }
  354. #endif
  355. expression_and_evaluate (&exp);
  356. switch (exp.X_op)
  357. {
  358. case O_register:
  359. case O_constant:
  360. regno = exp.X_add_number;
  361. break;
  362. default:
  363. as_bad (_("bad register expression"));
  364. regno = 0;
  365. break;
  366. }
  367. return regno;
  368. }
  369. static offsetT
  370. cfi_parse_const (void)
  371. {
  372. return get_absolute_expression ();
  373. }
  374. static void
  375. dot_cfi (int arg)
  376. {
  377. offsetT offset;
  378. unsigned reg1, reg2;
  379. if (frchain_now->frch_cfi_data == NULL)
  380. {
  381. as_bad (_("CFI instruction used without previous .cfi_startproc"));
  382. ignore_rest_of_line ();
  383. return;
  384. }
  385. /* If the last address was not at the current PC, advance to current. */
  386. if (symbol_get_frag (frchain_now->frch_cfi_data->last_address) != frag_now
  387. || S_GET_VALUE (frchain_now->frch_cfi_data->last_address)
  388. != frag_now_fix ())
  389. cfi_add_advance_loc (symbol_temp_new_now ());
  390. switch (arg)
  391. {
  392. case DW_CFA_offset:
  393. reg1 = cfi_parse_reg ();
  394. cfi_parse_separator ();
  395. offset = cfi_parse_const ();
  396. cfi_add_CFA_offset (reg1, offset);
  397. break;
  398. case CFI_rel_offset:
  399. reg1 = cfi_parse_reg ();
  400. cfi_parse_separator ();
  401. offset = cfi_parse_const ();
  402. cfi_add_CFA_offset (reg1,
  403. offset - frchain_now->frch_cfi_data->cur_cfa_offset);
  404. break;
  405. case DW_CFA_def_cfa:
  406. reg1 = cfi_parse_reg ();
  407. cfi_parse_separator ();
  408. offset = cfi_parse_const ();
  409. cfi_add_CFA_def_cfa (reg1, offset);
  410. break;
  411. case DW_CFA_register:
  412. reg1 = cfi_parse_reg ();
  413. cfi_parse_separator ();
  414. reg2 = cfi_parse_reg ();
  415. cfi_add_CFA_register (reg1, reg2);
  416. break;
  417. case DW_CFA_def_cfa_register:
  418. reg1 = cfi_parse_reg ();
  419. cfi_add_CFA_def_cfa_register (reg1);
  420. break;
  421. case DW_CFA_def_cfa_offset:
  422. offset = cfi_parse_const ();
  423. cfi_add_CFA_def_cfa_offset (offset);
  424. break;
  425. case CFI_adjust_cfa_offset:
  426. offset = cfi_parse_const ();
  427. cfi_add_CFA_def_cfa_offset (frchain_now->frch_cfi_data->cur_cfa_offset
  428. + offset);
  429. break;
  430. case DW_CFA_restore:
  431. for (;;)
  432. {
  433. reg1 = cfi_parse_reg ();
  434. cfi_add_CFA_restore (reg1);
  435. SKIP_WHITESPACE ();
  436. if (*input_line_pointer != ',')
  437. break;
  438. ++input_line_pointer;
  439. }
  440. break;
  441. case DW_CFA_undefined:
  442. for (;;)
  443. {
  444. reg1 = cfi_parse_reg ();
  445. cfi_add_CFA_undefined (reg1);
  446. SKIP_WHITESPACE ();
  447. if (*input_line_pointer != ',')
  448. break;
  449. ++input_line_pointer;
  450. }
  451. break;
  452. case DW_CFA_same_value:
  453. reg1 = cfi_parse_reg ();
  454. cfi_add_CFA_same_value (reg1);
  455. break;
  456. case CFI_return_column:
  457. reg1 = cfi_parse_reg ();
  458. cfi_set_return_column (reg1);
  459. break;
  460. case DW_CFA_remember_state:
  461. cfi_add_CFA_remember_state ();
  462. break;
  463. case DW_CFA_restore_state:
  464. cfi_add_CFA_restore_state ();
  465. break;
  466. case DW_CFA_GNU_window_save:
  467. cfi_add_CFA_insn (DW_CFA_GNU_window_save);
  468. break;
  469. case CFI_signal_frame:
  470. frchain_now->frch_cfi_data->cur_fde_data->signal_frame = 1;
  471. break;
  472. default:
  473. abort ();
  474. }
  475. demand_empty_rest_of_line ();
  476. }
  477. static void
  478. dot_cfi_escape (int ignored ATTRIBUTE_UNUSED)
  479. {
  480. struct cfi_escape_data *head, **tail, *e;
  481. struct cfi_insn_data *insn;
  482. if (frchain_now->frch_cfi_data == NULL)
  483. {
  484. as_bad (_("CFI instruction used without previous .cfi_startproc"));
  485. ignore_rest_of_line ();
  486. return;
  487. }
  488. /* If the last address was not at the current PC, advance to current. */
  489. if (symbol_get_frag (frchain_now->frch_cfi_data->last_address) != frag_now
  490. || S_GET_VALUE (frchain_now->frch_cfi_data->last_address)
  491. != frag_now_fix ())
  492. cfi_add_advance_loc (symbol_temp_new_now ());
  493. tail = &head;
  494. do
  495. {
  496. e = xmalloc (sizeof (*e));
  497. do_parse_cons_expression (&e->exp, 1);
  498. *tail = e;
  499. tail = &e->next;
  500. }
  501. while (*input_line_pointer++ == ',');
  502. *tail = NULL;
  503. insn = alloc_cfi_insn_data ();
  504. insn->insn = CFI_escape;
  505. insn->u.esc = head;
  506. --input_line_pointer;
  507. demand_empty_rest_of_line ();
  508. }
  509. static void
  510. dot_cfi_personality (int ignored ATTRIBUTE_UNUSED)
  511. {
  512. struct fde_entry *fde;
  513. offsetT encoding;
  514. if (frchain_now->frch_cfi_data == NULL)
  515. {
  516. as_bad (_("CFI instruction used without previous .cfi_startproc"));
  517. ignore_rest_of_line ();
  518. return;
  519. }
  520. fde = frchain_now->frch_cfi_data->cur_fde_data;
  521. encoding = get_absolute_expression ();
  522. if (encoding == DW_EH_PE_omit)
  523. {
  524. demand_empty_rest_of_line ();
  525. fde->per_encoding = encoding;
  526. return;
  527. }
  528. if ((encoding & 0xff) != encoding
  529. || ((encoding & 0x70) != 0
  530. #if defined DIFF_EXPR_OK || defined tc_cfi_emit_pcrel_expr
  531. && (encoding & 0x70) != DW_EH_PE_pcrel
  532. #endif
  533. )
  534. /* leb128 can be handled, but does something actually need it? */
  535. || (encoding & 7) == DW_EH_PE_uleb128
  536. || (encoding & 7) > DW_EH_PE_udata8)
  537. {
  538. as_bad (_("invalid or unsupported encoding in .cfi_personality"));
  539. ignore_rest_of_line ();
  540. return;
  541. }
  542. if (*input_line_pointer++ != ',')
  543. {
  544. as_bad (_(".cfi_personality requires encoding and symbol arguments"));
  545. ignore_rest_of_line ();
  546. return;
  547. }
  548. expression_and_evaluate (&fde->personality);
  549. switch (fde->personality.X_op)
  550. {
  551. case O_symbol:
  552. break;
  553. case O_constant:
  554. if ((encoding & 0x70) == DW_EH_PE_pcrel)
  555. encoding = DW_EH_PE_omit;
  556. break;
  557. default:
  558. encoding = DW_EH_PE_omit;
  559. break;
  560. }
  561. fde->per_encoding = encoding;
  562. if (encoding == DW_EH_PE_omit)
  563. {
  564. as_bad (_("wrong second argument to .cfi_personality"));
  565. ignore_rest_of_line ();
  566. return;
  567. }
  568. demand_empty_rest_of_line ();
  569. }
  570. static void
  571. dot_cfi_lsda (int ignored ATTRIBUTE_UNUSED)
  572. {
  573. struct fde_entry *fde;
  574. offsetT encoding;
  575. if (frchain_now->frch_cfi_data == NULL)
  576. {
  577. as_bad (_("CFI instruction used without previous .cfi_startproc"));
  578. ignore_rest_of_line ();
  579. return;
  580. }
  581. fde = frchain_now->frch_cfi_data->cur_fde_data;
  582. encoding = get_absolute_expression ();
  583. if (encoding == DW_EH_PE_omit)
  584. {
  585. demand_empty_rest_of_line ();
  586. fde->lsda_encoding = encoding;
  587. return;
  588. }
  589. if ((encoding & 0xff) != encoding
  590. || ((encoding & 0x70) != 0
  591. #if defined DIFF_EXPR_OK || defined tc_cfi_emit_pcrel_expr
  592. && (encoding & 0x70) != DW_EH_PE_pcrel
  593. #endif
  594. )
  595. /* leb128 can be handled, but does something actually need it? */
  596. || (encoding & 7) == DW_EH_PE_uleb128
  597. || (encoding & 7) > DW_EH_PE_udata8)
  598. {
  599. as_bad (_("invalid or unsupported encoding in .cfi_lsda"));
  600. ignore_rest_of_line ();
  601. return;
  602. }
  603. if (*input_line_pointer++ != ',')
  604. {
  605. as_bad (_(".cfi_lsda requires encoding and symbol arguments"));
  606. ignore_rest_of_line ();
  607. return;
  608. }
  609. fde->lsda_encoding = encoding;
  610. expression_and_evaluate (&fde->lsda);
  611. switch (fde->lsda.X_op)
  612. {
  613. case O_symbol:
  614. break;
  615. case O_constant:
  616. if ((encoding & 0x70) == DW_EH_PE_pcrel)
  617. encoding = DW_EH_PE_omit;
  618. break;
  619. default:
  620. encoding = DW_EH_PE_omit;
  621. break;
  622. }
  623. fde->lsda_encoding = encoding;
  624. if (encoding == DW_EH_PE_omit)
  625. {
  626. as_bad (_("wrong second argument to .cfi_lsda"));
  627. ignore_rest_of_line ();
  628. return;
  629. }
  630. demand_empty_rest_of_line ();
  631. }
  632. static void
  633. dot_cfi_startproc (int ignored ATTRIBUTE_UNUSED)
  634. {
  635. int simple = 0;
  636. if (frchain_now->frch_cfi_data != NULL)
  637. {
  638. as_bad (_("previous CFI entry not closed (missing .cfi_endproc)"));
  639. ignore_rest_of_line ();
  640. return;
  641. }
  642. cfi_new_fde (symbol_temp_new_now ());
  643. SKIP_WHITESPACE ();
  644. if (is_name_beginner (*input_line_pointer))
  645. {
  646. char *name, c;
  647. name = input_line_pointer;
  648. c = get_symbol_end ();
  649. if (strcmp (name, "simple") == 0)
  650. {
  651. simple = 1;
  652. *input_line_pointer = c;
  653. }
  654. else
  655. input_line_pointer = name;
  656. }
  657. demand_empty_rest_of_line ();
  658. frchain_now->frch_cfi_data->cur_cfa_offset = 0;
  659. if (!simple)
  660. tc_cfi_frame_initial_instructions ();
  661. }
  662. static void
  663. dot_cfi_endproc (int ignored ATTRIBUTE_UNUSED)
  664. {
  665. if (frchain_now->frch_cfi_data == NULL)
  666. {
  667. as_bad (_(".cfi_endproc without corresponding .cfi_startproc"));
  668. ignore_rest_of_line ();
  669. return;
  670. }
  671. cfi_end_fde (symbol_temp_new_now ());
  672. demand_empty_rest_of_line ();
  673. }
  674. /* Emit a single byte into the current segment. */
  675. static inline void
  676. out_one (int byte)
  677. {
  678. FRAG_APPEND_1_CHAR (byte);
  679. }
  680. /* Emit a two-byte word into the current segment. */
  681. static inline void
  682. out_two (int data)
  683. {
  684. md_number_to_chars (frag_more (2), data, 2);
  685. }
  686. /* Emit a four byte word into the current segment. */
  687. static inline void
  688. out_four (int data)
  689. {
  690. md_number_to_chars (frag_more (4), data, 4);
  691. }
  692. /* Emit an unsigned "little-endian base 128" number. */
  693. static void
  694. out_uleb128 (addressT value)
  695. {
  696. output_leb128 (frag_more (sizeof_leb128 (value, 0)), value, 0);
  697. }
  698. /* Emit an unsigned "little-endian base 128" number. */
  699. static void
  700. out_sleb128 (offsetT value)
  701. {
  702. output_leb128 (frag_more (sizeof_leb128 (value, 1)), value, 1);
  703. }
  704. static void
  705. output_cfi_insn (struct cfi_insn_data *insn)
  706. {
  707. offsetT offset;
  708. unsigned int regno;
  709. switch (insn->insn)
  710. {
  711. case DW_CFA_advance_loc:
  712. {
  713. symbolS *from = insn->u.ll.lab1;
  714. symbolS *to = insn->u.ll.lab2;
  715. if (symbol_get_frag (to) == symbol_get_frag (from))
  716. {
  717. addressT delta = S_GET_VALUE (to) - S_GET_VALUE (from);
  718. addressT scaled = delta / DWARF2_LINE_MIN_INSN_LENGTH;
  719. if (scaled <= 0x3F)
  720. out_one (DW_CFA_advance_loc + scaled);
  721. else if (delta <= 0xFF)
  722. {
  723. out_one (DW_CFA_advance_loc1);
  724. out_one (delta);
  725. }
  726. else if (delta <= 0xFFFF)
  727. {
  728. out_one (DW_CFA_advance_loc2);
  729. out_two (delta);
  730. }
  731. else
  732. {
  733. out_one (DW_CFA_advance_loc4);
  734. out_four (delta);
  735. }
  736. }
  737. else
  738. {
  739. expressionS exp;
  740. exp.X_op = O_subtract;
  741. exp.X_add_symbol = to;
  742. exp.X_op_symbol = from;
  743. exp.X_add_number = 0;
  744. /* The code in ehopt.c expects that one byte of the encoding
  745. is already allocated to the frag. This comes from the way
  746. that it scans the .eh_frame section looking first for the
  747. .byte DW_CFA_advance_loc4. */
  748. frag_more (1);
  749. frag_var (rs_cfa, 4, 0, DWARF2_LINE_MIN_INSN_LENGTH << 3,
  750. make_expr_symbol (&exp), frag_now_fix () - 1,
  751. (char *) frag_now);
  752. }
  753. }
  754. break;
  755. case DW_CFA_def_cfa:
  756. offset = insn->u.ri.offset;
  757. if (offset < 0)
  758. {
  759. out_one (DW_CFA_def_cfa_sf);
  760. out_uleb128 (insn->u.ri.reg);
  761. out_sleb128 (offset / DWARF2_CIE_DATA_ALIGNMENT);
  762. }
  763. else
  764. {
  765. out_one (DW_CFA_def_cfa);
  766. out_uleb128 (insn->u.ri.reg);
  767. out_uleb128 (offset);
  768. }
  769. break;
  770. case DW_CFA_def_cfa_register:
  771. case DW_CFA_undefined:
  772. case DW_CFA_same_value:
  773. out_one (insn->insn);
  774. out_uleb128 (insn->u.r);
  775. break;
  776. case DW_CFA_def_cfa_offset:
  777. offset = insn->u.i;
  778. if (offset < 0)
  779. {
  780. out_one (DW_CFA_def_cfa_offset_sf);
  781. out_sleb128 (offset / DWARF2_CIE_DATA_ALIGNMENT);
  782. }
  783. else
  784. {
  785. out_one (DW_CFA_def_cfa_offset);
  786. out_uleb128 (offset);
  787. }
  788. break;
  789. case DW_CFA_restore:
  790. regno = insn->u.r;
  791. if (regno <= 0x3F)
  792. {
  793. out_one (DW_CFA_restore + regno);
  794. }
  795. else
  796. {
  797. out_one (DW_CFA_restore_extended);
  798. out_uleb128 (regno);
  799. }
  800. break;
  801. case DW_CFA_offset:
  802. regno = insn->u.ri.reg;
  803. offset = insn->u.ri.offset / DWARF2_CIE_DATA_ALIGNMENT;
  804. if (offset < 0)
  805. {
  806. out_one (DW_CFA_offset_extended_sf);
  807. out_uleb128 (regno);
  808. out_sleb128 (offset);
  809. }
  810. else if (regno <= 0x3F)
  811. {
  812. out_one (DW_CFA_offset + regno);
  813. out_uleb128 (offset);
  814. }
  815. else
  816. {
  817. out_one (DW_CFA_offset_extended);
  818. out_uleb128 (regno);
  819. out_uleb128 (offset);
  820. }
  821. break;
  822. case DW_CFA_register:
  823. out_one (DW_CFA_register);
  824. out_uleb128 (insn->u.rr.reg1);
  825. out_uleb128 (insn->u.rr.reg2);
  826. break;
  827. case DW_CFA_remember_state:
  828. case DW_CFA_restore_state:
  829. out_one (insn->insn);
  830. break;
  831. case DW_CFA_GNU_window_save:
  832. out_one (DW_CFA_GNU_window_save);
  833. break;
  834. case CFI_escape:
  835. {
  836. struct cfi_escape_data *e;
  837. for (e = insn->u.esc; e ; e = e->next)
  838. emit_expr (&e->exp, 1);
  839. break;
  840. }
  841. default:
  842. abort ();
  843. }
  844. }
  845. static offsetT
  846. encoding_size (unsigned char encoding)
  847. {
  848. if (encoding == DW_EH_PE_omit)
  849. return 0;
  850. switch (encoding & 0x7)
  851. {
  852. case 0:
  853. return bfd_get_arch_size (stdoutput) == 64 ? 8 : 4;
  854. case DW_EH_PE_udata2:
  855. return 2;
  856. case DW_EH_PE_udata4:
  857. return 4;
  858. case DW_EH_PE_udata8:
  859. return 8;
  860. default:
  861. abort ();
  862. }
  863. }
  864. static void
  865. output_cie (struct cie_entry *cie)
  866. {
  867. symbolS *after_size_address, *end_address;
  868. expressionS exp;
  869. struct cfi_insn_data *i;
  870. offsetT augmentation_size;
  871. cie->start_address = symbol_temp_new_now ();
  872. after_size_address = symbol_temp_make ();
  873. end_address = symbol_temp_make ();
  874. exp.X_op = O_subtract;
  875. exp.X_add_symbol = end_address;
  876. exp.X_op_symbol = after_size_address;
  877. exp.X_add_number = 0;
  878. emit_expr (&exp, 4); /* Length. */
  879. symbol_set_value_now (after_size_address);
  880. out_four (0); /* CIE id. */
  881. out_one (DW_CIE_VERSION); /* Version. */
  882. out_one ('z'); /* Augmentation. */
  883. if (cie->per_encoding != DW_EH_PE_omit)
  884. out_one ('P');
  885. if (cie->lsda_encoding != DW_EH_PE_omit)
  886. out_one ('L');
  887. out_one ('R');
  888. if (cie->signal_frame)
  889. out_one ('S');
  890. out_one (0);
  891. out_uleb128 (DWARF2_LINE_MIN_INSN_LENGTH); /* Code alignment. */
  892. out_sleb128 (DWARF2_CIE_DATA_ALIGNMENT); /* Data alignment. */
  893. if (DW_CIE_VERSION == 1) /* Return column. */
  894. out_one (cie->return_column);
  895. else
  896. out_uleb128 (cie->return_column);
  897. augmentation_size = 1 + (cie->lsda_encoding != DW_EH_PE_omit);
  898. if (cie->per_encoding != DW_EH_PE_omit)
  899. augmentation_size += 1 + encoding_size (cie->per_encoding);
  900. out_uleb128 (augmentation_size); /* Augmentation size. */
  901. if (cie->per_encoding != DW_EH_PE_omit)
  902. {
  903. offsetT size = encoding_size (cie->per_encoding);
  904. out_one (cie->per_encoding);
  905. exp = cie->personality;
  906. if ((cie->per_encoding & 0x70) == DW_EH_PE_pcrel)
  907. {
  908. #ifdef DIFF_EXPR_OK
  909. exp.X_op = O_subtract;
  910. exp.X_op_symbol = symbol_temp_new_now ();
  911. emit_expr (&exp, size);
  912. #elif defined (tc_cfi_emit_pcrel_expr)
  913. tc_cfi_emit_pcrel_expr (&exp, size);
  914. #else
  915. abort ();
  916. #endif
  917. }
  918. else
  919. emit_expr (&exp, size);
  920. }
  921. if (cie->lsda_encoding != DW_EH_PE_omit)
  922. out_one (cie->lsda_encoding);
  923. #if defined DIFF_EXPR_OK || defined tc_cfi_emit_pcrel_expr
  924. out_one (DW_EH_PE_pcrel | DW_EH_PE_sdata4);
  925. #else
  926. out_one (DW_EH_PE_sdata4);
  927. #endif
  928. if (cie->first)
  929. for (i = cie->first; i != cie->last; i = i->next)
  930. output_cfi_insn (i);
  931. frag_align (2, DW_CFA_nop, 0);
  932. symbol_set_value_now (end_address);
  933. }
  934. static void
  935. output_fde (struct fde_entry *fde, struct cie_entry *cie,
  936. struct cfi_insn_data *first, int align)
  937. {
  938. symbolS *after_size_address, *end_address;
  939. expressionS exp;
  940. offsetT augmentation_size;
  941. after_size_address = symbol_temp_make ();
  942. end_address = symbol_temp_make ();
  943. exp.X_op = O_subtract;
  944. exp.X_add_symbol = end_address;
  945. exp.X_op_symbol = after_size_address;
  946. exp.X_add_number = 0;
  947. emit_expr (&exp, 4); /* Length. */
  948. symbol_set_value_now (after_size_address);
  949. exp.X_add_symbol = after_size_address;
  950. exp.X_op_symbol = cie->start_address;
  951. emit_expr (&exp, 4); /* CIE offset. */
  952. #ifdef DIFF_EXPR_OK
  953. exp.X_add_symbol = fde->start_address;
  954. exp.X_op_symbol = symbol_temp_new_now ();
  955. emit_expr (&exp, 4); /* Code offset. */
  956. #else
  957. exp.X_op = O_symbol;
  958. exp.X_add_symbol = fde->start_address;
  959. exp.X_op_symbol = NULL;
  960. #ifdef tc_cfi_emit_pcrel_expr
  961. tc_cfi_emit_pcrel_expr (&exp, 4); /* Code offset. */
  962. #else
  963. emit_expr (&exp, 4); /* Code offset. */
  964. #endif
  965. exp.X_op = O_subtract;
  966. #endif
  967. exp.X_add_symbol = fde->end_address;
  968. exp.X_op_symbol = fde->start_address; /* Code length. */
  969. emit_expr (&exp, 4);
  970. augmentation_size = encoding_size (fde->lsda_encoding);
  971. out_uleb128 (augmentation_size); /* Augmentation size. */
  972. if (fde->lsda_encoding != DW_EH_PE_omit)
  973. {
  974. exp = fde->lsda;
  975. if ((fde->lsda_encoding & 0x70) == DW_EH_PE_pcrel)
  976. {
  977. #ifdef DIFF_EXPR_OK
  978. exp.X_op = O_subtract;
  979. exp.X_op_symbol = symbol_temp_new_now ();
  980. emit_expr (&exp, augmentation_size);
  981. #elif defined (tc_cfi_emit_pcrel_expr)
  982. tc_cfi_emit_pcrel_expr (&exp, augmentation_size);
  983. #else
  984. abort ();
  985. #endif
  986. }
  987. else
  988. emit_expr (&exp, augmentation_size);
  989. }
  990. for (; first; first = first->next)
  991. output_cfi_insn (first);
  992. frag_align (align, DW_CFA_nop, 0);
  993. symbol_set_value_now (end_address);
  994. }
  995. static struct cie_entry *
  996. select_cie_for_fde (struct fde_entry *fde, struct cfi_insn_data **pfirst)
  997. {
  998. struct cfi_insn_data *i, *j;
  999. struct cie_entry *cie;
  1000. for (cie = cie_root; cie; cie = cie->next)
  1001. {
  1002. if (cie->return_column != fde->return_column
  1003. || cie->signal_frame != fde->signal_frame
  1004. || cie->per_encoding != fde->per_encoding
  1005. || cie->lsda_encoding != fde->lsda_encoding)
  1006. continue;
  1007. if (cie->per_encoding != DW_EH_PE_omit)
  1008. {
  1009. if (cie->personality.X_op != fde->personality.X_op
  1010. || cie->personality.X_add_number
  1011. != fde->personality.X_add_number)
  1012. continue;
  1013. switch (cie->personality.X_op)
  1014. {
  1015. case O_constant:
  1016. if (cie->personality.X_unsigned != fde->personality.X_unsigned)
  1017. continue;
  1018. break;
  1019. case O_symbol:
  1020. if (cie->personality.X_add_symbol
  1021. != fde->personality.X_add_symbol)
  1022. continue;
  1023. break;
  1024. default:
  1025. abort ();
  1026. }
  1027. }
  1028. for (i = cie->first, j = fde->data;
  1029. i != cie->last && j != NULL;
  1030. i = i->next, j = j->next)
  1031. {
  1032. if (i->insn != j->insn)
  1033. goto fail;
  1034. switch (i->insn)
  1035. {
  1036. case DW_CFA_advance_loc:
  1037. case DW_CFA_remember_state:
  1038. /* We reached the first advance/remember in the FDE,
  1039. but did not reach the end of the CIE list. */
  1040. goto fail;
  1041. case DW_CFA_offset:
  1042. case DW_CFA_def_cfa:
  1043. if (i->u.ri.reg != j->u.ri.reg)
  1044. goto fail;
  1045. if (i->u.ri.offset != j->u.ri.offset)
  1046. goto fail;
  1047. break;
  1048. case DW_CFA_register:
  1049. if (i->u.rr.reg1 != j->u.rr.reg1)
  1050. goto fail;
  1051. if (i->u.rr.reg2 != j->u.rr.reg2)
  1052. goto fail;
  1053. break;
  1054. case DW_CFA_def_cfa_register:
  1055. case DW_CFA_restore:
  1056. case DW_CFA_undefined:
  1057. case DW_CFA_same_value:
  1058. if (i->u.r != j->u.r)
  1059. goto fail;
  1060. break;
  1061. case DW_CFA_def_cfa_offset:
  1062. if (i->u.i != j->u.i)
  1063. goto fail;
  1064. break;
  1065. case CFI_escape:
  1066. /* Don't bother matching these for now. */
  1067. goto fail;
  1068. default:
  1069. abort ();
  1070. }
  1071. }
  1072. /* Success if we reached the end of the CIE list, and we've either
  1073. run out of FDE entries or we've encountered an advance,
  1074. remember, or escape. */
  1075. if (i == cie->last
  1076. && (!j
  1077. || j->insn == DW_CFA_advance_loc
  1078. || j->insn == DW_CFA_remember_state
  1079. || j->insn == CFI_escape))
  1080. {
  1081. *pfirst = j;
  1082. return cie;
  1083. }
  1084. fail:;
  1085. }
  1086. cie = xmalloc (sizeof (struct cie_entry));
  1087. cie->next = cie_root;
  1088. cie_root = cie;
  1089. cie->return_column = fde->return_column;
  1090. cie->signal_frame = fde->signal_frame;
  1091. cie->per_encoding = fde->per_encoding;
  1092. cie->lsda_encoding = fde->lsda_encoding;
  1093. cie->personality = fde->personality;
  1094. cie->first = fde->data;
  1095. for (i = cie->first; i ; i = i->next)
  1096. if (i->insn == DW_CFA_advance_loc
  1097. || i->insn == DW_CFA_remember_state
  1098. || i->insn == CFI_escape)
  1099. break;
  1100. cie->last = i;
  1101. *pfirst = i;
  1102. output_cie (cie);
  1103. return cie;
  1104. }
  1105. void
  1106. cfi_finish (void)
  1107. {
  1108. segT cfi_seg;
  1109. struct fde_entry *fde;
  1110. int save_flag_traditional_format;
  1111. if (all_fde_data == 0)
  1112. return;
  1113. /* Open .eh_frame section. */
  1114. cfi_seg = subseg_new (".eh_frame", 0);
  1115. bfd_set_section_flags (stdoutput, cfi_seg,
  1116. SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_READONLY);
  1117. subseg_set (cfi_seg, 0);
  1118. record_alignment (cfi_seg, EH_FRAME_ALIGNMENT);
  1119. /* Make sure check_eh_frame doesn't do anything with our output. */
  1120. save_flag_traditional_format = flag_traditional_format;
  1121. flag_traditional_format = 1;
  1122. for (fde = all_fde_data; fde ; fde = fde->next)
  1123. {
  1124. struct cfi_insn_data *first;
  1125. struct cie_entry *cie;
  1126. if (fde->end_address == NULL)
  1127. {
  1128. as_bad (_("open CFI at the end of file; missing .cfi_endproc directive"));
  1129. fde->end_address = fde->start_address;
  1130. }
  1131. cie = select_cie_for_fde (fde, &first);
  1132. output_fde (fde, cie, first, fde->next == NULL ? EH_FRAME_ALIGNMENT : 2);
  1133. }
  1134. flag_traditional_format = save_flag_traditional_format;
  1135. }