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