* RFC: add DWARF-4 features
@ 2010-04-13 20:28 Tom Tromey
2010-04-19 14:45 ` Joel Brobecker
2010-04-19 18:08 ` Jan Kratochvil
0 siblings, 2 replies; 4+ messages in thread
From: Tom Tromey @ 2010-04-13 20:28 UTC (permalink / raw)
To: gdb-patches
Following Jakub's patches for GCC and binutils, this adds support for
new DWARF-4 features to gdb.
I would appreciate some extra eyes on this.
The new features are:
* GCC will start emitting "4" as the DWARF version number
* CIE version 4 has two extra header fields
* New forms DW_FORM_flag_present, DW_FORM_sec_offset, DW_FORM_exprloc
* Line table version 4 has maximum_ops_per_instruction field in the
header, plus a new state machine variable
Built and regtested on x86-64. I also ran the test suite with -gdwarf-4
using svn gcc; the results looked sane, and at least some of the new
code is covered. I think GCC still doesn't emit the DWARF 4-style CIE.
I was not completely sure how to handle the line table addition. I
chose to have it only note a line when op_index==0, that is (IIUC). GCC
doesn't emit maximum_ops_per_instruction!=1, so I have no way of testing
this in any case.
Let me know what you think.
Tom
2010-04-13 Tom Tromey <tromey@redhat.com>
* dwarf2-frame.c (decode_frame_entry_1): Handle CIE version 4.
(struct dwarf2_cie) <segment_size>: New field.
* dwarf2read.c (partial_read_comp_unit_head): Accept DWARF 4.
(skip_one_die): Handle DW_FORM_flag_present, DW_FORM_sec_offset,
DW_FORM_exprloc.
(read_attribute_value): Handle DW_FORM_flag_present,
DW_FORM_sec_offset, DW_FORM_exprloc.
(dump_die_shallow): Likewise.
(attr_form_is_section_offset): Handle DW_FORM_sec_offset.
(dwarf2_const_value): Handle DW_FORM_exprloc.
(attr_form_is_block): Likewise.
(struct line_header) <maximum_ops_per_instruction>: New field.
(dwarf_decode_line_header): Set new field.
(dwarf_decode_lines): Handle new field.
diff --git a/gdb/dwarf2-frame.c b/gdb/dwarf2-frame.c
index 47a2cf1..33d001c 100644
--- a/gdb/dwarf2-frame.c
+++ b/gdb/dwarf2-frame.c
@@ -85,6 +85,9 @@ struct dwarf2_cie
/* The version recorded in the CIE. */
unsigned char version;
+
+ /* The segment size. */
+ unsigned char segment_size;
};
struct dwarf2_cie_table
@@ -1714,7 +1717,7 @@ decode_frame_entry_1 (struct comp_unit *unit, gdb_byte *start, int eh_frame_p,
/* Check version number. */
cie_version = read_1_byte (unit->abfd, buf);
- if (cie_version != 1 && cie_version != 3)
+ if (cie_version != 1 && cie_version != 3 && cie_version != 4)
return NULL;
cie->version = cie_version;
buf += 1;
@@ -1738,6 +1741,20 @@ decode_frame_entry_1 (struct comp_unit *unit, gdb_byte *start, int eh_frame_p,
augmentation += 2;
}
+ if (cie->version >= 4)
+ {
+ /* FIXME: check that this is the same as from the CU header. */
+ cie->addr_size = read_1_byte (unit->abfd, buf);
+ ++buf;
+ cie->segment_size = read_1_byte (unit->abfd, buf);
+ ++buf;
+ }
+ else
+ {
+ cie->addr_size = gdbarch_ptr_bit (gdbarch) / TARGET_CHAR_BIT;
+ cie->segment_size = 0;
+ }
+
cie->code_alignment_factor =
read_unsigned_leb128 (unit->abfd, buf, &bytes_read);
buf += bytes_read;
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index 724016f..c2017e5 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -396,6 +396,7 @@ struct line_header
unsigned short version;
unsigned int header_length;
unsigned char minimum_instruction_length;
+ unsigned char maximum_ops_per_instruction;
unsigned char default_is_stmt;
int line_base;
unsigned char line_range;
@@ -1488,10 +1489,10 @@ partial_read_comp_unit_head (struct comp_unit_head *header, gdb_byte *info_ptr,
info_ptr = read_comp_unit_head (header, info_ptr, abfd);
- if (header->version != 2 && header->version != 3)
+ if (header->version != 2 && header->version != 3 && header->version != 4)
error (_("Dwarf Error: wrong version in compilation unit header "
- "(is %d, should be %d) [in module %s]"), header->version,
- 2, bfd_get_filename (abfd));
+ "(is %d, should be 2, 3, or 4) [in module %s]"), header->version,
+ bfd_get_filename (abfd));
if (header->abbrev_offset >= dwarf2_per_objfile->abbrev.size)
error (_("Dwarf Error: bad offset (0x%lx) in compilation unit header "
@@ -2776,6 +2777,8 @@ skip_one_die (gdb_byte *buffer, gdb_byte *info_ptr,
case DW_FORM_flag:
info_ptr += 1;
break;
+ case DW_FORM_flag_present:
+ break;
case DW_FORM_data2:
case DW_FORM_ref2:
info_ptr += 2;
@@ -2793,9 +2796,11 @@ skip_one_die (gdb_byte *buffer, gdb_byte *info_ptr,
read_string (abfd, info_ptr, &bytes_read);
info_ptr += bytes_read;
break;
+ case DW_FORM_sec_offset:
case DW_FORM_strp:
info_ptr += cu->header.offset_size;
break;
+ case DW_FORM_exprloc:
case DW_FORM_block:
info_ptr += read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
info_ptr += bytes_read;
@@ -7129,6 +7134,10 @@ read_attribute_value (struct attribute *attr, unsigned form,
DW_UNSND (attr) = read_8_bytes (abfd, info_ptr);
info_ptr += 8;
break;
+ case DW_FORM_sec_offset:
+ DW_ADDR (attr) = read_offset (abfd, info_ptr, &cu->header, &bytes_read);
+ info_ptr += bytes_read;
+ break;
case DW_FORM_string:
DW_STRING (attr) = read_string (abfd, info_ptr, &bytes_read);
DW_STRING_IS_CANONICAL (attr) = 0;
@@ -7140,6 +7149,7 @@ read_attribute_value (struct attribute *attr, unsigned form,
DW_STRING_IS_CANONICAL (attr) = 0;
info_ptr += bytes_read;
break;
+ case DW_FORM_exprloc:
case DW_FORM_block:
blk = dwarf_alloc_block (cu);
blk->size = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
@@ -7164,6 +7174,9 @@ read_attribute_value (struct attribute *attr, unsigned form,
DW_UNSND (attr) = read_1_byte (abfd, info_ptr);
info_ptr += 1;
break;
+ case DW_FORM_flag_present:
+ DW_UNSND (attr) = 1;
+ break;
case DW_FORM_sdata:
DW_SND (attr) = read_signed_leb128 (abfd, info_ptr, &bytes_read);
info_ptr += bytes_read;
@@ -7680,7 +7693,7 @@ dwarf2_attr_no_follow (struct die_info *die, unsigned int name,
/* Return non-zero iff the attribute NAME is defined for the given DIE,
and holds a non-zero value. This function should only be used for
- DW_FORM_flag attributes. */
+ DW_FORM_flag or DW_FORM_flag_present attributes. */
static int
dwarf2_flag_true_p (struct die_info *die, unsigned name, struct dwarf2_cu *cu)
@@ -7862,6 +7875,21 @@ dwarf_decode_line_header (unsigned int offset, bfd *abfd,
line_ptr += offset_size;
lh->minimum_instruction_length = read_1_byte (abfd, line_ptr);
line_ptr += 1;
+ if (lh->version >= 4)
+ {
+ lh->maximum_ops_per_instruction = read_1_byte (abfd, line_ptr);
+ line_ptr += 1;
+ }
+ else
+ lh->maximum_ops_per_instruction = 1;
+
+ if (lh->maximum_ops_per_instruction == 0)
+ {
+ lh->maximum_ops_per_instruction = 1;
+ complaint (&symfile_complaints,
+ _("invalid maximum_ops_per_instruction in `.debug_line' section"));
+ }
+
lh->default_is_stmt = read_1_byte (abfd, line_ptr);
line_ptr += 1;
lh->line_base = read_1_signed_byte (abfd, line_ptr);
@@ -8010,6 +8038,7 @@ dwarf_decode_lines (struct line_header *lh, char *comp_dir, bfd *abfd,
int basic_block = 0;
int end_sequence = 0;
CORE_ADDR addr;
+ unsigned char op_index = 0;
if (!decode_for_pst_p && lh->num_file_names >= file)
{
@@ -8041,12 +8070,17 @@ dwarf_decode_lines (struct line_header *lh, char *comp_dir, bfd *abfd,
{
/* Special operand. */
adj_opcode = op_code - lh->opcode_base;
- address += (adj_opcode / lh->line_range)
- * lh->minimum_instruction_length;
+ address += ((op_index + (adj_opcode / lh->line_range)
+ / lh->maximum_ops_per_instruction)
+ * lh->minimum_instruction_length);
+ op_index = (op_index + (adj_opcode / lh->line_range)
+ % lh->maximum_ops_per_instruction);
line += lh->line_base + (adj_opcode % lh->line_range);
if (lh->num_file_names < file || file == 0)
dwarf2_debug_line_missing_file_complaint ();
- else
+ /* For now we ignore lines not starting on an
+ instruction boundary. */
+ else if (op_index == 0)
{
lh->file_names[file - 1].included_p = 1;
if (!decode_for_pst_p && is_stmt)
@@ -8081,6 +8115,7 @@ dwarf_decode_lines (struct line_header *lh, char *comp_dir, bfd *abfd,
break;
case DW_LNE_set_address:
address = read_address (abfd, line_ptr, cu, &bytes_read);
+ op_index = 0;
line_ptr += bytes_read;
address += baseaddr;
break;
@@ -8146,9 +8181,17 @@ dwarf_decode_lines (struct line_header *lh, char *comp_dir, bfd *abfd,
basic_block = 0;
break;
case DW_LNS_advance_pc:
- address += lh->minimum_instruction_length
- * read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
- line_ptr += bytes_read;
+ {
+ CORE_ADDR adjust
+ = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+
+ address += (((op_index + adjust)
+ / lh->maximum_ops_per_instruction)
+ * lh->minimum_instruction_length);
+ op_index = ((op_index + adjust)
+ % lh->maximum_ops_per_instruction);
+ line_ptr += bytes_read;
+ }
break;
case DW_LNS_advance_line:
line += read_signed_leb128 (abfd, line_ptr, &bytes_read);
@@ -8195,11 +8238,19 @@ dwarf_decode_lines (struct line_header *lh, char *comp_dir, bfd *abfd,
instruction length since special opcode 255 would have
scaled the the increment. */
case DW_LNS_const_add_pc:
- address += (lh->minimum_instruction_length
- * ((255 - lh->opcode_base) / lh->line_range));
+ {
+ CORE_ADDR adjust = (255 - lh->opcode_base) / lh->line_range;
+
+ address += (lh->minimum_instruction_length
+ * ((op_index + adjust)
+ / lh->maximum_ops_per_instruction));
+ op_index = ((op_index + adjust)
+ % lh->maximum_ops_per_instruction);
+ }
break;
case DW_LNS_fixed_advance_pc:
address += read_2_bytes (abfd, line_ptr);
+ op_index = 0;
line_ptr += 2;
break;
default:
@@ -8761,6 +8812,7 @@ dwarf2_const_value (struct attribute *attr, struct symbol *sym,
case DW_FORM_block2:
case DW_FORM_block4:
case DW_FORM_block:
+ case DW_FORM_exprloc:
blk = DW_BLOCK (attr);
if (TYPE_LENGTH (SYMBOL_TYPE (sym)) != blk->size)
dwarf2_const_value_length_mismatch_complaint (SYMBOL_PRINT_NAME (sym),
@@ -10308,6 +10360,10 @@ dump_die_shallow (struct ui_file *f, int indent, struct die_info *die)
case DW_FORM_block1:
fprintf_unfiltered (f, "block: size %d", DW_BLOCK (&die->attrs[i])->size);
break;
+ case DW_FORM_exprloc:
+ fprintf_unfiltered (f, "expression: size %d",
+ DW_BLOCK (&die->attrs[i])->size);
+ break;
case DW_FORM_ref1:
case DW_FORM_ref2:
case DW_FORM_ref4:
@@ -10323,6 +10379,10 @@ dump_die_shallow (struct ui_file *f, int indent, struct die_info *die)
fprintf_unfiltered (f, "constant: %s",
pulongest (DW_UNSND (&die->attrs[i])));
break;
+ case DW_FORM_sec_offset:
+ fprintf_unfiltered (f, "section offset: %s",
+ pulongest (DW_UNSND (&die->attrs[i])));
+ break;
case DW_FORM_sig8:
if (DW_SIGNATURED_TYPE (&die->attrs[i]) != NULL)
fprintf_unfiltered (f, "signatured type, offset: 0x%x",
@@ -10343,6 +10403,9 @@ dump_die_shallow (struct ui_file *f, int indent, struct die_info *die)
else
fprintf_unfiltered (f, "flag: FALSE");
break;
+ case DW_FORM_flag_present:
+ fprintf_unfiltered (f, "flag: TRUE");
+ break;
case DW_FORM_indirect:
/* the reader will have reduced the indirect form to
the "base form" so this form should not occur */
@@ -11520,7 +11583,8 @@ attr_form_is_block (struct attribute *attr)
attr->form == DW_FORM_block1
|| attr->form == DW_FORM_block2
|| attr->form == DW_FORM_block4
- || attr->form == DW_FORM_block);
+ || attr->form == DW_FORM_block
+ || attr->form == DW_FORM_exprloc);
}
/* Return non-zero if ATTR's value is a section offset --- classes
@@ -11535,7 +11599,8 @@ static int
attr_form_is_section_offset (struct attribute *attr)
{
return (attr->form == DW_FORM_data4
- || attr->form == DW_FORM_data8);
+ || attr->form == DW_FORM_data8
+ || attr->form == DW_FORM_sec_offset);
}
^ permalink raw reply [flat|nested] 4+ messages in thread* Re: RFC: add DWARF-4 features
2010-04-13 20:28 RFC: add DWARF-4 features Tom Tromey
@ 2010-04-19 14:45 ` Joel Brobecker
2010-04-19 18:08 ` Jan Kratochvil
1 sibling, 0 replies; 4+ messages in thread
From: Joel Brobecker @ 2010-04-19 14:45 UTC (permalink / raw)
To: Tom Tromey; +Cc: gdb-patches
> 2010-04-13 Tom Tromey <tromey@redhat.com>
>
> * dwarf2-frame.c (decode_frame_entry_1): Handle CIE version 4.
> (struct dwarf2_cie) <segment_size>: New field.
> * dwarf2read.c (partial_read_comp_unit_head): Accept DWARF 4.
> (skip_one_die): Handle DW_FORM_flag_present, DW_FORM_sec_offset,
> DW_FORM_exprloc.
> (read_attribute_value): Handle DW_FORM_flag_present,
> DW_FORM_sec_offset, DW_FORM_exprloc.
> (dump_die_shallow): Likewise.
> (attr_form_is_section_offset): Handle DW_FORM_sec_offset.
> (dwarf2_const_value): Handle DW_FORM_exprloc.
> (attr_form_is_block): Likewise.
> (struct line_header) <maximum_ops_per_instruction>: New field.
> (dwarf_decode_line_header): Set new field.
> (dwarf_decode_lines): Handle new field.
I won't pretend that I looked at this patch very carefully, but what
I looked it seemed to make sense to me. FWIW...
--
Joel
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: RFC: add DWARF-4 features
2010-04-13 20:28 RFC: add DWARF-4 features Tom Tromey
2010-04-19 14:45 ` Joel Brobecker
@ 2010-04-19 18:08 ` Jan Kratochvil
2010-04-20 17:33 ` Tom Tromey
1 sibling, 1 reply; 4+ messages in thread
From: Jan Kratochvil @ 2010-04-19 18:08 UTC (permalink / raw)
To: Tom Tromey; +Cc: gdb-patches
On Tue, 13 Apr 2010 22:28:16 +0200, Tom Tromey wrote:
> + case DW_FORM_sec_offset:
> + DW_ADDR (attr) = read_offset (abfd, info_ptr, &cu->header, &bytes_read);
> + info_ptr += bytes_read;
> + break;
should be DW_UNSND, already used such in your:
> + case DW_FORM_sec_offset:
> + fprintf_unfiltered (f, "section offset: %s",
> + pulongest (DW_UNSND (&die->attrs[i])));
> + break;
and the only consumer of this value in FSF GDB code is:
dwarf2_symbol_mark_computed
baton->size = dwarf2_per_objfile->loc.size - DW_UNSND (attr);
baton->data = dwarf2_per_objfile->loc.buffer + DW_UNSND (attr);
> @@ -8041,12 +8070,17 @@ dwarf_decode_lines (struct line_header *lh, char *comp_dir, bfd *abfd,
> {
> /* Special operand. */
> adj_opcode = op_code - lh->opcode_base;
> - address += (adj_opcode / lh->line_range)
> - * lh->minimum_instruction_length;
> + address += ((op_index + (adj_opcode / lh->line_range)
> + / lh->maximum_ops_per_instruction)
> + * lh->minimum_instruction_length);
While I understand the VLIW support is not there implemented anyway still here
the association is wrong; the division (/) and multiplication (*) should apply
even to OP_INDEX.
The indentation is inappropriate for the expression (the indentation falsely
suggests the calculation is right).
> @@ -8195,11 +8238,19 @@ dwarf_decode_lines (struct line_header *lh, char *comp_dir, bfd *abfd,
> instruction length since special opcode 255 would have
> scaled the the increment. */
> case DW_LNS_const_add_pc:
> - address += (lh->minimum_instruction_length
> - * ((255 - lh->opcode_base) / lh->line_range));
> + {
> + CORE_ADDR adjust = (255 - lh->opcode_base) / lh->line_range;
> +
> + address += (lh->minimum_instruction_length
> + * ((op_index + adjust)
> + / lh->maximum_ops_per_instruction));
I would prefer unified form of the expressions as an aid to the reader. Here
is MINIMUM_INSTRUCTION_LENGTH preceding the rest of the expression while it is
succeeding the rest of the expression in the patch chunk above.
> + case DW_FORM_exprloc:
> + fprintf_unfiltered (f, "expression: size %d",
> + DW_BLOCK (&die->attrs[i])->size);
> + break;
It should be %u.
Thanks,
Jan
^ permalink raw reply [flat|nested] 4+ messages in thread* Re: RFC: add DWARF-4 features
2010-04-19 18:08 ` Jan Kratochvil
@ 2010-04-20 17:33 ` Tom Tromey
0 siblings, 0 replies; 4+ messages in thread
From: Tom Tromey @ 2010-04-20 17:33 UTC (permalink / raw)
To: Jan Kratochvil; +Cc: gdb-patches
>>>>> "Jan" == Jan Kratochvil <jan.kratochvil@redhat.com> writes:
[...]
Jan> I would prefer unified form of the expressions as an aid to the
Jan> reader. Here is MINIMUM_INSTRUCTION_LENGTH preceding the rest of
Jan> the expression while it is succeeding the rest of the expression in
Jan> the patch chunk above.
Thanks for your excellent review.
I am committing the appended updated patch.
Tom
2010-04-20 Tom Tromey <tromey@redhat.com>
* dwarf2-frame.c (decode_frame_entry_1): Handle CIE version 4.
(struct dwarf2_cie) <segment_size>: New field.
* dwarf2read.c (partial_read_comp_unit_head): Accept DWARF 4.
(skip_one_die): Handle DW_FORM_flag_present, DW_FORM_sec_offset,
DW_FORM_exprloc.
(read_attribute_value): Handle DW_FORM_flag_present,
DW_FORM_sec_offset, DW_FORM_exprloc.
(dump_die_shallow): Likewise.
(attr_form_is_section_offset): Handle DW_FORM_sec_offset.
(dwarf2_const_value): Handle DW_FORM_exprloc.
(attr_form_is_block): Likewise.
(struct line_header) <maximum_ops_per_instruction>: New field.
(dwarf_decode_line_header): Set new field.
(dwarf_decode_lines): Handle new field.
Index: dwarf2-frame.c
===================================================================
RCS file: /cvs/src/src/gdb/dwarf2-frame.c,v
retrieving revision 1.107
diff -u -r1.107 dwarf2-frame.c
--- dwarf2-frame.c 24 Mar 2010 21:06:30 -0000 1.107
+++ dwarf2-frame.c 20 Apr 2010 17:32:08 -0000
@@ -85,6 +85,9 @@
/* The version recorded in the CIE. */
unsigned char version;
+
+ /* The segment size. */
+ unsigned char segment_size;
};
struct dwarf2_cie_table
@@ -1714,7 +1717,7 @@
/* Check version number. */
cie_version = read_1_byte (unit->abfd, buf);
- if (cie_version != 1 && cie_version != 3)
+ if (cie_version != 1 && cie_version != 3 && cie_version != 4)
return NULL;
cie->version = cie_version;
buf += 1;
@@ -1738,6 +1741,20 @@
augmentation += 2;
}
+ if (cie->version >= 4)
+ {
+ /* FIXME: check that this is the same as from the CU header. */
+ cie->addr_size = read_1_byte (unit->abfd, buf);
+ ++buf;
+ cie->segment_size = read_1_byte (unit->abfd, buf);
+ ++buf;
+ }
+ else
+ {
+ cie->addr_size = gdbarch_ptr_bit (gdbarch) / TARGET_CHAR_BIT;
+ cie->segment_size = 0;
+ }
+
cie->code_alignment_factor =
read_unsigned_leb128 (unit->abfd, buf, &bytes_read);
buf += bytes_read;
Index: dwarf2read.c
===================================================================
RCS file: /cvs/src/src/gdb/dwarf2read.c,v
retrieving revision 1.378
diff -u -r1.378 dwarf2read.c
--- dwarf2read.c 2 Apr 2010 15:21:47 -0000 1.378
+++ dwarf2read.c 20 Apr 2010 17:32:09 -0000
@@ -396,6 +396,7 @@
unsigned short version;
unsigned int header_length;
unsigned char minimum_instruction_length;
+ unsigned char maximum_ops_per_instruction;
unsigned char default_is_stmt;
int line_base;
unsigned char line_range;
@@ -1488,10 +1489,10 @@
info_ptr = read_comp_unit_head (header, info_ptr, abfd);
- if (header->version != 2 && header->version != 3)
+ if (header->version != 2 && header->version != 3 && header->version != 4)
error (_("Dwarf Error: wrong version in compilation unit header "
- "(is %d, should be %d) [in module %s]"), header->version,
- 2, bfd_get_filename (abfd));
+ "(is %d, should be 2, 3, or 4) [in module %s]"), header->version,
+ bfd_get_filename (abfd));
if (header->abbrev_offset >= dwarf2_per_objfile->abbrev.size)
error (_("Dwarf Error: bad offset (0x%lx) in compilation unit header "
@@ -2776,6 +2777,8 @@
case DW_FORM_flag:
info_ptr += 1;
break;
+ case DW_FORM_flag_present:
+ break;
case DW_FORM_data2:
case DW_FORM_ref2:
info_ptr += 2;
@@ -2793,9 +2796,11 @@
read_string (abfd, info_ptr, &bytes_read);
info_ptr += bytes_read;
break;
+ case DW_FORM_sec_offset:
case DW_FORM_strp:
info_ptr += cu->header.offset_size;
break;
+ case DW_FORM_exprloc:
case DW_FORM_block:
info_ptr += read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
info_ptr += bytes_read;
@@ -7129,6 +7134,10 @@
DW_UNSND (attr) = read_8_bytes (abfd, info_ptr);
info_ptr += 8;
break;
+ case DW_FORM_sec_offset:
+ DW_UNSND (attr) = read_offset (abfd, info_ptr, &cu->header, &bytes_read);
+ info_ptr += bytes_read;
+ break;
case DW_FORM_string:
DW_STRING (attr) = read_string (abfd, info_ptr, &bytes_read);
DW_STRING_IS_CANONICAL (attr) = 0;
@@ -7140,6 +7149,7 @@
DW_STRING_IS_CANONICAL (attr) = 0;
info_ptr += bytes_read;
break;
+ case DW_FORM_exprloc:
case DW_FORM_block:
blk = dwarf_alloc_block (cu);
blk->size = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
@@ -7164,6 +7174,9 @@
DW_UNSND (attr) = read_1_byte (abfd, info_ptr);
info_ptr += 1;
break;
+ case DW_FORM_flag_present:
+ DW_UNSND (attr) = 1;
+ break;
case DW_FORM_sdata:
DW_SND (attr) = read_signed_leb128 (abfd, info_ptr, &bytes_read);
info_ptr += bytes_read;
@@ -7680,7 +7693,7 @@
/* Return non-zero iff the attribute NAME is defined for the given DIE,
and holds a non-zero value. This function should only be used for
- DW_FORM_flag attributes. */
+ DW_FORM_flag or DW_FORM_flag_present attributes. */
static int
dwarf2_flag_true_p (struct die_info *die, unsigned name, struct dwarf2_cu *cu)
@@ -7862,6 +7875,21 @@
line_ptr += offset_size;
lh->minimum_instruction_length = read_1_byte (abfd, line_ptr);
line_ptr += 1;
+ if (lh->version >= 4)
+ {
+ lh->maximum_ops_per_instruction = read_1_byte (abfd, line_ptr);
+ line_ptr += 1;
+ }
+ else
+ lh->maximum_ops_per_instruction = 1;
+
+ if (lh->maximum_ops_per_instruction == 0)
+ {
+ lh->maximum_ops_per_instruction = 1;
+ complaint (&symfile_complaints,
+ _("invalid maximum_ops_per_instruction in `.debug_line' section"));
+ }
+
lh->default_is_stmt = read_1_byte (abfd, line_ptr);
line_ptr += 1;
lh->line_base = read_1_signed_byte (abfd, line_ptr);
@@ -8010,6 +8038,7 @@
int basic_block = 0;
int end_sequence = 0;
CORE_ADDR addr;
+ unsigned char op_index = 0;
if (!decode_for_pst_p && lh->num_file_names >= file)
{
@@ -8041,12 +8070,17 @@
{
/* Special operand. */
adj_opcode = op_code - lh->opcode_base;
- address += (adj_opcode / lh->line_range)
- * lh->minimum_instruction_length;
+ address += (((op_index + (adj_opcode / lh->line_range))
+ / lh->maximum_ops_per_instruction)
+ * lh->minimum_instruction_length);
+ op_index = ((op_index + (adj_opcode / lh->line_range))
+ % lh->maximum_ops_per_instruction);
line += lh->line_base + (adj_opcode % lh->line_range);
if (lh->num_file_names < file || file == 0)
dwarf2_debug_line_missing_file_complaint ();
- else
+ /* For now we ignore lines not starting on an
+ instruction boundary. */
+ else if (op_index == 0)
{
lh->file_names[file - 1].included_p = 1;
if (!decode_for_pst_p && is_stmt)
@@ -8081,6 +8115,7 @@
break;
case DW_LNE_set_address:
address = read_address (abfd, line_ptr, cu, &bytes_read);
+ op_index = 0;
line_ptr += bytes_read;
address += baseaddr;
break;
@@ -8146,9 +8181,17 @@
basic_block = 0;
break;
case DW_LNS_advance_pc:
- address += lh->minimum_instruction_length
- * read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
- line_ptr += bytes_read;
+ {
+ CORE_ADDR adjust
+ = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+
+ address += (((op_index + adjust)
+ / lh->maximum_ops_per_instruction)
+ * lh->minimum_instruction_length);
+ op_index = ((op_index + adjust)
+ % lh->maximum_ops_per_instruction);
+ line_ptr += bytes_read;
+ }
break;
case DW_LNS_advance_line:
line += read_signed_leb128 (abfd, line_ptr, &bytes_read);
@@ -8195,11 +8238,19 @@
instruction length since special opcode 255 would have
scaled the the increment. */
case DW_LNS_const_add_pc:
- address += (lh->minimum_instruction_length
- * ((255 - lh->opcode_base) / lh->line_range));
+ {
+ CORE_ADDR adjust = (255 - lh->opcode_base) / lh->line_range;
+
+ address += (((op_index + adjust)
+ / lh->maximum_ops_per_instruction)
+ * lh->minimum_instruction_length);
+ op_index = ((op_index + adjust)
+ % lh->maximum_ops_per_instruction);
+ }
break;
case DW_LNS_fixed_advance_pc:
address += read_2_bytes (abfd, line_ptr);
+ op_index = 0;
line_ptr += 2;
break;
default:
@@ -8761,6 +8812,7 @@
case DW_FORM_block2:
case DW_FORM_block4:
case DW_FORM_block:
+ case DW_FORM_exprloc:
blk = DW_BLOCK (attr);
if (TYPE_LENGTH (SYMBOL_TYPE (sym)) != blk->size)
dwarf2_const_value_length_mismatch_complaint (SYMBOL_PRINT_NAME (sym),
@@ -10308,6 +10360,10 @@
case DW_FORM_block1:
fprintf_unfiltered (f, "block: size %d", DW_BLOCK (&die->attrs[i])->size);
break;
+ case DW_FORM_exprloc:
+ fprintf_unfiltered (f, "expression: size %u",
+ DW_BLOCK (&die->attrs[i])->size);
+ break;
case DW_FORM_ref1:
case DW_FORM_ref2:
case DW_FORM_ref4:
@@ -10323,6 +10379,10 @@
fprintf_unfiltered (f, "constant: %s",
pulongest (DW_UNSND (&die->attrs[i])));
break;
+ case DW_FORM_sec_offset:
+ fprintf_unfiltered (f, "section offset: %s",
+ pulongest (DW_UNSND (&die->attrs[i])));
+ break;
case DW_FORM_sig8:
if (DW_SIGNATURED_TYPE (&die->attrs[i]) != NULL)
fprintf_unfiltered (f, "signatured type, offset: 0x%x",
@@ -10343,6 +10403,9 @@
else
fprintf_unfiltered (f, "flag: FALSE");
break;
+ case DW_FORM_flag_present:
+ fprintf_unfiltered (f, "flag: TRUE");
+ break;
case DW_FORM_indirect:
/* the reader will have reduced the indirect form to
the "base form" so this form should not occur */
@@ -11520,7 +11583,8 @@
attr->form == DW_FORM_block1
|| attr->form == DW_FORM_block2
|| attr->form == DW_FORM_block4
- || attr->form == DW_FORM_block);
+ || attr->form == DW_FORM_block
+ || attr->form == DW_FORM_exprloc);
}
/* Return non-zero if ATTR's value is a section offset --- classes
@@ -11535,7 +11599,8 @@
attr_form_is_section_offset (struct attribute *attr)
{
return (attr->form == DW_FORM_data4
- || attr->form == DW_FORM_data8);
+ || attr->form == DW_FORM_data8
+ || attr->form == DW_FORM_sec_offset);
}
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2010-04-20 17:33 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-04-13 20:28 RFC: add DWARF-4 features Tom Tromey
2010-04-19 14:45 ` Joel Brobecker
2010-04-19 18:08 ` Jan Kratochvil
2010-04-20 17:33 ` Tom Tromey
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox