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