1 // Copyright 2012 Google LLC
2 //
3 // Redistribution and use in source and binary forms, with or without
4 // modification, are permitted provided that the following conditions are
5 // met:
6 //
7 // * Redistributions of source code must retain the above copyright
8 // notice, this list of conditions and the following disclaimer.
9 // * Redistributions in binary form must reproduce the above
10 // copyright notice, this list of conditions and the following disclaimer
11 // in the documentation and/or other materials provided with the
12 // distribution.
13 // * Neither the name of Google LLC nor the names of its
14 // contributors may be used to endorse or promote products derived from
15 // this software without specific prior written permission.
16 //
17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
29 // Original author: Jim Blandy <[email protected]> <[email protected]>
30
31 // dwarf2reader_die_unittest.cc: Unit tests for google_breakpad::CompilationUnit
32
33 #ifdef HAVE_CONFIG_H
34 #include <config.h> // Must come first
35 #endif
36
37 #include <stdint.h>
38 #include <stdlib.h>
39
40 #include <iostream>
41 #include <string>
42 #include <vector>
43
44 #include "breakpad_googletest_includes.h"
45 #include "common/dwarf/bytereader-inl.h"
46 #include "common/dwarf/dwarf2reader_test_common.h"
47 #include "common/dwarf/dwarf2reader.h"
48 #include "common/using_std_string.h"
49 #include "google_breakpad/common/breakpad_types.h"
50
51 using google_breakpad::test_assembler::Endianness;
52 using google_breakpad::test_assembler::Label;
53 using google_breakpad::test_assembler::Section;
54 using google_breakpad::test_assembler::kBigEndian;
55 using google_breakpad::test_assembler::kLittleEndian;
56
57 using google_breakpad::ByteReader;
58 using google_breakpad::CompilationUnit;
59 using google_breakpad::Dwarf2Handler;
60 using google_breakpad::DwarfAttribute;
61 using google_breakpad::DwarfForm;
62 using google_breakpad::DwarfHasChild;
63 using google_breakpad::DwarfTag;
64 using google_breakpad::ENDIANNESS_BIG;
65 using google_breakpad::ENDIANNESS_LITTLE;
66 using google_breakpad::SectionMap;
67
68 using std::vector;
69 using testing::InSequence;
70 using testing::Pointee;
71 using testing::Return;
72 using testing::Sequence;
73 using testing::Test;
74 using testing::TestWithParam;
75 using testing::_;
76
77 class MockDwarf2Handler: public Dwarf2Handler {
78 public:
79 MOCK_METHOD5(StartCompilationUnit, bool(uint64_t offset, uint8_t address_size,
80 uint8_t offset_size,
81 uint64_t cu_length,
82 uint8_t dwarf_version));
83 MOCK_METHOD2(StartDIE, bool(uint64_t offset, enum DwarfTag tag));
84 MOCK_METHOD4(ProcessAttributeUnsigned, void(uint64_t offset,
85 DwarfAttribute attr,
86 enum DwarfForm form,
87 uint64_t data));
88 MOCK_METHOD4(ProcessAttributeSigned, void(uint64_t offset,
89 enum DwarfAttribute attr,
90 enum DwarfForm form,
91 int64_t data));
92 MOCK_METHOD4(ProcessAttributeReference, void(uint64_t offset,
93 enum DwarfAttribute attr,
94 enum DwarfForm form,
95 uint64_t data));
96 MOCK_METHOD5(ProcessAttributeBuffer, void(uint64_t offset,
97 enum DwarfAttribute attr,
98 enum DwarfForm form,
99 const uint8_t* data,
100 uint64_t len));
101 MOCK_METHOD4(ProcessAttributeString, void(uint64_t offset,
102 enum DwarfAttribute attr,
103 enum DwarfForm form,
104 const string& data));
105 MOCK_METHOD4(ProcessAttributeSignature, void(uint64_t offset,
106 DwarfAttribute attr,
107 enum DwarfForm form,
108 uint64_t signature));
109 MOCK_METHOD1(EndDIE, void(uint64_t offset));
110 };
111
112 struct DIEFixture {
113
DIEFixtureDIEFixture114 DIEFixture() {
115 // Fix the initial offset of the .debug_info and .debug_abbrev sections.
116 info.start() = 0;
117 abbrevs.start() = 0;
118
119 // Default expectations for the data handler.
120 EXPECT_CALL(handler, StartCompilationUnit(_, _, _, _, _)).Times(0);
121 EXPECT_CALL(handler, StartDIE(_, _)).Times(0);
122 EXPECT_CALL(handler, ProcessAttributeUnsigned(_, _, _, _)).Times(0);
123 EXPECT_CALL(handler, ProcessAttributeSigned(_, _, _, _)).Times(0);
124 EXPECT_CALL(handler, ProcessAttributeReference(_, _, _, _)).Times(0);
125 EXPECT_CALL(handler, ProcessAttributeBuffer(_, _, _, _, _)).Times(0);
126 EXPECT_CALL(handler, ProcessAttributeString(_, _, _, _)).Times(0);
127 EXPECT_CALL(handler, EndDIE(_)).Times(0);
128 }
129
130 // Return a reference to a section map whose .debug_info section refers
131 // to |info|, and whose .debug_abbrev section refers to |abbrevs|. This
132 // function returns a reference to the same SectionMap each time; new
133 // calls wipe out maps established by earlier calls.
MakeSectionMapDIEFixture134 const SectionMap& MakeSectionMap() {
135 // Copy the sections' contents into strings that will live as long as
136 // the map itself.
137 assert(info.GetContents(&info_contents));
138 assert(abbrevs.GetContents(&abbrevs_contents));
139 section_map.clear();
140 section_map[".debug_info"].first
141 = reinterpret_cast<const uint8_t*>(info_contents.data());
142 section_map[".debug_info"].second = info_contents.size();
143 section_map[".debug_abbrev"].first
144 = reinterpret_cast<const uint8_t*>(abbrevs_contents.data());
145 section_map[".debug_abbrev"].second = abbrevs_contents.size();
146 return section_map;
147 }
148
149 TestCompilationUnit info;
150 TestAbbrevTable abbrevs;
151 MockDwarf2Handler handler;
152 string abbrevs_contents, info_contents;
153 SectionMap section_map;
154 };
155
156 struct DwarfHeaderParams {
DwarfHeaderParamsDwarfHeaderParams157 DwarfHeaderParams(Endianness endianness, size_t format_size,
158 int version, size_t address_size, int header_type)
159 : endianness(endianness), format_size(format_size),
160 version(version), address_size(address_size), header_type(header_type)
161 { }
162 Endianness endianness;
163 size_t format_size; // 4-byte or 8-byte DWARF offsets
164 int version;
165 size_t address_size;
166 int header_type; // DW_UT_{compile, type, partial, skeleton, etc}
167 };
168
169 class DwarfHeader: public DIEFixture,
170 public TestWithParam<DwarfHeaderParams> { };
171
TEST_P(DwarfHeader,Header)172 TEST_P(DwarfHeader, Header) {
173 Label abbrev_table = abbrevs.Here();
174 abbrevs.Abbrev(1, google_breakpad::DW_TAG_compile_unit,
175 google_breakpad::DW_children_yes)
176 .Attribute(google_breakpad::DW_AT_name, google_breakpad::DW_FORM_string)
177 .EndAbbrev()
178 .EndTable();
179
180 info.set_format_size(GetParam().format_size);
181 info.set_endianness(GetParam().endianness);
182
183 info.Header(GetParam().version, abbrev_table, GetParam().address_size,
184 google_breakpad::DW_UT_compile)
185 .ULEB128(1) // DW_TAG_compile_unit, with children
186 .AppendCString("sam") // DW_AT_name, DW_FORM_string
187 .D8(0); // end of children
188 info.Finish();
189
190 {
191 InSequence s;
192 EXPECT_CALL(handler,
193 StartCompilationUnit(0, GetParam().address_size,
194 GetParam().format_size, _,
195 GetParam().version))
196 .WillOnce(Return(true));
197 EXPECT_CALL(handler, StartDIE(_, google_breakpad::DW_TAG_compile_unit))
198 .WillOnce(Return(true));
199 EXPECT_CALL(handler, ProcessAttributeString(_, google_breakpad::DW_AT_name,
200 google_breakpad::DW_FORM_string,
201 "sam"))
202 .WillOnce(Return());
203 EXPECT_CALL(handler, EndDIE(_))
204 .WillOnce(Return());
205 }
206
207 ByteReader byte_reader(GetParam().endianness == kLittleEndian ?
208 ENDIANNESS_LITTLE : ENDIANNESS_BIG);
209 CompilationUnit parser("", MakeSectionMap(), 0, &byte_reader, &handler);
210 EXPECT_EQ(parser.Start(), info_contents.size());
211 }
212
TEST_P(DwarfHeader,TypeUnitHeader)213 TEST_P(DwarfHeader, TypeUnitHeader) {
214 Label abbrev_table = abbrevs.Here();
215 int version = 5;
216 abbrevs.Abbrev(1, google_breakpad::DW_TAG_type_unit,
217 google_breakpad::DW_children_yes)
218 .Attribute(google_breakpad::DW_AT_name, google_breakpad::DW_FORM_string)
219 .EndAbbrev()
220 .EndTable();
221
222 info.set_format_size(GetParam().format_size);
223 info.set_endianness(GetParam().endianness);
224
225 info.Header(version, abbrev_table, GetParam().address_size,
226 google_breakpad::DW_UT_type)
227 .ULEB128(0x41) // DW_TAG_type_unit, with children
228 .AppendCString("sam") // DW_AT_name, DW_FORM_string
229 .D8(0); // end of children
230 info.Finish();
231
232 {
233 InSequence s;
234 EXPECT_CALL(handler,
235 StartCompilationUnit(0, GetParam().address_size,
236 GetParam().format_size, _,
237 version))
238 .WillOnce(Return(true));
239 // If the type unit is handled properly, these calls will be skipped.
240 EXPECT_CALL(handler, StartDIE(_, google_breakpad::DW_TAG_type_unit))
241 .Times(0);
242 EXPECT_CALL(handler, ProcessAttributeString(_, google_breakpad::DW_AT_name,
243 google_breakpad::DW_FORM_string,
244 "sam"))
245 .Times(0);
246 EXPECT_CALL(handler, EndDIE(_))
247 .Times(0);
248 }
249
250 ByteReader byte_reader(GetParam().endianness == kLittleEndian ?
251 ENDIANNESS_LITTLE : ENDIANNESS_BIG);
252 CompilationUnit parser("", MakeSectionMap(), 0, &byte_reader, &handler);
253 EXPECT_EQ(parser.Start(), info_contents.size());
254 }
255
256 INSTANTIATE_TEST_SUITE_P(
257 HeaderVariants, DwarfHeader,
258 ::testing::Values(DwarfHeaderParams(kLittleEndian, 4, 2, 4, 1),
259 DwarfHeaderParams(kLittleEndian, 4, 2, 8, 1),
260 DwarfHeaderParams(kLittleEndian, 4, 3, 4, 1),
261 DwarfHeaderParams(kLittleEndian, 4, 3, 8, 1),
262 DwarfHeaderParams(kLittleEndian, 4, 4, 4, 1),
263 DwarfHeaderParams(kLittleEndian, 4, 4, 8, 1),
264 DwarfHeaderParams(kLittleEndian, 8, 2, 4, 1),
265 DwarfHeaderParams(kLittleEndian, 8, 2, 8, 1),
266 DwarfHeaderParams(kLittleEndian, 8, 3, 4, 1),
267 DwarfHeaderParams(kLittleEndian, 8, 3, 8, 1),
268 DwarfHeaderParams(kLittleEndian, 8, 4, 4, 1),
269 DwarfHeaderParams(kLittleEndian, 8, 4, 8, 1),
270 DwarfHeaderParams(kLittleEndian, 8, 5, 4, 1),
271 DwarfHeaderParams(kLittleEndian, 8, 5, 8, 1),
272 DwarfHeaderParams(kBigEndian, 4, 2, 4, 1),
273 DwarfHeaderParams(kBigEndian, 4, 2, 8, 1),
274 DwarfHeaderParams(kBigEndian, 4, 3, 4, 1),
275 DwarfHeaderParams(kBigEndian, 4, 3, 8, 1),
276 DwarfHeaderParams(kBigEndian, 4, 4, 4, 1),
277 DwarfHeaderParams(kBigEndian, 4, 4, 8, 1),
278 DwarfHeaderParams(kBigEndian, 8, 2, 4, 1),
279 DwarfHeaderParams(kBigEndian, 8, 2, 8, 1),
280 DwarfHeaderParams(kBigEndian, 8, 3, 4, 1),
281 DwarfHeaderParams(kBigEndian, 8, 3, 8, 1),
282 DwarfHeaderParams(kBigEndian, 8, 4, 4, 1),
283 DwarfHeaderParams(kBigEndian, 8, 4, 8, 1),
284 DwarfHeaderParams(kBigEndian, 8, 5, 4, 1),
285 DwarfHeaderParams(kBigEndian, 8, 5, 8, 1)));
286
287 struct DwarfFormsFixture: public DIEFixture {
288 // Start a compilation unit, as directed by |params|, containing one
289 // childless DIE of the given tag, with one attribute of the given name
290 // and form. The 'info' fixture member is left just after the abbrev
291 // code, waiting for the attribute value to be appended.
StartSingleAttributeDIEDwarfFormsFixture292 void StartSingleAttributeDIE(const DwarfHeaderParams& params,
293 DwarfTag tag, DwarfAttribute name,
294 DwarfForm form) {
295 // Create the abbreviation table.
296 Label abbrev_table = abbrevs.Here();
297 abbrevs.Abbrev(1, tag, google_breakpad::DW_children_no)
298 .Attribute(name, form)
299 .EndAbbrev()
300 .EndTable();
301
302 // Create the compilation unit, up to the attribute value.
303 info.set_format_size(params.format_size);
304 info.set_endianness(params.endianness);
305 info.Header(params.version, abbrev_table, params.address_size,
306 google_breakpad::DW_UT_compile)
307 .ULEB128(1); // abbrev code
308 }
309
310 // Set up handler to expect a compilation unit matching |params|,
311 // containing one childless DIE of the given tag, in the sequence s. Stop
312 // just before the expectations.
ExpectBeginCompilationUnitDwarfFormsFixture313 void ExpectBeginCompilationUnit(const DwarfHeaderParams& params,
314 DwarfTag tag, uint64_t offset=0) {
315 EXPECT_CALL(handler,
316 StartCompilationUnit(offset, params.address_size,
317 params.format_size, _,
318 params.version))
319 .InSequence(s)
320 .WillOnce(Return(true));
321 EXPECT_CALL(handler, StartDIE(_, tag))
322 .InSequence(s)
323 .WillOnce(Return(true));
324 }
325
ExpectEndCompilationUnitDwarfFormsFixture326 void ExpectEndCompilationUnit() {
327 EXPECT_CALL(handler, EndDIE(_))
328 .InSequence(s)
329 .WillOnce(Return());
330 }
331
ParseCompilationUnitDwarfFormsFixture332 void ParseCompilationUnit(const DwarfHeaderParams& params,
333 uint64_t offset=0) {
334 ByteReader byte_reader(params.endianness == kLittleEndian ?
335 ENDIANNESS_LITTLE : ENDIANNESS_BIG);
336 CompilationUnit parser("", MakeSectionMap(), offset, &byte_reader,
337 &handler);
338 EXPECT_EQ(offset + parser.Start(), info_contents.size());
339 }
340
341 // The sequence to which the fixture's methods append expectations.
342 Sequence s;
343 };
344
345 struct DwarfForms: public DwarfFormsFixture,
346 public TestWithParam<DwarfHeaderParams> { };
347
TEST_P(DwarfForms,addr)348 TEST_P(DwarfForms, addr) {
349 StartSingleAttributeDIE(GetParam(), google_breakpad::DW_TAG_compile_unit,
350 google_breakpad::DW_AT_low_pc,
351 google_breakpad::DW_FORM_addr);
352 uint64_t value;
353 if (GetParam().address_size == 4) {
354 value = 0xc8e9ffcc;
355 info.D32(value);
356 } else {
357 value = 0xe942517fc2768564ULL;
358 info.D64(value);
359 }
360 info.Finish();
361
362 ExpectBeginCompilationUnit(GetParam(), google_breakpad::DW_TAG_compile_unit);
363 EXPECT_CALL(handler, ProcessAttributeUnsigned(_, google_breakpad::DW_AT_low_pc,
364 google_breakpad::DW_FORM_addr,
365 value))
366 .InSequence(s)
367 .WillOnce(Return());
368 ExpectEndCompilationUnit();
369
370 ParseCompilationUnit(GetParam());
371 }
372
TEST_P(DwarfForms,strx1)373 TEST_P(DwarfForms, strx1) {
374 if (GetParam().version != 5) {
375 return;
376 }
377 Label abbrev_table = abbrevs.Here();
378 abbrevs.Abbrev(1, google_breakpad::DW_TAG_compile_unit,
379 google_breakpad::DW_children_no)
380 .Attribute(google_breakpad::DW_AT_name, google_breakpad::DW_FORM_strx1)
381 .Attribute(google_breakpad::DW_AT_low_pc, google_breakpad::DW_FORM_addr)
382 .Attribute(google_breakpad::DW_AT_str_offsets_base,
383 google_breakpad::DW_FORM_sec_offset)
384 .EndAbbrev()
385 .EndTable();
386
387 info.set_format_size(GetParam().format_size);
388 info.set_endianness(GetParam().endianness);
389 info.Header(GetParam().version, abbrev_table, GetParam().address_size,
390 google_breakpad::DW_UT_compile)
391 .ULEB128(1) // abbrev index
392 .D8(2); // string index
393
394 uint64_t value;
395 uint64_t offsets_base;
396 if (GetParam().address_size == 4) {
397 value = 0xc8e9ffcc;
398 offsets_base = 8;
399 info.D32(value); // low pc
400 info.D32(offsets_base); // str_offsets_base
401 } else {
402 value = 0xe942517fc2768564ULL;
403 offsets_base = 16;
404 info.D64(value); // low_pc
405 info.D64(offsets_base); // str_offsets_base
406 }
407 info.Finish();
408
409 Section debug_strings;
410 // no header, just a series of null-terminated strings.
411 debug_strings.AppendCString("apple"); // offset = 0
412 debug_strings.AppendCString("bird"); // offset = 6
413 debug_strings.AppendCString("canary"); // offset = 11
414 debug_strings.AppendCString("dinosaur"); // offset = 18
415
416 Section str_offsets;
417 str_offsets.set_endianness(GetParam().endianness);
418 // Header for .debug_str_offsets
419 if (GetParam().address_size == 4) {
420 str_offsets.D32(24); // section length (4 bytes)
421 } else {
422 str_offsets.D32(0xffffffff);
423 str_offsets.D64(48); // section length (12 bytes)
424 }
425 str_offsets.D16(GetParam().version); // version (2 bytes)
426 str_offsets.D16(0); // padding (2 bytes)
427
428 // .debug_str_offsets data (the offsets)
429 if (GetParam().address_size == 4) {
430 str_offsets.D32(0);
431 str_offsets.D32(6);
432 str_offsets.D32(11);
433 str_offsets.D32(18);
434 } else {
435 str_offsets.D64(0);
436 str_offsets.D64(6);
437 str_offsets.D64(11);
438 str_offsets.D64(18);
439 }
440
441
442 ExpectBeginCompilationUnit(GetParam(), google_breakpad::DW_TAG_compile_unit);
443 EXPECT_CALL(handler, ProcessAttributeString(_, google_breakpad::DW_AT_name,
444 google_breakpad::DW_FORM_strx1,
445 "bird"))
446 .WillOnce(Return());
447 EXPECT_CALL(handler, ProcessAttributeUnsigned(_, google_breakpad::DW_AT_low_pc,
448 google_breakpad::DW_FORM_addr,
449 value))
450 .InSequence(s)
451 .WillOnce(Return());
452 ExpectEndCompilationUnit();
453
454 ParseCompilationUnit(GetParam());
455 }
456
TEST_P(DwarfForms,block2_empty)457 TEST_P(DwarfForms, block2_empty) {
458 StartSingleAttributeDIE(GetParam(), (DwarfTag) 0x16e4d2f7,
459 (DwarfAttribute) 0xe52c4463,
460 google_breakpad::DW_FORM_block2);
461 info.D16(0);
462 info.Finish();
463
464 ExpectBeginCompilationUnit(GetParam(), (DwarfTag) 0x16e4d2f7);
465 EXPECT_CALL(handler, ProcessAttributeBuffer(_, (DwarfAttribute) 0xe52c4463,
466 google_breakpad::DW_FORM_block2,
467 _, 0))
468 .InSequence(s)
469 .WillOnce(Return());
470 ExpectEndCompilationUnit();
471
472 ParseCompilationUnit(GetParam());
473 }
474
TEST_P(DwarfForms,block2)475 TEST_P(DwarfForms, block2) {
476 StartSingleAttributeDIE(GetParam(), (DwarfTag) 0x16e4d2f7,
477 (DwarfAttribute) 0xe52c4463,
478 google_breakpad::DW_FORM_block2);
479 unsigned char data[258];
480 memset(data, '*', sizeof(data));
481 info.D16(sizeof(data))
482 .Append(data, sizeof(data));
483 info.Finish();
484
485 ExpectBeginCompilationUnit(GetParam(), (DwarfTag) 0x16e4d2f7);
486 EXPECT_CALL(handler, ProcessAttributeBuffer(_, (DwarfAttribute) 0xe52c4463,
487 google_breakpad::DW_FORM_block2,
488 Pointee('*'), 258))
489 .InSequence(s)
490 .WillOnce(Return());
491 ExpectEndCompilationUnit();
492
493 ParseCompilationUnit(GetParam());
494 }
495
TEST_P(DwarfForms,flag_present)496 TEST_P(DwarfForms, flag_present) {
497 StartSingleAttributeDIE(GetParam(), (DwarfTag) 0x3e449ac2,
498 (DwarfAttribute) 0x359d1972,
499 google_breakpad::DW_FORM_flag_present);
500 // DW_FORM_flag_present occupies no space in the DIE.
501 info.Finish();
502
503 ExpectBeginCompilationUnit(GetParam(), (DwarfTag) 0x3e449ac2);
504 EXPECT_CALL(handler,
505 ProcessAttributeUnsigned(_, (DwarfAttribute) 0x359d1972,
506 google_breakpad::DW_FORM_flag_present,
507 1))
508 .InSequence(s)
509 .WillOnce(Return());
510 ExpectEndCompilationUnit();
511
512 ParseCompilationUnit(GetParam());
513 }
514
TEST_P(DwarfForms,sec_offset)515 TEST_P(DwarfForms, sec_offset) {
516 StartSingleAttributeDIE(GetParam(), (DwarfTag) 0x1d971689,
517 (DwarfAttribute) 0xa060bfd1,
518 google_breakpad::DW_FORM_sec_offset);
519 uint64_t value;
520 if (GetParam().format_size == 4) {
521 value = 0xacc9c388;
522 info.D32(value);
523 } else {
524 value = 0xcffe5696ffe3ed0aULL;
525 info.D64(value);
526 }
527 info.Finish();
528
529 ExpectBeginCompilationUnit(GetParam(), (DwarfTag) 0x1d971689);
530 EXPECT_CALL(handler, ProcessAttributeUnsigned(_, (DwarfAttribute) 0xa060bfd1,
531 google_breakpad::DW_FORM_sec_offset,
532 value))
533 .InSequence(s)
534 .WillOnce(Return());
535 ExpectEndCompilationUnit();
536
537 ParseCompilationUnit(GetParam());
538 }
539
TEST_P(DwarfForms,exprloc)540 TEST_P(DwarfForms, exprloc) {
541 StartSingleAttributeDIE(GetParam(), (DwarfTag) 0xb6d167bb,
542 (DwarfAttribute) 0xba3ae5cb,
543 google_breakpad::DW_FORM_exprloc);
544 info.ULEB128(29)
545 .Append(29, 173);
546 info.Finish();
547
548 ExpectBeginCompilationUnit(GetParam(), (DwarfTag) 0xb6d167bb);
549 EXPECT_CALL(handler, ProcessAttributeBuffer(_, (DwarfAttribute) 0xba3ae5cb,
550 google_breakpad::DW_FORM_exprloc,
551 Pointee(173), 29))
552 .InSequence(s)
553 .WillOnce(Return());
554 ExpectEndCompilationUnit();
555
556 ParseCompilationUnit(GetParam());
557 }
558
TEST_P(DwarfForms,ref_sig8)559 TEST_P(DwarfForms, ref_sig8) {
560 StartSingleAttributeDIE(GetParam(), (DwarfTag) 0x253e7b2b,
561 (DwarfAttribute) 0xd708d908,
562 google_breakpad::DW_FORM_ref_sig8);
563 info.D64(0xf72fa0cb6ddcf9d6ULL);
564 info.Finish();
565
566 ExpectBeginCompilationUnit(GetParam(), (DwarfTag) 0x253e7b2b);
567 EXPECT_CALL(handler, ProcessAttributeSignature(_, (DwarfAttribute) 0xd708d908,
568 google_breakpad::DW_FORM_ref_sig8,
569 0xf72fa0cb6ddcf9d6ULL))
570 .InSequence(s)
571 .WillOnce(Return());
572 ExpectEndCompilationUnit();
573
574 ParseCompilationUnit(GetParam());
575 }
576
577 // A value passed to ProcessAttributeSignature is just an absolute number,
578 // not an offset within the compilation unit as most of the other
579 // DW_FORM_ref forms are. Check that the reader doesn't try to apply any
580 // offset to the signature, by reading it from a compilation unit that does
581 // not start at the beginning of the section.
TEST_P(DwarfForms,ref_sig8_not_first)582 TEST_P(DwarfForms, ref_sig8_not_first) {
583 info.Append(98, '*');
584 StartSingleAttributeDIE(GetParam(), (DwarfTag) 0x253e7b2b,
585 (DwarfAttribute) 0xd708d908,
586 google_breakpad::DW_FORM_ref_sig8);
587 info.D64(0xf72fa0cb6ddcf9d6ULL);
588 info.Finish();
589
590 ExpectBeginCompilationUnit(GetParam(), (DwarfTag) 0x253e7b2b, 98);
591 EXPECT_CALL(handler, ProcessAttributeSignature(_, (DwarfAttribute) 0xd708d908,
592 google_breakpad::DW_FORM_ref_sig8,
593 0xf72fa0cb6ddcf9d6ULL))
594 .InSequence(s)
595 .WillOnce(Return());
596 ExpectEndCompilationUnit();
597
598 ParseCompilationUnit(GetParam(), 98);
599 }
600
TEST_P(DwarfForms,implicit_const)601 TEST_P(DwarfForms, implicit_const) {
602 const DwarfHeaderParams& params = GetParam();
603 const uint64_t implicit_constant_value = 0x1234;
604 // Create the abbreviation table.
605 Label abbrev_table = abbrevs.Here();
606 abbrevs.Abbrev(1, (DwarfTag) 0x253e7b2b, google_breakpad::DW_children_no)
607 .Attribute((DwarfAttribute) 0xd708d908,
608 google_breakpad::DW_FORM_implicit_const)
609 .ULEB128(implicit_constant_value);
610 abbrevs.EndAbbrev().EndTable();
611
612 info.set_format_size(params.format_size);
613 info.set_endianness(params.endianness);
614 info.Header(params.version, abbrev_table, params.address_size,
615 google_breakpad::DW_UT_compile)
616 .ULEB128(1); // abbrev code
617 info.Finish();
618
619 ExpectBeginCompilationUnit(GetParam(), (DwarfTag) 0x253e7b2b);
620 EXPECT_CALL(handler,
621 ProcessAttributeUnsigned(_, (DwarfAttribute) 0xd708d908,
622 google_breakpad::DW_FORM_implicit_const,
623 implicit_constant_value))
624 .InSequence(s)
625 .WillOnce(Return());
626 ExpectEndCompilationUnit();
627
628 ParseCompilationUnit(GetParam());
629 }
630
631 // Tests for the other attribute forms could go here.
632
633 INSTANTIATE_TEST_SUITE_P(
634 HeaderVariants, DwarfForms,
635 ::testing::Values(DwarfHeaderParams(kLittleEndian, 4, 2, 4, 1),
636 DwarfHeaderParams(kLittleEndian, 4, 2, 8, 1),
637 DwarfHeaderParams(kLittleEndian, 4, 3, 4, 1),
638 DwarfHeaderParams(kLittleEndian, 4, 3, 8, 1),
639 DwarfHeaderParams(kLittleEndian, 4, 4, 4, 1),
640 DwarfHeaderParams(kLittleEndian, 4, 4, 8, 1),
641 DwarfHeaderParams(kLittleEndian, 8, 2, 4, 1),
642 DwarfHeaderParams(kLittleEndian, 8, 2, 8, 1),
643 DwarfHeaderParams(kLittleEndian, 8, 3, 4, 1),
644 DwarfHeaderParams(kLittleEndian, 8, 3, 8, 1),
645 DwarfHeaderParams(kLittleEndian, 8, 4, 4, 1),
646 DwarfHeaderParams(kLittleEndian, 8, 4, 8, 1),
647 DwarfHeaderParams(kBigEndian, 4, 2, 4, 1),
648 DwarfHeaderParams(kBigEndian, 4, 2, 8, 1),
649 DwarfHeaderParams(kBigEndian, 4, 3, 4, 1),
650 DwarfHeaderParams(kBigEndian, 4, 3, 8, 1),
651 DwarfHeaderParams(kBigEndian, 4, 4, 4, 1),
652 DwarfHeaderParams(kBigEndian, 4, 4, 8, 1),
653 DwarfHeaderParams(kBigEndian, 8, 2, 4, 1),
654 DwarfHeaderParams(kBigEndian, 8, 2, 8, 1),
655 DwarfHeaderParams(kBigEndian, 8, 3, 4, 1),
656 DwarfHeaderParams(kBigEndian, 8, 3, 8, 1),
657 DwarfHeaderParams(kBigEndian, 8, 4, 4, 1),
658 DwarfHeaderParams(kBigEndian, 8, 4, 8, 1)));
659
660 class MockRangeListHandler: public google_breakpad::RangeListHandler {
661 public:
662 MOCK_METHOD(void, AddRange, (uint64_t begin, uint64_t end));
663 MOCK_METHOD(void, Finish, ());
664 };
665
TEST(RangeList,Dwarf4ReadRangeList)666 TEST(RangeList, Dwarf4ReadRangeList) {
667 using google_breakpad::RangeListReader;
668 using google_breakpad::DW_FORM_sec_offset;
669
670 // Create a dwarf4 .debug_ranges section.
671 google_breakpad::test_assembler::Section ranges(kBigEndian);
672 std::string padding_offset = "padding offset";
673 ranges.Append(padding_offset);
674 const uint64_t section_offset = ranges.Size();
675 ranges.D32(1).D32(2); // (2, 3)
676 ranges.D32(0xFFFFFFFF).D32(3); // base_address = 3.
677 ranges.D32(1).D32(2); // (4, 5)
678 ranges.D32(0).D32(1); // (3, 4) An out of order entry is legal.
679 ranges.D32(0).D32(0); // End of range.
680
681 std::string section_contents;
682 ranges.GetContents(§ion_contents);
683
684 ByteReader byte_reader(ENDIANNESS_BIG);
685 byte_reader.SetAddressSize(4);
686
687 RangeListReader::CURangesInfo cu_info;
688 // Only set the fields that matter for dwarf 4.
689 cu_info.version_ = 4;
690 cu_info.base_address_ = 1;
691 cu_info.buffer_ = reinterpret_cast<const uint8_t*>(section_contents.data());
692 cu_info.size_ = section_contents.size();
693
694 MockRangeListHandler handler;
695 google_breakpad::RangeListReader range_list_reader(&byte_reader, &cu_info,
696 &handler);
697 EXPECT_CALL(handler, AddRange(2, 3));
698 EXPECT_CALL(handler, AddRange(4, 5));
699 EXPECT_CALL(handler, AddRange(3, 4));
700 EXPECT_CALL(handler, Finish());
701 EXPECT_TRUE(range_list_reader.ReadRanges(DW_FORM_sec_offset,
702 section_offset));
703 }
704
TEST(RangeList,Dwarf5ReadRangeList_rnglists)705 TEST(RangeList, Dwarf5ReadRangeList_rnglists) {
706 using google_breakpad::RangeListReader;
707 using google_breakpad::DW_RLE_base_addressx;
708 using google_breakpad::DW_RLE_startx_endx;
709 using google_breakpad::DW_RLE_startx_length;
710 using google_breakpad::DW_RLE_offset_pair;
711 using google_breakpad::DW_RLE_end_of_list;
712 using google_breakpad::DW_RLE_base_address;
713 using google_breakpad::DW_RLE_start_end;
714 using google_breakpad::DW_RLE_start_length;
715 using google_breakpad::DW_FORM_sec_offset;
716 using google_breakpad::DW_FORM_rnglistx;
717
718 // Size of header
719 const uint64_t header_size = 12;
720 // Size of length field in header
721 const uint64_t length_size = 4;
722
723 // .debug_addr for the indexed entries like startx.
724 Section addr;
725 addr.set_endianness(kBigEndian);
726 // Test addr_base handling with a padding address at 0.
727 addr.D32(0).D32(1).D32(2).D32(3).D32(4);
728 std::string addr_contents;
729 assert(addr.GetContents(&addr_contents));
730
731 // .debug_rnglists is the dwarf 5 section.
732 Section rnglists1(kBigEndian);
733 Section rnglists2(kBigEndian);
734
735 // First header and body.
736 Label section_size1;
737 rnglists1.Append(kBigEndian, length_size, section_size1);
738 rnglists1.D16(5); // Version
739 rnglists1.D8(4); // Address size
740 rnglists1.D8(0); // Segment selector size
741 rnglists1.D32(2); // Offset entry count
742 const uint64_t ranges_base_1 = rnglists1.Size();
743
744 // Offset entries.
745 Label range0;
746 rnglists1.Append(kBigEndian, 4, range0);
747 Label range1;
748 rnglists1.Append(kBigEndian, 4, range1);
749
750 // Range 0 (will be read via DW_AT_ranges, DW_FORM_rnglistx).
751 range0 = rnglists1.Size() - header_size;
752 rnglists1.D8(DW_RLE_base_addressx).ULEB128(0); // base_addr = 1
753 rnglists1.D8(DW_RLE_startx_endx).ULEB128(1).ULEB128(2); // [2, 3)
754 rnglists1.D8(DW_RLE_startx_length).ULEB128(3).ULEB128(1); // [4, 5)
755 rnglists1.D8(DW_RLE_offset_pair).ULEB128(5).ULEB128(6); // [6, 7)
756 rnglists1.D8(DW_RLE_end_of_list);
757
758 // Range 1 (will be read via DW_AT_ranges, DW_FORM_rnglistx).
759 range1 = rnglists1.Size() - header_size;
760 rnglists1.D8(DW_RLE_base_address).D32(8); // base_addr = 8
761 rnglists1.D8(DW_RLE_offset_pair).ULEB128(1).ULEB128(2); // [9, 10)
762 rnglists1.D8(DW_RLE_start_end).D32(10).D32(11); // [10, 11)
763 rnglists1.D8(DW_RLE_start_length).D32(12).ULEB128(1); // [12, 13)
764 rnglists1.D8(DW_RLE_end_of_list);
765 // The size doesn't include the size of length field itself.
766 section_size1 = rnglists1.Size() - length_size;
767
768 // Second header and body.
769 Label section_size2;
770 rnglists2.Append(kBigEndian, length_size, section_size2);
771 rnglists2.D16(5); // Version
772 rnglists2.D8(4); // Address size
773 rnglists2.D8(0); // Segment selector size
774 rnglists2.D32(2); // Offset entry count
775 const uint64_t ranges_base_2 = rnglists1.Size() + rnglists2.Size();
776
777 // Offset entries.
778 Label range2;
779 rnglists2.Append(kBigEndian, 4, range2);
780 Label range3;
781 rnglists2.Append(kBigEndian, 4, range3);
782
783 // Range 2 (will be read via DW_AT_ranges, DW_FORM_sec_offset).
784 range2 = rnglists2.Size() - header_size;
785 rnglists2.D8(DW_RLE_base_addressx).ULEB128(0); // base_addr = 1
786 rnglists2.D8(DW_RLE_startx_endx).ULEB128(1).ULEB128(2); // [2, 3)
787 rnglists2.D8(DW_RLE_startx_length).ULEB128(3).ULEB128(1); // [4, 5)
788 rnglists2.D8(DW_RLE_offset_pair).ULEB128(5).ULEB128(6); // [6, 7)
789 rnglists2.D8(DW_RLE_end_of_list);
790
791 // Range 3 (will be read via DW_AT_ranges, DW_FORM_rnglistx).
792 range3 = rnglists2.Size() - header_size;
793 rnglists2.D8(DW_RLE_base_address).D32(15); // base_addr = 15
794 rnglists2.D8(DW_RLE_offset_pair).ULEB128(1).ULEB128(2); // [16, 17)
795 rnglists2.D8(DW_RLE_start_end).D32(17).D32(18); // [17, 18)
796 rnglists2.D8(DW_RLE_start_length).D32(19).ULEB128(1); // [19, 20)
797 rnglists2.D8(DW_RLE_end_of_list);
798 // The size doesn't include the size of length field itself.
799 section_size2 = rnglists2.Size() - length_size;
800
801 rnglists1.Append(rnglists2);
802 string rnglists_contents;
803 assert(rnglists1.GetContents(&rnglists_contents));
804
805 RangeListReader::CURangesInfo cu_info;
806 cu_info.version_ = 5;
807 cu_info.base_address_ = 1;
808 cu_info.ranges_base_ = ranges_base_1;
809 cu_info.buffer_ =
810 reinterpret_cast<const uint8_t*>(rnglists_contents.data());
811 cu_info.size_ = rnglists_contents.size();
812 cu_info.addr_buffer_ =
813 reinterpret_cast<const uint8_t*>(addr_contents.data());
814 cu_info.addr_buffer_size_ = addr_contents.size();
815 cu_info.addr_base_ = 4;
816
817 ByteReader byte_reader(ENDIANNESS_BIG);
818 byte_reader.SetOffsetSize(4);
819 byte_reader.SetAddressSize(4);
820 MockRangeListHandler handler;
821 google_breakpad::RangeListReader range_list_reader1(&byte_reader, &cu_info,
822 &handler);
823 EXPECT_CALL(handler, AddRange(2, 3));
824 EXPECT_CALL(handler, AddRange(4, 5));
825 EXPECT_CALL(handler, AddRange(6, 7));
826 EXPECT_CALL(handler, AddRange(9, 10));
827 EXPECT_CALL(handler, AddRange(10, 11));
828 EXPECT_CALL(handler, AddRange(12, 13));
829 EXPECT_CALL(handler, Finish()).Times(2);
830 EXPECT_TRUE(range_list_reader1.ReadRanges(DW_FORM_rnglistx, 0));
831 EXPECT_TRUE(range_list_reader1.ReadRanges(DW_FORM_rnglistx, 1));
832 // Out of range index, should result in no calls.
833 EXPECT_FALSE(range_list_reader1.ReadRanges(DW_FORM_rnglistx, 2));
834
835 // Set to new ranges_base
836 cu_info.ranges_base_ = ranges_base_2;
837 google_breakpad::RangeListReader range_list_reader2(&byte_reader, &cu_info,
838 &handler);
839 EXPECT_CALL(handler, AddRange(2, 3));
840 EXPECT_CALL(handler, AddRange(4, 5));
841 EXPECT_CALL(handler, AddRange(6, 7));
842 EXPECT_CALL(handler, AddRange(16, 17));
843 EXPECT_CALL(handler, AddRange(17, 18));
844 EXPECT_CALL(handler, AddRange(19, 20));
845 EXPECT_CALL(handler, Finish()).Times(2);
846 EXPECT_TRUE(range_list_reader2.ReadRanges(DW_FORM_rnglistx, 0));
847 EXPECT_TRUE(range_list_reader2.ReadRanges(DW_FORM_rnglistx, 1));
848 // Out of range index, should result in no calls.
849 EXPECT_FALSE(range_list_reader2.ReadRanges(DW_FORM_rnglistx, 2));
850 }
851
TEST(RangeList,Dwarf5ReadRangeList_sec_offset)852 TEST(RangeList, Dwarf5ReadRangeList_sec_offset) {
853 using google_breakpad::RangeListReader;
854 using google_breakpad::DW_RLE_base_addressx;
855 using google_breakpad::DW_RLE_startx_endx;
856 using google_breakpad::DW_RLE_startx_length;
857 using google_breakpad::DW_RLE_offset_pair;
858 using google_breakpad::DW_RLE_end_of_list;
859 using google_breakpad::DW_RLE_base_address;
860 using google_breakpad::DW_RLE_start_end;
861 using google_breakpad::DW_RLE_start_length;
862 using google_breakpad::DW_FORM_sec_offset;
863 using google_breakpad::DW_FORM_rnglistx;
864
865 // Size of length field in header
866 const uint64_t length_size = 4;
867
868 // .debug_addr for the indexed entries like startx.
869 Section addr;
870 addr.set_endianness(kBigEndian);
871 // Test addr_base handling with a padding address at 0.
872 addr.D32(0).D32(1).D32(2).D32(3).D32(4).D32(21).D32(22);
873 std::string addr_contents;
874 assert(addr.GetContents(&addr_contents));
875
876 // .debug_rnglists is the dwarf 5 section.
877 Section rnglists1(kBigEndian);
878 Section rnglists2(kBigEndian);
879
880 // First header and body.
881 Label section_size1;
882 rnglists1.Append(kBigEndian, length_size, section_size1);
883 rnglists1.D16(5); // Version
884 rnglists1.D8(4); // Address size
885 rnglists1.D8(0); // Segment selector size
886 rnglists1.D32(0); // Offset entry count
887
888 const uint64_t offset1 = rnglists1.Size();
889
890 rnglists1.D8(DW_RLE_base_addressx).ULEB128(0); // base_addr = 1
891 rnglists1.D8(DW_RLE_startx_endx).ULEB128(1).ULEB128(2); // [2, 3)
892 rnglists1.D8(DW_RLE_startx_length).ULEB128(3).ULEB128(1); // [4, 5)
893 rnglists1.D8(DW_RLE_offset_pair).ULEB128(5).ULEB128(6); // [6, 7)
894 rnglists1.D8(DW_RLE_base_address).D32(8); // base_addr = 8
895 rnglists1.D8(DW_RLE_offset_pair).ULEB128(1).ULEB128(2); // [9, 10)
896 rnglists1.D8(DW_RLE_start_end).D32(10).D32(11); // [10, 11)
897 rnglists1.D8(DW_RLE_start_length).D32(12).ULEB128(1); // [12, 13)
898 rnglists1.D8(DW_RLE_end_of_list);
899 // The size doesn't include the size of length field itself.
900 section_size1 = rnglists1.Size() - length_size;
901
902 // Second header and body.
903 Label section_size2;
904 rnglists2.Append(kBigEndian, length_size, section_size2);
905 rnglists2.D16(5); // Version
906 rnglists2.D8(4); // Address size
907 rnglists2.D8(0); // Segment selector size
908 rnglists2.D32(0); // Offset entry count
909
910 const uint64_t offset2 = rnglists1.Size() + rnglists2.Size();
911
912 rnglists2.D8(DW_RLE_base_addressx).ULEB128(0); // base_addr = 1
913 rnglists2.D8(DW_RLE_startx_endx).ULEB128(1).ULEB128(2); // [2, 3)
914 rnglists2.D8(DW_RLE_startx_length).ULEB128(3).ULEB128(1); // [4, 5)
915 rnglists2.D8(DW_RLE_offset_pair).ULEB128(5).ULEB128(6); // [6, 7)
916 rnglists2.D8(DW_RLE_base_address).D32(15); // base_addr = 15
917 rnglists2.D8(DW_RLE_offset_pair).ULEB128(1).ULEB128(2); // [16, 17)
918 rnglists2.D8(DW_RLE_start_end).D32(17).D32(18); // [17, 18)
919 rnglists2.D8(DW_RLE_start_length).D32(19).ULEB128(1); // [19, 20)
920 rnglists2.D8(DW_RLE_end_of_list);
921 // The size doesn't include the size of length field itself.
922 section_size2 = rnglists2.Size() - length_size;
923
924 rnglists1.Append(rnglists2);
925 string rnglists_contents;
926 assert(rnglists1.GetContents(&rnglists_contents));
927
928 RangeListReader::CURangesInfo cu_info;
929 cu_info.version_ = 5;
930 cu_info.base_address_ = 1;
931 cu_info.buffer_ =
932 reinterpret_cast<const uint8_t*>(rnglists_contents.data());
933 cu_info.size_ = rnglists_contents.size();
934 cu_info.addr_buffer_ =
935 reinterpret_cast<const uint8_t*>(addr_contents.data());
936 cu_info.addr_buffer_size_ = addr_contents.size();
937 cu_info.addr_base_ = 4;
938
939 ByteReader byte_reader(ENDIANNESS_BIG);
940 byte_reader.SetOffsetSize(4);
941 byte_reader.SetAddressSize(4);
942 MockRangeListHandler handler;
943 google_breakpad::RangeListReader range_list_reader(&byte_reader, &cu_info,
944 &handler);
945 EXPECT_CALL(handler, AddRange(2, 3));
946 EXPECT_CALL(handler, AddRange(4, 5));
947 EXPECT_CALL(handler, AddRange(6, 7));
948 EXPECT_CALL(handler, AddRange(9, 10));
949 EXPECT_CALL(handler, AddRange(10, 11));
950 EXPECT_CALL(handler, AddRange(12, 13));
951 EXPECT_CALL(handler, Finish()).Times(1);
952 EXPECT_TRUE(range_list_reader.ReadRanges(DW_FORM_sec_offset, offset1));
953 // Out of range index, should result in no calls.
954 EXPECT_FALSE(range_list_reader.ReadRanges(DW_FORM_sec_offset,
955 rnglists_contents.size()));
956
957 EXPECT_CALL(handler, AddRange(2, 3));
958 EXPECT_CALL(handler, AddRange(4, 5));
959 EXPECT_CALL(handler, AddRange(6, 7));
960 EXPECT_CALL(handler, AddRange(16, 17));
961 EXPECT_CALL(handler, AddRange(17, 18));
962 EXPECT_CALL(handler, AddRange(19, 20));
963 EXPECT_CALL(handler, Finish()).Times(1);
964 EXPECT_TRUE(range_list_reader.ReadRanges(DW_FORM_sec_offset, offset2));
965 // Out of range index, should result in no calls.
966 EXPECT_FALSE(range_list_reader.ReadRanges(DW_FORM_sec_offset,
967 rnglists_contents.size()));
968 }
969