Rev 5222 | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 5222 | Rev 6324 | ||
---|---|---|---|
Line 1... | Line 1... | ||
1 | /* dwarf2dbg.c - DWARF2 debug support |
1 | /* dwarf2dbg.c - DWARF2 debug support |
2 | Copyright 1999-2013 Free Software Foundation, Inc. |
2 | Copyright (C) 1999-2015 Free Software Foundation, Inc. |
3 | Contributed by David Mosberger-Tang |
3 | Contributed by David Mosberger-Tang |
Line 4... | Line 4... | ||
4 | 4 | ||
Line 5... | Line 5... | ||
5 | This file is part of GAS, the GNU Assembler. |
5 | This file is part of GAS, the GNU Assembler. |
Line 156... | Line 156... | ||
156 | #define SPECIAL_ADDR(op) (((op) - DWARF2_LINE_OPCODE_BASE)/DWARF2_LINE_RANGE) |
156 | #define SPECIAL_ADDR(op) (((op) - DWARF2_LINE_OPCODE_BASE)/DWARF2_LINE_RANGE) |
Line 157... | Line 157... | ||
157 | 157 | ||
158 | /* The maximum address skip amount that can be encoded with a special op. */ |
158 | /* The maximum address skip amount that can be encoded with a special op. */ |
Line -... | Line 159... | ||
- | 159 | #define MAX_SPECIAL_ADDR_DELTA SPECIAL_ADDR(255) |
|
- | 160 | ||
- | 161 | #ifndef TC_PARSE_CONS_RETURN_NONE |
|
- | 162 | #define TC_PARSE_CONS_RETURN_NONE BFD_RELOC_NONE |
|
159 | #define MAX_SPECIAL_ADDR_DELTA SPECIAL_ADDR(255) |
163 | #endif |
160 | 164 | ||
161 | struct line_entry { |
165 | struct line_entry { |
162 | struct line_entry *next; |
166 | struct line_entry *next; |
163 | symbolS *label; |
167 | symbolS *label; |
Line 180... | Line 184... | ||
180 | symbolS *text_end; |
184 | symbolS *text_end; |
181 | }; |
185 | }; |
Line 182... | Line 186... | ||
182 | 186 | ||
183 | /* Collects data for all line table entries during assembly. */ |
187 | /* Collects data for all line table entries during assembly. */ |
184 | static struct line_seg *all_segs; |
- | |
185 | /* Hash used to quickly lookup a segment by name, avoiding the need to search |
- | |
186 | through the all_segs list. */ |
- | |
187 | static struct hash_control *all_segs_hash; |
188 | static struct line_seg *all_segs; |
Line 188... | Line 189... | ||
188 | static struct line_seg **last_seg_ptr; |
189 | static struct line_seg **last_seg_ptr; |
189 | 190 | ||
190 | struct file_entry { |
191 | struct file_entry { |
Line 242... | Line 243... | ||
242 | /* Find or create (if CREATE_P) an entry for SEG+SUBSEG in ALL_SEGS. */ |
243 | /* Find or create (if CREATE_P) an entry for SEG+SUBSEG in ALL_SEGS. */ |
Line 243... | Line 244... | ||
243 | 244 | ||
244 | static struct line_subseg * |
245 | static struct line_subseg * |
245 | get_line_subseg (segT seg, subsegT subseg, bfd_boolean create_p) |
246 | get_line_subseg (segT seg, subsegT subseg, bfd_boolean create_p) |
246 | { |
- | |
247 | static segT last_seg; |
- | |
248 | static subsegT last_subseg; |
247 | { |
249 | static struct line_subseg *last_line_subseg; |
- | |
250 | - | ||
251 | struct line_seg *s; |
248 | struct line_seg *s = seg_info (seg)->dwarf2_line_seg; |
Line 252... | Line -... | ||
252 | struct line_subseg **pss, *lss; |
- | |
253 | - | ||
254 | if (seg == last_seg && subseg == last_subseg) |
- | |
255 | return last_line_subseg; |
- | |
256 | 249 | struct line_subseg **pss, *lss; |
|
257 | s = (struct line_seg *) hash_find (all_segs_hash, seg->name); |
250 | |
258 | if (s == NULL) |
251 | if (s == NULL) |
259 | { |
252 | { |
Line 264... | Line 257... | ||
264 | s->next = NULL; |
257 | s->next = NULL; |
265 | s->seg = seg; |
258 | s->seg = seg; |
266 | s->head = NULL; |
259 | s->head = NULL; |
267 | *last_seg_ptr = s; |
260 | *last_seg_ptr = s; |
268 | last_seg_ptr = &s->next; |
261 | last_seg_ptr = &s->next; |
269 | hash_insert (all_segs_hash, seg->name, s); |
262 | seg_info (seg)->dwarf2_line_seg = s; |
270 | } |
263 | } |
271 | gas_assert (seg == s->seg); |
264 | gas_assert (seg == s->seg); |
Line 272... | Line 265... | ||
272 | 265 | ||
273 | for (pss = &s->head; (lss = *pss) != NULL ; pss = &lss->next) |
266 | for (pss = &s->head; (lss = *pss) != NULL ; pss = &lss->next) |
Line 285... | Line 278... | ||
285 | lss->ptail = &lss->head; |
278 | lss->ptail = &lss->head; |
286 | lss->pmove_tail = &lss->head; |
279 | lss->pmove_tail = &lss->head; |
287 | *pss = lss; |
280 | *pss = lss; |
Line 288... | Line 281... | ||
288 | 281 | ||
289 | found_subseg: |
- | |
290 | last_seg = seg; |
- | |
291 | last_subseg = subseg; |
- | |
292 | last_line_subseg = lss; |
- | |
293 | 282 | found_subseg: |
|
294 | return lss; |
283 | return lss; |
Line 295... | Line 284... | ||
295 | } |
284 | } |
Line 679... | Line 668... | ||
679 | while (ISALPHA (*input_line_pointer)) |
668 | while (ISALPHA (*input_line_pointer)) |
680 | { |
669 | { |
681 | char *p, c; |
670 | char *p, c; |
682 | offsetT value; |
671 | offsetT value; |
Line 683... | Line -... | ||
683 | - | ||
684 | p = input_line_pointer; |
672 | |
Line 685... | Line 673... | ||
685 | c = get_symbol_end (); |
673 | c = get_symbol_name (& p); |
686 | 674 | ||
687 | if (strcmp (p, "basic_block") == 0) |
675 | if (strcmp (p, "basic_block") == 0) |
688 | { |
676 | { |
Line 699... | Line 687... | ||
699 | current.flags |= DWARF2_FLAG_EPILOGUE_BEGIN; |
687 | current.flags |= DWARF2_FLAG_EPILOGUE_BEGIN; |
700 | *input_line_pointer = c; |
688 | *input_line_pointer = c; |
701 | } |
689 | } |
702 | else if (strcmp (p, "is_stmt") == 0) |
690 | else if (strcmp (p, "is_stmt") == 0) |
703 | { |
691 | { |
704 | *input_line_pointer = c; |
692 | (void) restore_line_pointer (c); |
705 | value = get_absolute_expression (); |
693 | value = get_absolute_expression (); |
706 | if (value == 0) |
694 | if (value == 0) |
707 | current.flags &= ~DWARF2_FLAG_IS_STMT; |
695 | current.flags &= ~DWARF2_FLAG_IS_STMT; |
708 | else if (value == 1) |
696 | else if (value == 1) |
709 | current.flags |= DWARF2_FLAG_IS_STMT; |
697 | current.flags |= DWARF2_FLAG_IS_STMT; |
Line 713... | Line 701... | ||
713 | return; |
701 | return; |
714 | } |
702 | } |
715 | } |
703 | } |
716 | else if (strcmp (p, "isa") == 0) |
704 | else if (strcmp (p, "isa") == 0) |
717 | { |
705 | { |
718 | *input_line_pointer = c; |
706 | (void) restore_line_pointer (c); |
719 | value = get_absolute_expression (); |
707 | value = get_absolute_expression (); |
720 | if (value >= 0) |
708 | if (value >= 0) |
721 | current.isa = value; |
709 | current.isa = value; |
722 | else |
710 | else |
723 | { |
711 | { |
Line 725... | Line 713... | ||
725 | return; |
713 | return; |
726 | } |
714 | } |
727 | } |
715 | } |
728 | else if (strcmp (p, "discriminator") == 0) |
716 | else if (strcmp (p, "discriminator") == 0) |
729 | { |
717 | { |
730 | *input_line_pointer = c; |
718 | (void) restore_line_pointer (c); |
731 | value = get_absolute_expression (); |
719 | value = get_absolute_expression (); |
732 | if (value >= 0) |
720 | if (value >= 0) |
733 | current.discriminator = value; |
721 | current.discriminator = value; |
734 | else |
722 | else |
735 | { |
723 | { |
Line 738... | Line 726... | ||
738 | } |
726 | } |
739 | } |
727 | } |
740 | else |
728 | else |
741 | { |
729 | { |
742 | as_bad (_("unknown .loc sub-directive `%s'"), p); |
730 | as_bad (_("unknown .loc sub-directive `%s'"), p); |
743 | *input_line_pointer = c; |
731 | (void) restore_line_pointer (c); |
744 | return; |
732 | return; |
745 | } |
733 | } |
Line 746... | Line 734... | ||
746 | 734 | ||
747 | SKIP_WHITESPACE (); |
735 | SKIP_WHITESPACE_AFTER_NAME (); |
Line 748... | Line 736... | ||
748 | } |
736 | } |
749 | 737 | ||
750 | demand_empty_rest_of_line (); |
738 | demand_empty_rest_of_line (); |
Line 1142... | Line 1130... | ||
1142 | p += output_leb128 (p, sizeof_address + 1, 0); |
1130 | p += output_leb128 (p, sizeof_address + 1, 0); |
1143 | *p++ = DW_LNE_set_address; |
1131 | *p++ = DW_LNE_set_address; |
1144 | exp.X_op = O_symbol; |
1132 | exp.X_op = O_symbol; |
1145 | exp.X_add_symbol = to_sym; |
1133 | exp.X_add_symbol = to_sym; |
1146 | exp.X_add_number = 0; |
1134 | exp.X_add_number = 0; |
1147 | emit_expr_fix (&exp, sizeof_address, frag, p); |
1135 | emit_expr_fix (&exp, sizeof_address, frag, p, TC_PARSE_CONS_RETURN_NONE); |
1148 | p += sizeof_address; |
1136 | p += sizeof_address; |
1149 | } |
1137 | } |
1150 | else |
1138 | else |
1151 | { |
1139 | { |
1152 | *p++ = DW_LNS_fixed_advance_pc; |
1140 | *p++ = DW_LNS_fixed_advance_pc; |
1153 | emit_expr_fix (pexp, 2, frag, p); |
1141 | emit_expr_fix (pexp, 2, frag, p, TC_PARSE_CONS_RETURN_NONE); |
1154 | p += 2; |
1142 | p += 2; |
1155 | } |
1143 | } |
Line 1156... | Line 1144... | ||
1156 | 1144 | ||
1157 | if (line_delta == INT_MAX) |
1145 | if (line_delta == INT_MAX) |
Line 1467... | Line 1455... | ||
1467 | out_byte (0); |
1455 | out_byte (0); |
1468 | } |
1456 | } |
Line 1469... | Line 1457... | ||
1469 | 1457 | ||
1470 | /* Switch to SEC and output a header length field. Return the size of |
1458 | /* Switch to SEC and output a header length field. Return the size of |
- | 1459 | offsets used in SEC. The caller must set EXPR->X_add_symbol value |
|
1471 | offsets used in SEC. The caller must set EXPR->X_add_symbol value |
1460 | to the end of the section. EXPR->X_add_number will be set to the |
Line 1472... | Line 1461... | ||
1472 | to the end of the section. */ |
1461 | negative size of the header. */ |
1473 | 1462 | ||
1474 | static int |
1463 | static int |
1475 | out_header (asection *sec, expressionS *exp) |
1464 | out_header (asection *sec, expressionS *exp) |
1476 | { |
1465 | { |
Line 1477... | Line 1466... | ||
1477 | symbolS *start_sym; |
1466 | symbolS *start_sym; |
- | 1467 | symbolS *end_sym; |
|
- | 1468 | ||
- | 1469 | subseg_set (sec, 0); |
|
- | 1470 | ||
- | 1471 | if (flag_dwarf_sections) |
|
- | 1472 | { |
|
- | 1473 | /* If we are going to put the start and end symbols in different |
|
- | 1474 | sections, then we need real symbols, not just fake, local ones. */ |
|
- | 1475 | frag_now_fix (); |
|
- | 1476 | start_sym = symbol_make (".Ldebug_line_start"); |
|
- | 1477 | end_sym = symbol_make (".Ldebug_line_end"); |
|
- | 1478 | symbol_set_value_now (start_sym); |
|
1478 | symbolS *end_sym; |
1479 | } |
1479 | 1480 | else |
|
- | 1481 | { |
|
Line 1480... | Line 1482... | ||
1480 | subseg_set (sec, 0); |
1482 | start_sym = symbol_temp_new_now (); |
1481 | start_sym = symbol_temp_new_now (); |
1483 | end_sym = symbol_temp_make (); |
1482 | end_sym = symbol_temp_make (); |
1484 | } |
1483 | 1485 | ||
Line 1513... | Line 1515... | ||
1513 | 1515 | ||
1514 | static void |
1516 | static void |
1515 | out_debug_line (segT line_seg) |
1517 | out_debug_line (segT line_seg) |
1516 | { |
1518 | { |
1517 | expressionS exp; |
1519 | expressionS exp; |
1518 | symbolS *prologue_end; |
1520 | symbolS *prologue_start, *prologue_end; |
1519 | symbolS *line_end; |
1521 | symbolS *line_end; |
1520 | struct line_seg *s; |
1522 | struct line_seg *s; |
Line 1521... | Line 1523... | ||
1521 | int sizeof_offset; |
1523 | int sizeof_offset; |
Line 1525... | Line 1527... | ||
1525 | 1527 | ||
1526 | /* Version. */ |
1528 | /* Version. */ |
Line 1527... | Line 1529... | ||
1527 | out_two (DWARF2_LINE_VERSION); |
1529 | out_two (DWARF2_LINE_VERSION); |
- | 1530 | ||
1528 | 1531 | /* Length of the prologue following this length. */ |
|
- | 1532 | prologue_start = symbol_temp_make (); |
|
1529 | /* Length of the prologue following this length. */ |
1533 | prologue_end = symbol_temp_make (); |
- | 1534 | exp.X_op = O_subtract; |
|
1530 | prologue_end = symbol_temp_make (); |
1535 | exp.X_add_symbol = prologue_end; |
1531 | exp.X_add_symbol = prologue_end; |
1536 | exp.X_op_symbol = prologue_start; |
- | 1537 | exp.X_add_number = 0; |
|
Line 1532... | Line 1538... | ||
1532 | exp.X_add_number = - (4 + 2 + 4); |
1538 | emit_expr (&exp, sizeof_offset); |
1533 | emit_expr (&exp, sizeof_offset); |
1539 | symbol_set_value_now (prologue_start); |
1534 | 1540 | ||
1535 | /* Parameters of the state machine. */ |
1541 | /* Parameters of the state machine. */ |
Line 1630... | Line 1636... | ||
1630 | 1636 | ||
1631 | static void |
1637 | static void |
1632 | out_debug_aranges (segT aranges_seg, segT info_seg) |
1638 | out_debug_aranges (segT aranges_seg, segT info_seg) |
1633 | { |
1639 | { |
- | 1640 | unsigned int addr_size = sizeof_address; |
|
1634 | unsigned int addr_size = sizeof_address; |
1641 | offsetT size; |
1635 | struct line_seg *s; |
1642 | struct line_seg *s; |
1636 | expressionS exp; |
1643 | expressionS exp; |
1637 | symbolS *aranges_end; |
1644 | symbolS *aranges_end; |
1638 | char *p; |
1645 | char *p; |
Line 1639... | Line 1646... | ||
1639 | int sizeof_offset; |
1646 | int sizeof_offset; |
1640 | 1647 | ||
- | 1648 | sizeof_offset = out_header (aranges_seg, &exp); |
|
Line 1641... | Line 1649... | ||
1641 | sizeof_offset = out_header (aranges_seg, &exp); |
1649 | aranges_end = exp.X_add_symbol; |
1642 | aranges_end = exp.X_add_symbol; |
1650 | size = -exp.X_add_number; |
- | 1651 | ||
Line 1643... | Line 1652... | ||
1643 | 1652 | /* Version. */ |
|
1644 | /* Version. */ |
1653 | out_two (DWARF2_ARANGES_VERSION); |
- | 1654 | size += 2; |
|
Line 1645... | Line 1655... | ||
1645 | out_two (DWARF2_ARANGES_VERSION); |
1655 | |
1646 | 1656 | /* Offset to .debug_info. */ |
|
- | 1657 | TC_DWARF2_EMIT_OFFSET (section_symbol (info_seg), sizeof_offset); |
|
Line 1647... | Line 1658... | ||
1647 | /* Offset to .debug_info. */ |
1658 | size += sizeof_offset; |
1648 | TC_DWARF2_EMIT_OFFSET (section_symbol (info_seg), sizeof_offset); |
1659 | |
- | 1660 | /* Size of an address (offset portion). */ |
|
Line 1649... | Line 1661... | ||
1649 | 1661 | out_byte (addr_size); |
|
1650 | /* Size of an address (offset portion). */ |
1662 | size++; |
- | 1663 | ||
Line 1651... | Line 1664... | ||
1651 | out_byte (addr_size); |
1664 | /* Size of a segment descriptor. */ |
1652 | 1665 | out_byte (0); |
|
1653 | /* Size of a segment descriptor. */ |
1666 | size++; |
1654 | out_byte (0); |
1667 | |
Line 1837... | Line 1850... | ||
1837 | } |
1850 | } |
Line 1838... | Line 1851... | ||
1838 | 1851 | ||
1839 | void |
1852 | void |
1840 | dwarf2_init (void) |
1853 | dwarf2_init (void) |
1841 | { |
- | |
1842 | all_segs_hash = hash_new (); |
1854 | { |
1843 | last_seg_ptr = &all_segs; |
1855 | last_seg_ptr = &all_segs; |
Line 1844... | Line 1856... | ||
1844 | } |
1856 | } |