gctf2023/pwn/flipper/dist/utils/add-debug/dwarf/abbrev.cc
2023-11-24 13:11:34 -05:00

169 lines
5.5 KiB
C++

#include "internal.hh"
using namespace std;
DWARFPP_BEGIN_NAMESPACE
static value::type
resolve_type(DW_AT name, DW_FORM form)
{
switch (form) {
case DW_FORM::addr:
return value::type::address;
case DW_FORM::block:
case DW_FORM::block1:
case DW_FORM::block2:
case DW_FORM::block4:
// Prior to DWARF 4, exprlocs didn't have their own
// form and were represented as blocks.
// XXX Should this be predicated on version?
switch (name) {
case DW_AT::location:
case DW_AT::byte_size:
case DW_AT::bit_offset:
case DW_AT::bit_size:
case DW_AT::string_length:
case DW_AT::lower_bound:
case DW_AT::return_addr:
case DW_AT::bit_stride:
case DW_AT::upper_bound:
case DW_AT::count:
case DW_AT::data_member_location:
case DW_AT::frame_base:
case DW_AT::segment:
case DW_AT::static_link:
case DW_AT::use_location:
case DW_AT::vtable_elem_location:
case DW_AT::allocated:
case DW_AT::associated:
case DW_AT::data_location:
case DW_AT::byte_stride:
return value::type::exprloc;
default:
return value::type::block;
}
case DW_FORM::data4:
case DW_FORM::data8:
// Prior to DWARF 4, section offsets didn't have their
// own form and were represented as data4 or data8.
// DWARF 3 clarified that types that accepted both
// constants and section offsets were to treat data4
// and data8 as section offsets and other constant
// forms as constants.
// XXX Should this be predicated on version?
switch (name) {
case DW_AT::location:
case DW_AT::stmt_list:
case DW_AT::string_length:
case DW_AT::return_addr:
case DW_AT::start_scope:
case DW_AT::data_member_location:
case DW_AT::frame_base:
case DW_AT::macro_info:
case DW_AT::segment:
case DW_AT::static_link:
case DW_AT::use_location:
case DW_AT::vtable_elem_location:
case DW_AT::ranges:
goto sec_offset;
default:
// fallthrough
break;
} // fallthrough
case DW_FORM::data1:
case DW_FORM::data2:
return value::type::constant;
case DW_FORM::udata:
return value::type::uconstant;
case DW_FORM::sdata:
return value::type::sconstant;
case DW_FORM::exprloc:
return value::type::exprloc;
case DW_FORM::flag:
case DW_FORM::flag_present:
return value::type::flag;
case DW_FORM::ref1:
case DW_FORM::ref2:
case DW_FORM::ref4:
case DW_FORM::ref8:
case DW_FORM::ref_addr:
case DW_FORM::ref_sig8:
case DW_FORM::ref_udata:
return value::type::reference;
case DW_FORM::string:
case DW_FORM::strp:
return value::type::string;
case DW_FORM::indirect:
// There's nothing meaningful we can do
return value::type::invalid;
case DW_FORM::sec_offset:
sec_offset:
// The type of this form depends on the attribute
switch (name) {
case DW_AT::stmt_list:
return value::type::line;
case DW_AT::location:
case DW_AT::string_length:
case DW_AT::return_addr:
case DW_AT::data_member_location:
case DW_AT::frame_base:
case DW_AT::segment:
case DW_AT::static_link:
case DW_AT::use_location:
case DW_AT::vtable_elem_location:
return value::type::loclist;
case DW_AT::macro_info:
return value::type::mac;
case DW_AT::start_scope:
case DW_AT::ranges:
return value::type::rangelist;
default:
throw format_error("DW_FORM_sec_offset not expected for attribute " +
to_string(name));
}
}
throw format_error("unknown attribute form " + to_string(form));
}
attribute_spec::attribute_spec(DW_AT name, DW_FORM form)
: name(name), form(form), type(resolve_type(name, form))
{
}
bool
abbrev_entry::read(cursor *cur)
{
attributes.clear();
// Section 7.5.3
code = cur->uleb128();
if (!code)
return false;
tag = (DW_TAG)cur->uleb128();
children = cur->fixed<DW_CHILDREN>() == DW_CHILDREN::yes;
while (1) {
DW_AT name = (DW_AT)cur->uleb128();
DW_FORM form = (DW_FORM)cur->uleb128();
if (name == (DW_AT)0 && form == (DW_FORM)0)
break;
attributes.push_back(attribute_spec(name, form));
}
attributes.shrink_to_fit();
return true;
}
DWARFPP_END_NAMESPACE