1
// Copyright (c) 2010 Google Inc.
2
// All rights reserved.
4
// Redistribution and use in source and binary forms, with or without
5
// modification, are permitted provided that the following conditions are
8
// * Redistributions of source code must retain the above copyright
9
// notice, this list of conditions and the following disclaimer.
10
// * Redistributions in binary form must reproduce the above
11
// copyright notice, this list of conditions and the following disclaimer
12
// in the documentation and/or other materials provided with the
14
// * Neither the name of Google Inc. nor the names of its
15
// contributors may be used to endorse or promote products derived from
16
// this software without specific prior written permission.
18
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
32
// Implement the DwarfCUToModule class; see dwarf_cu_to_module.h.
34
// For <inttypes.h> PRI* macros, before anything else might #include it.
35
#ifndef __STDC_FORMAT_MACROS
36
#define __STDC_FORMAT_MACROS
37
#endif /* __STDC_FORMAT_MACROS */
39
#include "common/dwarf_cu_to_module.h"
49
#include "common/dwarf_line_to_module.h"
51
namespace google_breakpad {
58
// Data provided by a DWARF specification DIE.
60
// In DWARF, the DIE for a definition may contain a DW_AT_specification
61
// attribute giving the offset of the corresponding declaration DIE, and
62
// the definition DIE may omit information given in the declaration. For
63
// example, it's common for a function's address range to appear only in
64
// its definition DIE, but its name to appear only in its declaration
67
// The dumper needs to be able to follow DW_AT_specification links to
68
// bring all this information together in a FUNC record. Conveniently,
69
// DIEs that are the target of such links have a DW_AT_declaration flag
70
// set, so we can identify them when we first see them, and record their
71
// contents for later reference.
73
// A Specification holds information gathered from a declaration DIE that
74
// we may need if we find a DW_AT_specification link pointing to it.
75
struct DwarfCUToModule::Specification {
76
// The name of the enclosing scope, or the empty string if there is none.
77
string enclosing_name;
79
// The name for the specification DIE itself, without any enclosing
81
string unqualified_name;
84
// An abstract origin -- base definition of an inline function.
85
struct AbstractOrigin {
86
AbstractOrigin() : name() {}
87
AbstractOrigin(const string& name) : name(name) {}
92
typedef map<uint64, AbstractOrigin> AbstractOriginByOffset;
94
// Data global to the DWARF-bearing file that is private to the
95
// DWARF-to-Module process.
96
struct DwarfCUToModule::FilePrivate {
97
// A set of strings used in this CU. Before storing a string in one of
98
// our data structures, insert it into this set, and then use the string
101
// Because std::string uses reference counting internally, simply using
102
// strings from this set, even if passed by value, assigned, or held
103
// directly in structures and containers (map<string, ...>, for example),
104
// causes those strings to share a single instance of each distinct piece
106
set<string> common_strings;
108
// A map from offsets of DIEs within the .debug_info section to
109
// Specifications describing those DIEs. Specification references can
110
// cross compilation unit boundaries.
111
SpecificationByOffset specifications;
113
AbstractOriginByOffset origins;
116
DwarfCUToModule::FileContext::FileContext(const string &filename_arg,
118
: filename(filename_arg), module(module_arg) {
119
file_private = new FilePrivate();
122
DwarfCUToModule::FileContext::~FileContext() {
126
// Information global to the particular compilation unit we're
127
// parsing. This is for data shared across the CU's entire DIE tree,
128
// and parameters from the code invoking the CU parser.
129
struct DwarfCUToModule::CUContext {
130
CUContext(FileContext *file_context_arg, WarningReporter *reporter_arg)
131
: file_context(file_context_arg),
132
reporter(reporter_arg),
133
language(Language::CPlusPlus) { }
135
for (vector<Module::Function *>::iterator it = functions.begin();
136
it != functions.end(); it++)
140
// The DWARF-bearing file into which this CU was incorporated.
141
FileContext *file_context;
143
// For printing error messages.
144
WarningReporter *reporter;
146
// The source language of this compilation unit.
147
const Language *language;
149
// The functions defined in this compilation unit. We accumulate
150
// them here during parsing. Then, in DwarfCUToModule::Finish, we
151
// assign them lines and add them to file_context->module.
153
// Destroying this destroys all the functions this vector points to.
154
vector<Module::Function *> functions;
157
// Information about the context of a particular DIE. This is for
158
// information that changes as we descend the tree towards the leaves:
159
// the containing classes/namespaces, etc.
160
struct DwarfCUToModule::DIEContext {
161
// The fully-qualified name of the context. For example, for a
164
// DW_TAG_namespace Foo
166
// DW_TAG_subprogram Baz
168
// in a C++ compilation unit, the DIEContext's name for the
169
// DW_TAG_subprogram DIE would be "Foo::Bar". The DIEContext's
170
// name for the DW_TAG_namespace DIE would be "".
174
// An abstract base class for all the dumper's DIE handlers.
175
class DwarfCUToModule::GenericDIEHandler: public dwarf2reader::DIEHandler {
177
// Create a handler for the DIE at OFFSET whose compilation unit is
178
// described by CU_CONTEXT, and whose immediate context is described
179
// by PARENT_CONTEXT.
180
GenericDIEHandler(CUContext *cu_context, DIEContext *parent_context,
182
: cu_context_(cu_context),
183
parent_context_(parent_context),
186
specification_(NULL) { }
188
// Derived classes' ProcessAttributeUnsigned can defer to this to
189
// handle DW_AT_declaration, or simply not override it.
190
void ProcessAttributeUnsigned(enum DwarfAttribute attr,
194
// Derived classes' ProcessAttributeReference can defer to this to
195
// handle DW_AT_specification, or simply not override it.
196
void ProcessAttributeReference(enum DwarfAttribute attr,
200
// Derived classes' ProcessAttributeReference can defer to this to
201
// handle DW_AT_specification, or simply not override it.
202
void ProcessAttributeString(enum DwarfAttribute attr,
207
// Compute and return the fully-qualified name of the DIE. If this
208
// DIE is a declaration DIE, to be cited by other DIEs'
209
// DW_AT_specification attributes, record its enclosing name and
210
// unqualified name in the specification table.
212
// Use this from EndAttributes member functions, not ProcessAttribute*
213
// functions; only the former can be sure that all the DIE's attributes
215
string ComputeQualifiedName();
217
CUContext *cu_context_;
218
DIEContext *parent_context_;
221
// If this DIE has a DW_AT_declaration attribute, this is its value.
222
// It is false on DIEs with no DW_AT_declaration attribute.
225
// If this DIE has a DW_AT_specification attribute, this is the
226
// Specification structure for the DIE the attribute refers to.
227
// Otherwise, this is NULL.
228
Specification *specification_;
230
// The value of the DW_AT_name attribute, or the empty string if the
231
// DIE has no such attribute.
232
string name_attribute_;
235
void DwarfCUToModule::GenericDIEHandler::ProcessAttributeUnsigned(
236
enum DwarfAttribute attr,
240
case dwarf2reader::DW_AT_declaration: declaration_ = (data != 0); break;
245
void DwarfCUToModule::GenericDIEHandler::ProcessAttributeReference(
246
enum DwarfAttribute attr,
250
case dwarf2reader::DW_AT_specification: {
251
// Find the Specification to which this attribute refers, and
252
// set specification_ appropriately. We could do more processing
253
// here, but it's better to leave the real work to our
254
// EndAttribute member function, at which point we know we have
255
// seen all the DIE's attributes.
256
FileContext *file_context = cu_context_->file_context;
257
SpecificationByOffset *specifications
258
= &file_context->file_private->specifications;
259
SpecificationByOffset::iterator spec = specifications->find(data);
260
if (spec != specifications->end()) {
261
specification_ = &spec->second;
263
// Technically, there's no reason a DW_AT_specification
264
// couldn't be a forward reference, but supporting that would
265
// be a lot of work (changing to a two-pass structure), and I
266
// don't think any producers we care about ever emit such
268
cu_context_->reporter->UnknownSpecification(offset_, data);
276
void DwarfCUToModule::GenericDIEHandler::ProcessAttributeString(
277
enum DwarfAttribute attr,
279
const string &data) {
281
case dwarf2reader::DW_AT_name: {
282
// Place the name in our global set of strings, and then use the
283
// string from the set. Even though the assignment looks like a copy,
284
// all the major std::string implementations use reference counting
285
// internally, so the effect is to have all our data structures share
286
// copies of strings whenever possible.
287
pair<set<string>::iterator, bool> result =
288
cu_context_->file_context->file_private->common_strings.insert(data);
289
name_attribute_ = *result.first;
296
string DwarfCUToModule::GenericDIEHandler::ComputeQualifiedName() {
297
// Find our unqualified name. If the DIE has its own DW_AT_name
298
// attribute, then use that; otherwise, check our specification.
299
const string *unqualified_name;
300
if (name_attribute_.empty() && specification_)
301
unqualified_name = &specification_->unqualified_name;
303
unqualified_name = &name_attribute_;
305
// Find the name of our enclosing context. If we have a
306
// specification, it's the specification's enclosing context that
307
// counts; otherwise, use this DIE's context.
308
const string *enclosing_name;
310
enclosing_name = &specification_->enclosing_name;
312
enclosing_name = &parent_context_->name;
314
// If this DIE was marked as a declaration, record its names in the
315
// specification table.
317
FileContext *file_context = cu_context_->file_context;
319
spec.enclosing_name = *enclosing_name;
320
spec.unqualified_name = *unqualified_name;
321
file_context->file_private->specifications[offset_] = spec;
324
// Combine the enclosing name and unqualified name to produce our
325
// own fully-qualified name.
326
return cu_context_->language->MakeQualifiedName(*enclosing_name,
330
// A handler class for DW_TAG_subprogram DIEs.
331
class DwarfCUToModule::FuncHandler: public GenericDIEHandler {
333
FuncHandler(CUContext *cu_context, DIEContext *parent_context,
335
: GenericDIEHandler(cu_context, parent_context, offset),
336
low_pc_(0), high_pc_(0), abstract_origin_(NULL), inline_(false) { }
337
void ProcessAttributeUnsigned(enum DwarfAttribute attr,
340
void ProcessAttributeSigned(enum DwarfAttribute attr,
343
void ProcessAttributeReference(enum DwarfAttribute attr,
347
bool EndAttributes();
351
// The fully-qualified name, as derived from name_attribute_,
352
// specification_, parent_context_. Computed in EndAttributes.
354
uint64 low_pc_, high_pc_; // DW_AT_low_pc, DW_AT_high_pc
355
const AbstractOrigin* abstract_origin_;
359
void DwarfCUToModule::FuncHandler::ProcessAttributeUnsigned(
360
enum DwarfAttribute attr,
364
// If this attribute is present at all --- even if its value is
365
// DW_INL_not_inlined --- then GCC may cite it as someone else's
366
// DW_AT_abstract_origin attribute.
367
case dwarf2reader::DW_AT_inline: inline_ = true; break;
369
case dwarf2reader::DW_AT_low_pc: low_pc_ = data; break;
370
case dwarf2reader::DW_AT_high_pc: high_pc_ = data; break;
372
GenericDIEHandler::ProcessAttributeUnsigned(attr, form, data);
377
void DwarfCUToModule::FuncHandler::ProcessAttributeSigned(
378
enum DwarfAttribute attr,
382
// If this attribute is present at all --- even if its value is
383
// DW_INL_not_inlined --- then GCC may cite it as someone else's
384
// DW_AT_abstract_origin attribute.
385
case dwarf2reader::DW_AT_inline: inline_ = true; break;
392
void DwarfCUToModule::FuncHandler::ProcessAttributeReference(
393
enum DwarfAttribute attr,
397
case dwarf2reader::DW_AT_abstract_origin: {
398
const AbstractOriginByOffset& origins =
399
cu_context_->file_context->file_private->origins;
400
AbstractOriginByOffset::const_iterator origin = origins.find(data);
401
if (origin != origins.end()) {
402
abstract_origin_ = &(origin->second);
404
cu_context_->reporter->UnknownAbstractOrigin(offset_, data);
409
GenericDIEHandler::ProcessAttributeReference(attr, form, data);
414
bool DwarfCUToModule::FuncHandler::EndAttributes() {
415
// Compute our name, and record a specification, if appropriate.
416
name_ = ComputeQualifiedName();
417
if (name_.empty() && abstract_origin_) {
418
name_ = abstract_origin_->name;
423
void DwarfCUToModule::FuncHandler::Finish() {
424
// Did we collect the information we need? Not all DWARF function
425
// entries have low and high addresses (for example, inlined
426
// functions that were never used), but all the ones we're
427
// interested in cover a non-empty range of bytes.
428
if (low_pc_ < high_pc_) {
429
// Create a Module::Function based on the data we've gathered, and
430
// add it to the functions_ list.
431
Module::Function *func = new Module::Function;
432
// Malformed DWARF may omit the name, but all Module::Functions must
434
if (!name_.empty()) {
437
cu_context_->reporter->UnnamedFunction(offset_);
438
func->name = "<name omitted>";
440
func->address = low_pc_;
441
func->size = high_pc_ - low_pc_;
442
func->parameter_size = 0;
444
// If the function address is zero this is a sign that this function
445
// description is just empty debug data and should just be discarded.
446
cu_context_->functions.push_back(func);
448
} else if (inline_) {
449
AbstractOrigin origin(name_);
450
cu_context_->file_context->file_private->origins[offset_] = origin;
454
// A handler for DIEs that contain functions and contribute a
455
// component to their names: namespaces, classes, etc.
456
class DwarfCUToModule::NamedScopeHandler: public GenericDIEHandler {
458
NamedScopeHandler(CUContext *cu_context, DIEContext *parent_context,
460
: GenericDIEHandler(cu_context, parent_context, offset) { }
461
bool EndAttributes();
462
DIEHandler *FindChildHandler(uint64 offset, enum DwarfTag tag,
463
const AttributeList &attrs);
466
DIEContext child_context_; // A context for our children.
469
bool DwarfCUToModule::NamedScopeHandler::EndAttributes() {
470
child_context_.name = ComputeQualifiedName();
474
dwarf2reader::DIEHandler *DwarfCUToModule::NamedScopeHandler::FindChildHandler(
477
const AttributeList &attrs) {
479
case dwarf2reader::DW_TAG_subprogram:
480
return new FuncHandler(cu_context_, &child_context_, offset);
481
case dwarf2reader::DW_TAG_namespace:
482
case dwarf2reader::DW_TAG_class_type:
483
case dwarf2reader::DW_TAG_structure_type:
484
case dwarf2reader::DW_TAG_union_type:
485
return new NamedScopeHandler(cu_context_, &child_context_, offset);
491
void DwarfCUToModule::WarningReporter::CUHeading() {
492
if (printed_cu_header_)
494
fprintf(stderr, "%s: in compilation unit '%s' (offset 0x%llx):\n",
495
filename_.c_str(), cu_name_.c_str(), cu_offset_);
496
printed_cu_header_ = true;
499
void DwarfCUToModule::WarningReporter::UnknownSpecification(uint64 offset,
502
fprintf(stderr, "%s: the DIE at offset 0x%llx has a DW_AT_specification"
503
" attribute referring to the die at offset 0x%llx, which either"
504
" was not marked as a declaration, or comes later in the file\n",
505
filename_.c_str(), offset, target);
508
void DwarfCUToModule::WarningReporter::UnknownAbstractOrigin(uint64 offset,
511
fprintf(stderr, "%s: the DIE at offset 0x%llx has a DW_AT_abstract_origin"
512
" attribute referring to the die at offset 0x%llx, which either"
513
" was not marked as an inline, or comes later in the file\n",
514
filename_.c_str(), offset, target);
517
void DwarfCUToModule::WarningReporter::MissingSection(const string &name) {
519
fprintf(stderr, "%s: warning: couldn't find DWARF '%s' section\n",
520
filename_.c_str(), name.c_str());
523
void DwarfCUToModule::WarningReporter::BadLineInfoOffset(uint64 offset) {
525
fprintf(stderr, "%s: warning: line number data offset beyond end"
526
" of '.debug_line' section\n",
530
void DwarfCUToModule::WarningReporter::UncoveredHeading() {
531
if (printed_unpaired_header_)
534
fprintf(stderr, "%s: warning: skipping unpaired lines/functions:\n",
536
printed_unpaired_header_ = true;
539
void DwarfCUToModule::WarningReporter::UncoveredFunction(
540
const Module::Function &function) {
541
if (!uncovered_warnings_enabled_)
544
fprintf(stderr, " function%s: %s\n",
545
function.size == 0 ? " (zero-length)" : "",
546
function.name.c_str());
549
void DwarfCUToModule::WarningReporter::UncoveredLine(const Module::Line &line) {
550
if (!uncovered_warnings_enabled_)
553
fprintf(stderr, " line%s: %s:%d at 0x%" PRIx64 "\n",
554
(line.size == 0 ? " (zero-length)" : ""),
555
line.file->name.c_str(), line.number, line.address);
558
void DwarfCUToModule::WarningReporter::UnnamedFunction(uint64 offset) {
560
fprintf(stderr, "%s: warning: function at offset 0x%llx has no name\n",
561
filename_.c_str(), offset);
564
DwarfCUToModule::DwarfCUToModule(FileContext *file_context,
565
LineToModuleFunctor *line_reader,
566
WarningReporter *reporter)
567
: line_reader_(line_reader), has_source_line_info_(false) {
568
cu_context_ = new CUContext(file_context, reporter);
569
child_context_ = new DIEContext();
572
DwarfCUToModule::~DwarfCUToModule() {
574
delete child_context_;
577
void DwarfCUToModule::ProcessAttributeSigned(enum DwarfAttribute attr,
581
case dwarf2reader::DW_AT_language: // source language of this CU
582
SetLanguage(static_cast<DwarfLanguage>(data));
589
void DwarfCUToModule::ProcessAttributeUnsigned(enum DwarfAttribute attr,
593
case dwarf2reader::DW_AT_stmt_list: // Line number information.
594
has_source_line_info_ = true;
595
source_line_offset_ = data;
597
case dwarf2reader::DW_AT_language: // source language of this CU
598
SetLanguage(static_cast<DwarfLanguage>(data));
605
void DwarfCUToModule::ProcessAttributeString(enum DwarfAttribute attr,
607
const string &data) {
608
if (attr == dwarf2reader::DW_AT_name)
609
cu_context_->reporter->SetCUName(data);
612
bool DwarfCUToModule::EndAttributes() {
616
dwarf2reader::DIEHandler *DwarfCUToModule::FindChildHandler(
619
const AttributeList &attrs) {
621
case dwarf2reader::DW_TAG_subprogram:
622
return new FuncHandler(cu_context_, child_context_, offset);
623
case dwarf2reader::DW_TAG_namespace:
624
case dwarf2reader::DW_TAG_class_type:
625
case dwarf2reader::DW_TAG_structure_type:
626
case dwarf2reader::DW_TAG_union_type:
627
return new NamedScopeHandler(cu_context_, child_context_, offset);
633
void DwarfCUToModule::SetLanguage(DwarfLanguage language) {
635
case dwarf2reader::DW_LANG_Java:
636
cu_context_->language = Language::Java;
639
// DWARF has no generic language code for assembly language; this is
640
// what the GNU toolchain uses.
641
case dwarf2reader::DW_LANG_Mips_Assembler:
642
cu_context_->language = Language::Assembler;
645
// C++ covers so many cases that it probably has some way to cope
646
// with whatever the other languages throw at us. So make it the
649
// Objective C and Objective C++ seem to create entries for
650
// methods whose DW_AT_name values are already fully-qualified:
651
// "-[Classname method:]". These appear at the top level.
653
// DWARF data for C should never include namespaces or functions
654
// nested in struct types, but if it ever does, then C++'s
655
// notation is probably not a bad choice for that.
657
case dwarf2reader::DW_LANG_ObjC:
658
case dwarf2reader::DW_LANG_ObjC_plus_plus:
659
case dwarf2reader::DW_LANG_C:
660
case dwarf2reader::DW_LANG_C89:
661
case dwarf2reader::DW_LANG_C99:
662
case dwarf2reader::DW_LANG_C_plus_plus:
663
cu_context_->language = Language::CPlusPlus;
668
void DwarfCUToModule::ReadSourceLines(uint64 offset) {
669
const dwarf2reader::SectionMap §ion_map
670
= cu_context_->file_context->section_map;
671
dwarf2reader::SectionMap::const_iterator map_entry
672
= section_map.find(".debug_line");
673
// Mac OS X puts DWARF data in sections whose names begin with "__"
675
if (map_entry == section_map.end())
676
map_entry = section_map.find("__debug_line");
677
if (map_entry == section_map.end()) {
678
cu_context_->reporter->MissingSection(".debug_line");
681
const char *section_start = map_entry->second.first;
682
uint64 section_length = map_entry->second.second;
683
if (offset >= section_length) {
684
cu_context_->reporter->BadLineInfoOffset(offset);
687
(*line_reader_)(section_start + offset, section_length - offset,
688
cu_context_->file_context->module, &lines_);
692
// Return true if ADDRESS falls within the range of ITEM.
694
inline bool within(const T &item, Module::Address address) {
695
// Because Module::Address is unsigned, and unsigned arithmetic
696
// wraps around, this will be false if ADDRESS falls before the
697
// start of ITEM, or if it falls after ITEM's end.
698
return address - item.address < item.size;
702
void DwarfCUToModule::AssignLinesToFunctions() {
703
vector<Module::Function *> *functions = &cu_context_->functions;
704
WarningReporter *reporter = cu_context_->reporter;
706
// This would be simpler if we assumed that source line entries
707
// don't cross function boundaries. However, there's no real reason
708
// to assume that (say) a series of function definitions on the same
709
// line wouldn't get coalesced into one line number entry. The
710
// DWARF spec certainly makes no such promises.
712
// So treat the functions and lines as peers, and take the trouble
713
// to compute their ranges' intersections precisely. In any case,
714
// the hair here is a constant factor for performance; the
715
// complexity from here on out is linear.
717
// Put both our functions and lines in order by address.
718
sort(functions->begin(), functions->end(),
719
Module::Function::CompareByAddress);
720
sort(lines_.begin(), lines_.end(), Module::Line::CompareByAddress);
722
// The last line that we used any piece of. We use this only for
723
// generating warnings.
724
const Module::Line *last_line_used = NULL;
726
// The last function and line we warned about --- so we can avoid
727
// doing so more than once.
728
const Module::Function *last_function_cited = NULL;
729
const Module::Line *last_line_cited = NULL;
731
// Make a single pass through both vectors from lower to higher
732
// addresses, populating each Function's lines vector with lines
733
// from our lines_ vector that fall within the function's address
735
vector<Module::Function *>::iterator func_it = functions->begin();
736
vector<Module::Line>::const_iterator line_it = lines_.begin();
738
Module::Address current;
740
// Pointers to the referents of func_it and line_it, or NULL if the
741
// iterator is at the end of the sequence.
742
Module::Function *func;
743
const Module::Line *line;
745
// Start current at the beginning of the first line or function,
746
// whichever is earlier.
747
if (func_it != functions->end() && line_it != lines_.end()) {
750
current = std::min(func->address, line->address);
751
} else if (line_it != lines_.end()) {
754
current = line->address;
755
} else if (func_it != functions->end()) {
758
current = (*func_it)->address;
763
while (func || line) {
764
// This loop has two invariants that hold at the top.
766
// First, at least one of the iterators is not at the end of its
767
// sequence, and those that are not refer to the earliest
768
// function or line that contains or starts after CURRENT.
770
// Note that every byte is in one of four states: it is covered
771
// or not covered by a function, and, independently, it is
772
// covered or not covered by a line.
774
// The second invariant is that CURRENT refers to a byte whose
775
// state is different from its predecessor, or it refers to the
776
// first byte in the address space. In other words, CURRENT is
777
// always the address of a transition.
779
// Note that, although each iteration advances CURRENT from one
780
// transition address to the next in each iteration, it might
781
// not advance the iterators. Suppose we have a function that
782
// starts with a line, has a gap, and then a second line, and
783
// suppose that we enter an iteration with CURRENT at the end of
784
// the first line. The next transition address is the start of
785
// the second line, after the gap, so the iteration should
786
// advance CURRENT to that point. At the head of that iteration,
787
// the invariants require that the line iterator be pointing at
788
// the second line. But this is also true at the head of the
789
// next. And clearly, the iteration must not change the function
790
// iterator. So neither iterator moves.
792
// Assert the first invariant (see above).
793
assert(!func || current < func->address || within(*func, current));
794
assert(!line || current < line->address || within(*line, current));
796
// The next transition after CURRENT.
797
Module::Address next_transition;
799
// Figure out which state we're in, add lines or warn, and compute
800
// the next transition address.
801
if (func && current >= func->address) {
802
if (line && current >= line->address) {
803
// Covered by both a line and a function.
804
Module::Address func_left = func->size - (current - func->address);
805
Module::Address line_left = line->size - (current - line->address);
806
// This may overflow, but things work out.
807
next_transition = current + std::min(func_left, line_left);
808
Module::Line l = *line;
810
l.size = next_transition - current;
811
func->lines.push_back(l);
812
last_line_used = line;
814
// Covered by a function, but no line.
815
if (func != last_function_cited) {
816
reporter->UncoveredFunction(*func);
817
last_function_cited = func;
819
if (line && within(*func, line->address))
820
next_transition = line->address;
822
// If this overflows, we'll catch it below.
823
next_transition = func->address + func->size;
826
if (line && current >= line->address) {
827
// Covered by a line, but no function.
829
// If GCC emits padding after one function to align the start
830
// of the next, then it will attribute the padding
831
// instructions to the last source line of function (to reduce
832
// the size of the line number info), but omit it from the
833
// DW_AT_{low,high}_pc range given in .debug_info (since it
834
// costs nothing to be precise there). If we did use at least
835
// some of the line we're about to skip, and it ends at the
836
// start of the next function, then assume this is what
837
// happened, and don't warn.
838
if (line != last_line_cited
840
&& line == last_line_used
841
&& func->address - line->address == line->size)) {
842
reporter->UncoveredLine(*line);
843
last_line_cited = line;
845
if (func && within(*line, func->address))
846
next_transition = func->address;
848
// If this overflows, we'll catch it below.
849
next_transition = line->address + line->size;
851
// Covered by neither a function nor a line. By the invariant,
852
// both func and line begin after CURRENT. The next transition
853
// is the start of the next function or next line, whichever
855
assert (func || line);
857
next_transition = std::min(func->address, line->address);
859
next_transition = func->address;
861
next_transition = line->address;
865
// If a function or line abuts the end of the address space, then
866
// next_transition may end up being zero, in which case we've completed
867
// our pass. Handle that here, instead of trying to deal with it in
868
// each place we compute next_transition.
869
if (!next_transition)
872
// Advance iterators as needed. If lines overlap or functions overlap,
873
// then we could go around more than once. We don't worry too much
874
// about what result we produce in that case, just as long as we don't
876
while (func_it != functions->end()
877
&& next_transition >= (*func_it)->address
878
&& !within(**func_it, next_transition))
880
func = (func_it != functions->end()) ? *func_it : NULL;
881
while (line_it != lines_.end()
882
&& next_transition >= line_it->address
883
&& !within(*line_it, next_transition))
885
line = (line_it != lines_.end()) ? &*line_it : NULL;
887
// We must make progress.
888
assert(next_transition > current);
889
current = next_transition;
893
void DwarfCUToModule::Finish() {
894
// Assembly language files have no function data, and that gives us
895
// no place to store our line numbers (even though the GNU toolchain
896
// will happily produce source line info for assembly language
897
// files). To avoid spurious warnings about lines we can't assign
898
// to functions, skip CUs in languages that lack functions.
899
if (!cu_context_->language->HasFunctions())
902
// Read source line info, if we have any.
903
if (has_source_line_info_)
904
ReadSourceLines(source_line_offset_);
906
vector<Module::Function *> *functions = &cu_context_->functions;
908
// Dole out lines to the appropriate functions.
909
AssignLinesToFunctions();
911
// Add our functions, which now have source lines assigned to them,
913
cu_context_->file_context->module->AddFunctions(functions->begin(),
916
// Ownership of the function objects has shifted from cu_context to
921
bool DwarfCUToModule::StartCompilationUnit(uint64 offset,
925
uint8 dwarf_version) {
926
return dwarf_version >= 2;
929
bool DwarfCUToModule::StartRootDIE(uint64 offset, enum DwarfTag tag,
930
const AttributeList& attrs) {
931
// We don't deal with partial compilation units (the only other tag
932
// likely to be used for root DIE).
933
return tag == dwarf2reader::DW_TAG_compile_unit;
936
} // namespace google_breakpad