xref: /aosp_15_r20/external/google-breakpad/src/common/dwarf/dwarf2reader_die_unittest.cc (revision 9712c20fc9bbfbac4935993a2ca0b3958c5adad2)
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(&section_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