/* * 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; }