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