Breakpad DWARF: Add support for DWARF 4 attribute forms.
This patch allows Breakpad's DWARF reader to at least read or skip attributes using the new forms defined in version 4 of the DWARF specification, instead of crashing. Attributes encoded using DW_FORM_flag_present, DW_FORM_sec_offset, and DW_FORM_exprloc should work fine now. However, compilation units using DW_FORM_ref_sig8 to refer to types in .debug_types will need further work to support. (GCC 4.6.2 does not emit .debug_types sections.) Specifically: - dwarf2reader::DwarfForm gets new values. - dwarf2reader::Dwarf2Handler and dwarf2reader::DIEHandler get new handler methods, named ProcessAttributeSignature, for DW_FORM_ref_sig8 attributes. - dwarf2reader::CompilationUnit reads DW_FORM_ref_sig8 attributes, and passes them to ProcessAttributeSignature. It also gets support for DW_FORM_sec_offset, DW_FORM_exprloc, and DW_FORM_flag_present, using the existing appropriate ProcessAttribute* methods. - dwarf2reader::DIEDispatcher passes through ProcessAttributeSignature attributes to its DIEHandler. - Unit tests are updated. a=jimb, r=ted.mielczarek Review URL: http://breakpad.appspot.com/343003/ git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@912 4c0a9323-5329-0410-9bdc-e9ce6186880e
This commit is contained in:
parent
08b912f1ed
commit
5e4f6feaf6
@ -183,4 +183,14 @@ void DIEDispatcher::ProcessAttributeString(uint64 offset,
|
|||||||
current.handler_->ProcessAttributeString(attr, form, data);
|
current.handler_->ProcessAttributeString(attr, form, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DIEDispatcher::ProcessAttributeSignature(uint64 offset,
|
||||||
|
enum DwarfAttribute attr,
|
||||||
|
enum DwarfForm form,
|
||||||
|
uint64 signature) {
|
||||||
|
HandlerStack ¤t = die_handlers_.top();
|
||||||
|
// This had better be an attribute of the DIE we were meant to handle.
|
||||||
|
assert(offset == current.offset_);
|
||||||
|
current.handler_->ProcessAttributeSignature(attr, form, signature);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace dwarf2reader
|
} // namespace dwarf2reader
|
||||||
|
@ -209,6 +209,9 @@ class DIEHandler {
|
|||||||
virtual void ProcessAttributeString(enum DwarfAttribute attr,
|
virtual void ProcessAttributeString(enum DwarfAttribute attr,
|
||||||
enum DwarfForm form,
|
enum DwarfForm form,
|
||||||
const std::string& data) { }
|
const std::string& data) { }
|
||||||
|
virtual void ProcessAttributeSignature(enum DwarfAttribute attr,
|
||||||
|
enum DwarfForm form,
|
||||||
|
uint64 signture) { }
|
||||||
|
|
||||||
// Once we have reported all the DIE's attributes' values, we call
|
// Once we have reported all the DIE's attributes' values, we call
|
||||||
// this member function. If it returns false, we skip all the DIE's
|
// this member function. If it returns false, we skip all the DIE's
|
||||||
@ -314,6 +317,10 @@ class DIEDispatcher: public Dwarf2Handler {
|
|||||||
enum DwarfAttribute attr,
|
enum DwarfAttribute attr,
|
||||||
enum DwarfForm form,
|
enum DwarfForm form,
|
||||||
const std::string &data);
|
const std::string &data);
|
||||||
|
void ProcessAttributeSignature(uint64 offset,
|
||||||
|
enum DwarfAttribute attr,
|
||||||
|
enum DwarfForm form,
|
||||||
|
uint64 signature);
|
||||||
void EndDIE(uint64 offset);
|
void EndDIE(uint64 offset);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -71,6 +71,8 @@ class MockDIEHandler: public DIEHandler {
|
|||||||
void(DwarfAttribute, DwarfForm, const char *, uint64));
|
void(DwarfAttribute, DwarfForm, const char *, uint64));
|
||||||
MOCK_METHOD3(ProcessAttributeString,
|
MOCK_METHOD3(ProcessAttributeString,
|
||||||
void(DwarfAttribute, DwarfForm, const string &));
|
void(DwarfAttribute, DwarfForm, const string &));
|
||||||
|
MOCK_METHOD3(ProcessAttributeSignature,
|
||||||
|
void(DwarfAttribute, DwarfForm, uint64));
|
||||||
MOCK_METHOD0(EndAttributes, bool());
|
MOCK_METHOD0(EndAttributes, bool());
|
||||||
MOCK_METHOD3(FindChildHandler, DIEHandler *(uint64, DwarfTag,
|
MOCK_METHOD3(FindChildHandler, DIEHandler *(uint64, DwarfTag,
|
||||||
const AttributeList &));
|
const AttributeList &));
|
||||||
@ -89,6 +91,8 @@ class MockRootDIEHandler: public RootDIEHandler {
|
|||||||
void(DwarfAttribute, DwarfForm, const char *, uint64));
|
void(DwarfAttribute, DwarfForm, const char *, uint64));
|
||||||
MOCK_METHOD3(ProcessAttributeString,
|
MOCK_METHOD3(ProcessAttributeString,
|
||||||
void(DwarfAttribute, DwarfForm, const string &));
|
void(DwarfAttribute, DwarfForm, const string &));
|
||||||
|
MOCK_METHOD3(ProcessAttributeSignature,
|
||||||
|
void(DwarfAttribute, DwarfForm, uint64));
|
||||||
MOCK_METHOD0(EndAttributes, bool());
|
MOCK_METHOD0(EndAttributes, bool());
|
||||||
MOCK_METHOD3(FindChildHandler, DIEHandler *(uint64, DwarfTag,
|
MOCK_METHOD3(FindChildHandler, DIEHandler *(uint64, DwarfTag,
|
||||||
const AttributeList &));
|
const AttributeList &));
|
||||||
@ -244,6 +248,11 @@ TEST(Dwarf2DIEHandler, PassAttributeValues) {
|
|||||||
(DwarfForm) 0x15762fec,
|
(DwarfForm) 0x15762fec,
|
||||||
StrEq(str)))
|
StrEq(str)))
|
||||||
.WillOnce(Return());
|
.WillOnce(Return());
|
||||||
|
EXPECT_CALL(mock_root_handler,
|
||||||
|
ProcessAttributeSignature((DwarfAttribute) 0x58790d72,
|
||||||
|
(DwarfForm) 0x4159f138,
|
||||||
|
0x94682463613e6a5fULL))
|
||||||
|
.WillOnce(Return());
|
||||||
EXPECT_CALL(mock_root_handler, EndAttributes())
|
EXPECT_CALL(mock_root_handler, EndAttributes())
|
||||||
.WillOnce(Return(true));
|
.WillOnce(Return(true));
|
||||||
EXPECT_CALL(mock_root_handler, FindChildHandler(_, _, _))
|
EXPECT_CALL(mock_root_handler, FindChildHandler(_, _, _))
|
||||||
@ -285,6 +294,10 @@ TEST(Dwarf2DIEHandler, PassAttributeValues) {
|
|||||||
(DwarfAttribute) 0x310ed065,
|
(DwarfAttribute) 0x310ed065,
|
||||||
(DwarfForm) 0x15762fec,
|
(DwarfForm) 0x15762fec,
|
||||||
str);
|
str);
|
||||||
|
die_dispatcher.ProcessAttributeSignature(0xe2222da01e29f2a9LL,
|
||||||
|
(DwarfAttribute) 0x58790d72,
|
||||||
|
(DwarfForm) 0x4159f138,
|
||||||
|
0x94682463613e6a5fULL);
|
||||||
|
|
||||||
// Finish the root DIE (and thus the CU).
|
// Finish the root DIE (and thus the CU).
|
||||||
die_dispatcher.EndDIE(0xe2222da01e29f2a9LL);
|
die_dispatcher.EndDIE(0xe2222da01e29f2a9LL);
|
||||||
|
@ -143,7 +143,13 @@ enum DwarfForm {
|
|||||||
DW_FORM_ref4 = 0x13,
|
DW_FORM_ref4 = 0x13,
|
||||||
DW_FORM_ref8 = 0x14,
|
DW_FORM_ref8 = 0x14,
|
||||||
DW_FORM_ref_udata = 0x15,
|
DW_FORM_ref_udata = 0x15,
|
||||||
DW_FORM_indirect = 0x16
|
DW_FORM_indirect = 0x16,
|
||||||
|
|
||||||
|
// Added in DWARF 4:
|
||||||
|
DW_FORM_sec_offset = 0x17,
|
||||||
|
DW_FORM_exprloc = 0x18,
|
||||||
|
DW_FORM_flag_present = 0x19,
|
||||||
|
DW_FORM_ref_sig8 = 0x20
|
||||||
};
|
};
|
||||||
|
|
||||||
// Attribute names and codes
|
// Attribute names and codes
|
||||||
|
@ -151,6 +151,8 @@ const char* CompilationUnit::SkipAttribute(const char* start,
|
|||||||
start += len;
|
start += len;
|
||||||
return SkipAttribute(start, form);
|
return SkipAttribute(start, form);
|
||||||
|
|
||||||
|
case DW_FORM_flag_present:
|
||||||
|
return start;
|
||||||
case DW_FORM_data1:
|
case DW_FORM_data1:
|
||||||
case DW_FORM_flag:
|
case DW_FORM_flag:
|
||||||
case DW_FORM_ref1:
|
case DW_FORM_ref1:
|
||||||
@ -163,6 +165,7 @@ const char* CompilationUnit::SkipAttribute(const char* start,
|
|||||||
return start + 4;
|
return start + 4;
|
||||||
case DW_FORM_ref8:
|
case DW_FORM_ref8:
|
||||||
case DW_FORM_data8:
|
case DW_FORM_data8:
|
||||||
|
case DW_FORM_ref_sig8:
|
||||||
return start + 8;
|
return start + 8;
|
||||||
case DW_FORM_string:
|
case DW_FORM_string:
|
||||||
return start + strlen(start) + 1;
|
return start + strlen(start) + 1;
|
||||||
@ -192,11 +195,13 @@ const char* CompilationUnit::SkipAttribute(const char* start,
|
|||||||
return start + 2 + reader_->ReadTwoBytes(start);
|
return start + 2 + reader_->ReadTwoBytes(start);
|
||||||
case DW_FORM_block4:
|
case DW_FORM_block4:
|
||||||
return start + 4 + reader_->ReadFourBytes(start);
|
return start + 4 + reader_->ReadFourBytes(start);
|
||||||
case DW_FORM_block: {
|
case DW_FORM_block:
|
||||||
|
case DW_FORM_exprloc: {
|
||||||
uint64 size = reader_->ReadUnsignedLEB128(start, &len);
|
uint64 size = reader_->ReadUnsignedLEB128(start, &len);
|
||||||
return start + size + len;
|
return start + size + len;
|
||||||
}
|
}
|
||||||
case DW_FORM_strp:
|
case DW_FORM_strp:
|
||||||
|
case DW_FORM_sec_offset:
|
||||||
return start + reader_->OffsetSize();
|
return start + reader_->OffsetSize();
|
||||||
}
|
}
|
||||||
fprintf(stderr,"Unhandled form type");
|
fprintf(stderr,"Unhandled form type");
|
||||||
@ -310,6 +315,9 @@ const char* CompilationUnit::ProcessAttribute(
|
|||||||
start += len;
|
start += len;
|
||||||
return ProcessAttribute(dieoffset, start, attr, form);
|
return ProcessAttribute(dieoffset, start, attr, form);
|
||||||
|
|
||||||
|
case DW_FORM_flag_present:
|
||||||
|
handler_->ProcessAttributeUnsigned(dieoffset, attr, form, 1);
|
||||||
|
return start;
|
||||||
case DW_FORM_data1:
|
case DW_FORM_data1:
|
||||||
case DW_FORM_flag:
|
case DW_FORM_flag:
|
||||||
handler_->ProcessAttributeUnsigned(dieoffset, attr, form,
|
handler_->ProcessAttributeUnsigned(dieoffset, attr, form,
|
||||||
@ -347,6 +355,10 @@ const char* CompilationUnit::ProcessAttribute(
|
|||||||
handler_->ProcessAttributeUnsigned(dieoffset, attr, form,
|
handler_->ProcessAttributeUnsigned(dieoffset, attr, form,
|
||||||
reader_->ReadAddress(start));
|
reader_->ReadAddress(start));
|
||||||
return start + reader_->AddressSize();
|
return start + reader_->AddressSize();
|
||||||
|
case DW_FORM_sec_offset:
|
||||||
|
handler_->ProcessAttributeUnsigned(dieoffset, attr, form,
|
||||||
|
reader_->ReadOffset(start));
|
||||||
|
return start + reader_->OffsetSize();
|
||||||
|
|
||||||
case DW_FORM_ref1:
|
case DW_FORM_ref1:
|
||||||
handler_->ProcessAttributeReference(dieoffset, attr, form,
|
handler_->ProcessAttributeReference(dieoffset, attr, form,
|
||||||
@ -388,6 +400,10 @@ const char* CompilationUnit::ProcessAttribute(
|
|||||||
return start + reader_->OffsetSize();
|
return start + reader_->OffsetSize();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case DW_FORM_ref_sig8:
|
||||||
|
handler_->ProcessAttributeSignature(dieoffset, attr, form,
|
||||||
|
reader_->ReadEightBytes(start));
|
||||||
|
return start + 8;
|
||||||
|
|
||||||
case DW_FORM_block1: {
|
case DW_FORM_block1: {
|
||||||
uint64 datalen = reader_->ReadOneByte(start);
|
uint64 datalen = reader_->ReadOneByte(start);
|
||||||
@ -407,7 +423,8 @@ const char* CompilationUnit::ProcessAttribute(
|
|||||||
datalen);
|
datalen);
|
||||||
return start + 4 + datalen;
|
return start + 4 + datalen;
|
||||||
}
|
}
|
||||||
case DW_FORM_block: {
|
case DW_FORM_block:
|
||||||
|
case DW_FORM_exprloc: {
|
||||||
uint64 datalen = reader_->ReadUnsignedLEB128(start, &len);
|
uint64 datalen = reader_->ReadUnsignedLEB128(start, &len);
|
||||||
handler_->ProcessAttributeBuffer(dieoffset, attr, form, start + len,
|
handler_->ProcessAttributeBuffer(dieoffset, attr, form, start + len,
|
||||||
datalen);
|
datalen);
|
||||||
|
@ -393,6 +393,15 @@ class Dwarf2Handler {
|
|||||||
enum DwarfForm form,
|
enum DwarfForm form,
|
||||||
const std::string& data) { }
|
const std::string& data) { }
|
||||||
|
|
||||||
|
// Called when we have an attribute whose value is the 64-bit signature
|
||||||
|
// of a type unit in the .debug_types section. OFFSET is the offset of
|
||||||
|
// the DIE whose attribute we're reporting. ATTR and FORM are the
|
||||||
|
// attribute's name and form. SIGNATURE is the type unit's signature.
|
||||||
|
virtual void ProcessAttributeSignature(uint64 offset,
|
||||||
|
enum DwarfAttribute attr,
|
||||||
|
enum DwarfForm form,
|
||||||
|
uint64 signature) { }
|
||||||
|
|
||||||
// Called when finished processing the DIE at OFFSET.
|
// Called when finished processing the DIE at OFFSET.
|
||||||
// Because DWARF2/3 specifies a tree of DIEs, you may get starts
|
// Because DWARF2/3 specifies a tree of DIEs, you may get starts
|
||||||
// before ends of the previous DIE, as we process children before
|
// before ends of the previous DIE, as we process children before
|
||||||
|
@ -99,6 +99,10 @@ class MockDwarf2Handler: public Dwarf2Handler {
|
|||||||
enum DwarfAttribute attr,
|
enum DwarfAttribute attr,
|
||||||
enum DwarfForm form,
|
enum DwarfForm form,
|
||||||
const std::string& data));
|
const std::string& data));
|
||||||
|
MOCK_METHOD4(ProcessAttributeSignature, void(uint64 offset,
|
||||||
|
DwarfAttribute attr,
|
||||||
|
enum DwarfForm form,
|
||||||
|
uint64 signature));
|
||||||
MOCK_METHOD1(EndDIE, void(uint64 offset));
|
MOCK_METHOD1(EndDIE, void(uint64 offset));
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -251,9 +255,9 @@ struct DwarfFormsFixture: public DIEFixture {
|
|||||||
// containing one childless DIE of the given tag, in the sequence s. Stop
|
// containing one childless DIE of the given tag, in the sequence s. Stop
|
||||||
// just before the expectations.
|
// just before the expectations.
|
||||||
void ExpectBeginCompilationUnit(const DwarfHeaderParams ¶ms,
|
void ExpectBeginCompilationUnit(const DwarfHeaderParams ¶ms,
|
||||||
DwarfTag tag) {
|
DwarfTag tag, uint64 offset=0) {
|
||||||
EXPECT_CALL(handler,
|
EXPECT_CALL(handler,
|
||||||
StartCompilationUnit(0, params.address_size,
|
StartCompilationUnit(offset, params.address_size,
|
||||||
params.format_size, _,
|
params.format_size, _,
|
||||||
params.version))
|
params.version))
|
||||||
.InSequence(s)
|
.InSequence(s)
|
||||||
@ -269,11 +273,11 @@ struct DwarfFormsFixture: public DIEFixture {
|
|||||||
.WillOnce(Return());
|
.WillOnce(Return());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ParseCompilationUnit(const DwarfHeaderParams ¶ms) {
|
void ParseCompilationUnit(const DwarfHeaderParams ¶ms, uint64 offset=0) {
|
||||||
ByteReader byte_reader(params.endianness == kLittleEndian ?
|
ByteReader byte_reader(params.endianness == kLittleEndian ?
|
||||||
ENDIANNESS_LITTLE : ENDIANNESS_BIG);
|
ENDIANNESS_LITTLE : ENDIANNESS_BIG);
|
||||||
CompilationUnit parser(MakeSectionMap(), 0, &byte_reader, &handler);
|
CompilationUnit parser(MakeSectionMap(), offset, &byte_reader, &handler);
|
||||||
EXPECT_EQ(parser.Start(), info_contents.size());
|
EXPECT_EQ(offset + parser.Start(), info_contents.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
// The sequence to which the fixture's methods append expectations.
|
// The sequence to which the fixture's methods append expectations.
|
||||||
@ -347,6 +351,111 @@ TEST_P(DwarfForms, block2) {
|
|||||||
ParseCompilationUnit(GetParam());
|
ParseCompilationUnit(GetParam());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_P(DwarfForms, flag_present) {
|
||||||
|
StartSingleAttributeDIE(GetParam(), (DwarfTag) 0x3e449ac2,
|
||||||
|
(DwarfAttribute) 0x359d1972,
|
||||||
|
dwarf2reader::DW_FORM_flag_present);
|
||||||
|
// DW_FORM_flag_present occupies no space in the DIE.
|
||||||
|
info.Finish();
|
||||||
|
|
||||||
|
ExpectBeginCompilationUnit(GetParam(), (DwarfTag) 0x3e449ac2);
|
||||||
|
EXPECT_CALL(handler,
|
||||||
|
ProcessAttributeUnsigned(_, (DwarfAttribute) 0x359d1972,
|
||||||
|
dwarf2reader::DW_FORM_flag_present,
|
||||||
|
1))
|
||||||
|
.InSequence(s)
|
||||||
|
.WillOnce(Return());
|
||||||
|
ExpectEndCompilationUnit();
|
||||||
|
|
||||||
|
ParseCompilationUnit(GetParam());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_P(DwarfForms, sec_offset) {
|
||||||
|
StartSingleAttributeDIE(GetParam(), (DwarfTag) 0x1d971689,
|
||||||
|
(DwarfAttribute) 0xa060bfd1,
|
||||||
|
dwarf2reader::DW_FORM_sec_offset);
|
||||||
|
u_int64_t value;
|
||||||
|
if (GetParam().format_size == 4) {
|
||||||
|
value = 0xacc9c388;
|
||||||
|
info.D32(value);
|
||||||
|
} else {
|
||||||
|
value = 0xcffe5696ffe3ed0aULL;
|
||||||
|
info.D64(value);
|
||||||
|
}
|
||||||
|
info.Finish();
|
||||||
|
|
||||||
|
ExpectBeginCompilationUnit(GetParam(), (DwarfTag) 0x1d971689);
|
||||||
|
EXPECT_CALL(handler, ProcessAttributeUnsigned(_, (DwarfAttribute) 0xa060bfd1,
|
||||||
|
dwarf2reader::DW_FORM_sec_offset,
|
||||||
|
value))
|
||||||
|
.InSequence(s)
|
||||||
|
.WillOnce(Return());
|
||||||
|
ExpectEndCompilationUnit();
|
||||||
|
|
||||||
|
ParseCompilationUnit(GetParam());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_P(DwarfForms, exprloc) {
|
||||||
|
StartSingleAttributeDIE(GetParam(), (DwarfTag) 0xb6d167bb,
|
||||||
|
(DwarfAttribute) 0xba3ae5cb,
|
||||||
|
dwarf2reader::DW_FORM_exprloc);
|
||||||
|
info.ULEB128(29)
|
||||||
|
.Append(29, 173);
|
||||||
|
info.Finish();
|
||||||
|
|
||||||
|
ExpectBeginCompilationUnit(GetParam(), (DwarfTag) 0xb6d167bb);
|
||||||
|
EXPECT_CALL(handler, ProcessAttributeBuffer(_, (DwarfAttribute) 0xba3ae5cb,
|
||||||
|
dwarf2reader::DW_FORM_exprloc,
|
||||||
|
Pointee(173), 29))
|
||||||
|
.InSequence(s)
|
||||||
|
.WillOnce(Return());
|
||||||
|
ExpectEndCompilationUnit();
|
||||||
|
|
||||||
|
ParseCompilationUnit(GetParam());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_P(DwarfForms, ref_sig8) {
|
||||||
|
StartSingleAttributeDIE(GetParam(), (DwarfTag) 0x253e7b2b,
|
||||||
|
(DwarfAttribute) 0xd708d908,
|
||||||
|
dwarf2reader::DW_FORM_ref_sig8);
|
||||||
|
info.D64(0xf72fa0cb6ddcf9d6ULL);
|
||||||
|
info.Finish();
|
||||||
|
|
||||||
|
ExpectBeginCompilationUnit(GetParam(), (DwarfTag) 0x253e7b2b);
|
||||||
|
EXPECT_CALL(handler, ProcessAttributeSignature(_, (DwarfAttribute) 0xd708d908,
|
||||||
|
dwarf2reader::DW_FORM_ref_sig8,
|
||||||
|
0xf72fa0cb6ddcf9d6ULL))
|
||||||
|
.InSequence(s)
|
||||||
|
.WillOnce(Return());
|
||||||
|
ExpectEndCompilationUnit();
|
||||||
|
|
||||||
|
ParseCompilationUnit(GetParam());
|
||||||
|
}
|
||||||
|
|
||||||
|
// A value passed to ProcessAttributeSignature is just an absolute number,
|
||||||
|
// not an offset within the compilation unit as most of the other
|
||||||
|
// DW_FORM_ref forms are. Check that the reader doesn't try to apply any
|
||||||
|
// offset to the signature, by reading it from a compilation unit that does
|
||||||
|
// not start at the beginning of the section.
|
||||||
|
TEST_P(DwarfForms, ref_sig8_not_first) {
|
||||||
|
info.Append(98, '*');
|
||||||
|
StartSingleAttributeDIE(GetParam(), (DwarfTag) 0x253e7b2b,
|
||||||
|
(DwarfAttribute) 0xd708d908,
|
||||||
|
dwarf2reader::DW_FORM_ref_sig8);
|
||||||
|
info.D64(0xf72fa0cb6ddcf9d6ULL);
|
||||||
|
info.Finish();
|
||||||
|
|
||||||
|
ExpectBeginCompilationUnit(GetParam(), (DwarfTag) 0x253e7b2b, 98);
|
||||||
|
EXPECT_CALL(handler, ProcessAttributeSignature(_, (DwarfAttribute) 0xd708d908,
|
||||||
|
dwarf2reader::DW_FORM_ref_sig8,
|
||||||
|
0xf72fa0cb6ddcf9d6ULL))
|
||||||
|
.InSequence(s)
|
||||||
|
.WillOnce(Return());
|
||||||
|
ExpectEndCompilationUnit();
|
||||||
|
|
||||||
|
ParseCompilationUnit(GetParam(), 98);
|
||||||
|
}
|
||||||
|
|
||||||
// Tests for the other attribute forms could go here.
|
// Tests for the other attribute forms could go here.
|
||||||
|
|
||||||
INSTANTIATE_TEST_CASE_P(
|
INSTANTIATE_TEST_CASE_P(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user