Coverage Report

Created: 2026-05-11 07:54

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
110
#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
109
#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
62
#define DWARF2_EH_FRAME_READ_ONLY SEC_READONLY
61
#endif
62
63
#ifndef EH_FRAME_ALIGNMENT
64
96
#define EH_FRAME_ALIGNMENT (bfd_get_arch_size (stdoutput) == 64 ? 3 : 2)
65
#endif
66
67
248
#define EH_FRAME_LINKONCE (SUPPORT_FRAME_LINKONCE || compact_eh \
68
248
         || TARGET_MULTIPLE_EH_FRAME_SECTIONS)
69
70
#ifndef DWARF2_FORMAT
71
111
#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
3.59k
#define CUR_SEG(structp) NULL
85
2.41k
#define SET_CUR_SEG(structp, seg) (void) (0 && seg)
86
0
#define HANDLED(structp) 0
87
80
#define SET_HANDLED(structp, val) (void) (0 && val)
88
#endif
89
90
#ifndef tc_cfi_reloc_for_encoding
91
59
#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
817
{
115
817
  FRAG_APPEND_1_CHAR (byte);
116
817
}
117
118
/* Emit a two-byte word into the current segment.  */
119
120
static inline void
121
out_two (int data)
122
0
{
123
0
  md_number_to_chars (frag_more (2), data, 2);
124
0
}
125
126
/* Emit a four byte word into the current segment.  */
127
128
static inline void
129
out_four (int data)
130
57
{
131
57
  md_number_to_chars (frag_more (4), data, 4);
132
57
}
133
134
/* Emit an unsigned "little-endian base 128" number.  */
135
136
static void
137
out_uleb128 (addressT value)
138
663
{
139
663
  output_leb128 (frag_more (sizeof_leb128 (value, 0)), value, 0);
140
663
}
141
142
/* Emit an unsigned "little-endian base 128" number.  */
143
144
static void
145
out_sleb128 (offsetT value)
146
61
{
147
61
  output_leb128 (frag_more (sizeof_leb128 (value, 1)), value, 1);
148
61
}
149
150
static unsigned int
151
encoding_size (unsigned char encoding)
152
167
{
153
167
  if (encoding == DW_EH_PE_omit)
154
161
    return 0;
155
6
  switch (encoding & 0x7)
156
6
    {
157
2
    case 0:
158
2
      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
2
    case DW_EH_PE_udata8:
164
2
      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
109
{
176
109
  unsigned int size = encoding_size (encoding);
177
109
  bfd_reloc_code_real_type code;
178
179
109
  if (encoding == DW_EH_PE_omit)
180
106
    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
1
    {
197
1
#if CFI_DIFF_EXPR_OK
198
1
      expressionS tmp = *exp;
199
1
      tmp.X_op = O_subtract;
200
1
      tmp.X_op_symbol = symbol_temp_new_now ();
201
1
      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
1
    }
208
2
  else
209
2
    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
80
{
398
80
  struct fde_entry *fde = notes_calloc (1, sizeof (*fde));
399
400
80
  frchain_now->frch_cfi_data = notes_calloc (1, sizeof (struct frch_cfi_data));
401
80
  frchain_now->frch_cfi_data->cur_fde_data = fde;
402
80
  *last_fde_data = fde;
403
80
  last_fde_data = &fde->next;
404
80
  SET_CUR_SEG (fde, is_now_linkonce_segment ());
405
80
  SET_HANDLED (fde, 0);
406
80
  fde->last = &fde->data;
407
80
  fde->return_column = DWARF2_DEFAULT_RETURN_COLUMN;
408
80
  fde->per_encoding = DW_EH_PE_omit;
409
80
  fde->lsda_encoding = DW_EH_PE_omit;
410
80
  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
80
  return fde;
416
80
}
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
2.28k
{
432
2.28k
  struct cfi_insn_data *insn = notes_calloc (1, sizeof (*insn));
433
2.28k
  struct fde_entry *cur_fde_data = frchain_now->frch_cfi_data->cur_fde_data;
434
435
2.28k
  *cur_fde_data->last = insn;
436
2.28k
  cur_fde_data->last = &insn->next;
437
2.28k
  SET_CUR_SEG (insn, is_now_linkonce_segment ());
438
2.28k
#ifndef NO_LISTING
439
2.28k
  insn->listing_ctxt = cur_fde_data->listing_ctxt ? listing_tail : NULL;
440
2.28k
#endif
441
2.28k
  return insn;
442
2.28k
}
443
444
/* Construct a new FDE structure that begins at LABEL.  */
445
446
void
447
cfi_new_fde (symbolS *label, bool do_listing)
448
80
{
449
80
  struct fde_entry *fde = alloc_fde_entry ();
450
80
  fde->start_address = label;
451
80
  if (do_listing)
452
0
    {
453
0
#ifndef NO_LISTING
454
0
      fde->listing_ctxt = listing_tail;
455
0
#endif
456
0
    }
457
80
  frchain_now->frch_cfi_data->last_address = label;
458
80
}
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
80
{
492
80
  all_cfi_sections |= cfi_sections;
493
80
  frchain_now->frch_cfi_data->cur_fde_data->sections = all_cfi_sections;
494
80
  cfi_sections_set = true;
495
80
}
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
361
{
510
361
  struct cfi_insn_data *insn_ptr = alloc_cfi_insn_data ();
511
512
361
  insn_ptr->insn = insn;
513
361
  insn_ptr->u.r = regno;
514
361
}
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
1
{
528
1
  struct cfi_insn_data *insn_ptr = alloc_cfi_insn_data ();
529
530
1
  insn_ptr->insn = insn;
531
1
  insn_ptr->u.rr.reg1 = reg1;
532
1
  insn_ptr->u.rr.reg2 = reg2;
533
1
}
534
535
static void
536
cfi_add_CFA_insn_reg_offset (int insn, unsigned regno, offsetT offset)
537
226
{
538
226
  struct cfi_insn_data *insn_ptr = alloc_cfi_insn_data ();
539
540
226
  insn_ptr->insn = insn;
541
226
  insn_ptr->u.ri.reg = regno;
542
226
  insn_ptr->u.ri.offset = offset;
543
226
}
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
75
{
550
75
  struct cfi_insn_data *insn = alloc_cfi_insn_data ();
551
552
75
  insn->insn = DW_CFA_advance_loc;
553
75
  insn->u.ll.lab1 = frchain_now->frch_cfi_data->last_address;
554
75
  insn->u.ll.lab2 = label;
555
556
75
  frchain_now->frch_cfi_data->last_address = label;
557
75
}
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
29
{
564
29
  struct cfi_insn_data *insn = alloc_cfi_insn_data ();
565
566
29
  insn->insn = CFI_label;
567
29
  insn->u.sym_name = notes_strdup (name);
568
29
}
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
109
{
575
109
  unsigned int abs_data_align;
576
577
109
  gas_assert (DWARF2_CIE_DATA_ALIGNMENT != 0);
578
109
  cfi_add_CFA_insn_reg_offset (DW_CFA_offset, regno, offset);
579
580
109
  abs_data_align = (DWARF2_CIE_DATA_ALIGNMENT < 0
581
109
        ? -DWARF2_CIE_DATA_ALIGNMENT : DWARF2_CIE_DATA_ALIGNMENT);
582
109
  if (offset % abs_data_align)
583
2
    as_bad (_("register save offset not a multiple of %u"), abs_data_align);
584
109
}
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
117
{
607
117
  cfi_add_CFA_insn_reg_offset (DW_CFA_def_cfa, regno, offset);
608
117
  frchain_now->frch_cfi_data->cur_cfa_offset = offset;
609
117
}
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
1
{
616
1
  cfi_add_CFA_insn_reg_reg (DW_CFA_register, reg1, reg2);
617
1
}
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
31
{
624
31
  cfi_add_CFA_insn_reg (DW_CFA_def_cfa_register, regno);
625
31
}
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
60
{
639
60
  cfi_add_CFA_insn_reg (DW_CFA_restore, regno);
640
60
}
641
642
void
643
cfi_add_CFA_undefined (unsigned regno)
644
270
{
645
270
  cfi_add_CFA_insn_reg (DW_CFA_undefined, regno);
646
270
}
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
107
{
736
107
  SKIP_WHITESPACE ();
737
107
  if (*input_line_pointer == ',')
738
55
    input_line_pointer++;
739
52
  else
740
52
    as_bad (_("missing separator"));
741
107
}
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
451
{
771
451
  int regno;
772
451
  expressionS exp;
773
774
451
  tc_parse_to_dw2regnum (&exp);
775
451
  switch (exp.X_op)
776
451
    {
777
0
    case O_register:
778
109
    case O_constant:
779
109
      regno = exp.X_add_number;
780
109
      break;
781
782
342
    default:
783
342
      regno = -1;
784
342
      break;
785
451
    }
786
787
451
  if (regno < 0)
788
343
    {
789
343
      as_bad (_("bad register expression"));
790
343
      regno = 0;
791
343
    }
792
793
451
  return regno;
794
451
}
795
796
static offsetT
797
cfi_parse_const (void)
798
137
{
799
137
  return get_absolute_expression ();
800
137
}
801
802
static void
803
dot_cfi (int arg)
804
198
{
805
198
  offsetT offset;
806
198
  unsigned reg1, reg2;
807
808
198
  if (frchain_now->frch_cfi_data == NULL)
809
3
    {
810
3
      as_bad (_("CFI instruction used without previous .cfi_startproc"));
811
3
      ignore_rest_of_line ();
812
3
      return;
813
3
    }
814
815
  /* If the last address was not at the current PC, advance to current.  */
816
195
  if (symbol_get_frag (frchain_now->frch_cfi_data->last_address) != frag_now
817
170
      || (S_GET_VALUE (frchain_now->frch_cfi_data->last_address)
818
170
    != frag_now_fix ()))
819
38
    cfi_add_advance_loc (symbol_temp_new_now ());
820
821
195
  switch (arg)
822
195
    {
823
8
    case DW_CFA_offset:
824
8
      reg1 = cfi_parse_reg ();
825
8
      cfi_parse_separator ();
826
8
      offset = cfi_parse_const ();
827
8
      cfi_add_CFA_offset (reg1, offset);
828
8
      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
23
    case CFI_rel_offset:
838
23
      reg1 = cfi_parse_reg ();
839
23
      cfi_parse_separator ();
840
23
      offset = cfi_parse_const ();
841
23
      cfi_add_CFA_offset (reg1,
842
23
        offset - frchain_now->frch_cfi_data->cur_cfa_offset);
843
23
      break;
844
845
39
    case DW_CFA_def_cfa:
846
39
      reg1 = cfi_parse_reg ();
847
39
      cfi_parse_separator ();
848
39
      offset = cfi_parse_const ();
849
39
      cfi_add_CFA_def_cfa (reg1, offset);
850
39
      break;
851
852
1
    case DW_CFA_register:
853
1
      reg1 = cfi_parse_reg ();
854
1
      cfi_parse_separator ();
855
1
      reg2 = cfi_parse_reg ();
856
1
      cfi_add_CFA_register (reg1, reg2);
857
1
      break;
858
859
31
    case DW_CFA_def_cfa_register:
860
31
      reg1 = cfi_parse_reg ();
861
31
      cfi_add_CFA_def_cfa_register (reg1);
862
31
      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
57
    case DW_CFA_restore:
876
57
      for (;;)
877
60
  {
878
60
    reg1 = cfi_parse_reg ();
879
60
    cfi_add_CFA_restore (reg1);
880
60
    SKIP_WHITESPACE ();
881
60
    if (*input_line_pointer != ',')
882
57
      break;
883
3
    ++input_line_pointer;
884
3
  }
885
57
      break;
886
887
32
    case DW_CFA_undefined:
888
32
      for (;;)
889
270
  {
890
270
    reg1 = cfi_parse_reg ();
891
270
    cfi_add_CFA_undefined (reg1);
892
270
    SKIP_WHITESPACE ();
893
270
    if (*input_line_pointer != ',')
894
32
      break;
895
238
    ++input_line_pointer;
896
238
  }
897
32
      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
195
    }
932
933
195
  demand_empty_rest_of_line ();
934
195
}
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
1.57k
{
954
1.57k
  struct cfi_escape_data *head, **tail;
955
1.57k
  struct cfi_insn_data *insn;
956
957
1.57k
  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
1.57k
  if (symbol_get_frag (frchain_now->frch_cfi_data->last_address) != frag_now
966
1.56k
      || (S_GET_VALUE (frchain_now->frch_cfi_data->last_address)
967
1.56k
    != frag_now_fix ()))
968
25
    cfi_add_advance_loc (symbol_temp_new_now ());
969
970
1.57k
  tail = &head;
971
1.57k
  do
972
1.69k
    {
973
1.69k
      struct cfi_escape_data *e = notes_alloc (sizeof (*e));
974
1.69k
      char *id, *ilp_save = input_line_pointer;
975
1.69k
      char c = get_symbol_name (&id);
976
977
1.69k
      if (strcmp (id, "sleb128") == 0)
978
0
  e->type = CFI_ESC_sleb128;
979
1.69k
      else if (strcmp (id, "uleb128") == 0)
980
0
  e->type = CFI_ESC_uleb128;
981
1.69k
      else if (strcmp (id, "data2") == 0)
982
0
  e->type = 2;
983
1.69k
      else if (TC_ADDRESS_BYTES () >= 4 && strcmp (id, "data4") == 0)
984
105
  e->type = 4;
985
1.58k
      else if (TC_ADDRESS_BYTES () >= 8 && strcmp (id, "data8") == 0)
986
16
  e->type = 8;
987
1.57k
      else if (strcmp (id, "addr") == 0)
988
0
  e->type = TC_ADDRESS_BYTES ();
989
1.57k
      else
990
1.57k
  e->type = CFI_ESC_byte;
991
992
1.69k
      c = restore_line_pointer (c);
993
994
1.69k
      if (e->type != CFI_ESC_byte)
995
121
  {
996
121
    if (is_whitespace (c))
997
0
      c = *++input_line_pointer;
998
121
    if (c != '(')
999
121
      e->type = CFI_ESC_byte;
1000
121
  }
1001
1.69k
      if (e->type == CFI_ESC_byte)
1002
1.69k
  input_line_pointer = ilp_save;
1003
1004
1.69k
      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
1.69k
      else
1012
1.69k
  {
1013
    /* We may still be at an opening parenthesis.  Leave it to expression()
1014
       to parse it and find the matching closing one.  */
1015
1.69k
    e->reloc = do_parse_cons_expression (&e->exp, e->type);
1016
1.69k
  }
1017
1018
1.69k
      *tail = e;
1019
1.69k
      tail = &e->next;
1020
1.69k
    }
1021
1.69k
  while (*input_line_pointer++ == ',');
1022
1.57k
  *tail = NULL;
1023
1024
1.57k
  insn = alloc_cfi_insn_data ();
1025
1.57k
  insn->insn = CFI_escape;
1026
1.57k
  insn->u.esc = head;
1027
1028
1.57k
  --input_line_pointer;
1029
1.57k
  demand_empty_rest_of_line ();
1030
1.57k
}
1031
1032
static void
1033
dot_cfi_personality (int ignored ATTRIBUTE_UNUSED)
1034
10
{
1035
10
  struct fde_entry *fde;
1036
10
  offsetT encoding;
1037
1038
10
  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
10
  fde = frchain_now->frch_cfi_data->cur_fde_data;
1046
10
  encoding = cfi_parse_const ();
1047
10
  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
10
  if ((encoding & 0xff) != encoding
1055
6
      || ((((encoding & 0x70) != 0
1056
4
#if CFI_DIFF_EXPR_OK || defined tc_cfi_emit_pcrel_expr
1057
4
      && (encoding & 0x70) != DW_EH_PE_pcrel
1058
6
#endif
1059
6
      )
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
8
    {
1065
8
      as_bad (_("invalid or unsupported encoding in .cfi_personality"));
1066
8
      ignore_rest_of_line ();
1067
8
      return;
1068
8
    }
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
50
{
1106
50
  struct fde_entry *fde;
1107
50
  offsetT encoding;
1108
1109
50
  if (frchain_now->frch_cfi_data == NULL)
1110
11
    {
1111
11
      as_bad (_("CFI instruction used without previous .cfi_startproc"));
1112
11
      ignore_rest_of_line ();
1113
11
      return;
1114
11
    }
1115
1116
39
  fde = frchain_now->frch_cfi_data->cur_fde_data;
1117
39
  encoding = cfi_parse_const ();
1118
39
  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
39
  if ((encoding & 0xff) != encoding
1126
38
      || ((((encoding & 0x70) != 0
1127
22
#if CFI_DIFF_LSDA_OK || defined tc_cfi_emit_pcrel_expr
1128
22
      && (encoding & 0x70) != DW_EH_PE_pcrel
1129
38
#endif
1130
38
      )
1131
     /* leb128 can be handled, but does something actually need it?  */
1132
38
     || (encoding & 7) == DW_EH_PE_uleb128
1133
38
     || (encoding & 7) > DW_EH_PE_udata8)
1134
0
    && tc_cfi_reloc_for_encoding (encoding) == BFD_RELOC_NONE))
1135
1
    {
1136
1
      as_bad (_("invalid or unsupported encoding in .cfi_lsda"));
1137
1
      ignore_rest_of_line ();
1138
1
      return;
1139
1
    }
1140
1141
38
  if (*input_line_pointer++ != ',')
1142
23
    {
1143
23
      as_bad (_(".cfi_lsda requires encoding and symbol arguments"));
1144
23
      ignore_rest_of_line ();
1145
23
      return;
1146
23
    }
1147
1148
15
  fde->lsda_encoding = encoding;
1149
1150
15
  expression_and_evaluate (&fde->lsda);
1151
15
  switch (fde->lsda.X_op)
1152
15
    {
1153
3
    case O_symbol:
1154
3
      break;
1155
10
    case O_constant:
1156
10
      if ((encoding & 0x70) == DW_EH_PE_pcrel)
1157
0
  encoding = DW_EH_PE_omit;
1158
10
      break;
1159
2
    default:
1160
2
      encoding = DW_EH_PE_omit;
1161
2
      break;
1162
15
    }
1163
1164
15
  fde->lsda_encoding = encoding;
1165
1166
15
  if (encoding == DW_EH_PE_omit)
1167
2
    {
1168
2
      as_bad (_("wrong second argument to .cfi_lsda"));
1169
2
      ignore_rest_of_line ();
1170
2
      return;
1171
2
    }
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
33
{
1179
33
  struct cfi_insn_data *insn_ptr;
1180
33
  offsetT encoding;
1181
1182
33
  if (frchain_now->frch_cfi_data == NULL)
1183
15
    {
1184
15
      as_bad (_("CFI instruction used without previous .cfi_startproc"));
1185
15
      ignore_rest_of_line ();
1186
15
      return;
1187
15
    }
1188
1189
  /* If the last address was not at the current PC, advance to current.  */
1190
18
  if (symbol_get_frag (frchain_now->frch_cfi_data->last_address) != frag_now
1191
18
      || (S_GET_VALUE (frchain_now->frch_cfi_data->last_address)
1192
18
    != frag_now_fix ()))
1193
0
    cfi_add_advance_loc (symbol_temp_new_now ());
1194
1195
18
  insn_ptr = alloc_cfi_insn_data ();
1196
18
  insn_ptr->insn = CFI_val_encoded_addr;
1197
1198
18
  insn_ptr->u.ea.reg = cfi_parse_reg ();
1199
1200
18
  cfi_parse_separator ();
1201
18
  encoding = cfi_parse_const ();
1202
18
  if ((encoding & 0xff) != encoding
1203
5
      || ((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
5
#endif
1207
5
    )
1208
      /* leb128 can be handled, but does something actually need it?  */
1209
5
      || (encoding & 7) == DW_EH_PE_uleb128
1210
5
      || (encoding & 7) > DW_EH_PE_udata8)
1211
13
    {
1212
13
      as_bad (_("invalid or unsupported encoding in .cfi_lsda"));
1213
13
      encoding = DW_EH_PE_omit;
1214
13
    }
1215
1216
18
  cfi_parse_separator ();
1217
18
  expression_and_evaluate (&insn_ptr->u.ea.exp);
1218
18
  switch (insn_ptr->u.ea.exp.X_op)
1219
18
    {
1220
14
    case O_symbol:
1221
14
      break;
1222
0
    case O_constant:
1223
0
      if ((encoding & 0x70) != DW_EH_PE_pcrel)
1224
0
  break;
1225
      /* Fall through.  */
1226
4
    default:
1227
4
      encoding = DW_EH_PE_omit;
1228
4
      break;
1229
18
    }
1230
1231
18
  insn_ptr->u.ea.encoding = encoding;
1232
18
  if (encoding == DW_EH_PE_omit)
1233
17
    {
1234
17
      as_bad (_("wrong third argument to .cfi_val_encoded_addr"));
1235
17
      ignore_rest_of_line ();
1236
17
      return;
1237
17
    }
1238
1239
1
  demand_empty_rest_of_line ();
1240
1
}
1241
1242
static void
1243
dot_cfi_label (int ignored ATTRIBUTE_UNUSED)
1244
29
{
1245
29
  char *name;
1246
1247
29
  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
29
  name = read_symbol_name ();
1255
29
  if (name == NULL)
1256
0
    return;
1257
1258
  /* If the last address was not at the current PC, advance to current.  */
1259
29
  if (symbol_get_frag (frchain_now->frch_cfi_data->last_address) != frag_now
1260
19
      || (S_GET_VALUE (frchain_now->frch_cfi_data->last_address)
1261
19
    != frag_now_fix ()))
1262
12
    cfi_add_advance_loc (symbol_temp_new_now ());
1263
1264
29
  cfi_add_label (name);
1265
29
  free (name);
1266
1267
29
  demand_empty_rest_of_line ();
1268
29
}
1269
1270
void
1271
dot_cfi_sections (int ignored ATTRIBUTE_UNUSED)
1272
298
{
1273
298
  int sections = 0;
1274
1275
298
  SKIP_WHITESPACE ();
1276
298
  if (is_name_beginner (*input_line_pointer) || *input_line_pointer == '"')
1277
517
    while (1)
1278
517
      {
1279
517
  char * saved_ilp;
1280
517
  char *name, c;
1281
1282
517
  saved_ilp = input_line_pointer;
1283
517
  c = get_symbol_name (& name);
1284
1285
517
  if (startswith (name, ".eh_frame")
1286
27
      && name[9] != '_')
1287
27
    sections |= CFI_EMIT_eh_frame;
1288
490
  else if (startswith (name, ".debug_frame"))
1289
196
    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
294
  else if (startswith (name, ".sframe"))
1302
17
      sections |= CFI_EMIT_sframe;
1303
277
  else
1304
277
    {
1305
277
      *input_line_pointer = c;
1306
277
      input_line_pointer = saved_ilp;
1307
277
      break;
1308
277
    }
1309
1310
240
  restore_line_pointer (c);
1311
240
  SKIP_WHITESPACE ();
1312
240
  if (*input_line_pointer == ',')
1313
0
    {
1314
0
      name = input_line_pointer++;
1315
0
      SKIP_WHITESPACE ();
1316
0
      if (!is_name_beginner (*input_line_pointer)
1317
0
    && *input_line_pointer != '"')
1318
0
        {
1319
0
    input_line_pointer = name;
1320
0
    break;
1321
0
        }
1322
0
    }
1323
240
  else if (is_name_beginner (*input_line_pointer)
1324
223
     || *input_line_pointer == '"')
1325
17
    break;
1326
240
      }
1327
1328
298
  demand_empty_rest_of_line ();
1329
298
  if (cfi_sections_set
1330
62
      && (sections & (CFI_EMIT_eh_frame | CFI_EMIT_eh_frame_compact))
1331
15
      && ((cfi_sections & (CFI_EMIT_eh_frame | CFI_EMIT_eh_frame_compact))
1332
15
    != (sections & (CFI_EMIT_eh_frame | CFI_EMIT_eh_frame_compact))))
1333
14
    as_bad (_("inconsistent uses of .cfi_sections"));
1334
298
  cfi_sections = sections;
1335
298
}
1336
1337
static void
1338
dot_cfi_startproc (int ignored ATTRIBUTE_UNUSED)
1339
116
{
1340
116
  int simple = 0;
1341
1342
116
  if (frchain_now->frch_cfi_data != NULL)
1343
36
    {
1344
36
      as_bad (_("previous CFI entry not closed (missing .cfi_endproc)"));
1345
36
      ignore_rest_of_line ();
1346
36
      return;
1347
36
    }
1348
1349
80
  cfi_new_fde (symbol_temp_new_now (), listing & LISTING_LISTING);
1350
1351
80
  SKIP_WHITESPACE ();
1352
80
  if (is_name_beginner (*input_line_pointer) || *input_line_pointer == '"')
1353
15
    {
1354
15
      char * saved_ilp = input_line_pointer;
1355
15
      char *name, c;
1356
1357
15
      c = get_symbol_name (& name);
1358
1359
15
      if (strcmp (name, "simple") == 0)
1360
2
  {
1361
2
    simple = 1;
1362
2
    restore_line_pointer (c);
1363
2
  }
1364
13
      else
1365
13
  input_line_pointer = saved_ilp;
1366
15
    }
1367
80
  demand_empty_rest_of_line ();
1368
1369
80
  cfi_set_sections ();
1370
1371
80
  frchain_now->frch_cfi_data->cur_cfa_offset = 0;
1372
80
  if (!simple)
1373
78
    tc_cfi_frame_initial_instructions ();
1374
1375
80
  if ((all_cfi_sections & CFI_EMIT_target) != 0)
1376
0
    tc_cfi_startproc ();
1377
80
}
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
64
{
1402
  /* Exclude .debug_frame sections for Compact EH.  */
1403
64
  if (SUPPORT_FRAME_LINKONCE || ((flags & SEC_DEBUGGING) == 0 && compact_eh)
1404
64
      || ((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
64
  else
1432
64
    {
1433
64
      cseg = subseg_new (base, 0);
1434
64
      bfd_set_section_flags (cseg, flags);
1435
64
    }
1436
64
  record_alignment (cseg, align);
1437
64
  return cseg;
1438
64
}
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
1.78k
{
1660
1.78k
  offsetT offset;
1661
1.78k
  unsigned int regno;
1662
1663
1.78k
  switch (insn->insn)
1664
1.78k
    {
1665
57
    case DW_CFA_advance_loc:
1666
57
      {
1667
57
  symbolS *from = insn->u.ll.lab1;
1668
57
  symbolS *to = insn->u.ll.lab2;
1669
1670
57
  if (symbol_get_frag (to) == symbol_get_frag (from))
1671
26
    {
1672
26
      addressT delta = S_GET_VALUE (to) - S_GET_VALUE (from);
1673
26
      addressT scaled = delta / DWARF2_LINE_MIN_INSN_LENGTH;
1674
1675
26
      if (scaled == 0)
1676
0
        ;
1677
26
      else if (scaled <= 0x3F)
1678
22
        out_one (DW_CFA_advance_loc + scaled);
1679
4
      else if (scaled <= 0xFF)
1680
0
        {
1681
0
    out_one (DW_CFA_advance_loc1);
1682
0
    out_one (scaled);
1683
0
        }
1684
4
      else if (scaled <= 0xFFFF)
1685
0
        {
1686
0
    out_one (DW_CFA_advance_loc2);
1687
0
    out_two (scaled);
1688
0
        }
1689
4
      else
1690
4
        {
1691
4
    out_one (DW_CFA_advance_loc4);
1692
4
    out_four (scaled);
1693
4
        }
1694
26
    }
1695
31
  else
1696
31
    {
1697
31
      expressionS exp = {
1698
31
        .X_op = O_subtract,
1699
31
        .X_add_symbol = to,
1700
31
        .X_op_symbol = from,
1701
31
      };
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
31
      frag_grow (5);
1712
31
      *frag_more (1) = DW_CFA_advance_loc4;
1713
1714
31
      frag_var (rs_cfa, 4, 0, DWARF2_LINE_MIN_INSN_LENGTH << 3,
1715
31
          make_expr_symbol (&exp), frag_now_fix () - 1,
1716
31
          (char *) frag_now);
1717
31
    }
1718
57
      }
1719
57
      break;
1720
1721
90
    case DW_CFA_def_cfa:
1722
90
      offset = insn->u.ri.offset;
1723
90
      if (offset < 0)
1724
4
  {
1725
4
    out_one (DW_CFA_def_cfa_sf);
1726
4
    out_uleb128 (insn->u.ri.reg);
1727
4
    out_sleb128 (offset / DWARF2_CIE_DATA_ALIGNMENT);
1728
4
  }
1729
86
      else
1730
86
  {
1731
86
    out_one (DW_CFA_def_cfa);
1732
86
    out_uleb128 (insn->u.ri.reg);
1733
86
    out_uleb128 (offset);
1734
86
  }
1735
90
      break;
1736
1737
3
    case DW_CFA_def_cfa_register:
1738
254
    case DW_CFA_undefined:
1739
254
    case DW_CFA_same_value:
1740
254
      out_one (insn->insn);
1741
254
      out_uleb128 (insn->u.r);
1742
254
      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
54
    case DW_CFA_restore:
1759
54
      regno = insn->u.r;
1760
54
      if (regno <= 0x3F)
1761
54
  {
1762
54
    out_one (DW_CFA_restore + regno);
1763
54
  }
1764
0
      else
1765
0
  {
1766
0
    out_one (DW_CFA_restore_extended);
1767
0
    out_uleb128 (regno);
1768
0
  }
1769
54
      break;
1770
1771
68
    case DW_CFA_offset:
1772
68
      regno = insn->u.ri.reg;
1773
68
      offset = insn->u.ri.offset / DWARF2_CIE_DATA_ALIGNMENT;
1774
68
      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
64
      else if (regno <= 0x3F)
1781
61
  {
1782
61
    out_one (DW_CFA_offset + regno);
1783
61
    out_uleb128 (offset);
1784
61
  }
1785
3
      else
1786
3
  {
1787
3
    out_one (DW_CFA_offset_extended);
1788
3
    out_uleb128 (regno);
1789
3
    out_uleb128 (offset);
1790
3
  }
1791
68
      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
4
    case DW_CFA_GNU_window_save:
1822
4
      out_one (DW_CFA_GNU_window_save);
1823
4
      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
1.21k
    case CFI_escape:
1830
1.21k
      {
1831
1.21k
  struct cfi_escape_data *e;
1832
2.55k
  for (e = insn->u.esc; e ; e = e->next)
1833
1.33k
    {
1834
1.33k
      if (e->type == CFI_ESC_sleb128 || e->type == CFI_ESC_uleb128)
1835
0
        emit_leb128_expr (&e->exp, e->type == CFI_ESC_sleb128);
1836
1.33k
      else
1837
1.33k
        emit_expr_with_reloc (&e->exp, e->type, e->reloc);
1838
1.33k
    }
1839
1.21k
  break;
1840
0
      }
1841
1842
18
    case CFI_val_encoded_addr:
1843
18
      {
1844
18
  unsigned encoding = insn->u.ea.encoding;
1845
18
  offsetT enc_size;
1846
1847
18
  if (encoding == DW_EH_PE_omit)
1848
17
    break;
1849
1
  out_one (DW_CFA_val_expression);
1850
1
  out_uleb128 (insn->u.ea.reg);
1851
1852
1
  switch (encoding & 0x7)
1853
1
    {
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
1
    case DW_EH_PE_udata8:
1864
1
      enc_size = 8;
1865
1
      break;
1866
0
    default:
1867
0
      abort ();
1868
1
    }
1869
1870
  /* If the user has requested absolute encoding,
1871
     then use the smaller DW_OP_addr encoding.  */
1872
1
  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
1
  else
1878
1
    {
1879
1
      out_uleb128 (1 + 1 + enc_size);
1880
1
      out_one (DW_OP_GNU_encoded_addr);
1881
1
      out_one (encoding);
1882
1883
1
      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
1
    }
1896
1
  emit_expr (&insn->u.ea.exp, enc_size);
1897
1
      }
1898
0
      break;
1899
1900
27
    case CFI_label:
1901
27
      colon (insn->u.sym_name);
1902
27
      break;
1903
1904
0
    default:
1905
0
      abort ();
1906
1.78k
    }
1907
1.78k
}
1908
1909
static void
1910
output_cie (struct cie_entry *cie, bool eh_frame, int align)
1911
53
{
1912
53
  symbolS *after_size_address, *end_address;
1913
53
  expressionS exp;
1914
53
  struct cfi_insn_data *i;
1915
53
  offsetT augmentation_size;
1916
53
  int enc;
1917
53
  enum dwarf2_format fmt = DWARF2_FORMAT (now_seg);
1918
1919
53
  cie->start_address = symbol_temp_new_now ();
1920
53
  after_size_address = symbol_temp_make ();
1921
53
  end_address = symbol_temp_make ();
1922
1923
53
  exp.X_op = O_subtract;
1924
53
  exp.X_add_symbol = end_address;
1925
53
  exp.X_op_symbol = after_size_address;
1926
53
  exp.X_add_number = 0;
1927
1928
53
  if (eh_frame || fmt == dwarf2_format_32bit)
1929
53
    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
53
  symbol_set_value_now (after_size_address);
1937
53
  if (eh_frame)
1938
51
    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
53
  out_one (flag_dwarf_cie_version);   /* Version.  */
1946
53
  if (eh_frame)
1947
51
    {
1948
51
      out_one ('z');        /* Augmentation.  */
1949
51
      if (cie->per_encoding != DW_EH_PE_omit)
1950
0
  out_one ('P');
1951
51
      if (cie->lsda_encoding != DW_EH_PE_omit)
1952
3
  out_one ('L');
1953
51
      out_one ('R');
1954
#ifdef tc_output_cie_extra
1955
      tc_output_cie_extra (cie);
1956
#endif
1957
51
    }
1958
53
  if (cie->signal_frame)
1959
0
    out_one ('S');
1960
53
  out_one (0);
1961
53
  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
53
  out_uleb128 (DWARF2_LINE_MIN_INSN_LENGTH);  /* Code alignment.  */
1970
53
  out_sleb128 (DWARF2_CIE_DATA_ALIGNMENT);  /* Data alignment.  */
1971
53
  if (flag_dwarf_cie_version == 1)   /* Return column.  */
1972
53
    {
1973
53
      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
53
      out_one (cie->return_column);
1977
53
    }
1978
0
  else
1979
0
    out_uleb128 (cie->return_column);
1980
53
  if (eh_frame)
1981
51
    {
1982
51
      augmentation_size = 1 + (cie->lsda_encoding != DW_EH_PE_omit);
1983
51
      if (cie->per_encoding != DW_EH_PE_omit)
1984
0
  augmentation_size += 1 + encoding_size (cie->per_encoding);
1985
51
      out_uleb128 (augmentation_size);    /* Augmentation size.  */
1986
1987
51
      emit_expr_encoded (&cie->personality, cie->per_encoding, true);
1988
1989
51
      if (cie->lsda_encoding != DW_EH_PE_omit)
1990
3
  out_one (cie->lsda_encoding);
1991
51
    }
1992
1993
53
  switch (DWARF2_FDE_RELOC_SIZE)
1994
53
    {
1995
0
    case 2:
1996
0
      enc = DW_EH_PE_sdata2;
1997
0
      break;
1998
53
    case 4:
1999
53
      enc = DW_EH_PE_sdata4;
2000
53
      break;
2001
0
    case 8:
2002
0
      enc = DW_EH_PE_sdata8;
2003
0
      break;
2004
0
    default:
2005
0
      abort ();
2006
53
    }
2007
53
#if CFI_DIFF_EXPR_OK || defined tc_cfi_emit_pcrel_expr
2008
53
  enc |= DW_EH_PE_pcrel;
2009
53
#endif
2010
#ifdef DWARF2_FDE_RELOC_ENCODING
2011
  /* Allow target to override encoding.  */
2012
  enc = DWARF2_FDE_RELOC_ENCODING (enc);
2013
#endif
2014
53
  cie->fde_encoding = enc;
2015
53
  if (eh_frame)
2016
51
    out_one (enc);
2017
2018
53
  if (cie->first)
2019
53
    {
2020
458
      for (i = cie->first; i != cie->last; i = i->next)
2021
405
  {
2022
405
    if (CUR_SEG (i) != CUR_SEG (cie))
2023
0
      continue;
2024
405
    output_cfi_insn (i);
2025
405
  }
2026
53
    }
2027
2028
53
  frag_align (align, DW_CFA_nop, 0);
2029
53
  symbol_set_value_now (end_address);
2030
53
}
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
58
{
2037
58
  symbolS *after_size_address, *end_address;
2038
58
  expressionS exp;
2039
58
  offsetT augmentation_size;
2040
58
  enum dwarf2_format fmt = DWARF2_FORMAT (now_seg);
2041
58
  unsigned int offset_size;
2042
58
  unsigned int addr_size;
2043
2044
58
  after_size_address = symbol_temp_make ();
2045
58
  end_address = symbol_temp_make ();
2046
2047
58
  exp.X_op = O_subtract;
2048
58
  exp.X_add_symbol = end_address;
2049
58
  exp.X_op_symbol = after_size_address;
2050
58
  exp.X_add_number = 0;
2051
58
  if (eh_frame || fmt == dwarf2_format_32bit)
2052
58
    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
58
  emit_expr (&exp, offset_size);    /* Length.  */
2060
58
  symbol_set_value_now (after_size_address);
2061
2062
58
  if (eh_frame)
2063
56
    {
2064
56
      exp.X_op = O_subtract;
2065
56
      exp.X_add_symbol = after_size_address;
2066
56
      exp.X_op_symbol = cie->start_address;
2067
56
      exp.X_add_number = 0;
2068
56
      emit_expr (&exp, offset_size);    /* CIE offset.  */
2069
56
    }
2070
2
  else
2071
2
    {
2072
2
      TC_DWARF2_EMIT_OFFSET (cie->start_address, offset_size);
2073
2
    }
2074
2075
58
  exp.X_op = O_symbol;
2076
58
  if (eh_frame)
2077
56
    {
2078
56
      bfd_reloc_code_real_type code
2079
56
  = tc_cfi_reloc_for_encoding (cie->fde_encoding);
2080
56
      addr_size = DWARF2_FDE_RELOC_SIZE;
2081
56
      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
56
      else
2091
56
  {
2092
56
    exp.X_op = O_subtract;
2093
56
    exp.X_add_number = 0;
2094
56
#if CFI_DIFF_EXPR_OK
2095
56
    exp.X_add_symbol = fde->start_address;
2096
56
    exp.X_op_symbol = symbol_temp_new_now ();
2097
56
    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
56
  }
2109
56
    }
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
58
  exp.X_op = O_subtract;
2119
58
  exp.X_add_symbol = fde->end_address;
2120
58
  exp.X_op_symbol = fde->start_address;   /* Code length.  */
2121
58
  exp.X_add_number = 0;
2122
58
  emit_expr (&exp, addr_size);
2123
2124
58
  augmentation_size = encoding_size (fde->lsda_encoding);
2125
58
  if (eh_frame)
2126
56
    out_uleb128 (augmentation_size);   /* Augmentation size.  */
2127
2128
58
  emit_expr_encoded (&fde->lsda, cie->lsda_encoding, false);
2129
2130
1.44k
  for (; first; first = first->next)
2131
1.38k
    if (CUR_SEG (first) == CUR_SEG (fde))
2132
1.38k
      {
2133
1.38k
#ifndef NO_LISTING
2134
1.38k
  if (eh_frame)
2135
1.37k
    listing_override_tail (first->listing_ctxt);
2136
1.38k
#endif
2137
1.38k
  output_cfi_insn (first);
2138
1.38k
      }
2139
2140
58
#ifndef NO_LISTING
2141
  /* Associate any padding with .cfi_endproc.  */
2142
58
  if (eh_frame)
2143
56
    listing_override_tail (fde->listing_end);
2144
58
#endif
2145
2146
58
  frag_align (align, DW_CFA_nop, 0);
2147
58
  symbol_set_value_now (end_address);
2148
58
}
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
448
{
2156
448
  if (j && i->insn != j->insn)
2157
1
    return false;
2158
447
  switch (i->insn)
2159
447
    {
2160
72
    case DW_CFA_offset:
2161
144
    case DW_CFA_def_cfa:
2162
144
    case DW_CFA_val_offset:
2163
144
      if (j)
2164
15
  {
2165
15
    if (i->u.ri.reg != j->u.ri.reg)
2166
1
      return false;
2167
14
    if (i->u.ri.offset != j->u.ri.offset)
2168
0
      return false;
2169
14
  }
2170
143
      break;
2171
2172
143
    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
4
    case DW_CFA_def_cfa_register:
2183
36
    case DW_CFA_restore:
2184
278
    case DW_CFA_undefined:
2185
278
    case DW_CFA_same_value:
2186
278
      if (j)
2187
2
  {
2188
2
    if (i->u.r != j->u.r)
2189
0
      return false;
2190
2
  }
2191
278
      break;
2192
2193
278
    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
25
    default:
2202
25
      return false;
2203
447
    }
2204
421
  return true;
2205
447
}
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
58
{
2211
58
  struct cfi_insn_data *i, *j;
2212
58
  struct cie_entry *cie;
2213
2214
61
  for (cie = cie_root; cie; cie = cie->next)
2215
8
    {
2216
8
      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
8
      if (cie->return_column != fde->return_column
2223
8
    || cie->signal_frame != fde->signal_frame
2224
8
    || cie->per_encoding != fde->per_encoding
2225
8
    || cie->lsda_encoding != fde->lsda_encoding)
2226
1
  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
18
  {
2252
18
    if (!initial_cie_insn (i, j))
2253
2
      break;
2254
18
  }
2255
2256
7
      if (i == cie->last)
2257
5
  {
2258
5
    *pfirst = j;
2259
5
    return cie;
2260
5
  }
2261
7
    }
2262
2263
53
  cie = XNEW (struct cie_entry);
2264
53
  cie->next = cie_root;
2265
53
  cie_root = cie;
2266
53
  SET_CUR_SEG (cie, CUR_SEG (fde));
2267
53
  cie->return_column = fde->return_column;
2268
53
  cie->signal_frame = fde->signal_frame;
2269
53
  cie->per_encoding = fde->per_encoding;
2270
53
  cie->lsda_encoding = fde->lsda_encoding;
2271
53
  cie->personality = fde->personality;
2272
53
  cie->first = fde->data;
2273
#ifdef tc_cie_entry_init_extra
2274
  tc_cie_entry_init_extra (cie, fde);
2275
#endif
2276
2277
458
  for (i = cie->first; i ; i = i->next)
2278
430
    if (!initial_cie_insn (i, NULL))
2279
25
      break;
2280
2281
53
  cie->last = i;
2282
53
  *pfirst = i;
2283
2284
53
  output_cie (cie, eh_frame, align);
2285
2286
53
  return cie;
2287
58
}
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
478
{
2387
478
  struct cie_entry *cie, *cie_next;
2388
478
  segT cfi_seg, ccseg;
2389
478
  struct fde_entry *fde;
2390
478
  struct cfi_insn_data *first;
2391
478
#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
478
  struct list_info_struct *saved_listing_tail = NULL;
2396
478
#endif
2397
478
  int save_flag_traditional_format, seek_next_seg;
2398
2399
478
  if (all_fde_data == 0)
2400
411
    return;
2401
2402
67
  if ((all_cfi_sections & CFI_EMIT_eh_frame) != 0
2403
19
      || (all_cfi_sections & CFI_EMIT_eh_frame_compact) != 0)
2404
48
    {
2405
      /* Make sure check_eh_frame doesn't do anything with our output.  */
2406
48
      save_flag_traditional_format = flag_traditional_format;
2407
48
      flag_traditional_format = 1;
2408
2409
48
      if (!EH_FRAME_LINKONCE)
2410
48
  {
2411
    /* Open .eh_frame section.  */
2412
48
    cfi_seg = get_cfi_seg (NULL, ".eh_frame",
2413
48
         (SEC_ALLOC | SEC_LOAD | SEC_DATA
2414
48
          | DWARF2_EH_FRAME_READ_ONLY),
2415
48
         EH_FRAME_ALIGNMENT);
2416
#ifdef md_fix_up_eh_frame
2417
    md_fix_up_eh_frame (cfi_seg);
2418
#else
2419
48
    (void) cfi_seg;
2420
48
#endif
2421
48
  }
2422
2423
48
      do
2424
48
  {
2425
48
    ccseg = NULL;
2426
48
    seek_next_seg = 0;
2427
2428
104
    for (fde = all_fde_data; fde ; fde = fde->next)
2429
56
      {
2430
56
        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
56
        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
56
        if (fde->end_address == NULL)
2473
56
    {
2474
56
      as_bad (_("open CFI at the end of file; "
2475
56
          "missing .cfi_endproc directive"));
2476
56
      fde->end_address = fde->start_address;
2477
56
    }
2478
2479
56
#ifndef NO_LISTING
2480
56
        {
2481
56
    struct list_info_struct *listing_prev
2482
56
      = listing_override_tail (fde->listing_ctxt);
2483
2484
56
    if (!saved_listing_tail)
2485
56
      saved_listing_tail = listing_prev;
2486
56
        }
2487
56
#endif
2488
2489
56
        cie = select_cie_for_fde (fde, true, &first, 2);
2490
56
        fde->eh_loc = symbol_temp_new_now ();
2491
56
        output_fde (fde, cie, true, first,
2492
56
        fde->next == NULL ? EH_FRAME_ALIGNMENT : 2);
2493
56
      }
2494
2495
99
    for (cie = cie_root; cie; cie = cie_next)
2496
51
      {
2497
51
        cie_next = cie->next;
2498
51
        free (cie);
2499
51
      }
2500
48
    cie_root = NULL;
2501
48
  }
2502
48
      while (EH_FRAME_LINKONCE && seek_next_seg == 2);
2503
2504
48
      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
48
      flag_traditional_format = save_flag_traditional_format;
2596
48
    }
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
67
  if (flag_gen_sframe == GEN_SFRAME_ENABLED
2604
67
      || flag_gen_sframe == GEN_SFRAME_CONFIG_ENABLED
2605
67
      || ((all_cfi_sections & CFI_EMIT_sframe) != 0
2606
14
    && flag_gen_sframe != GEN_SFRAME_DISABLED))
2607
14
    {
2608
14
#ifdef support_sframe_p
2609
14
      if (support_sframe_p () && !SUPPORT_FRAME_LINKONCE)
2610
14
  {
2611
14
    segT sframe_seg;
2612
14
    int alignment = ffs (DWARF2_ADDR_SIZE (stdoutput)) - 1;
2613
2614
14
    sframe_seg = get_cfi_seg (NULL, ".sframe",
2615
14
            (SEC_ALLOC | SEC_LOAD | SEC_DATA
2616
14
             | DWARF2_EH_FRAME_READ_ONLY),
2617
14
            alignment);
2618
14
    elf_section_type (sframe_seg) = SHT_GNU_SFRAME;
2619
14
    output_sframe (sframe_seg);
2620
14
  }
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
14
    }
2627
2628
67
  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
6
    for (fde = all_fde_data; fde ; fde = fde->next)
2643
4
      {
2644
4
        if ((fde->sections & CFI_EMIT_debug_frame) == 0)
2645
2
    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
67
  all_fde_data = NULL;
2695
67
  last_fde_data = &all_fde_data;
2696
67
  cfi_sections_set = false;
2697
67
  cfi_sections = CFI_EMIT_eh_frame;
2698
67
  all_cfi_sections = 0;
2699
67
  last_fde = NULL;
2700
67
  if (dwcfi_hash)
2701
0
    {
2702
0
      htab_delete (dwcfi_hash);
2703
0
      dwcfi_hash = NULL;
2704
0
    }
2705
2706
67
#ifndef NO_LISTING
2707
67
  if (saved_listing_tail)
2708
0
    listing_tail = saved_listing_tail;
2709
67
#endif
2710
67
}
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 */