Coverage Report

Created: 2026-03-10 08:46

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/binutils-gdb/gas/dw2gencfi.c
Line
Count
Source
1
/* dw2gencfi.c - Support for generating Dwarf2 CFI information.
2
   Copyright (C) 2003-2026 Free Software Foundation, Inc.
3
   Contributed by Michal Ludvig <mludvig@suse.cz>
4
5
   This file is part of GAS, the GNU Assembler.
6
7
   GAS is free software; you can redistribute it and/or modify
8
   it under the terms of the GNU General Public License as published by
9
   the Free Software Foundation; either version 3, or (at your option)
10
   any later version.
11
12
   GAS is distributed in the hope that it will be useful,
13
   but WITHOUT ANY WARRANTY; without even the implied warranty of
14
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
   GNU General Public License for more details.
16
17
   You should have received a copy of the GNU General Public License
18
   along with GAS; see the file COPYING.  If not, write to the Free
19
   Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
20
   02110-1301, USA.  */
21
22
#include "as.h"
23
#include "dw2gencfi.h"
24
#include "subsegs.h"
25
#include "dwarf2dbg.h"
26
#include "gen-sframe.h"
27
28
#ifdef TARGET_USE_CFIPOP
29
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
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
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.  */
49
#ifndef DWARF2_LINE_MIN_INSN_LENGTH
50
39
#define DWARF2_LINE_MIN_INSN_LENGTH 1
51
#endif
52
53
/* By default, use 32-bit relocations from .eh_frame into .text.  */
54
#ifndef DWARF2_FDE_RELOC_SIZE
55
65
#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
28
#define DWARF2_EH_FRAME_READ_ONLY SEC_READONLY
61
#endif
62
63
#ifndef EH_FRAME_ALIGNMENT
64
50
#define EH_FRAME_ALIGNMENT (bfd_get_arch_size (stdoutput) == 64 ? 3 : 2)
65
#endif
66
67
132
#define EH_FRAME_LINKONCE (SUPPORT_FRAME_LINKONCE || compact_eh \
68
132
         || TARGET_MULTIPLE_EH_FRAME_SECTIONS)
69
70
#ifndef DWARF2_FORMAT
71
67
#define DWARF2_FORMAT(SEC) dwarf2_format_32bit
72
#endif
73
74
#ifndef DWARF2_ADDR_SIZE
75
#define DWARF2_ADDR_SIZE(bfd) (bfd_arch_bits_per_address (bfd) / 8)
76
#endif
77
78
#if MULTIPLE_FRAME_SECTIONS
79
#define CUR_SEG(structp) structp->cur_seg
80
#define SET_CUR_SEG(structp, seg) structp->cur_seg = seg
81
#define HANDLED(structp) structp->handled
82
#define SET_HANDLED(structp, val) structp->handled = val
83
#else
84
382
#define CUR_SEG(structp) NULL
85
285
#define SET_CUR_SEG(structp, seg) (void) (0 && seg)
86
0
#define HANDLED(structp) 0
87
39
#define SET_HANDLED(structp, val) (void) (0 && val)
88
#endif
89
90
#ifndef tc_cfi_reloc_for_encoding
91
35
#define tc_cfi_reloc_for_encoding(e) BFD_RELOC_NONE
92
#endif
93
94
/* Private segment collection list.  */
95
struct dwcfi_seg_list
96
{
97
  segT   seg;
98
  int    subseg;
99
  char * seg_name;
100
};
101
102
#ifdef SUPPORT_COMPACT_EH
103
static bool compact_eh;
104
#else
105
#define compact_eh 0
106
#endif
107
108
static htab_t dwcfi_hash;
109

110
/* Emit a single byte into the current segment.  */
111
112
static inline void
113
out_one (int byte)
114
362
{
115
362
  FRAG_APPEND_1_CHAR (byte);
116
362
}
117
118
/* Emit a two-byte word into the current segment.  */
119
120
static inline void
121
out_two (int data)
122
1
{
123
1
  md_number_to_chars (frag_more (2), data, 2);
124
1
}
125
126
/* Emit a four byte word into the current segment.  */
127
128
static inline void
129
out_four (int data)
130
34
{
131
34
  md_number_to_chars (frag_more (4), data, 4);
132
34
}
133
134
/* Emit an unsigned "little-endian base 128" number.  */
135
136
static void
137
out_uleb128 (addressT value)
138
299
{
139
299
  output_leb128 (frag_more (sizeof_leb128 (value, 0)), value, 0);
140
299
}
141
142
/* Emit an unsigned "little-endian base 128" number.  */
143
144
static void
145
out_sleb128 (offsetT value)
146
45
{
147
45
  output_leb128 (frag_more (sizeof_leb128 (value, 1)), value, 1);
148
45
}
149
150
static unsigned int
151
encoding_size (unsigned char encoding)
152
99
{
153
99
  if (encoding == DW_EH_PE_omit)
154
93
    return 0;
155
6
  switch (encoding & 0x7)
156
6
    {
157
4
    case 0:
158
4
      return bfd_get_arch_size (stdoutput) == 64 ? 8 : 4;
159
2
    case DW_EH_PE_udata2:
160
2
      return 2;
161
0
    case DW_EH_PE_udata4:
162
0
      return 4;
163
0
    case DW_EH_PE_udata8:
164
0
      return 8;
165
0
    default:
166
0
      abort ();
167
6
    }
168
6
}
169
170
/* Emit expression EXP in ENCODING.  If EMIT_ENCODING is true, first
171
   emit a byte containing ENCODING.  */
172
173
static void
174
emit_expr_encoded (expressionS *exp, int encoding, bool emit_encoding)
175
65
{
176
65
  unsigned int size = encoding_size (encoding);
177
65
  bfd_reloc_code_real_type code;
178
179
65
  if (encoding == DW_EH_PE_omit)
180
62
    return;
181
182
3
  if (emit_encoding)
183
0
    out_one (encoding);
184
185
3
  code = tc_cfi_reloc_for_encoding (encoding);
186
3
  if (code != BFD_RELOC_NONE)
187
0
    {
188
0
      reloc_howto_type *howto = bfd_reloc_type_lookup (stdoutput, code);
189
0
      char *p = frag_more (size);
190
0
      gas_assert (size == (unsigned) howto->bitsize / 8);
191
0
      md_number_to_chars (p, 0, size);
192
0
      fix_new (frag_now, p - frag_now->fr_literal, size, exp->X_add_symbol,
193
0
         exp->X_add_number, howto->pc_relative, code);
194
0
    }
195
3
  else if ((encoding & 0x70) == DW_EH_PE_pcrel)
196
0
    {
197
0
#if CFI_DIFF_EXPR_OK
198
0
      expressionS tmp = *exp;
199
0
      tmp.X_op = O_subtract;
200
0
      tmp.X_op_symbol = symbol_temp_new_now ();
201
0
      emit_expr (&tmp, size);
202
#elif defined (tc_cfi_emit_pcrel_expr)
203
      tc_cfi_emit_pcrel_expr (exp, size);
204
#else
205
      abort ();
206
#endif
207
0
    }
208
3
  else
209
3
    emit_expr (exp, size);
210
3
}
211

212
/* Build based on segment the derived .debug_...
213
   segment name containing origin segment's postfix name part.  */
214
215
static char *
216
get_debugseg_name (segT seg, const char *base_name)
217
0
{
218
0
  const char * name;
219
0
  const char * dollar;
220
0
  const char * dot;
221
222
0
  if (!seg
223
0
      || (name = bfd_section_name (seg)) == NULL
224
0
      || *name == 0)
225
0
    return notes_strdup (base_name);
226
  
227
0
  dollar = strchr (name, '$');
228
0
  dot = strchr (name + 1, '.');
229
230
0
  if (!dollar && !dot)
231
0
    {
232
0
      if (!strcmp (base_name, ".eh_frame_entry")
233
0
    && strcmp (name, ".text") != 0)
234
0
  return notes_concat (base_name, ".", name, (const char *) NULL);
235
236
0
      name = "";
237
0
    }
238
0
  else if (!dollar)
239
0
    name = dot;
240
0
  else if (!dot)
241
0
    name = dollar;
242
0
  else if (dot < dollar)
243
0
    name = dot;
244
0
  else
245
0
    name = dollar;
246
247
0
  return notes_concat (base_name, name, (const char *) NULL);
248
0
}
249
250
/* Allocate a dwcfi_seg_list structure.  */
251
252
static struct dwcfi_seg_list *
253
alloc_debugseg_item (segT seg, int subseg, char *name)
254
0
{
255
0
  struct dwcfi_seg_list *r;
256
257
0
  r = notes_alloc (sizeof (*r) + strlen (name));
258
0
  r->seg = seg;
259
0
  r->subseg = subseg;
260
0
  r->seg_name = name;
261
0
  return r;
262
0
}
263
264
static segT
265
is_now_linkonce_segment (void)
266
0
{
267
0
  if (compact_eh)
268
0
    return now_seg;
269
0
270
0
  if (TARGET_MULTIPLE_EH_FRAME_SECTIONS)
271
0
    return now_seg;
272
0
273
0
  if ((bfd_section_flags (now_seg)
274
0
       & (SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD
275
0
    | SEC_LINK_DUPLICATES_ONE_ONLY | SEC_LINK_DUPLICATES_SAME_SIZE
276
0
    | SEC_LINK_DUPLICATES_SAME_CONTENTS)) != 0)
277
0
    return now_seg;
278
0
  return NULL;
279
0
}
280
281
/* Generate debug... segment with same linkonce properties
282
   of based segment.  */
283
284
static segT
285
make_debug_seg (segT cseg, char *name, int sflags)
286
0
{
287
0
  segT save_seg = now_seg;
288
0
  int save_subseg = now_subseg;
289
0
  segT r;
290
0
  flagword flags;
291
292
0
  r = subseg_new (name, 0);
293
294
  /* Check if code segment is marked as linked once.  */
295
0
  if (!cseg)
296
0
    flags = 0;
297
0
  else
298
0
    flags = (bfd_section_flags (cseg)
299
0
       & (SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD
300
0
    | SEC_LINK_DUPLICATES_ONE_ONLY | SEC_LINK_DUPLICATES_SAME_SIZE
301
0
    | SEC_LINK_DUPLICATES_SAME_CONTENTS));
302
303
  /* Add standard section flags.  */
304
0
  flags |= sflags;
305
306
  /* Apply possibly linked once flags to new generated segment, too.  */
307
0
  if (!bfd_set_section_flags (r, flags))
308
0
    as_bad (_("bfd_set_section_flags: %s"),
309
0
      bfd_errmsg (bfd_get_error ()));
310
311
  /* Restore to previous segment.  */
312
0
  if (save_seg != NULL)
313
0
    subseg_set (save_seg, save_subseg);
314
0
  return r;
315
0
}
316
317
static struct dwcfi_seg_list *
318
dwcfi_hash_find (char *name)
319
0
{
320
0
  return (struct dwcfi_seg_list *) str_hash_find (dwcfi_hash, name);
321
0
}
322
323
static struct dwcfi_seg_list *
324
dwcfi_hash_find_or_make (segT cseg, const char *base_name, int flags)
325
0
{
326
0
  struct dwcfi_seg_list *item;
327
0
  char *name;
328
329
  /* Initialize dwcfi_hash once.  */
330
0
  if (!dwcfi_hash)
331
0
    dwcfi_hash = str_htab_create ();
332
333
0
  name = get_debugseg_name (cseg, base_name);
334
335
0
  item = dwcfi_hash_find (name);
336
0
  if (!item)
337
0
    {
338
0
      item = alloc_debugseg_item (make_debug_seg (cseg, name, flags), 0, name);
339
340
0
      str_hash_insert (dwcfi_hash, item->seg_name, item, 0);
341
0
    }
342
0
  else
343
0
    notes_free (name);
344
345
0
  return item;
346
0
}
347
348
/* ??? Share this with dwarf2cfg.c.  */
349
#ifndef TC_DWARF2_EMIT_OFFSET
350
2
#define TC_DWARF2_EMIT_OFFSET  generic_dwarf2_emit_offset
351
352
/* Create an offset to .dwarf2_*.  */
353
354
static void
355
generic_dwarf2_emit_offset (symbolS *symbol, unsigned int size)
356
2
{
357
2
  expressionS exp;
358
359
2
  exp.X_op = O_symbol;
360
2
  exp.X_add_symbol = symbol;
361
2
  exp.X_add_number = 0;
362
2
  emit_expr (&exp, size);
363
2
}
364
#endif
365
366
struct cie_entry
367
{
368
  struct cie_entry *next;
369
#if MULTIPLE_FRAME_SECTIONS
370
  segT cur_seg;
371
#endif
372
  symbolS *start_address;
373
  unsigned int return_column;
374
  unsigned int signal_frame;
375
  unsigned char fde_encoding;
376
  unsigned char per_encoding;
377
  unsigned char lsda_encoding;
378
  expressionS personality;
379
#ifdef tc_cie_entry_extras
380
  tc_cie_entry_extras
381
#endif
382
  struct cfi_insn_data *first, *last;
383
};
384
385
/* List of FDE entries.  */
386
387
struct fde_entry *all_fde_data;
388
static struct fde_entry **last_fde_data = &all_fde_data;
389
390
/* List of CIEs so that they could be reused.  */
391
static struct cie_entry *cie_root;
392
393
/* Construct a new FDE structure and add it to the end of the fde list.  */
394
395
static struct fde_entry *
396
alloc_fde_entry (void)
397
39
{
398
39
  struct fde_entry *fde = notes_calloc (1, sizeof (*fde));
399
400
39
  frchain_now->frch_cfi_data = notes_calloc (1, sizeof (struct frch_cfi_data));
401
39
  frchain_now->frch_cfi_data->cur_fde_data = fde;
402
39
  *last_fde_data = fde;
403
39
  last_fde_data = &fde->next;
404
39
  SET_CUR_SEG (fde, is_now_linkonce_segment ());
405
39
  SET_HANDLED (fde, 0);
406
39
  fde->last = &fde->data;
407
39
  fde->return_column = DWARF2_DEFAULT_RETURN_COLUMN;
408
39
  fde->per_encoding = DW_EH_PE_omit;
409
39
  fde->lsda_encoding = DW_EH_PE_omit;
410
39
  fde->eh_header_type = EH_COMPACT_UNKNOWN;
411
#ifdef tc_fde_entry_init_extra
412
  tc_fde_entry_init_extra (fde);
413
#endif
414
415
39
  return fde;
416
39
}
417
418
/* The following functions are available for a backend to construct its
419
   own unwind information, usually from legacy unwind directives.  */
420
421
/* Construct a new INSN structure and add it to the end of the insn list
422
   for the currently active FDE.  */
423
424
static bool cfi_sections_set = false;
425
static int cfi_sections = CFI_EMIT_eh_frame;
426
int all_cfi_sections = 0;
427
static struct fde_entry *last_fde;
428
429
static struct cfi_insn_data *
430
alloc_cfi_insn_data (void)
431
213
{
432
213
  struct cfi_insn_data *insn = notes_calloc (1, sizeof (*insn));
433
213
  struct fde_entry *cur_fde_data = frchain_now->frch_cfi_data->cur_fde_data;
434
435
213
  *cur_fde_data->last = insn;
436
213
  cur_fde_data->last = &insn->next;
437
213
  SET_CUR_SEG (insn, is_now_linkonce_segment ());
438
213
#ifndef NO_LISTING
439
213
  insn->listing_ctxt = cur_fde_data->listing_ctxt ? listing_tail : NULL;
440
213
#endif
441
213
  return insn;
442
213
}
443
444
/* Construct a new FDE structure that begins at LABEL.  */
445
446
void
447
cfi_new_fde (symbolS *label, bool do_listing)
448
39
{
449
39
  struct fde_entry *fde = alloc_fde_entry ();
450
39
  fde->start_address = label;
451
39
  if (do_listing)
452
0
    {
453
0
#ifndef NO_LISTING
454
0
      fde->listing_ctxt = listing_tail;
455
0
#endif
456
0
    }
457
39
  frchain_now->frch_cfi_data->last_address = label;
458
39
}
459
460
/* End the currently open FDE.  */
461
462
void
463
cfi_end_fde (symbolS *label)
464
0
{
465
0
  struct fde_entry *cur_fde_data = frchain_now->frch_cfi_data->cur_fde_data;
466
467
0
  cur_fde_data->end_address = label;
468
0
#ifndef NO_LISTING
469
0
  cur_fde_data->listing_end = cur_fde_data->listing_ctxt ? listing_tail : NULL;
470
0
#endif
471
0
  frchain_now->frch_cfi_data = NULL;
472
0
}
473
474
/* Set the last FDE  .*/
475
void
476
cfi_set_last_fde (struct fde_entry *fde)
477
0
{
478
0
  last_fde = fde;
479
0
}
480
481
/* Set the return column for the current FDE.  */
482
483
void
484
cfi_set_return_column (unsigned regno)
485
0
{
486
0
  frchain_now->frch_cfi_data->cur_fde_data->return_column = regno;
487
0
}
488
489
void
490
cfi_set_sections (void)
491
39
{
492
39
  all_cfi_sections |= cfi_sections;
493
39
  frchain_now->frch_cfi_data->cur_fde_data->sections = all_cfi_sections;
494
39
  cfi_sections_set = true;
495
39
}
496
497
/* Universal functions to store new instructions.  */
498
499
static void
500
cfi_add_CFA_insn (int insn)
501
4
{
502
4
  struct cfi_insn_data *insn_ptr = alloc_cfi_insn_data ();
503
504
4
  insn_ptr->insn = insn;
505
4
}
506
507
static void
508
cfi_add_CFA_insn_reg (int insn, unsigned regno)
509
63
{
510
63
  struct cfi_insn_data *insn_ptr = alloc_cfi_insn_data ();
511
512
63
  insn_ptr->insn = insn;
513
63
  insn_ptr->u.r = regno;
514
63
}
515
516
static void
517
cfi_add_CFA_insn_offset (int insn, offsetT offset)
518
0
{
519
0
  struct cfi_insn_data *insn_ptr = alloc_cfi_insn_data ();
520
521
0
  insn_ptr->insn = insn;
522
0
  insn_ptr->u.i = offset;
523
0
}
524
525
static void
526
cfi_add_CFA_insn_reg_reg (int insn, unsigned reg1, unsigned reg2)
527
0
{
528
0
  struct cfi_insn_data *insn_ptr = alloc_cfi_insn_data ();
529
530
0
  insn_ptr->insn = insn;
531
0
  insn_ptr->u.rr.reg1 = reg1;
532
0
  insn_ptr->u.rr.reg2 = reg2;
533
0
}
534
535
static void
536
cfi_add_CFA_insn_reg_offset (int insn, unsigned regno, offsetT offset)
537
119
{
538
119
  struct cfi_insn_data *insn_ptr = alloc_cfi_insn_data ();
539
540
119
  insn_ptr->insn = insn;
541
119
  insn_ptr->u.ri.reg = regno;
542
119
  insn_ptr->u.ri.offset = offset;
543
119
}
544
545
/* Add a CFI insn to advance the PC from the last address to LABEL.  */
546
547
void
548
cfi_add_advance_loc (symbolS *label)
549
10
{
550
10
  struct cfi_insn_data *insn = alloc_cfi_insn_data ();
551
552
10
  insn->insn = DW_CFA_advance_loc;
553
10
  insn->u.ll.lab1 = frchain_now->frch_cfi_data->last_address;
554
10
  insn->u.ll.lab2 = label;
555
556
10
  frchain_now->frch_cfi_data->last_address = label;
557
10
}
558
559
/* Add a CFI insn to label the current position in the CFI segment.  */
560
561
void
562
cfi_add_label (const char *name)
563
0
{
564
0
  struct cfi_insn_data *insn = alloc_cfi_insn_data ();
565
566
0
  insn->insn = CFI_label;
567
0
  insn->u.sym_name = notes_strdup (name);
568
0
}
569
570
/* Add a DW_CFA_offset record to the CFI data.  */
571
572
void
573
cfi_add_CFA_offset (unsigned regno, offsetT offset)
574
58
{
575
58
  unsigned int abs_data_align;
576
577
58
  gas_assert (DWARF2_CIE_DATA_ALIGNMENT != 0);
578
58
  cfi_add_CFA_insn_reg_offset (DW_CFA_offset, regno, offset);
579
580
58
  abs_data_align = (DWARF2_CIE_DATA_ALIGNMENT < 0
581
58
        ? -DWARF2_CIE_DATA_ALIGNMENT : DWARF2_CIE_DATA_ALIGNMENT);
582
58
  if (offset % abs_data_align)
583
3
    as_bad (_("register save offset not a multiple of %u"), abs_data_align);
584
58
}
585
586
/* Add a DW_CFA_val_offset record to the CFI data.  */
587
588
void
589
cfi_add_CFA_val_offset (unsigned regno, offsetT offset)
590
0
{
591
0
  unsigned int abs_data_align;
592
593
0
  gas_assert (DWARF2_CIE_DATA_ALIGNMENT != 0);
594
0
  cfi_add_CFA_insn_reg_offset (DW_CFA_val_offset, regno, offset);
595
596
0
  abs_data_align = (DWARF2_CIE_DATA_ALIGNMENT < 0
597
0
        ? -DWARF2_CIE_DATA_ALIGNMENT : DWARF2_CIE_DATA_ALIGNMENT);
598
0
  if (offset % abs_data_align)
599
0
    as_bad (_("register save offset not a multiple of %u"), abs_data_align);
600
0
}
601
602
/* Add a DW_CFA_def_cfa record to the CFI data.  */
603
604
void
605
cfi_add_CFA_def_cfa (unsigned regno, offsetT offset)
606
61
{
607
61
  cfi_add_CFA_insn_reg_offset (DW_CFA_def_cfa, regno, offset);
608
61
  frchain_now->frch_cfi_data->cur_cfa_offset = offset;
609
61
}
610
611
/* Add a DW_CFA_register record to the CFI data.  */
612
613
void
614
cfi_add_CFA_register (unsigned reg1, unsigned reg2)
615
0
{
616
0
  cfi_add_CFA_insn_reg_reg (DW_CFA_register, reg1, reg2);
617
0
}
618
619
/* Add a DW_CFA_def_cfa_register record to the CFI data.  */
620
621
void
622
cfi_add_CFA_def_cfa_register (unsigned regno)
623
1
{
624
1
  cfi_add_CFA_insn_reg (DW_CFA_def_cfa_register, regno);
625
1
}
626
627
/* Add a DW_CFA_def_cfa_offset record to the CFI data.  */
628
629
void
630
cfi_add_CFA_def_cfa_offset (offsetT offset)
631
0
{
632
0
  cfi_add_CFA_insn_offset (DW_CFA_def_cfa_offset, offset);
633
0
  frchain_now->frch_cfi_data->cur_cfa_offset = offset;
634
0
}
635
636
void
637
cfi_add_CFA_restore (unsigned regno)
638
0
{
639
0
  cfi_add_CFA_insn_reg (DW_CFA_restore, regno);
640
0
}
641
642
void
643
cfi_add_CFA_undefined (unsigned regno)
644
62
{
645
62
  cfi_add_CFA_insn_reg (DW_CFA_undefined, regno);
646
62
}
647
648
void
649
cfi_add_CFA_same_value (unsigned regno)
650
0
{
651
0
  cfi_add_CFA_insn_reg (DW_CFA_same_value, regno);
652
0
}
653
654
void
655
cfi_add_CFA_remember_state (void)
656
0
{
657
0
  struct cfa_save_data *p;
658
659
0
  cfi_add_CFA_insn (DW_CFA_remember_state);
660
661
0
  p = notes_alloc (sizeof (*p));
662
0
  p->cfa_offset = frchain_now->frch_cfi_data->cur_cfa_offset;
663
0
  p->next = frchain_now->frch_cfi_data->cfa_save_stack;
664
0
  frchain_now->frch_cfi_data->cfa_save_stack = p;
665
0
}
666
667
void
668
cfi_add_CFA_restore_state (void)
669
0
{
670
0
  struct cfa_save_data *p;
671
672
0
  cfi_add_CFA_insn (DW_CFA_restore_state);
673
674
0
  p = frchain_now->frch_cfi_data->cfa_save_stack;
675
0
  if (p)
676
0
    {
677
0
      frchain_now->frch_cfi_data->cur_cfa_offset = p->cfa_offset;
678
0
      frchain_now->frch_cfi_data->cfa_save_stack = p->next;
679
0
    }
680
0
  else
681
0
    as_bad (_("CFI state restore without previous remember"));
682
0
}
683
684

685
/* Parse CFI assembler directives.  */
686
687
static void dot_cfi (int);
688
static void dot_cfi_escape (int);
689
static void dot_cfi_startproc (int);
690
static void dot_cfi_endproc (int);
691
static void dot_cfi_fde_data (int);
692
static void dot_cfi_personality (int);
693
static void dot_cfi_personality_id (int);
694
static void dot_cfi_lsda (int);
695
static void dot_cfi_val_encoded_addr (int);
696
static void dot_cfi_inline_lsda (int);
697
static void dot_cfi_label (int);
698
699
const pseudo_typeS cfi_pseudo_table[] =
700
  {
701
    { "cfi_sections", dot_cfi_sections, 0 },
702
    { "cfi_startproc", dot_cfi_startproc, 0 },
703
    { "cfi_endproc", dot_cfi_endproc, 0 },
704
    { "cfi_fde_data", dot_cfi_fde_data, 0 },
705
    { "cfi_def_cfa", dot_cfi, DW_CFA_def_cfa },
706
    { "cfi_def_cfa_register", dot_cfi, DW_CFA_def_cfa_register },
707
    { "cfi_def_cfa_offset", dot_cfi, DW_CFA_def_cfa_offset },
708
    { "cfi_adjust_cfa_offset", dot_cfi, CFI_adjust_cfa_offset },
709
    { "cfi_offset", dot_cfi, DW_CFA_offset },
710
    { "cfi_rel_offset", dot_cfi, CFI_rel_offset },
711
    { "cfi_register", dot_cfi, DW_CFA_register },
712
    { "cfi_return_column", dot_cfi, CFI_return_column },
713
    { "cfi_restore", dot_cfi, DW_CFA_restore },
714
    { "cfi_undefined", dot_cfi, DW_CFA_undefined },
715
    { "cfi_same_value", dot_cfi, DW_CFA_same_value },
716
    { "cfi_remember_state", dot_cfi, DW_CFA_remember_state },
717
    { "cfi_restore_state", dot_cfi, DW_CFA_restore_state },
718
    { "cfi_window_save", dot_cfi, DW_CFA_GNU_window_save },
719
    { "cfi_negate_ra_state", dot_cfi, DW_CFA_AARCH64_negate_ra_state },
720
    { "cfi_negate_ra_state_with_pc", dot_cfi, DW_CFA_AARCH64_negate_ra_state_with_pc },
721
    { "cfi_escape", dot_cfi_escape, 0 },
722
    { "cfi_signal_frame", dot_cfi, CFI_signal_frame },
723
    { "cfi_personality", dot_cfi_personality, 0 },
724
    { "cfi_personality_id", dot_cfi_personality_id, 0 },
725
    { "cfi_lsda", dot_cfi_lsda, 0 },
726
    { "cfi_val_encoded_addr", dot_cfi_val_encoded_addr, 0 },
727
    { "cfi_inline_lsda", dot_cfi_inline_lsda, 0 },
728
    { "cfi_label", dot_cfi_label, 0 },
729
    { "cfi_val_offset", dot_cfi, DW_CFA_val_offset },
730
    { NULL, NULL, 0 }
731
  };
