OpenCores
URL https://opencores.org/ocsvn/scarts/scarts/trunk

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-binutils/] [binutils-2.19.1/] [gas/] [dw2gencfi.c] - Blame information for rev 6

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.