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