~ubuntu-branches/ubuntu/trusty/tomahawk/trusty-proposed

« back to all changes in this revision

Viewing changes to thirdparty/breakpad/common/dwarf_cu_to_module.cc

  • Committer: Package Import Robot
  • Author(s): Harald Sitter
  • Date: 2013-03-07 21:50:13 UTC
  • Revision ID: package-import@ubuntu.com-20130307215013-6gdjkdds7i9uenvs
Tags: upstream-0.6.0+dfsg
ImportĀ upstreamĀ versionĀ 0.6.0+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright (c) 2010 Google Inc.
 
2
// All rights reserved.
 
3
//
 
4
// Redistribution and use in source and binary forms, with or without
 
5
// modification, are permitted provided that the following conditions are
 
6
// met:
 
7
//
 
8
//     * Redistributions of source code must retain the above copyright
 
9
// notice, this list of conditions and the following disclaimer.
 
10
//     * Redistributions in binary form must reproduce the above
 
11
// copyright notice, this list of conditions and the following disclaimer
 
12
// in the documentation and/or other materials provided with the
 
13
// distribution.
 
14
//     * Neither the name of Google Inc. nor the names of its
 
15
// contributors may be used to endorse or promote products derived from
 
16
// this software without specific prior written permission.
 
17
//
 
18
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 
19
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 
20
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 
21
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 
22
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 
23
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 
24
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 
25
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 
26
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 
27
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 
28
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
29
 
 
30
// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
 
31
 
 
32
// Implement the DwarfCUToModule class; see dwarf_cu_to_module.h.
 
33
 
 
34
// For <inttypes.h> PRI* macros, before anything else might #include it.
 
35
#ifndef __STDC_FORMAT_MACROS
 
36
#define __STDC_FORMAT_MACROS
 
37
#endif  /* __STDC_FORMAT_MACROS */
 
38
 
 
39
#include "common/dwarf_cu_to_module.h"
 
40
 
 
41
#include <assert.h>
 
42
#include <inttypes.h>
 
43
#include <stdio.h>
 
44
 
 
45
#include <algorithm>
 
46
#include <set>
 
47
#include <utility>
 
48
 
 
49
#include "common/dwarf_line_to_module.h"
 
50
 
 
51
namespace google_breakpad {
 
52
 
 
53
using std::map;
 
54
using std::pair;
 
55
using std::set;
 
56
using std::vector;
 
57
 
 
58
// Data provided by a DWARF specification DIE.
 
59
// 
 
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
 
65
// DIE.
 
66
//
 
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.
 
72
//
 
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;
 
78
 
 
79
  // The name for the specification DIE itself, without any enclosing
 
80
  // name components.
 
81
  string unqualified_name;
 
82
};
 
83
 
 
84
// An abstract origin -- base definition of an inline function.
 
85
struct AbstractOrigin {
 
86
  AbstractOrigin() : name() {}
 
87
  AbstractOrigin(const string& name) : name(name) {}
 
88
 
 
89
  string name;
 
90
};
 
91
 
 
92
typedef map<uint64, AbstractOrigin> AbstractOriginByOffset;
 
93
 
 
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
 
99
  // from the set.
 
100
  // 
 
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
 
105
  // of text.
 
106
  set<string> common_strings;
 
107
 
 
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;
 
112
 
 
113
  AbstractOriginByOffset origins;
 
114
};
 
115
 
 
116
DwarfCUToModule::FileContext::FileContext(const string &filename_arg,
 
117
                                          Module *module_arg)
 
118
    : filename(filename_arg), module(module_arg) {
 
119
  file_private = new FilePrivate();
 
120
}
 
121
 
 
122
DwarfCUToModule::FileContext::~FileContext() {
 
123
  delete file_private;
 
124
}
 
125
 
 
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) { }
 
134
  ~CUContext() {
 
135
    for (vector<Module::Function *>::iterator it = functions.begin();
 
136
         it != functions.end(); it++)
 
137
      delete *it;
 
138
  };
 
