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