dump_syms: Fix handling of DW_FORM_ref_addr to work with DWARF 4

Previously, dump_syms did not handle DW_FORM_ref_addr if it appeared
in DWARF 4 debugging info.

Also fix a DW_FORM_ref_addr case so that it doesn't fall through to
the next switch case when assertions are disabled and the DWARF
version isn't recognised.

The following steps will reproduce the problem when using LLVM 3.4:

cat <<END >example1.c
int main() { return 0; }
END
cat <<END >example2.c
void foo(int x) {}
END

clang -emit-llvm -g -c example1.c -o example1.bc
clang -emit-llvm -g -c example2.c -o example2.bc
llvm-link-3.4 example1.bc example2.bc -o combined.bc
clang combined.bc -o executable
./google-breakpad/build/src/tools/linux/dump_syms/dump_syms executable

When using LLVM bitcode linking in this way, LLVM's backend generates
partially-merged DWARF debugging info in which some of the references
to the "int" type go via "DW_FORM_ref_addr".  Since PNaCl uses LLVM
bitcode linking, this dump_syms failure occurs with nexes produced by
the PNaCl toolchain.

BUG= https://code.google.com/p/chromium/issues/detail?id=416368
TEST= see above
R=mark@chromium.org, mcgrathr@chromium.org

Review URL: https://breakpad.appspot.com/5744002

git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1408 4c0a9323-5329-0410-9bdc-e9ce6186880e
This commit is contained in:
mseaborn@chromium.org 2014-12-03 20:39:55 +00:00
parent 0b6cc95246
commit 10baadae40

View file

@ -183,14 +183,15 @@ const char* CompilationUnit::SkipAttribute(const char* start,
case DW_FORM_addr: case DW_FORM_addr:
return start + reader_->AddressSize(); return start + reader_->AddressSize();
case DW_FORM_ref_addr: case DW_FORM_ref_addr:
// DWARF2 and 3 differ on whether ref_addr is address size or // DWARF2 and 3/4 differ on whether ref_addr is address size or
// offset size. // offset size.
assert(header_.version == 2 || header_.version == 3); assert(header_.version >= 2);
if (header_.version == 2) { if (header_.version == 2) {
return start + reader_->AddressSize(); return start + reader_->AddressSize();
} else if (header_.version == 3) { } else if (header_.version >= 3) {
return start + reader_->OffsetSize(); return start + reader_->OffsetSize();
} }
break;
case DW_FORM_block1: case DW_FORM_block1:
return start + 1 + reader_->ReadOneByte(start); return start + 1 + reader_->ReadOneByte(start);
@ -390,14 +391,14 @@ const char* CompilationUnit::ProcessAttribute(
+ offset_from_section_start_); + offset_from_section_start_);
return start + len; return start + len;
case DW_FORM_ref_addr: case DW_FORM_ref_addr:
// DWARF2 and 3 differ on whether ref_addr is address size or // DWARF2 and 3/4 differ on whether ref_addr is address size or
// offset size. // offset size.
assert(header_.version == 2 || header_.version == 3); assert(header_.version >= 2);
if (header_.version == 2) { if (header_.version == 2) {
handler_->ProcessAttributeReference(dieoffset, attr, form, handler_->ProcessAttributeReference(dieoffset, attr, form,
reader_->ReadAddress(start)); reader_->ReadAddress(start));
return start + reader_->AddressSize(); return start + reader_->AddressSize();
} else if (header_.version == 3) { } else if (header_.version >= 3) {
handler_->ProcessAttributeReference(dieoffset, attr, form, handler_->ProcessAttributeReference(dieoffset, attr, form,
reader_->ReadOffset(start)); reader_->ReadOffset(start));
return start + reader_->OffsetSize(); return start + reader_->OffsetSize();