732
733
static void
734
cfi_parse_separator (void)
735
47
{
736
47
  SKIP_WHITESPACE ();
737
47
  if (*input_line_pointer == ',')
738
21
    input_line_pointer++;
739
26
  else
740
26
    as_bad (_("missing separator"));
741
47
}
742
743
#ifndef tc_parse_to_dw2regnum
744
static void
745
tc_parse_to_dw2regnum (expressionS *exp)
746
{
747
# ifdef tc_regname_to_dw2regnum
748
  SKIP_WHITESPACE ();
749
  if (is_name_beginner (*input_line_pointer)
750
      || (*input_line_pointer == '%'
751
    && is_name_beginner (*++input_line_pointer)))
752
    {
753
      char *name, c;
754
755
      c = get_symbol_name (& name);
756
757
      exp->X_op = O_constant;
758
      exp->X_add_number = tc_regname_to_dw2regnum (name);
759
760
      restore_line_pointer (c);
761
    }
762
  else
763
# endif
764
    expression_and_evaluate (exp);
765
}
766
#endif
767
768
static unsigned
769
cfi_parse_reg (void)
770
107
{
771
107
  int regno;
772
107
  expressionS exp;
773
774
107
  tc_parse_to_dw2regnum (&exp);
775
107
  switch (exp.X_op)
776
107
    {
777
0
    case O_register:
778
34
    case O_constant:
779
34
      regno = exp.X_add_number;
780
34
      break;
781
782
73
    default:
783
73
      regno = -1;
784
73
      break;
785
107
    }
786
787
107
  if (regno < 0)
788
73
    {
789
73
      as_bad (_("bad register expression"));
790
73
      regno = 0;
791
73
    }
792
793
107
  return regno;
794
107
}
795
796
static offsetT
797
cfi_parse_const (void)
798
69
{
799
69
  return get_absolute_expression ();
800
69
}
801
802
static void
803
dot_cfi (int arg)
804
61
{
805
61
  offsetT offset;
806
61
  unsigned reg1, reg2;
807
808
61
  if (frchain_now->frch_cfi_data == NULL)
809
8
    {
810
8
      as_bad (_("CFI instruction used without previous .cfi_startproc"));
811
8
      ignore_rest_of_line ();
812
8
      return;
813
8
    }
814
815
  /* If the last address was not at the current PC, advance to current.  */
816
53
  if (symbol_get_frag (frchain_now->frch_cfi_data->last_address) != frag_now
817
53
      || (S_GET_VALUE (frchain_now->frch_cfi_data->last_address)
818
53
    != frag_now_fix ()))
819
6
    cfi_add_advance_loc (symbol_temp_new_now ());
820
821
53
  switch (arg)
822
53
    {
823
7
    case DW_CFA_offset:
824
7
      reg1 = cfi_parse_reg ();
825
7
      cfi_parse_separator ();
826
7
      offset = cfi_parse_const ();
827
7
      cfi_add_CFA_offset (reg1, offset);
828
7
      break;
829
830
0
    case DW_CFA_val_offset:
831
0
      reg1 = cfi_parse_reg ();
832
0
      cfi_parse_separator ();
833
0
      offset = cfi_parse_const ();
834
0
      cfi_add_CFA_val_offset (reg1, offset);
835
0
      break;
836
837
12
    case CFI_rel_offset:
838
12
      reg1 = cfi_parse_reg ();
839
12
      cfi_parse_separator ();
840
12
      offset = cfi_parse_const ();
841
12
      cfi_add_CFA_offset (reg1,
842
12
        offset - frchain_now->frch_cfi_data->cur_cfa_offset);
843
12
      break;
844
845
22
    case DW_CFA_def_cfa:
846
22
      reg1 = cfi_parse_reg ();
847
22
      cfi_parse_separator ();
848
22
      offset = cfi_parse_const ();
849
22
      cfi_add_CFA_def_cfa (reg1, offset);
850
22
      break;
851
852
0
    case DW_CFA_register:
853
0
      reg1 = cfi_parse_reg ();
854
0
      cfi_parse_separator ();
855
0
      reg2 = cfi_parse_reg ();
856
0
      cfi_add_CFA_register (reg1, reg2);
857
0
      break;
858
859
1
    case DW_CFA_def_cfa_register:
860
1
      reg1 = cfi_parse_reg ();
861
1
      cfi_add_CFA_def_cfa_register (reg1);
862
1
      break;
863
864
0
    case DW_CFA_def_cfa_offset:
865
0
      offset = cfi_parse_const ();
866
0
      cfi_add_CFA_def_cfa_offset (offset);
867
0
      break;
868
869
0
    case CFI_adjust_cfa_offset:
870
0
      offset = cfi_parse_const ();
871
0
      cfi_add_CFA_def_cfa_offset (frchain_now->frch_cfi_data->cur_cfa_offset
872
0
          + offset);
873
0
      break;
874
875
0
    case DW_CFA_restore:
876
0
      for (;;)
877
0
  {
878
0
    reg1 = cfi_parse_reg ();
879
0
    cfi_add_CFA_restore (reg1);
880
0
    SKIP_WHITESPACE ();
881
0
    if (*input_line_pointer != ',')
882
0
      break;
883
0
    ++input_line_pointer;
884
0
  }
885
0
      break;
886
887
7
    case DW_CFA_undefined:
888
7
      for (;;)
889
62
  {
890
62
    reg1 = cfi_parse_reg ();
891
62
    cfi_add_CFA_undefined (reg1);
892
62
    SKIP_WHITESPACE ();
893
62
    if (*input_line_pointer != ',')
894
7
      break;
895
55
    ++input_line_pointer;
896
55
  }
897
7
      break;
898
899
0
    case DW_CFA_same_value:
900
0
      reg1 = cfi_parse_reg ();
901
0
      cfi_add_CFA_same_value (reg1);
902
0
      break;
903
904
0
    case CFI_return_column:
905
0
      reg1 = cfi_parse_reg ();
906
0
      cfi_set_return_column (reg1);
907
0
      break;
908
909
0
    case DW_CFA_remember_state:
910
0
      cfi_add_CFA_remember_state ();
911
0
      break;
912
913
0
    case DW_CFA_restore_state:
914
0
      cfi_add_CFA_restore_state ();
915
0
      break;
916
917
4
    case DW_CFA_GNU_window_save:
918
4
      cfi_add_CFA_insn (DW_CFA_GNU_window_save);
919
4
      break;
920
921
0
    case DW_CFA_AARCH64_negate_ra_state_with_pc:
922
0
      cfi_add_CFA_insn (DW_CFA_AARCH64_negate_ra_state_with_pc);
923
0
      break;
924
925
0
    case CFI_signal_frame:
926
0
      frchain_now->frch_cfi_data->cur_fde_data->signal_frame = 1;
927
0
      break;
928
929
0
    default:
930
0
      abort ();
931
53
    }
932
933
53
  demand_empty_rest_of_line ();
934
53
}
935
936
#ifndef TC_ADDRESS_BYTES
937
#define TC_ADDRESS_BYTES address_bytes
938
939
static inline unsigned int
940
address_bytes (void)
941
{
942
  /* Choose smallest of 1, 2, 4, 8 bytes that is large enough to
943
     contain an address.  */
944
  unsigned int n = (stdoutput->arch_info->bits_per_address - 1) / 8;
945
  n |= n >> 1;
946
  n |= n >> 2;
947
  return n + 1;
948
}
949
#endif
950
951
static void
952
dot_cfi_escape (int ignored ATTRIBUTE_UNUSED)
953
14
{
954
14
  struct cfi_escape_data *head, **tail;
955
14
  struct cfi_insn_data *insn;
956
957
14
  if (frchain_now->frch_cfi_data == NULL)
958
0
    {
959
0
      as_bad (_("CFI instruction used without previous .cfi_startproc"));
960
0
      ignore_rest_of_line ();
961
0
      return;
962
0
    }
963
964
  /* If the last address was not at the current PC, advance to current.  */
965
14
  if (symbol_get_frag (frchain_now->frch_cfi_data->last_address) != frag_now
966
10
      || (S_GET_VALUE (frchain_now->frch_cfi_data->last_address)
967
10
    != frag_now_fix ()))
968
4
    cfi_add_advance_loc (symbol_temp_new_now ());
969
970
14
  tail = &head;
971
14
  do
972
21
    {
973
21
      struct cfi_escape_data *e = notes_alloc (sizeof (*e));
974
21
      char *id, *ilp_save = input_line_pointer;
975
21
      char c = get_symbol_name (&id);
976
977
21
      if (strcmp (id, "sleb128") == 0)
978
0
  e->type = CFI_ESC_sleb128;
979
21
      else if (strcmp (id, "uleb128") == 0)
980
0
  e->type = CFI_ESC_uleb128;
981
21
      else if (strcmp (id, "data2") == 0)
982
2
  e->type = 2;
983
19
      else if (TC_ADDRESS_BYTES () >= 4 && strcmp (id, "data4") == 0)
984
3
  e->type = 4;
985
16
      else if (TC_ADDRESS_BYTES () >= 8 && strcmp (id, "data8") == 0)
986
0
  e->type = 8;
987
16
      else if (strcmp (id, "addr") == 0)
988
0
  e->type = TC_ADDRESS_BYTES ();
989
16
      else
990
16
  e->type = CFI_ESC_byte;
991
992
21
      c = restore_line_pointer (c);
993
994
21
      if (e->type != CFI_ESC_byte)
995
5
  {
996
5
    if (is_whitespace (c))
997
0
      c = *++input_line_pointer;
998
5
    if (c != '(')
999
5
      e->type = CFI_ESC_byte;
1000
5
  }
1001
21
      if (e->type == CFI_ESC_byte)
1002
21
  input_line_pointer = ilp_save;
1003
1004
21
      if (e->type == CFI_ESC_sleb128 || e->type == CFI_ESC_uleb128)
1005
0
  {
1006
    /* We're still at the opening parenthesis.  Leave it to expression()
1007
       to parse it and find the matching closing one.  */
1008
0
    expression (&e->exp);
1009
0
    e->reloc = TC_PARSE_CONS_RETURN_NONE;
1010
0
  }
1011
21
      else
1012
21
  {
1013
    /* We may still be at an opening parenthesis.  Leave it to expression()
1014
       to parse it and find the matching closing one.  */
1015
21
    e->reloc = do_parse_cons_expression (&e->exp, e->type);
1016
21
  }
1017
1018
21
      *tail = e;
1019
21
      tail = &e->next;
1020
21
    }
1021
21
  while (*input_line_pointer++ == ',');
1022
14
  *tail = NULL;
1023
1024
14
  insn = alloc_cfi_insn_data ();
1025
14
  insn->insn = CFI_escape;
1026
14
  insn->u.esc = head;
1027
1028
14
  --input_line_pointer;
1029
14
  demand_empty_rest_of_line ();
1030
14
}
1031
1032
static void
1033
dot_cfi_personality (int ignored ATTRIBUTE_UNUSED)
1034
2
{
1035
2
  struct fde_entry *fde;
1036
2
  offsetT encoding;
1037
1038
2
  if (frchain_now->frch_cfi_data == NULL)
1039
0
    {
1040
0
      as_bad (_("CFI instruction used without previous .cfi_startproc"));
1041
0
      ignore_rest_of_line ();
1042
0
      return;
1043
0
    }
1044
1045
2
  fde = frchain_now->frch_cfi_data->cur_fde_data;
1046
2
  encoding = cfi_parse_const ();
1047
2
  if (encoding == DW_EH_PE_omit)
1048
0
    {
1049
0
      demand_empty_rest_of_line ();
1050
0
      fde->per_encoding = encoding;
1051
0
      return;
1052
0
    }
1053
1054
2
  if ((encoding & 0xff) != encoding
1055
2
      || ((((encoding & 0x70) != 0
1056
0
#if CFI_DIFF_EXPR_OK || defined tc_cfi_emit_pcrel_expr
1057
0
      && (encoding & 0x70) != DW_EH_PE_pcrel
1058
2
#endif
1059
2
      )
1060
     /* leb128 can be handled, but does something actually need it?  */
1061
2
     || (encoding & 7) == DW_EH_PE_uleb128
1062
2
     || (encoding & 7) > DW_EH_PE_udata8)
1063
0
    && tc_cfi_reloc_for_encoding (encoding) == BFD_RELOC_NONE))
1064
0
    {
1065
0
      as_bad (_("invalid or unsupported encoding in .cfi_personality"));
1066
0
      ignore_rest_of_line ();
1067
0
      return;
1068
0
    }
1069
1070
2
  if (*input_line_pointer++ != ',')
1071
0
    {
1072
0
      as_bad (_(".cfi_personality requires encoding and symbol arguments"));
1073
0
      ignore_rest_of_line ();
1074
0
      return;
1075
0
    }
1076
1077
2
  expression_and_evaluate (&fde->personality);
1078
2
  switch (fde->personality.X_op)
1079
2
    {
1080
0
    case O_symbol:
1081
0
      break;
1082
0
    case O_constant:
1083
0
      if ((encoding & 0x70) == DW_EH_PE_pcrel)
1084
0
  encoding = DW_EH_PE_omit;
1085
0
      break;
1086
2
    default:
1087
2
      encoding = DW_EH_PE_omit;
1088
2
      break;
1089
2
    }
1090
1091
2
  fde->per_encoding = encoding;
1092
1093
2
  if (encoding == DW_EH_PE_omit)
1094
2
    {
1095
2
      as_bad (_("wrong second argument to .cfi_personality"));
1096
2
      ignore_rest_of_line ();
1097
2
      return;
1098
2
    }
1099
1100
0
  demand_empty_rest_of_line ();
1101
0
}
1102
1103
static void
1104
dot_cfi_lsda (int ignored ATTRIBUTE_UNUSED)
1105
25
{
1106
25
  struct fde_entry *fde;
1107
25
  offsetT encoding;
1108
1109
25
  if (frchain_now->frch_cfi_data == NULL)
1110
2
    {
1111
2
      as_bad (_("CFI instruction used without previous .cfi_startproc"));
1112
2
      ignore_rest_of_line ();
1113
2
      return;
1114
2
    }
1115
1116
23
  fde = frchain_now->frch_cfi_data->cur_fde_data;
1117
23
  encoding = cfi_parse_const ();
1118
23
  if (encoding == DW_EH_PE_omit)
1119
0
    {
1120
0
      demand_empty_rest_of_line ();
1121
0
      fde->lsda_encoding = encoding;
1122
0
      return;
1123
0
    }
1124
1125
23
  if ((encoding & 0xff) != encoding
1126
23
      || ((((encoding & 0x70) != 0
1127
0
#if CFI_DIFF_LSDA_OK || defined tc_cfi_emit_pcrel_expr
1128
0
      && (encoding & 0x70) != DW_EH_PE_pcrel
1129
23
#endif
1130
23
      )
1131
     /* leb128 can be handled, but does something actually need it?  */
1132
23
     || (encoding & 7) == DW_EH_PE_uleb128
1133
21
     || (encoding & 7) > DW_EH_PE_udata8)
1134
0
    && tc_cfi_reloc_for_encoding (encoding) == BFD_RELOC_NONE))
1135
2
    {
1136
2
      as_bad (_("invalid or unsupported encoding in .cfi_lsda"));
1137
2
      ignore_rest_of_line ();
1138
2
      return;
1139
2
    }
1140
1141
21
  if (*input_line_pointer++ != ',')
1142
8
    {
1143
8
      as_bad (_(".cfi_lsda requires encoding and symbol arguments"));
1144
8
      ignore_rest_of_line ();
1145
8
      return;
1146
8
    }
1147
1148
13
  fde->lsda_encoding = encoding;
1149
1150
13
  expression_and_evaluate (&fde->lsda);
1151
13
  switch (fde->lsda.X_op)
1152
13
    {
1153
6
    case O_symbol:
1154
6
      break;
1155
7
    case O_constant:
1156
7
      if ((encoding & 0x70) == DW_EH_PE_pcrel)
1157
0
  encoding = DW_EH_PE_omit;
1158
7
      break;
1159
0
    default:
1160
0
      encoding = DW_EH_PE_omit;
1161
0
      break;
1162
13
    }
1163
1164
13
  fde->lsda_encoding = encoding;
1165
1166
13
  if (encoding == DW_EH_PE_omit)
1167
0
    {
1168
0
      as_bad (_("wrong second argument to .cfi_lsda"));
1169
0
      ignore_rest_of_line ();
1170
0
      return;
1171
0
    }
1172
1173
13
  demand_empty_rest_of_line ();
1174
13
}
1175
1176
static void
1177
dot_cfi_val_encoded_addr (int ignored ATTRIBUTE_UNUSED)
1178
11
{
1179
11
  struct cfi_insn_data *insn_ptr;
1180
11
  offsetT encoding;
1181
1182
11
  if (frchain_now->frch_cfi_data == NULL)
1183
8
    {
1184
8
      as_bad (_("CFI instruction used without previous .cfi_startproc"));
1185
8
      ignore_rest_of_line ();
1186
8
      return;
1187
8
    }
1188
1189
  /* If the last address was not at the current PC, advance to current.  */
1190
3
  if (symbol_get_frag (frchain_now->frch_cfi_data->last_address) != frag_now
1191
3
      || (S_GET_VALUE (frchain_now->frch_cfi_data->last_address)
1192
3
    != frag_now_fix ()))
1193
0
    cfi_add_advance_loc (symbol_temp_new_now ());
1194
1195
3
  insn_ptr = alloc_cfi_insn_data ();
1196
3
  insn_ptr->insn = CFI_val_encoded_addr;
1197
1198
3
  insn_ptr->u.ea.reg = cfi_parse_reg ();
1199
1200
3
  cfi_parse_separator ();
1201
3
  encoding = cfi_parse_const ();
1202
3
  if ((encoding & 0xff) != encoding
1203
0
      || ((encoding & 0x70) != 0
1204
0
#if CFI_DIFF_EXPR_OK || defined tc_cfi_emit_pcrel_expr
1205
0
    && (encoding & 0x70) != DW_EH_PE_pcrel
1206
0
#endif
1207
0
    )
1208
      /* leb128 can be handled, but does something actually need it?  */
1209
0
      || (encoding & 7) == DW_EH_PE_uleb128
1210
0
      || (encoding & 7) > DW_EH_PE_udata8)
1211
3
    {
1212
3
      as_bad (_("invalid or unsupported encoding in .cfi_lsda"));
1213
3
      encoding = DW_EH_PE_omit;
1214
3
    }
1215
1216
3
  cfi_parse_separator ();
1217
3
  expression_and_evaluate (&insn_ptr->u.ea.exp);
1218
3
  switch (insn_ptr->u.ea.exp.X_op)
1219
3
    {
1220
3
    case O_symbol:
1221
3
      break;
1222
0
    case O_constant:
1223
0
      if ((encoding & 0x70) != DW_EH_PE_pcrel)
1224
0
  break;
1225
      /* Fall through.  */
1226
0
    default:
1227
0
      encoding = DW_EH_PE_omit;
1228
0
      break;
1229
3
    }
1230
1231
3
  insn_ptr->u.ea.encoding = encoding;
1232
3
  if (encoding == DW_EH_PE_omit)
1233
3
    {
1234
3
      as_bad (_("wrong third argument to .cfi_val_encoded_addr"));
1235
3
      ignore_rest_of_line ();
1236
3
      return;
1237
3
    }
1238
1239
0
  demand_empty_rest_of_line ();
1240
0
}
1241
1242
static void
1243
dot_cfi_label (int ignored ATTRIBUTE_UNUSED)
1244
3
{
1245
3
  char *name;
1246
1247
3
  if (frchain_now->frch_cfi_data == NULL)
1248
0
    {
1249
0
      as_bad (_("CFI instruction used without previous .cfi_startproc"));
1250
0
      ignore_rest_of_line ();
1251
0
      return;
1252
0
    }
1253
1254
3
  name = read_symbol_name ();
1255
3
  if (name == NULL)
1256
3
    return;
1257
1258
  /* If the last address was not at the current PC, advance to current.  */
1259
0
  if (symbol_get_frag (frchain_now->frch_cfi_data->last_address) != frag_now
1260
0
      || (S_GET_VALUE (frchain_now->frch_cfi_data->last_address)
1261
0
    != frag_now_fix ()))
1262
0
    cfi_add_advance_loc (symbol_temp_new_now ());
1263
1264
0
  cfi_add_label (name);
1265
0
  free (name);
1266
1267
0
  demand_empty_rest_of_line ();
1268
0
}
1269
1270
void
1271
dot_cfi_sections (int ignored ATTRIBUTE_UNUSED)
1272
3.12k
{
1273
3.12k
  int sections = 0;
1274
1275
3.12k
  SKIP_WHITESPACE ();
1276
3.12k
  if (is_name_beginner (*input_line_pointer) || *input_line_pointer == '"')
1277
6.16k
    while (1)
1278
6.16k
      {
1279
6.16k
  char * saved_ilp;
1280
6.16k
  char *name, c;
1281
1282
6.16k
  saved_ilp = input_line_pointer;
1283
6.16k
  c = get_symbol_name (& name);
1284
1285
6.16k
  if (startswith (name, ".eh_frame")
1286
11
      && name[9] != '_')
1287
11
    sections |= CFI_EMIT_eh_frame;
1288
6.15k
  else if (startswith (name, ".debug_frame"))
1289
3.03k
    sections |= CFI_EMIT_debug_frame;
1290
#if SUPPORT_COMPACT_EH
1291
  else if (startswith (name, ".eh_frame_entry"))
1292
    {
1293
      compact_eh = true;
1294
      sections |= CFI_EMIT_eh_frame_compact;
1295
    }
1296
#endif
1297
#ifdef tc_cfi_section_name
1298
  else if (strcmp (name, tc_cfi_section_name) == 0)
1299
    sections |= CFI_EMIT_target;
1300
#endif
1301
3.12k
  else if (startswith (name, ".sframe"))
1302
47
      sections |= CFI_EMIT_sframe;
1303
3.07k
  else
1304
3.07k
    {
1305
3.07k
      *input_line_pointer = c;
1306
3.07k
      input_line_pointer = saved_ilp;
1307
3.07k
      break;
1308
3.07k
    }
1309
1310
3.08k
  restore_line_pointer (c);
1311
3.08k
  SKIP_WHITESPACE ();
1312
3.08k
  if (*input_line_pointer == ',')
1313
42
    {
1314
42
      name = input_line_pointer++;
1315
42
      SKIP_WHITESPACE ();
1316
42
      if (!is_name_beginner (*input_line_pointer)
1317
42
    && *input_line_pointer != '"')
1318
42
        {
1319
42
    input_line_pointer = name;
1320
42
    break;
1321
42
        }
1322
42
    }
1323
3.04k
  else if (is_name_beginner (*input_line_pointer)
1324
3.04k
     || *input_line_pointer == '"')
1325
6
    break;
1326
3.08k
      }
1327
1328
3.12k
  demand_empty_rest_of_line ();
1329
3.12k
  if (cfi_sections_set
1330
3.11k
      && (sections & (CFI_EMIT_eh_frame | CFI_EMIT_eh_frame_compact))
1331
8
      && ((cfi_sections & (CFI_EMIT_eh_frame | CFI_EMIT_eh_frame_compact))
1332
8
    != (sections & (CFI_EMIT_eh_frame | CFI_EMIT_eh_frame_compact))))
1333
8
    as_bad (_("inconsistent uses of .cfi_sections"));
1334
3.12k
  cfi_sections = sections;
1335
3.12k
}
1336
1337
static void
1338
dot_cfi_startproc (int ignored ATTRIBUTE_UNUSED)
1339
55
{
1340
55
  int simple = 0;
1341
1342
55
  if (frchain_now->frch_cfi_data != NULL)
1343
16
    {
1344
16
      as_bad (_("previous CFI entry not closed (missing .cfi_endproc)"));
1345
16
      ignore_rest_of_line ();
1346
16
      return;
1347
16
    }
1348
1349
39
  cfi_new_fde (symbol_temp_new_now (), listing & LISTING_LISTING);
1350
1351
39
  SKIP_WHITESPACE ();
1352
39
  if (is_name_beginner (*input_line_pointer) || *input_line_pointer == '"')
1353
1
    {
1354
1
      char * saved_ilp = input_line_pointer;
1355
1
      char *name, c;
1356
1357
1
      c = get_symbol_name (& name);
1358
1359
1
      if (strcmp (name, "simple") == 0)
1360
0
  {
1361
0
    simple = 1;
1362
0
    restore_line_pointer (c);
1363
0
  }
1364
1
      else
1365
1
  input_line_pointer = saved_ilp;
1366
1
    }
1367
39
  demand_empty_rest_of_line ();
1368
1369
39
  cfi_set_sections ();
1370
1371
39
  frchain_now->frch_cfi_data->cur_cfa_offset = 0;
1372
39
  if (!simple)
1373
39
    tc_cfi_frame_initial_instructions ();
1374
1375
39
  if ((all_cfi_sections & CFI_EMIT_target) != 0)
1376
0
    tc_cfi_startproc ();
1377
39
}
1378
1379
static void
1380
dot_cfi_endproc (int ignored ATTRIBUTE_UNUSED)
1381
0
{
1382
0
  if (frchain_now->frch_cfi_data == NULL)
1383
0
    {
1384
0
      as_bad (_(".cfi_endproc without corresponding .cfi_startproc"));
1385
0
      ignore_rest_of_line ();
1386
0
      return;
1387
0
    }
1388
1389
0
  cfi_set_last_fde (frchain_now->frch_cfi_data->cur_fde_data);
1390
1391
0
  cfi_end_fde (symbol_temp_new_now ());
1392
1393
0
  demand_empty_rest_of_line ();
1394
1395
0
  if ((all_cfi_sections & CFI_EMIT_target) != 0)
1396
0
    tc_cfi_endproc (last_fde);
1397
0
}
1398
1399
static segT
1400
get_cfi_seg (segT cseg, const char *base, flagword flags, int align)
1401
30
{
1402
  /* Exclude .debug_frame sections for Compact EH.  */
1403
30
  if (SUPPORT_FRAME_LINKONCE || ((flags & SEC_DEBUGGING) == 0 && compact_eh)
1404
30
      || ((flags & SEC_DEBUGGING) == 0 && TARGET_MULTIPLE_EH_FRAME_SECTIONS))
1405
0
    {
1406
0
      segT iseg = cseg;
1407
0
      struct dwcfi_seg_list *l;
1408
1409
0
      l = dwcfi_hash_find_or_make (cseg, base, flags);
1410
1411
0
      cseg = l->seg;
1412
0
      subseg_set (cseg, l->subseg);
1413
1414
0
      if (TARGET_MULTIPLE_EH_FRAME_SECTIONS
1415
0
    && (flags & DWARF2_EH_FRAME_READ_ONLY))
1416
0
  {
1417
0
    const frchainS *ifrch = seg_info (iseg)->frchainP;
1418
0
    const frchainS *frch = seg_info (cseg)->frchainP;
1419
0
    expressionS exp;
1420
1421
0
    exp.X_op = O_symbol;
1422
0
    exp.X_add_symbol = (symbolS *) local_symbol_make (cseg->name, cseg, frch->frch_root, 0);
1423
0
    exp.X_add_number = 0;
1424
0
    subseg_set (iseg, ifrch->frch_subseg);
1425
0
    fix_new_exp (ifrch->frch_root, 0, 0, &exp, 0, BFD_RELOC_NONE);
1426
1427
    /* Restore the original segment info.  */
1428
0
    subseg_set (cseg, l->subseg);
1429
0
  }
1430
0
    }
1431
30
  else
1432
30
    {
1433
30
      cseg = subseg_new (base, 0);
1434
30
      bfd_set_section_flags (cseg, flags);
1435
30
    }
1436
30
  record_alignment (cseg, align);
1437
30
  return cseg;
1438
30
}
1439
1440
#if SUPPORT_COMPACT_EH
1441
static void
1442
dot_cfi_personality_id (int ignored ATTRIBUTE_UNUSED)
1443
{
1444
  struct fde_entry *fde;
1445
1446
  if (frchain_now->frch_cfi_data == NULL)
1447
    {
1448
      as_bad (_("CFI instruction used without previous .cfi_startproc"));
1449
      ignore_rest_of_line ();
1450
      return;
1451
    }
1452
1453
  fde = frchain_now->frch_cfi_data->cur_fde_data;
1454
  fde->personality_id = cfi_parse_const ();
1455
  demand_empty_rest_of_line ();
1456
1457
  if (fde->personality_id == 0 || fde->personality_id > 3)
1458
    {
1459
      as_bad (_("wrong argument to .cfi_personality_id"));
1460
      return;
1461
    }
1462
}
1463
1464
static void
1465
dot_cfi_fde_data (int ignored ATTRIBUTE_UNUSED)
1466
{
1467
  if (frchain_now->frch_cfi_data == NULL)
1468
    {
1469
      as_bad (_(".cfi_fde_data without corresponding .cfi_startproc"));
1470
      ignore_rest_of_line ();
1471
      return;
1472
    }
1473
1474
  cfi_set_last_fde (frchain_now->frch_cfi_data->cur_fde_data);
1475
1476
  if ((all_cfi_sections & CFI_EMIT_target) != 0
1477
      || (all_cfi_sections & CFI_EMIT_eh_frame_compact) != 0)
1478
    {
1479
      struct cfi_escape_data *head, **tail, *e;
1480
      int num_ops = 0;
1481
1482
      tail = &head;
1483
      if (!is_it_end_of_statement ())
1484
  {
1485
    num_ops = 0;
1486
    do
1487
      {
1488
        e = XNEW (struct cfi_escape_data);
1489
        e->reloc = do_parse_cons_expression (&e->exp, 1);
1490
        if (e->reloc != TC_PARSE_CONS_RETURN_NONE
1491
      || e->exp.X_op != O_constant)
1492
    as_bad (_("only constants may be used with .cfi_fde_data"));
1493
        *tail = e;
1494
        tail = &e->next;
1495
        num_ops++;
1496
      }
1497
    while (*input_line_pointer++ == ',');
1498
    --input_line_pointer;
1499
  }
1500
      *tail = NULL;
1501
1502
      if (last_fde->lsda_encoding != DW_EH_PE_omit)
1503
  last_fde->eh_header_type = EH_COMPACT_HAS_LSDA;
1504
      else if (num_ops <= 3 && last_fde->per_encoding == DW_EH_PE_omit)
1505
  last_fde->eh_header_type = EH_COMPACT_INLINE;
1506
      else
1507
  last_fde->eh_header_type = EH_COMPACT_OUTLINE;
1508
1509
      if (last_fde->eh_header_type == EH_COMPACT_INLINE)
1510
  num_ops = 3;
1511
1512
      last_fde->eh_data_size = num_ops;
1513
      last_fde->eh_data =  XNEWVEC (bfd_byte, num_ops);
1514
      num_ops = 0;
1515
      while (head)
1516
  {
1517
    e = head;
1518
    head = e->next;
1519
    last_fde->eh_data[num_ops++] = e->exp.X_add_number;
1520
    free (e);
1521
  }
1522
      if (last_fde->eh_header_type == EH_COMPACT_INLINE)
1523
  while (num_ops < 3)
1524
    last_fde->eh_data[num_ops++] = tc_compact_eh_opcode_stop;
1525
    }
1526
1527
  demand_empty_rest_of_line ();
1528
}
1529
1530
/* Function to emit the compact unwinding opcodes stored in the
1531
   fde's eh_data field.  The end of the opcode data will be
1532
   padded to the value in align.  */
1533
1534
static void
1535
output_compact_unwind_data (struct fde_entry *fde, int align)
1536
{
1537
  int data_size = fde->eh_data_size + 2;
1538
  int align_padding;
1539
  int amask;
1540
  char *p;
1541
1542
  fde->eh_loc = symbol_temp_new_now ();
1543
1544
  p = frag_more (1);
1545
  if (fde->personality_id != 0)
1546
    *p = fde->personality_id;
1547
  else if (fde->per_encoding != DW_EH_PE_omit)
1548
    {
1549
      *p = 0;
1550
      emit_expr_encoded (&fde->personality, fde->per_encoding, false);
1551
      data_size += encoding_size (fde->per_encoding);
1552
    }
1553
  else
1554
    *p = 1;
1555
1556
  amask = (1 << align) - 1;
1557
  align_padding = ((data_size + amask) & ~amask) - data_size;
1558
1559
  p = frag_more (fde->eh_data_size + 1 + align_padding);
1560
  memcpy (p, fde->eh_data, fde->eh_data_size);
1561
  p += fde->eh_data_size;
1562
1563
  while (align_padding-- > 0)
1564
    *(p++) = tc_compact_eh_opcode_pad;
1565
1566
  *(p++) = tc_compact_eh_opcode_stop;
1567
  fde->eh_header_type = EH_COMPACT_OUTLINE_DONE;
1568
}
1569
1570
/* Handle the .cfi_inline_lsda directive.  */
1571
static void
1572
dot_cfi_inline_lsda (int ignored ATTRIBUTE_UNUSED)
1573
{
1574
  segT ccseg;
1575
  int align;
1576
  long max_alignment = 28;
1577
1578
  if (!last_fde)
1579
    {
1580
      as_bad (_("unexpected .cfi_inline_lsda"));
1581
      ignore_rest_of_line ();
1582
      return;
1583
    }
1584
1585
  if ((last_fde->sections & CFI_EMIT_eh_frame_compact) == 0)
1586
    {
1587
      as_bad (_(".cfi_inline_lsda not valid for this frame"));
1588
      ignore_rest_of_line ();
1589
      return;
1590
    }
1591
1592
  if (last_fde->eh_header_type != EH_COMPACT_UNKNOWN
1593
      && last_fde->eh_header_type != EH_COMPACT_HAS_LSDA)
1594
    {
1595
      as_bad (_(".cfi_inline_lsda seen for frame without .cfi_lsda"));
1596
      ignore_rest_of_line ();
1597
      return;
1598
    }
1599
1600
#ifdef md_flush_pending_output
1601
  md_flush_pending_output ();
1602
#endif
1603
1604
  align = get_absolute_expression ();
1605
  if (align > max_alignment)
1606
    {
1607
      align = max_alignment;
1608
      as_bad (_("Alignment too large: %d. assumed."), align);
1609
    }
1610
  else if (align < 0)
1611
    {
1612
      as_warn (_("Alignment negative: 0 assumed."));
1613
      align = 0;
1614
    }
1615
1616
  demand_empty_rest_of_line ();
1617
  ccseg = CUR_SEG (last_fde);
1618
1619
  /* Open .gnu_extab section.  */
1620
  get_cfi_seg (ccseg, ".gnu_extab",
1621
         (SEC_ALLOC | SEC_LOAD | SEC_DATA
1622
    | DWARF2_EH_FRAME_READ_ONLY),
1623
         1);
1624
1625
  frag_align (align, 0, 0);
1626
  record_alignment (now_seg, align);
1627
  if (last_fde->eh_header_type == EH_COMPACT_HAS_LSDA)
1628
    output_compact_unwind_data (last_fde, align);
1629
1630
  cfi_set_last_fde (NULL);
1631
1632
  return;
1633
}
1634
#else /* !SUPPORT_COMPACT_EH */
1635
static void
1636
dot_cfi_inline_lsda (int ignored ATTRIBUTE_UNUSED)
1637
0
{
1638
0
  as_bad (_(".cfi_inline_lsda is not supported for this target"));
1639
0
  ignore_rest_of_line ();
1640
0
}
1641
1642
static void
1643
dot_cfi_fde_data (int ignored ATTRIBUTE_UNUSED)
1644
0
{
1645
0
  as_bad (_(".cfi_fde_data is not supported for this target"));
1646
0
  ignore_rest_of_line ();
1647
0
}
1648
1649
static void
1650
dot_cfi_personality_id (int ignored ATTRIBUTE_UNUSED)
1651
0
{
1652
0
  as_bad (_(".cfi_personality_id is not supported for this target"));
1653
0
  ignore_rest_of_line ();
1654
0
}
1655
#endif
1656

