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