/ src / common / dwarf / dwarf2reader_die_unittest.cc
dwarf2reader_die_unittest.cc
  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 <jimb@mozilla.com> <jimb@red-bean.com>
 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  
114    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.
134    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 {
157    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  
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  
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.
292    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.
313    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  
326    void ExpectEndCompilationUnit() {
327      EXPECT_CALL(handler, EndDIE(_))
328          .InSequence(s)
329          .WillOnce(Return());
330    }
331  
332    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  
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  
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  
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  
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  
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  
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  
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  
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.
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  
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  
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  
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  
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  }