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