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