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