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 // Implement the DwarfCUToModule class; see dwarf_cu_to_module.h.
33 
34 // For <inttypes.h> PRI* macros, before anything else might #include it.
35 #ifndef __STDC_FORMAT_MACROS
36 #define __STDC_FORMAT_MACROS
37 #endif  /* __STDC_FORMAT_MACROS */
38 
39 #include "common/dwarf_cu_to_module.h"
40 
41 #include <assert.h>
42 #include <inttypes.h>
43 #include <stdint.h>
44 #include <stdio.h>
45 
46 #include <algorithm>
47 #include <numeric>
48 #include <utility>
49 
50 #include "common/dwarf_line_to_module.h"
51 #include "common/unordered.h"
52 
53 namespace google_breakpad {
54 
55 using std::accumulate;
56 using std::map;
57 using std::pair;
58 using std::sort;
59 using std::vector;
60 
61 // Data provided by a DWARF specification DIE.
62 //
63 // In DWARF, the DIE for a definition may contain a DW_AT_specification
64 // attribute giving the offset of the corresponding declaration DIE, and
65 // the definition DIE may omit information given in the declaration. For
66 // example, it's common for a function's address range to appear only in
67 // its definition DIE, but its name to appear only in its declaration
68 // DIE.
69 //
70 // The dumper needs to be able to follow DW_AT_specification links to
71 // bring all this information together in a FUNC record. Conveniently,
72 // DIEs that are the target of such links have a DW_AT_declaration flag
73 // set, so we can identify them when we first see them, and record their
74 // contents for later reference.
75 //
76 // A Specification holds information gathered from a declaration DIE that
77 // we may need if we find a DW_AT_specification link pointing to it.
78 struct DwarfCUToModule::Specification {
79   // The qualified name that can be found by demangling DW_AT_MIPS_linkage_name.
80   string qualified_name;
81 
82   // The name of the enclosing scope, or the empty string if there is none.
83   string enclosing_name;
84 
85   // The name for the specification DIE itself, without any enclosing
86   // name components.
87   string unqualified_name;
88 };
89 
90 // An abstract origin -- base definition of an inline function.
91 struct AbstractOrigin {
AbstractOrigingoogle_breakpad::AbstractOrigin92   AbstractOrigin() : name() {}
AbstractOrigingoogle_breakpad::AbstractOrigin93   explicit AbstractOrigin(const string& name) : name(name) {}
94 
95   string name;
96 };
97 
98 typedef map<uint64, AbstractOrigin> AbstractOriginByOffset;
99 
100 // Data global to the DWARF-bearing file that is private to the
101 // DWARF-to-Module process.
102 struct DwarfCUToModule::FilePrivate {
103   // A set of strings used in this CU. Before storing a string in one of
104   // our data structures, insert it into this set, and then use the string
105   // from the set.
106   //
107   // In some STL implementations, strings are reference-counted internally,
108   // meaning that simply using strings from this set, even if passed by
109   // value, assigned, or held directly in structures and containers
110   // (map<string, ...>, for example), causes those strings to share a
111   // single instance of each distinct piece of text. GNU's libstdc++ uses
112   // reference counts, and I believe MSVC did as well, at some point.
113   // However, C++ '11 implementations are moving away from reference
114   // counting.
115   //
116   // In other implementations, string assignments copy the string's text,
117   // so this set will actually hold yet another copy of the string (although
118   // everything will still work). To improve memory consumption portably,
119   // we will probably need to use pointers to strings held in this set.
120   unordered_set<string> common_strings;
121 
122   // A map from offsets of DIEs within the .debug_info section to
123   // Specifications describing those DIEs. Specification references can
124   // cross compilation unit boundaries.
125   SpecificationByOffset specifications;
126 
127   AbstractOriginByOffset origins;
128 };
129 
FileContext(const string & filename,Module * module,bool handle_inter_cu_refs)130 DwarfCUToModule::FileContext::FileContext(const string &filename,
131                                           Module *module,
132                                           bool handle_inter_cu_refs)
133     : filename_(filename),
134       module_(module),
135       handle_inter_cu_refs_(handle_inter_cu_refs),
136       file_private_(new FilePrivate()) {
137 }
138 
~FileContext()139 DwarfCUToModule::FileContext::~FileContext() {
140 }
141 
AddSectionToSectionMap(const string & name,const uint8_t * contents,uint64 length)142 void DwarfCUToModule::FileContext::AddSectionToSectionMap(
143     const string& name, const uint8_t *contents, uint64 length) {
144   section_map_[name] = std::make_pair(contents, length);
145 }
146 
ClearSectionMapForTest()147 void DwarfCUToModule::FileContext::ClearSectionMapForTest() {
148   section_map_.clear();
149 }
150 
151 const dwarf2reader::SectionMap&
section_map() const152 DwarfCUToModule::FileContext::section_map() const {
153   return section_map_;
154 }
155 
ClearSpecifications()156 void DwarfCUToModule::FileContext::ClearSpecifications() {
157   if (!handle_inter_cu_refs_)
158     file_private_->specifications.clear();
159 }
160 
IsUnhandledInterCUReference(uint64 offset,uint64 compilation_unit_start) const161 bool DwarfCUToModule::FileContext::IsUnhandledInterCUReference(
162     uint64 offset, uint64 compilation_unit_start) const {
163   if (handle_inter_cu_refs_)
164     return false;
165   return offset < compilation_unit_start;
166 }
167 
168 // Information global to the particular compilation unit we're
169 // parsing. This is for data shared across the CU's entire DIE tree,
170 // and parameters from the code invoking the CU parser.
171 struct DwarfCUToModule::CUContext {
CUContextgoogle_breakpad::DwarfCUToModule::CUContext172   CUContext(FileContext *file_context_arg, WarningReporter *reporter_arg,
173             RangesHandler *ranges_handler_arg)
174       : file_context(file_context_arg),
175         reporter(reporter_arg),
176         ranges_handler(ranges_handler_arg),
177         language(Language::CPlusPlus),
178         low_pc(0),
179         high_pc(0),
180         ranges(0) {}
181 
~CUContextgoogle_breakpad::DwarfCUToModule::CUContext182   ~CUContext() {
183     for (vector<Module::Function *>::iterator it = functions.begin();
184          it != functions.end(); ++it) {
185       delete *it;
186     }
187   };
188 
189   // The DWARF-bearing file into which this CU was incorporated.
190   FileContext *file_context;
191 
192   // For printing error messages.
193   WarningReporter *reporter;
194 
195   // For reading ranges from the .debug_ranges section
196   RangesHandler *ranges_handler;
197 
198   // The source language of this compilation unit.
199   const Language *language;
200 
201   // Addresses covered by this CU. If high_pc_ is non-zero then the CU covers
202   // low_pc to high_pc, otherwise ranges is non-zero and low_pc represents
203   // the base address of the ranges covered by the CU.
204   uint64 low_pc;
205   uint64 high_pc;
206   uint64 ranges;
207 
208   // The functions defined in this compilation unit. We accumulate
209   // them here during parsing. Then, in DwarfCUToModule::Finish, we
210   // assign them lines and add them to file_context->module.
211   //
212   // Destroying this destroys all the functions this vector points to.
213   vector<Module::Function *> functions;
214 
215   // Keep a list of forward references from DW_AT_abstract_origin and
216   // DW_AT_specification attributes so names can be fixed up.
217   std::map<uint64_t, Module::Function *> forward_ref_die_to_func;
218 };
219 
220 // Information about the context of a particular DIE. This is for
221 // information that changes as we descend the tree towards the leaves:
222 // the containing classes/namespaces, etc.
223 struct DwarfCUToModule::DIEContext {
224   // The fully-qualified name of the context. For example, for a
225   // tree like:
226   //
227   // DW_TAG_namespace Foo
228   //   DW_TAG_class Bar
229   //     DW_TAG_subprogram Baz
230   //
231   // in a C++ compilation unit, the DIEContext's name for the
232   // DW_TAG_subprogram DIE would be "Foo::Bar". The DIEContext's
233   // name for the DW_TAG_namespace DIE would be "".
234   string name;
235 };
236 
237 // An abstract base class for all the dumper's DIE handlers.
238 class DwarfCUToModule::GenericDIEHandler: public dwarf2reader::DIEHandler {
239  public:
240   // Create a handler for the DIE at OFFSET whose compilation unit is
241   // described by CU_CONTEXT, and whose immediate context is described
242   // by PARENT_CONTEXT.
GenericDIEHandler(CUContext * cu_context,DIEContext * parent_context,uint64 offset)243   GenericDIEHandler(CUContext *cu_context, DIEContext *parent_context,
244                     uint64 offset)
245       : cu_context_(cu_context),
246         parent_context_(parent_context),
247         offset_(offset),
248         declaration_(false),
249         specification_(NULL),
250         forward_ref_die_offset_(0) { }
251 
252   // Derived classes' ProcessAttributeUnsigned can defer to this to
253   // handle DW_AT_declaration, or simply not override it.
254   void ProcessAttributeUnsigned(enum DwarfAttribute attr,
255                                 enum DwarfForm form,
256                                 uint64 data);
257 
258   // Derived classes' ProcessAttributeReference can defer to this to
259   // handle DW_AT_specification, or simply not override it.
260   void ProcessAttributeReference(enum DwarfAttribute attr,
261                                  enum DwarfForm form,
262                                  uint64 data);
263 
264   // Derived classes' ProcessAttributeReference can defer to this to
265   // handle DW_AT_specification, or simply not override it.
266   void ProcessAttributeString(enum DwarfAttribute attr,
267                               enum DwarfForm form,
268                               const string &data);
269 
270  protected:
271   // Compute and return the fully-qualified name of the DIE. If this
272   // DIE is a declaration DIE, to be cited by other DIEs'
273   // DW_AT_specification attributes, record its enclosing name and
274   // unqualified name in the specification table.
275   //
276   // Use this from EndAttributes member functions, not ProcessAttribute*
277   // functions; only the former can be sure that all the DIE's attributes
278   // have been seen.
279   string ComputeQualifiedName();
280 
281   CUContext *cu_context_;
282   DIEContext *parent_context_;
283   uint64 offset_;
284 
285   // Place the name in the global set of strings. Even though this looks
286   // like a copy, all the major string implementations use reference
287   // counting internally, so the effect is to have all the data structures
288   // share copies of strings whenever possible.
289   // FIXME: Should this return something like a string_ref to avoid the
290   // assumption about how strings are implemented?
291   string AddStringToPool(const string &str);
292 
293   // If this DIE has a DW_AT_declaration attribute, this is its value.
294   // It is false on DIEs with no DW_AT_declaration attribute.
295   bool declaration_;
296 
297   // If this DIE has a DW_AT_specification attribute, this is the
298   // Specification structure for the DIE the attribute refers to.
299   // Otherwise, this is NULL.
300   Specification *specification_;
301 
302   // If this DIE has a DW_AT_specification or DW_AT_abstract_origin and it is a
303   // forward reference, no Specification will be available. Track the reference
304   // to be fixed up when the DIE is parsed.
305   uint64_t forward_ref_die_offset_;
306 
307   // The value of the DW_AT_name attribute, or the empty string if the
308   // DIE has no such attribute.
309   string name_attribute_;
310 
311   // The demangled value of the DW_AT_MIPS_linkage_name attribute, or the empty
312   // string if the DIE has no such attribute or its content could not be
313   // demangled.
314   string demangled_name_;
315 
316   // The non-demangled value of the DW_AT_MIPS_linkage_name attribute,
317   // it its content count not be demangled.
318   string raw_name_;
319 };
320 
ProcessAttributeUnsigned(enum DwarfAttribute attr,enum DwarfForm form,uint64 data)321 void DwarfCUToModule::GenericDIEHandler::ProcessAttributeUnsigned(
322     enum DwarfAttribute attr,
323     enum DwarfForm form,
324     uint64 data) {
325   switch (attr) {
326     case dwarf2reader::DW_AT_declaration: declaration_ = (data != 0); break;
327     default: break;
328   }
329 }
330 
ProcessAttributeReference(enum DwarfAttribute attr,enum DwarfForm form,uint64 data)331 void DwarfCUToModule::GenericDIEHandler::ProcessAttributeReference(
332     enum DwarfAttribute attr,
333     enum DwarfForm form,
334     uint64 data) {
335   switch (attr) {
336     case dwarf2reader::DW_AT_specification: {
337       FileContext *file_context = cu_context_->file_context;
338       if (file_context->IsUnhandledInterCUReference(
339               data, cu_context_->reporter->cu_offset())) {
340         cu_context_->reporter->UnhandledInterCUReference(offset_, data);
341         break;
342       }
343       // Find the Specification to which this attribute refers, and
344       // set specification_ appropriately. We could do more processing
345       // here, but it's better to leave the real work to our
346       // EndAttribute member function, at which point we know we have
347       // seen all the DIE's attributes.
348       SpecificationByOffset *specifications =
349           &file_context->file_private_->specifications;
350       SpecificationByOffset::iterator spec = specifications->find(data);
351       if (spec != specifications->end()) {
352         specification_ = &spec->second;
353       } else if (data > offset_) {
354         forward_ref_die_offset_ = data;
355       } else {
356         cu_context_->reporter->UnknownSpecification(offset_, data);
357       }
358       break;
359     }
360     default: break;
361   }
362 }
363 
AddStringToPool(const string & str)364 string DwarfCUToModule::GenericDIEHandler::AddStringToPool(const string &str) {
365   pair<unordered_set<string>::iterator, bool> result =
366     cu_context_->file_context->file_private_->common_strings.insert(str);
367   return *result.first;
368 }
369 
ProcessAttributeString(enum DwarfAttribute attr,enum DwarfForm form,const string & data)370 void DwarfCUToModule::GenericDIEHandler::ProcessAttributeString(
371     enum DwarfAttribute attr,
372     enum DwarfForm form,
373     const string &data) {
374   switch (attr) {
375     case dwarf2reader::DW_AT_name:
376       name_attribute_ = AddStringToPool(data);
377       break;
378     case dwarf2reader::DW_AT_MIPS_linkage_name:
379     case dwarf2reader::DW_AT_linkage_name: {
380       string demangled;
381       Language::DemangleResult result =
382           cu_context_->language->DemangleName(data, &demangled);
383       switch (result) {
384         case Language::kDemangleSuccess:
385           demangled_name_ = AddStringToPool(demangled);
386           break;
387 
388         case Language::kDemangleFailure:
389           cu_context_->reporter->DemangleError(data);
390           // fallthrough
391         case Language::kDontDemangle:
392           demangled_name_.clear();
393           raw_name_ = AddStringToPool(data);
394           break;
395       }
396       break;
397     }
398     default: break;
399   }
400 }
401 
ComputeQualifiedName()402 string DwarfCUToModule::GenericDIEHandler::ComputeQualifiedName() {
403   // Use the demangled name, if one is available. Demangled names are
404   // preferable to those inferred from the DWARF structure because they
405   // include argument types.
406   const string *qualified_name = NULL;
407   if (!demangled_name_.empty()) {
408     // Found it is this DIE.
409     qualified_name = &demangled_name_;
410   } else if (specification_ && !specification_->qualified_name.empty()) {
411     // Found it on the specification.
412     qualified_name = &specification_->qualified_name;
413   }
414 
415   const string *unqualified_name = NULL;
416   const string *enclosing_name;
417   if (!qualified_name) {
418     // Find the unqualified name. If the DIE has its own DW_AT_name
419     // attribute, then use that; otherwise, check the specification.
420     if (!name_attribute_.empty())
421       unqualified_name = &name_attribute_;
422     else if (specification_)
423       unqualified_name = &specification_->unqualified_name;
424     else if (!raw_name_.empty())
425       unqualified_name = &raw_name_;
426 
427     // Find the name of the enclosing context. If this DIE has a
428     // specification, it's the specification's enclosing context that
429     // counts; otherwise, use this DIE's context.
430     if (specification_)
431       enclosing_name = &specification_->enclosing_name;
432     else
433       enclosing_name = &parent_context_->name;
434   }
435 
436   // Prepare the return value before upcoming mutations possibly invalidate the
437   // existing pointers.
438   string return_value;
439   if (qualified_name) {
440     return_value = *qualified_name;
441   } else if (unqualified_name && enclosing_name) {
442     // Combine the enclosing name and unqualified name to produce our
443     // own fully-qualified name.
444     return_value = cu_context_->language->MakeQualifiedName(*enclosing_name,
445                                                             *unqualified_name);
446   }
447 
448   // If this DIE was marked as a declaration, record its names in the
449   // specification table.
450   if ((declaration_ && qualified_name) ||
451       (unqualified_name && enclosing_name)) {
452     Specification spec;
453     if (qualified_name) {
454       spec.qualified_name = *qualified_name;
455     } else {
456       spec.enclosing_name = *enclosing_name;
457       spec.unqualified_name = *unqualified_name;
458     }
459     cu_context_->file_context->file_private_->specifications[offset_] = spec;
460   }
461 
462   return return_value;
463 }
464 
465 // A handler class for DW_TAG_subprogram DIEs.
466 class DwarfCUToModule::FuncHandler: public GenericDIEHandler {
467  public:
FuncHandler(CUContext * cu_context,DIEContext * parent_context,uint64 offset)468   FuncHandler(CUContext *cu_context, DIEContext *parent_context,
469               uint64 offset)
470       : GenericDIEHandler(cu_context, parent_context, offset),
471         low_pc_(0), high_pc_(0), high_pc_form_(dwarf2reader::DW_FORM_addr),
472         ranges_(0), abstract_origin_(NULL), inline_(false) { }
473   void ProcessAttributeUnsigned(enum DwarfAttribute attr,
474                                 enum DwarfForm form,
475                                 uint64 data);
476   void ProcessAttributeSigned(enum DwarfAttribute attr,
477                               enum DwarfForm form,
478                               int64 data);
479   void ProcessAttributeReference(enum DwarfAttribute attr,
480                                  enum DwarfForm form,
481                                  uint64 data);
482 
483   bool EndAttributes();
484   void Finish();
485 
486  private:
487   // The fully-qualified name, as derived from name_attribute_,
488   // specification_, parent_context_.  Computed in EndAttributes.
489   string name_;
490   uint64 low_pc_, high_pc_; // DW_AT_low_pc, DW_AT_high_pc
491   DwarfForm high_pc_form_; // DW_AT_high_pc can be length or address.
492   uint64 ranges_; // DW_AT_ranges
493   const AbstractOrigin* abstract_origin_;
494   bool inline_;
495 };
496 
ProcessAttributeUnsigned(enum DwarfAttribute attr,enum DwarfForm form,uint64 data)497 void DwarfCUToModule::FuncHandler::ProcessAttributeUnsigned(
498     enum DwarfAttribute attr,
499     enum DwarfForm form,
500     uint64 data) {
501   switch (attr) {
502     // If this attribute is present at all --- even if its value is
503     // DW_INL_not_inlined --- then GCC may cite it as someone else's
504     // DW_AT_abstract_origin attribute.
505     case dwarf2reader::DW_AT_inline:      inline_  = true; break;
506 
507     case dwarf2reader::DW_AT_low_pc:      low_pc_  = data; break;
508     case dwarf2reader::DW_AT_high_pc:
509       high_pc_form_ = form;
510       high_pc_ = data;
511       break;
512     case dwarf2reader::DW_AT_ranges:
513       ranges_ = data;
514       break;
515 
516     default:
517       GenericDIEHandler::ProcessAttributeUnsigned(attr, form, data);
518       break;
519   }
520 }
521 
ProcessAttributeSigned(enum DwarfAttribute attr,enum DwarfForm form,int64 data)522 void DwarfCUToModule::FuncHandler::ProcessAttributeSigned(
523     enum DwarfAttribute attr,
524     enum DwarfForm form,
525     int64 data) {
526   switch (attr) {
527     // If this attribute is present at all --- even if its value is
528     // DW_INL_not_inlined --- then GCC may cite it as someone else's
529     // DW_AT_abstract_origin attribute.
530     case dwarf2reader::DW_AT_inline:      inline_  = true; break;
531 
532     default:
533       break;
534   }
535 }
536 
ProcessAttributeReference(enum DwarfAttribute attr,enum DwarfForm form,uint64 data)537 void DwarfCUToModule::FuncHandler::ProcessAttributeReference(
538     enum DwarfAttribute attr,
539     enum DwarfForm form,
540     uint64 data) {
541   switch (attr) {
542     case dwarf2reader::DW_AT_abstract_origin: {
543       const AbstractOriginByOffset& origins =
544           cu_context_->file_context->file_private_->origins;
545       AbstractOriginByOffset::const_iterator origin = origins.find(data);
546       if (origin != origins.end()) {
547         abstract_origin_ = &(origin->second);
548       } else if (data > offset_) {
549         forward_ref_die_offset_ = data;
550       } else {
551         cu_context_->reporter->UnknownAbstractOrigin(offset_, data);
552       }
553       break;
554     }
555     default:
556       GenericDIEHandler::ProcessAttributeReference(attr, form, data);
557       break;
558   }
559 }
560 
EndAttributes()561 bool DwarfCUToModule::FuncHandler::EndAttributes() {
562   // Compute our name, and record a specification, if appropriate.
563   name_ = ComputeQualifiedName();
564   if (name_.empty() && abstract_origin_) {
565     name_ = abstract_origin_->name;
566   }
567   return true;
568 }
569 
IsEmptyRange(const vector<Module::Range> & ranges)570 static bool IsEmptyRange(const vector<Module::Range>& ranges) {
571   uint64 size = accumulate(ranges.cbegin(), ranges.cend(), 0,
572     [](uint64 total, Module::Range entry) {
573       return total + entry.size;
574     }
575   );
576 
577   return size == 0;
578 }
579 
Finish()580 void DwarfCUToModule::FuncHandler::Finish() {
581   vector<Module::Range> ranges;
582 
583   // Check if this DIE was one of the forward references that was not able
584   // to be processed, and fix up the name of the appropriate Module::Function.
585   // "name_" will have already been fixed up in EndAttributes().
586   if (!name_.empty()) {
587     auto iter = cu_context_->forward_ref_die_to_func.find(offset_);
588     if (iter != cu_context_->forward_ref_die_to_func.end())
589       iter->second->name = name_;
590   }
591 
592   if (!ranges_) {
593     // Make high_pc_ an address, if it isn't already.
594     if (high_pc_form_ != dwarf2reader::DW_FORM_addr &&
595         high_pc_form_ != dwarf2reader::DW_FORM_GNU_addr_index) {
596       high_pc_ += low_pc_;
597     }
598 
599     Module::Range range(low_pc_, high_pc_ - low_pc_);
600     ranges.push_back(range);
601   } else {
602     RangesHandler *ranges_handler = cu_context_->ranges_handler;
603 
604     if (ranges_handler) {
605       if (!ranges_handler->ReadRanges(ranges_, cu_context_->low_pc, &ranges)) {
606         ranges.clear();
607         cu_context_->reporter->MalformedRangeList(ranges_);
608       }
609     } else {
610       cu_context_->reporter->MissingRanges();
611     }
612   }
613 
614   // Did we collect the information we need?  Not all DWARF function
615   // entries are non-empty (for example, inlined functions that were never
616   // used), but all the ones we're interested in cover a non-empty range of
617   // bytes.
618   if (!IsEmptyRange(ranges)) {
619     low_pc_ = ranges.front().address;
620 
621     // Malformed DWARF may omit the name, but all Module::Functions must
622     // have names.
623     string name;
624     if (!name_.empty()) {
625       name = name_;
626     } else {
627       // If we have a forward reference to a DW_AT_specification or
628       // DW_AT_abstract_origin, then don't warn, the name will be fixed up
629       // later
630       if (forward_ref_die_offset_ == 0)
631         cu_context_->reporter->UnnamedFunction(offset_);
632       name = "<name omitted>";
633     }
634 
635     // Create a Module::Function based on the data we've gathered, and
636     // add it to the functions_ list.
637     scoped_ptr<Module::Function> func(new Module::Function(name, low_pc_));
638     func->ranges = ranges;
639     func->parameter_size = 0;
640     if (func->address) {
641       // If the function address is zero this is a sign that this function
642       // description is just empty debug data and should just be discarded.
643       cu_context_->functions.push_back(func.release());
644       if (forward_ref_die_offset_ != 0) {
645         auto iter =
646             cu_context_->forward_ref_die_to_func.find(forward_ref_die_offset_);
647         if (iter == cu_context_->forward_ref_die_to_func.end()) {
648           cu_context_->reporter->UnknownSpecification(offset_,
649                                                       forward_ref_die_offset_);
650         } else {
651           iter->second = cu_context_->functions.back();
652         }
653       }
654     }
655   } else if (inline_) {
656     AbstractOrigin origin(name_);
657     cu_context_->file_context->file_private_->origins[offset_] = origin;
658   }
659 }
660 
661 // A handler for DIEs that contain functions and contribute a
662 // component to their names: namespaces, classes, etc.
663 class DwarfCUToModule::NamedScopeHandler: public GenericDIEHandler {
664  public:
NamedScopeHandler(CUContext * cu_context,DIEContext * parent_context,uint64 offset)665   NamedScopeHandler(CUContext *cu_context, DIEContext *parent_context,
666                     uint64 offset)
667       : GenericDIEHandler(cu_context, parent_context, offset) { }
668   bool EndAttributes();
669   DIEHandler *FindChildHandler(uint64 offset, enum DwarfTag tag);
670 
671  private:
672   DIEContext child_context_; // A context for our children.
673 };
674 
EndAttributes()675 bool DwarfCUToModule::NamedScopeHandler::EndAttributes() {
676   child_context_.name = ComputeQualifiedName();
677   return true;
678 }
679 
FindChildHandler(uint64 offset,enum DwarfTag tag)680 dwarf2reader::DIEHandler *DwarfCUToModule::NamedScopeHandler::FindChildHandler(
681     uint64 offset,
682     enum DwarfTag tag) {
683   switch (tag) {
684     case dwarf2reader::DW_TAG_subprogram:
685       return new FuncHandler(cu_context_, &child_context_, offset);
686     case dwarf2reader::DW_TAG_namespace:
687     case dwarf2reader::DW_TAG_class_type:
688     case dwarf2reader::DW_TAG_structure_type:
689     case dwarf2reader::DW_TAG_union_type:
690       return new NamedScopeHandler(cu_context_, &child_context_, offset);
691     default:
692       return NULL;
693   }
694 }
695 
CUHeading()696 void DwarfCUToModule::WarningReporter::CUHeading() {
697   if (printed_cu_header_)
698     return;
699   fprintf(stderr, "%s: in compilation unit '%s' (offset 0x%llx):\n",
700           filename_.c_str(), cu_name_.c_str(), cu_offset_);
701   printed_cu_header_ = true;
702 }
703 
UnknownSpecification(uint64 offset,uint64 target)704 void DwarfCUToModule::WarningReporter::UnknownSpecification(uint64 offset,
705                                                             uint64 target) {
706   CUHeading();
707   fprintf(stderr, "%s: the DIE at offset 0x%llx has a DW_AT_specification"
708           " attribute referring to the DIE at offset 0x%llx, which was not"
709           " marked as a declaration\n",
710           filename_.c_str(), offset, target);
711 }
712 
UnknownAbstractOrigin(uint64 offset,uint64 target)713 void DwarfCUToModule::WarningReporter::UnknownAbstractOrigin(uint64 offset,
714                                                              uint64 target) {
715   CUHeading();
716   fprintf(stderr, "%s: the DIE at offset 0x%llx has a DW_AT_abstract_origin"
717           " attribute referring to the DIE at offset 0x%llx, which was not"
718           " marked as an inline\n",
719           filename_.c_str(), offset, target);
720 }
721 
MissingSection(const string & name)722 void DwarfCUToModule::WarningReporter::MissingSection(const string &name) {
723   CUHeading();
724   fprintf(stderr, "%s: warning: couldn't find DWARF '%s' section\n",
725           filename_.c_str(), name.c_str());
726 }
727 
BadLineInfoOffset(uint64 offset)728 void DwarfCUToModule::WarningReporter::BadLineInfoOffset(uint64 offset) {
729   CUHeading();
730   fprintf(stderr, "%s: warning: line number data offset beyond end"
731           " of '.debug_line' section\n",
732           filename_.c_str());
733 }
734 
UncoveredHeading()735 void DwarfCUToModule::WarningReporter::UncoveredHeading() {
736   if (printed_unpaired_header_)
737     return;
738   CUHeading();
739   fprintf(stderr, "%s: warning: skipping unpaired lines/functions:\n",
740           filename_.c_str());
741   printed_unpaired_header_ = true;
742 }
743 
UncoveredFunction(const Module::Function & function)744 void DwarfCUToModule::WarningReporter::UncoveredFunction(
745     const Module::Function &function) {
746   if (!uncovered_warnings_enabled_)
747     return;
748   UncoveredHeading();
749   fprintf(stderr, "    function%s: %s\n",
750           IsEmptyRange(function.ranges) ? " (zero-length)" : "",
751           function.name.c_str());
752 }
753 
UncoveredLine(const Module::Line & line)754 void DwarfCUToModule::WarningReporter::UncoveredLine(const Module::Line &line) {
755   if (!uncovered_warnings_enabled_)
756     return;
757   UncoveredHeading();
758   fprintf(stderr, "    line%s: %s:%d at 0x%" PRIx64 "\n",
759           (line.size == 0 ? " (zero-length)" : ""),
760           line.file->name.c_str(), line.number, line.address);
761 }
762 
UnnamedFunction(uint64 offset)763 void DwarfCUToModule::WarningReporter::UnnamedFunction(uint64 offset) {
764   CUHeading();
765   fprintf(stderr, "%s: warning: function at offset 0x%llx has no name\n",
766           filename_.c_str(), offset);
767 }
768 
DemangleError(const string & input)769 void DwarfCUToModule::WarningReporter::DemangleError(const string &input) {
770   CUHeading();
771   fprintf(stderr, "%s: warning: failed to demangle %s\n",
772           filename_.c_str(), input.c_str());
773 }
774 
UnhandledInterCUReference(uint64 offset,uint64 target)775 void DwarfCUToModule::WarningReporter::UnhandledInterCUReference(
776     uint64 offset, uint64 target) {
777   CUHeading();
778   fprintf(stderr, "%s: warning: the DIE at offset 0x%llx has a "
779                   "DW_FORM_ref_addr attribute with an inter-CU reference to "
780                   "0x%llx, but inter-CU reference handling is turned off.\n",
781                   filename_.c_str(), offset, target);
782 }
783 
MalformedRangeList(uint64 offset)784 void DwarfCUToModule::WarningReporter::MalformedRangeList(uint64 offset) {
785   CUHeading();
786   fprintf(stderr, "%s: warning: the range list at offset 0x%llx falls out of "
787                   "the .debug_ranges section.\n",
788                   filename_.c_str(), offset);
789 }
790 
MissingRanges()791 void DwarfCUToModule::WarningReporter::MissingRanges() {
792   CUHeading();
793   fprintf(stderr, "%s: warning: A DW_AT_ranges attribute was encountered but "
794                   "the .debug_ranges section is missing.\n", filename_.c_str());
795 }
796 
DwarfCUToModule(FileContext * file_context,LineToModuleHandler * line_reader,RangesHandler * ranges_handler,WarningReporter * reporter)797 DwarfCUToModule::DwarfCUToModule(FileContext *file_context,
798                                  LineToModuleHandler *line_reader,
799                                  RangesHandler *ranges_handler,
800                                  WarningReporter *reporter)
801     : line_reader_(line_reader),
802       cu_context_(new CUContext(file_context, reporter, ranges_handler)),
803       child_context_(new DIEContext()),
804       has_source_line_info_(false) {
805 }
806 
~DwarfCUToModule()807 DwarfCUToModule::~DwarfCUToModule() {
808 }
809 
ProcessAttributeSigned(enum DwarfAttribute attr,enum DwarfForm form,int64 data)810 void DwarfCUToModule::ProcessAttributeSigned(enum DwarfAttribute attr,
811                                              enum DwarfForm form,
812                                              int64 data) {
813   switch (attr) {
814     case dwarf2reader::DW_AT_language: // source language of this CU
815       SetLanguage(static_cast<DwarfLanguage>(data));
816       break;
817     default:
818       break;
819   }
820 }
821 
ProcessAttributeUnsigned(enum DwarfAttribute attr,enum DwarfForm form,uint64 data)822 void DwarfCUToModule::ProcessAttributeUnsigned(enum DwarfAttribute attr,
823                                                enum DwarfForm form,
824                                                uint64 data) {
825   switch (attr) {
826     case dwarf2reader::DW_AT_stmt_list: // Line number information.
827       has_source_line_info_ = true;
828       source_line_offset_ = data;
829       break;
830     case dwarf2reader::DW_AT_language: // source language of this CU
831       SetLanguage(static_cast<DwarfLanguage>(data));
832       break;
833     case dwarf2reader::DW_AT_low_pc:
834       cu_context_->low_pc  = data;
835       break;
836     case dwarf2reader::DW_AT_high_pc:
837       cu_context_->high_pc  = data;
838       break;
839     case dwarf2reader::DW_AT_ranges:
840       cu_context_->ranges = data;
841       break;
842 
843     default:
844       break;
845   }
846 }
847 
ProcessAttributeString(enum DwarfAttribute attr,enum DwarfForm form,const string & data)848 void DwarfCUToModule::ProcessAttributeString(enum DwarfAttribute attr,
849                                              enum DwarfForm form,
850                                              const string &data) {
851   switch (attr) {
852     case dwarf2reader::DW_AT_name:
853       cu_context_->reporter->SetCUName(data);
854       break;
855     case dwarf2reader::DW_AT_comp_dir:
856       line_reader_->StartCompilationUnit(data);
857       break;
858     default:
859       break;
860   }
861 }
862 
EndAttributes()863 bool DwarfCUToModule::EndAttributes() {
864   return true;
865 }
866 
FindChildHandler(uint64 offset,enum DwarfTag tag)867 dwarf2reader::DIEHandler *DwarfCUToModule::FindChildHandler(
868     uint64 offset,
869     enum DwarfTag tag) {
870   switch (tag) {
871     case dwarf2reader::DW_TAG_subprogram:
872       return new FuncHandler(cu_context_.get(), child_context_.get(), offset);
873     case dwarf2reader::DW_TAG_namespace:
874     case dwarf2reader::DW_TAG_class_type:
875     case dwarf2reader::DW_TAG_structure_type:
876     case dwarf2reader::DW_TAG_union_type:
877     case dwarf2reader::DW_TAG_module:
878       return new NamedScopeHandler(cu_context_.get(), child_context_.get(),
879                                    offset);
880     default:
881       return NULL;
882   }
883 }
884 
SetLanguage(DwarfLanguage language)885 void DwarfCUToModule::SetLanguage(DwarfLanguage language) {
886   switch (language) {
887     case dwarf2reader::DW_LANG_Java:
888       cu_context_->language = Language::Java;
889       break;
890 
891     case dwarf2reader::DW_LANG_Swift:
892       cu_context_->language = Language::Swift;
893       break;
894 
895     case dwarf2reader::DW_LANG_Rust:
896       cu_context_->language = Language::Rust;
897       break;
898 
899     // DWARF has no generic language code for assembly language; this is
900     // what the GNU toolchain uses.
901     case dwarf2reader::DW_LANG_Mips_Assembler:
902       cu_context_->language = Language::Assembler;
903       break;
904 
905     // C++ covers so many cases that it probably has some way to cope
906     // with whatever the other languages throw at us. So make it the
907     // default.
908     //
909     // Objective C and Objective C++ seem to create entries for
910     // methods whose DW_AT_name values are already fully-qualified:
911     // "-[Classname method:]".  These appear at the top level.
912     //
913     // DWARF data for C should never include namespaces or functions
914     // nested in struct types, but if it ever does, then C++'s
915     // notation is probably not a bad choice for that.
916     default:
917     case dwarf2reader::DW_LANG_ObjC:
918     case dwarf2reader::DW_LANG_ObjC_plus_plus:
919     case dwarf2reader::DW_LANG_C:
920     case dwarf2reader::DW_LANG_C89:
921     case dwarf2reader::DW_LANG_C99:
922     case dwarf2reader::DW_LANG_C_plus_plus:
923       cu_context_->language = Language::CPlusPlus;
924       break;
925   }
926 }
927 
ReadSourceLines(uint64 offset)928 void DwarfCUToModule::ReadSourceLines(uint64 offset) {
929   const dwarf2reader::SectionMap &section_map
930       = cu_context_->file_context->section_map();
931   dwarf2reader::SectionMap::const_iterator map_entry
932       = section_map.find(".debug_line");
933   // Mac OS X puts DWARF data in sections whose names begin with "__"
934   // instead of ".".
935   if (map_entry == section_map.end())
936     map_entry = section_map.find("__debug_line");
937   if (map_entry == section_map.end()) {
938     cu_context_->reporter->MissingSection(".debug_line");
939     return;
940   }
941   const uint8_t *section_start = map_entry->second.first;
942   uint64 section_length = map_entry->second.second;
943   if (offset >= section_length) {
944     cu_context_->reporter->BadLineInfoOffset(offset);
945     return;
946   }
947   line_reader_->ReadProgram(section_start + offset, section_length - offset,
948                             cu_context_->file_context->module_, &lines_);
949 }
950 
951 namespace {
952 class FunctionRange {
953  public:
FunctionRange(const Module::Range & range,Module::Function * function)954   FunctionRange(const Module::Range &range, Module::Function *function) :
955       address(range.address), size(range.size), function(function) { }
956 
AddLine(Module::Line & line)957   void AddLine(Module::Line &line) {
958     function->lines.push_back(line);
959   }
960 
961   Module::Address address;
962   Module::Address size;
963   Module::Function *function;
964 };
965 
966 // Fills an array of ranges with pointers to the functions which owns
967 // them. The array is sorted in ascending order and the ranges are non
968 // empty and non-overlapping.
969 
FillSortedFunctionRanges(vector<FunctionRange> & dest_ranges,vector<Module::Function * > * functions)970 static void FillSortedFunctionRanges(vector<FunctionRange> &dest_ranges,
971                                      vector<Module::Function *> *functions) {
972   for (vector<Module::Function *>::const_iterator func_it = functions->cbegin();
973        func_it != functions->cend();
974        func_it++)
975   {
976     Module::Function *func = *func_it;
977     vector<Module::Range> &ranges = func->ranges;
978     for (vector<Module::Range>::const_iterator ranges_it = ranges.cbegin();
979          ranges_it != ranges.cend();
980          ++ranges_it) {
981       FunctionRange range(*ranges_it, func);
982       if (range.size != 0) {
983           dest_ranges.push_back(range);
984       }
985     }
986   }
987 
988   sort(dest_ranges.begin(), dest_ranges.end(),
989     [](const FunctionRange &fr1, const FunctionRange &fr2) {
990       return fr1.address < fr2.address;
991     }
992   );
993 }
994 
995 // Return true if ADDRESS falls within the range of ITEM.
996 template <class T>
within(const T & item,Module::Address address)997 inline bool within(const T &item, Module::Address address) {
998   // Because Module::Address is unsigned, and unsigned arithmetic
999   // wraps around, this will be false if ADDRESS falls before the
1000   // start of ITEM, or if it falls after ITEM's end.
1001   return address - item.address < item.size;
1002 }
1003 }
1004 
AssignLinesToFunctions()1005 void DwarfCUToModule::AssignLinesToFunctions() {
1006   vector<Module::Function *> *functions = &cu_context_->functions;
1007   WarningReporter *reporter = cu_context_->reporter;
1008 
1009   // This would be simpler if we assumed that source line entries
1010   // don't cross function boundaries.  However, there's no real reason
1011   // to assume that (say) a series of function definitions on the same
1012   // line wouldn't get coalesced into one line number entry.  The
1013   // DWARF spec certainly makes no such promises.
1014   //
1015   // So treat the functions and lines as peers, and take the trouble
1016   // to compute their ranges' intersections precisely.  In any case,
1017   // the hair here is a constant factor for performance; the
1018   // complexity from here on out is linear.
1019 
1020   // Put both our functions and lines in order by address.
1021   std::sort(functions->begin(), functions->end(),
1022             Module::Function::CompareByAddress);
1023   std::sort(lines_.begin(), lines_.end(), Module::Line::CompareByAddress);
1024 
1025   // The last line that we used any piece of.  We use this only for
1026   // generating warnings.
1027   const Module::Line *last_line_used = NULL;
1028 
1029   // The last function and line we warned about --- so we can avoid
1030   // doing so more than once.
1031   const Module::Function *last_function_cited = NULL;
1032   const Module::Line *last_line_cited = NULL;
1033 
1034   // Prepare a sorted list of ranges with range-to-function mapping
1035   vector<FunctionRange> sorted_ranges;
1036   FillSortedFunctionRanges(sorted_ranges, functions);
1037 
1038   // Make a single pass through both the range and line vectors from lower to
1039   // higher addresses, populating each range's function lines vector with lines
1040   // from our lines_ vector that fall within the range.
1041   vector<FunctionRange>::iterator range_it = sorted_ranges.begin();
1042   vector<Module::Line>::const_iterator line_it = lines_.begin();
1043 
1044   Module::Address current;
1045 
1046   // Pointers to the referents of func_it and line_it, or NULL if the
1047   // iterator is at the end of the sequence.
1048   FunctionRange *range;
1049   const Module::Line *line;
1050 
1051   // Start current at the beginning of the first line or function,
1052   // whichever is earlier.
1053   if (range_it != sorted_ranges.end() && line_it != lines_.end()) {
1054     range = &*range_it;
1055     line = &*line_it;
1056     current = std::min(range->address, line->address);
1057   } else if (line_it != lines_.end()) {
1058     range = NULL;
1059     line = &*line_it;
1060     current = line->address;
1061   } else if (range_it != sorted_ranges.end()) {
1062     range = &*range_it;
1063     line = NULL;
1064     current = range->address;
1065   } else {
1066     return;
1067   }
1068 
1069   while (range || line) {
1070     // This loop has two invariants that hold at the top.
1071     //
1072     // First, at least one of the iterators is not at the end of its
1073     // sequence, and those that are not refer to the earliest
1074     // range or line that contains or starts after CURRENT.
1075     //
1076     // Note that every byte is in one of four states: it is covered
1077     // or not covered by a range, and, independently, it is
1078     // covered or not covered by a line.
1079     //
1080     // The second invariant is that CURRENT refers to a byte whose
1081     // state is different from its predecessor, or it refers to the
1082     // first byte in the address space. In other words, CURRENT is
1083     // always the address of a transition.
1084     //
1085     // Note that, although each iteration advances CURRENT from one
1086     // transition address to the next in each iteration, it might
1087     // not advance the iterators. Suppose we have a range that
1088     // starts with a line, has a gap, and then a second line, and
1089     // suppose that we enter an iteration with CURRENT at the end of
1090     // the first line. The next transition address is the start of
1091     // the second line, after the gap, so the iteration should
1092     // advance CURRENT to that point. At the head of that iteration,
1093     // the invariants require that the line iterator be pointing at
1094     // the second line. But this is also true at the head of the
1095     // next. And clearly, the iteration must not change the range
1096     // iterator. So neither iterator moves.
1097 
1098     // Assert the first invariant (see above).
1099     assert(!range || current < range->address || within(*range, current));
1100     assert(!line || current < line->address || within(*line, current));
1101 
1102     // The next transition after CURRENT.
1103     Module::Address next_transition;
1104 
1105     // Figure out which state we're in, add lines or warn, and compute
1106     // the next transition address.
1107     if (range && current >= range->address) {
1108       if (line && current >= line->address) {
1109         // Covered by both a line and a range.
1110         Module::Address range_left = range->size - (current - range->address);
1111         Module::Address line_left = line->size - (current - line->address);
1112         // This may overflow, but things work out.
1113         next_transition = current + std::min(range_left, line_left);
1114         Module::Line l = *line;
1115         l.address = current;
1116         l.size = next_transition - current;
1117         range->AddLine(l);
1118         last_line_used = line;
1119       } else {
1120         // Covered by a range, but no line.
1121         if (range->function != last_function_cited) {
1122           reporter->UncoveredFunction(*(range->function));
1123           last_function_cited = range->function;
1124         }
1125         if (line && within(*range, line->address))
1126           next_transition = line->address;
1127         else
1128           // If this overflows, we'll catch it below.
1129           next_transition = range->address + range->size;
1130       }
1131     } else {
1132       if (line && current >= line->address) {
1133         // Covered by a line, but no range.
1134         //
1135         // If GCC emits padding after one function to align the start
1136         // of the next, then it will attribute the padding
1137         // instructions to the last source line of function (to reduce
1138         // the size of the line number info), but omit it from the
1139         // DW_AT_{low,high}_pc range given in .debug_info (since it
1140         // costs nothing to be precise there). If we did use at least
1141         // some of the line we're about to skip, and it ends at the
1142         // start of the next function, then assume this is what
1143         // happened, and don't warn.
1144         if (line != last_line_cited
1145             && !(range
1146                  && line == last_line_used
1147                  && range->address - line->address == line->size)) {
1148           reporter->UncoveredLine(*line);
1149           last_line_cited = line;
1150         }
1151         if (range && within(*line, range->address))
1152           next_transition = range->address;
1153         else
1154           // If this overflows, we'll catch it below.
1155           next_transition = line->address + line->size;
1156       } else {
1157         // Covered by neither a range nor a line. By the invariant,
1158         // both range and line begin after CURRENT. The next transition
1159         // is the start of the next range or next line, whichever
1160         // is earliest.
1161         assert(range || line);
1162         if (range && line)
1163           next_transition = std::min(range->address, line->address);
1164         else if (range)
1165           next_transition = range->address;
1166         else
1167           next_transition = line->address;
1168       }
1169     }
1170 
1171     // If a function or line abuts the end of the address space, then
1172     // next_transition may end up being zero, in which case we've completed
1173     // our pass. Handle that here, instead of trying to deal with it in
1174     // each place we compute next_transition.
1175     if (!next_transition)
1176       break;
1177 
1178     // Advance iterators as needed. If lines overlap or functions overlap,
1179     // then we could go around more than once. We don't worry too much
1180     // about what result we produce in that case, just as long as we don't
1181     // hang or crash.
1182     while (range_it != sorted_ranges.end()
1183            && next_transition >= range_it->address
1184            && !within(*range_it, next_transition))
1185       range_it++;
1186     range = (range_it != sorted_ranges.end()) ? &(*range_it) : NULL;
1187     while (line_it != lines_.end()
1188            && next_transition >= line_it->address
1189            && !within(*line_it, next_transition))
1190       line_it++;
1191     line = (line_it != lines_.end()) ? &*line_it : NULL;
1192 
1193     // We must make progress.
1194     assert(next_transition > current);
1195     current = next_transition;
1196   }
1197 }
1198 
Finish()1199 void DwarfCUToModule::Finish() {
1200   // Assembly language files have no function data, and that gives us
1201   // no place to store our line numbers (even though the GNU toolchain
1202   // will happily produce source line info for assembly language
1203   // files).  To avoid spurious warnings about lines we can't assign
1204   // to functions, skip CUs in languages that lack functions.
1205   if (!cu_context_->language->HasFunctions())
1206     return;
1207 
1208   // Read source line info, if we have any.
1209   if (has_source_line_info_)
1210     ReadSourceLines(source_line_offset_);
1211 
1212   vector<Module::Function *> *functions = &cu_context_->functions;
1213 
1214   // Dole out lines to the appropriate functions.
1215   AssignLinesToFunctions();
1216 
1217   // Add our functions, which now have source lines assigned to them,
1218   // to module_.
1219   cu_context_->file_context->module_->AddFunctions(functions->begin(),
1220                                                    functions->end());
1221 
1222   // Ownership of the function objects has shifted from cu_context to
1223   // the Module.
1224   functions->clear();
1225 
1226   cu_context_->file_context->ClearSpecifications();
1227 }
1228 
StartCompilationUnit(uint64 offset,uint8 address_size,uint8 offset_size,uint64 cu_length,uint8 dwarf_version)1229 bool DwarfCUToModule::StartCompilationUnit(uint64 offset,
1230                                            uint8 address_size,
1231                                            uint8 offset_size,
1232                                            uint64 cu_length,
1233                                            uint8 dwarf_version) {
1234   return dwarf_version >= 2;
1235 }
1236 
StartRootDIE(uint64 offset,enum DwarfTag tag)1237 bool DwarfCUToModule::StartRootDIE(uint64 offset, enum DwarfTag tag) {
1238   // We don't deal with partial compilation units (the only other tag
1239   // likely to be used for root DIE).
1240   return tag == dwarf2reader::DW_TAG_compile_unit;
1241 }
1242 
1243 } // namespace google_breakpad
1244