Parse DWARF 4 line tables correctly

Breakpad’s DWARF line table reader only understood line tables at the
level of DWARF 2. This wasn’t a problem because LLVM only produced line
tables at this level, even when generating DWARF 4. But LLVM would like
to output DWARF 4 line tables when generating DWARF 4, and Breakpad
needs to understand this format. (Meanwhile, it seems that GCC has used
DWARF 4 line tables with DWARF 4 output since 4.5.0, 2010-04-14.)

DWARF 3 line tables are fully compatible with DWARF 2 (assuming that
nothing needs “prologue end,” “epilogue begin,” or “isa”, and opcodes
related to these fields are properly skipped). DWARF 4 changes the line
number program header slightly to include a “maximum operations per
instruction” field. This field must be recognized, but can safely be
ignored (and assumed to be always 1) if VLIW architectures are not
supported (they aren’t). DWARF 4 also introduces a “discriminator”,
whose opcode can also be skipped if these values are not needed (they
shouldn’t be).

This recognizes the “maximum operations per instruction” field when
processing DWARF 4 line tables, but asserts that its value is 1 and
otherwise ignores it.

This is not compatible with VLIW architectures that set this field to a
value other than 1. Such architectures are irrelevant to Breakpad, and
mainline GCC and the proposed LLVM patch always set this field to 1.
There are other things that could be extracted from DWARF 3 and 4 line
tables that aren’t currently extracted (although these are currently
irrelevant to Breakpad too).

Bug: google-breakpad:745
Change-Id: I5bf9c0b1aa654849c9cce64e60682447d10be8ba
Reviewed-on: https://chromium-review.googlesource.com/663441
Reviewed-by: Mike Frysinger <vapier@chromium.org>
This commit is contained in:
Mark Mentovai 2017-09-13 14:18:00 -04:00
parent a1dbcdcb43
commit 7c409af709

View File

@ -942,6 +942,13 @@ void LineInfo::ReadHeader() {
header_.min_insn_length = reader_->ReadOneByte(lineptr); header_.min_insn_length = reader_->ReadOneByte(lineptr);
lineptr += 1; lineptr += 1;
if (header_.version >= 4) {
__attribute__((unused)) uint8 max_ops_per_insn =
reader_->ReadOneByte(lineptr);
++lineptr;
assert(max_ops_per_insn == 1);
}
header_.default_is_stmt = reader_->ReadOneByte(lineptr); header_.default_is_stmt = reader_->ReadOneByte(lineptr);
lineptr += 1; lineptr += 1;