1657
static void
1658
output_cfi_insn (struct cfi_insn_data *insn)
1659
184
{
1660
184
  offsetT offset;
1661
184
  unsigned int regno;
1662
1663
184
  switch (insn->insn)
1664
184
    {
1665
6
    case DW_CFA_advance_loc:
1666
6
      {
1667
6
  symbolS *from = insn->u.ll.lab1;
1668
6
  symbolS *to = insn->u.ll.lab2;
1669
1670
6
  if (symbol_get_frag (to) == symbol_get_frag (from))
1671
2
    {
1672
2
      addressT delta = S_GET_VALUE (to) - S_GET_VALUE (from);
1673
2
      addressT scaled = delta / DWARF2_LINE_MIN_INSN_LENGTH;
1674
1675
2
      if (scaled == 0)
1676
0
        ;
1677
2
      else if (scaled <= 0x3F)
1678
0
        out_one (DW_CFA_advance_loc + scaled);
1679
2
      else if (scaled <= 0xFF)
1680
0
        {
1681
0
    out_one (DW_CFA_advance_loc1);
1682
0
    out_one (scaled);
1683
0
        }
1684
2
      else if (scaled <= 0xFFFF)
1685
1
        {
1686
1
    out_one (DW_CFA_advance_loc2);
1687
1
    out_two (scaled);
1688
1
        }
1689
1
      else
1690
1
        {
1691
1
    out_one (DW_CFA_advance_loc4);
1692
1
    out_four (scaled);
1693
1
        }
1694
2
    }
1695
4
  else
1696
4
    {
1697
4
      expressionS exp = {
1698
4
        .X_op = O_subtract,
1699
4
        .X_add_symbol = to,
1700
4
        .X_op_symbol = from,
1701
4
      };
1702
1703
      /* The code in ehopt.c expects that one byte of the encoding
1704
         is already allocated to the frag.  This comes from the way
1705
         that it scans the .eh_frame section looking first for the
1706
         .byte DW_CFA_advance_loc4.  Call frag_grow with the sum of
1707
         room needed by frag_more and frag_var to preallocate space
1708
         ensuring that the DW_CFA_advance_loc4 is in the fixed part
1709
         of the rs_cfa frag, so that the relax machinery can remove
1710
         the advance_loc should it advance by zero.  */
1711
4
      frag_grow (5);
1712
4
      *frag_more (1) = DW_CFA_advance_loc4;
1713
1714
4
      frag_var (rs_cfa, 4, 0, DWARF2_LINE_MIN_INSN_LENGTH << 3,
1715
4
          make_expr_symbol (&exp), frag_now_fix () - 1,
1716
4
          (char *) frag_now);
1717
4
    }
1718
6
      }
1719
6
      break;
1720
1721
52
    case DW_CFA_def_cfa:
1722
52
      offset = insn->u.ri.offset;
1723
52
      if (offset < 0)
1724
8
  {
1725
8
    out_one (DW_CFA_def_cfa_sf);
1726
8
    out_uleb128 (insn->u.ri.reg);
1727
8
    out_sleb128 (offset / DWARF2_CIE_DATA_ALIGNMENT);
1728
8
  }
1729
44
      else
1730
44
  {
1731
44
    out_one (DW_CFA_def_cfa);
1732
44
    out_uleb128 (insn->u.ri.reg);
1733
44
    out_uleb128 (offset);
1734
44
  }
1735
52
      break;
1736
1737
1
    case DW_CFA_def_cfa_register:
1738
59
    case DW_CFA_undefined:
1739
59
    case DW_CFA_same_value:
1740
59
      out_one (insn->insn);
1741
59
      out_uleb128 (insn->u.r);
1742
59
      break;
1743
1744
0
    case DW_CFA_def_cfa_offset:
1745
0
      offset = insn->u.i;
1746
0
      if (offset < 0)
1747
0
  {
1748
0
    out_one (DW_CFA_def_cfa_offset_sf);
1749
0
    out_sleb128 (offset / DWARF2_CIE_DATA_ALIGNMENT);
1750
0
  }
1751
0
      else
1752
0
  {
1753
0
    out_one (DW_CFA_def_cfa_offset);
1754
0
    out_uleb128 (offset);
1755
0
  }
1756
0
      break;
1757
1758
0
    case DW_CFA_restore:
1759
0
      regno = insn->u.r;
1760
0
      if (regno <= 0x3F)
1761
0
  {
1762
0
    out_one (DW_CFA_restore + regno);
1763
0
  }
1764
0
      else
1765
0
  {
1766
0
    out_one (DW_CFA_restore_extended);
1767
0
    out_uleb128 (regno);
1768
0
  }
1769
0
      break;
1770
1771
48
    case DW_CFA_offset:
1772
48
      regno = insn->u.ri.reg;
1773
48
      offset = insn->u.ri.offset / DWARF2_CIE_DATA_ALIGNMENT;
1774
48
      if (offset < 0)
1775
4
  {
1776
4
    out_one (DW_CFA_offset_extended_sf);
1777
4
    out_uleb128 (regno);
1778
4
    out_sleb128 (offset);
1779
4
  }
1780
44
      else if (regno <= 0x3F)
1781
44
  {
1782
44
    out_one (DW_CFA_offset + regno);
1783
44
    out_uleb128 (offset);
1784
44
  }
1785
0
      else
1786
0
  {
1787
0
    out_one (DW_CFA_offset_extended);
1788
0
    out_uleb128 (regno);
1789
0
    out_uleb128 (offset);
1790
0
  }
1791
48
      break;
1792
1793
0
    case DW_CFA_val_offset:
1794
0
      regno = insn->u.ri.reg;
1795
0
      offset = insn->u.ri.offset / DWARF2_CIE_DATA_ALIGNMENT;
1796
0
      if (offset < 0)
1797
0
  {
1798
0
    out_one (DW_CFA_val_offset_sf);
1799
0
    out_uleb128 (regno);
1800
0
    out_sleb128 (offset);
1801
0
  }
1802
0
      else
1803
0
  {
1804
0
    out_one (DW_CFA_val_offset);
1805
0
    out_uleb128 (regno);
1806
0
    out_uleb128 (offset);
1807
0
  }
1808
0
      break;
1809
1810
0
    case DW_CFA_register:
1811
0
      out_one (DW_CFA_register);
1812
0
      out_uleb128 (insn->u.rr.reg1);
1813
0
      out_uleb128 (insn->u.rr.reg2);
1814
0
      break;
1815
1816
0
    case DW_CFA_remember_state:
1817
0
    case DW_CFA_restore_state:
1818
0
      out_one (insn->insn);
1819
0
      break;
1820
1821
3
    case DW_CFA_GNU_window_save:
1822
3
      out_one (DW_CFA_GNU_window_save);
1823
3
      break;
1824
1825
0
    case DW_CFA_AARCH64_negate_ra_state_with_pc:
1826
0
      out_one (DW_CFA_AARCH64_negate_ra_state_with_pc);
1827
0
      break;
1828
1829
13
    case CFI_escape:
1830
13
      {
1831
13
  struct cfi_escape_data *e;
1832
33
  for (e = insn->u.esc; e ; e = e->next)
1833
20
    {
1834
20
      if (e->type == CFI_ESC_sleb128 || e->type == CFI_ESC_uleb128)
1835
0
        emit_leb128_expr (&e->exp, e->type == CFI_ESC_sleb128);
1836
20
      else
1837
20
        emit_expr_with_reloc (&e->exp, e->type, e->reloc);
1838
20
    }
1839
13
  break;
1840
0
      }
1841
1842
3
    case CFI_val_encoded_addr:
1843
3
      {
1844
3
  unsigned encoding = insn->u.ea.encoding;
1845
3
  offsetT enc_size;
1846
1847
3
  if (encoding == DW_EH_PE_omit)
1848
3
    break;
1849
0
  out_one (DW_CFA_val_expression);
1850
0
  out_uleb128 (insn->u.ea.reg);
1851
1852
0
  switch (encoding & 0x7)
1853
0
    {
1854
0
    case DW_EH_PE_absptr:
1855
0
      enc_size = DWARF2_ADDR_SIZE (stdoutput);
1856
0
      break;
1857
0
    case DW_EH_PE_udata2:
1858
0
      enc_size = 2;
1859
0
      break;
1860
0
    case DW_EH_PE_udata4:
1861
0
      enc_size = 4;
1862
0
      break;
1863
0
    case DW_EH_PE_udata8:
1864
0
      enc_size = 8;
1865
0
      break;
1866
0
    default:
1867
0
      abort ();
1868
0
    }
1869
1870
  /* If the user has requested absolute encoding,
1871
     then use the smaller DW_OP_addr encoding.  */
1872
0
  if (insn->u.ea.encoding == DW_EH_PE_absptr)
1873
0
    {
1874
0
      out_uleb128 (1 + enc_size);
1875
0
      out_one (DW_OP_addr);
1876
0
    }
1877
0
  else
1878
0
    {
1879
0
      out_uleb128 (1 + 1 + enc_size);
1880
0
      out_one (DW_OP_GNU_encoded_addr);
1881
0
      out_one (encoding);
1882
1883
0
      if ((encoding & 0x70) == DW_EH_PE_pcrel)
1884
0
        {
1885
0
#if CFI_DIFF_EXPR_OK
1886
0
    insn->u.ea.exp.X_op = O_subtract;
1887
0
    insn->u.ea.exp.X_op_symbol = symbol_temp_new_now ();
1888
#elif defined (tc_cfi_emit_pcrel_expr)
1889
    tc_cfi_emit_pcrel_expr (&insn->u.ea.exp, enc_size);
1890
    break;
1891
#else
1892
    abort ();
1893
#endif
1894
0
        }
1895
0
    }
1896
0
  emit_expr (&insn->u.ea.exp, enc_size);
1897
0
      }
1898
0
      break;
1899
1900
0
    case CFI_label:
1901
0
      colon (insn->u.sym_name);
1902
0
      break;
1903
1904
0
    default:
1905
0
      abort ();
1906
184
    }
1907
184
}
1908
1909
static void
1910
output_cie (struct cie_entry *cie, bool eh_frame, int align)
1911
33
{
1912
33
  symbolS *after_size_address, *end_address;
1913
33
  expressionS exp;
1914
33
  struct cfi_insn_data *i;
1915
33
  offsetT augmentation_size;
1916
33
  int enc;
1917
33
  enum dwarf2_format fmt = DWARF2_FORMAT (now_seg);
1918
1919
33
  cie->start_address = symbol_temp_new_now ();
1920
33
  after_size_address = symbol_temp_make ();
1921
33
  end_address = symbol_temp_make ();
1922
1923
33
  exp.X_op = O_subtract;
1924
33
  exp.X_add_symbol = end_address;
1925
33
  exp.X_op_symbol = after_size_address;
1926
33
  exp.X_add_number = 0;
1927
1928
33
  if (eh_frame || fmt == dwarf2_format_32bit)
1929
33
    emit_expr (&exp, 4);      /* Length.  */
1930
0
  else
1931
0
    {
1932
0
      if (fmt == dwarf2_format_64bit)
1933
0
  out_four (-1);
1934
0
      emit_expr (&exp, 8);      /* Length.  */
1935
0
    }
1936
33
  symbol_set_value_now (after_size_address);
1937
33
  if (eh_frame)
1938
31
    out_four (0);        /* CIE id.  */
1939
2
  else
1940
2
    {
1941
2
      out_four (-1);        /* CIE id.  */
1942
2
      if (fmt != dwarf2_format_32bit)
1943
0
  out_four (-1);
1944
2
    }
1945
33
  out_one (flag_dwarf_cie_version);   /* Version.  */
1946
33
  if (eh_frame)
1947
31
    {
1948
31
      out_one ('z');        /* Augmentation.  */
1949
31
      if (cie->per_encoding != DW_EH_PE_omit)
1950
0
  out_one ('P');
1951
31
      if (cie->lsda_encoding != DW_EH_PE_omit)
1952
3
  out_one ('L');
1953
31
      out_one ('R');
1954
#ifdef tc_output_cie_extra
1955
      tc_output_cie_extra (cie);
1956
#endif
1957
31
    }
1958
33
  if (cie->signal_frame)
1959
0
    out_one ('S');
1960
33
  out_one (0);
1961
33
  if (flag_dwarf_cie_version >= 4)
1962
0
    {
1963
      /* For now we are assuming a flat address space with 4 or 8 byte
1964
         addresses.  */
1965
0
      int address_size = dwarf2_format_32bit ? 4 : 8;
1966
0
      out_one (address_size);     /* Address size.  */
1967
0
      out_one (0);        /* Segment size.  */
1968
0
    }
1969
33
  out_uleb128 (DWARF2_LINE_MIN_INSN_LENGTH);  /* Code alignment.  */
1970
33
  out_sleb128 (DWARF2_CIE_DATA_ALIGNMENT);  /* Data alignment.  */
1971
33
  if (flag_dwarf_cie_version == 1)   /* Return column.  */
1972
33
    {
1973
33
      if ((cie->return_column & 0xff) != cie->return_column)
1974
0
  as_bad (_("return column number %d overflows in CIE version 1"),
1975
0
    cie->return_column);
1976
33
      out_one (cie->return_column);
1977
33
    }
1978
0
  else
1979
0
    out_uleb128 (cie->return_column);
1980
33
  if (eh_frame)
1981
31
    {
1982
31
      augmentation_size = 1 + (cie->lsda_encoding != DW_EH_PE_omit);
1983
31
      if (cie->per_encoding != DW_EH_PE_omit)
1984
0
  augmentation_size += 1 + encoding_size (cie->per_encoding);
1985
31
      out_uleb128 (augmentation_size);    /* Augmentation size.  */
1986
1987
31
      emit_expr_encoded (&cie->personality, cie->per_encoding, true);
1988
1989
31
      if (cie->lsda_encoding != DW_EH_PE_omit)
1990
3
  out_one (cie->lsda_encoding);
1991
31
    }
1992
1993
33
  switch (DWARF2_FDE_RELOC_SIZE)
1994
33
    {
1995
0
    case 2:
1996
0
      enc = DW_EH_PE_sdata2;
1997
0
      break;
1998
33
    case 4:
1999
33
      enc = DW_EH_PE_sdata4;
2000
33
      break;
2001
0
    case 8:
2002
0
      enc = DW_EH_PE_sdata8;
2003
0
      break;
2004
0
    default:
2005
0
      abort ();
2006
33
    }
2007
33
#if CFI_DIFF_EXPR_OK || defined tc_cfi_emit_pcrel_expr
2008
33
  enc |= DW_EH_PE_pcrel;
2009
33
#endif
2010
#ifdef DWARF2_FDE_RELOC_ENCODING
2011
  /* Allow target to override encoding.  */
2012
  enc = DWARF2_FDE_RELOC_ENCODING (enc);
2013
#endif
2014
33
  cie->fde_encoding = enc;
2015
33
  if (eh_frame)
2016
31
    out_one (enc);
2017
2018
33
  if (cie->first)
2019
33
    {
2020
137
      for (i = cie->first; i != cie->last; i = i->next)
2021
104
  {
2022
104
    if (CUR_SEG (i) != CUR_SEG (cie))
2023
0
      continue;
2024
104
    output_cfi_insn (i);
2025
104
  }
2026
33
    }
2027
2028
33
  frag_align (align, DW_CFA_nop, 0);
2029
33
  symbol_set_value_now (end_address);
2030
33
}
2031
2032
static void
2033
output_fde (struct fde_entry *fde, struct cie_entry *cie,
2034
      bool eh_frame, struct cfi_insn_data *first,
2035
      int align)
2036
34
{
2037
34
  symbolS *after_size_address, *end_address;
2038
34
  expressionS exp;
2039
34
  offsetT augmentation_size;
2040
34
  enum dwarf2_format fmt = DWARF2_FORMAT (now_seg);
2041
34
  unsigned int offset_size;
2042
34
  unsigned int addr_size;
2043
2044
34
  after_size_address = symbol_temp_make ();
2045
34
  end_address = symbol_temp_make ();
2046
2047
34
  exp.X_op = O_subtract;
2048
34
  exp.X_add_symbol = end_address;
2049
34
  exp.X_op_symbol = after_size_address;
2050
34
  exp.X_add_number = 0;
2051
34
  if (eh_frame || fmt == dwarf2_format_32bit)
2052
34
    offset_size = 4;
2053
0
  else
2054
0
    {
2055
0
      if (fmt == dwarf2_format_64bit)
2056
0
  out_four (-1);
2057
0
      offset_size = 8;
2058
0
    }
2059
34
  emit_expr (&exp, offset_size);    /* Length.  */
2060
34
  symbol_set_value_now (after_size_address);
2061
2062
34
  if (eh_frame)
2063
32
    {
2064
32
      exp.X_op = O_subtract;
2065
32
      exp.X_add_symbol = after_size_address;
2066
32
      exp.X_op_symbol = cie->start_address;
2067
32
      exp.X_add_number = 0;
2068
32
      emit_expr (&exp, offset_size);    /* CIE offset.  */
2069
32
    }
2070
2
  else
2071
2
    {
2072
2
      TC_DWARF2_EMIT_OFFSET (cie->start_address, offset_size);
2073
2
    }
2074
2075
34
  exp.X_op = O_symbol;
2076
34
  if (eh_frame)
2077
32
    {
2078
32
      bfd_reloc_code_real_type code
2079
32
  = tc_cfi_reloc_for_encoding (cie->fde_encoding);
2080
32
      addr_size = DWARF2_FDE_RELOC_SIZE;
2081
32
      if (code != BFD_RELOC_NONE)
2082
0
  {
2083
0
    reloc_howto_type *howto = bfd_reloc_type_lookup (stdoutput, code);
2084
0
    char *p = frag_more (addr_size);
2085
0
    gas_assert (addr_size == (unsigned) howto->bitsize / 8);
2086
0
    md_number_to_chars (p, 0, addr_size);
2087
0
    fix_new (frag_now, p - frag_now->fr_literal, addr_size,
2088
0
       fde->start_address, 0, howto->pc_relative, code);
2089
0
  }
2090
32
      else
2091
32
  {
2092
32
    exp.X_op = O_subtract;
2093
32
    exp.X_add_number = 0;
2094
32
#if CFI_DIFF_EXPR_OK
2095
32
    exp.X_add_symbol = fde->start_address;
2096
32
    exp.X_op_symbol = symbol_temp_new_now ();
2097
32
    emit_expr (&exp, addr_size);  /* Code offset.  */
2098
#else
2099
    exp.X_op = O_symbol;
2100
    exp.X_add_symbol = fde->start_address;
2101
2102
#if defined(tc_cfi_emit_pcrel_expr)
2103
    tc_cfi_emit_pcrel_expr (&exp, addr_size);  /* Code offset.  */
2104
#else
2105
    emit_expr (&exp, addr_size);  /* Code offset.  */
2106
#endif
2107
#endif
2108
32
  }
2109
32
    }
2110
2
  else
2111
2
    {
2112
2
      exp.X_add_number = 0;
2113
2
      exp.X_add_symbol = fde->start_address;
2114
2
      addr_size = DWARF2_ADDR_SIZE (stdoutput);
2115
2
      emit_expr (&exp, addr_size);
2116
2
    }
2117
2118
34
  exp.X_op = O_subtract;
2119
34
  exp.X_add_symbol = fde->end_address;
2120
34
  exp.X_op_symbol = fde->start_address;   /* Code length.  */
2121
34
  exp.X_add_number = 0;
2122
34
  emit_expr (&exp, addr_size);
2123
2124
34
  augmentation_size = encoding_size (fde->lsda_encoding);
2125
34
  if (eh_frame)
2126
32
    out_uleb128 (augmentation_size);   /* Augmentation size.  */
2127
2128
34
  emit_expr_encoded (&fde->lsda, cie->lsda_encoding, false);
2129
2130
114
  for (; first; first = first->next)
2131
80
    if (CUR_SEG (first) == CUR_SEG (fde))
2132
80
      {
2133
80
#ifndef NO_LISTING
2134
80
  if (eh_frame)
2135
79
    listing_override_tail (first->listing_ctxt);
2136
80
#endif
2137
80
  output_cfi_insn (first);
2138
80
      }
2139
2140
34
#ifndef NO_LISTING
2141
  /* Associate any padding with .cfi_endproc.  */
2142
34
  if (eh_frame)
2143
32
    listing_override_tail (fde->listing_end);
2144
34
#endif
2145
2146
34
  frag_align (align, DW_CFA_nop, 0);
2147
34
  symbol_set_value_now (end_address);
2148
34
}
2149
2150
/* Allow these insns to be put in the initial sequence of a CIE.
2151
   If J is non-NULL, then compare I and J insns for a match.  */