139
 
 
140
  // The DWARF-bearing file into which this CU was incorporated.
 
141
  FileContext *file_context;
 
142
 
 
143
  // For printing error messages.
 
144
  WarningReporter *reporter;
 
145
 
 
146
  // The source language of this compilation unit.
 
147
  const Language *language;
 
148
 
 
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.
 
152
  //
 
153
  // Destroying this destroys all the functions this vector points to.
 
154
  vector<Module::Function *> functions;
 
155
};
 
156
 
 
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
 
162
  // tree like:
 
163
  //
 
164
  // DW_TAG_namespace Foo
 
165
  //   DW_TAG_class Bar
 
166
  //     DW_TAG_subprogram Baz
 
167
  //
 
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 "".
 
171
  string name;
 
172
};
 
173
 
 
174
// An abstract base class for all the dumper's DIE handlers.
 
175
class DwarfCUToModule::GenericDIEHandler: public dwarf2reader::DIEHandler {
 
176
 public:
 
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,
 
181
                    uint64 offset)
 
182
      : cu_context_(cu_context),
 
183
        parent_context_(parent_context),
 
184
        offset_(offset),
 
185
        declaration_(false),
 
186
        specification_(NULL) { }
 
187
 
 
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,
 
191
                                enum DwarfForm form,
 
192
                                uint64 data);
 
193
 
 
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,
 
197
                                 enum DwarfForm form,
 
198
                                 uint64 data);
 
199
 
 
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,
 
203
                              enum DwarfForm form,
 
204
                              const string &data);
 
205
 
 
206
 protected:
 
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.
 
211
  //
 
212
  // Use this from EndAttributes member functions, not ProcessAttribute*
 
213
  // functions; only the former can be sure that all the DIE's attributes
 
214
  // have been seen.
 
215
  string ComputeQualifiedName();
 
216
 
 
217
  CUContext *cu_context_;
 
218
  DIEContext *parent_context_;
 
219
  uint64 offset_;
 
220
 
 
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.
 
223
  bool declaration_;
 
224
 
 
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_;
 
229
 
 
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_;
 
233
};
 
234
 
 
235
void DwarfCUToModule::GenericDIEHandler::ProcessAttributeUnsigned(
 
236
    enum DwarfAttribute attr,
 
237
    enum DwarfForm form,
 
238
    uint64 data) {
 
239
  switch (attr) {
 
240
    case dwarf2reader::DW_AT_declaration: declaration_ = (data != 0); break;
 
241
    default: break;
 
242
  }
 
243
}
 
244
 
 
245
void DwarfCUToModule::GenericDIEHandler::ProcessAttributeReference(
 
246
    enum DwarfAttribute attr,
 
247
    enum DwarfForm form,
 
248
    uint64 data) {
 
249
  switch (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;
 
262
      } else {
 
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
 
267
        // things.
 
268
        cu_context_->reporter->UnknownSpecification(offset_, data);
 
269
      }
 
270
      break;
 
271
    }
 
272
    default: break;
 
273
  }
 
274
}
 
275
 
 
276
void DwarfCUToModule::GenericDIEHandler::ProcessAttributeString(
 
277
    enum DwarfAttribute attr,
 
278
    enum DwarfForm form,
 
279
    const string &data) {
 
280
  switch (attr) {
 
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; 
 
290
      break;
 
291
    }
 
292
    default: break;
 
293
  }
 
294
}
 
295
 
 
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;
 
302
  else
 
303
    unqualified_name = &name_attribute_;
 
304
 
 
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;
 
309
  if (specification_)
 
310
    enclosing_name = &specification_->enclosing_name;
 
311
  else
 
312
    enclosing_name = &parent_context_->name;
 
313
 
 
314
  // If this DIE was marked as a declaration, record its names in the
 
315
  // specification table.
 
