* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Copyright 2013-2018, Rene Gollent, rene@gollent.com.
* Distributed under the terms of the MIT License.
*/
#include "AttributeClasses.h"
#include "Dwarf.h"
enum {
AC_ADDRESS = 1 << (ATTRIBUTE_CLASS_ADDRESS - 1),
AC_ADDRPTR = 1 << (ATTRIBUTE_CLASS_ADDRPTR - 1),
AC_BLOCK = 1 << (ATTRIBUTE_CLASS_BLOCK - 1),
AC_CONSTANT = 1 << (ATTRIBUTE_CLASS_CONSTANT - 1),
AC_FLAG = 1 << (ATTRIBUTE_CLASS_FLAG - 1),
AC_LINEPTR = 1 << (ATTRIBUTE_CLASS_LINEPTR - 1),
AC_LOCLIST = 1 << (ATTRIBUTE_CLASS_LOCLIST - 1),
AC_LOCLISTPTR = 1 << (ATTRIBUTE_CLASS_LOCLISTPTR - 1),
AC_MACPTR = 1 << (ATTRIBUTE_CLASS_MACPTR - 1),
AC_RANGELIST = 1 << (ATTRIBUTE_CLASS_RANGELIST - 1),
AC_RANGELISTPTR = 1 << (ATTRIBUTE_CLASS_RANGELISTPTR - 1),
AC_REFERENCE = 1 << (ATTRIBUTE_CLASS_REFERENCE - 1),
AC_STRING = 1 << (ATTRIBUTE_CLASS_STRING - 1),
AC_STROFFSETSPTR= 1 << (ATTRIBUTE_CLASS_STROFFSETSPTR - 1),
};
struct attribute_info_entry {
const char* name;
uint16 value;
uint16 classes;
};
struct attribute_name_info_entry {
const char* name;
DebugInfoEntrySetter setter;
uint16 value;
uint16 classes;
};
#undef ENTRY
#define ENTRY(name) "DW_AT_" #name, &DebugInfoEntry::AddAttribute_##name, \
DW_AT_##name
static const attribute_name_info_entry kAttributeNameInfos[] = {
{ ENTRY(sibling), AC_REFERENCE },
{ ENTRY(location), AC_BLOCK | AC_LOCLIST },
{ ENTRY(name), AC_STRING },
{ ENTRY(ordering), AC_CONSTANT },
{ ENTRY(byte_size), AC_BLOCK | AC_CONSTANT | AC_REFERENCE },
{ ENTRY(bit_offset), AC_BLOCK | AC_CONSTANT | AC_REFERENCE },
{ ENTRY(bit_size), AC_BLOCK | AC_CONSTANT | AC_REFERENCE },
{ ENTRY(stmt_list), AC_LINEPTR },
{ ENTRY(low_pc), AC_ADDRESS | AC_CONSTANT | AC_REFERENCE },
{ ENTRY(high_pc), AC_ADDRESS | AC_CONSTANT | AC_REFERENCE },
{ ENTRY(language), AC_CONSTANT },
{ ENTRY(discr), AC_REFERENCE },
{ ENTRY(discr_value), AC_CONSTANT },
{ ENTRY(visibility), AC_CONSTANT },
{ ENTRY(import), AC_REFERENCE },
{ ENTRY(string_length), AC_BLOCK | AC_LOCLIST },
{ ENTRY(common_reference), AC_REFERENCE },
{ ENTRY(comp_dir), AC_STRING },
{ ENTRY(const_value), AC_BLOCK | AC_CONSTANT | AC_STRING },
{ ENTRY(containing_type), AC_REFERENCE },
{ ENTRY(default_value), AC_REFERENCE | AC_CONSTANT | AC_FLAG },
{ ENTRY(inline), AC_CONSTANT },
{ ENTRY(is_optional), AC_FLAG },
{ ENTRY(lower_bound), AC_BLOCK | AC_CONSTANT | AC_REFERENCE },
{ ENTRY(producer), AC_STRING },
{ ENTRY(prototyped), AC_FLAG },
{ ENTRY(return_addr), AC_BLOCK | AC_LOCLIST },
{ ENTRY(start_scope), AC_CONSTANT },
{ ENTRY(bit_stride), AC_BLOCK | AC_CONSTANT | AC_REFERENCE },
{ ENTRY(upper_bound), AC_BLOCK | AC_CONSTANT | AC_REFERENCE },
{ ENTRY(abstract_origin), AC_REFERENCE },
{ ENTRY(accessibility), AC_CONSTANT },
{ ENTRY(address_class), AC_CONSTANT },
{ ENTRY(artificial), AC_FLAG },
{ ENTRY(base_types), AC_REFERENCE },
{ ENTRY(calling_convention), AC_CONSTANT },
{ ENTRY(count), AC_BLOCK | AC_CONSTANT | AC_REFERENCE },
{ ENTRY(data_member_location), AC_BLOCK | AC_CONSTANT | AC_LOCLIST },
{ ENTRY(decl_column), AC_CONSTANT },
{ ENTRY(decl_file), AC_CONSTANT },
{ ENTRY(decl_line), AC_CONSTANT },
{ ENTRY(declaration), AC_FLAG },
{ ENTRY(discr_list), AC_BLOCK },
{ ENTRY(encoding), AC_CONSTANT },
{ ENTRY(external), AC_FLAG },
{ ENTRY(frame_base), AC_BLOCK | AC_LOCLIST },
{ ENTRY(friend), AC_REFERENCE },
{ ENTRY(identifier_case), AC_CONSTANT },
{ ENTRY(macro_info), AC_MACPTR },
{ ENTRY(namelist_item), AC_BLOCK | AC_REFERENCE },
{ ENTRY(priority), AC_REFERENCE },
{ ENTRY(segment), AC_BLOCK | AC_LOCLIST },
{ ENTRY(specification), AC_REFERENCE },
{ ENTRY(static_link), AC_BLOCK | AC_LOCLIST },
{ ENTRY(type), AC_REFERENCE },
{ ENTRY(use_location), AC_BLOCK | AC_LOCLIST },
{ ENTRY(variable_parameter), AC_FLAG },
{ ENTRY(virtuality), AC_CONSTANT },
{ ENTRY(vtable_elem_location), AC_BLOCK | AC_LOCLIST },
{ ENTRY(allocated), AC_BLOCK | AC_CONSTANT | AC_REFERENCE },
{ ENTRY(associated), AC_BLOCK | AC_CONSTANT | AC_REFERENCE },
{ ENTRY(data_location), AC_BLOCK },
{ ENTRY(byte_stride), AC_BLOCK | AC_CONSTANT | AC_REFERENCE },
{ ENTRY(entry_pc), AC_ADDRESS },
{ ENTRY(use_UTF8), AC_FLAG },
{ ENTRY(extension), AC_REFERENCE },
{ ENTRY(ranges), AC_RANGELIST },
{ ENTRY(trampoline), AC_ADDRESS | AC_FLAG | AC_REFERENCE
| AC_STRING },
{ ENTRY(call_column), AC_CONSTANT },
{ ENTRY(call_file), AC_CONSTANT },
{ ENTRY(call_line), AC_CONSTANT },
{ ENTRY(description), AC_STRING },
{ ENTRY(binary_scale), AC_CONSTANT },
{ ENTRY(decimal_scale), AC_CONSTANT },
{ ENTRY(small), AC_REFERENCE },
{ ENTRY(decimal_sign), AC_CONSTANT },
{ ENTRY(digit_count), AC_CONSTANT },
{ ENTRY(picture_string), AC_STRING },
{ ENTRY(mutable), AC_FLAG },
{ ENTRY(threads_scaled), AC_FLAG },
{ ENTRY(explicit), AC_FLAG },
{ ENTRY(object_pointer), AC_REFERENCE },
{ ENTRY(endianity), AC_CONSTANT },
{ ENTRY(elemental), AC_FLAG },
{ ENTRY(pure), AC_FLAG },
{ ENTRY(recursive), AC_FLAG },
{ ENTRY(signature), AC_REFERENCE },
{ ENTRY(main_subprogram), AC_FLAG },
{ ENTRY(data_bit_offset), AC_CONSTANT },
{ ENTRY(const_expr), AC_FLAG },
{ ENTRY(enum_class), AC_FLAG },
{ ENTRY(linkage_name), AC_STRING },
{ ENTRY(string_length_bit_size),
AC_CONSTANT },
{ ENTRY(string_length_byte_size),
AC_CONSTANT },
{ ENTRY(rank), AC_CONSTANT | AC_BLOCK },
{ ENTRY(str_offsets_base), AC_STROFFSETSPTR },
{ ENTRY(addr_base), AC_ADDRPTR },
{ ENTRY(rnglists_base), AC_RANGELISTPTR },
{ ENTRY(dwo_name), AC_STRING },
{ ENTRY(reference), AC_FLAG },
{ ENTRY(rvalue_reference), AC_FLAG },
{ ENTRY(macros), AC_MACPTR },
{ ENTRY(call_all_calls), AC_FLAG },
{ ENTRY(call_all_source_calls), AC_FLAG },
{ ENTRY(call_all_tail_calls), AC_FLAG },
{ ENTRY(call_return_pc), AC_ADDRESS },
{ ENTRY(call_value), AC_BLOCK },
{ ENTRY(call_origin), AC_BLOCK },
{ ENTRY(call_parameter), AC_REFERENCE },
{ ENTRY(call_pc), AC_ADDRESS },
{ ENTRY(call_tail_call), AC_FLAG },
{ ENTRY(call_target), AC_BLOCK },
{ ENTRY(call_target_clobbered), AC_BLOCK },
{ ENTRY(call_data_location), AC_BLOCK },
{ ENTRY(call_data_value), AC_BLOCK },
{ ENTRY(noreturn), AC_FLAG },
{ ENTRY(alignment), AC_CONSTANT },
{ ENTRY(export_symbols), AC_FLAG },
{ ENTRY(deleted), AC_FLAG },
{ ENTRY(defaulted), AC_CONSTANT },
{ ENTRY(loclists_base), AC_LOCLISTPTR },
{ ENTRY(call_site_value), AC_BLOCK },
{ ENTRY(call_site_data_value), AC_BLOCK },
{ ENTRY(call_site_target), AC_BLOCK },
{ ENTRY(call_site_target_clobbered),
AC_BLOCK },
{ ENTRY(tail_call), AC_FLAG },
{ ENTRY(all_tail_call_sites), AC_FLAG },
{ ENTRY(all_call_sites), AC_FLAG },
{ ENTRY(all_source_call_sites), AC_FLAG },
{}
};
static const uint32 kAttributeNameInfoCount = DW_AT_loclists_base + 9;
static attribute_name_info_entry sAttributeNameInfos[kAttributeNameInfoCount];
#undef ENTRY
#define ENTRY(name) "DW_FORM_" #name, DW_FORM_##name
static const attribute_info_entry kAttributeFormInfos[] = {
{ ENTRY(addr), AC_ADDRESS },
{ ENTRY(block2), AC_BLOCK },
{ ENTRY(block4), AC_BLOCK },
{ ENTRY(data2), AC_CONSTANT },
{ ENTRY(data4), AC_CONSTANT | AC_LINEPTR | AC_LOCLIST
| AC_MACPTR | AC_RANGELIST },
{ ENTRY(data8), AC_CONSTANT | AC_LINEPTR | AC_LOCLIST
| AC_MACPTR | AC_RANGELIST },
{ ENTRY(string), AC_STRING },
{ ENTRY(block), AC_BLOCK },
{ ENTRY(block1), AC_BLOCK },
{ ENTRY(data1), AC_CONSTANT },
{ ENTRY(flag), AC_FLAG },
{ ENTRY(sdata), AC_CONSTANT },
{ ENTRY(strp), AC_STRING },
{ ENTRY(udata), AC_CONSTANT },
{ ENTRY(ref_addr), AC_REFERENCE },
{ ENTRY(ref1), AC_REFERENCE },
{ ENTRY(ref2), AC_REFERENCE },
{ ENTRY(ref4), AC_REFERENCE },
{ ENTRY(ref8), AC_REFERENCE },
{ ENTRY(ref_udata), AC_REFERENCE },
{ ENTRY(indirect), AC_REFERENCE },
{ ENTRY(sec_offset), AC_ADDRPTR | AC_LINEPTR
| AC_LOCLIST | AC_LOCLISTPTR
| AC_MACPTR
| AC_RANGELIST | AC_RANGELISTPTR
| AC_STROFFSETSPTR },
{ ENTRY(exprloc), AC_BLOCK },
{ ENTRY(flag_present), AC_FLAG },
{ ENTRY(strx), AC_STRING },
{ ENTRY(addrx), AC_ADDRESS },
{ ENTRY(ref_sup4), AC_REFERENCE },
{ ENTRY(strp_sup), AC_STRING },
{ ENTRY(data16), AC_CONSTANT },
{ ENTRY(line_strp), AC_STRING },
{ ENTRY(ref_sig8), AC_REFERENCE },
{ ENTRY(implicit_const),
AC_CONSTANT },
{ ENTRY(loclistx), AC_LOCLIST },
{ ENTRY(rnglistx), AC_RANGELIST },
{ ENTRY(ref_sup8), AC_REFERENCE },
{ ENTRY(strx1), AC_STRING },
{ ENTRY(strx2), AC_STRING },
{ ENTRY(strx3), AC_STRING },
{ ENTRY(strx4), AC_STRING },
{ ENTRY(addrx1), AC_ADDRESS },
{ ENTRY(addrx2), AC_ADDRESS },
{ ENTRY(addrx3), AC_ADDRESS },
{ ENTRY(addrx4), AC_ADDRESS },
{}
};
static const uint32 kAttributeFormInfoCount = DW_FORM_addrx4 + 1;
static attribute_info_entry sAttributeFormInfos[kAttributeFormInfoCount];
static struct InitAttributeInfos {
InitAttributeInfos()
{
for (uint32 i = 0; kAttributeNameInfos[i].name != NULL; i++) {
const attribute_name_info_entry& entry = kAttributeNameInfos[i];
if (entry.value <= DW_AT_loclists_base)
sAttributeNameInfos[entry.value] = entry;
else {
sAttributeNameInfos[DW_AT_loclists_base + 1
+ (entry.value - DW_AT_call_site_value)] = entry;
}
}
for (uint32 i = 0; kAttributeFormInfos[i].name != NULL; i++) {
const attribute_info_entry& entry = kAttributeFormInfos[i];
sAttributeFormInfos[entry.value] = entry;
}
}
} sInitAttributeInfos;
uint16
get_attribute_name_classes(uint32 name)
{
if (name <= DW_AT_loclists_base)
return sAttributeNameInfos[name].classes;
else if (name >= DW_AT_call_site_value
&& name <= DW_AT_all_source_call_sites) {
return sAttributeNameInfos[DW_AT_loclists_base + 1
+ (name - DW_AT_call_site_value)].classes;
}
return 0;
}
uint16
get_attribute_form_classes(uint32 form)
{
return form < kAttributeFormInfoCount
? sAttributeFormInfos[form].classes : 0;
}
uint8
get_attribute_class(uint32 name, uint32 form)
{
uint16 classes = get_attribute_name_classes(name)
& get_attribute_form_classes(form);
int clazz = 0;
while (classes != 0) {
classes >>= 1;
clazz++;
}
return clazz;
}
const char*
get_attribute_name_name(uint32 name)
{
if (name <= DW_AT_loclists_base)
return sAttributeNameInfos[name].name;
else if (name >= DW_AT_call_site_value
&& name <= DW_AT_all_source_call_sites) {
return sAttributeNameInfos[DW_AT_loclists_base + 1 +
(name - DW_AT_call_site_value)].name;
}
return NULL;
}
const char*
get_attribute_form_name(uint32 form)
{
return form < kAttributeFormInfoCount
? sAttributeFormInfos[form].name : NULL;
}
DebugInfoEntrySetter
get_attribute_name_setter(uint32 name)
{
return (name < kAttributeNameInfoCount)
? sAttributeNameInfos[name].setter : NULL;
}