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