316
  if (declaration_) {
 
317
    FileContext *file_context = cu_context_->file_context;
 
318
    Specification spec;
 
319
    spec.enclosing_name = *enclosing_name;
 
320
    spec.unqualified_name = *unqualified_name;
 
321
    file_context->file_private->specifications[offset_] = spec;
 
322
  }
 
323
 
 
324
  // Combine the enclosing name and unqualified name to produce our
 
325
  // own fully-qualified name.
 
326
  return cu_context_->language->MakeQualifiedName(*enclosing_name,
 
327
                                                  *unqualified_name);
 
328
}
 
329
 
 
330
// A handler class for DW_TAG_subprogram DIEs.
 
331
class DwarfCUToModule::FuncHandler: public GenericDIEHandler {
 
332
 public:
 
333
  FuncHandler(CUContext *cu_context, DIEContext *parent_context,
 
334
              uint64 offset)
 
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,
 
338
                                enum DwarfForm form,
 
339
                                uint64 data);
 
340
  void ProcessAttributeSigned(enum DwarfAttribute attr,
 
341
                              enum DwarfForm form,
 
342
                              int64 data);
 
343
  void ProcessAttributeReference(enum DwarfAttribute attr,
 
344
                                 enum DwarfForm form,
 
345
                                 uint64 data);
 
346
 
 
347
  bool EndAttributes();
 
348
  void Finish();
 
349
 
 
350
 private:
 
351
  // The fully-qualified name, as derived from name_attribute_,
 
352
  // specification_, parent_context_.  Computed in EndAttributes.
 
353
  string name_;
 
354
  uint64 low_pc_, high_pc_; // DW_AT_low_pc, DW_AT_high_pc
 
355
  const AbstractOrigin* abstract_origin_;
 
356
  bool inline_;
 
357
};
 
358
 
 
359
void DwarfCUToModule::FuncHandler::ProcessAttributeUnsigned(
 
360
    enum DwarfAttribute attr,
 
361
    enum DwarfForm form,
 
362
    uint64 data) {
 
363
  switch (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;
 
368
 
 
369
    case dwarf2reader::DW_AT_low_pc:      low_pc_  = data; break;
 
370
    case dwarf2reader::DW_AT_high_pc:     high_pc_ = data; break;
 
371
    default:
 
372
      GenericDIEHandler::ProcessAttributeUnsigned(attr, form, data);
 
373
      break;
 
374
  }
 
375
}
 
376
 
 
377
void DwarfCUToModule::FuncHandler::ProcessAttributeSigned(
 
378
    enum DwarfAttribute attr,
 
379
    enum DwarfForm form,
 
380
    int64 data) {
 
381
  switch (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;
 
386
 
 
387
    default:
 
388
      break;
 
389
  }
 
390
}
 
391
 
 
392
void DwarfCUToModule::FuncHandler::ProcessAttributeReference(
 
393
    enum DwarfAttribute attr,
 
394
    enum DwarfForm form,
 
395
    uint64 data) {
 
396
  switch(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);
 
403
      } else {
 
404
        cu_context_->reporter->UnknownAbstractOrigin(offset_, data);
 
405
      }
 
406
      break;
 
407
    }
 
408
    default:
 
409
      GenericDIEHandler::ProcessAttributeReference(attr, form, data);
 
410
      break;
 
411
  }
 
412
}
 
413
 
 
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;
 
419
  }
 
420
  return true;
 
421
}
 
422
 
 
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
 
433
    // have names.
 
434
    if (!name_.empty()) {
 
435
      func->name = name_;
 
436
    } else {
 
437
      cu_context_->reporter->UnnamedFunction(offset_);
 
438
      func->name = "<name omitted>";
 
439
    }
 
440
    func->address = low_pc_;
 
441
    func->size = high_pc_ - low_pc_;
 
442
    func->parameter_size = 0;
 
443
    if (func->address) {
 
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);
 
447
     }
 
448
  } else if (inline_) {
 
449
    AbstractOrigin origin(name_);
 
450
    cu_context_->file_context->file_private->origins[offset_] = origin;
 
451
  }
 
452
}
 
