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