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 §ion_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