453
 
 
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 {
 
457
 public:
 
458
  NamedScopeHandler(CUContext *cu_context, DIEContext *parent_context,
 
459
                    uint64 offset)
 
460
      : GenericDIEHandler(cu_context, parent_context, offset) { }
 
461
  bool EndAttributes();
 
462
  DIEHandler *FindChildHandler(uint64 offset, enum DwarfTag tag,
 
463
                               const AttributeList &attrs);
 
464
 
 
465
 private:
 
466
  DIEContext child_context_; // A context for our children.
 
467
};
 
468
 
 
469
bool DwarfCUToModule::NamedScopeHandler::EndAttributes() {
 
470
  child_context_.name = ComputeQualifiedName();
 
471
  return true;
 
472
}
 
473
 
 
474
dwarf2reader::DIEHandler *DwarfCUToModule::NamedScopeHandler::FindChildHandler(
 
475
    uint64 offset,
 
476
    enum DwarfTag tag,
 
477
    const AttributeList &attrs) {
 
478
  switch (tag) {
 
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);
 
486
    default:
 
487
      return NULL;
 
488
  }
 
489
}
 
490
 
 
491
void DwarfCUToModule::WarningReporter::CUHeading() {
 
492
  if (printed_cu_header_)
 
493
    return;
 
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;
 
497
}
 
498
 
 
499
void DwarfCUToModule::WarningReporter::UnknownSpecification(uint64 offset,
 
500
                                                            uint64 target) {
 
501
  CUHeading();
 
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);
 
506
}
 
507
 
 
508
void DwarfCUToModule::WarningReporter::UnknownAbstractOrigin(uint64 offset,
 
509
                                                             uint64 target) {
 
510
  CUHeading();
 
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);
 
515
}
 
516
 
 
517
void DwarfCUToModule::WarningReporter::MissingSection(const string &name) {
 
518
  CUHeading();
 
519
  fprintf(stderr, "%s: warning: couldn't find DWARF '%s' section\n",
 
520
          filename_.c_str(), name.c_str());
 
521
}
 
522
 
 
523
void DwarfCUToModule::WarningReporter::BadLineInfoOffset(uint64 offset) {
 
524
  CUHeading();
 
525
  fprintf(stderr, "%s: warning: line number data offset beyond end"
 
526
          " of '.debug_line' section\n",
 
527
          filename_.c_str());
 
528
}
 
529
 
 
530
void DwarfCUToModule::WarningReporter::UncoveredHeading() {
 
531
  if (printed_unpaired_header_)
 
532
    return;
 
533
  CUHeading();
 
534
  fprintf(stderr, "%s: warning: skipping unpaired lines/functions:\n",
 
535
          filename_.c_str());
 
536
  printed_unpaired_header_ = true;
 
537
}
 
538
 
 
539
void DwarfCUToModule::WarningReporter::UncoveredFunction(
 
540
    const Module::Function &function) {
 
541
  if (!uncovered_warnings_enabled_)
 
542
    return;
 
543
  UncoveredHeading();
 
544
  fprintf(stderr, "    function%s: %s\n",
 
545
          function.size == 0 ? " (zero-length)" : "",
 
546
          function.name.c_str());
 
547
}
 
548
 
 
549
void DwarfCUToModule::WarningReporter::UncoveredLine(const Module::Line &line) {
 
550
  if (!uncovered_warnings_enabled_)
 
551
    return;
 
552
  UncoveredHeading();
 
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);
 
556
}
 
557
 
 
558
void DwarfCUToModule::WarningReporter::UnnamedFunction(uint64 offset) {
 
559
  CUHeading();
 
560
  fprintf(stderr, "%s: warning: function at offset 0x%llx has no name\n",
 
561
          filename_.c_str(), offset);
 
562
}
 
563
 
 
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();
 
570
}
 
571
 
 
572
DwarfCUToModule::~DwarfCUToModule() {
 
573
  delete cu_context_;
 
574
  delete child_context_;
 
575
}
 
