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