2152
2153
static inline bool
2154
initial_cie_insn (const struct cfi_insn_data *i, const struct cfi_insn_data *j)
2155
132
{
2156
132
  if (j && i->insn != j->insn)
2157
1
    return false;
2158
131
  switch (i->insn)
2159
131
    {
2160
55
    case DW_CFA_offset:
2161
118
    case DW_CFA_def_cfa:
2162
118
    case DW_CFA_val_offset:
2163
118
      if (j)
2164
18
  {
2165
18
    if (i->u.ri.reg != j->u.ri.reg)
2166
1
      return false;
2167
17
    if (i->u.ri.offset != j->u.ri.offset)
2168
2
      return false;
2169
17
  }
2170
115
      break;
2171
2172
115
    case DW_CFA_register:
2173
0
      if (j)
2174
0
  {
2175
0
    if (i->u.rr.reg1 != j->u.rr.reg1)
2176
0
      return false;
2177
0
    if (i->u.rr.reg2 != j->u.rr.reg2)
2178
0
      return false;
2179
0
  }
2180
0
      break;
2181
2182
1
    case DW_CFA_def_cfa_register:
2183
1
    case DW_CFA_restore:
2184
5
    case DW_CFA_undefined:
2185
5
    case DW_CFA_same_value:
2186
5
      if (j)
2187
1
  {
2188
1
    if (i->u.r != j->u.r)
2189
0
      return false;
2190
1
  }
2191
5
      break;
2192
2193
5
    case DW_CFA_def_cfa_offset:
2194
0
      if (j)
2195
0
  {
2196
0
    if (i->u.i != j->u.i)
2197
0
      return false;
2198
0
  }
2199
0
      break;
2200
2201
8
    default:
2202
8
      return false;
2203
131
    }
2204
120
  return true;
2205
131
}
2206
2207
static struct cie_entry *
2208
select_cie_for_fde (struct fde_entry *fde, bool eh_frame,
2209
        struct cfi_insn_data **pfirst, int align)
