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