Coverage Report

Created: 2025-06-24 06:45

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