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