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