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