aboutsummaryrefslogtreecommitdiff
path: root/src/common/dwarf_cu_to_module.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/common/dwarf_cu_to_module.cc')
-rw-r--r--src/common/dwarf_cu_to_module.cc91
1 files changed, 69 insertions, 22 deletions
diff --git a/src/common/dwarf_cu_to_module.cc b/src/common/dwarf_cu_to_module.cc
index a5a1fd06..94a0d428 100644
--- a/src/common/dwarf_cu_to_module.cc
+++ b/src/common/dwarf_cu_to_module.cc
@@ -35,6 +35,10 @@
#define __STDC_FORMAT_MACROS
#endif /* __STDC_FORMAT_MACROS */
+#ifdef HAVE_CONFIG_H
+#include <config.h> // Must come first
+#endif
+
#include "common/dwarf_cu_to_module.h"
#include <assert.h>
@@ -165,19 +169,23 @@ bool DwarfCUToModule::FileContext::IsUnhandledInterCUReference(
// parsing. This is for data shared across the CU's entire DIE tree,
// and parameters from the code invoking the CU parser.
struct DwarfCUToModule::CUContext {
- CUContext(FileContext* file_context_arg, WarningReporter* reporter_arg,
- RangesHandler* ranges_handler_arg)
+ CUContext(FileContext* file_context_arg,
+ WarningReporter* reporter_arg,
+ RangesHandler* ranges_handler_arg,
+ uint64_t low_pc,
+ uint64_t addr_base)
: version(0),
file_context(file_context_arg),
reporter(reporter_arg),
ranges_handler(ranges_handler_arg),
language(Language::CPlusPlus),
- low_pc(0),
+ low_pc(low_pc),
high_pc(0),
ranges_form(DW_FORM_sec_offset),
ranges_data(0),
ranges_base(0),
- str_offsets_base(0) { }
+ addr_base(addr_base),
+ str_offsets_base(0) {}
~CUContext() {
for (vector<Module::Function*>::iterator it = functions.begin();
@@ -326,7 +334,10 @@ class DwarfCUToModule::GenericDIEHandler: public DIEHandler {
// Use this from EndAttributes member functions, not ProcessAttribute*
// functions; only the former can be sure that all the DIE's attributes
// have been seen.
- StringView ComputeQualifiedName();
+ //
+ // On return, if has_qualified_name is non-NULL, *has_qualified_name is set to
+ // true if the DIE includes a fully-qualified name, false otherwise.
+ StringView ComputeQualifiedName(bool* has_qualified_name);
CUContext* cu_context_;
DIEContext* parent_context_;
@@ -462,7 +473,8 @@ void DwarfCUToModule::GenericDIEHandler::ProcessAttributeString(
}
}
-StringView DwarfCUToModule::GenericDIEHandler::ComputeQualifiedName() {
+StringView DwarfCUToModule::GenericDIEHandler::ComputeQualifiedName(
+ bool* has_qualified_name) {
// Use the demangled name, if one is available. Demangled names are
// preferable to those inferred from the DWARF structure because they
// include argument types.
@@ -478,6 +490,15 @@ StringView DwarfCUToModule::GenericDIEHandler::ComputeQualifiedName() {
StringView* unqualified_name = nullptr;
StringView* enclosing_name = nullptr;
if (!qualified_name) {
+ if (has_qualified_name) {
+ // dSYMs built with -gmlt do not include the DW_AT_linkage_name
+ // with the unmangled symbol, but rather include it in the
+ // LC_SYMTAB STABS, which end up in the externs of the module.
+ //
+ // Remember this so the Module can copy over the extern name later.
+ *has_qualified_name = false;
+ }
+
// Find the unqualified name. If the DIE has its own DW_AT_name
// attribute, then use that; otherwise, check the specification.
if (!name_attribute_.empty()) {
@@ -496,6 +517,10 @@ StringView DwarfCUToModule::GenericDIEHandler::ComputeQualifiedName() {
} else if (parent_context_) {
enclosing_name = &parent_context_->name;
}
+ } else {
+ if (has_qualified_name) {
+ *has_qualified_name = true;
+ }
}
// Prepare the return value before upcoming mutations possibly invalidate the
@@ -554,6 +579,7 @@ class DwarfCUToModule::InlineHandler : public GenericDIEHandler {
ranges_data_(0),
call_site_line_(0),
inline_nest_level_(inline_nest_level),
+ has_range_data_(false),
inlines_(inlines) {}
void ProcessAttributeUnsigned(enum DwarfAttribute attr,
@@ -575,6 +601,7 @@ class DwarfCUToModule::InlineHandler : public GenericDIEHandler {
int call_site_line_; // DW_AT_call_line
int call_site_file_id_; // DW_AT_call_file
int inline_nest_level_;
+ bool has_range_data_;
// A vector of inlines in the same nest level. It's owned by its parent
// function/inline. At Finish(), add this inline into the vector.
vector<unique_ptr<Module::Inline>>& inlines_;
@@ -595,6 +622,7 @@ void DwarfCUToModule::InlineHandler::ProcessAttributeUnsigned(
high_pc_ = data;
break;
case DW_AT_ranges:
+ has_range_data_ = true;
ranges_data_ = data;
ranges_form_ = form;
break;
@@ -638,7 +666,7 @@ bool DwarfCUToModule::InlineHandler::EndAttributes() {
void DwarfCUToModule::InlineHandler::Finish() {
vector<Module::Range> ranges;
- if (low_pc_ && high_pc_) {
+ if (!has_range_data_) {
if (high_pc_form_ != DW_FORM_addr &&
high_pc_form_ != DW_FORM_GNU_addr_index &&
high_pc_form_ != DW_FORM_addrx &&
@@ -675,11 +703,12 @@ void DwarfCUToModule::InlineHandler::Finish() {
// Every DW_TAG_inlined_subroutine should have a DW_AT_abstract_origin.
assert(specification_offset_ != 0);
- cu_context_->file_context->module_->inline_origin_map.SetReference(
- specification_offset_, specification_offset_);
+ Module::InlineOriginMap& inline_origin_map =
+ cu_context_->file_context->module_
+ ->inline_origin_maps[cu_context_->file_context->filename_];
+ inline_origin_map.SetReference(specification_offset_, specification_offset_);
Module::InlineOrigin* origin =
- cu_context_->file_context->module_->inline_origin_map
- .GetOrCreateInlineOrigin(specification_offset_, name_);
+ inline_origin_map.GetOrCreateInlineOrigin(specification_offset_, name_);
unique_ptr<Module::Inline> in(
new Module::Inline(origin, ranges, call_site_line_, call_site_file_id_,
inline_nest_level_, std::move(child_inlines_)));
@@ -718,7 +747,9 @@ class DwarfCUToModule::FuncHandler: public GenericDIEHandler {
ranges_form_(DW_FORM_sec_offset),
ranges_data_(0),
inline_(false),
- handle_inline_(handle_inline) {}
+ handle_inline_(handle_inline),
+ has_qualified_name_(false),
+ has_range_data_(false) {}
void ProcessAttributeUnsigned(enum DwarfAttribute attr,
enum DwarfForm form,
@@ -741,6 +772,8 @@ class DwarfCUToModule::FuncHandler: public GenericDIEHandler {
bool inline_;
vector<unique_ptr<Module::Inline>> child_inlines_;
bool handle_inline_;
+ bool has_qualified_name_;
+ bool has_range_data_;
DIEContext child_context_; // A context for our children.
};
@@ -760,6 +793,7 @@ void DwarfCUToModule::FuncHandler::ProcessAttributeUnsigned(
high_pc_ = data;
break;
case DW_AT_ranges:
+ has_range_data_ = true;
ranges_data_ = data;
ranges_form_ = form;
break;
@@ -804,7 +838,7 @@ DIEHandler* DwarfCUToModule::FuncHandler::FindChildHandler(
bool DwarfCUToModule::FuncHandler::EndAttributes() {
// Compute our name, and record a specification, if appropriate.
- name_ = ComputeQualifiedName();
+ name_ = ComputeQualifiedName(&has_qualified_name_);
if (name_.empty() && abstract_origin_) {
name_ = abstract_origin_->name;
}
@@ -830,7 +864,7 @@ void DwarfCUToModule::FuncHandler::Finish() {
iter->second->name = name_;
}
- if (!ranges_data_) {
+ if (!has_range_data_) {
// Make high_pc_ an address, if it isn't already.
if (high_pc_form_ != DW_FORM_addr &&
high_pc_form_ != DW_FORM_GNU_addr_index &&
@@ -877,6 +911,9 @@ void DwarfCUToModule::FuncHandler::Finish() {
scoped_ptr<Module::Function> func(new Module::Function(name, low_pc_));
func->ranges = ranges;
func->parameter_size = 0;
+ // If the name was unqualified, prefer the Extern name if there's a mismatch
+ // (the Extern name will be fully-qualified in that case).
+ func->prefer_extern_name = !has_qualified_name_;
if (func->address) {
// If the function address is zero this is a sign that this function
// description is just empty debug data and should just be discarded.
@@ -903,15 +940,16 @@ void DwarfCUToModule::FuncHandler::Finish() {
StringView name = name_.empty() ? name_omitted : name_;
uint64_t offset =
specification_offset_ != 0 ? specification_offset_ : offset_;
- cu_context_->file_context->module_->inline_origin_map.SetReference(offset_,
- offset);
- cu_context_->file_context->module_->inline_origin_map
- .GetOrCreateInlineOrigin(offset_, name);
+ Module::InlineOriginMap& inline_origin_map =
+ cu_context_->file_context->module_
+ ->inline_origin_maps[cu_context_->file_context->filename_];
+ inline_origin_map.SetReference(offset_, offset);
+ inline_origin_map.GetOrCreateInlineOrigin(offset_, name);
}
}
bool DwarfCUToModule::NamedScopeHandler::EndAttributes() {
- child_context_.name = ComputeQualifiedName();
+ child_context_.name = ComputeQualifiedName(NULL);
if (child_context_.name.empty() && no_specification) {
cu_context_->reporter->UnknownSpecification(offset_, specification_offset_);
}
@@ -1041,12 +1079,21 @@ DwarfCUToModule::DwarfCUToModule(FileContext* file_context,
LineToModuleHandler* line_reader,
RangesHandler* ranges_handler,
WarningReporter* reporter,
- bool handle_inline)
+ bool handle_inline,
+ uint64_t low_pc,
+ uint64_t addr_base,
+ bool has_source_line_info,
+ uint64_t source_line_offset)
: RootDIEHandler(handle_inline),
line_reader_(line_reader),
- cu_context_(new CUContext(file_context, reporter, ranges_handler)),
+ cu_context_(new CUContext(file_context,
+ reporter,
+ ranges_handler,
+ low_pc,
+ addr_base)),
child_context_(new DIEContext()),
- has_source_line_info_(false) {}
+ has_source_line_info_(has_source_line_info),
+ source_line_offset_(source_line_offset) {}
DwarfCUToModule::~DwarfCUToModule() {
}