576
 
 
577
void DwarfCUToModule::ProcessAttributeSigned(enum DwarfAttribute attr,
 
578
                                             enum DwarfForm form,
 
579
                                             int64 data) {
 
580
  switch (attr) {
 
581
    case dwarf2reader::DW_AT_language: // source language of this CU
 
582
      SetLanguage(static_cast<DwarfLanguage>(data));
 
583
      break;
 
584
    default:
 
585
      break;
 
586
  }
 
587
}
 
588
 
 
589
void DwarfCUToModule::ProcessAttributeUnsigned(enum DwarfAttribute attr,
 
590
                                               enum DwarfForm form,
 
591
                                               uint64 data) {
 
592
  switch (attr) {
 
593
    case dwarf2reader::DW_AT_stmt_list: // Line number information.
 
594
      has_source_line_info_ = true;
 
595
      source_line_offset_ = data;
 
596
      break;
 
597
    case dwarf2reader::DW_AT_language: // source language of this CU
 
598
      SetLanguage(static_cast<DwarfLanguage>(data));
 
599
      break;
 
600
    default:
 
601
      break;
 
602
  }
 
603
}
 
604
 
 
605
void DwarfCUToModule::ProcessAttributeString(enum DwarfAttribute attr,
 
606
                                             enum DwarfForm form,
 
607
                                             const string &data) {
 
608
  if (attr == dwarf2reader::DW_AT_name)
 
609
    cu_context_->reporter->SetCUName(data);
 
610
}
 
611
 
 
612
bool DwarfCUToModule::EndAttributes() {
 
613
  return true;
 
614
}
 
615
 
 
616
dwarf2reader::DIEHandler *DwarfCUToModule::FindChildHandler(
 
617
    uint64 offset,
 
618
    enum DwarfTag tag,
 
619
    const AttributeList &attrs) {
 
620
  switch (tag) {
 
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);
 
628
    default:
 
629
      return NULL;
 
630
  }
 
631
}
 
632
 
 
633
void DwarfCUToModule::SetLanguage(DwarfLanguage language) {
 
634
  switch (language) {
 
635
    case dwarf2reader::DW_LANG_Java:
 
636
      cu_context_->language = Language::Java;
 
637
      break;
 
638
 
 
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;
 
643
      break;
 
644
 
 
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
 
647
    // default.
 
648
    //
 
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.
 
652
    // 
 
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.
 
656
    default:
 
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;
 
664
      break;
 
665
  }
 
666
}
 
667
 
 
668
void DwarfCUToModule::ReadSourceLines(uint64 offset) {
 
669
  const dwarf2reader::SectionMap &section_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 "__"
 
674
  // instead of ".".
 
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");
 
679
    return;
 
680
  }
 
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);
 
685
    return;
 
686
  }
 
687
  (*line_reader_)(section_start + offset, section_length - offset,
 
688
                  cu_context_->file_context->module, &lines_);
 
689
}
 
690
 
 
691
namespace {
 
692
// Return true if ADDRESS falls within the range of ITEM.
 
693
template <class T>
 
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;
 
699
}
 
700
}
 
701
 
 
702
void DwarfCUToModule::AssignLinesToFunctions() {
 
703
  vector<Module::Function *> *functions = &cu_context_->functions;
 
704
  WarningReporter *reporter = cu_context_->reporter;
 
705
 
 
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.
 
711
  //
 
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.
 
716
 
 
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);
 
721
 
 
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;
 
725
 
 
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;
 
730
 
 
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
 
734
  // range.
 
735
  vector<Module::Function *>::iterator func_it = functions->begin();
 
736
  vector<Module::Line>::const_iterator line_it = lines_.begin();
 
737
 
 
738
  Module::Address current;
 
739
 
 
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;
 
