Skip to content

Commit db18954

Browse files
committed
Refactor subprogram_symbol
1 parent fc9459a commit db18954

File tree

2 files changed

+45
-25
lines changed

2 files changed

+45
-25
lines changed

src/symbols/dwarf/dwarf_resolver.cpp

Lines changed: 35 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -359,38 +359,48 @@ namespace libdwarf {
359359
return prefix;
360360
}
361361

362+
// Follows DW_AT_specification or DW_AT_abstract_origin reference
363+
static optional<die_object> maybe_resolve_subprogram_reference(const die_object& die) {
364+
if(die.has_attr(DW_AT_specification)) {
365+
return die.resolve_reference_attribute(DW_AT_specification);
366+
}
367+
if(die.has_attr(DW_AT_abstract_origin)) {
368+
return die.resolve_reference_attribute(DW_AT_abstract_origin);
369+
}
370+
return nullopt;
371+
}
372+
362373
std::string subprogram_symbol(
363374
const die_object& cu_die,
364375
const die_object& die,
365-
Dwarf_Half dwversion,
366376
optional<string_view> walked_prefix = nullopt
367377
) {
368378
ASSERT(die.get_tag() == DW_TAG_subprogram || die.get_tag() == DW_TAG_inlined_subroutine);
369-
optional<std::string> name;
370-
if(auto linkage_name = die.get_string_attribute(DW_AT_linkage_name)) {
371-
name = std::move(linkage_name);
372-
} else if(auto linkage_name = die.get_string_attribute(DW_AT_MIPS_linkage_name)) {
373-
name = std::move(linkage_name);
374-
} else if(auto raw_name = die.get_string_attribute(DW_AT_name)) {
375-
// DW_AT_name is unqualified according to the DWARF standard
376-
// In cache_mode == speed we preprocess all the namespace prefixes and a cache will hit in
377-
// get_die_namespace_prefix, otherwise hopefully we can use the prefix we collected while walking
378-
// and otherwise we'll have to re-walk from the cu_die to create the namespace prefix
379+
optional<die_object> ref_holder;
380+
const die_object* current = &die;
381+
while(current) {
382+
if(auto linkage_name = die.get_string_attribute(DW_AT_linkage_name)) {
383+
return std::move(linkage_name).unwrap();
384+
}
385+
if(auto linkage_name = die.get_string_attribute(DW_AT_MIPS_linkage_name)) {
386+
return std::move(linkage_name).unwrap();
387+
}
388+
if(auto raw_name = current->get_string_attribute(DW_AT_name)) {
389+
// DW_AT_name is unqualified according to the DWARF standard
390+
// In cache_mode == speed we preprocess all the namespace prefixes and a cache will hit in
391+
// get_die_namespace_prefix, otherwise hopefully we can use the prefix we collected while walking
392+
// and otherwise we'll have to re-walk from the cu_die to create the namespace prefix
379393
auto prefix = walked_prefix.has_value()
380394
? std::string(walked_prefix.unwrap())
381-
: get_die_namespace_prefix(cu_die, die);
382-
name = prefix + raw_name.unwrap();
395+
: get_die_namespace_prefix(cu_die, *current);
396+
return prefix + raw_name.unwrap();
383397
}
384-
if(name.has_value()) {
385-
return std::move(name).unwrap();
386-
} else {
387-
if(die.has_attr(DW_AT_specification)) {
388-
die_object spec = die.resolve_reference_attribute(DW_AT_specification);
389-
return subprogram_symbol(cu_die, spec, dwversion);
390-
} else if(die.has_attr(DW_AT_abstract_origin)) {
391-
die_object spec = die.resolve_reference_attribute(DW_AT_abstract_origin);
392-
return subprogram_symbol(cu_die, spec, dwversion);
393-
}
398+
// let's try to follow DW_AT_specification / DW_AT_abstract_origin
399+
// when we do so, we discard any walked prefix we have since the referenced die might live in a
400+
// different series of nested namespaces etc
401+
walked_prefix.reset();
402+
ref_holder = maybe_resolve_subprogram_reference(*current);
403+
current = ref_holder ? &ref_holder.unwrap() : nullptr;
394404
}
395405
return "";
396406
}
@@ -452,7 +462,7 @@ namespace libdwarf {
452462
child,
453463
[this, &cu_die, pc, dwversion, &inlines, &target_die, &current_obj_holder] (const die_object& die) {
454464
if(die.get_tag() == DW_TAG_inlined_subroutine && die.pc_in_die(cu_die, dwversion, pc)) {
455-
const auto name = subprogram_symbol(cu_die, die, dwversion);
465+
const auto name = subprogram_symbol(cu_die, die);
456466
auto file_i = die.get_unsigned_attribute(DW_AT_call_file);
457467
// TODO: Refactor.... Probably put logic in resolve_filename.
458468
if(file_i) {
@@ -518,7 +528,7 @@ namespace libdwarf {
518528
optional<string_view> walked_prefix = nullopt
519529
) {
520530
ASSERT(die.get_tag() == DW_TAG_subprogram);
521-
const auto name = subprogram_symbol(cu_die, die, dwversion, walked_prefix);
531+
const auto name = subprogram_symbol(cu_die, die, walked_prefix);
522532
if(should_resolve_inlined_calls()) {
523533
get_inlines_info(cu_die, die, pc, dwversion, inlines);
524534
}

src/utils/optional.hpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,16 @@ namespace detail {
163163
NODISCARD T value_or(U&& default_value) && {
164164
return holds_value ? static_cast<T>(std::move(uvalue)) : static_cast<T>(std::forward<U>(default_value));
165165
}
166+
167+
template<typename F>
168+
NODISCARD optional or_else(F&& f) const & {
169+
return holds_value ? *this : std::forward<F>(f)();
170+
}
171+
172+
template<typename F>
173+
NODISCARD optional or_else(F&& f) && {
174+
return holds_value ? std::move(*this) : std::forward<F>(f)();
175+
}
166176
};
167177
}
168178
CPPTRACE_END_NAMESPACE

0 commit comments

Comments
 (0)