Dwarf5 fixes [4 of 5]: Skip processing Dwarf5 type units.
Fourth of 5 small patches to fix various breakpad issues found while testing dump_syms on DWARF v5 in ChromeOS. Dwarfv5 adds many new Type Unit sections to debug information. Since these only contain type information, they are of no interest to dump_syms. This CL gets dump_syms to skip trying to process the type unit sections. Without this CL, dump_syms takes ~ 3 hours to process the DWARF v5 Chrome binary. With this CL, dump_syms takes ~ 8 minutes to process the DWARF v5 Chrome binary (about the same time as it takes for DWARF v4). This CL also adds a test case to verify that type units are being skipped. Change-Id: Ie0bb2d675718f7041b8e9b3186ed44f80a3ad39c Reviewed-on: https://chromium-review.googlesource.com/c/breakpad/breakpad/+/2634549 Reviewed-by: Sterling Augustine <saugustine@google.com>
This commit is contained in:
parent
646f0f4920
commit
3c528da94c
4 changed files with 128 additions and 63 deletions
|
@ -74,7 +74,7 @@ CompilationUnit::CompilationUnit(const string& path,
|
|||
line_string_buffer_(NULL), line_string_buffer_length_(0),
|
||||
str_offsets_buffer_(NULL), str_offsets_buffer_length_(0),
|
||||
addr_buffer_(NULL), addr_buffer_length_(0),
|
||||
is_split_dwarf_(false), dwo_id_(0), dwo_name_(),
|
||||
is_split_dwarf_(false), is_type_unit_(false), dwo_id_(0), dwo_name_(),
|
||||
skeleton_dwo_id_(0), ranges_base_(0), addr_base_(0),
|
||||
str_offsets_base_(0), have_checked_for_dwp_(false), dwp_path_(),
|
||||
dwp_byte_reader_(), dwp_reader_() {}
|
||||
|
@ -358,6 +358,7 @@ void CompilationUnit::ReadHeader() {
|
|||
break;
|
||||
case DW_UT_type:
|
||||
case DW_UT_split_type:
|
||||
is_type_unit_ = true;
|
||||
headerptr += ReadTypeSignature(headerptr);
|
||||
headerptr += ReadTypeOffset(headerptr);
|
||||
break;
|
||||
|
@ -404,6 +405,8 @@ uint64_t CompilationUnit::Start() {
|
|||
header_.length,
|
||||
header_.version))
|
||||
return ourlength;
|
||||
else if (header_.version == 5 && is_type_unit_)
|
||||
return ourlength;
|
||||
|
||||
// Otherwise, continue by reading our abbreviation entries.
|
||||
ReadAbbrevs();
|
||||
|
|
|
@ -714,6 +714,9 @@ class CompilationUnit {
|
|||
// associated with the skeleton compilation unit.
|
||||
bool is_split_dwarf_;
|
||||
|
||||
// Flag indicating if it's a Type Unit (only applicable to DWARF v5).
|
||||
bool is_type_unit_;
|
||||
|
||||
// The value of the DW_AT_GNU_dwo_id attribute, if any.
|
||||
uint64_t dwo_id_;
|
||||
|
||||
|
|
|
@ -152,13 +152,15 @@ struct DIEFixture {
|
|||
|
||||
struct DwarfHeaderParams {
|
||||
DwarfHeaderParams(Endianness endianness, size_t format_size,
|
||||
int version, size_t address_size)
|
||||
int version, size_t address_size, int header_type)
|
||||
: endianness(endianness), format_size(format_size),
|
||||
version(version), address_size(address_size) { }
|
||||
version(version), address_size(address_size), header_type(header_type)
|
||||
{ }
|
||||
Endianness endianness;
|
||||
size_t format_size; // 4-byte or 8-byte DWARF offsets
|
||||
int version;
|
||||
size_t address_size;
|
||||
int header_type; // DW_UT_{compile, type, partial, skeleton, etc}
|
||||
};
|
||||
|
||||
class DwarfHeader: public DIEFixture,
|
||||
|
@ -175,7 +177,8 @@ TEST_P(DwarfHeader, Header) {
|
|||
info.set_format_size(GetParam().format_size);
|
||||
info.set_endianness(GetParam().endianness);
|
||||
|
||||
info.Header(GetParam().version, abbrev_table, GetParam().address_size)
|
||||
info.Header(GetParam().version, abbrev_table, GetParam().address_size,
|
||||
dwarf2reader::DW_UT_compile)
|
||||
.ULEB128(1) // DW_TAG_compile_unit, with children
|
||||
.AppendCString("sam") // DW_AT_name, DW_FORM_string
|
||||
.D8(0); // end of children
|
||||
|
@ -190,7 +193,7 @@ TEST_P(DwarfHeader, Header) {
|
|||
.WillOnce(Return(true));
|
||||
EXPECT_CALL(handler, StartDIE(_, dwarf2reader::DW_TAG_compile_unit))
|
||||
.WillOnce(Return(true));
|
||||
EXPECT_CALL(handler, ProcessAttributeString(_, dwarf2reader::DW_AT_name,
|
||||
EXPECT_CALL(handler, ProcessAttributeString(_, dwarf2reader::DW_AT_name,
|
||||
dwarf2reader::DW_FORM_string,
|
||||
"sam"))
|
||||
.WillOnce(Return());
|
||||
|
@ -204,36 +207,79 @@ TEST_P(DwarfHeader, Header) {
|
|||
EXPECT_EQ(parser.Start(), info_contents.size());
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
TEST_P(DwarfHeader, TypeUnitHeader) {
|
||||
Label abbrev_table = abbrevs.Here();
|
||||
int version = 5;
|
||||
abbrevs.Abbrev(1, dwarf2reader::DW_TAG_type_unit,
|
||||
dwarf2reader::DW_children_yes)
|
||||
.Attribute(dwarf2reader::DW_AT_name, dwarf2reader::DW_FORM_string)
|
||||
.EndAbbrev()
|
||||
.EndTable();
|
||||
|
||||
info.set_format_size(GetParam().format_size);
|
||||
info.set_endianness(GetParam().endianness);
|
||||
|
||||
info.Header(version, abbrev_table, GetParam().address_size,
|
||||
dwarf2reader::DW_UT_type)
|
||||
.ULEB128(0x41) // DW_TAG_type_unit, with children
|
||||
.AppendCString("sam") // DW_AT_name, DW_FORM_string
|
||||
.D8(0); // end of children
|
||||
info.Finish();
|
||||
|
||||
{
|
||||
InSequence s;
|
||||
EXPECT_CALL(handler,
|
||||
StartCompilationUnit(0, GetParam().address_size,
|
||||
GetParam().format_size, _,
|
||||
version))
|
||||
.WillOnce(Return(true));
|
||||
// If the type unit is handled properly, these calls will be skipped.
|
||||
EXPECT_CALL(handler, StartDIE(_, dwarf2reader::DW_TAG_type_unit))
|
||||
.Times(0);
|
||||
EXPECT_CALL(handler, ProcessAttributeString(_, dwarf2reader::DW_AT_name,
|
||||
dwarf2reader::DW_FORM_string,
|
||||
"sam"))
|
||||
.Times(0);
|
||||
EXPECT_CALL(handler, EndDIE(_))
|
||||
.Times(0);
|
||||
}
|
||||
|
||||
ByteReader byte_reader(GetParam().endianness == kLittleEndian ?
|
||||
ENDIANNESS_LITTLE : ENDIANNESS_BIG);
|
||||
CompilationUnit parser("", MakeSectionMap(), 0, &byte_reader, &handler);
|
||||
EXPECT_EQ(parser.Start(), info_contents.size());
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
HeaderVariants, DwarfHeader,
|
||||
::testing::Values(DwarfHeaderParams(kLittleEndian, 4, 2, 4),
|
||||
DwarfHeaderParams(kLittleEndian, 4, 2, 8),
|
||||
DwarfHeaderParams(kLittleEndian, 4, 3, 4),
|
||||
DwarfHeaderParams(kLittleEndian, 4, 3, 8),
|
||||
DwarfHeaderParams(kLittleEndian, 4, 4, 4),
|
||||
DwarfHeaderParams(kLittleEndian, 4, 4, 8),
|
||||
DwarfHeaderParams(kLittleEndian, 8, 2, 4),
|
||||
DwarfHeaderParams(kLittleEndian, 8, 2, 8),
|
||||
DwarfHeaderParams(kLittleEndian, 8, 3, 4),
|
||||
DwarfHeaderParams(kLittleEndian, 8, 3, 8),
|
||||
DwarfHeaderParams(kLittleEndian, 8, 4, 4),
|
||||
DwarfHeaderParams(kLittleEndian, 8, 4, 8),
|
||||
DwarfHeaderParams(kLittleEndian, 8, 5, 4),
|
||||
DwarfHeaderParams(kLittleEndian, 8, 5, 8),
|
||||
DwarfHeaderParams(kBigEndian, 4, 2, 4),
|
||||
DwarfHeaderParams(kBigEndian, 4, 2, 8),
|
||||
DwarfHeaderParams(kBigEndian, 4, 3, 4),
|
||||
DwarfHeaderParams(kBigEndian, 4, 3, 8),
|
||||
DwarfHeaderParams(kBigEndian, 4, 4, 4),
|
||||
DwarfHeaderParams(kBigEndian, 4, 4, 8),
|
||||
DwarfHeaderParams(kBigEndian, 8, 2, 4),
|
||||
DwarfHeaderParams(kBigEndian, 8, 2, 8),
|
||||
DwarfHeaderParams(kBigEndian, 8, 3, 4),
|
||||
DwarfHeaderParams(kBigEndian, 8, 3, 8),
|
||||
DwarfHeaderParams(kBigEndian, 8, 4, 4),
|
||||
DwarfHeaderParams(kBigEndian, 8, 4, 8),
|
||||
DwarfHeaderParams(kBigEndian, 8, 5, 4),
|
||||
DwarfHeaderParams(kBigEndian, 8, 5, 8)));
|
||||
::testing::Values(DwarfHeaderParams(kLittleEndian, 4, 2, 4, 1),
|
||||
DwarfHeaderParams(kLittleEndian, 4, 2, 8, 1),
|
||||
DwarfHeaderParams(kLittleEndian, 4, 3, 4, 1),
|
||||
DwarfHeaderParams(kLittleEndian, 4, 3, 8, 1),
|
||||
DwarfHeaderParams(kLittleEndian, 4, 4, 4, 1),
|
||||
DwarfHeaderParams(kLittleEndian, 4, 4, 8, 1),
|
||||
DwarfHeaderParams(kLittleEndian, 8, 2, 4, 1),
|
||||
DwarfHeaderParams(kLittleEndian, 8, 2, 8, 1),
|
||||
DwarfHeaderParams(kLittleEndian, 8, 3, 4, 1),
|
||||
DwarfHeaderParams(kLittleEndian, 8, 3, 8, 1),
|
||||
DwarfHeaderParams(kLittleEndian, 8, 4, 4, 1),
|
||||
DwarfHeaderParams(kLittleEndian, 8, 4, 8, 1),
|
||||
DwarfHeaderParams(kLittleEndian, 8, 5, 4, 1),
|
||||
DwarfHeaderParams(kLittleEndian, 8, 5, 8, 1),
|
||||
DwarfHeaderParams(kBigEndian, 4, 2, 4, 1),
|
||||
DwarfHeaderParams(kBigEndian, 4, 2, 8, 1),
|
||||
DwarfHeaderParams(kBigEndian, 4, 3, 4, 1),
|
||||
DwarfHeaderParams(kBigEndian, 4, 3, 8, 1),
|
||||
DwarfHeaderParams(kBigEndian, 4, 4, 4, 1),
|
||||
DwarfHeaderParams(kBigEndian, 4, 4, 8, 1),
|
||||
DwarfHeaderParams(kBigEndian, 8, 2, 4, 1),
|
||||
DwarfHeaderParams(kBigEndian, 8, 2, 8, 1),
|
||||
DwarfHeaderParams(kBigEndian, 8, 3, 4, 1),
|
||||
DwarfHeaderParams(kBigEndian, 8, 3, 8, 1),
|
||||
DwarfHeaderParams(kBigEndian, 8, 4, 4, 1),
|
||||
DwarfHeaderParams(kBigEndian, 8, 4, 8, 1),
|
||||
DwarfHeaderParams(kBigEndian, 8, 5, 4, 1),
|
||||
DwarfHeaderParams(kBigEndian, 8, 5, 8, 1)));
|
||||
|
||||
struct DwarfFormsFixture: public DIEFixture {
|
||||
// Start a compilation unit, as directed by |params|, containing one
|
||||
|
@ -253,7 +299,8 @@ struct DwarfFormsFixture: public DIEFixture {
|
|||
// Create the compilation unit, up to the attribute value.
|
||||
info.set_format_size(params.format_size);
|
||||
info.set_endianness(params.endianness);
|
||||
info.Header(params.version, abbrev_table, params.address_size)
|
||||
info.Header(params.version, abbrev_table, params.address_size,
|
||||
dwarf2reader::DW_UT_compile)
|
||||
.ULEB128(1); // abbrev code
|
||||
}
|
||||
|
||||
|
@ -560,7 +607,8 @@ TEST_P(DwarfForms, implicit_const) {
|
|||
|
||||
info.set_format_size(params.format_size);
|
||||
info.set_endianness(params.endianness);
|
||||
info.Header(params.version, abbrev_table, params.address_size)
|
||||
info.Header(params.version, abbrev_table, params.address_size,
|
||||
dwarf2reader::DW_UT_compile)
|
||||
.ULEB128(1); // abbrev code
|
||||
info.Finish();
|
||||
|
||||
|
@ -578,32 +626,32 @@ TEST_P(DwarfForms, implicit_const) {
|
|||
|
||||
// Tests for the other attribute forms could go here.
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
HeaderVariants, DwarfForms,
|
||||
::testing::Values(DwarfHeaderParams(kLittleEndian, 4, 2, 4),
|
||||
DwarfHeaderParams(kLittleEndian, 4, 2, 8),
|
||||
DwarfHeaderParams(kLittleEndian, 4, 3, 4),
|
||||
DwarfHeaderParams(kLittleEndian, 4, 3, 8),
|
||||
DwarfHeaderParams(kLittleEndian, 4, 4, 4),
|
||||
DwarfHeaderParams(kLittleEndian, 4, 4, 8),
|
||||
DwarfHeaderParams(kLittleEndian, 8, 2, 4),
|
||||
DwarfHeaderParams(kLittleEndian, 8, 2, 8),
|
||||
DwarfHeaderParams(kLittleEndian, 8, 3, 4),
|
||||
DwarfHeaderParams(kLittleEndian, 8, 3, 8),
|
||||
DwarfHeaderParams(kLittleEndian, 8, 4, 4),
|
||||
DwarfHeaderParams(kLittleEndian, 8, 4, 8),
|
||||
DwarfHeaderParams(kBigEndian, 4, 2, 4),
|
||||
DwarfHeaderParams(kBigEndian, 4, 2, 8),
|
||||
DwarfHeaderParams(kBigEndian, 4, 3, 4),
|
||||
DwarfHeaderParams(kBigEndian, 4, 3, 8),
|
||||
DwarfHeaderParams(kBigEndian, 4, 4, 4),
|
||||
DwarfHeaderParams(kBigEndian, 4, 4, 8),
|
||||
DwarfHeaderParams(kBigEndian, 8, 2, 4),
|
||||
DwarfHeaderParams(kBigEndian, 8, 2, 8),
|
||||
DwarfHeaderParams(kBigEndian, 8, 3, 4),
|
||||
DwarfHeaderParams(kBigEndian, 8, 3, 8),
|
||||
DwarfHeaderParams(kBigEndian, 8, 4, 4),
|
||||
DwarfHeaderParams(kBigEndian, 8, 4, 8)));
|
||||
::testing::Values(DwarfHeaderParams(kLittleEndian, 4, 2, 4, 1),
|
||||
DwarfHeaderParams(kLittleEndian, 4, 2, 8, 1),
|
||||
DwarfHeaderParams(kLittleEndian, 4, 3, 4, 1),
|
||||
DwarfHeaderParams(kLittleEndian, 4, 3, 8, 1),
|
||||
DwarfHeaderParams(kLittleEndian, 4, 4, 4, 1),
|
||||
DwarfHeaderParams(kLittleEndian, 4, 4, 8, 1),
|
||||
DwarfHeaderParams(kLittleEndian, 8, 2, 4, 1),
|
||||
DwarfHeaderParams(kLittleEndian, 8, 2, 8, 1),
|
||||
DwarfHeaderParams(kLittleEndian, 8, 3, 4, 1),
|
||||
DwarfHeaderParams(kLittleEndian, 8, 3, 8, 1),
|
||||
DwarfHeaderParams(kLittleEndian, 8, 4, 4, 1),
|
||||
DwarfHeaderParams(kLittleEndian, 8, 4, 8, 1),
|
||||
DwarfHeaderParams(kBigEndian, 4, 2, 4, 1),
|
||||
DwarfHeaderParams(kBigEndian, 4, 2, 8, 1),
|
||||
DwarfHeaderParams(kBigEndian, 4, 3, 4, 1),
|
||||
DwarfHeaderParams(kBigEndian, 4, 3, 8, 1),
|
||||
DwarfHeaderParams(kBigEndian, 4, 4, 4, 1),
|
||||
DwarfHeaderParams(kBigEndian, 4, 4, 8, 1),
|
||||
DwarfHeaderParams(kBigEndian, 8, 2, 4, 1),
|
||||
DwarfHeaderParams(kBigEndian, 8, 2, 8, 1),
|
||||
DwarfHeaderParams(kBigEndian, 8, 3, 4, 1),
|
||||
DwarfHeaderParams(kBigEndian, 8, 3, 8, 1),
|
||||
DwarfHeaderParams(kBigEndian, 8, 4, 4, 1),
|
||||
DwarfHeaderParams(kBigEndian, 8, 4, 8, 1)));
|
||||
|
||||
class MockRangeListHandler: public dwarf2reader::RangeListHandler {
|
||||
public:
|
||||
|
@ -658,8 +706,10 @@ TEST(RangeList, Dwarf5ReadRangeList) {
|
|||
using dwarf2reader::DW_RLE_offset_pair;
|
||||
using dwarf2reader::DW_RLE_end_of_list;
|
||||
using dwarf2reader::DW_RLE_base_address;
|
||||
using dwarf2reader::DW_RLE_offset_pair;
|
||||
using dwarf2reader::DW_RLE_start_end;
|
||||
using dwarf2reader::DW_RLE_start_length;
|
||||
using dwarf2reader::DW_RLE_end_of_list;
|
||||
using dwarf2reader::DW_FORM_sec_offset;
|
||||
using dwarf2reader::DW_FORM_rnglistx;
|
||||
|
||||
|
|
|
@ -71,7 +71,7 @@ class TestCompilationUnit: public google_breakpad::test_assembler::Section {
|
|||
// Append a DWARF compilation unit header to the section, with the given
|
||||
// DWARF version, abbrev table offset, and address size.
|
||||
TestCompilationUnit& Header(int version, const Label& abbrev_offset,
|
||||
size_t address_size) {
|
||||
size_t address_size, int header_type) {
|
||||
if (format_size_ == 4) {
|
||||
D32(length_);
|
||||
} else {
|
||||
|
@ -84,9 +84,18 @@ class TestCompilationUnit: public google_breakpad::test_assembler::Section {
|
|||
SectionOffset(abbrev_offset);
|
||||
D8(address_size);
|
||||
} else {
|
||||
D8(0x01); // DW_UT_compile
|
||||
D8(header_type); // DW_UT_compile, DW_UT_type, etc.
|
||||
D8(address_size);
|
||||
SectionOffset(abbrev_offset);
|
||||
if (header_type == dwarf2reader::DW_UT_type) {
|
||||
uint64 dummy_type_signature = 0xdeadbeef;
|
||||
uint64 dummy_type_offset = 0x2b;
|
||||
D64(dummy_type_signature);
|
||||
if (format_size_ == 4)
|
||||
D32(dummy_type_offset);
|
||||
else
|
||||
D64(dummy_type_offset);
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue