Home | History | Annotate | Download | only in common
      1 // Copyright (c) 2010 Google Inc.
      2 // All rights reserved.
      3 //
      4 // Redistribution and use in source and binary forms, with or without
      5 // modification, are permitted provided that the following conditions are
      6 // met:
      7 //
      8 //     * Redistributions of source code must retain the above copyright
      9 // notice, this list of conditions and the following disclaimer.
     10 //     * Redistributions in binary form must reproduce the above
     11 // copyright notice, this list of conditions and the following disclaimer
     12 // in the documentation and/or other materials provided with the
     13 // distribution.
     14 //     * Neither the name of Google Inc. nor the names of its
     15 // contributors may be used to endorse or promote products derived from
     16 // this software without specific prior written permission.
     17 //
     18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29 
     30 // Original author: Jim Blandy <jimb (at) mozilla.com> <jimb (at) red-bean.com>
     31 
     32 // dwarf_cu_to_module.cc: Unit tests for google_breakpad::DwarfCUToModule.
     33 
     34 #include <string>
     35 #include <utility>
     36 #include <vector>
     37 
     38 #include "breakpad_googletest_includes.h"
     39 #include "common/dwarf_cu_to_module.h"
     40 #include "common/using_std_string.h"
     41 
     42 using std::make_pair;
     43 using std::vector;
     44 
     45 using dwarf2reader::DIEHandler;
     46 using dwarf2reader::DwarfTag;
     47 using dwarf2reader::DwarfAttribute;
     48 using dwarf2reader::DwarfForm;
     49 using dwarf2reader::DwarfInline;
     50 using dwarf2reader::RootDIEHandler;
     51 using google_breakpad::DwarfCUToModule;
     52 using google_breakpad::Module;
     53 
     54 using ::testing::_;
     55 using ::testing::AtMost;
     56 using ::testing::Invoke;
     57 using ::testing::Return;
     58 using ::testing::Test;
     59 using ::testing::TestWithParam;
     60 using ::testing::Values;
     61 using ::testing::ValuesIn;
     62 
     63 // Mock classes.
     64 
     65 class MockLineToModuleHandler: public DwarfCUToModule::LineToModuleHandler {
     66  public:
     67   MOCK_METHOD1(StartCompilationUnit, void(const string& compilation_dir));
     68   MOCK_METHOD4(ReadProgram, void(const char* program, uint64 length,
     69                                  Module *module, vector<Module::Line> *lines));
     70 };
     71 
     72 class MockWarningReporter: public DwarfCUToModule::WarningReporter {
     73  public:
     74   MockWarningReporter(const string &filename, uint64 cu_offset)
     75       : DwarfCUToModule::WarningReporter(filename, cu_offset) { }
     76   MOCK_METHOD1(SetCUName, void(const string &name));
     77   MOCK_METHOD2(UnknownSpecification, void(uint64 offset, uint64 target));
     78   MOCK_METHOD2(UnknownAbstractOrigin, void(uint64 offset, uint64 target));
     79   MOCK_METHOD1(MissingSection, void(const string &section_name));
     80   MOCK_METHOD1(BadLineInfoOffset, void(uint64 offset));
     81   MOCK_METHOD1(UncoveredFunction, void(const Module::Function &function));
     82   MOCK_METHOD1(UncoveredLine, void(const Module::Line &line));
     83   MOCK_METHOD1(UnnamedFunction, void(uint64 offset));
     84   MOCK_METHOD2(DemangleError, void(const string &input, int error));
     85   MOCK_METHOD2(UnhandledInterCUReference, void(uint64 offset, uint64 target));
     86 };
     87 
     88 // A fixture class including all the objects needed to handle a
     89 // compilation unit, and their entourage. It includes member functions
     90 // for doing common kinds of setup and tests.
     91 class CUFixtureBase {
     92  public:
     93   // If we have:
     94   //
     95   //   vector<Module::Line> lines;
     96   //   AppendLinesFunctor appender(lines);
     97   //
     98   // then doing:
     99   //
    100   //   appender(line_program, length, module, line_vector);
    101   //
    102   // will append lines to the end of line_vector.  We can use this with
    103   // MockLineToModuleHandler like this:
    104   //
    105   //   MockLineToModuleHandler l2m;
    106   //   EXPECT_CALL(l2m, ReadProgram(_,_,_,_))
    107   //       .WillOnce(DoAll(Invoke(appender), Return()));
    108   //
    109   // in which case calling l2m with some line vector will append lines.
    110   class AppendLinesFunctor {
    111    public:
    112     explicit AppendLinesFunctor(
    113         const vector<Module::Line> *lines) : lines_(lines) { }
    114     void operator()(const char *program, uint64 length,
    115                     Module *module, vector<Module::Line> *lines) {
    116       lines->insert(lines->end(), lines_->begin(), lines_->end());
    117     }
    118    private:
    119     const vector<Module::Line> *lines_;
    120   };
    121 
    122   CUFixtureBase()
    123       : module_("module-name", "module-os", "module-arch", "module-id"),
    124         file_context_("dwarf-filename", &module_, true),
    125         language_(dwarf2reader::DW_LANG_none),
    126         language_signed_(false),
    127         appender_(&lines_),
    128         reporter_("dwarf-filename", 0xcf8f9bb6443d29b5LL),
    129         root_handler_(&file_context_, &line_reader_, &reporter_),
    130         functions_filled_(false) {
    131     // By default, expect no warnings to be reported, and expect the
    132     // compilation unit's name to be provided. The test can override
    133     // these expectations.
    134     EXPECT_CALL(reporter_, SetCUName("compilation-unit-name")).Times(1);
    135     EXPECT_CALL(reporter_, UnknownSpecification(_, _)).Times(0);
    136     EXPECT_CALL(reporter_, UnknownAbstractOrigin(_, _)).Times(0);
    137     EXPECT_CALL(reporter_, MissingSection(_)).Times(0);
    138     EXPECT_CALL(reporter_, BadLineInfoOffset(_)).Times(0);
    139     EXPECT_CALL(reporter_, UncoveredFunction(_)).Times(0);
    140     EXPECT_CALL(reporter_, UncoveredLine(_)).Times(0);
    141     EXPECT_CALL(reporter_, UnnamedFunction(_)).Times(0);
    142     EXPECT_CALL(reporter_, UnhandledInterCUReference(_, _)).Times(0);
    143 
    144     // By default, expect the line program reader not to be invoked. We
    145     // may override this in StartCU.
    146     EXPECT_CALL(line_reader_, StartCompilationUnit(_)).Times(0);
    147     EXPECT_CALL(line_reader_, ReadProgram(_,_,_,_)).Times(0);
    148 
    149     // The handler will consult this section map to decide what to
    150     // pass to our line reader.
    151     file_context_.AddSectionToSectionMap(".debug_line",
    152                                          dummy_line_program_,
    153                                          dummy_line_size_);
    154   }
    155 
    156   // Add a line with the given address, size, filename, and line
    157   // number to the end of the statement list the handler will receive
    158   // when it invokes its LineToModuleHandler. Call this before calling
    159   // StartCU.
    160   void PushLine(Module::Address address, Module::Address size,
    161                 const string &filename, int line_number);
    162 
    163   // Use LANGUAGE for the compilation unit. More precisely, arrange
    164   // for StartCU to pass the compilation unit's root DIE a
    165   // DW_AT_language attribute whose value is LANGUAGE.
    166   void SetLanguage(dwarf2reader::DwarfLanguage language) {
    167     language_ = language;
    168   }
    169 
    170   // If SIGNED true, have StartCU report DW_AT_language as a signed
    171   // attribute; if false, have it report it as unsigned.
    172   void SetLanguageSigned(bool is_signed) { language_signed_ = is_signed; }
    173 
    174   // Call the handler this.root_handler_'s StartCompilationUnit and
    175   // StartRootDIE member functions, passing it appropriate attributes as
    176   // determined by prior calls to PushLine and SetLanguage. Leave
    177   // this.root_handler_ ready to hear about children: call
    178   // this.root_handler_.EndAttributes, but not this.root_handler_.Finish.
    179   void StartCU();
    180 
    181   // Have HANDLER process some strange attribute/form/value triples.
    182   void ProcessStrangeAttributes(dwarf2reader::DIEHandler *handler);
    183 
    184   // Start a child DIE of PARENT with the given tag and name. Leave
    185   // the handler ready to hear about children: call EndAttributes, but
    186   // not Finish.
    187   DIEHandler *StartNamedDIE(DIEHandler *parent, DwarfTag tag,
    188                             const string &name);
    189 
    190   // Start a child DIE of PARENT with the given tag and a
    191   // DW_AT_specification attribute whose value is SPECIFICATION. Leave
    192   // the handler ready to hear about children: call EndAttributes, but
    193   // not Finish. If NAME is non-zero, use it as the DW_AT_name
    194   // attribute.
    195   DIEHandler *StartSpecifiedDIE(DIEHandler *parent, DwarfTag tag,
    196                                 uint64 specification, const char *name = NULL);
    197 
    198   // Define a function as a child of PARENT with the given name, address, and
    199   // size. If high_pc_form is DW_FORM_addr then the DW_AT_high_pc attribute
    200   // will be written as an address; otherwise it will be written as the
    201   // function's size. Call EndAttributes and Finish; one cannot define
    202   // children of the defined function's DIE.
    203   void DefineFunction(DIEHandler *parent, const string &name,
    204                       Module::Address address, Module::Address size,
    205                       const char* mangled_name,
    206                       DwarfForm high_pc_form = dwarf2reader::DW_FORM_addr);
    207 
    208   // Create a declaration DIE as a child of PARENT with the given
    209   // offset, tag and name. If NAME is the empty string, don't provide
    210   // a DW_AT_name attribute. Call EndAttributes and Finish.
    211   void DeclarationDIE(DIEHandler *parent, uint64 offset,
    212                       DwarfTag tag, const string &name,
    213                       const string &mangled_name);
    214 
    215   // Create a definition DIE as a child of PARENT with the given tag
    216   // that refers to the declaration DIE at offset SPECIFICATION as its
    217   // specification. If NAME is non-empty, pass it as the DW_AT_name
    218   // attribute. If SIZE is non-zero, record ADDRESS and SIZE as
    219   // low_pc/high_pc attributes.
    220   void DefinitionDIE(DIEHandler *parent, DwarfTag tag,
    221                      uint64 specification, const string &name,
    222                      Module::Address address = 0, Module::Address size = 0);
    223 
    224   // Create an inline DW_TAG_subprogram DIE as a child of PARENT.  If
    225   // SPECIFICATION is non-zero, then the DIE refers to the declaration DIE at
    226   // offset SPECIFICATION as its specification.  If Name is non-empty, pass it
    227   // as the DW_AT_name attribute.
    228   void AbstractInstanceDIE(DIEHandler *parent, uint64 offset,
    229                            DwarfInline type, uint64 specification,
    230                            const string &name,
    231                            DwarfForm form = dwarf2reader::DW_FORM_data1);
    232 
    233   // Create a DW_TAG_subprogram DIE as a child of PARENT that refers to
    234   // ORIGIN in its DW_AT_abstract_origin attribute.  If NAME is the empty
    235   // string, don't provide a DW_AT_name attribute.
    236   void DefineInlineInstanceDIE(DIEHandler *parent, const string &name,
    237                                uint64 origin, Module::Address address,
    238                                Module::Address size);
    239 
    240   // The following Test* functions should be called after calling
    241   // this.root_handler_.Finish. After that point, no further calls
    242   // should be made on the handler.
    243 
    244   // Test that the number of functions defined in the module this.module_ is
    245   // equal to EXPECTED.
    246   void TestFunctionCount(size_t expected);
    247 
    248   // Test that the I'th function (ordered by address) in the module
    249   // this.module_ has the given name, address, and size, and that its
    250   // parameter size is zero.
    251   void TestFunction(int i, const string &name,
    252                     Module::Address address, Module::Address size);
    253 
    254   // Test that the number of source lines owned by the I'th function
    255   // in the module this.module_ is equal to EXPECTED.
    256   void TestLineCount(int i, size_t expected);
    257 
    258   // Test that the J'th line (ordered by address) of the I'th function
    259   // (again, by address) has the given address, size, filename, and
    260   // line number.
    261   void TestLine(int i, int j, Module::Address address, Module::Address size,
    262                 const string &filename, int number);
    263 
    264   // Actual objects under test.
    265   Module module_;
    266   DwarfCUToModule::FileContext file_context_;
    267 
    268   // If this is not DW_LANG_none, we'll pass it as a DW_AT_language
    269   // attribute to the compilation unit. This defaults to DW_LANG_none.
    270   dwarf2reader::DwarfLanguage language_;
    271 
    272   // If this is true, report DW_AT_language as a signed value; if false,
    273   // report it as an unsigned value.
    274   bool language_signed_;
    275 
    276   // If this is not empty, we'll give the CU a DW_AT_comp_dir attribute that
    277   // indicates the path that this compilation unit was compiled in.
    278   string compilation_dir_;
    279 
    280   // If this is not empty, we'll give the CU a DW_AT_stmt_list
    281   // attribute that, when passed to line_reader_, adds these lines to the
    282   // provided lines array.
    283   vector<Module::Line> lines_;
    284 
    285   // Mock line program reader.
    286   MockLineToModuleHandler line_reader_;
    287   AppendLinesFunctor appender_;
    288   static const char dummy_line_program_[];
    289   static const size_t dummy_line_size_;
    290 
    291   MockWarningReporter reporter_;
    292   DwarfCUToModule root_handler_;
    293 
    294  private:
    295   // Fill functions_, if we haven't already.
    296   void FillFunctions();
    297 
    298   // If functions_filled_ is true, this is a table of functions we've
    299   // extracted from module_, sorted by address.
    300   vector<Module::Function *> functions_;
    301   // True if we have filled the above vector with this.module_'s function list.
    302   bool functions_filled_;
    303 };
    304 
    305 const char CUFixtureBase::dummy_line_program_[] = "lots of fun data";
    306 const size_t CUFixtureBase::dummy_line_size_ =
    307     sizeof(CUFixtureBase::dummy_line_program_);
    308 
    309 void CUFixtureBase::PushLine(Module::Address address, Module::Address size,
    310                              const string &filename, int line_number) {
    311   Module::Line l;
    312   l.address = address;
    313   l.size = size;
    314   l.file = module_.FindFile(filename);
    315   l.number = line_number;
    316   lines_.push_back(l);
    317 }
    318 
    319 void CUFixtureBase::StartCU() {
    320   if (!compilation_dir_.empty())
    321     EXPECT_CALL(line_reader_,
    322                 StartCompilationUnit(compilation_dir_)).Times(1);
    323 
    324   // If we have lines, make the line reader expect to be invoked at
    325   // most once. (Hey, if the handler can pass its tests without
    326   // bothering to read the line number data, that's great.)
    327   // Have it add the lines passed to PushLine. Otherwise, leave the
    328   // initial expectation (no calls) in force.
    329   if (!lines_.empty())
    330     EXPECT_CALL(line_reader_,
    331                 ReadProgram(&dummy_line_program_[0], dummy_line_size_,
    332                             &module_, _))
    333         .Times(AtMost(1))
    334         .WillOnce(DoAll(Invoke(appender_), Return()));
    335 
    336   ASSERT_TRUE(root_handler_
    337               .StartCompilationUnit(0x51182ec307610b51ULL, 0x81, 0x44,
    338                                     0x4241b4f33720dd5cULL, 3));
    339   {
    340     ASSERT_TRUE(root_handler_.StartRootDIE(0x02e56bfbda9e7337ULL,
    341                                            dwarf2reader::DW_TAG_compile_unit));
    342   }
    343   root_handler_.ProcessAttributeString(dwarf2reader::DW_AT_name,
    344                                        dwarf2reader::DW_FORM_strp,
    345                                        "compilation-unit-name");
    346   if (!compilation_dir_.empty())
    347     root_handler_.ProcessAttributeString(dwarf2reader::DW_AT_comp_dir,
    348                                          dwarf2reader::DW_FORM_strp,
    349                                          compilation_dir_);
    350   if (!lines_.empty())
    351     root_handler_.ProcessAttributeUnsigned(dwarf2reader::DW_AT_stmt_list,
    352                                            dwarf2reader::DW_FORM_ref4,
    353                                            0);
    354   if (language_ != dwarf2reader::DW_LANG_none) {
    355     if (language_signed_)
    356       root_handler_.ProcessAttributeSigned(dwarf2reader::DW_AT_language,
    357                                            dwarf2reader::DW_FORM_sdata,
    358                                            language_);
    359     else
    360       root_handler_.ProcessAttributeUnsigned(dwarf2reader::DW_AT_language,
    361                                              dwarf2reader::DW_FORM_udata,
    362                                              language_);
    363   }
    364   ASSERT_TRUE(root_handler_.EndAttributes());
    365 }
    366 
    367 void CUFixtureBase::ProcessStrangeAttributes(
    368     dwarf2reader::DIEHandler *handler) {
    369   handler->ProcessAttributeUnsigned((DwarfAttribute) 0xf560dead,
    370                                     (DwarfForm) 0x4106e4db,
    371                                     0xa592571997facda1ULL);
    372   handler->ProcessAttributeSigned((DwarfAttribute) 0x85380095,
    373                                   (DwarfForm) 0x0f16fe87,
    374                                   0x12602a4e3bf1f446LL);
    375   handler->ProcessAttributeReference((DwarfAttribute) 0xf7f7480f,
    376                                      (DwarfForm) 0x829e038a,
    377                                      0x50fddef44734fdecULL);
    378   static const char buffer[10] = "frobynode";
    379   handler->ProcessAttributeBuffer((DwarfAttribute) 0xa55ffb51,
    380                                   (DwarfForm) 0x2f43b041,
    381                                   buffer, sizeof(buffer));
    382   handler->ProcessAttributeString((DwarfAttribute) 0x2f43b041,
    383                                   (DwarfForm) 0x895ffa23,
    384                                   "strange string");
    385 }
    386 
    387 DIEHandler *CUFixtureBase::StartNamedDIE(DIEHandler *parent,
    388                                          DwarfTag tag,
    389                                          const string &name) {
    390   dwarf2reader::DIEHandler *handler
    391     = parent->FindChildHandler(0x8f4c783c0467c989ULL, tag);
    392   if (!handler)
    393     return NULL;
    394   handler->ProcessAttributeString(dwarf2reader::DW_AT_name,
    395                                   dwarf2reader::DW_FORM_strp,
    396                                   name);
    397   ProcessStrangeAttributes(handler);
    398   if (!handler->EndAttributes()) {
    399     handler->Finish();
    400     delete handler;
    401     return NULL;
    402   }
    403 
    404   return handler;
    405 }
    406 
    407 DIEHandler *CUFixtureBase::StartSpecifiedDIE(DIEHandler *parent,
    408                                              DwarfTag tag,
    409                                              uint64 specification,
    410                                              const char *name) {
    411   dwarf2reader::DIEHandler *handler
    412     = parent->FindChildHandler(0x8f4c783c0467c989ULL, tag);
    413   if (!handler)
    414     return NULL;
    415   if (name)
    416     handler->ProcessAttributeString(dwarf2reader::DW_AT_name,
    417                                     dwarf2reader::DW_FORM_strp,
    418                                     name);
    419   handler->ProcessAttributeReference(dwarf2reader::DW_AT_specification,
    420                                      dwarf2reader::DW_FORM_ref4,
    421                                      specification);
    422   if (!handler->EndAttributes()) {
    423     handler->Finish();
    424     delete handler;
    425     return NULL;
    426   }
    427 
    428   return handler;
    429 }
    430 
    431 void CUFixtureBase::DefineFunction(dwarf2reader::DIEHandler *parent,
    432                                    const string &name, Module::Address address,
    433                                    Module::Address size,
    434                                    const char* mangled_name,
    435                                    DwarfForm high_pc_form) {
    436   dwarf2reader::DIEHandler *func
    437       = parent->FindChildHandler(0xe34797c7e68590a8LL,
    438                                  dwarf2reader::DW_TAG_subprogram);
    439   ASSERT_TRUE(func != NULL);
    440   func->ProcessAttributeString(dwarf2reader::DW_AT_name,
    441                                dwarf2reader::DW_FORM_strp,
    442                                name);
    443   func->ProcessAttributeUnsigned(dwarf2reader::DW_AT_low_pc,
    444                                  dwarf2reader::DW_FORM_addr,
    445                                  address);
    446 
    447   Module::Address high_pc = size;
    448   if (high_pc_form == dwarf2reader::DW_FORM_addr) {
    449     high_pc += address;
    450   }
    451   func->ProcessAttributeUnsigned(dwarf2reader::DW_AT_high_pc,
    452                                  high_pc_form,
    453                                  high_pc);
    454 
    455   if (mangled_name)
    456     func->ProcessAttributeString(dwarf2reader::DW_AT_MIPS_linkage_name,
    457                                  dwarf2reader::DW_FORM_strp,
    458                                  mangled_name);
    459 
    460   ProcessStrangeAttributes(func);
    461   EXPECT_TRUE(func->EndAttributes());
    462   func->Finish();
    463   delete func;
    464 }
    465 
    466 void CUFixtureBase::DeclarationDIE(DIEHandler *parent, uint64 offset,
    467                                    DwarfTag tag,
    468                                    const string &name,
    469                                    const string &mangled_name) {
    470   dwarf2reader::DIEHandler *die = parent->FindChildHandler(offset, tag);
    471   ASSERT_TRUE(die != NULL);
    472   if (!name.empty())
    473     die->ProcessAttributeString(dwarf2reader::DW_AT_name,
    474                                 dwarf2reader::DW_FORM_strp,
    475                                 name);
    476   if (!mangled_name.empty())
    477     die->ProcessAttributeString(dwarf2reader::DW_AT_MIPS_linkage_name,
    478                                 dwarf2reader::DW_FORM_strp,
    479                                 mangled_name);
    480 
    481   die->ProcessAttributeUnsigned(dwarf2reader::DW_AT_declaration,
    482                                 dwarf2reader::DW_FORM_flag,
    483                                 1);
    484   EXPECT_TRUE(die->EndAttributes());
    485   die->Finish();
    486   delete die;
    487 }
    488 
    489 void CUFixtureBase::DefinitionDIE(DIEHandler *parent,
    490                                   DwarfTag tag,
    491                                   uint64 specification,
    492                                   const string &name,
    493                                   Module::Address address,
    494                                   Module::Address size) {
    495   dwarf2reader::DIEHandler *die
    496     = parent->FindChildHandler(0x6ccfea031a9e6cc9ULL, tag);
    497   ASSERT_TRUE(die != NULL);
    498   die->ProcessAttributeReference(dwarf2reader::DW_AT_specification,
    499                                  dwarf2reader::DW_FORM_ref4,
    500                                  specification);
    501   if (!name.empty())
    502     die->ProcessAttributeString(dwarf2reader::DW_AT_name,
    503                                 dwarf2reader::DW_FORM_strp,
    504                                 name);
    505   if (size) {
    506     die->ProcessAttributeUnsigned(dwarf2reader::DW_AT_low_pc,
    507                                   dwarf2reader::DW_FORM_addr,
    508                                   address);
    509     die->ProcessAttributeUnsigned(dwarf2reader::DW_AT_high_pc,
    510                                   dwarf2reader::DW_FORM_addr,
    511                                   address + size);
    512   }
    513   EXPECT_TRUE(die->EndAttributes());
    514   die->Finish();
    515   delete die;
    516 }
    517 
    518 void CUFixtureBase::AbstractInstanceDIE(DIEHandler *parent,
    519                                         uint64 offset,
    520                                         DwarfInline type,
    521                                         uint64 specification,
    522                                         const string &name,
    523                                         DwarfForm form) {
    524   dwarf2reader::DIEHandler *die
    525     = parent->FindChildHandler(offset, dwarf2reader::DW_TAG_subprogram);
    526   ASSERT_TRUE(die != NULL);
    527   if (specification != 0ULL)
    528     die->ProcessAttributeReference(dwarf2reader::DW_AT_specification,
    529                                    dwarf2reader::DW_FORM_ref4,
    530                                    specification);
    531   if (form == dwarf2reader::DW_FORM_sdata) {
    532     die->ProcessAttributeSigned(dwarf2reader::DW_AT_inline, form, type);
    533   } else {
    534     die->ProcessAttributeUnsigned(dwarf2reader::DW_AT_inline, form, type);
    535   }
    536   if (!name.empty())
    537     die->ProcessAttributeString(dwarf2reader::DW_AT_name,
    538                                 dwarf2reader::DW_FORM_strp,
    539                                 name);
    540 
    541   EXPECT_TRUE(die->EndAttributes());
    542   die->Finish();
    543   delete die;
    544 }
    545 
    546 void CUFixtureBase::DefineInlineInstanceDIE(DIEHandler *parent,
    547                                             const string &name,
    548                                             uint64 origin,
    549                                             Module::Address address,
    550                                             Module::Address size) {
    551   dwarf2reader::DIEHandler *func
    552       = parent->FindChildHandler(0x11c70f94c6e87ccdLL,
    553                                  dwarf2reader::DW_TAG_subprogram);
    554   ASSERT_TRUE(func != NULL);
    555   if (!name.empty()) {
    556     func->ProcessAttributeString(dwarf2reader::DW_AT_name,
    557                                  dwarf2reader::DW_FORM_strp,
    558                                  name);
    559   }
    560   func->ProcessAttributeUnsigned(dwarf2reader::DW_AT_low_pc,
    561                                  dwarf2reader::DW_FORM_addr,
    562                                  address);
    563   func->ProcessAttributeUnsigned(dwarf2reader::DW_AT_high_pc,
    564                                  dwarf2reader::DW_FORM_addr,
    565                                  address + size);
    566   func->ProcessAttributeReference(dwarf2reader::DW_AT_abstract_origin,
    567                                  dwarf2reader::DW_FORM_ref4,
    568                                  origin);
    569   ProcessStrangeAttributes(func);
    570   EXPECT_TRUE(func->EndAttributes());
    571   func->Finish();
    572   delete func;
    573 }
    574 
    575 void CUFixtureBase::FillFunctions() {
    576   if (functions_filled_)
    577     return;
    578   module_.GetFunctions(&functions_, functions_.end());
    579   sort(functions_.begin(), functions_.end(),
    580        Module::Function::CompareByAddress);
    581   functions_filled_ = true;
    582 }
    583 
    584 void CUFixtureBase::TestFunctionCount(size_t expected) {
    585   FillFunctions();
    586   ASSERT_EQ(expected, functions_.size());
    587 }
    588 
    589 void CUFixtureBase::TestFunction(int i, const string &name,
    590                                  Module::Address address,
    591                                  Module::Address size) {
    592   FillFunctions();
    593   ASSERT_LT((size_t) i, functions_.size());
    594 
    595   Module::Function *function = functions_[i];
    596   EXPECT_EQ(name,    function->name);
    597   EXPECT_EQ(address, function->address);
    598   EXPECT_EQ(size,    function->size);
    599   EXPECT_EQ(0U,      function->parameter_size);
    600 }
    601 
    602 void CUFixtureBase::TestLineCount(int i, size_t expected) {
    603   FillFunctions();
    604   ASSERT_LT((size_t) i, functions_.size());
    605 
    606   ASSERT_EQ(expected, functions_[i]->lines.size());
    607 }
    608 
    609 void CUFixtureBase::TestLine(int i, int j,
    610                              Module::Address address, Module::Address size,
    611                              const string &filename, int number) {
    612   FillFunctions();
    613   ASSERT_LT((size_t) i, functions_.size());
    614   ASSERT_LT((size_t) j, functions_[i]->lines.size());
    615 
    616   Module::Line *line = &functions_[i]->lines[j];
    617   EXPECT_EQ(address,  line->address);
    618   EXPECT_EQ(size,     line->size);
    619   EXPECT_EQ(filename, line->file->name.c_str());
    620   EXPECT_EQ(number,   line->number);
    621 }
    622 
    623 // Include caller locations for our test subroutines.
    624 #define TRACE(call) do { SCOPED_TRACE("called from here"); call; } while (0)
    625 #define PushLine(a,b,c,d)         TRACE(PushLine((a),(b),(c),(d)))
    626 #define SetLanguage(a)            TRACE(SetLanguage(a))
    627 #define StartCU()                 TRACE(StartCU())
    628 #define DefineFunction(a,b,c,d,e) TRACE(DefineFunction((a),(b),(c),(d),(e)))
    629 // (DefineFunction) instead of DefineFunction to avoid macro expansion.
    630 #define DefineFunction6(a,b,c,d,e,f) \
    631     TRACE((DefineFunction)((a),(b),(c),(d),(e),(f)))
    632 #define DeclarationDIE(a,b,c,d,e) TRACE(DeclarationDIE((a),(b),(c),(d),(e)))
    633 #define DefinitionDIE(a,b,c,d,e,f) \
    634     TRACE(DefinitionDIE((a),(b),(c),(d),(e),(f)))
    635 #define TestFunctionCount(a)      TRACE(TestFunctionCount(a))
    636 #define TestFunction(a,b,c,d)     TRACE(TestFunction((a),(b),(c),(d)))
    637 #define TestLineCount(a,b)        TRACE(TestLineCount((a),(b)))
    638 #define TestLine(a,b,c,d,e,f)     TRACE(TestLine((a),(b),(c),(d),(e),(f)))
    639 
    640 class SimpleCU: public CUFixtureBase, public Test {
    641 };
    642 
    643 TEST_F(SimpleCU, CompilationDir) {
    644   compilation_dir_ = "/src/build/";
    645 
    646   StartCU();
    647   root_handler_.Finish();
    648 }
    649 
    650 TEST_F(SimpleCU, OneFunc) {
    651   PushLine(0x938cf8c07def4d34ULL, 0x55592d727f6cd01fLL, "line-file", 246571772);
    652 
    653   StartCU();
    654   DefineFunction(&root_handler_, "function1",
    655                  0x938cf8c07def4d34ULL, 0x55592d727f6cd01fLL, NULL);
    656   root_handler_.Finish();
    657 
    658   TestFunctionCount(1);
    659   TestFunction(0, "function1", 0x938cf8c07def4d34ULL, 0x55592d727f6cd01fLL);
    660   TestLineCount(0, 1);
    661   TestLine(0, 0, 0x938cf8c07def4d34ULL, 0x55592d727f6cd01fLL, "line-file",
    662            246571772);
    663 }
    664 
    665 // As above, only DW_AT_high_pc is a length rather than an address.
    666 TEST_F(SimpleCU, OneFuncHighPcIsLength) {
    667   PushLine(0x938cf8c07def4d34ULL, 0x55592d727f6cd01fLL, "line-file", 246571772);
    668 
    669   StartCU();
    670   DefineFunction6(&root_handler_, "function1",
    671                   0x938cf8c07def4d34ULL, 0x55592d727f6cd01fLL, NULL,
    672                   dwarf2reader::DW_FORM_udata);
    673   root_handler_.Finish();
    674 
    675   TestFunctionCount(1);
    676   TestFunction(0, "function1", 0x938cf8c07def4d34ULL, 0x55592d727f6cd01fLL);
    677   TestLineCount(0, 1);
    678   TestLine(0, 0, 0x938cf8c07def4d34ULL, 0x55592d727f6cd01fLL, "line-file",
    679            246571772);
    680 }
    681 
    682 TEST_F(SimpleCU, MangledName) {
    683   PushLine(0x938cf8c07def4d34ULL, 0x55592d727f6cd01fLL, "line-file", 246571772);
    684 
    685   StartCU();
    686   DefineFunction(&root_handler_, "function1",
    687                  0x938cf8c07def4d34ULL, 0x55592d727f6cd01fLL, "_ZN1n1fEi");
    688   root_handler_.Finish();
    689 
    690   TestFunctionCount(1);
    691   TestFunction(0, "n::f(int)", 0x938cf8c07def4d34ULL, 0x55592d727f6cd01fLL);
    692 }
    693 
    694 TEST_F(SimpleCU, IrrelevantRootChildren) {
    695   StartCU();
    696   EXPECT_FALSE(root_handler_
    697                .FindChildHandler(0x7db32bff4e2dcfb1ULL,
    698                                  dwarf2reader::DW_TAG_lexical_block));
    699 }
    700 
    701 TEST_F(SimpleCU, IrrelevantNamedScopeChildren) {
    702   StartCU();
    703   DIEHandler *class_A_handler
    704     = StartNamedDIE(&root_handler_, dwarf2reader::DW_TAG_class_type, "class_A");
    705   EXPECT_TRUE(class_A_handler != NULL);
    706   EXPECT_FALSE(class_A_handler
    707                ->FindChildHandler(0x02e55999b865e4e9ULL,
    708                                   dwarf2reader::DW_TAG_lexical_block));
    709   delete class_A_handler;
    710 }
    711 
    712 // Verify that FileContexts can safely be deleted unused.
    713 TEST_F(SimpleCU, UnusedFileContext) {
    714   Module m("module-name", "module-os", "module-arch", "module-id");
    715   DwarfCUToModule::FileContext fc("dwarf-filename", &m, true);
    716 
    717   // Kludge: satisfy reporter_'s expectation.
    718   reporter_.SetCUName("compilation-unit-name");
    719 }
    720 
    721 TEST_F(SimpleCU, InlineFunction) {
    722   PushLine(0x1758a0f941b71efbULL, 0x1cf154f1f545e146ULL, "line-file", 75173118);
    723 
    724   StartCU();
    725   AbstractInstanceDIE(&root_handler_, 0x1e8dac5d507ed7abULL,
    726                       dwarf2reader::DW_INL_inlined, 0, "inline-name");
    727   DefineInlineInstanceDIE(&root_handler_, "", 0x1e8dac5d507ed7abULL,
    728                        0x1758a0f941b71efbULL, 0x1cf154f1f545e146ULL);
    729   root_handler_.Finish();
    730 
    731   TestFunctionCount(1);
    732   TestFunction(0, "inline-name",
    733                0x1758a0f941b71efbULL, 0x1cf154f1f545e146ULL);
    734 }
    735 
    736 TEST_F(SimpleCU, InlineFunctionSignedAttribute) {
    737   PushLine(0x1758a0f941b71efbULL, 0x1cf154f1f545e146ULL, "line-file", 75173118);
    738 
    739   StartCU();
    740   AbstractInstanceDIE(&root_handler_, 0x1e8dac5d507ed7abULL,
    741                       dwarf2reader::DW_INL_inlined, 0, "inline-name",
    742                       dwarf2reader::DW_FORM_sdata);
    743   DefineInlineInstanceDIE(&root_handler_, "", 0x1e8dac5d507ed7abULL,
    744                        0x1758a0f941b71efbULL, 0x1cf154f1f545e146ULL);
    745   root_handler_.Finish();
    746 
    747   TestFunctionCount(1);
    748   TestFunction(0, "inline-name",
    749                0x1758a0f941b71efbULL, 0x1cf154f1f545e146ULL);
    750 }
    751 
    752 // Any DIE with an DW_AT_inline attribute can be cited by
    753 // DW_AT_abstract_origin attributes --- even if the value of the
    754 // DW_AT_inline attribute is DW_INL_not_inlined.
    755 TEST_F(SimpleCU, AbstractOriginNotInlined) {
    756   PushLine(0x2805c4531be6ca0eULL, 0x686b52155a8d4d2cULL, "line-file", 6111581);
    757 
    758   StartCU();
    759   AbstractInstanceDIE(&root_handler_, 0x93e9cdad52826b39ULL,
    760                       dwarf2reader::DW_INL_not_inlined, 0, "abstract-instance");
    761   DefineInlineInstanceDIE(&root_handler_, "", 0x93e9cdad52826b39ULL,
    762                           0x2805c4531be6ca0eULL, 0x686b52155a8d4d2cULL);
    763   root_handler_.Finish();
    764 
    765   TestFunctionCount(1);
    766   TestFunction(0, "abstract-instance",
    767                0x2805c4531be6ca0eULL, 0x686b52155a8d4d2cULL);
    768 }
    769 
    770 TEST_F(SimpleCU, UnknownAbstractOrigin) {
    771   EXPECT_CALL(reporter_, UnknownAbstractOrigin(_, 1ULL)).WillOnce(Return());
    772   EXPECT_CALL(reporter_, UnnamedFunction(0x11c70f94c6e87ccdLL))
    773     .WillOnce(Return());
    774   PushLine(0x1758a0f941b71efbULL, 0x1cf154f1f545e146ULL, "line-file", 75173118);
    775 
    776   StartCU();
    777   AbstractInstanceDIE(&root_handler_, 0x1e8dac5d507ed7abULL,
    778                       dwarf2reader::DW_INL_inlined, 0, "inline-name");
    779   DefineInlineInstanceDIE(&root_handler_, "", 1ULL,
    780                        0x1758a0f941b71efbULL, 0x1cf154f1f545e146ULL);
    781   root_handler_.Finish();
    782 
    783   TestFunctionCount(1);
    784   TestFunction(0, "<name omitted>",
    785                0x1758a0f941b71efbULL, 0x1cf154f1f545e146ULL);
    786 }
    787 
    788 TEST_F(SimpleCU, UnnamedFunction) {
    789   EXPECT_CALL(reporter_, UnnamedFunction(0xe34797c7e68590a8LL))
    790     .WillOnce(Return());
    791   PushLine(0x72b80e41a0ac1d40ULL, 0x537174f231ee181cULL, "line-file", 14044850);
    792 
    793   StartCU();
    794   DefineFunction(&root_handler_, "",
    795                  0x72b80e41a0ac1d40ULL, 0x537174f231ee181cULL, NULL);
    796   root_handler_.Finish();
    797 
    798   TestFunctionCount(1);
    799   TestFunction(0, "<name omitted>",
    800                0x72b80e41a0ac1d40ULL, 0x537174f231ee181cULL);
    801 }
    802 
    803 // An address range.
    804 struct Range {
    805   Module::Address start, end;
    806 };
    807 
    808 // Test data for pairing functions and lines.
    809 struct Situation {
    810   // Two function intervals, and two line intervals.
    811   Range functions[2], lines[2];
    812 
    813   // The number of lines we expect to be assigned to each of the
    814   // functions, and the address ranges.
    815   int paired_count[2];
    816   Range paired[2][2];
    817 
    818   // The number of functions that are not entirely covered by lines,
    819   // and vice versa.
    820   int uncovered_functions, uncovered_lines;
    821 };
    822 
    823 #define PAIRING(func1_start, func1_end, func2_start, func2_end, \
    824                 line1_start, line1_end, line2_start, line2_end, \
    825                 func1_num_lines, func2_num_lines,               \
    826                 func1_line1_start, func1_line1_end,             \
    827                 func1_line2_start, func1_line2_end,             \
    828                 func2_line1_start, func2_line1_end,             \
    829                 func2_line2_start, func2_line2_end,             \
    830                 uncovered_functions, uncovered_lines)           \
    831   { { { func1_start, func1_end }, { func2_start, func2_end } }, \
    832     { { line1_start, line1_end }, { line2_start, line2_end } }, \
    833     { func1_num_lines, func2_num_lines },                       \
    834     { { { func1_line1_start, func1_line1_end },                 \
    835         { func1_line2_start, func1_line2_end } },               \
    836       { { func2_line1_start, func2_line1_end },                 \
    837           { func2_line2_start, func2_line2_end } } },           \
    838     uncovered_functions, uncovered_lines },
    839 
    840 Situation situations[] = {
    841 #include "common/testdata/func-line-pairing.h"
    842 };
    843 
    844 #undef PAIRING
    845 
    846 class FuncLinePairing: public CUFixtureBase,
    847                        public TestWithParam<Situation> { };
    848 
    849 INSTANTIATE_TEST_CASE_P(AllSituations, FuncLinePairing,
    850                         ValuesIn(situations));
    851 
    852 TEST_P(FuncLinePairing, Pairing) {
    853   const Situation &s = GetParam();
    854   PushLine(s.lines[0].start,
    855            s.lines[0].end - s.lines[0].start,
    856            "line-file", 67636963);
    857   PushLine(s.lines[1].start,
    858            s.lines[1].end - s.lines[1].start,
    859            "line-file", 67636963);
    860   if (s.uncovered_functions)
    861     EXPECT_CALL(reporter_, UncoveredFunction(_))
    862       .Times(s.uncovered_functions)
    863       .WillRepeatedly(Return());
    864   if (s.uncovered_lines)
    865     EXPECT_CALL(reporter_, UncoveredLine(_))
    866       .Times(s.uncovered_lines)
    867       .WillRepeatedly(Return());
    868 
    869   StartCU();
    870   DefineFunction(&root_handler_, "function1",
    871                  s.functions[0].start,
    872                  s.functions[0].end - s.functions[0].start, NULL);
    873   DefineFunction(&root_handler_, "function2",
    874                  s.functions[1].start,
    875                  s.functions[1].end - s.functions[1].start, NULL);
    876   root_handler_.Finish();
    877 
    878   TestFunctionCount(2);
    879   TestFunction(0, "function1",
    880                s.functions[0].start,
    881                s.functions[0].end - s.functions[0].start);
    882   TestLineCount(0, s.paired_count[0]);
    883   for (int i = 0; i < s.paired_count[0]; i++)
    884     TestLine(0, i, s.paired[0][i].start,
    885              s.paired[0][i].end - s.paired[0][i].start,
    886              "line-file", 67636963);
    887   TestFunction(1, "function2",
    888                s.functions[1].start,
    889                s.functions[1].end - s.functions[1].start);
    890   TestLineCount(1, s.paired_count[1]);
    891   for (int i = 0; i < s.paired_count[1]; i++)
    892     TestLine(1, i, s.paired[1][i].start,
    893              s.paired[1][i].end - s.paired[1][i].start,
    894              "line-file", 67636963);
    895 }
    896 
    897 TEST_F(FuncLinePairing, EmptyCU) {
    898   StartCU();
    899   root_handler_.Finish();
    900 
    901   TestFunctionCount(0);
    902 }
    903 
    904 TEST_F(FuncLinePairing, LinesNoFuncs) {
    905   PushLine(40, 2, "line-file", 82485646);
    906   EXPECT_CALL(reporter_, UncoveredLine(_)).WillOnce(Return());
    907 
    908   StartCU();
    909   root_handler_.Finish();
    910 
    911   TestFunctionCount(0);
    912 }
    913 
    914 TEST_F(FuncLinePairing, FuncsNoLines) {
    915   EXPECT_CALL(reporter_, UncoveredFunction(_)).WillOnce(Return());
    916 
    917   StartCU();
    918   DefineFunction(&root_handler_, "function1", 0x127da12ffcf5c51fULL, 0x1000U,
    919                  NULL);
    920   root_handler_.Finish();
    921 
    922   TestFunctionCount(1);
    923   TestFunction(0, "function1", 0x127da12ffcf5c51fULL, 0x1000U);
    924 }
    925 
    926 TEST_F(FuncLinePairing, GapThenFunction) {
    927   PushLine(20, 2, "line-file-2", 174314698);
    928   PushLine(10, 2, "line-file-1", 263008005);
    929 
    930   StartCU();
    931   DefineFunction(&root_handler_, "function1", 10, 2, NULL);
    932   DefineFunction(&root_handler_, "function2", 20, 2, NULL);
    933   root_handler_.Finish();
    934 
    935   TestFunctionCount(2);
    936   TestFunction(0, "function1", 10, 2);
    937   TestLineCount(0, 1);
    938   TestLine(0, 0, 10, 2, "line-file-1", 263008005);
    939   TestFunction(1, "function2", 20, 2);
    940   TestLineCount(1, 1);
    941   TestLine(1, 0, 20, 2, "line-file-2", 174314698);
    942 }
    943 
    944 // If GCC emits padding after one function to align the start of
    945 // the next, then it will attribute the padding instructions to
    946 // the last source line of function (to reduce the size of the
    947 // line number info), but omit it from the DW_AT_{low,high}_pc
    948 // range given in .debug_info (since it costs nothing to be
    949 // precise there).  If we did use at least some of the line
    950 // we're about to skip, then assume this is what happened, and
    951 // don't warn.
    952 TEST_F(FuncLinePairing, GCCAlignmentStretch) {
    953   PushLine(10, 10, "line-file", 63351048);
    954   PushLine(20, 10, "line-file", 61661044);
    955 
    956   StartCU();
    957   DefineFunction(&root_handler_, "function1", 10, 5, NULL);
    958   // five-byte gap between functions, covered by line 63351048.
    959   // This should not elicit a warning.
    960   DefineFunction(&root_handler_, "function2", 20, 10, NULL);
    961   root_handler_.Finish();
    962 
    963   TestFunctionCount(2);
    964   TestFunction(0, "function1", 10, 5);
    965   TestLineCount(0, 1);
    966   TestLine(0, 0, 10, 5, "line-file", 63351048);
    967   TestFunction(1, "function2", 20, 10);
    968   TestLineCount(1, 1);
    969   TestLine(1, 0, 20, 10, "line-file", 61661044);
    970 }
    971 
    972 // Unfortunately, neither the DWARF parser's handler interface nor the
    973 // DIEHandler interface is capable of expressing a function that abuts
    974 // the end of the address space: the high_pc value looks like zero.
    975 
    976 TEST_F(FuncLinePairing, LineAtEndOfAddressSpace) {
    977   PushLine(0xfffffffffffffff0ULL, 16, "line-file", 63351048);
    978   EXPECT_CALL(reporter_, UncoveredLine(_)).WillOnce(Return());
    979 
    980   StartCU();
    981   DefineFunction(&root_handler_, "function1", 0xfffffffffffffff0ULL, 6, NULL);
    982   DefineFunction(&root_handler_, "function2", 0xfffffffffffffffaULL, 5, NULL);
    983   root_handler_.Finish();
    984 
    985   TestFunctionCount(2);
    986   TestFunction(0, "function1", 0xfffffffffffffff0ULL, 6);
    987   TestLineCount(0, 1);
    988   TestLine(0, 0, 0xfffffffffffffff0ULL, 6, "line-file", 63351048);
    989   TestFunction(1, "function2", 0xfffffffffffffffaULL, 5);
    990   TestLineCount(1, 1);
    991   TestLine(1, 0, 0xfffffffffffffffaULL, 5, "line-file", 63351048);
    992 }
    993 
    994 // A function with more than one uncovered area should only be warned
    995 // about once.
    996 TEST_F(FuncLinePairing, WarnOnceFunc) {
    997   PushLine(20, 1, "line-file-2", 262951329);
    998   PushLine(11, 1, "line-file-1", 219964021);
    999   EXPECT_CALL(reporter_, UncoveredFunction(_)).WillOnce(Return());
   1000 
   1001   StartCU();
   1002   DefineFunction(&root_handler_, "function", 10, 11, NULL);
   1003   root_handler_.Finish();
   1004 
   1005   TestFunctionCount(1);
   1006   TestFunction(0, "function", 10, 11);
   1007   TestLineCount(0, 2);
   1008   TestLine(0, 0, 11, 1, "line-file-1", 219964021);
   1009   TestLine(0, 1, 20, 1, "line-file-2", 262951329);
   1010 }
   1011 
   1012 // A line with more than one uncovered area should only be warned
   1013 // about once.
   1014 TEST_F(FuncLinePairing, WarnOnceLine) {
   1015   PushLine(10, 20, "filename1", 118581871);
   1016   EXPECT_CALL(reporter_, UncoveredLine(_)).WillOnce(Return());
   1017 
   1018   StartCU();
   1019   DefineFunction(&root_handler_, "function1", 11, 1, NULL);
   1020   DefineFunction(&root_handler_, "function2", 13, 1, NULL);
   1021   root_handler_.Finish();
   1022 
   1023   TestFunctionCount(2);
   1024   TestFunction(0, "function1", 11, 1);
   1025   TestLineCount(0, 1);
   1026   TestLine(0, 0, 11, 1, "filename1", 118581871);
   1027   TestFunction(1, "function2", 13, 1);
   1028   TestLineCount(1, 1);
   1029   TestLine(1, 0, 13, 1, "filename1", 118581871);
   1030 }
   1031 
   1032 class CXXQualifiedNames: public CUFixtureBase,
   1033                          public TestWithParam<DwarfTag> { };
   1034 
   1035 INSTANTIATE_TEST_CASE_P(VersusEnclosures, CXXQualifiedNames,
   1036                         Values(dwarf2reader::DW_TAG_class_type,
   1037                                dwarf2reader::DW_TAG_structure_type,
   1038                                dwarf2reader::DW_TAG_union_type,
   1039                                dwarf2reader::DW_TAG_namespace));
   1040 
   1041 TEST_P(CXXQualifiedNames, TwoFunctions) {
   1042   DwarfTag tag = GetParam();
   1043 
   1044   SetLanguage(dwarf2reader::DW_LANG_C_plus_plus);
   1045   PushLine(10, 1, "filename1", 69819327);
   1046   PushLine(20, 1, "filename2", 95115701);
   1047 
   1048   StartCU();
   1049   DIEHandler *enclosure_handler = StartNamedDIE(&root_handler_, tag,
   1050                                                 "Enclosure");
   1051   EXPECT_TRUE(enclosure_handler != NULL);
   1052   DefineFunction(enclosure_handler, "func_B", 10, 1, NULL);
   1053   DefineFunction(enclosure_handler, "func_C", 20, 1, NULL);
   1054   enclosure_handler->Finish();
   1055   delete enclosure_handler;
   1056   root_handler_.Finish();
   1057 
   1058   TestFunctionCount(2);
   1059   TestFunction(0, "Enclosure::func_B", 10, 1);
   1060   TestFunction(1, "Enclosure::func_C", 20, 1);
   1061 }
   1062 
   1063 TEST_P(CXXQualifiedNames, FuncInEnclosureInNamespace) {
   1064   DwarfTag tag = GetParam();
   1065 
   1066   SetLanguage(dwarf2reader::DW_LANG_C_plus_plus);
   1067   PushLine(10, 1, "line-file", 69819327);
   1068 
   1069   StartCU();
   1070   DIEHandler *namespace_handler
   1071       = StartNamedDIE(&root_handler_, dwarf2reader::DW_TAG_namespace,
   1072                       "Namespace");
   1073   EXPECT_TRUE(namespace_handler != NULL);
   1074   DIEHandler *enclosure_handler = StartNamedDIE(namespace_handler, tag,
   1075                                                 "Enclosure");
   1076   EXPECT_TRUE(enclosure_handler != NULL);
   1077   DefineFunction(enclosure_handler, "function", 10, 1, NULL);
   1078   enclosure_handler->Finish();
   1079   delete enclosure_handler;
   1080   namespace_handler->Finish();
   1081   delete namespace_handler;
   1082   root_handler_.Finish();
   1083 
   1084   TestFunctionCount(1);
   1085   TestFunction(0, "Namespace::Enclosure::function", 10, 1);
   1086 }
   1087 
   1088 TEST_F(CXXQualifiedNames, FunctionInClassInStructInNamespace) {
   1089   SetLanguage(dwarf2reader::DW_LANG_C_plus_plus);
   1090   PushLine(10, 1, "filename1", 69819327);
   1091 
   1092   StartCU();
   1093   DIEHandler *namespace_handler
   1094       = StartNamedDIE(&root_handler_, dwarf2reader::DW_TAG_namespace,
   1095                       "namespace_A");
   1096   EXPECT_TRUE(namespace_handler != NULL);
   1097   DIEHandler *struct_handler
   1098       = StartNamedDIE(namespace_handler, dwarf2reader::DW_TAG_structure_type,
   1099                       "struct_B");
   1100   EXPECT_TRUE(struct_handler != NULL);
   1101   DIEHandler *class_handler
   1102       = StartNamedDIE(struct_handler, dwarf2reader::DW_TAG_class_type,
   1103                       "class_C");
   1104   DefineFunction(class_handler, "function_D", 10, 1, NULL);
   1105   class_handler->Finish();
   1106   delete class_handler;
   1107   struct_handler->Finish();
   1108   delete struct_handler;
   1109   namespace_handler->Finish();
   1110   delete namespace_handler;
   1111   root_handler_.Finish();
   1112 
   1113   TestFunctionCount(1);
   1114   TestFunction(0, "namespace_A::struct_B::class_C::function_D", 10, 1);
   1115 }
   1116 
   1117 struct LanguageAndQualifiedName {
   1118   dwarf2reader::DwarfLanguage language;
   1119   const char *name;
   1120 };
   1121 
   1122 const LanguageAndQualifiedName LanguageAndQualifiedNameCases[] = {
   1123   { dwarf2reader::DW_LANG_none,           "class_A::function_B" },
   1124   { dwarf2reader::DW_LANG_C,              "class_A::function_B" },
   1125   { dwarf2reader::DW_LANG_C89,            "class_A::function_B" },
   1126   { dwarf2reader::DW_LANG_C99,            "class_A::function_B" },
   1127   { dwarf2reader::DW_LANG_C_plus_plus,    "class_A::function_B" },
   1128   { dwarf2reader::DW_LANG_Java,           "class_A.function_B" },
   1129   { dwarf2reader::DW_LANG_Cobol74,        "class_A::function_B" },
   1130   { dwarf2reader::DW_LANG_Mips_Assembler, NULL }
   1131 };
   1132 
   1133 class QualifiedForLanguage
   1134     : public CUFixtureBase,
   1135       public TestWithParam<LanguageAndQualifiedName> { };
   1136 
   1137 INSTANTIATE_TEST_CASE_P(LanguageAndQualifiedName, QualifiedForLanguage,
   1138                         ValuesIn(LanguageAndQualifiedNameCases));
   1139 
   1140 TEST_P(QualifiedForLanguage, MemberFunction) {
   1141   const LanguageAndQualifiedName &param = GetParam();
   1142 
   1143   PushLine(10, 1, "line-file", 212966758);
   1144   SetLanguage(param.language);
   1145 
   1146   StartCU();
   1147   DIEHandler *class_handler
   1148       = StartNamedDIE(&root_handler_, dwarf2reader::DW_TAG_class_type,
   1149                       "class_A");
   1150   DefineFunction(class_handler, "function_B", 10, 1, NULL);
   1151   class_handler->Finish();
   1152   delete class_handler;
   1153   root_handler_.Finish();
   1154 
   1155   if (param.name) {
   1156     TestFunctionCount(1);
   1157     TestFunction(0, param.name, 10, 1);
   1158   } else {
   1159     TestFunctionCount(0);
   1160   }
   1161 }
   1162 
   1163 TEST_P(QualifiedForLanguage, MemberFunctionSignedLanguage) {
   1164   const LanguageAndQualifiedName &param = GetParam();
   1165 
   1166   PushLine(10, 1, "line-file", 212966758);
   1167   SetLanguage(param.language);
   1168   SetLanguageSigned(true);
   1169 
   1170   StartCU();
   1171   DIEHandler *class_handler
   1172       = StartNamedDIE(&root_handler_, dwarf2reader::DW_TAG_class_type,
   1173                       "class_A");
   1174   DefineFunction(class_handler, "function_B", 10, 1, NULL);
   1175   class_handler->Finish();
   1176   delete class_handler;
   1177   root_handler_.Finish();
   1178 
   1179   if (param.name) {
   1180     TestFunctionCount(1);
   1181     TestFunction(0, param.name, 10, 1);
   1182   } else {
   1183     TestFunctionCount(0);
   1184   }
   1185 }
   1186 
   1187 class Specifications: public CUFixtureBase, public Test { };
   1188 
   1189 TEST_F(Specifications, Function) {
   1190   PushLine(0x93cd3dfc1aa10097ULL, 0x0397d47a0b4ca0d4ULL, "line-file", 54883661);
   1191 
   1192   StartCU();
   1193   DeclarationDIE(&root_handler_, 0xcd3c51b946fb1eeeLL,
   1194                  dwarf2reader::DW_TAG_subprogram, "declaration-name", "");
   1195   DefinitionDIE(&root_handler_, dwarf2reader::DW_TAG_subprogram,
   1196                 0xcd3c51b946fb1eeeLL, "",
   1197                 0x93cd3dfc1aa10097ULL, 0x0397d47a0b4ca0d4ULL);
   1198   root_handler_.Finish();
   1199 
   1200   TestFunctionCount(1);
   1201   TestFunction(0, "declaration-name",
   1202                0x93cd3dfc1aa10097ULL, 0x0397d47a0b4ca0d4ULL);
   1203 }
   1204 
   1205 TEST_F(Specifications, MangledName) {
   1206   PushLine(0x93cd3dfc1aa10097ULL, 0x0397d47a0b4ca0d4ULL, "line-file", 54883661);
   1207 
   1208   StartCU();
   1209   DeclarationDIE(&root_handler_, 0xcd3c51b946fb1eeeLL,
   1210                  dwarf2reader::DW_TAG_subprogram, "declaration-name",
   1211                  "_ZN1C1fEi");
   1212   DefinitionDIE(&root_handler_, dwarf2reader::DW_TAG_subprogram,
   1213                 0xcd3c51b946fb1eeeLL, "",
   1214                 0x93cd3dfc1aa10097ULL, 0x0397d47a0b4ca0d4ULL);
   1215   root_handler_.Finish();
   1216 
   1217   TestFunctionCount(1);
   1218   TestFunction(0, "C::f(int)",
   1219                0x93cd3dfc1aa10097ULL, 0x0397d47a0b4ca0d4ULL);
   1220 }
   1221 
   1222 TEST_F(Specifications, MemberFunction) {
   1223   PushLine(0x3341a248634e7170ULL, 0x5f6938ee5553b953ULL, "line-file", 18116691);
   1224 
   1225   StartCU();
   1226   DIEHandler *class_handler
   1227     = StartNamedDIE(&root_handler_, dwarf2reader::DW_TAG_class_type, "class_A");
   1228   DeclarationDIE(class_handler, 0x7d83028c431406e8ULL,
   1229                  dwarf2reader::DW_TAG_subprogram, "declaration-name", "");
   1230   class_handler->Finish();
   1231   delete class_handler;
   1232   DefinitionDIE(&root_handler_, dwarf2reader::DW_TAG_subprogram,
   1233                 0x7d83028c431406e8ULL, "",
   1234                 0x3341a248634e7170ULL, 0x5f6938ee5553b953ULL);
   1235   root_handler_.Finish();
   1236 
   1237   TestFunctionCount(1);
   1238   TestFunction(0, "class_A::declaration-name",
   1239                0x3341a248634e7170ULL, 0x5f6938ee5553b953ULL);
   1240 }
   1241 
   1242 // This case should gather the name from both the definition and the
   1243 // declaration's parent.
   1244 TEST_F(Specifications, FunctionDeclarationParent) {
   1245   PushLine(0x463c9ddf405be227ULL, 0x6a47774af5049680ULL, "line-file", 70254922);
   1246 
   1247   StartCU();
   1248   {
   1249     DIEHandler *class_handler
   1250       = StartNamedDIE(&root_handler_, dwarf2reader::DW_TAG_class_type,
   1251                       "class_A");
   1252     ASSERT_TRUE(class_handler != NULL);
   1253     DeclarationDIE(class_handler, 0x0e0e877c8404544aULL,
   1254                    dwarf2reader::DW_TAG_subprogram, "declaration-name", "");
   1255     class_handler->Finish();
   1256     delete class_handler;
   1257   }
   1258 
   1259   DefinitionDIE(&root_handler_, dwarf2reader::DW_TAG_subprogram,
   1260                 0x0e0e877c8404544aULL, "definition-name",
   1261                 0x463c9ddf405be227ULL, 0x6a47774af5049680ULL);
   1262 
   1263   root_handler_.Finish();
   1264 
   1265   TestFunctionCount(1);
   1266   TestFunction(0, "class_A::definition-name",
   1267                0x463c9ddf405be227ULL, 0x6a47774af5049680ULL);
   1268 }
   1269 
   1270 // Named scopes should also gather enclosing name components from
   1271 // their declarations.
   1272 TEST_F(Specifications, NamedScopeDeclarationParent) {
   1273   PushLine(0x5d13433d0df13d00ULL, 0x48ebebe5ade2cab4ULL, "line-file", 77392604);
   1274 
   1275   StartCU();
   1276   {
   1277     DIEHandler *space_handler
   1278       = StartNamedDIE(&root_handler_, dwarf2reader::DW_TAG_namespace,
   1279                       "space_A");
   1280     ASSERT_TRUE(space_handler != NULL);
   1281     DeclarationDIE(space_handler, 0x419bb1d12f9a73a2ULL,
   1282                    dwarf2reader::DW_TAG_class_type, "class-declaration-name",
   1283                    "");
   1284     space_handler->Finish();
   1285     delete space_handler;
   1286   }
   1287 
   1288   {
   1289     DIEHandler *class_handler
   1290       = StartSpecifiedDIE(&root_handler_, dwarf2reader::DW_TAG_class_type,
   1291                           0x419bb1d12f9a73a2ULL, "class-definition-name");
   1292     ASSERT_TRUE(class_handler != NULL);
   1293     DefineFunction(class_handler, "function",
   1294                    0x5d13433d0df13d00ULL, 0x48ebebe5ade2cab4ULL, NULL);
   1295     class_handler->Finish();
   1296     delete class_handler;
   1297   }
   1298 
   1299   root_handler_.Finish();
   1300 
   1301   TestFunctionCount(1);
   1302   TestFunction(0, "space_A::class-definition-name::function",
   1303                0x5d13433d0df13d00ULL, 0x48ebebe5ade2cab4ULL);
   1304 }
   1305 
   1306 // This test recreates bug 364.
   1307 TEST_F(Specifications, InlineFunction) {
   1308   PushLine(0x1758a0f941b71efbULL, 0x1cf154f1f545e146ULL, "line-file", 75173118);
   1309 
   1310   StartCU();
   1311   DeclarationDIE(&root_handler_, 0xcd3c51b946fb1eeeLL,
   1312                  dwarf2reader::DW_TAG_subprogram, "inline-name", "");
   1313   AbstractInstanceDIE(&root_handler_, 0x1e8dac5d507ed7abULL,
   1314                       dwarf2reader::DW_INL_inlined, 0xcd3c51b946fb1eeeLL, "");
   1315   DefineInlineInstanceDIE(&root_handler_, "", 0x1e8dac5d507ed7abULL,
   1316                        0x1758a0f941b71efbULL, 0x1cf154f1f545e146ULL);
   1317   root_handler_.Finish();
   1318 
   1319   TestFunctionCount(1);
   1320   TestFunction(0, "inline-name",
   1321                0x1758a0f941b71efbULL, 0x1cf154f1f545e146ULL);
   1322 }
   1323 
   1324 // Check name construction for a long chain containing each combination of:
   1325 // - struct, union, class, namespace
   1326 // - direct and definition
   1327 TEST_F(Specifications, LongChain) {
   1328   PushLine(0x5a0dd6bb85db754cULL, 0x3bccb213d08c7fd3ULL, "line-file", 21192926);
   1329   SetLanguage(dwarf2reader::DW_LANG_C_plus_plus);
   1330 
   1331   StartCU();
   1332   // The structure we're building here is:
   1333   // space_A full definition
   1334   //   space_B declaration
   1335   // space_B definition
   1336   //   struct_C full definition
   1337   //     struct_D declaration
   1338   // struct_D definition
   1339   //   union_E full definition
   1340   //     union_F declaration
   1341   // union_F definition
   1342   //   class_G full definition
   1343   //     class_H declaration
   1344   // class_H definition
   1345   //   func_I declaration
   1346   // func_I definition
   1347   //
   1348   // So:
   1349   // - space_A, struct_C, union_E, and class_G don't use specifications;
   1350   // - space_B, struct_D, union_F, and class_H do.
   1351   // - func_I uses a specification.
   1352   //
   1353   // The full name for func_I is thus:
   1354   //
   1355   // space_A::space_B::struct_C::struct_D::union_E::union_F::
   1356   //   class_G::class_H::func_I
   1357   {
   1358     DIEHandler *space_A_handler
   1359       = StartNamedDIE(&root_handler_, dwarf2reader::DW_TAG_namespace,
   1360                       "space_A");
   1361     DeclarationDIE(space_A_handler, 0x2e111126496596e2ULL,
   1362                    dwarf2reader::DW_TAG_namespace, "space_B", "");
   1363     space_A_handler->Finish();
   1364     delete space_A_handler;
   1365   }
   1366 
   1367   {
   1368     DIEHandler *space_B_handler
   1369       = StartSpecifiedDIE(&root_handler_, dwarf2reader::DW_TAG_namespace,
   1370                           0x2e111126496596e2ULL);
   1371     DIEHandler *struct_C_handler
   1372       = StartNamedDIE(space_B_handler, dwarf2reader::DW_TAG_structure_type,
   1373                       "struct_C");
   1374     DeclarationDIE(struct_C_handler, 0x20cd423bf2a25a4cULL,
   1375                    dwarf2reader::DW_TAG_structure_type, "struct_D", "");
   1376     struct_C_handler->Finish();
   1377     delete struct_C_handler;
   1378     space_B_handler->Finish();
   1379     delete space_B_handler;
   1380   }
   1381 
   1382   {
   1383     DIEHandler *struct_D_handler
   1384       = StartSpecifiedDIE(&root_handler_, dwarf2reader::DW_TAG_structure_type,
   1385                           0x20cd423bf2a25a4cULL);
   1386     DIEHandler *union_E_handler
   1387       = StartNamedDIE(struct_D_handler, dwarf2reader::DW_TAG_union_type,
   1388                       "union_E");
   1389     DeclarationDIE(union_E_handler, 0xe25c84805aa58c32ULL,
   1390                    dwarf2reader::DW_TAG_union_type, "union_F", "");
   1391     union_E_handler->Finish();
   1392     delete union_E_handler;
   1393     struct_D_handler->Finish();
   1394     delete struct_D_handler;
   1395   }
   1396 
   1397   {
   1398     DIEHandler *union_F_handler
   1399       = StartSpecifiedDIE(&root_handler_, dwarf2reader::DW_TAG_union_type,
   1400                           0xe25c84805aa58c32ULL);
   1401     DIEHandler *class_G_handler
   1402       = StartNamedDIE(union_F_handler, dwarf2reader::DW_TAG_class_type,
   1403                       "class_G");
   1404     DeclarationDIE(class_G_handler, 0xb70d960dcc173b6eULL,
   1405                    dwarf2reader::DW_TAG_class_type, "class_H", "");
   1406     class_G_handler->Finish();
   1407     delete class_G_handler;
   1408     union_F_handler->Finish();
   1409     delete union_F_handler;
   1410   }
   1411 
   1412   {
   1413     DIEHandler *class_H_handler
   1414       = StartSpecifiedDIE(&root_handler_, dwarf2reader::DW_TAG_class_type,
   1415                           0xb70d960dcc173b6eULL);
   1416     DeclarationDIE(class_H_handler, 0x27ff829e3bf69f37ULL,
   1417                    dwarf2reader::DW_TAG_subprogram, "func_I", "");
   1418     class_H_handler->Finish();
   1419     delete class_H_handler;
   1420   }
   1421 
   1422   DefinitionDIE(&root_handler_, dwarf2reader::DW_TAG_subprogram,
   1423                 0x27ff829e3bf69f37ULL, "",
   1424                 0x5a0dd6bb85db754cULL, 0x3bccb213d08c7fd3ULL);
   1425   root_handler_.Finish();
   1426 
   1427   TestFunctionCount(1);
   1428   TestFunction(0, "space_A::space_B::struct_C::struct_D::union_E::union_F"
   1429                "::class_G::class_H::func_I",
   1430                0x5a0dd6bb85db754cULL, 0x3bccb213d08c7fd3ULL);
   1431 }
   1432 
   1433 TEST_F(Specifications, InterCU) {
   1434   Module m("module-name", "module-os", "module-arch", "module-id");
   1435   DwarfCUToModule::FileContext fc("dwarf-filename", &m, true);
   1436   EXPECT_CALL(reporter_, UncoveredFunction(_)).WillOnce(Return());
   1437   MockLineToModuleHandler lr;
   1438   EXPECT_CALL(lr, ReadProgram(_,_,_,_)).Times(0);
   1439 
   1440   // Kludge: satisfy reporter_'s expectation.
   1441   reporter_.SetCUName("compilation-unit-name");
   1442 
   1443   // First CU.  Declares class_A.
   1444   {
   1445     DwarfCUToModule root1_handler(&fc, &lr, &reporter_);
   1446     ASSERT_TRUE(root1_handler.StartCompilationUnit(0, 1, 2, 3, 3));
   1447     ASSERT_TRUE(root1_handler.StartRootDIE(1,
   1448                                            dwarf2reader::DW_TAG_compile_unit));
   1449     ProcessStrangeAttributes(&root1_handler);
   1450     ASSERT_TRUE(root1_handler.EndAttributes());
   1451     DeclarationDIE(&root1_handler, 0xb8fbfdd5f0b26fceULL,
   1452                    dwarf2reader::DW_TAG_class_type, "class_A", "");
   1453     root1_handler.Finish();
   1454   }
   1455 
   1456   // Second CU.  Defines class_A, declares member_func_B.
   1457   {
   1458     DwarfCUToModule root2_handler(&fc, &lr, &reporter_);
   1459     ASSERT_TRUE(root2_handler.StartCompilationUnit(0, 1, 2, 3, 3));
   1460     ASSERT_TRUE(root2_handler.StartRootDIE(1,
   1461                                            dwarf2reader::DW_TAG_compile_unit));
   1462     ASSERT_TRUE(root2_handler.EndAttributes());
   1463     DIEHandler *class_A_handler
   1464       = StartSpecifiedDIE(&root2_handler, dwarf2reader::DW_TAG_class_type,
   1465                           0xb8fbfdd5f0b26fceULL);
   1466     DeclarationDIE(class_A_handler, 0xb01fef8b380bd1a2ULL,
   1467                    dwarf2reader::DW_TAG_subprogram, "member_func_B", "");
   1468     class_A_handler->Finish();
   1469     delete class_A_handler;
   1470     root2_handler.Finish();
   1471   }
   1472 
   1473   // Third CU.  Defines member_func_B.
   1474   {
   1475     DwarfCUToModule root3_handler(&fc, &lr, &reporter_);
   1476     ASSERT_TRUE(root3_handler.StartCompilationUnit(0, 1, 2, 3, 3));
   1477     ASSERT_TRUE(root3_handler.StartRootDIE(1,
   1478                                            dwarf2reader::DW_TAG_compile_unit));
   1479     ASSERT_TRUE(root3_handler.EndAttributes());
   1480     DefinitionDIE(&root3_handler, dwarf2reader::DW_TAG_subprogram,
   1481                   0xb01fef8b380bd1a2ULL, "",
   1482                   0x2618f00a1a711e53ULL, 0x4fd94b76d7c2caf5ULL);
   1483     root3_handler.Finish();
   1484   }
   1485 
   1486   vector<Module::Function *> functions;
   1487   m.GetFunctions(&functions, functions.end());
   1488   EXPECT_EQ(1U, functions.size());
   1489   EXPECT_STREQ("class_A::member_func_B", functions[0]->name.c_str());
   1490 }
   1491 
   1492 TEST_F(Specifications, UnhandledInterCU) {
   1493   Module m("module-name", "module-os", "module-arch", "module-id");
   1494   DwarfCUToModule::FileContext fc("dwarf-filename", &m, false);
   1495   EXPECT_CALL(reporter_, UncoveredFunction(_)).WillOnce(Return());
   1496   MockLineToModuleHandler lr;
   1497   EXPECT_CALL(lr, ReadProgram(_,_,_,_)).Times(0);
   1498 
   1499   // Kludge: satisfy reporter_'s expectation.
   1500   reporter_.SetCUName("compilation-unit-name");
   1501 
   1502   // First CU.  Declares class_A.
   1503   {
   1504     DwarfCUToModule root1_handler(&fc, &lr, &reporter_);
   1505     ASSERT_TRUE(root1_handler.StartCompilationUnit(0, 1, 2, 3, 3));
   1506     ASSERT_TRUE(root1_handler.StartRootDIE(1,
   1507                                            dwarf2reader::DW_TAG_compile_unit));
   1508     ProcessStrangeAttributes(&root1_handler);
   1509     ASSERT_TRUE(root1_handler.EndAttributes());
   1510     DeclarationDIE(&root1_handler, 0xb8fbfdd5f0b26fceULL,
   1511                    dwarf2reader::DW_TAG_class_type, "class_A", "");
   1512     root1_handler.Finish();
   1513   }
   1514 
   1515   // Second CU.  Defines class_A, declares member_func_B.
   1516   {
   1517     DwarfCUToModule root2_handler(&fc, &lr, &reporter_);
   1518     ASSERT_TRUE(root2_handler.StartCompilationUnit(0, 1, 2, 3, 3));
   1519     ASSERT_TRUE(root2_handler.StartRootDIE(1,
   1520                                            dwarf2reader::DW_TAG_compile_unit));
   1521     ASSERT_TRUE(root2_handler.EndAttributes());
   1522     EXPECT_CALL(reporter_, UnhandledInterCUReference(_, _)).Times(1);
   1523     DIEHandler *class_A_handler
   1524       = StartSpecifiedDIE(&root2_handler, dwarf2reader::DW_TAG_class_type,
   1525                           0xb8fbfdd5f0b26fceULL);
   1526     DeclarationDIE(class_A_handler, 0xb01fef8b380bd1a2ULL,
   1527                    dwarf2reader::DW_TAG_subprogram, "member_func_B", "");
   1528     class_A_handler->Finish();
   1529     delete class_A_handler;
   1530     root2_handler.Finish();
   1531   }
   1532 
   1533   // Third CU.  Defines member_func_B.
   1534   {
   1535     DwarfCUToModule root3_handler(&fc, &lr, &reporter_);
   1536     ASSERT_TRUE(root3_handler.StartCompilationUnit(0, 1, 2, 3, 3));
   1537     ASSERT_TRUE(root3_handler.StartRootDIE(1,
   1538                                            dwarf2reader::DW_TAG_compile_unit));
   1539     ASSERT_TRUE(root3_handler.EndAttributes());
   1540     EXPECT_CALL(reporter_, UnhandledInterCUReference(_, _)).Times(1);
   1541     EXPECT_CALL(reporter_, UnnamedFunction(_)).Times(1);
   1542     DefinitionDIE(&root3_handler, dwarf2reader::DW_TAG_subprogram,
   1543                   0xb01fef8b380bd1a2ULL, "",
   1544                   0x2618f00a1a711e53ULL, 0x4fd94b76d7c2caf5ULL);
   1545     root3_handler.Finish();
   1546   }
   1547 }
   1548 
   1549 TEST_F(Specifications, BadOffset) {
   1550   PushLine(0xa0277efd7ce83771ULL, 0x149554a184c730c1ULL, "line-file", 56636272);
   1551   EXPECT_CALL(reporter_, UnknownSpecification(_, 0x2be953efa6f9a996ULL))
   1552     .WillOnce(Return());
   1553 
   1554   StartCU();
   1555   DeclarationDIE(&root_handler_, 0xefd7f7752c27b7e4ULL,
   1556                  dwarf2reader::DW_TAG_subprogram, "", "");
   1557   DefinitionDIE(&root_handler_, dwarf2reader::DW_TAG_subprogram,
   1558                 0x2be953efa6f9a996ULL, "function",
   1559                 0xa0277efd7ce83771ULL, 0x149554a184c730c1ULL);
   1560   root_handler_.Finish();
   1561 }
   1562 
   1563 TEST_F(Specifications, FunctionDefinitionHasOwnName) {
   1564   PushLine(0xced50b3eea81022cULL, 0x08dd4d301cc7a7d2ULL, "line-file", 56792403);
   1565 
   1566   StartCU();
   1567   DeclarationDIE(&root_handler_, 0xc34ff4786cae78bdULL,
   1568                  dwarf2reader::DW_TAG_subprogram, "declaration-name", "");
   1569   DefinitionDIE(&root_handler_, dwarf2reader::DW_TAG_subprogram,
   1570                 0xc34ff4786cae78bdULL, "definition-name",
   1571                 0xced50b3eea81022cULL, 0x08dd4d301cc7a7d2ULL);
   1572   root_handler_.Finish();
   1573 
   1574   TestFunctionCount(1);
   1575   TestFunction(0, "definition-name",
   1576                0xced50b3eea81022cULL, 0x08dd4d301cc7a7d2ULL);
   1577 }
   1578 
   1579 TEST_F(Specifications, ClassDefinitionHasOwnName) {
   1580   PushLine(0x1d0f5e0f6ce309bdULL, 0x654e1852ec3599e7ULL, "line-file", 57119241);
   1581 
   1582   StartCU();
   1583   DeclarationDIE(&root_handler_, 0xd0fe467ec2f1a58cULL,
   1584                  dwarf2reader::DW_TAG_class_type, "class-declaration-name", "");
   1585 
   1586   dwarf2reader::DIEHandler *class_definition
   1587     = StartSpecifiedDIE(&root_handler_, dwarf2reader::DW_TAG_class_type,
   1588                         0xd0fe467ec2f1a58cULL, "class-definition-name");
   1589   ASSERT_TRUE(class_definition);
   1590   DeclarationDIE(class_definition, 0x6d028229c15623dbULL,
   1591                  dwarf2reader::DW_TAG_subprogram,
   1592                  "function-declaration-name", "");
   1593   class_definition->Finish();
   1594   delete class_definition;
   1595 
   1596   DefinitionDIE(&root_handler_, dwarf2reader::DW_TAG_subprogram,
   1597                 0x6d028229c15623dbULL, "function-definition-name",
   1598                 0x1d0f5e0f6ce309bdULL, 0x654e1852ec3599e7ULL);
   1599 
   1600   root_handler_.Finish();
   1601 
   1602   TestFunctionCount(1);
   1603   TestFunction(0, "class-definition-name::function-definition-name",
   1604                0x1d0f5e0f6ce309bdULL, 0x654e1852ec3599e7ULL);
   1605 }
   1606 
   1607 // DIEs that cite a specification should prefer the specification's
   1608 // parents over their own when choosing qualified names. In this test,
   1609 // we take the name from our definition but the enclosing scope name
   1610 // from our declaration. I don't see why they'd ever be different, but
   1611 // we want to verify what DwarfCUToModule is looking at.
   1612 TEST_F(Specifications, PreferSpecificationParents) {
   1613   PushLine(0xbbd9d54dce3b95b7ULL, 0x39188b7b52b0899fULL, "line-file", 79488694);
   1614 
   1615   StartCU();
   1616   {
   1617     dwarf2reader::DIEHandler *declaration_class_handler =
   1618       StartNamedDIE(&root_handler_, dwarf2reader::DW_TAG_class_type,
   1619                     "declaration-class");
   1620     DeclarationDIE(declaration_class_handler, 0x9ddb35517455ef7aULL,
   1621                    dwarf2reader::DW_TAG_subprogram, "function-declaration",
   1622                    "");
   1623     declaration_class_handler->Finish();
   1624     delete declaration_class_handler;
   1625   }
   1626   {
   1627     dwarf2reader::DIEHandler *definition_class_handler
   1628       = StartNamedDIE(&root_handler_, dwarf2reader::DW_TAG_class_type,
   1629                       "definition-class");
   1630     DefinitionDIE(definition_class_handler, dwarf2reader::DW_TAG_subprogram,
   1631                   0x9ddb35517455ef7aULL, "function-definition",
   1632                   0xbbd9d54dce3b95b7ULL, 0x39188b7b52b0899fULL);
   1633     definition_class_handler->Finish();
   1634     delete definition_class_handler;
   1635   }
   1636   root_handler_.Finish();
   1637 
   1638   TestFunctionCount(1);
   1639   TestFunction(0, "declaration-class::function-definition",
   1640                0xbbd9d54dce3b95b7ULL, 0x39188b7b52b0899fULL);
   1641 }
   1642 
   1643 class CUErrors: public CUFixtureBase, public Test { };
   1644 
   1645 TEST_F(CUErrors, BadStmtList) {
   1646   EXPECT_CALL(reporter_, BadLineInfoOffset(dummy_line_size_ + 10)).Times(1);
   1647 
   1648   ASSERT_TRUE(root_handler_
   1649               .StartCompilationUnit(0xc591d5b037543d7cULL, 0x11, 0xcd,
   1650                                     0x2d7d19546cf6590cULL, 3));
   1651   ASSERT_TRUE(root_handler_.StartRootDIE(0xae789dc102cfca54ULL,
   1652                                          dwarf2reader::DW_TAG_compile_unit));
   1653   root_handler_.ProcessAttributeString(dwarf2reader::DW_AT_name,
   1654                                        dwarf2reader::DW_FORM_strp,
   1655                                        "compilation-unit-name");
   1656   root_handler_.ProcessAttributeUnsigned(dwarf2reader::DW_AT_stmt_list,
   1657                                          dwarf2reader::DW_FORM_ref4,
   1658                                          dummy_line_size_ + 10);
   1659   root_handler_.EndAttributes();
   1660   root_handler_.Finish();
   1661 }
   1662 
   1663 TEST_F(CUErrors, NoLineSection) {
   1664   EXPECT_CALL(reporter_, MissingSection(".debug_line")).Times(1);
   1665   PushLine(0x88507fb678052611ULL, 0x42c8e9de6bbaa0faULL, "line-file", 64472290);
   1666   // Delete the entry for .debug_line added by the fixture class's constructor.
   1667   file_context_.ClearSectionMapForTest();
   1668 
   1669   StartCU();
   1670   root_handler_.Finish();
   1671 }
   1672 
   1673 TEST_F(CUErrors, BadDwarfVersion1) {
   1674   // Kludge: satisfy reporter_'s expectation.
   1675   reporter_.SetCUName("compilation-unit-name");
   1676 
   1677   ASSERT_FALSE(root_handler_
   1678                .StartCompilationUnit(0xadf6e0eb71e2b0d9ULL, 0x4d, 0x90,
   1679                                      0xc9de224ccb99ac3eULL, 1));
   1680 }
   1681 
   1682 TEST_F(CUErrors, GoodDwarfVersion2) {
   1683   // Kludge: satisfy reporter_'s expectation.
   1684   reporter_.SetCUName("compilation-unit-name");
   1685 
   1686   ASSERT_TRUE(root_handler_
   1687                .StartCompilationUnit(0xadf6e0eb71e2b0d9ULL, 0x4d, 0x90,
   1688                                      0xc9de224ccb99ac3eULL, 2));
   1689 }
   1690 
   1691 TEST_F(CUErrors, GoodDwarfVersion3) {
   1692   // Kludge: satisfy reporter_'s expectation.
   1693   reporter_.SetCUName("compilation-unit-name");
   1694 
   1695   ASSERT_TRUE(root_handler_
   1696                .StartCompilationUnit(0xadf6e0eb71e2b0d9ULL, 0x4d, 0x90,
   1697                                      0xc9de224ccb99ac3eULL, 3));
   1698 }
   1699 
   1700 TEST_F(CUErrors, BadCURootDIETag) {
   1701   // Kludge: satisfy reporter_'s expectation.
   1702   reporter_.SetCUName("compilation-unit-name");
   1703 
   1704   ASSERT_TRUE(root_handler_
   1705                .StartCompilationUnit(0xadf6e0eb71e2b0d9ULL, 0x4d, 0x90,
   1706                                      0xc9de224ccb99ac3eULL, 3));
   1707 
   1708   ASSERT_FALSE(root_handler_.StartRootDIE(0x02e56bfbda9e7337ULL,
   1709                                           dwarf2reader::DW_TAG_subprogram));
   1710 }
   1711 
   1712 // Tests for DwarfCUToModule::Reporter. These just produce (or fail to
   1713 // produce) output, so their results need to be checked by hand.
   1714 struct Reporter: public Test {
   1715   Reporter()
   1716       : reporter("filename", 0x123456789abcdef0ULL),
   1717         function("function name", 0x19c45c30770c1eb0ULL),
   1718         file("source file name") {
   1719     reporter.SetCUName("compilation-unit-name");
   1720 
   1721     function.size = 0x89808a5bdfa0a6a3ULL;
   1722     function.parameter_size = 0x6a329f18683dcd51ULL;
   1723 
   1724     line.address = 0x3606ac6267aebeccULL;
   1725     line.size = 0x5de482229f32556aULL;
   1726     line.file = &file;
   1727     line.number = 93400201;
   1728   }
   1729 
   1730   DwarfCUToModule::WarningReporter reporter;
   1731   Module::Function function;
   1732   Module::File file;
   1733   Module::Line line;
   1734 };
   1735 
   1736 TEST_F(Reporter, UnknownSpecification) {
   1737   reporter.UnknownSpecification(0x123456789abcdef1ULL, 0x323456789abcdef2ULL);
   1738 }
   1739 
   1740 TEST_F(Reporter, UnknownAbstractOrigin) {
   1741   reporter.UnknownAbstractOrigin(0x123456789abcdef1ULL, 0x323456789abcdef2ULL);
   1742 }
   1743 
   1744 TEST_F(Reporter, MissingSection) {
   1745   reporter.MissingSection("section name");
   1746 }
   1747 
   1748 TEST_F(Reporter, BadLineInfoOffset) {
   1749   reporter.BadLineInfoOffset(0x123456789abcdef1ULL);
   1750 }
   1751 
   1752 TEST_F(Reporter, UncoveredFunctionDisabled) {
   1753   reporter.UncoveredFunction(function);
   1754   EXPECT_FALSE(reporter.uncovered_warnings_enabled());
   1755 }
   1756 
   1757 TEST_F(Reporter, UncoveredFunctionEnabled) {
   1758   reporter.set_uncovered_warnings_enabled(true);
   1759   reporter.UncoveredFunction(function);
   1760   EXPECT_TRUE(reporter.uncovered_warnings_enabled());
   1761 }
   1762 
   1763 TEST_F(Reporter, UncoveredLineDisabled) {
   1764   reporter.UncoveredLine(line);
   1765   EXPECT_FALSE(reporter.uncovered_warnings_enabled());
   1766 }
   1767 
   1768 TEST_F(Reporter, UncoveredLineEnabled) {
   1769   reporter.set_uncovered_warnings_enabled(true);
   1770   reporter.UncoveredLine(line);
   1771   EXPECT_TRUE(reporter.uncovered_warnings_enabled());
   1772 }
   1773 
   1774 TEST_F(Reporter, UnnamedFunction) {
   1775   reporter.UnnamedFunction(0x90c0baff9dedb2d9ULL);
   1776 }
   1777 
   1778 // Would be nice to also test:
   1779 // - overlapping lines, functions
   1780