183e085b7a331c96237cf8e814f97b3ef4c36a70fjimblandy// Copyright (c) 2010 Google Inc.
2057aa1f6173501e1a62cf91fd08275e7da439166jimblandy// All rights reserved.
3057aa1f6173501e1a62cf91fd08275e7da439166jimblandy//
4057aa1f6173501e1a62cf91fd08275e7da439166jimblandy// Redistribution and use in source and binary forms, with or without
5057aa1f6173501e1a62cf91fd08275e7da439166jimblandy// modification, are permitted provided that the following conditions are
6057aa1f6173501e1a62cf91fd08275e7da439166jimblandy// met:
7057aa1f6173501e1a62cf91fd08275e7da439166jimblandy//
8057aa1f6173501e1a62cf91fd08275e7da439166jimblandy//     * Redistributions of source code must retain the above copyright
9057aa1f6173501e1a62cf91fd08275e7da439166jimblandy// notice, this list of conditions and the following disclaimer.
10057aa1f6173501e1a62cf91fd08275e7da439166jimblandy//     * Redistributions in binary form must reproduce the above
11057aa1f6173501e1a62cf91fd08275e7da439166jimblandy// copyright notice, this list of conditions and the following disclaimer
12057aa1f6173501e1a62cf91fd08275e7da439166jimblandy// in the documentation and/or other materials provided with the
13057aa1f6173501e1a62cf91fd08275e7da439166jimblandy// distribution.
14057aa1f6173501e1a62cf91fd08275e7da439166jimblandy//     * Neither the name of Google Inc. nor the names of its
15057aa1f6173501e1a62cf91fd08275e7da439166jimblandy// contributors may be used to endorse or promote products derived from
16057aa1f6173501e1a62cf91fd08275e7da439166jimblandy// this software without specific prior written permission.
17057aa1f6173501e1a62cf91fd08275e7da439166jimblandy//
18057aa1f6173501e1a62cf91fd08275e7da439166jimblandy// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19057aa1f6173501e1a62cf91fd08275e7da439166jimblandy// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20057aa1f6173501e1a62cf91fd08275e7da439166jimblandy// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21057aa1f6173501e1a62cf91fd08275e7da439166jimblandy// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22057aa1f6173501e1a62cf91fd08275e7da439166jimblandy// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23057aa1f6173501e1a62cf91fd08275e7da439166jimblandy// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24057aa1f6173501e1a62cf91fd08275e7da439166jimblandy// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25057aa1f6173501e1a62cf91fd08275e7da439166jimblandy// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26057aa1f6173501e1a62cf91fd08275e7da439166jimblandy// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27057aa1f6173501e1a62cf91fd08275e7da439166jimblandy// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28057aa1f6173501e1a62cf91fd08275e7da439166jimblandy// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29057aa1f6173501e1a62cf91fd08275e7da439166jimblandy
30c50e7c604cd1b12bba9421b0a95357fc942ecd7cjimblandy// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
31c50e7c604cd1b12bba9421b0a95357fc942ecd7cjimblandy
32c50e7c604cd1b12bba9421b0a95357fc942ecd7cjimblandy// Implement the DwarfCUToModule class; see dwarf_cu_to_module.h.
33c50e7c604cd1b12bba9421b0a95357fc942ecd7cjimblandy
348ca54e486c2b1df72a6eebc0dcb43ef7847cd428mark@chromium.org// For <inttypes.h> PRI* macros, before anything else might #include it.
358ca54e486c2b1df72a6eebc0dcb43ef7847cd428mark@chromium.org#ifndef __STDC_FORMAT_MACROS
368ca54e486c2b1df72a6eebc0dcb43ef7847cd428mark@chromium.org#define __STDC_FORMAT_MACROS
378ca54e486c2b1df72a6eebc0dcb43ef7847cd428mark@chromium.org#endif  /* __STDC_FORMAT_MACROS */
388ca54e486c2b1df72a6eebc0dcb43ef7847cd428mark@chromium.org
39e1930985430ce289f4fe8525f51050e5d78cc44eted.mielczarek#include "common/dwarf_cu_to_module.h"
40e1930985430ce289f4fe8525f51050e5d78cc44eted.mielczarek
41e1930985430ce289f4fe8525f51050e5d78cc44eted.mielczarek#include <assert.h>
42f9ba50d41d6fe2fc3fa29fe8db547e418edc460ated.mielczarek@gmail.com#if !defined(__ANDROID__)
431277babefa9180dc4bc83c9f70afb0014df82d0fted.mielczarek@gmail.com#include <cxxabi.h>
44f9ba50d41d6fe2fc3fa29fe8db547e418edc460ated.mielczarek@gmail.com#endif
458ca54e486c2b1df72a6eebc0dcb43ef7847cd428mark@chromium.org#include <inttypes.h>
463ca4a120de8ec3f35e972e4b23f527bb8f65c479ted.mielczarek#include <stdio.h>
47e1930985430ce289f4fe8525f51050e5d78cc44eted.mielczarek
48057aa1f6173501e1a62cf91fd08275e7da439166jimblandy#include <algorithm>
49786275e7195761228374d7c0f5ff02403c7e1ef8jimblandy#include <utility>
50057aa1f6173501e1a62cf91fd08275e7da439166jimblandy
5187855248f1fab83caf002418196a34051d359f2cjimblandy#include "common/dwarf_line_to_module.h"
52467db189796399215568d59e2b936f3388a6081aivanpe@chromium.org#include "common/unordered.h"
53057aa1f6173501e1a62cf91fd08275e7da439166jimblandy
54057aa1f6173501e1a62cf91fd08275e7da439166jimblandynamespace google_breakpad {
55057aa1f6173501e1a62cf91fd08275e7da439166jimblandy
56057aa1f6173501e1a62cf91fd08275e7da439166jimblandyusing std::map;
57786275e7195761228374d7c0f5ff02403c7e1ef8jimblandyusing std::pair;
585454576276fa6932bdfcddc959c785ebd601d273ted.mielczarek@gmail.comusing std::sort;
59057aa1f6173501e1a62cf91fd08275e7da439166jimblandyusing std::vector;
60057aa1f6173501e1a62cf91fd08275e7da439166jimblandy
61057aa1f6173501e1a62cf91fd08275e7da439166jimblandy// Data provided by a DWARF specification DIE.
621277babefa9180dc4bc83c9f70afb0014df82d0fted.mielczarek@gmail.com//
63057aa1f6173501e1a62cf91fd08275e7da439166jimblandy// In DWARF, the DIE for a definition may contain a DW_AT_specification
64057aa1f6173501e1a62cf91fd08275e7da439166jimblandy// attribute giving the offset of the corresponding declaration DIE, and
65057aa1f6173501e1a62cf91fd08275e7da439166jimblandy// the definition DIE may omit information given in the declaration. For
66057aa1f6173501e1a62cf91fd08275e7da439166jimblandy// example, it's common for a function's address range to appear only in
67057aa1f6173501e1a62cf91fd08275e7da439166jimblandy// its definition DIE, but its name to appear only in its declaration
68057aa1f6173501e1a62cf91fd08275e7da439166jimblandy// DIE.
69057aa1f6173501e1a62cf91fd08275e7da439166jimblandy//
70057aa1f6173501e1a62cf91fd08275e7da439166jimblandy// The dumper needs to be able to follow DW_AT_specification links to
71057aa1f6173501e1a62cf91fd08275e7da439166jimblandy// bring all this information together in a FUNC record. Conveniently,
72057aa1f6173501e1a62cf91fd08275e7da439166jimblandy// DIEs that are the target of such links have a DW_AT_declaration flag
73057aa1f6173501e1a62cf91fd08275e7da439166jimblandy// set, so we can identify them when we first see them, and record their
74057aa1f6173501e1a62cf91fd08275e7da439166jimblandy// contents for later reference.
75057aa1f6173501e1a62cf91fd08275e7da439166jimblandy//
76057aa1f6173501e1a62cf91fd08275e7da439166jimblandy// A Specification holds information gathered from a declaration DIE that
77057aa1f6173501e1a62cf91fd08275e7da439166jimblandy// we may need if we find a DW_AT_specification link pointing to it.
78057aa1f6173501e1a62cf91fd08275e7da439166jimblandystruct DwarfCUToModule::Specification {
79acf56d00ae530b653c23cf2ed71c4c434c81b154jimblandy  // The qualified name that can be found by demangling DW_AT_MIPS_linkage_name.
80acf56d00ae530b653c23cf2ed71c4c434c81b154jimblandy  string qualified_name;
81acf56d00ae530b653c23cf2ed71c4c434c81b154jimblandy
82057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  // The name of the enclosing scope, or the empty string if there is none.
83057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  string enclosing_name;
84057aa1f6173501e1a62cf91fd08275e7da439166jimblandy
85057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  // The name for the specification DIE itself, without any enclosing
86057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  // name components.
87057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  string unqualified_name;
88057aa1f6173501e1a62cf91fd08275e7da439166jimblandy};
89057aa1f6173501e1a62cf91fd08275e7da439166jimblandy
90dd5067f391baee2561404f8e2915429b3d638ff7jimblandy// An abstract origin -- base definition of an inline function.
91dd5067f391baee2561404f8e2915429b3d638ff7jimblandystruct AbstractOrigin {
92dd5067f391baee2561404f8e2915429b3d638ff7jimblandy  AbstractOrigin() : name() {}
9352dc308f4271478a77415f6b71b7e1c96fe56e5athestig@chromium.org  explicit AbstractOrigin(const string& name) : name(name) {}
94dd5067f391baee2561404f8e2915429b3d638ff7jimblandy
95dd5067f391baee2561404f8e2915429b3d638ff7jimblandy  string name;
96dd5067f391baee2561404f8e2915429b3d638ff7jimblandy};
97dd5067f391baee2561404f8e2915429b3d638ff7jimblandy
98dd5067f391baee2561404f8e2915429b3d638ff7jimblandytypedef map<uint64, AbstractOrigin> AbstractOriginByOffset;
99dd5067f391baee2561404f8e2915429b3d638ff7jimblandy
100057aa1f6173501e1a62cf91fd08275e7da439166jimblandy// Data global to the DWARF-bearing file that is private to the
101057aa1f6173501e1a62cf91fd08275e7da439166jimblandy// DWARF-to-Module process.
102057aa1f6173501e1a62cf91fd08275e7da439166jimblandystruct DwarfCUToModule::FilePrivate {
103786275e7195761228374d7c0f5ff02403c7e1ef8jimblandy  // A set of strings used in this CU. Before storing a string in one of
104786275e7195761228374d7c0f5ff02403c7e1ef8jimblandy  // our data structures, insert it into this set, and then use the string
105786275e7195761228374d7c0f5ff02403c7e1ef8jimblandy  // from the set.
106ec0d980602262e4543143c0222eceddd993f6a61jimblandy  //
107ec0d980602262e4543143c0222eceddd993f6a61jimblandy  // In some STL implementations, strings are reference-counted internally,
108ec0d980602262e4543143c0222eceddd993f6a61jimblandy  // meaning that simply using strings from this set, even if passed by
109ec0d980602262e4543143c0222eceddd993f6a61jimblandy  // value, assigned, or held directly in structures and containers
110ec0d980602262e4543143c0222eceddd993f6a61jimblandy  // (map<string, ...>, for example), causes those strings to share a
111ec0d980602262e4543143c0222eceddd993f6a61jimblandy  // single instance of each distinct piece of text. GNU's libstdc++ uses
112ec0d980602262e4543143c0222eceddd993f6a61jimblandy  // reference counts, and I believe MSVC did as well, at some point.
113ec0d980602262e4543143c0222eceddd993f6a61jimblandy  // However, C++ '11 implementations are moving away from reference
114ec0d980602262e4543143c0222eceddd993f6a61jimblandy  // counting.
115ec0d980602262e4543143c0222eceddd993f6a61jimblandy  //
116ec0d980602262e4543143c0222eceddd993f6a61jimblandy  // In other implementations, string assignments copy the string's text,
117ec0d980602262e4543143c0222eceddd993f6a61jimblandy  // so this set will actually hold yet another copy of the string (although
118ec0d980602262e4543143c0222eceddd993f6a61jimblandy  // everything will still work). To improve memory consumption portably,
119ec0d980602262e4543143c0222eceddd993f6a61jimblandy  // we will probably need to use pointers to strings held in this set.
12035c3e843ad4d19aae8c5a7508503a23e38d29772mark@chromium.org  unordered_set<string> common_strings;
121786275e7195761228374d7c0f5ff02403c7e1ef8jimblandy
122057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  // A map from offsets of DIEs within the .debug_info section to
123057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  // Specifications describing those DIEs. Specification references can
124057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  // cross compilation unit boundaries.
125057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  SpecificationByOffset specifications;
126dd5067f391baee2561404f8e2915429b3d638ff7jimblandy
127dd5067f391baee2561404f8e2915429b3d638ff7jimblandy  AbstractOriginByOffset origins;
128057aa1f6173501e1a62cf91fd08275e7da439166jimblandy};
129057aa1f6173501e1a62cf91fd08275e7da439166jimblandy
13052dc308f4271478a77415f6b71b7e1c96fe56e5athestig@chromium.orgDwarfCUToModule::FileContext::FileContext(const string &filename,
13152dc308f4271478a77415f6b71b7e1c96fe56e5athestig@chromium.org                                          Module *module,
13252dc308f4271478a77415f6b71b7e1c96fe56e5athestig@chromium.org                                          bool handle_inter_cu_refs)
13352dc308f4271478a77415f6b71b7e1c96fe56e5athestig@chromium.org    : filename_(filename),
13452dc308f4271478a77415f6b71b7e1c96fe56e5athestig@chromium.org      module_(module),
135b9d6ed468efaa4b65d42c4c5379fde15dcce14c5thestig@chromium.org      handle_inter_cu_refs_(handle_inter_cu_refs),
136b9d6ed468efaa4b65d42c4c5379fde15dcce14c5thestig@chromium.org      file_private_(new FilePrivate()) {
137057aa1f6173501e1a62cf91fd08275e7da439166jimblandy}
138057aa1f6173501e1a62cf91fd08275e7da439166jimblandy
139057aa1f6173501e1a62cf91fd08275e7da439166jimblandyDwarfCUToModule::FileContext::~FileContext() {
14052dc308f4271478a77415f6b71b7e1c96fe56e5athestig@chromium.org}
14152dc308f4271478a77415f6b71b7e1c96fe56e5athestig@chromium.org
14252dc308f4271478a77415f6b71b7e1c96fe56e5athestig@chromium.orgvoid DwarfCUToModule::FileContext::AddSectionToSectionMap(
14352dc308f4271478a77415f6b71b7e1c96fe56e5athestig@chromium.org    const string& name, const char* contents, uint64 length) {
14452dc308f4271478a77415f6b71b7e1c96fe56e5athestig@chromium.org  section_map_[name] = std::make_pair(contents, length);
14552dc308f4271478a77415f6b71b7e1c96fe56e5athestig@chromium.org}
14652dc308f4271478a77415f6b71b7e1c96fe56e5athestig@chromium.org
14752dc308f4271478a77415f6b71b7e1c96fe56e5athestig@chromium.orgvoid DwarfCUToModule::FileContext::ClearSectionMapForTest() {
14852dc308f4271478a77415f6b71b7e1c96fe56e5athestig@chromium.org  section_map_.clear();
14952dc308f4271478a77415f6b71b7e1c96fe56e5athestig@chromium.org}
15052dc308f4271478a77415f6b71b7e1c96fe56e5athestig@chromium.org
15152dc308f4271478a77415f6b71b7e1c96fe56e5athestig@chromium.orgconst dwarf2reader::SectionMap&
15252dc308f4271478a77415f6b71b7e1c96fe56e5athestig@chromium.orgDwarfCUToModule::FileContext::section_map() const {
15352dc308f4271478a77415f6b71b7e1c96fe56e5athestig@chromium.org  return section_map_;
15452dc308f4271478a77415f6b71b7e1c96fe56e5athestig@chromium.org}
15552dc308f4271478a77415f6b71b7e1c96fe56e5athestig@chromium.org
15652dc308f4271478a77415f6b71b7e1c96fe56e5athestig@chromium.orgvoid DwarfCUToModule::FileContext::ClearSpecifications() {
15752dc308f4271478a77415f6b71b7e1c96fe56e5athestig@chromium.org  if (!handle_inter_cu_refs_)
15852dc308f4271478a77415f6b71b7e1c96fe56e5athestig@chromium.org    file_private_->specifications.clear();
15952dc308f4271478a77415f6b71b7e1c96fe56e5athestig@chromium.org}
16052dc308f4271478a77415f6b71b7e1c96fe56e5athestig@chromium.org
16152dc308f4271478a77415f6b71b7e1c96fe56e5athestig@chromium.orgbool DwarfCUToModule::FileContext::IsUnhandledInterCUReference(
16252dc308f4271478a77415f6b71b7e1c96fe56e5athestig@chromium.org    uint64 offset, uint64 compilation_unit_start) const {
16352dc308f4271478a77415f6b71b7e1c96fe56e5athestig@chromium.org  if (handle_inter_cu_refs_)
16452dc308f4271478a77415f6b71b7e1c96fe56e5athestig@chromium.org    return false;
16552dc308f4271478a77415f6b71b7e1c96fe56e5athestig@chromium.org  return offset < compilation_unit_start;
166057aa1f6173501e1a62cf91fd08275e7da439166jimblandy}
167057aa1f6173501e1a62cf91fd08275e7da439166jimblandy
168057aa1f6173501e1a62cf91fd08275e7da439166jimblandy// Information global to the particular compilation unit we're
169057aa1f6173501e1a62cf91fd08275e7da439166jimblandy// parsing. This is for data shared across the CU's entire DIE tree,
170057aa1f6173501e1a62cf91fd08275e7da439166jimblandy// and parameters from the code invoking the CU parser.
171057aa1f6173501e1a62cf91fd08275e7da439166jimblandystruct DwarfCUToModule::CUContext {
172057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  CUContext(FileContext *file_context_arg, WarningReporter *reporter_arg)
173057aa1f6173501e1a62cf91fd08275e7da439166jimblandy      : file_context(file_context_arg),
174057aa1f6173501e1a62cf91fd08275e7da439166jimblandy        reporter(reporter_arg),
17552dc308f4271478a77415f6b71b7e1c96fe56e5athestig@chromium.org        language(Language::CPlusPlus) {}
17652dc308f4271478a77415f6b71b7e1c96fe56e5athestig@chromium.org
177057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  ~CUContext() {
178057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    for (vector<Module::Function *>::iterator it = functions.begin();
17952dc308f4271478a77415f6b71b7e1c96fe56e5athestig@chromium.org         it != functions.end(); ++it) {
180057aa1f6173501e1a62cf91fd08275e7da439166jimblandy      delete *it;
18152dc308f4271478a77415f6b71b7e1c96fe56e5athestig@chromium.org    }
182057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  };
183057aa1f6173501e1a62cf91fd08275e7da439166jimblandy
184057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  // The DWARF-bearing file into which this CU was incorporated.
185057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  FileContext *file_context;
186057aa1f6173501e1a62cf91fd08275e7da439166jimblandy
187057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  // For printing error messages.
188057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  WarningReporter *reporter;
189057aa1f6173501e1a62cf91fd08275e7da439166jimblandy
190057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  // The source language of this compilation unit.
191057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  const Language *language;
192057aa1f6173501e1a62cf91fd08275e7da439166jimblandy
193057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  // The functions defined in this compilation unit. We accumulate
194057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  // them here during parsing. Then, in DwarfCUToModule::Finish, we
195057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  // assign them lines and add them to file_context->module.
196057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  //
197057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  // Destroying this destroys all the functions this vector points to.
198057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  vector<Module::Function *> functions;
199057aa1f6173501e1a62cf91fd08275e7da439166jimblandy};
200057aa1f6173501e1a62cf91fd08275e7da439166jimblandy
201057aa1f6173501e1a62cf91fd08275e7da439166jimblandy// Information about the context of a particular DIE. This is for
202057aa1f6173501e1a62cf91fd08275e7da439166jimblandy// information that changes as we descend the tree towards the leaves:
203057aa1f6173501e1a62cf91fd08275e7da439166jimblandy// the containing classes/namespaces, etc.
204057aa1f6173501e1a62cf91fd08275e7da439166jimblandystruct DwarfCUToModule::DIEContext {
205057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  // The fully-qualified name of the context. For example, for a
206057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  // tree like:
207057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  //
208057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  // DW_TAG_namespace Foo
209057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  //   DW_TAG_class Bar
210057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  //     DW_TAG_subprogram Baz
211057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  //
212057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  // in a C++ compilation unit, the DIEContext's name for the
213057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  // DW_TAG_subprogram DIE would be "Foo::Bar". The DIEContext's
214057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  // name for the DW_TAG_namespace DIE would be "".
215057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  string name;
216057aa1f6173501e1a62cf91fd08275e7da439166jimblandy};
217057aa1f6173501e1a62cf91fd08275e7da439166jimblandy
218057aa1f6173501e1a62cf91fd08275e7da439166jimblandy// An abstract base class for all the dumper's DIE handlers.
219057aa1f6173501e1a62cf91fd08275e7da439166jimblandyclass DwarfCUToModule::GenericDIEHandler: public dwarf2reader::DIEHandler {
220057aa1f6173501e1a62cf91fd08275e7da439166jimblandy public:
221057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  // Create a handler for the DIE at OFFSET whose compilation unit is
222057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  // described by CU_CONTEXT, and whose immediate context is described
223057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  // by PARENT_CONTEXT.
224057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  GenericDIEHandler(CUContext *cu_context, DIEContext *parent_context,
225057aa1f6173501e1a62cf91fd08275e7da439166jimblandy                    uint64 offset)
226057aa1f6173501e1a62cf91fd08275e7da439166jimblandy      : cu_context_(cu_context),
227057aa1f6173501e1a62cf91fd08275e7da439166jimblandy        parent_context_(parent_context),
228057aa1f6173501e1a62cf91fd08275e7da439166jimblandy        offset_(offset),
229057aa1f6173501e1a62cf91fd08275e7da439166jimblandy        declaration_(false),
230057aa1f6173501e1a62cf91fd08275e7da439166jimblandy        specification_(NULL) { }
231057aa1f6173501e1a62cf91fd08275e7da439166jimblandy
232057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  // Derived classes' ProcessAttributeUnsigned can defer to this to
233057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  // handle DW_AT_declaration, or simply not override it.
234057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  void ProcessAttributeUnsigned(enum DwarfAttribute attr,
235057aa1f6173501e1a62cf91fd08275e7da439166jimblandy                                enum DwarfForm form,
236057aa1f6173501e1a62cf91fd08275e7da439166jimblandy                                uint64 data);
237057aa1f6173501e1a62cf91fd08275e7da439166jimblandy
238057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  // Derived classes' ProcessAttributeReference can defer to this to
239057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  // handle DW_AT_specification, or simply not override it.
240057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  void ProcessAttributeReference(enum DwarfAttribute attr,
241057aa1f6173501e1a62cf91fd08275e7da439166jimblandy                                 enum DwarfForm form,
242057aa1f6173501e1a62cf91fd08275e7da439166jimblandy                                 uint64 data);
243057aa1f6173501e1a62cf91fd08275e7da439166jimblandy
244057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  // Derived classes' ProcessAttributeReference can defer to this to
245057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  // handle DW_AT_specification, or simply not override it.
246057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  void ProcessAttributeString(enum DwarfAttribute attr,
247057aa1f6173501e1a62cf91fd08275e7da439166jimblandy                              enum DwarfForm form,
248057aa1f6173501e1a62cf91fd08275e7da439166jimblandy                              const string &data);
249057aa1f6173501e1a62cf91fd08275e7da439166jimblandy
250057aa1f6173501e1a62cf91fd08275e7da439166jimblandy protected:
251057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  // Compute and return the fully-qualified name of the DIE. If this
252057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  // DIE is a declaration DIE, to be cited by other DIEs'
253057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  // DW_AT_specification attributes, record its enclosing name and
254057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  // unqualified name in the specification table.
255c50e7c604cd1b12bba9421b0a95357fc942ecd7cjimblandy  //
256c50e7c604cd1b12bba9421b0a95357fc942ecd7cjimblandy  // Use this from EndAttributes member functions, not ProcessAttribute*
257c50e7c604cd1b12bba9421b0a95357fc942ecd7cjimblandy  // functions; only the former can be sure that all the DIE's attributes
258c50e7c604cd1b12bba9421b0a95357fc942ecd7cjimblandy  // have been seen.
259057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  string ComputeQualifiedName();
260057aa1f6173501e1a62cf91fd08275e7da439166jimblandy
261057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  CUContext *cu_context_;
262057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  DIEContext *parent_context_;
263057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  uint64 offset_;
264057aa1f6173501e1a62cf91fd08275e7da439166jimblandy
2651277babefa9180dc4bc83c9f70afb0014df82d0fted.mielczarek@gmail.com  // Place the name in the global set of strings. Even though this looks
2661277babefa9180dc4bc83c9f70afb0014df82d0fted.mielczarek@gmail.com  // like a copy, all the major std::string implementations use reference
2671277babefa9180dc4bc83c9f70afb0014df82d0fted.mielczarek@gmail.com  // counting internally, so the effect is to have all the data structures
2681277babefa9180dc4bc83c9f70afb0014df82d0fted.mielczarek@gmail.com  // share copies of strings whenever possible.
2691277babefa9180dc4bc83c9f70afb0014df82d0fted.mielczarek@gmail.com  // FIXME: Should this return something like a string_ref to avoid the
2701277babefa9180dc4bc83c9f70afb0014df82d0fted.mielczarek@gmail.com  // assumption about how strings are implemented?
2711277babefa9180dc4bc83c9f70afb0014df82d0fted.mielczarek@gmail.com  string AddStringToPool(const string &str);
2721277babefa9180dc4bc83c9f70afb0014df82d0fted.mielczarek@gmail.com
273057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  // If this DIE has a DW_AT_declaration attribute, this is its value.
274057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  // It is false on DIEs with no DW_AT_declaration attribute.
275057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  bool declaration_;
276057aa1f6173501e1a62cf91fd08275e7da439166jimblandy
277057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  // If this DIE has a DW_AT_specification attribute, this is the
278057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  // Specification structure for the DIE the attribute refers to.
279057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  // Otherwise, this is NULL.
280057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  Specification *specification_;
281057aa1f6173501e1a62cf91fd08275e7da439166jimblandy
282057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  // The value of the DW_AT_name attribute, or the empty string if the
283057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  // DIE has no such attribute.
284057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  string name_attribute_;
2851277babefa9180dc4bc83c9f70afb0014df82d0fted.mielczarek@gmail.com
2861277babefa9180dc4bc83c9f70afb0014df82d0fted.mielczarek@gmail.com  // The demangled value of the DW_AT_MIPS_linkage_name attribute, or the empty
2871277babefa9180dc4bc83c9f70afb0014df82d0fted.mielczarek@gmail.com  // string if the DIE has no such attribute or its content could not be
2881277babefa9180dc4bc83c9f70afb0014df82d0fted.mielczarek@gmail.com  // demangled.
2891277babefa9180dc4bc83c9f70afb0014df82d0fted.mielczarek@gmail.com  string demangled_name_;
290057aa1f6173501e1a62cf91fd08275e7da439166jimblandy};
291057aa1f6173501e1a62cf91fd08275e7da439166jimblandy
292057aa1f6173501e1a62cf91fd08275e7da439166jimblandyvoid DwarfCUToModule::GenericDIEHandler::ProcessAttributeUnsigned(
293057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    enum DwarfAttribute attr,
294057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    enum DwarfForm form,
295057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    uint64 data) {
296057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  switch (attr) {
297057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    case dwarf2reader::DW_AT_declaration: declaration_ = (data != 0); break;
298057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    default: break;
299057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  }
300057aa1f6173501e1a62cf91fd08275e7da439166jimblandy}
301057aa1f6173501e1a62cf91fd08275e7da439166jimblandy
302057aa1f6173501e1a62cf91fd08275e7da439166jimblandyvoid DwarfCUToModule::GenericDIEHandler::ProcessAttributeReference(
303057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    enum DwarfAttribute attr,
304057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    enum DwarfForm form,
305057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    uint64 data) {
306057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  switch (attr) {
307057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    case dwarf2reader::DW_AT_specification: {
30852dc308f4271478a77415f6b71b7e1c96fe56e5athestig@chromium.org      FileContext *file_context = cu_context_->file_context;
30952dc308f4271478a77415f6b71b7e1c96fe56e5athestig@chromium.org      if (file_context->IsUnhandledInterCUReference(
31052dc308f4271478a77415f6b71b7e1c96fe56e5athestig@chromium.org              data, cu_context_->reporter->cu_offset())) {
31152dc308f4271478a77415f6b71b7e1c96fe56e5athestig@chromium.org        cu_context_->reporter->UnhandledInterCUReference(offset_, data);
31252dc308f4271478a77415f6b71b7e1c96fe56e5athestig@chromium.org        break;
31352dc308f4271478a77415f6b71b7e1c96fe56e5athestig@chromium.org      }
314c50e7c604cd1b12bba9421b0a95357fc942ecd7cjimblandy      // Find the Specification to which this attribute refers, and
315c50e7c604cd1b12bba9421b0a95357fc942ecd7cjimblandy      // set specification_ appropriately. We could do more processing
316c50e7c604cd1b12bba9421b0a95357fc942ecd7cjimblandy      // here, but it's better to leave the real work to our
317c50e7c604cd1b12bba9421b0a95357fc942ecd7cjimblandy      // EndAttribute member function, at which point we know we have
318c50e7c604cd1b12bba9421b0a95357fc942ecd7cjimblandy      // seen all the DIE's attributes.
31952dc308f4271478a77415f6b71b7e1c96fe56e5athestig@chromium.org      SpecificationByOffset *specifications =
32052dc308f4271478a77415f6b71b7e1c96fe56e5athestig@chromium.org          &file_context->file_private_->specifications;
321057aa1f6173501e1a62cf91fd08275e7da439166jimblandy      SpecificationByOffset::iterator spec = specifications->find(data);
322057aa1f6173501e1a62cf91fd08275e7da439166jimblandy      if (spec != specifications->end()) {
323057aa1f6173501e1a62cf91fd08275e7da439166jimblandy        specification_ = &spec->second;
324057aa1f6173501e1a62cf91fd08275e7da439166jimblandy      } else {
325057aa1f6173501e1a62cf91fd08275e7da439166jimblandy        // Technically, there's no reason a DW_AT_specification
326057aa1f6173501e1a62cf91fd08275e7da439166jimblandy        // couldn't be a forward reference, but supporting that would
327057aa1f6173501e1a62cf91fd08275e7da439166jimblandy        // be a lot of work (changing to a two-pass structure), and I
328057aa1f6173501e1a62cf91fd08275e7da439166jimblandy        // don't think any producers we care about ever emit such
329057aa1f6173501e1a62cf91fd08275e7da439166jimblandy        // things.
330057aa1f6173501e1a62cf91fd08275e7da439166jimblandy        cu_context_->reporter->UnknownSpecification(offset_, data);
331dd5067f391baee2561404f8e2915429b3d638ff7jimblandy      }
332057aa1f6173501e1a62cf91fd08275e7da439166jimblandy      break;
333057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    }
334057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    default: break;
335057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  }
336057aa1f6173501e1a62cf91fd08275e7da439166jimblandy}
337057aa1f6173501e1a62cf91fd08275e7da439166jimblandy
3381277babefa9180dc4bc83c9f70afb0014df82d0fted.mielczarek@gmail.comstring DwarfCUToModule::GenericDIEHandler::AddStringToPool(const string &str) {
33935c3e843ad4d19aae8c5a7508503a23e38d29772mark@chromium.org  pair<unordered_set<string>::iterator, bool> result =
34052dc308f4271478a77415f6b71b7e1c96fe56e5athestig@chromium.org    cu_context_->file_context->file_private_->common_strings.insert(str);
3411277babefa9180dc4bc83c9f70afb0014df82d0fted.mielczarek@gmail.com  return *result.first;
3421277babefa9180dc4bc83c9f70afb0014df82d0fted.mielczarek@gmail.com}
3431277babefa9180dc4bc83c9f70afb0014df82d0fted.mielczarek@gmail.com
344057aa1f6173501e1a62cf91fd08275e7da439166jimblandyvoid DwarfCUToModule::GenericDIEHandler::ProcessAttributeString(
345057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    enum DwarfAttribute attr,
346057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    enum DwarfForm form,
347057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    const string &data) {
348057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  switch (attr) {
3491277babefa9180dc4bc83c9f70afb0014df82d0fted.mielczarek@gmail.com    case dwarf2reader::DW_AT_name:
3501277babefa9180dc4bc83c9f70afb0014df82d0fted.mielczarek@gmail.com      name_attribute_ = AddStringToPool(data);
3511277babefa9180dc4bc83c9f70afb0014df82d0fted.mielczarek@gmail.com      break;
3521277babefa9180dc4bc83c9f70afb0014df82d0fted.mielczarek@gmail.com    case dwarf2reader::DW_AT_MIPS_linkage_name: {
353f9ba50d41d6fe2fc3fa29fe8db547e418edc460ated.mielczarek@gmail.com      char* demangled = NULL;
3546105ae42dc0a63fe651b050244c9bbc6a549bfc5erikchen@chromium.org      int status = -1;
3557b127284ccc6d8dfa2d998d2ffea0ced9ff48a86hashimoto@chromium.org#if !defined(__ANDROID__)  // Android NDK doesn't provide abi::__cxa_demangle.
3566105ae42dc0a63fe651b050244c9bbc6a549bfc5erikchen@chromium.org      demangled = abi::__cxa_demangle(data.c_str(), NULL, NULL, &status);
357f9ba50d41d6fe2fc3fa29fe8db547e418edc460ated.mielczarek@gmail.com#endif
3586105ae42dc0a63fe651b050244c9bbc6a549bfc5erikchen@chromium.org      if (status != 0) {
3596105ae42dc0a63fe651b050244c9bbc6a549bfc5erikchen@chromium.org        cu_context_->reporter->DemangleError(data, status);
3606105ae42dc0a63fe651b050244c9bbc6a549bfc5erikchen@chromium.org        demangled_name_ = "";
3616105ae42dc0a63fe651b050244c9bbc6a549bfc5erikchen@chromium.org        break;
3626105ae42dc0a63fe651b050244c9bbc6a549bfc5erikchen@chromium.org      }
3631277babefa9180dc4bc83c9f70afb0014df82d0fted.mielczarek@gmail.com      if (demangled) {
3641277babefa9180dc4bc83c9f70afb0014df82d0fted.mielczarek@gmail.com        demangled_name_ = AddStringToPool(demangled);
3651277babefa9180dc4bc83c9f70afb0014df82d0fted.mielczarek@gmail.com        free(reinterpret_cast<void*>(demangled));
3661277babefa9180dc4bc83c9f70afb0014df82d0fted.mielczarek@gmail.com      }
367786275e7195761228374d7c0f5ff02403c7e1ef8jimblandy      break;
368786275e7195761228374d7c0f5ff02403c7e1ef8jimblandy    }
369057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    default: break;
370057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  }
371057aa1f6173501e1a62cf91fd08275e7da439166jimblandy}
372057aa1f6173501e1a62cf91fd08275e7da439166jimblandy
373057aa1f6173501e1a62cf91fd08275e7da439166jimblandystring DwarfCUToModule::GenericDIEHandler::ComputeQualifiedName() {
374acf56d00ae530b653c23cf2ed71c4c434c81b154jimblandy  // Use the demangled name, if one is available. Demangled names are
375acf56d00ae530b653c23cf2ed71c4c434c81b154jimblandy  // preferable to those inferred from the DWARF structure because they
376acf56d00ae530b653c23cf2ed71c4c434c81b154jimblandy  // include argument types.
377acf56d00ae530b653c23cf2ed71c4c434c81b154jimblandy  const string *qualified_name = NULL;
378acf56d00ae530b653c23cf2ed71c4c434c81b154jimblandy  if (!demangled_name_.empty()) {
379acf56d00ae530b653c23cf2ed71c4c434c81b154jimblandy    // Found it is this DIE.
380acf56d00ae530b653c23cf2ed71c4c434c81b154jimblandy    qualified_name = &demangled_name_;
381acf56d00ae530b653c23cf2ed71c4c434c81b154jimblandy  } else if (specification_ && !specification_->qualified_name.empty()) {
382acf56d00ae530b653c23cf2ed71c4c434c81b154jimblandy    // Found it on the specification.
383acf56d00ae530b653c23cf2ed71c4c434c81b154jimblandy    qualified_name = &specification_->qualified_name;
384acf56d00ae530b653c23cf2ed71c4c434c81b154jimblandy  }
3851277babefa9180dc4bc83c9f70afb0014df82d0fted.mielczarek@gmail.com
386057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  const string *unqualified_name;
387057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  const string *enclosing_name;
388acf56d00ae530b653c23cf2ed71c4c434c81b154jimblandy  if (!qualified_name) {
389acf56d00ae530b653c23cf2ed71c4c434c81b154jimblandy    // Find our unqualified name. If the DIE has its own DW_AT_name
390acf56d00ae530b653c23cf2ed71c4c434c81b154jimblandy    // attribute, then use that; otherwise, check our specification.
391acf56d00ae530b653c23cf2ed71c4c434c81b154jimblandy    if (name_attribute_.empty() && specification_)
392acf56d00ae530b653c23cf2ed71c4c434c81b154jimblandy      unqualified_name = &specification_->unqualified_name;
393acf56d00ae530b653c23cf2ed71c4c434c81b154jimblandy    else
394acf56d00ae530b653c23cf2ed71c4c434c81b154jimblandy      unqualified_name = &name_attribute_;
395acf56d00ae530b653c23cf2ed71c4c434c81b154jimblandy
396acf56d00ae530b653c23cf2ed71c4c434c81b154jimblandy    // Find the name of our enclosing context. If we have a
397acf56d00ae530b653c23cf2ed71c4c434c81b154jimblandy    // specification, it's the specification's enclosing context that
398acf56d00ae530b653c23cf2ed71c4c434c81b154jimblandy    // counts; otherwise, use this DIE's context.
399acf56d00ae530b653c23cf2ed71c4c434c81b154jimblandy    if (specification_)
400acf56d00ae530b653c23cf2ed71c4c434c81b154jimblandy      enclosing_name = &specification_->enclosing_name;
401acf56d00ae530b653c23cf2ed71c4c434c81b154jimblandy    else
402acf56d00ae530b653c23cf2ed71c4c434c81b154jimblandy      enclosing_name = &parent_context_->name;
403acf56d00ae530b653c23cf2ed71c4c434c81b154jimblandy  }
404057aa1f6173501e1a62cf91fd08275e7da439166jimblandy
405f1ecc41ff43ebd44ddac195bcdace03f421eb852erikchen@chromium.org  // Prepare the return value before upcoming mutations possibly invalidate the
406f1ecc41ff43ebd44ddac195bcdace03f421eb852erikchen@chromium.org  // existing pointers.
407f1ecc41ff43ebd44ddac195bcdace03f421eb852erikchen@chromium.org  string return_value;
408f1ecc41ff43ebd44ddac195bcdace03f421eb852erikchen@chromium.org  if (qualified_name) {
409f1ecc41ff43ebd44ddac195bcdace03f421eb852erikchen@chromium.org    return_value = *qualified_name;
410f1ecc41ff43ebd44ddac195bcdace03f421eb852erikchen@chromium.org  } else {
411f1ecc41ff43ebd44ddac195bcdace03f421eb852erikchen@chromium.org    // Combine the enclosing name and unqualified name to produce our
412f1ecc41ff43ebd44ddac195bcdace03f421eb852erikchen@chromium.org    // own fully-qualified name.
413f1ecc41ff43ebd44ddac195bcdace03f421eb852erikchen@chromium.org    return_value = cu_context_->language->MakeQualifiedName(*enclosing_name,
414f1ecc41ff43ebd44ddac195bcdace03f421eb852erikchen@chromium.org                                                            *unqualified_name);
415f1ecc41ff43ebd44ddac195bcdace03f421eb852erikchen@chromium.org  }
416f1ecc41ff43ebd44ddac195bcdace03f421eb852erikchen@chromium.org
417057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  // If this DIE was marked as a declaration, record its names in the
418057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  // specification table.
419057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  if (declaration_) {
420057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    Specification spec;
42152dc308f4271478a77415f6b71b7e1c96fe56e5athestig@chromium.org    if (qualified_name) {
422acf56d00ae530b653c23cf2ed71c4c434c81b154jimblandy      spec.qualified_name = *qualified_name;
42352dc308f4271478a77415f6b71b7e1c96fe56e5athestig@chromium.org    } else {
424acf56d00ae530b653c23cf2ed71c4c434c81b154jimblandy      spec.enclosing_name = *enclosing_name;
425acf56d00ae530b653c23cf2ed71c4c434c81b154jimblandy      spec.unqualified_name = *unqualified_name;
426acf56d00ae530b653c23cf2ed71c4c434c81b154jimblandy    }
42752dc308f4271478a77415f6b71b7e1c96fe56e5athestig@chromium.org    cu_context_->file_context->file_private_->specifications[offset_] = spec;
428057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  }
429057aa1f6173501e1a62cf91fd08275e7da439166jimblandy
430f1ecc41ff43ebd44ddac195bcdace03f421eb852erikchen@chromium.org  return return_value;
431057aa1f6173501e1a62cf91fd08275e7da439166jimblandy}
432057aa1f6173501e1a62cf91fd08275e7da439166jimblandy
433057aa1f6173501e1a62cf91fd08275e7da439166jimblandy// A handler class for DW_TAG_subprogram DIEs.
434057aa1f6173501e1a62cf91fd08275e7da439166jimblandyclass DwarfCUToModule::FuncHandler: public GenericDIEHandler {
435057aa1f6173501e1a62cf91fd08275e7da439166jimblandy public:
436057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  FuncHandler(CUContext *cu_context, DIEContext *parent_context,
437057aa1f6173501e1a62cf91fd08275e7da439166jimblandy              uint64 offset)
438057aa1f6173501e1a62cf91fd08275e7da439166jimblandy      : GenericDIEHandler(cu_context, parent_context, offset),
439ee2531873f38ecb81e45f9f80bdf0ada4a881e3bjimblandy        low_pc_(0), high_pc_(0), high_pc_form_(dwarf2reader::DW_FORM_addr),
440ee2531873f38ecb81e45f9f80bdf0ada4a881e3bjimblandy        abstract_origin_(NULL), inline_(false) { }
441057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  void ProcessAttributeUnsigned(enum DwarfAttribute attr,
442057aa1f6173501e1a62cf91fd08275e7da439166jimblandy                                enum DwarfForm form,
443057aa1f6173501e1a62cf91fd08275e7da439166jimblandy                                uint64 data);
444dd5067f391baee2561404f8e2915429b3d638ff7jimblandy  void ProcessAttributeSigned(enum DwarfAttribute attr,
445dd5067f391baee2561404f8e2915429b3d638ff7jimblandy                              enum DwarfForm form,
446dd5067f391baee2561404f8e2915429b3d638ff7jimblandy                              int64 data);
447dd5067f391baee2561404f8e2915429b3d638ff7jimblandy  void ProcessAttributeReference(enum DwarfAttribute attr,
448dd5067f391baee2561404f8e2915429b3d638ff7jimblandy                                 enum DwarfForm form,
449dd5067f391baee2561404f8e2915429b3d638ff7jimblandy                                 uint64 data);
450dd5067f391baee2561404f8e2915429b3d638ff7jimblandy
451057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  bool EndAttributes();
452057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  void Finish();
453057aa1f6173501e1a62cf91fd08275e7da439166jimblandy
454057aa1f6173501e1a62cf91fd08275e7da439166jimblandy private:
455057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  // The fully-qualified name, as derived from name_attribute_,
456057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  // specification_, parent_context_.  Computed in EndAttributes.
457057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  string name_;
458057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  uint64 low_pc_, high_pc_; // DW_AT_low_pc, DW_AT_high_pc
459ee2531873f38ecb81e45f9f80bdf0ada4a881e3bjimblandy  DwarfForm high_pc_form_; // DW_AT_high_pc can be length or address.
460dd5067f391baee2561404f8e2915429b3d638ff7jimblandy  const AbstractOrigin* abstract_origin_;
461dd5067f391baee2561404f8e2915429b3d638ff7jimblandy  bool inline_;
462057aa1f6173501e1a62cf91fd08275e7da439166jimblandy};
463057aa1f6173501e1a62cf91fd08275e7da439166jimblandy
464057aa1f6173501e1a62cf91fd08275e7da439166jimblandyvoid DwarfCUToModule::FuncHandler::ProcessAttributeUnsigned(
465057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    enum DwarfAttribute attr,
466057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    enum DwarfForm form,
467057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    uint64 data) {
468057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  switch (attr) {
469d6fb5a7c510917af7455e28ac28423d0ee280207jimblandy    // If this attribute is present at all --- even if its value is
470d6fb5a7c510917af7455e28ac28423d0ee280207jimblandy    // DW_INL_not_inlined --- then GCC may cite it as someone else's
471d6fb5a7c510917af7455e28ac28423d0ee280207jimblandy    // DW_AT_abstract_origin attribute.
472d6fb5a7c510917af7455e28ac28423d0ee280207jimblandy    case dwarf2reader::DW_AT_inline:      inline_  = true; break;
473d6fb5a7c510917af7455e28ac28423d0ee280207jimblandy
474057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    case dwarf2reader::DW_AT_low_pc:      low_pc_  = data; break;
475ee2531873f38ecb81e45f9f80bdf0ada4a881e3bjimblandy    case dwarf2reader::DW_AT_high_pc:
476ee2531873f38ecb81e45f9f80bdf0ada4a881e3bjimblandy      high_pc_form_ = form;
477ee2531873f38ecb81e45f9f80bdf0ada4a881e3bjimblandy      high_pc_ = data;
478ee2531873f38ecb81e45f9f80bdf0ada4a881e3bjimblandy      break;
479ee2531873f38ecb81e45f9f80bdf0ada4a881e3bjimblandy
480057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    default:
481057aa1f6173501e1a62cf91fd08275e7da439166jimblandy      GenericDIEHandler::ProcessAttributeUnsigned(attr, form, data);
482057aa1f6173501e1a62cf91fd08275e7da439166jimblandy      break;
483057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  }
484057aa1f6173501e1a62cf91fd08275e7da439166jimblandy}
485057aa1f6173501e1a62cf91fd08275e7da439166jimblandy
486dd5067f391baee2561404f8e2915429b3d638ff7jimblandyvoid DwarfCUToModule::FuncHandler::ProcessAttributeSigned(
487dd5067f391baee2561404f8e2915429b3d638ff7jimblandy    enum DwarfAttribute attr,
488dd5067f391baee2561404f8e2915429b3d638ff7jimblandy    enum DwarfForm form,
489dd5067f391baee2561404f8e2915429b3d638ff7jimblandy    int64 data) {
490dd5067f391baee2561404f8e2915429b3d638ff7jimblandy  switch (attr) {
491d6fb5a7c510917af7455e28ac28423d0ee280207jimblandy    // If this attribute is present at all --- even if its value is
492d6fb5a7c510917af7455e28ac28423d0ee280207jimblandy    // DW_INL_not_inlined --- then GCC may cite it as someone else's
493d6fb5a7c510917af7455e28ac28423d0ee280207jimblandy    // DW_AT_abstract_origin attribute.
494d6fb5a7c510917af7455e28ac28423d0ee280207jimblandy    case dwarf2reader::DW_AT_inline:      inline_  = true; break;
495d6fb5a7c510917af7455e28ac28423d0ee280207jimblandy
496dd5067f391baee2561404f8e2915429b3d638ff7jimblandy    default:
497dd5067f391baee2561404f8e2915429b3d638ff7jimblandy      break;
498dd5067f391baee2561404f8e2915429b3d638ff7jimblandy  }
499dd5067f391baee2561404f8e2915429b3d638ff7jimblandy}
500dd5067f391baee2561404f8e2915429b3d638ff7jimblandy
501dd5067f391baee2561404f8e2915429b3d638ff7jimblandyvoid DwarfCUToModule::FuncHandler::ProcessAttributeReference(
502dd5067f391baee2561404f8e2915429b3d638ff7jimblandy    enum DwarfAttribute attr,
503dd5067f391baee2561404f8e2915429b3d638ff7jimblandy    enum DwarfForm form,
504dd5067f391baee2561404f8e2915429b3d638ff7jimblandy    uint64 data) {
50552dc308f4271478a77415f6b71b7e1c96fe56e5athestig@chromium.org  switch (attr) {
506dd5067f391baee2561404f8e2915429b3d638ff7jimblandy    case dwarf2reader::DW_AT_abstract_origin: {
507dd5067f391baee2561404f8e2915429b3d638ff7jimblandy      const AbstractOriginByOffset& origins =
50852dc308f4271478a77415f6b71b7e1c96fe56e5athestig@chromium.org          cu_context_->file_context->file_private_->origins;
509dd5067f391baee2561404f8e2915429b3d638ff7jimblandy      AbstractOriginByOffset::const_iterator origin = origins.find(data);
510dd5067f391baee2561404f8e2915429b3d638ff7jimblandy      if (origin != origins.end()) {
511dd5067f391baee2561404f8e2915429b3d638ff7jimblandy        abstract_origin_ = &(origin->second);
512dd5067f391baee2561404f8e2915429b3d638ff7jimblandy      } else {
513dd5067f391baee2561404f8e2915429b3d638ff7jimblandy        cu_context_->reporter->UnknownAbstractOrigin(offset_, data);
514dd5067f391baee2561404f8e2915429b3d638ff7jimblandy      }
515dd5067f391baee2561404f8e2915429b3d638ff7jimblandy      break;
516dd5067f391baee2561404f8e2915429b3d638ff7jimblandy    }
517dd5067f391baee2561404f8e2915429b3d638ff7jimblandy    default:
518dd5067f391baee2561404f8e2915429b3d638ff7jimblandy      GenericDIEHandler::ProcessAttributeReference(attr, form, data);
519dd5067f391baee2561404f8e2915429b3d638ff7jimblandy      break;
520dd5067f391baee2561404f8e2915429b3d638ff7jimblandy  }
521dd5067f391baee2561404f8e2915429b3d638ff7jimblandy}
522dd5067f391baee2561404f8e2915429b3d638ff7jimblandy
523057aa1f6173501e1a62cf91fd08275e7da439166jimblandybool DwarfCUToModule::FuncHandler::EndAttributes() {
524057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  // Compute our name, and record a specification, if appropriate.
525057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  name_ = ComputeQualifiedName();
526dd5067f391baee2561404f8e2915429b3d638ff7jimblandy  if (name_.empty() && abstract_origin_) {
527dd5067f391baee2561404f8e2915429b3d638ff7jimblandy    name_ = abstract_origin_->name;
528dd5067f391baee2561404f8e2915429b3d638ff7jimblandy  }
529057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  return true;
530057aa1f6173501e1a62cf91fd08275e7da439166jimblandy}
531057aa1f6173501e1a62cf91fd08275e7da439166jimblandy
532057aa1f6173501e1a62cf91fd08275e7da439166jimblandyvoid DwarfCUToModule::FuncHandler::Finish() {
533ee2531873f38ecb81e45f9f80bdf0ada4a881e3bjimblandy  // Make high_pc_ an address, if it isn't already.
534ee2531873f38ecb81e45f9f80bdf0ada4a881e3bjimblandy  if (high_pc_form_ != dwarf2reader::DW_FORM_addr) {
535ee2531873f38ecb81e45f9f80bdf0ada4a881e3bjimblandy    high_pc_ += low_pc_;
536ee2531873f38ecb81e45f9f80bdf0ada4a881e3bjimblandy  }
537ee2531873f38ecb81e45f9f80bdf0ada4a881e3bjimblandy
538057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  // Did we collect the information we need?  Not all DWARF function
539057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  // entries have low and high addresses (for example, inlined
540057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  // functions that were never used), but all the ones we're
541057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  // interested in cover a non-empty range of bytes.
542057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  if (low_pc_ < high_pc_) {
543fd18beeb5c817aa3ecdb21caceee8e6ce08c6ab3jimblandy    // Malformed DWARF may omit the name, but all Module::Functions must
544fd18beeb5c817aa3ecdb21caceee8e6ce08c6ab3jimblandy    // have names.
5456105ae42dc0a63fe651b050244c9bbc6a549bfc5erikchen@chromium.org    string name;
546fd18beeb5c817aa3ecdb21caceee8e6ce08c6ab3jimblandy    if (!name_.empty()) {
5476105ae42dc0a63fe651b050244c9bbc6a549bfc5erikchen@chromium.org      name = name_;
548fd18beeb5c817aa3ecdb21caceee8e6ce08c6ab3jimblandy    } else {
549fd18beeb5c817aa3ecdb21caceee8e6ce08c6ab3jimblandy      cu_context_->reporter->UnnamedFunction(offset_);
5506105ae42dc0a63fe651b050244c9bbc6a549bfc5erikchen@chromium.org      name = "<name omitted>";
551fd18beeb5c817aa3ecdb21caceee8e6ce08c6ab3jimblandy    }
5526105ae42dc0a63fe651b050244c9bbc6a549bfc5erikchen@chromium.org
5536105ae42dc0a63fe651b050244c9bbc6a549bfc5erikchen@chromium.org    // Create a Module::Function based on the data we've gathered, and
5546105ae42dc0a63fe651b050244c9bbc6a549bfc5erikchen@chromium.org    // add it to the functions_ list.
5556105ae42dc0a63fe651b050244c9bbc6a549bfc5erikchen@chromium.org    scoped_ptr<Module::Function> func(new Module::Function(name, low_pc_));
5563e60d65111607f401461ff15981a463cde8f744ajimblandy    func->size = high_pc_ - low_pc_;
5573e60d65111607f401461ff15981a463cde8f744ajimblandy    func->parameter_size = 0;
558aa52a01f8a977bdb8a1f79ccabab963131574301mark@chromium.org    if (func->address) {
559aa52a01f8a977bdb8a1f79ccabab963131574301mark@chromium.org       // If the function address is zero this is a sign that this function
560aa52a01f8a977bdb8a1f79ccabab963131574301mark@chromium.org       // description is just empty debug data and should just be discarded.
561cd549d40fe428eee93dd3ead2a817fd68a0f5b25thestig@chromium.org       cu_context_->functions.push_back(func.release());
562aa52a01f8a977bdb8a1f79ccabab963131574301mark@chromium.org     }
563dd5067f391baee2561404f8e2915429b3d638ff7jimblandy  } else if (inline_) {
564dd5067f391baee2561404f8e2915429b3d638ff7jimblandy    AbstractOrigin origin(name_);
56552dc308f4271478a77415f6b71b7e1c96fe56e5athestig@chromium.org    cu_context_->file_context->file_private_->origins[offset_] = origin;
566057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  }
567057aa1f6173501e1a62cf91fd08275e7da439166jimblandy}
568057aa1f6173501e1a62cf91fd08275e7da439166jimblandy
569057aa1f6173501e1a62cf91fd08275e7da439166jimblandy// A handler for DIEs that contain functions and contribute a
570057aa1f6173501e1a62cf91fd08275e7da439166jimblandy// component to their names: namespaces, classes, etc.
571057aa1f6173501e1a62cf91fd08275e7da439166jimblandyclass DwarfCUToModule::NamedScopeHandler: public GenericDIEHandler {
572057aa1f6173501e1a62cf91fd08275e7da439166jimblandy public:
573057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  NamedScopeHandler(CUContext *cu_context, DIEContext *parent_context,
574057aa1f6173501e1a62cf91fd08275e7da439166jimblandy                    uint64 offset)
575057aa1f6173501e1a62cf91fd08275e7da439166jimblandy      : GenericDIEHandler(cu_context, parent_context, offset) { }
576057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  bool EndAttributes();
5777c2350868e7f53728866d304bc6a7ce8ba3b5d05mark@chromium.org  DIEHandler *FindChildHandler(uint64 offset, enum DwarfTag tag);
578057aa1f6173501e1a62cf91fd08275e7da439166jimblandy
579057aa1f6173501e1a62cf91fd08275e7da439166jimblandy private:
580057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  DIEContext child_context_; // A context for our children.
581057aa1f6173501e1a62cf91fd08275e7da439166jimblandy};
582057aa1f6173501e1a62cf91fd08275e7da439166jimblandy
583057aa1f6173501e1a62cf91fd08275e7da439166jimblandybool DwarfCUToModule::NamedScopeHandler::EndAttributes() {
584057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  child_context_.name = ComputeQualifiedName();
585057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  return true;
586057aa1f6173501e1a62cf91fd08275e7da439166jimblandy}
587057aa1f6173501e1a62cf91fd08275e7da439166jimblandy
588057aa1f6173501e1a62cf91fd08275e7da439166jimblandydwarf2reader::DIEHandler *DwarfCUToModule::NamedScopeHandler::FindChildHandler(
589057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    uint64 offset,
5907c2350868e7f53728866d304bc6a7ce8ba3b5d05mark@chromium.org    enum DwarfTag tag) {
591057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  switch (tag) {
592057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    case dwarf2reader::DW_TAG_subprogram:
593057aa1f6173501e1a62cf91fd08275e7da439166jimblandy      return new FuncHandler(cu_context_, &child_context_, offset);
594057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    case dwarf2reader::DW_TAG_namespace:
595057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    case dwarf2reader::DW_TAG_class_type:
596057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    case dwarf2reader::DW_TAG_structure_type:
597057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    case dwarf2reader::DW_TAG_union_type:
598057aa1f6173501e1a62cf91fd08275e7da439166jimblandy      return new NamedScopeHandler(cu_context_, &child_context_, offset);
599057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    default:
600057aa1f6173501e1a62cf91fd08275e7da439166jimblandy      return NULL;
601057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  }
602801407144050d86fb22364eb6b8f11873ea7bc1fted.mielczarek@gmail.com}
603057aa1f6173501e1a62cf91fd08275e7da439166jimblandy
604057aa1f6173501e1a62cf91fd08275e7da439166jimblandyvoid DwarfCUToModule::WarningReporter::CUHeading() {
605057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  if (printed_cu_header_)
606057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    return;
607057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  fprintf(stderr, "%s: in compilation unit '%s' (offset 0x%llx):\n",
608057aa1f6173501e1a62cf91fd08275e7da439166jimblandy          filename_.c_str(), cu_name_.c_str(), cu_offset_);
609057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  printed_cu_header_ = true;
610057aa1f6173501e1a62cf91fd08275e7da439166jimblandy}
611057aa1f6173501e1a62cf91fd08275e7da439166jimblandy
612057aa1f6173501e1a62cf91fd08275e7da439166jimblandyvoid DwarfCUToModule::WarningReporter::UnknownSpecification(uint64 offset,
613057aa1f6173501e1a62cf91fd08275e7da439166jimblandy                                                            uint64 target) {
614057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  CUHeading();
615057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  fprintf(stderr, "%s: the DIE at offset 0x%llx has a DW_AT_specification"
616057aa1f6173501e1a62cf91fd08275e7da439166jimblandy          " attribute referring to the die at offset 0x%llx, which either"
61719d77e0c33449b5a78243b8ecf8b8400bfbd5c88jimblandy          " was not marked as a declaration, or comes later in the file\n",
618057aa1f6173501e1a62cf91fd08275e7da439166jimblandy          filename_.c_str(), offset, target);
619057aa1f6173501e1a62cf91fd08275e7da439166jimblandy}
620057aa1f6173501e1a62cf91fd08275e7da439166jimblandy
621dd5067f391baee2561404f8e2915429b3d638ff7jimblandyvoid DwarfCUToModule::WarningReporter::UnknownAbstractOrigin(uint64 offset,
622dd5067f391baee2561404f8e2915429b3d638ff7jimblandy                                                             uint64 target) {
623dd5067f391baee2561404f8e2915429b3d638ff7jimblandy  CUHeading();
624dd5067f391baee2561404f8e2915429b3d638ff7jimblandy  fprintf(stderr, "%s: the DIE at offset 0x%llx has a DW_AT_abstract_origin"
625dd5067f391baee2561404f8e2915429b3d638ff7jimblandy          " attribute referring to the die at offset 0x%llx, which either"
62619d77e0c33449b5a78243b8ecf8b8400bfbd5c88jimblandy          " was not marked as an inline, or comes later in the file\n",
627dd5067f391baee2561404f8e2915429b3d638ff7jimblandy          filename_.c_str(), offset, target);
628dd5067f391baee2561404f8e2915429b3d638ff7jimblandy}
629dd5067f391baee2561404f8e2915429b3d638ff7jimblandy
630057aa1f6173501e1a62cf91fd08275e7da439166jimblandyvoid DwarfCUToModule::WarningReporter::MissingSection(const string &name) {
631057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  CUHeading();
632057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  fprintf(stderr, "%s: warning: couldn't find DWARF '%s' section\n",
633057aa1f6173501e1a62cf91fd08275e7da439166jimblandy          filename_.c_str(), name.c_str());
634057aa1f6173501e1a62cf91fd08275e7da439166jimblandy}
635057aa1f6173501e1a62cf91fd08275e7da439166jimblandy
636057aa1f6173501e1a62cf91fd08275e7da439166jimblandyvoid DwarfCUToModule::WarningReporter::BadLineInfoOffset(uint64 offset) {
637057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  CUHeading();
638057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  fprintf(stderr, "%s: warning: line number data offset beyond end"
639057aa1f6173501e1a62cf91fd08275e7da439166jimblandy          " of '.debug_line' section\n",
640057aa1f6173501e1a62cf91fd08275e7da439166jimblandy          filename_.c_str());
641057aa1f6173501e1a62cf91fd08275e7da439166jimblandy}
642057aa1f6173501e1a62cf91fd08275e7da439166jimblandy
643057aa1f6173501e1a62cf91fd08275e7da439166jimblandyvoid DwarfCUToModule::WarningReporter::UncoveredHeading() {
644057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  if (printed_unpaired_header_)
645057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    return;
646057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  CUHeading();
647057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  fprintf(stderr, "%s: warning: skipping unpaired lines/functions:\n",
648057aa1f6173501e1a62cf91fd08275e7da439166jimblandy          filename_.c_str());
649057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  printed_unpaired_header_ = true;
650057aa1f6173501e1a62cf91fd08275e7da439166jimblandy}
651057aa1f6173501e1a62cf91fd08275e7da439166jimblandy
652057aa1f6173501e1a62cf91fd08275e7da439166jimblandyvoid DwarfCUToModule::WarningReporter::UncoveredFunction(
653057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    const Module::Function &function) {
6549e6b619ad084c58af9fb8983b1a646192adb3835jimblandy  if (!uncovered_warnings_enabled_)
6559e6b619ad084c58af9fb8983b1a646192adb3835jimblandy    return;
656057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  UncoveredHeading();
657057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  fprintf(stderr, "    function%s: %s\n",
6583e60d65111607f401461ff15981a463cde8f744ajimblandy          function.size == 0 ? " (zero-length)" : "",
6593e60d65111607f401461ff15981a463cde8f744ajimblandy          function.name.c_str());
660057aa1f6173501e1a62cf91fd08275e7da439166jimblandy}
661057aa1f6173501e1a62cf91fd08275e7da439166jimblandy
662057aa1f6173501e1a62cf91fd08275e7da439166jimblandyvoid DwarfCUToModule::WarningReporter::UncoveredLine(const Module::Line &line) {
6639e6b619ad084c58af9fb8983b1a646192adb3835jimblandy  if (!uncovered_warnings_enabled_)
6649e6b619ad084c58af9fb8983b1a646192adb3835jimblandy    return;
665057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  UncoveredHeading();
6668ca54e486c2b1df72a6eebc0dcb43ef7847cd428mark@chromium.org  fprintf(stderr, "    line%s: %s:%d at 0x%" PRIx64 "\n",
6673e60d65111607f401461ff15981a463cde8f744ajimblandy          (line.size == 0 ? " (zero-length)" : ""),
6683e60d65111607f401461ff15981a463cde8f744ajimblandy          line.file->name.c_str(), line.number, line.address);
669057aa1f6173501e1a62cf91fd08275e7da439166jimblandy}
670057aa1f6173501e1a62cf91fd08275e7da439166jimblandy
671fd18beeb5c817aa3ecdb21caceee8e6ce08c6ab3jimblandyvoid DwarfCUToModule::WarningReporter::UnnamedFunction(uint64 offset) {
672fd18beeb5c817aa3ecdb21caceee8e6ce08c6ab3jimblandy  CUHeading();
673e40dd59ad4dbfaaba07a09c401fe5966d6130e26ted.mielczarek  fprintf(stderr, "%s: warning: function at offset 0x%llx has no name\n",
674fd18beeb5c817aa3ecdb21caceee8e6ce08c6ab3jimblandy          filename_.c_str(), offset);
675fd18beeb5c817aa3ecdb21caceee8e6ce08c6ab3jimblandy}
676fd18beeb5c817aa3ecdb21caceee8e6ce08c6ab3jimblandy
6776105ae42dc0a63fe651b050244c9bbc6a549bfc5erikchen@chromium.orgvoid DwarfCUToModule::WarningReporter::DemangleError(
6786105ae42dc0a63fe651b050244c9bbc6a549bfc5erikchen@chromium.org    const string &input, int error) {
6796105ae42dc0a63fe651b050244c9bbc6a549bfc5erikchen@chromium.org  CUHeading();
6806105ae42dc0a63fe651b050244c9bbc6a549bfc5erikchen@chromium.org  fprintf(stderr, "%s: warning: failed to demangle %s with error %d\n",
6816105ae42dc0a63fe651b050244c9bbc6a549bfc5erikchen@chromium.org          filename_.c_str(), input.c_str(), error);
6826105ae42dc0a63fe651b050244c9bbc6a549bfc5erikchen@chromium.org}
6836105ae42dc0a63fe651b050244c9bbc6a549bfc5erikchen@chromium.org
68452dc308f4271478a77415f6b71b7e1c96fe56e5athestig@chromium.orgvoid DwarfCUToModule::WarningReporter::UnhandledInterCUReference(
68552dc308f4271478a77415f6b71b7e1c96fe56e5athestig@chromium.org    uint64 offset, uint64 target) {
68652dc308f4271478a77415f6b71b7e1c96fe56e5athestig@chromium.org  CUHeading();
68752dc308f4271478a77415f6b71b7e1c96fe56e5athestig@chromium.org  fprintf(stderr, "%s: warning: the DIE at offset 0x%llx has a "
68852dc308f4271478a77415f6b71b7e1c96fe56e5athestig@chromium.org                  "DW_FORM_ref_addr attribute with an inter-CU reference to "
68952dc308f4271478a77415f6b71b7e1c96fe56e5athestig@chromium.org                  "0x%llx, but inter-CU reference handling is turned off.\n",
69052dc308f4271478a77415f6b71b7e1c96fe56e5athestig@chromium.org                  filename_.c_str(), offset, target);
69152dc308f4271478a77415f6b71b7e1c96fe56e5athestig@chromium.org}
69252dc308f4271478a77415f6b71b7e1c96fe56e5athestig@chromium.org
693057aa1f6173501e1a62cf91fd08275e7da439166jimblandyDwarfCUToModule::DwarfCUToModule(FileContext *file_context,
694248c84d2006fcde85b098066866aebec72b76125ted.mielczarek@gmail.com                                 LineToModuleHandler *line_reader,
695057aa1f6173501e1a62cf91fd08275e7da439166jimblandy                                 WarningReporter *reporter)
696b9d6ed468efaa4b65d42c4c5379fde15dcce14c5thestig@chromium.org    : line_reader_(line_reader),
697b9d6ed468efaa4b65d42c4c5379fde15dcce14c5thestig@chromium.org      cu_context_(new CUContext(file_context, reporter)),
698b9d6ed468efaa4b65d42c4c5379fde15dcce14c5thestig@chromium.org      child_context_(new DIEContext()),
699b9d6ed468efaa4b65d42c4c5379fde15dcce14c5thestig@chromium.org      has_source_line_info_(false) {
700057aa1f6173501e1a62cf91fd08275e7da439166jimblandy}
701057aa1f6173501e1a62cf91fd08275e7da439166jimblandy
702057aa1f6173501e1a62cf91fd08275e7da439166jimblandyDwarfCUToModule::~DwarfCUToModule() {
703057aa1f6173501e1a62cf91fd08275e7da439166jimblandy}
704057aa1f6173501e1a62cf91fd08275e7da439166jimblandy
705057aa1f6173501e1a62cf91fd08275e7da439166jimblandyvoid DwarfCUToModule::ProcessAttributeSigned(enum DwarfAttribute attr,
706057aa1f6173501e1a62cf91fd08275e7da439166jimblandy                                             enum DwarfForm form,
707057aa1f6173501e1a62cf91fd08275e7da439166jimblandy                                             int64 data) {
708057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  switch (attr) {
709057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    case dwarf2reader::DW_AT_language: // source language of this CU
710057aa1f6173501e1a62cf91fd08275e7da439166jimblandy      SetLanguage(static_cast<DwarfLanguage>(data));
711057aa1f6173501e1a62cf91fd08275e7da439166jimblandy      break;
712057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    default:
713057aa1f6173501e1a62cf91fd08275e7da439166jimblandy      break;
714057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  }
715057aa1f6173501e1a62cf91fd08275e7da439166jimblandy}
716057aa1f6173501e1a62cf91fd08275e7da439166jimblandy
717057aa1f6173501e1a62cf91fd08275e7da439166jimblandyvoid DwarfCUToModule::ProcessAttributeUnsigned(enum DwarfAttribute attr,
718057aa1f6173501e1a62cf91fd08275e7da439166jimblandy                                               enum DwarfForm form,
719057aa1f6173501e1a62cf91fd08275e7da439166jimblandy                                               uint64 data) {
720057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  switch (attr) {
721057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    case dwarf2reader::DW_AT_stmt_list: // Line number information.
722057aa1f6173501e1a62cf91fd08275e7da439166jimblandy      has_source_line_info_ = true;
723057aa1f6173501e1a62cf91fd08275e7da439166jimblandy      source_line_offset_ = data;
724057aa1f6173501e1a62cf91fd08275e7da439166jimblandy      break;
725057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    case dwarf2reader::DW_AT_language: // source language of this CU
726057aa1f6173501e1a62cf91fd08275e7da439166jimblandy      SetLanguage(static_cast<DwarfLanguage>(data));
727057aa1f6173501e1a62cf91fd08275e7da439166jimblandy      break;
728057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    default:
729057aa1f6173501e1a62cf91fd08275e7da439166jimblandy      break;
730057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  }
731057aa1f6173501e1a62cf91fd08275e7da439166jimblandy}
732057aa1f6173501e1a62cf91fd08275e7da439166jimblandy
733057aa1f6173501e1a62cf91fd08275e7da439166jimblandyvoid DwarfCUToModule::ProcessAttributeString(enum DwarfAttribute attr,
734057aa1f6173501e1a62cf91fd08275e7da439166jimblandy                                             enum DwarfForm form,
735057aa1f6173501e1a62cf91fd08275e7da439166jimblandy                                             const string &data) {
736248c84d2006fcde85b098066866aebec72b76125ted.mielczarek@gmail.com  switch (attr) {
737248c84d2006fcde85b098066866aebec72b76125ted.mielczarek@gmail.com    case dwarf2reader::DW_AT_name:
738248c84d2006fcde85b098066866aebec72b76125ted.mielczarek@gmail.com      cu_context_->reporter->SetCUName(data);
739248c84d2006fcde85b098066866aebec72b76125ted.mielczarek@gmail.com      break;
740248c84d2006fcde85b098066866aebec72b76125ted.mielczarek@gmail.com    case dwarf2reader::DW_AT_comp_dir:
741248c84d2006fcde85b098066866aebec72b76125ted.mielczarek@gmail.com      line_reader_->StartCompilationUnit(data);
742248c84d2006fcde85b098066866aebec72b76125ted.mielczarek@gmail.com      break;
743248c84d2006fcde85b098066866aebec72b76125ted.mielczarek@gmail.com    default:
744248c84d2006fcde85b098066866aebec72b76125ted.mielczarek@gmail.com      break;
745248c84d2006fcde85b098066866aebec72b76125ted.mielczarek@gmail.com  }
746057aa1f6173501e1a62cf91fd08275e7da439166jimblandy}
747057aa1f6173501e1a62cf91fd08275e7da439166jimblandy
748057aa1f6173501e1a62cf91fd08275e7da439166jimblandybool DwarfCUToModule::EndAttributes() {
749057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  return true;
750057aa1f6173501e1a62cf91fd08275e7da439166jimblandy}
751057aa1f6173501e1a62cf91fd08275e7da439166jimblandy
752057aa1f6173501e1a62cf91fd08275e7da439166jimblandydwarf2reader::DIEHandler *DwarfCUToModule::FindChildHandler(
753057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    uint64 offset,
7547c2350868e7f53728866d304bc6a7ce8ba3b5d05mark@chromium.org    enum DwarfTag tag) {
755057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  switch (tag) {
756057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    case dwarf2reader::DW_TAG_subprogram:
757b9d6ed468efaa4b65d42c4c5379fde15dcce14c5thestig@chromium.org      return new FuncHandler(cu_context_.get(), child_context_.get(), offset);
758057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    case dwarf2reader::DW_TAG_namespace:
759057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    case dwarf2reader::DW_TAG_class_type:
760057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    case dwarf2reader::DW_TAG_structure_type:
761057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    case dwarf2reader::DW_TAG_union_type:
762b9d6ed468efaa4b65d42c4c5379fde15dcce14c5thestig@chromium.org      return new NamedScopeHandler(cu_context_.get(), child_context_.get(),
763b9d6ed468efaa4b65d42c4c5379fde15dcce14c5thestig@chromium.org                                   offset);
764057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    default:
765057aa1f6173501e1a62cf91fd08275e7da439166jimblandy      return NULL;
766057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  }
767057aa1f6173501e1a62cf91fd08275e7da439166jimblandy}
768057aa1f6173501e1a62cf91fd08275e7da439166jimblandy
769057aa1f6173501e1a62cf91fd08275e7da439166jimblandyvoid DwarfCUToModule::SetLanguage(DwarfLanguage language) {
770057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  switch (language) {
771057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    case dwarf2reader::DW_LANG_Java:
772057aa1f6173501e1a62cf91fd08275e7da439166jimblandy      cu_context_->language = Language::Java;
773057aa1f6173501e1a62cf91fd08275e7da439166jimblandy      break;
774057aa1f6173501e1a62cf91fd08275e7da439166jimblandy
775057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    // DWARF has no generic language code for assembly language; this is
776057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    // what the GNU toolchain uses.
777057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    case dwarf2reader::DW_LANG_Mips_Assembler:
778057aa1f6173501e1a62cf91fd08275e7da439166jimblandy      cu_context_->language = Language::Assembler;
779057aa1f6173501e1a62cf91fd08275e7da439166jimblandy      break;
780057aa1f6173501e1a62cf91fd08275e7da439166jimblandy
781057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    // C++ covers so many cases that it probably has some way to cope
782057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    // with whatever the other languages throw at us. So make it the
783057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    // default.
784057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    //
785057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    // Objective C and Objective C++ seem to create entries for
786057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    // methods whose DW_AT_name values are already fully-qualified:
787057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    // "-[Classname method:]".  These appear at the top level.
78852dc308f4271478a77415f6b71b7e1c96fe56e5athestig@chromium.org    //
789057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    // DWARF data for C should never include namespaces or functions
790057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    // nested in struct types, but if it ever does, then C++'s
791057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    // notation is probably not a bad choice for that.
792057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    default:
793057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    case dwarf2reader::DW_LANG_ObjC:
794057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    case dwarf2reader::DW_LANG_ObjC_plus_plus:
795057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    case dwarf2reader::DW_LANG_C:
796057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    case dwarf2reader::DW_LANG_C89:
797057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    case dwarf2reader::DW_LANG_C99:
798057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    case dwarf2reader::DW_LANG_C_plus_plus:
799057aa1f6173501e1a62cf91fd08275e7da439166jimblandy      cu_context_->language = Language::CPlusPlus;
800057aa1f6173501e1a62cf91fd08275e7da439166jimblandy      break;
801057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  }
802057aa1f6173501e1a62cf91fd08275e7da439166jimblandy}
803057aa1f6173501e1a62cf91fd08275e7da439166jimblandy
804057aa1f6173501e1a62cf91fd08275e7da439166jimblandyvoid DwarfCUToModule::ReadSourceLines(uint64 offset) {
805057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  const dwarf2reader::SectionMap &section_map
80652dc308f4271478a77415f6b71b7e1c96fe56e5athestig@chromium.org      = cu_context_->file_context->section_map();
807057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  dwarf2reader::SectionMap::const_iterator map_entry
808057aa1f6173501e1a62cf91fd08275e7da439166jimblandy      = section_map.find(".debug_line");
809bd0a7f9da10909927dfe91c9f1010d03d07f3b7bted.mielczarek  // Mac OS X puts DWARF data in sections whose names begin with "__"
810bd0a7f9da10909927dfe91c9f1010d03d07f3b7bted.mielczarek  // instead of ".".
811bd0a7f9da10909927dfe91c9f1010d03d07f3b7bted.mielczarek  if (map_entry == section_map.end())
812bd0a7f9da10909927dfe91c9f1010d03d07f3b7bted.mielczarek    map_entry = section_map.find("__debug_line");
813057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  if (map_entry == section_map.end()) {
814057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    cu_context_->reporter->MissingSection(".debug_line");
815057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    return;
816057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  }
817057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  const char *section_start = map_entry->second.first;
818057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  uint64 section_length = map_entry->second.second;
819057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  if (offset >= section_length) {
820057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    cu_context_->reporter->BadLineInfoOffset(offset);
821057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    return;
822057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  }
823248c84d2006fcde85b098066866aebec72b76125ted.mielczarek@gmail.com  line_reader_->ReadProgram(section_start + offset, section_length - offset,
82452dc308f4271478a77415f6b71b7e1c96fe56e5athestig@chromium.org                            cu_context_->file_context->module_, &lines_);
825057aa1f6173501e1a62cf91fd08275e7da439166jimblandy}
826057aa1f6173501e1a62cf91fd08275e7da439166jimblandy
827057aa1f6173501e1a62cf91fd08275e7da439166jimblandynamespace {
828057aa1f6173501e1a62cf91fd08275e7da439166jimblandy// Return true if ADDRESS falls within the range of ITEM.
829057aa1f6173501e1a62cf91fd08275e7da439166jimblandytemplate <class T>
830057aa1f6173501e1a62cf91fd08275e7da439166jimblandyinline bool within(const T &item, Module::Address address) {
831057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  // Because Module::Address is unsigned, and unsigned arithmetic
832057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  // wraps around, this will be false if ADDRESS falls before the
833057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  // start of ITEM, or if it falls after ITEM's end.
8343e60d65111607f401461ff15981a463cde8f744ajimblandy  return address - item.address < item.size;
835057aa1f6173501e1a62cf91fd08275e7da439166jimblandy}
836057aa1f6173501e1a62cf91fd08275e7da439166jimblandy}
837057aa1f6173501e1a62cf91fd08275e7da439166jimblandy
838057aa1f6173501e1a62cf91fd08275e7da439166jimblandyvoid DwarfCUToModule::AssignLinesToFunctions() {
839057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  vector<Module::Function *> *functions = &cu_context_->functions;
840057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  WarningReporter *reporter = cu_context_->reporter;
841057aa1f6173501e1a62cf91fd08275e7da439166jimblandy
842057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  // This would be simpler if we assumed that source line entries
843057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  // don't cross function boundaries.  However, there's no real reason
844057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  // to assume that (say) a series of function definitions on the same
845057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  // line wouldn't get coalesced into one line number entry.  The
846057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  // DWARF spec certainly makes no such promises.
847057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  //
848057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  // So treat the functions and lines as peers, and take the trouble
849057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  // to compute their ranges' intersections precisely.  In any case,
850057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  // the hair here is a constant factor for performance; the
851057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  // complexity from here on out is linear.
852057aa1f6173501e1a62cf91fd08275e7da439166jimblandy
853057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  // Put both our functions and lines in order by address.
854f9ba50d41d6fe2fc3fa29fe8db547e418edc460ated.mielczarek@gmail.com  std::sort(functions->begin(), functions->end(),
855f9ba50d41d6fe2fc3fa29fe8db547e418edc460ated.mielczarek@gmail.com            Module::Function::CompareByAddress);
856f9ba50d41d6fe2fc3fa29fe8db547e418edc460ated.mielczarek@gmail.com  std::sort(lines_.begin(), lines_.end(), Module::Line::CompareByAddress);
857057aa1f6173501e1a62cf91fd08275e7da439166jimblandy
858057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  // The last line that we used any piece of.  We use this only for
859057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  // generating warnings.
860057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  const Module::Line *last_line_used = NULL;
861057aa1f6173501e1a62cf91fd08275e7da439166jimblandy
862057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  // The last function and line we warned about --- so we can avoid
863057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  // doing so more than once.
864057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  const Module::Function *last_function_cited = NULL;
865057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  const Module::Line *last_line_cited = NULL;
866057aa1f6173501e1a62cf91fd08275e7da439166jimblandy
867057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  // Make a single pass through both vectors from lower to higher
8683e60d65111607f401461ff15981a463cde8f744ajimblandy  // addresses, populating each Function's lines vector with lines
869057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  // from our lines_ vector that fall within the function's address
870057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  // range.
871057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  vector<Module::Function *>::iterator func_it = functions->begin();
872057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  vector<Module::Line>::const_iterator line_it = lines_.begin();
873057aa1f6173501e1a62cf91fd08275e7da439166jimblandy
874057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  Module::Address current;
875057aa1f6173501e1a62cf91fd08275e7da439166jimblandy
876057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  // Pointers to the referents of func_it and line_it, or NULL if the
877057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  // iterator is at the end of the sequence.
878057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  Module::Function *func;
879057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  const Module::Line *line;
880057aa1f6173501e1a62cf91fd08275e7da439166jimblandy
881057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  // Start current at the beginning of the first line or function,
882057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  // whichever is earlier.
883057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  if (func_it != functions->end() && line_it != lines_.end()) {
884057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    func = *func_it;
885057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    line = &*line_it;
8863e60d65111607f401461ff15981a463cde8f744ajimblandy    current = std::min(func->address, line->address);
887057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  } else if (line_it != lines_.end()) {
888057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    func = NULL;
889057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    line = &*line_it;
8903e60d65111607f401461ff15981a463cde8f744ajimblandy    current = line->address;
891057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  } else if (func_it != functions->end()) {
892057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    func = *func_it;
893057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    line = NULL;
8943e60d65111607f401461ff15981a463cde8f744ajimblandy    current = (*func_it)->address;
895057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  } else {
896057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    return;
897057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  }
898057aa1f6173501e1a62cf91fd08275e7da439166jimblandy
899057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  while (func || line) {
900057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    // This loop has two invariants that hold at the top.
901057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    //
902057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    // First, at least one of the iterators is not at the end of its
903057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    // sequence, and those that are not refer to the earliest
904057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    // function or line that contains or starts after CURRENT.
905057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    //
906057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    // Note that every byte is in one of four states: it is covered
907057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    // or not covered by a function, and, independently, it is
908057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    // covered or not covered by a line.
909057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    //
910057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    // The second invariant is that CURRENT refers to a byte whose
911057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    // state is different from its predecessor, or it refers to the
912057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    // first byte in the address space. In other words, CURRENT is
913057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    // always the address of a transition.
914057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    //
915057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    // Note that, although each iteration advances CURRENT from one
916057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    // transition address to the next in each iteration, it might
917057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    // not advance the iterators. Suppose we have a function that
918057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    // starts with a line, has a gap, and then a second line, and
919057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    // suppose that we enter an iteration with CURRENT at the end of
920057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    // the first line. The next transition address is the start of
921057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    // the second line, after the gap, so the iteration should
922057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    // advance CURRENT to that point. At the head of that iteration,
923057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    // the invariants require that the line iterator be pointing at
924057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    // the second line. But this is also true at the head of the
925057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    // next. And clearly, the iteration must not change the function
926057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    // iterator. So neither iterator moves.
927057aa1f6173501e1a62cf91fd08275e7da439166jimblandy
928057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    // Assert the first invariant (see above).
9293e60d65111607f401461ff15981a463cde8f744ajimblandy    assert(!func || current < func->address || within(*func, current));
9303e60d65111607f401461ff15981a463cde8f744ajimblandy    assert(!line || current < line->address || within(*line, current));
931057aa1f6173501e1a62cf91fd08275e7da439166jimblandy
932057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    // The next transition after CURRENT.
933057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    Module::Address next_transition;
934057aa1f6173501e1a62cf91fd08275e7da439166jimblandy
935057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    // Figure out which state we're in, add lines or warn, and compute
936057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    // the next transition address.
9373e60d65111607f401461ff15981a463cde8f744ajimblandy    if (func && current >= func->address) {
9383e60d65111607f401461ff15981a463cde8f744ajimblandy      if (line && current >= line->address) {
939057aa1f6173501e1a62cf91fd08275e7da439166jimblandy        // Covered by both a line and a function.
9403e60d65111607f401461ff15981a463cde8f744ajimblandy        Module::Address func_left = func->size - (current - func->address);
9413e60d65111607f401461ff15981a463cde8f744ajimblandy        Module::Address line_left = line->size - (current - line->address);
942057aa1f6173501e1a62cf91fd08275e7da439166jimblandy        // This may overflow, but things work out.
943057aa1f6173501e1a62cf91fd08275e7da439166jimblandy        next_transition = current + std::min(func_left, line_left);
944057aa1f6173501e1a62cf91fd08275e7da439166jimblandy        Module::Line l = *line;
9453e60d65111607f401461ff15981a463cde8f744ajimblandy        l.address = current;
9463e60d65111607f401461ff15981a463cde8f744ajimblandy        l.size = next_transition - current;
9473e60d65111607f401461ff15981a463cde8f744ajimblandy        func->lines.push_back(l);
948057aa1f6173501e1a62cf91fd08275e7da439166jimblandy        last_line_used = line;
949057aa1f6173501e1a62cf91fd08275e7da439166jimblandy      } else {
950057aa1f6173501e1a62cf91fd08275e7da439166jimblandy        // Covered by a function, but no line.
951057aa1f6173501e1a62cf91fd08275e7da439166jimblandy        if (func != last_function_cited) {
952057aa1f6173501e1a62cf91fd08275e7da439166jimblandy          reporter->UncoveredFunction(*func);
953057aa1f6173501e1a62cf91fd08275e7da439166jimblandy          last_function_cited = func;
954057aa1f6173501e1a62cf91fd08275e7da439166jimblandy        }
9553e60d65111607f401461ff15981a463cde8f744ajimblandy        if (line && within(*func, line->address))
9563e60d65111607f401461ff15981a463cde8f744ajimblandy          next_transition = line->address;
957057aa1f6173501e1a62cf91fd08275e7da439166jimblandy        else
958057aa1f6173501e1a62cf91fd08275e7da439166jimblandy          // If this overflows, we'll catch it below.
9593e60d65111607f401461ff15981a463cde8f744ajimblandy          next_transition = func->address + func->size;
960057aa1f6173501e1a62cf91fd08275e7da439166jimblandy      }
961057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    } else {
9623e60d65111607f401461ff15981a463cde8f744ajimblandy      if (line && current >= line->address) {
963057aa1f6173501e1a62cf91fd08275e7da439166jimblandy        // Covered by a line, but no function.
964057aa1f6173501e1a62cf91fd08275e7da439166jimblandy        //
965057aa1f6173501e1a62cf91fd08275e7da439166jimblandy        // If GCC emits padding after one function to align the start
966057aa1f6173501e1a62cf91fd08275e7da439166jimblandy        // of the next, then it will attribute the padding
967057aa1f6173501e1a62cf91fd08275e7da439166jimblandy        // instructions to the last source line of function (to reduce
968057aa1f6173501e1a62cf91fd08275e7da439166jimblandy        // the size of the line number info), but omit it from the
969057aa1f6173501e1a62cf91fd08275e7da439166jimblandy        // DW_AT_{low,high}_pc range given in .debug_info (since it
970057aa1f6173501e1a62cf91fd08275e7da439166jimblandy        // costs nothing to be precise there). If we did use at least
971057aa1f6173501e1a62cf91fd08275e7da439166jimblandy        // some of the line we're about to skip, and it ends at the
972057aa1f6173501e1a62cf91fd08275e7da439166jimblandy        // start of the next function, then assume this is what
973057aa1f6173501e1a62cf91fd08275e7da439166jimblandy        // happened, and don't warn.
974057aa1f6173501e1a62cf91fd08275e7da439166jimblandy        if (line != last_line_cited
975057aa1f6173501e1a62cf91fd08275e7da439166jimblandy            && !(func
976057aa1f6173501e1a62cf91fd08275e7da439166jimblandy                 && line == last_line_used
9773e60d65111607f401461ff15981a463cde8f744ajimblandy                 && func->address - line->address == line->size)) {
978057aa1f6173501e1a62cf91fd08275e7da439166jimblandy          reporter->UncoveredLine(*line);
979057aa1f6173501e1a62cf91fd08275e7da439166jimblandy          last_line_cited = line;
980057aa1f6173501e1a62cf91fd08275e7da439166jimblandy        }
9813e60d65111607f401461ff15981a463cde8f744ajimblandy        if (func && within(*line, func->address))
9823e60d65111607f401461ff15981a463cde8f744ajimblandy          next_transition = func->address;
983057aa1f6173501e1a62cf91fd08275e7da439166jimblandy        else
984057aa1f6173501e1a62cf91fd08275e7da439166jimblandy          // If this overflows, we'll catch it below.
9853e60d65111607f401461ff15981a463cde8f744ajimblandy          next_transition = line->address + line->size;
986057aa1f6173501e1a62cf91fd08275e7da439166jimblandy      } else {
987057aa1f6173501e1a62cf91fd08275e7da439166jimblandy        // Covered by neither a function nor a line. By the invariant,
988057aa1f6173501e1a62cf91fd08275e7da439166jimblandy        // both func and line begin after CURRENT. The next transition
989057aa1f6173501e1a62cf91fd08275e7da439166jimblandy        // is the start of the next function or next line, whichever
990057aa1f6173501e1a62cf91fd08275e7da439166jimblandy        // is earliest.
99152dc308f4271478a77415f6b71b7e1c96fe56e5athestig@chromium.org        assert(func || line);
992057aa1f6173501e1a62cf91fd08275e7da439166jimblandy        if (func && line)
9933e60d65111607f401461ff15981a463cde8f744ajimblandy          next_transition = std::min(func->address, line->address);
994057aa1f6173501e1a62cf91fd08275e7da439166jimblandy        else if (func)
9953e60d65111607f401461ff15981a463cde8f744ajimblandy          next_transition = func->address;
996057aa1f6173501e1a62cf91fd08275e7da439166jimblandy        else
9973e60d65111607f401461ff15981a463cde8f744ajimblandy          next_transition = line->address;
998057aa1f6173501e1a62cf91fd08275e7da439166jimblandy      }
999057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    }
1000057aa1f6173501e1a62cf91fd08275e7da439166jimblandy
1001057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    // If a function or line abuts the end of the address space, then
1002057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    // next_transition may end up being zero, in which case we've completed
1003057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    // our pass. Handle that here, instead of trying to deal with it in
1004057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    // each place we compute next_transition.
1005057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    if (!next_transition)
1006057aa1f6173501e1a62cf91fd08275e7da439166jimblandy      break;
1007057aa1f6173501e1a62cf91fd08275e7da439166jimblandy
1008057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    // Advance iterators as needed. If lines overlap or functions overlap,
1009057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    // then we could go around more than once. We don't worry too much
1010057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    // about what result we produce in that case, just as long as we don't
1011057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    // hang or crash.
1012057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    while (func_it != functions->end()
1013916a34a98293fd0d96f909a7c450a938d14361cethestig@chromium.org           && next_transition >= (*func_it)->address
1014057aa1f6173501e1a62cf91fd08275e7da439166jimblandy           && !within(**func_it, next_transition))
1015057aa1f6173501e1a62cf91fd08275e7da439166jimblandy      func_it++;
1016057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    func = (func_it != functions->end()) ? *func_it : NULL;
1017057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    while (line_it != lines_.end()
1018916a34a98293fd0d96f909a7c450a938d14361cethestig@chromium.org           && next_transition >= line_it->address
1019057aa1f6173501e1a62cf91fd08275e7da439166jimblandy           && !within(*line_it, next_transition))
1020057aa1f6173501e1a62cf91fd08275e7da439166jimblandy      line_it++;
1021057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    line = (line_it != lines_.end()) ? &*line_it : NULL;
1022057aa1f6173501e1a62cf91fd08275e7da439166jimblandy
1023057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    // We must make progress.
1024057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    assert(next_transition > current);
1025057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    current = next_transition;
1026057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  }
1027057aa1f6173501e1a62cf91fd08275e7da439166jimblandy}
1028057aa1f6173501e1a62cf91fd08275e7da439166jimblandy
1029057aa1f6173501e1a62cf91fd08275e7da439166jimblandyvoid DwarfCUToModule::Finish() {
1030057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  // Assembly language files have no function data, and that gives us
1031057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  // no place to store our line numbers (even though the GNU toolchain
1032057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  // will happily produce source line info for assembly language
1033057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  // files).  To avoid spurious warnings about lines we can't assign
1034057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  // to functions, skip CUs in languages that lack functions.
1035057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  if (!cu_context_->language->HasFunctions())
1036057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    return;
1037057aa1f6173501e1a62cf91fd08275e7da439166jimblandy
1038057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  // Read source line info, if we have any.
1039057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  if (has_source_line_info_)
1040057aa1f6173501e1a62cf91fd08275e7da439166jimblandy    ReadSourceLines(source_line_offset_);
1041057aa1f6173501e1a62cf91fd08275e7da439166jimblandy
1042057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  vector<Module::Function *> *functions = &cu_context_->functions;
1043057aa1f6173501e1a62cf91fd08275e7da439166jimblandy
1044057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  // Dole out lines to the appropriate functions.
1045057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  AssignLinesToFunctions();
1046057aa1f6173501e1a62cf91fd08275e7da439166jimblandy
1047057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  // Add our functions, which now have source lines assigned to them,
1048057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  // to module_.
104952dc308f4271478a77415f6b71b7e1c96fe56e5athestig@chromium.org  cu_context_->file_context->module_->AddFunctions(functions->begin(),
105052dc308f4271478a77415f6b71b7e1c96fe56e5athestig@chromium.org                                                   functions->end());
1051057aa1f6173501e1a62cf91fd08275e7da439166jimblandy
1052057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  // Ownership of the function objects has shifted from cu_context to
1053057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  // the Module.
1054057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  functions->clear();
105552dc308f4271478a77415f6b71b7e1c96fe56e5athestig@chromium.org
105652dc308f4271478a77415f6b71b7e1c96fe56e5athestig@chromium.org  cu_context_->file_context->ClearSpecifications();
1057057aa1f6173501e1a62cf91fd08275e7da439166jimblandy}
1058057aa1f6173501e1a62cf91fd08275e7da439166jimblandy
1059057aa1f6173501e1a62cf91fd08275e7da439166jimblandybool DwarfCUToModule::StartCompilationUnit(uint64 offset,
1060057aa1f6173501e1a62cf91fd08275e7da439166jimblandy                                           uint8 address_size,
1061057aa1f6173501e1a62cf91fd08275e7da439166jimblandy                                           uint8 offset_size,
1062057aa1f6173501e1a62cf91fd08275e7da439166jimblandy                                           uint64 cu_length,
1063057aa1f6173501e1a62cf91fd08275e7da439166jimblandy                                           uint8 dwarf_version) {
1064057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  return dwarf_version >= 2;
1065057aa1f6173501e1a62cf91fd08275e7da439166jimblandy}
1066057aa1f6173501e1a62cf91fd08275e7da439166jimblandy
10677c2350868e7f53728866d304bc6a7ce8ba3b5d05mark@chromium.orgbool DwarfCUToModule::StartRootDIE(uint64 offset, enum DwarfTag tag) {
1068057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  // We don't deal with partial compilation units (the only other tag
1069057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  // likely to be used for root DIE).
1070057aa1f6173501e1a62cf91fd08275e7da439166jimblandy  return tag == dwarf2reader::DW_TAG_compile_unit;
1071057aa1f6173501e1a62cf91fd08275e7da439166jimblandy}
1072057aa1f6173501e1a62cf91fd08275e7da439166jimblandy
1073057aa1f6173501e1a62cf91fd08275e7da439166jimblandy} // namespace google_breakpad
1074