2210
34
{
2211
34
  struct cfi_insn_data *i, *j;
2212
34
  struct cie_entry *cie;
2213
2214
40
  for (cie = cie_root; cie; cie = cie->next)
2215
7
    {
2216
7
      if (CUR_SEG (cie) != CUR_SEG (fde))
2217
0
  continue;
2218
#ifdef tc_cie_fde_equivalent_extra
2219
      if (!tc_cie_fde_equivalent_extra (cie, fde))
2220
  continue;
2221
#endif
2222
7
      if (cie->return_column != fde->return_column
2223
7
    || cie->signal_frame != fde->signal_frame
2224
7
    || cie->per_encoding != fde->per_encoding
2225
7
    || cie->lsda_encoding != fde->lsda_encoding)
2226
0
  continue;
2227
7
      if (cie->per_encoding != DW_EH_PE_omit)
2228
0
  {
2229
0
    if (cie->personality.X_op != fde->personality.X_op
2230
0
        || (cie->personality.X_add_number
2231
0
      != fde->personality.X_add_number))
2232
0
      continue;
2233
0
    switch (cie->personality.X_op)
2234
0
      {
2235
0
      case O_constant:
2236
0
        if (cie->personality.X_unsigned != fde->personality.X_unsigned)
2237
0
    continue;
2238
0
        break;
2239
0
      case O_symbol:
2240
0
        if (cie->personality.X_add_symbol
2241
0
      != fde->personality.X_add_symbol)
2242
0
    continue;
2243
0
        break;
2244
0
      default:
2245
0
        abort ();
2246
0
      }
2247
0
  }
2248
7
      for (i = cie->first, j = fde->data;
2249
23
     i != cie->last && j != NULL;
2250
16
     i = i->next, j = j->next)
2251
20
  {
2252
20
    if (!initial_cie_insn (i, j))
2253
4
      break;
2254
20
  }
2255
2256
7
      if (i == cie->last)
2257
1
  {
2258
1
    *pfirst = j;
2259
1
    return cie;
2260
1
  }
2261
7
    }
2262
2263
33
  cie = XNEW (struct cie_entry);
2264
33
  cie->next = cie_root;
2265
33
  cie_root = cie;
2266
33
  SET_CUR_SEG (cie, CUR_SEG (fde));
2267
33
  cie->return_column = fde->return_column;
2268
33
  cie->signal_frame = fde->signal_frame;
2269
33
  cie->per_encoding = fde->per_encoding;
2270
33
  cie->lsda_encoding = fde->lsda_encoding;
2271
33
  cie->personality = fde->personality;
2272
33
  cie->first = fde->data;
2273
#ifdef tc_cie_entry_init_extra
2274
  tc_cie_entry_init_extra (cie, fde);
2275
#endif
2276
2277
137
  for (i = cie->first; i ; i = i->next)
2278
112
    if (!initial_cie_insn (i, NULL))
2279
8
      break;
2280
2281
33
  cie->last = i;
2282
33
  *pfirst = i;
2283
2284
33
  output_cie (cie, eh_frame, align);
2285
2286
33
  return cie;
2287
34
}
2288
2289
#ifdef md_reg_eh_frame_to_debug_frame
2290
static void
2291
cfi_change_reg_numbers (struct cfi_insn_data *insn, segT ccseg)
2292
{
2293
  for (; insn; insn = insn->next)
2294
    {
2295
      if (CUR_SEG (insn) != ccseg)
2296
  continue;
2297
      switch (insn->insn)
2298
  {
2299
  case DW_CFA_advance_loc:
2300
  case DW_CFA_def_cfa_offset:
2301
  case DW_CFA_remember_state:
2302
  case DW_CFA_restore_state:
2303
  case DW_CFA_GNU_window_save:
2304
  case DW_CFA_AARCH64_negate_ra_state_with_pc:
2305
  case CFI_escape:
2306
  case CFI_label:
2307
    break;
2308
2309
  case DW_CFA_def_cfa:
2310
  case DW_CFA_offset:
2311
    insn->u.ri.reg = md_reg_eh_frame_to_debug_frame (insn->u.ri.reg);
2312
    break;
2313
2314
  case DW_CFA_def_cfa_register:
2315
  case DW_CFA_undefined:
2316
  case DW_CFA_same_value:
2317
  case DW_CFA_restore:
2318
    insn->u.r = md_reg_eh_frame_to_debug_frame (insn->u.r);
2319
    break;
2320
2321
  case DW_CFA_register:
2322
    insn->u.rr.reg1 = md_reg_eh_frame_to_debug_frame (insn->u.rr.reg1);
2323
    insn->u.rr.reg2 = md_reg_eh_frame_to_debug_frame (insn->u.rr.reg2);
2324
    break;
2325
2326
  case CFI_val_encoded_addr:
2327
    insn->u.ea.reg = md_reg_eh_frame_to_debug_frame (insn->u.ea.reg);
2328
    break;
2329
2330
  default:
2331
    abort ();
2332
  }
2333
    }
2334
}
2335
#else
2336
2
#define cfi_change_reg_numbers(insn, cseg) do { } while (0)
2337
#endif
2338
2339
#if SUPPORT_COMPACT_EH
2340
static void
2341
cfi_emit_eh_header (symbolS *sym, bfd_vma addend)
2342
{
2343
  expressionS exp;
2344
2345
  exp.X_add_number = addend;
2346
  exp.X_add_symbol = sym;
2347
  emit_expr_encoded (&exp, DW_EH_PE_sdata4 | DW_EH_PE_pcrel, false);
2348
}
2349
2350
static void
2351
output_eh_header (struct fde_entry *fde)
2352
{
2353
  char *p;
2354
  bfd_vma addend;
2355
2356
  if (fde->eh_header_type == EH_COMPACT_INLINE)
2357
    addend = 0;
2358
  else
2359
    addend = 1;
2360
2361
  cfi_emit_eh_header (fde->start_address, addend);
2362
2363
  if (fde->eh_header_type == EH_COMPACT_INLINE)
2364
    {
2365
      p = frag_more (4);
2366
      /* Inline entries always use PR1.  */
2367
      *(p++) = 1;
2368
      memcpy(p, fde->eh_data, 3);
2369
    }
2370
  else
2371
    {
2372
      if (fde->eh_header_type == EH_COMPACT_LEGACY)
2373
  addend = 1;
2374
      else if (fde->eh_header_type == EH_COMPACT_OUTLINE
2375
         || fde->eh_header_type == EH_COMPACT_OUTLINE_DONE)
2376
  addend = 0;
2377
      else
2378
  abort ();
2379
      cfi_emit_eh_header (fde->eh_loc, addend);
2380
    }
2381
}
2382
#endif
2383
2384
void
2385
cfi_finish (void)
2386
207
{
2387
207
  struct cie_entry *cie, *cie_next;
2388
207
  segT cfi_seg, ccseg;
2389
207
  struct fde_entry *fde;
2390
207
  struct cfi_insn_data *first;
2391
207
#ifndef NO_LISTING
2392
  /* We may temporarily replace listing_tail, which otherwise isn't supposed
2393
     to be changing anymore.  Play safe and restore the original value
2394
     afterwards.  */
2395
207
  struct list_info_struct *saved_listing_tail = NULL;
2396
207
#endif
2397
207
  int save_flag_traditional_format, seek_next_seg;
2398
2399
207
  if (all_fde_data == 0)
2400
176
    return;
2401
2402
31
  if ((all_cfi_sections & CFI_EMIT_eh_frame) != 0
2403
6
      || (all_cfi_sections & CFI_EMIT_eh_frame_compact) != 0)
2404
25
    {
2405
      /* Make sure check_eh_frame doesn't do anything with our output.  */
2406
25
      save_flag_traditional_format = flag_traditional_format;
2407
25
      flag_traditional_format = 1;
2408
2409
25
      if (!EH_FRAME_LINKONCE)
2410
25
  {
2411
    /* Open .eh_frame section.  */
2412
25
    cfi_seg = get_cfi_seg (NULL, ".eh_frame",
2413
25
         (SEC_ALLOC | SEC_LOAD | SEC_DATA
2414
25
          | DWARF2_EH_FRAME_READ_ONLY),
2415
25
         EH_FRAME_ALIGNMENT);
2416
#ifdef md_fix_up_eh_frame
2417
    md_fix_up_eh_frame (cfi_seg);
2418
#else
2419
25
    (void) cfi_seg;
2420
25
#endif
2421
25
  }
2422
2423
25
      do
2424
25
  {
2425
25
    ccseg = NULL;
2426
25
    seek_next_seg = 0;
2427
2428
57
    for (fde = all_fde_data; fde ; fde = fde->next)
2429
32
      {
2430
32
        if ((fde->sections & CFI_EMIT_eh_frame) == 0
2431
0
      && (fde->sections & CFI_EMIT_eh_frame_compact) == 0)
2432
0
    continue;
2433
2434
#if SUPPORT_COMPACT_EH
2435
        /* Emit a LEGACY format header if we have processed all
2436
     of the .cfi directives without encountering either inline or
2437
     out-of-line compact unwinding opcodes.  */
2438
        if (fde->eh_header_type == EH_COMPACT_HAS_LSDA
2439
      || fde->eh_header_type == EH_COMPACT_UNKNOWN)
2440
    fde->eh_header_type = EH_COMPACT_LEGACY;
2441
2442
        if (fde->eh_header_type != EH_COMPACT_LEGACY)
2443
    continue;
2444
#endif
2445
32
        if (EH_FRAME_LINKONCE)
2446
0
    {
2447
0
      if (HANDLED (fde))
2448
0
        continue;
2449
0
      if (seek_next_seg && CUR_SEG (fde) != ccseg)
2450
0
        {
2451
0
          seek_next_seg = 2;
2452
0
          continue;
2453
0
        }
2454
0
      if (!seek_next_seg)
2455
0
        {
2456
0
          ccseg = CUR_SEG (fde);
2457
          /* Open .eh_frame section.  */
2458
0
          cfi_seg = get_cfi_seg (ccseg, ".eh_frame",
2459
0
               (SEC_ALLOC | SEC_LOAD | SEC_DATA
2460
0
                | DWARF2_EH_FRAME_READ_ONLY),
2461
0
               EH_FRAME_ALIGNMENT);
2462
#ifdef md_fix_up_eh_frame
2463
          md_fix_up_eh_frame (cfi_seg);
2464
#else
2465
0
          (void) cfi_seg;
2466
0
#endif
2467
0
          seek_next_seg = 1;
2468
0
        }
2469
0
      SET_HANDLED (fde, 1);
2470
0
    }
2471
2472
32
        if (fde->end_address == NULL)
2473
32
    {
2474
32
      as_bad (_("open CFI at the end of file; "
2475
32
          "missing .cfi_endproc directive"));
2476
32
      fde->end_address = fde->start_address;
2477
32
    }
2478
2479
32
#ifndef NO_LISTING
2480
32
        {
2481
32
    struct list_info_struct *listing_prev
2482
32
      = listing_override_tail (fde->listing_ctxt);
2483
2484
32
    if (!saved_listing_tail)
2485
32
      saved_listing_tail = listing_prev;
2486
32
        }
2487
32
#endif
2488
2489
32
        cie = select_cie_for_fde (fde, true, &first, 2);
2490
32
        fde->eh_loc = symbol_temp_new_now ();
2491
32
        output_fde (fde, cie, true, first,
2492
32
        fde->next == NULL ? EH_FRAME_ALIGNMENT : 2);
2493
32
      }
2494
2495
56
    for (cie = cie_root; cie; cie = cie_next)
2496
31
      {
2497
31
        cie_next = cie->next;
2498
31
        free (cie);
2499
31
      }
2500
25
    cie_root = NULL;
2501
25
  }
2502
25
      while (EH_FRAME_LINKONCE && seek_next_seg == 2);
2503
2504
25
      if (EH_FRAME_LINKONCE)
2505
0
  for (fde = all_fde_data; fde ; fde = fde->next)
2506
0
    SET_HANDLED (fde, 0);
2507
2508
#if SUPPORT_COMPACT_EH
2509
      if (compact_eh)
2510
  {
2511
    /* Create remaining out of line table entries.  */
2512
    do
2513
      {
2514
        ccseg = NULL;
2515
        seek_next_seg = 0;
2516
2517
        for (fde = all_fde_data; fde ; fde = fde->next)
2518
    {
2519
      if ((fde->sections & CFI_EMIT_eh_frame) == 0
2520
          && (fde->sections & CFI_EMIT_eh_frame_compact) == 0)
2521
        continue;
2522
2523
      if (fde->eh_header_type != EH_COMPACT_OUTLINE)
2524
        continue;
2525
      if (HANDLED (fde))
2526
        continue;
2527
      if (seek_next_seg && CUR_SEG (fde) != ccseg)
2528
        {
2529
          seek_next_seg = 2;
2530
          continue;
2531
        }
2532
      if (!seek_next_seg)
2533
        {
2534
          ccseg = CUR_SEG (fde);
2535
          /* Open .gnu_extab section.  */
2536
          get_cfi_seg (ccseg, ".gnu_extab",
2537
           (SEC_ALLOC | SEC_LOAD | SEC_DATA
2538
            | DWARF2_EH_FRAME_READ_ONLY),
2539
           1);
2540
          seek_next_seg = 1;
2541
        }
2542
      SET_HANDLED (fde, 1);
2543
2544
      frag_align (1, 0, 0);
2545
      record_alignment (now_seg, 1);
2546
      output_compact_unwind_data (fde, 1);
2547
    }
2548
      }
2549
    while (EH_FRAME_LINKONCE && seek_next_seg == 2);
2550
2551
    for (fde = all_fde_data; fde ; fde = fde->next)
2552
      SET_HANDLED (fde, 0);
2553
2554
    /* Create index table fragments.  */
2555
    do
2556
      {
2557
        ccseg = NULL;
2558
        seek_next_seg = 0;
2559
2560
        for (fde = all_fde_data; fde ; fde = fde->next)
2561
    {
2562
      if ((fde->sections & CFI_EMIT_eh_frame) == 0
2563
          && (fde->sections & CFI_EMIT_eh_frame_compact) == 0)
2564
        continue;
2565
2566
      if (HANDLED (fde))
2567
        continue;
2568
      if (seek_next_seg && CUR_SEG (fde) != ccseg)
2569
        {
2570
          seek_next_seg = 2;
2571
          continue;
2572
        }
2573
      if (!seek_next_seg)
2574
        {
2575
          ccseg = CUR_SEG (fde);
2576
          /* Open .eh_frame_entry section.  */
2577
          cfi_seg = get_cfi_seg (ccseg, ".eh_frame_entry",
2578
               (SEC_ALLOC | SEC_LOAD | SEC_DATA
2579
                | DWARF2_EH_FRAME_READ_ONLY),
2580
               2);
2581
          seek_next_seg = 1;
2582
        }
2583
      SET_HANDLED (fde, 1);
2584
2585
      output_eh_header (fde);
2586
    }
2587
      }
2588
    while (seek_next_seg == 2);
2589
2590
    for (fde = all_fde_data; fde ; fde = fde->next)
2591
      SET_HANDLED (fde, 0);
2592
  }
2593
#endif /* SUPPORT_COMPACT_EH */
2594
2595
25
      flag_traditional_format = save_flag_traditional_format;
2596
25
    }
2597
2598
  /* Generate SFrame section if the user:
2599
  - enables via the command line option, or
2600
  - default-enabled at configure-time via --enable-default-sframe, or
2601
  - specifies .sframe in the .cfi_sections directive and does not disable
2602
    via the command line.  */
2603
31
  if (flag_gen_sframe == GEN_SFRAME_ENABLED
2604
31
      || flag_gen_sframe == GEN_SFRAME_CONFIG_ENABLED
2605
31
      || ((all_cfi_sections & CFI_EMIT_sframe) != 0
2606
3
    && flag_gen_sframe != GEN_SFRAME_DISABLED))
2607
3
    {
2608
3
#ifdef support_sframe_p
2609
3
      if (support_sframe_p () && !SUPPORT_FRAME_LINKONCE)
2610
3
  {
2611
3
    segT sframe_seg;
2612
3
    int alignment = ffs (DWARF2_ADDR_SIZE (stdoutput)) - 1;
2613
2614
3
    sframe_seg = get_cfi_seg (NULL, ".sframe",
2615
3
            (SEC_ALLOC | SEC_LOAD | SEC_DATA
2616
3
             | DWARF2_EH_FRAME_READ_ONLY),
2617
3
            alignment);
2618
3
    elf_section_type (sframe_seg) = SHT_GNU_SFRAME;
2619
3
    output_sframe (sframe_seg);
2620
3
  }
2621
0
      else
2622
0
#endif
2623
  /* Avoid erroring with DEFAULT_SFRAME for non-default options, like
2624
     -32 on x86_64.  */
2625
0
  sframe_as_bad ("%s", _(".sframe not supported for target"));
2626
3
    }
2627
2628
31
  if ((all_cfi_sections & CFI_EMIT_debug_frame) != 0)
2629
2
    {
2630
2
      int alignment = ffs (DWARF2_ADDR_SIZE (stdoutput)) - 1;
2631
2632
2
      if (!SUPPORT_FRAME_LINKONCE)
2633
2
  get_cfi_seg (NULL, ".debug_frame",
2634
2
         SEC_READONLY | SEC_DEBUGGING,
2635
2
         alignment);
2636
2637
2
      do
2638
2
  {
2639
2
    ccseg = NULL;
2640
2
    seek_next_seg = 0;
2641
2642
5
    for (fde = all_fde_data; fde ; fde = fde->next)
2643
3
      {
2644
3
        if ((fde->sections & CFI_EMIT_debug_frame) == 0)
2645
1
    continue;
2646
2647
2
        if (SUPPORT_FRAME_LINKONCE)
2648
0
    {
2649
0
      if (HANDLED (fde))
2650
0
        continue;
2651
0
      if (seek_next_seg && CUR_SEG (fde) != ccseg)
2652
0
        {
2653
0
          seek_next_seg = 2;
2654
0
          continue;
2655
0
        }
2656
0
      if (!seek_next_seg)
2657
0
        {
2658
0
          ccseg = CUR_SEG (fde);
2659
          /* Open .debug_frame section.  */
2660
0
          get_cfi_seg (ccseg, ".debug_frame",
2661
0
           SEC_READONLY | SEC_DEBUGGING,
2662
0
           alignment);
2663
0
          seek_next_seg = 1;
2664
0
        }
2665
0
      SET_HANDLED (fde, 1);
2666
0
    }
2667
2
        if (fde->end_address == NULL)
2668
1
    {
2669
1
      as_bad (_("open CFI at the end of file; "
2670
1
          "missing .cfi_endproc directive"));
2671
1
      fde->end_address = fde->start_address;
2672
1
    }
2673
2674
2
        fde->per_encoding = DW_EH_PE_omit;
2675
2
        fde->lsda_encoding = DW_EH_PE_omit;
2676
2
        cfi_change_reg_numbers (fde->data, ccseg);
2677
2
        cie = select_cie_for_fde (fde, false, &first, alignment);
2678
2
        output_fde (fde, cie, false, first, alignment);
2679
2
      }
2680
2681
4
    for (cie = cie_root; cie; cie = cie_next)
2682
2
      {
2683
2
        cie_next = cie->next;
2684
2
        free (cie);
2685
2
      }
2686
2
    cie_root = NULL;
2687
2
  }
2688
2
      while (SUPPORT_FRAME_LINKONCE && seek_next_seg == 2);
2689
2690
2
      if (SUPPORT_FRAME_LINKONCE)
2691
0
  for (fde = all_fde_data; fde ; fde = fde->next)
2692
0
    SET_HANDLED (fde, 0);
2693
2
    }
2694
31
  all_fde_data = NULL;
2695
31
  last_fde_data = &all_fde_data;
2696
31
  cfi_sections_set = false;
2697
31
  cfi_sections = CFI_EMIT_eh_frame;
2698
31
  all_cfi_sections = 0;
2699
31
  last_fde = NULL;
2700
31
  if (dwcfi_hash)
2701
0
    {
2702
0
      htab_delete (dwcfi_hash);
2703
0
      dwcfi_hash = NULL;
2704
0
    }
2705
2706
31
#ifndef NO_LISTING
2707
31
  if (saved_listing_tail)
2708
0
    listing_tail = saved_listing_tail;
2709
31
#endif
2710
31
}
2711
2712
#else /* TARGET_USE_CFIPOP */
2713
2714
/* Emit an intelligible error message for missing support.  */
2715
2716
static void
2717
dot_cfi_dummy (int ignored ATTRIBUTE_UNUSED)
2718
{
2719
  as_bad (_("CFI is not supported for this target"));
2720
  ignore_rest_of_line ();
2721
}
2722
2723
const pseudo_typeS cfi_pseudo_table[] =
2724
  {
2725
    { "cfi_sections", dot_cfi_dummy, 0 },
2726
    { "cfi_startproc", dot_cfi_dummy, 0 },
2727
    { "cfi_endproc", dot_cfi_dummy, 0 },
2728
    { "cfi_fde_data", dot_cfi_dummy, 0 },
2729
    { "cfi_def_cfa", dot_cfi_dummy, 0 },
2730
    { "cfi_def_cfa_register", dot_cfi_dummy, 0 },
2731
    { "cfi_def_cfa_offset", dot_cfi_dummy, 0 },
2732
    { "cfi_adjust_cfa_offset", dot_cfi_dummy, 0 },
2733
    { "cfi_offset", dot_cfi_dummy, 0 },
2734
    { "cfi_rel_offset", dot_cfi_dummy, 0 },
2735
    { "cfi_register", dot_cfi_dummy, 0 },
2736
    { "cfi_return_column", dot_cfi_dummy, 0 },
2737
    { "cfi_restore", dot_cfi_dummy, 0 },
2738
    { "cfi_undefined", dot_cfi_dummy, 0 },
2739
    { "cfi_same_value", dot_cfi_dummy, 0 },
2740
    { "cfi_remember_state", dot_cfi_dummy, 0 },
2741
    { "cfi_restore_state", dot_cfi_dummy, 0 },
2742
    { "cfi_window_save", dot_cfi_dummy, 0 },
2743
    { "cfi_negate_ra_state", dot_cfi_dummy, 0 },
2744
    { "cfi_negate_ra_state_with_pc", dot_cfi_dummy, 0 },
2745
    { "cfi_escape", dot_cfi_dummy, 0 },
2746
    { "cfi_signal_frame", dot_cfi_dummy, 0 },
2747
    { "cfi_personality", dot_cfi_dummy, 0 },
2748
    { "cfi_personality_id", dot_cfi_dummy, 0 },
2749
    { "cfi_lsda", dot_cfi_dummy, 0 },
2750
    { "cfi_val_encoded_addr", dot_cfi_dummy, 0 },
2751
    { "cfi_inline_lsda", dot_cfi_dummy, 0 },
2752
    { "cfi_label", dot_cfi_dummy, 0 },
2753
    { "cfi_val_offset", dot_cfi_dummy, 0 },
2754
    { NULL, NULL, 0 }
2755
  };
2756
2757
void
2758
cfi_finish (void)
2759
{
2760
}
2761
#endif /* TARGET_USE_CFIPOP */