744
 
 
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()) {
 
748
    func = *func_it;
 
749
    line = &*line_it;
 
750
    current = std::min(func->address, line->address);
 
751
  } else if (line_it != lines_.end()) {
 
752
    func = NULL;
 
753
    line = &*line_it;
 
754
    current = line->address;
 
755
  } else if (func_it != functions->end()) {
 
756
    func = *func_it;
 
757
    line = NULL;
 
758
    current = (*func_it)->address;
 
759
  } else {
 
760
    return;
 
761
  }
 
762
 
 
763
  while (func || line) {
 
764
    // This loop has two invariants that hold at the top.
 
765
    //
 
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.
 
769
    //
 
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.
 
773
    //
 
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.
 
778
    //
 
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.
 
791
 
 
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));
 
795
 
 
796
    // The next transition after CURRENT.
 
797
    Module::Address next_transition;
 
798
 
 
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;
 
809
        l.address = current;
 
810
        l.size = next_transition - current;
 
811
        func->lines.push_back(l);
 
812
        last_line_used = line;
 
813
      } else {
 
814
        // Covered by a function, but no line.
 
815
        if (func != last_function_cited) {
 
816
          reporter->UncoveredFunction(*func);
 
817
          last_function_cited = func;
 
818
        }
 
819
        if (line && within(*func, line->address))
 
820
          next_transition = line->address;
 
821
        else
 
822
          // If this overflows, we'll catch it below.
 
823
          next_transition = func->address + func->size;
 
824
      }
 
825
    } else {
 
826
      if (line && current >= line->address) {
 
827
        // Covered by a line, but no function.
 
828
        //
 
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
 
839
            && !(func
 
840
                 && line == last_line_used
 
841
                 && func->address - line->address == line->size)) {
 
842
          reporter->UncoveredLine(*line);
 
843
          last_line_cited = line;
 
844
        }
 
845
        if (func && within(*line, func->address))
 
846
          next_transition = func->address;
 
847
        else
 
848
          // If this overflows, we'll catch it below.
 
849
          next_transition = line->address + line->size;
 
850
      } else {
 
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
 
854
        // is earliest.
 
855
        assert (func || line);
 
856
        if (func && line)
 
857
          next_transition = std::min(func->address, line->address);
 
858
        else if (func)
 
859
          next_transition = func->address;
 
860
        else
 
861
          next_transition = line->address;
 
862
      }
 
863
    }
 
864
 
 
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)
 
870
      break;
 
871
 
 
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
 
875
    // hang or crash.
 
876
    while (func_it != functions->end()
 
877
           && next_transition >= (*func_it)->address
 
878
           && !within(**func_it, next_transition))
 
879
      func_it++;
 
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))
 
884
      line_it++;
 
885
    line = (line_it != lines_.end()) ? &*line_it : NULL;
 
886
 
 
887
    // We must make progress.
 
888
    assert(next_transition > current);
 
889
    current = next_transition;
 
890
  }
 
891
}
 
892
 
 
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())
 
900
    return;
 
901
 
 
902
  // Read source line info, if we have any.
 
903
  if (has_source_line_info_)
 
904
    ReadSourceLines(source_line_offset_);
 
905
 
 
906
  vector<Module::Function *> *functions = &cu_context_->functions;
 
907
 
 
908
  // Dole out lines to the appropriate functions.
 
909
  AssignLinesToFunctions();
 
910
 
 
911
  // Add our functions, which now have source lines assigned to them,
 
912
  // to module_.
 
913
  cu_context_->file_context->module->AddFunctions(functions->begin(),
 
914
                                                  functions->end());
 
915
 
 
916
  // Ownership of the function objects has shifted from cu_context to
 
917
  // the Module.
 
918
  functions->clear();
 
919
}
 
920
 
 
921
bool DwarfCUToModule::StartCompilationUnit(uint64 offset,
 
922
                                           uint8 address_size,
 
923
                                           uint8 offset_size,
 
924
                                           uint64 cu_length,
 
925
                                           uint8 dwarf_version) {
 
926
  return dwarf_version >= 2;
 
927
}
 
928
 
 
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;
 
934
}
 
935
 
 
936
} // namespace google_breakpad