From 256a67e6a5a07e37997d3a5ef64204a99b8e5a50 Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Mon, 25 Jan 2021 15:33:34 +0100 Subject: [PATCH] DWARF5 --- coregrind/m_debuginfo/d3basics.c | 99 ++++ coregrind/m_debuginfo/priv_d3basics.h | 195 +++++- coregrind/m_debuginfo/priv_readdwarf.h | 3 +- coregrind/m_debuginfo/priv_readdwarf3.h | 3 +- coregrind/m_debuginfo/readdwarf.c | 465 ++++++++++++--- coregrind/m_debuginfo/readdwarf3.c | 748 +++++++++++++++++++----- coregrind/m_debuginfo/readelf.c | 33 +- coregrind/m_debuginfo/readmacho.c | 14 +- 8 files changed, 1304 insertions(+), 256 deletions(-) diff --git a/coregrind/m_debuginfo/d3basics.c b/coregrind/m_debuginfo/d3basics.c index b6d13c118..e1127ffe2 100644 --- a/coregrind/m_debuginfo/d3basics.c +++ b/coregrind/m_debuginfo/d3basics.c @@ -128,6 +128,16 @@ const HChar* ML_(pp_DW_TAG) ( DW_TAG tag ) case DW_TAG_type_unit: return "DW_TAG_type_unit"; case DW_TAG_rvalue_reference_type: return "DW_TAG_rvalue_reference_type"; case DW_TAG_template_alias: return "DW_TAG_template_alias"; + /* DWARF 5. */ + case DW_TAG_coarray_type: return "DW_TAG_coarray_type"; + case DW_TAG_generic_subrange: return "DW_TAG_generic_subrange"; + case DW_TAG_dynamic_type: return "DW_TAG_dynamic_type"; + case DW_TAG_atomic_type: return "DW_TAG_atomic_type"; + case DW_TAG_call_site: return "DW_TAG_call_site"; + case DW_TAG_call_site_parameter: + return "DW_TAG_call_site_parameter"; + case DW_TAG_skeleton_unit: return "DW_TAG_skeleton_unit"; + case DW_TAG_immutable_type: return "DW_TAG_immutable_type"; /* SGI/MIPS Extensions. */ case DW_TAG_MIPS_loop: return "DW_TAG_MIPS_loop"; /* HP extensions. See: @@ -140,6 +150,16 @@ const HChar* ML_(pp_DW_TAG) ( DW_TAG tag ) case DW_TAG_class_template: return "DW_TAG_class_template"; case DW_TAG_GNU_BINCL: return "DW_TAG_GNU_BINCL"; case DW_TAG_GNU_EINCL: return "DW_TAG_GNU_EINCL"; + case DW_TAG_GNU_template_template_param: + return "DW_TAG_GNU_template_template_param"; + case DW_TAG_GNU_template_parameter_pack: + return"DW_TAG_GNU_template_parameter_pack"; + case DW_TAG_GNU_formal_parameter_pack: + return "DW_TAG_GNU_formal_parameter_pack"; + case DW_TAG_GNU_call_site: + return "DW_TAG_GNU_call_site"; + case DW_TAG_GNU_call_site_parameter: + return "DW_TAG_GNU_call_site_parameter"; /* Extensions for UPC. See: http://upc.gwu.edu/~upc. */ case DW_TAG_upc_shared_type: return "DW_TAG_upc_shared_type"; case DW_TAG_upc_strict_type: return "DW_TAG_upc_strict_type"; @@ -180,6 +200,27 @@ const HChar* ML_(pp_DW_FORM) ( DW_FORM form ) case DW_FORM_exprloc: return "DW_FORM_exprloc"; case DW_FORM_flag_present:return "DW_FORM_flag_present"; case DW_FORM_ref_sig8: return "DW_FORM_ref_sig8"; + case DW_FORM_strx: return "DW_FORM_strx"; + case DW_FORM_addrx: return "DW_FORM_addrx"; + case DW_FORM_ref_sup4: return "DW_FORM_ref_sup4"; + case DW_FORM_strp_sup: return "DW_FORM_strp_sup"; + case DW_FORM_data16: return "DW_FORM_data16"; + case DW_FORM_line_strp: return "DW_FORM_line_strp"; + case DW_FORM_implicit_const:return "DW_FORM_implicit_const"; + case DW_FORM_loclistx: return "DW_FORM_loclistx"; + case DW_FORM_rnglistx: return "DW_FORM_rnglistx"; + case DW_FORM_ref_sup8: return "DW_FORM_ref_sup8"; + case DW_FORM_strx1: return "DW_FORM_strx1"; + case DW_FORM_strx2: return "DW_FORM_strx2"; + case DW_FORM_strx3: return "DW_FORM_strx3"; + case DW_FORM_strx4: return "DW_FORM_strx4"; + case DW_FORM_addrx1: return "DW_FORM_addrx1"; + case DW_FORM_addrx2: return "DW_FORM_addrx2"; + case DW_FORM_addrx3: return "DW_FORM_addrx3"; + case DW_FORM_addrx4: return "DW_FORM_addrx4"; + /* GNU Debug Fission extensions. */ + case DW_FORM_GNU_addr_index:return "DW_FORM_GNU_addr_index"; + case DW_FORM_GNU_str_index:return "DW_FORM_GNU_str_index"; case DW_FORM_GNU_ref_alt:return "DW_FORM_GNU_ref_alt"; case DW_FORM_GNU_strp_alt:return "DW_FORM_GNU_strp_alt"; } @@ -286,6 +327,36 @@ const HChar* ML_(pp_DW_AT) ( DW_AT attr ) case DW_AT_const_expr: return "DW_AT_const_expr"; case DW_AT_enum_class: return "DW_AT_enum_class"; case DW_AT_linkage_name: return "DW_AT_linkage_name"; + /* DWARF 5 values. */ + case DW_AT_string_length_bit_size: return "DW_AT_string_length_bit_size"; + case DW_AT_string_length_byte_size: return "DW_AT_string_length_byte_size"; + case DW_AT_rank: return "DW_AT_rank"; + case DW_AT_str_offsets_base: return "DW_AT_str_offsets_base"; + case DW_AT_addr_base: return "DW_AT_addr_base"; + case DW_AT_rnglists_base: return "DW_AT_rnglists_base"; + case DW_AT_dwo_name: return "DW_AT_dwo_name"; + case DW_AT_reference: return "DW_AT_reference"; + case DW_AT_rvalue_reference: return "DW_AT_rvalue_reference"; + case DW_AT_macros: return "DW_AT_macros"; + case DW_AT_call_all_calls: return "DW_AT_call_all_calls"; + case DW_AT_call_all_source_calls: return "DW_AT_call_all_source_calls"; + case DW_AT_call_all_tail_calls: return "DW_AT_call_all_tail_calls"; + case DW_AT_call_return_pc: return "DW_AT_call_return_pc"; + case DW_AT_call_value: return "DW_AT_call_value"; + case DW_AT_call_origin: return "DW_AT_call_origin"; + case DW_AT_call_parameter: return "DW_AT_call_parameter"; + case DW_AT_call_pc: return "DW_AT_call_pc"; + case DW_AT_call_tail_call: return "DW_AT_call_tail_call"; + case DW_AT_call_target: return "DW_AT_call_target"; + case DW_AT_call_target_clobbered: return "DW_AT_call_target_clobbered"; + case DW_AT_call_data_location: return "DW_AT_call_data_location"; + case DW_AT_call_data_value: return "DW_AT_call_data_value"; + case DW_AT_noreturn: return "DW_AT_noreturn"; + case DW_AT_alignment: return "DW_AT_alignment"; + case DW_AT_export_symbols: return "DW_AT_export_symbols"; + case DW_AT_deleted: return "DW_AT_deleted"; + case DW_AT_defaulted: return "DW_AT_defaulted"; + case DW_AT_loclists_base: return "DW_AT_loclists_base"; /* SGI/MIPS extensions. */ /* case DW_AT_MIPS_fde: return "DW_AT_MIPS_fde"; */ /* DW_AT_MIPS_fde == DW_AT_HP_unmodifiable */ @@ -322,8 +393,36 @@ const HChar* ML_(pp_DW_AT) ( DW_AT attr ) case DW_AT_body_begin: return "DW_AT_body_begin"; case DW_AT_body_end: return "DW_AT_body_end"; case DW_AT_GNU_vector: return "DW_AT_GNU_vector"; + case DW_AT_GNU_guarded_by: return "DW_AT_GNU_guarded_by"; + case DW_AT_GNU_pt_guarded_by: return "DW_AT_GNU_pt_guarded_by"; + case DW_AT_GNU_guarded: return "DW_AT_GNU_guarded"; + case DW_AT_GNU_pt_guarded: return "DW_AT_GNU_pt_guarded"; + case DW_AT_GNU_locks_excluded: return "DW_AT_GNU_locks_excluded"; + case DW_AT_GNU_exclusive_locks_required: return "DW_AT_GNU_exclusive_locks_required"; + case DW_AT_GNU_shared_locks_required: return "DW_AT_GNU_shared_locks_required"; + case DW_AT_GNU_odr_signature: return "DW_AT_GNU_odr_signature"; + case DW_AT_GNU_template_name: return "DW_AT_GNU_template_name"; + case DW_AT_GNU_call_site_value: return "DW_AT_GNU_call_site_value"; + case DW_AT_GNU_call_site_data_value: return "DW_AT_GNU_call_site_data_value"; + case DW_AT_GNU_call_site_target: return "DW_AT_GNU_call_site_target"; + case DW_AT_GNU_call_site_target_clobbered: return "DW_AT_GNU_call_site_target_clobbered"; + case DW_AT_GNU_tail_call: return "DW_AT_GNU_tail_call"; case DW_AT_GNU_all_tail_call_sites: return "DW_AT_GNU_all_tail_call_sites"; case DW_AT_GNU_all_call_sites: return "DW_AT_GNU_all_call_sites"; + case DW_AT_GNU_all_source_call_sites: return "DW_AT_GNU_all_source_call_sites"; + case DW_AT_GNU_locviews: return "DW_AT_GNU_locviews"; + case DW_AT_GNU_entry_view: return "DW_AT_GNU_entry_view"; + case DW_AT_GNU_macros: return "DW_AT_GNU_macros"; + case DW_AT_GNU_deleted: return "DW_AT_GNU_deleted"; + case DW_AT_GNU_dwo_name: return "DW_AT_GNU_dwo_name"; + case DW_AT_GNU_dwo_id: return "DW_AT_GNU_dwo_id"; + case DW_AT_GNU_ranges_base: return "DW_AT_GNU_ranges_base"; + case DW_AT_GNU_addr_base: return "DW_AT_GNU_addr_base"; + case DW_AT_GNU_pubnames: return "DW_AT_GNU_pubnames"; + case DW_AT_GNU_pubtypes: return "DW_AT_GNU_pubtypes"; + case DW_AT_GNU_numerator: return "DW_AT_GNU_numerator"; + case DW_AT_GNU_denominator: return "DW_AT_GNU_denominator"; + case DW_AT_GNU_bias: return "DW_AT_GNU_bias"; /* VMS extensions. */ case DW_AT_VMS_rtnbeg_pd_address: return "DW_AT_VMS_rtnbeg_pd_address"; /* UPC extension. */ diff --git a/coregrind/m_debuginfo/priv_d3basics.h b/coregrind/m_debuginfo/priv_d3basics.h index b60e3e8eb..9d825e39e 100644 --- a/coregrind/m_debuginfo/priv_d3basics.h +++ b/coregrind/m_debuginfo/priv_d3basics.h @@ -108,6 +108,15 @@ typedef enum DW_TAG_type_unit = 0x41, DW_TAG_rvalue_reference_type = 0x42, DW_TAG_template_alias = 0x43, + /* DWARF 5. */ + DW_TAG_coarray_type = 0x44, + DW_TAG_generic_subrange = 0x45, + DW_TAG_dynamic_type = 0x46, + DW_TAG_atomic_type = 0x47, + DW_TAG_call_site = 0x48, + DW_TAG_call_site_parameter = 0x49, + DW_TAG_skeleton_unit = 0x4a, + DW_TAG_immutable_type = 0x4b, /* SGI/MIPS Extensions. */ DW_TAG_MIPS_loop = 0x4081, /* HP extensions. See: ftp://ftp.hp.com/pub/lang/tools/WDB/wdb-4.0.tar.gz . */ @@ -118,6 +127,11 @@ typedef enum DW_TAG_class_template = 0x4103, /* For C++. */ DW_TAG_GNU_BINCL = 0x4104, DW_TAG_GNU_EINCL = 0x4105, + DW_TAG_GNU_template_template_param = 0x4106, + DW_TAG_GNU_template_parameter_pack = 0x4107, + DW_TAG_GNU_formal_parameter_pack = 0x4108, + DW_TAG_GNU_call_site = 0x4109, + DW_TAG_GNU_call_site_parameter = 0x410a, /* Extensions for UPC. See: http://upc.gwu.edu/~upc. */ DW_TAG_upc_shared_type = 0x8765, DW_TAG_upc_strict_type = 0x8766, @@ -164,13 +178,23 @@ typedef enum dwarf_source_language DW_LANG_D = 0x0013, /* DWARF 4. */ DW_LANG_Python = 0x0014, - /* DWARF 5-pre. Only what GCC already outputs. */ + /* DWARF 5. */ DW_LANG_Go = 0x0016, + DW_LANG_Modula3 = 0x0017, + DW_LANG_Haskell = 0x0018, + DW_LANG_C_plus_plus_03 = 0x0019, DW_LANG_C_plus_plus_11 = 0x001a, + DW_LANG_OCaml = 0x001b, + DW_LANG_Rust = 0x001c, DW_LANG_C11 = 0x001d, + DW_LANG_Swift = 0x001e, + DW_LANG_Julia = 0x001f, + DW_LANG_Dylan = 0x0020, DW_LANG_C_plus_plus_14 = 0x0021, DW_LANG_Fortran03 = 0x0022, DW_LANG_Fortran08 = 0x0023, + DW_LANG_RenderScript = 0x0024, + DW_LANG_BLISS = 0x0025, /* MIPS. */ DW_LANG_Mips_Assembler = 0x8001, /* UPC. */ @@ -207,6 +231,28 @@ typedef enum DW_FORM_exprloc = 0x18, DW_FORM_flag_present = 0x19, DW_FORM_ref_sig8 = 0x20, + /* DWARF 5 values. */ + DW_FORM_strx = 0x1a, + DW_FORM_addrx = 0x1b, + DW_FORM_ref_sup4 = 0x1c, + DW_FORM_strp_sup = 0x1d, + DW_FORM_data16 = 0x1e, + DW_FORM_line_strp = 0x1f, + DW_FORM_implicit_const = 0x21, + DW_FORM_loclistx = 0x22, + DW_FORM_rnglistx = 0x23, + DW_FORM_ref_sup8 = 0x24, + DW_FORM_strx1 = 0x25, + DW_FORM_strx2 = 0x26, + DW_FORM_strx3 = 0x27, + DW_FORM_strx4 = 0x28, + DW_FORM_addrx1 = 0x29, + DW_FORM_addrx2 = 0x2a, + DW_FORM_addrx3 = 0x2b, + DW_FORM_addrx4 = 0x2c, + /* GNU Debug Fission extensions. */ + DW_FORM_GNU_addr_index = 0x1f01, + DW_FORM_GNU_str_index = 0x1f02, /* Extensions for DWZ multifile. See http://www.dwarfstd.org/ShowIssue.php?issue=120604.1&type=open . */ DW_FORM_GNU_ref_alt = 0x1f20, @@ -314,6 +360,36 @@ typedef enum DW_AT_const_expr = 0x6c, DW_AT_enum_class = 0x6d, DW_AT_linkage_name = 0x6e, + DW_AT_string_length_bit_size = 0x6f, + DW_AT_string_length_byte_size = 0x70, + DW_AT_rank = 0x71, + DW_AT_str_offsets_base = 0x72, + DW_AT_addr_base = 0x73, + DW_AT_rnglists_base = 0x74, + /* 0x75 reserved. */ + DW_AT_dwo_name = 0x76, + DW_AT_reference = 0x77, + DW_AT_rvalue_reference = 0x78, + DW_AT_macros = 0x79, + DW_AT_call_all_calls = 0x7a, + DW_AT_call_all_source_calls = 0x7b, + DW_AT_call_all_tail_calls = 0x7c, + DW_AT_call_return_pc = 0x7d, + DW_AT_call_value = 0x7e, + DW_AT_call_origin = 0x7f, + DW_AT_call_parameter = 0x80, + DW_AT_call_pc = 0x81, + DW_AT_call_tail_call = 0x82, + DW_AT_call_target = 0x83, + DW_AT_call_target_clobbered = 0x84, + DW_AT_call_data_location = 0x85, + DW_AT_call_data_value = 0x86, + DW_AT_noreturn = 0x87, + DW_AT_alignment = 0x88, + DW_AT_export_symbols = 0x89, + DW_AT_deleted = 0x8a, + DW_AT_defaulted = 0x8b, + DW_AT_loclists_base = 0x8c, /* SGI/MIPS extensions. */ DW_AT_MIPS_fde = 0x2001, DW_AT_MIPS_loop_begin = 0x2002, @@ -349,8 +425,39 @@ typedef enum DW_AT_body_begin = 0x2105, DW_AT_body_end = 0x2106, DW_AT_GNU_vector = 0x2107, + DW_AT_GNU_guarded_by = 0x2108, + DW_AT_GNU_pt_guarded_by = 0x2109, + DW_AT_GNU_guarded = 0x210a, + DW_AT_GNU_pt_guarded = 0x210b, + DW_AT_GNU_locks_excluded = 0x210c, + DW_AT_GNU_exclusive_locks_required = 0x210d, + DW_AT_GNU_shared_locks_required = 0x210e, + DW_AT_GNU_odr_signature = 0x210f, + DW_AT_GNU_template_name = 0x2110, + DW_AT_GNU_call_site_value = 0x2111, + DW_AT_GNU_call_site_data_value = 0x2112, + DW_AT_GNU_call_site_target = 0x2113, + DW_AT_GNU_call_site_target_clobbered = 0x2114, + DW_AT_GNU_tail_call = 0x2115, DW_AT_GNU_all_tail_call_sites = 0x2116, DW_AT_GNU_all_call_sites = 0x2117, + DW_AT_GNU_all_source_call_sites = 0x2118, + DW_AT_GNU_locviews = 0x2137, + DW_AT_GNU_entry_view = 0x2138, + DW_AT_GNU_macros = 0x2119, + DW_AT_GNU_deleted = 0x211a, + /* GNU Debug Fission extensions. */ + DW_AT_GNU_dwo_name = 0x2130, + DW_AT_GNU_dwo_id = 0x2131, + DW_AT_GNU_ranges_base = 0x2132, + DW_AT_GNU_addr_base = 0x2133, + DW_AT_GNU_pubnames = 0x2134, + DW_AT_GNU_pubtypes = 0x2135, + /* https://gcc.gnu.org/wiki/DW_AT_GNU_numerator_denominator */ + DW_AT_GNU_numerator = 0x2303, + DW_AT_GNU_denominator = 0x2304, + /* https://gcc.gnu.org/wiki/DW_AT_GNU_bias */ + DW_AT_GNU_bias = 0x2305, /* VMS extensions. */ DW_AT_VMS_rtnbeg_pd_address = 0x2201, /* UPC extension. */ @@ -387,6 +494,9 @@ typedef enum DW_ATE_decimal_float = 0xf, /* DWARF 4. */ DW_ATE_UTF = 0x10, + /* DWARF 5. */ + DW_ATE_UCS = 0x11, + DW_ATE_ASCII = 0x12, /* HP extensions. */ DW_ATE_HP_float80 = 0x80, /* Floating-point (80 bit). */ DW_ATE_HP_complex_float80 = 0x81, /* Complex floating-point (80 bit). */ @@ -558,8 +668,35 @@ typedef enum /* DWARF 4 extensions. */ DW_OP_implicit_value = 0x9e, DW_OP_stack_value = 0x9f, + /* DWARF 5 extensions. */ + DW_OP_implicit_pointer = 0xa0, + DW_OP_addrx = 0xa1, + DW_OP_constx = 0xa2, + DW_OP_entry_value = 0xa3, + DW_OP_const_type = 0xa4, + DW_OP_regval_type = 0xa5, + DW_OP_deref_type = 0xa6, + DW_OP_xderef_type = 0xa7, + DW_OP_convert = 0xa8, + DW_OP_reinterpret = 0xa9, /* GNU extensions. */ DW_OP_GNU_push_tls_address = 0xe0, + DW_OP_GNU_uninit = 0xf0, + DW_OP_GNU_encoded_addr = 0xf1, + DW_OP_GNU_implicit_pointer = 0xf2, + DW_OP_GNU_entry_value = 0xf3, + DW_OP_GNU_const_type = 0xf4, + DW_OP_GNU_regval_type = 0xf5, + DW_OP_GNU_deref_type = 0xf6, + DW_OP_GNU_convert = 0xf7, + DW_OP_GNU_reinterpret = 0xf9, + DW_OP_GNU_parameter_ref = 0xfa, + /* GNU Debug Fission extensions. */ + DW_OP_GNU_addr_index = 0xfb, + DW_OP_GNU_const_index = 0xfc, + /* The GNU variable value extension. + See http://dwarfstd.org/ShowIssue.php?issue=161109.2 . */ + DW_OP_GNU_variable_value = 0xfd, /* HP extensions. */ DW_OP_HP_unknown = 0xe0, /* Ouch, the same as GNU_push_tls_address. */ DW_OP_HP_is_value = 0xe1, @@ -571,6 +708,62 @@ typedef enum } DW_OP; +typedef enum + { + DW_UT_compile = 0x01, + DW_UT_type = 0x02, + DW_UT_partial = 0x03, + DW_UT_skeleton = 0x04, + DW_UT_split_compile = 0x05, + DW_UT_split_type = 0x06, + + DW_UT_lo_user = 0x80, + DW_UT_hi_user = 0xff + } + DW_UT; + +typedef enum + { + DW_LNCT_path = 0x1, + DW_LNCT_directory_index = 0x2, + DW_LNCT_timestamp = 0x3, + DW_LNCT_size = 0x4, + DW_LNCT_MD5 = 0x5, + + DW_LNCT_lo_user = 0x2000, + DW_LNCT_hi_user = 0x3fff + } + DW_LNCT; + +typedef enum + { + DW_RLE_end_of_list = 0x00, + DW_RLE_base_addressx = 0x01, + DW_RLE_startx_endx = 0x02, + DW_RLE_startx_length = 0x03, + DW_RLE_offset_pair = 0x04, + DW_RLE_base_address = 0x05, + DW_RLE_start_end = 0x06, + DW_RLE_start_length = 0x07 + } + DW_RLE; + +typedef enum + { + DW_LLE_end_of_list = 0x00, + DW_LLE_base_addressx = 0x01, + DW_LLE_startx_endx = 0x02, + DW_LLE_startx_length = 0x03, + DW_LLE_offset_pair = 0x04, + DW_LLE_default_location = 0x05, + DW_LLE_base_address = 0x06, + DW_LLE_start_end = 0x07, + DW_LLE_start_length = 0x08, + + DW_LLE_GNU_view_pair = 0x09 + } + DW_LLE; + const HChar* ML_(pp_DW_children) ( DW_children hashch ); const HChar* ML_(pp_DW_TAG) ( DW_TAG tag ); const HChar* ML_(pp_DW_FORM) ( DW_FORM form ); diff --git a/coregrind/m_debuginfo/priv_readdwarf.h b/coregrind/m_debuginfo/priv_readdwarf.h index 1e3f24c2a..302266924 100644 --- a/coregrind/m_debuginfo/priv_readdwarf.h +++ b/coregrind/m_debuginfo/priv_readdwarf.h @@ -50,7 +50,8 @@ void ML_(read_debuginfo_dwarf3) DiSlice escn_debug_abbv, /* .debug_abbrev */ DiSlice escn_debug_line, /* .debug_line */ DiSlice escn_debug_str, /* .debug_str */ - DiSlice escn_debug_str_alt ); /* .debug_str */ + DiSlice escn_debug_str_alt, /* .debug_str */ + DiSlice escn_debug_line_str );/* .debug_line_str */ /* -------------------- DWARF1 reader diff --git a/coregrind/m_debuginfo/priv_readdwarf3.h b/coregrind/m_debuginfo/priv_readdwarf3.h index 1a5bd61c3..f6d1dd1ee 100644 --- a/coregrind/m_debuginfo/priv_readdwarf3.h +++ b/coregrind/m_debuginfo/priv_readdwarf3.h @@ -45,9 +45,10 @@ ML_(new_dwarf3_reader) ( DiSlice escn_debug_info, DiSlice escn_debug_types, DiSlice escn_debug_abbv, DiSlice escn_debug_line, DiSlice escn_debug_str, DiSlice escn_debug_ranges, + DiSlice escn_debug_rnglists, DiSlice escn_debug_loclists, DiSlice escn_debug_loc, DiSlice escn_debug_info_alt, DiSlice escn_debug_abbv_alt, DiSlice escn_debug_line_alt, - DiSlice escn_debug_str_alt + DiSlice escn_debug_str_alt, DiSlice escn_debug_line_str ); #endif /* ndef __PRIV_READDWARF3_H */ diff --git a/coregrind/m_debuginfo/readdwarf.c b/coregrind/m_debuginfo/readdwarf.c index 5701c504b..88d5d99f1 100644 --- a/coregrind/m_debuginfo/readdwarf.c +++ b/coregrind/m_debuginfo/readdwarf.c @@ -322,6 +322,123 @@ void process_extended_line_op( struct _DebugInfo* di, //////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////// +static +HChar * get_line_str (struct _DebugInfo* di, const UnitInfo* ui, + DiCursor *data, const UInt form, + DiCursor debugstr_img, DiCursor debuglinestr_img) +{ + HChar *str = NULL; + switch (form) { + case DW_FORM_string: + str = ML_(cur_step_strdup)(data, "di.gls.string"); + break; + case DW_FORM_strp: + if (!ui->dw64) + str = ML_(cur_read_strdup)(ML_(cur_plus)(debugstr_img, + ML_(cur_step_UInt)(data)), + "di.gls.strp.dw32"); + else + str = ML_(cur_read_strdup)(ML_(cur_plus)(debugstr_img, + ML_(cur_step_ULong)(data)), + "di.gls.strp.dw64"); + break; + case DW_FORM_line_strp: + if (!ui->dw64) + str = ML_(cur_read_strdup)(ML_(cur_plus)(debuglinestr_img, + ML_(cur_step_UInt)(data)), + "di.gls.line_strp.dw32"); + else + str = ML_(cur_read_strdup)(ML_(cur_plus)(debuglinestr_img, + ML_(cur_step_ULong)(data)), + "di.gls.line_strp.dw64"); + break; + default: + ML_(symerr)(di, True, + "Unknown path string FORM in .debug_line"); + break; + } + return str; +} + +static +Int get_line_ndx (struct _DebugInfo* di, + DiCursor *data, const UInt form) +{ + Int res = 0; + switch (form) { + case DW_FORM_data1: + res = ML_(cur_step_UChar)(data); + break; + case DW_FORM_data2: + res = ML_(cur_step_UShort)(data); + break; + case DW_FORM_udata: + res = step_leb128U(data); + break; + default: + ML_(symerr)(di, True, + "Unknown directory_index value FORM in .debug_line"); + break; + } + return res; +} + +static +DiCursor skip_line_form (struct _DebugInfo* di, const UnitInfo* ui, + DiCursor d, const UInt form) +{ + switch (form) { + case DW_FORM_block: { + ULong len = step_leb128U(&d); + d = ML_(cur_plus)(d, len); + break; + } + case DW_FORM_block1: + d = ML_(cur_plus)(d, ML_(cur_read_UChar)(d) + 1); + break; + case DW_FORM_block2: + d = ML_(cur_plus)(d, ML_(cur_read_UShort)(d) + 2); + break; + case DW_FORM_block4: + d = ML_(cur_plus)(d, ML_(cur_read_UInt)(d) + 4); + break; + case DW_FORM_flag: + case DW_FORM_data1: + d = ML_(cur_plus)(d, 1); + break; + case DW_FORM_data2: + d = ML_(cur_plus)(d, 2); + break; + case DW_FORM_data4: + d = ML_(cur_plus)(d, 4); + break; + case DW_FORM_data8: + d = ML_(cur_plus)(d, 8); + break; + case DW_FORM_data16: + d = ML_(cur_plus)(d, 16); + break; + case DW_FORM_string: + d = ML_(cur_plus)(d, ML_(cur_strlen)(d) + 1); + break; + case DW_FORM_strp: + case DW_FORM_line_strp: + case DW_FORM_sec_offset: + d = ML_(cur_plus)(d, ui->dw64 ? 8 : 4); + break; + case DW_FORM_udata: + (void)step_leb128U(&d); + break; + case DW_FORM_sdata: + (void)step_leb128S(&d); + break; + default: + ML_(symerr)(di, True, "Unknown FORM in .debug_line"); + break; + } + return d; +} + /* read a .debug_line section block for a compilation unit * * Input: - theBlock must point to the start of the block @@ -335,7 +452,9 @@ static void read_dwarf2_lineblock ( struct _DebugInfo* di, const UnitInfo* ui, DiCursor theBlock, /* IMAGE */ - Int noLargerThan ) + Int noLargerThan, + DiCursor debugstr_img, + DiCursor debuglinestr_img) { Int i; DebugLineInfo info; @@ -348,6 +467,9 @@ void read_dwarf2_lineblock ( struct _DebugInfo* di, DiCursor external = theBlock; DiCursor data = theBlock; + UChar p_ndx = 0, d_ndx = 0; /* DWARF5 path and dir index. */ + UInt forms[256]; /* DWARF5 forms. */ + /* fndn_ix_xa is an xarray of fndn_ix (indexes in di->fndnpool) which are build from file names harvested from the DWARF2 info. Entry [0] is the "null" pool index and is never referred to @@ -372,17 +494,6 @@ void read_dwarf2_lineblock ( struct _DebugInfo* di, fndn_ix_xa = VG_(newXA) (ML_(dinfo_zalloc), "di.rd2l.2", ML_(dinfo_free), sizeof(UInt) ); - /* DWARF2 starts numbering filename entries at 1, so we need to - add a dummy zeroth entry to the table. */ - fndn_ix = 0; // 0 is the "null" index in a fixed pool. - VG_(addToXA) (fndn_ix_xa, &fndn_ix); - - if (ML_(cur_is_valid)(ui->compdir)) - dirname = ML_(addStrFromCursor)(di, ui->compdir); - else - dirname = ML_(addStr)(di, ".", -1); - VG_(addToXA) (dirname_xa, &dirname); - info.li_length = step_initial_length_field( &external, &is64 ); if (di->ddump_line) VG_(printf)(" Length: %llu\n", @@ -402,13 +513,19 @@ void read_dwarf2_lineblock ( struct _DebugInfo* di, VG_(printf)(" DWARF Version: %d\n", (Int)info.li_version); - if (info.li_version != 2 && info.li_version != 3 && info.li_version != 4) { + if (info.li_version != 2 && info.li_version != 3 && info.li_version != 4 + && info.li_version != 5) { ML_(symerr)(di, True, - "Only DWARF version 2, 3 and 4 line info " + "Only DWARF version 2, 3, 4 and 5 line info " "is currently supported."); goto out; } + if (info.li_version >= 5) { + /* UChar addr_size = */ ML_(cur_step_UChar)(&external); + /* UChar seg_size = */ ML_(cur_step_UChar)(&external); + } + info.li_header_length = is64 ? ML_(cur_step_ULong)(&external) : (ULong)(ML_(cur_step_UInt)(&external)); if (di->ddump_line) @@ -485,60 +602,141 @@ void read_dwarf2_lineblock ( struct _DebugInfo* di, /* skip over "standard_opcode_lengths" */ data = ML_(cur_plus)(standard_opcodes, info.li_opcode_base - 1); - /* Read the contents of the Directory table. */ - if (di->ddump_line) - VG_(printf)(" The Directory Table%s\n", - ML_(cur_read_UChar)(data) == 0 ? " is empty." : ":" ); - - while (ML_(cur_read_UChar)(data) != 0) { + if (ML_(cur_is_valid)(ui->compdir)) + dirname = ML_(addStrFromCursor)(di, ui->compdir); + else + dirname = ML_(addStr)(di, ".", -1); - HChar* data_str = ML_(cur_read_strdup)(data, "di.rd2l.1"); + if (info.li_version < 5) { + /* Read the contents of the Directory table. */ if (di->ddump_line) - VG_(printf)(" %s\n", data_str); - - /* If data[0] is '/', then 'data' is an absolute path and we - don't mess with it. Otherwise, construct the - path 'ui->compdir' ++ "/" ++ 'data'. */ - - if (data_str[0] != '/' - /* not an absolute path */ - && ML_(cur_is_valid)(ui->compdir) - /* actually got something sensible for compdir */ - && ML_(cur_strlen)(ui->compdir)) - { - HChar* compdir_str = ML_(cur_read_strdup)(ui->compdir, "di.rd2l.1b"); - SizeT len = VG_(strlen)(compdir_str) + 1 + VG_(strlen)(data_str); - HChar *buf = ML_(dinfo_zalloc)("di.rd2l.1c", len + 1); - - VG_(strcpy)(buf, compdir_str); - VG_(strcat)(buf, "/"); - VG_(strcat)(buf, data_str); - - dirname = ML_(addStr)(di, buf, len); - VG_(addToXA) (dirname_xa, &dirname); - if (0) VG_(printf)("rel path %s\n", buf); - ML_(dinfo_free)(compdir_str); - ML_(dinfo_free)(buf); - } else { - /* just use 'data'. */ - dirname = ML_(addStr)(di,data_str,-1); - VG_(addToXA) (dirname_xa, &dirname); - if (0) VG_(printf)("abs path %s\n", data_str); + VG_(printf)("The Directory Table%s\n", + ML_(cur_read_UChar)(data) == 0 ? " is empty." : ":" ); + + /* DWARF2 starts numbering filename entries at 1, so we need to + add a dummy zeroth entry to the table. */ + fndn_ix = 0; // 0 is the "null" index in a fixed pool. + VG_(addToXA) (fndn_ix_xa, &fndn_ix); + VG_(addToXA) (dirname_xa, &dirname); + + while (ML_(cur_read_UChar)(data) != 0) { + + HChar* data_str = ML_(cur_read_strdup)(data, "di.rd2l.1"); + if (di->ddump_line) + VG_(printf)(" %s\n", data_str); + + /* If data[0] is '/', then 'data' is an absolute path and we + don't mess with it. Otherwise, construct the + path 'ui->compdir' ++ "/" ++ 'data'. */ + + if (data_str[0] != '/' + /* not an absolute path */ + && ML_(cur_is_valid)(ui->compdir) + /* actually got something sensible for compdir */ + && ML_(cur_strlen)(ui->compdir)) + { + HChar* compdir_str = ML_(cur_read_strdup)(ui->compdir, + "di.rd2l.1b"); + SizeT len = VG_(strlen)(compdir_str) + 1 + VG_(strlen)(data_str); + HChar *buf = ML_(dinfo_zalloc)("di.rd2l.1c", len + 1); + + VG_(strcpy)(buf, compdir_str); + VG_(strcat)(buf, "/"); + VG_(strcat)(buf, data_str); + + dirname = ML_(addStr)(di, buf, len); + VG_(addToXA) (dirname_xa, &dirname); + if (0) VG_(printf)("rel path %s\n", buf); + ML_(dinfo_free)(compdir_str); + ML_(dinfo_free)(buf); + } else { + /* just use 'data'. */ + dirname = ML_(addStr)(di,data_str,-1); + VG_(addToXA) (dirname_xa, &dirname); + if (0) VG_(printf)("abs path %s\n", data_str); + } + + data = ML_(cur_plus)(data, VG_(strlen)(data_str) + 1); + ML_(dinfo_free)(data_str); } - data = ML_(cur_plus)(data, VG_(strlen)(data_str) + 1); - ML_(dinfo_free)(data_str); - } + if (di->ddump_line) + VG_(printf)("\n"); - if (di->ddump_line) - VG_(printf)("\n"); + if (ML_(cur_read_UChar)(data) != 0) { + ML_(symerr)(di, True, + "can't find NUL at end of DWARF2 directory table"); + goto out; + } + data = ML_(cur_plus)(data, 1); + } else { + UInt directories_count; + UChar directory_entry_format_count = ML_(cur_step_UChar)(&data); + UInt n; + for (n = 0; n < directory_entry_format_count; n++) { + UInt lnct = step_leb128U(&data); + UInt form = step_leb128U(&data); + if (lnct == DW_LNCT_path) + p_ndx = n; + forms[n] = form; + } + directories_count = step_leb128U(&data); + /* Read the contents of the Directory table. */ + if (di->ddump_line) + VG_(printf)(" dwarf The Directory Table%s\n", + directories_count == 0 ? " is empty." : ":" ); + + for (n = 0; n < directories_count; n++) { + UInt f; + for (f = 0; f < directory_entry_format_count; f++) { + UInt form = forms[f]; + if (f == p_ndx) { + HChar *data_str = get_line_str (di, ui, &data, form, + debugstr_img, + debuglinestr_img); + if (di->ddump_line) + VG_(printf)(" %s\n", data_str); + + /* If data[0] is '/', then 'data' is an absolute path and we + don't mess with it. Otherwise, construct the + path 'ui->compdir' ++ "/" ++ 'data'. */ + + if (data_str[0] != '/' + /* not an absolute path */ + && ML_(cur_is_valid)(ui->compdir) + /* actually got something sensible for compdir */ + && ML_(cur_strlen)(ui->compdir)) + { + HChar* compdir_str = ML_(cur_read_strdup)(ui->compdir, + "di.rd2l.1b"); + SizeT len = VG_(strlen)(compdir_str) + 1 + + VG_(strlen)(data_str); + HChar *buf = ML_(dinfo_zalloc)("di.rd2l.1c", len + 1); + + VG_(strcpy)(buf, compdir_str); + VG_(strcat)(buf, "/"); + VG_(strcat)(buf, data_str); + + dirname = ML_(addStr)(di, buf, len); + VG_(addToXA) (dirname_xa, &dirname); + if (0) VG_(printf)("rel path %s\n", buf); + ML_(dinfo_free)(compdir_str); + ML_(dinfo_free)(buf); + } else { + /* just use 'data'. */ + dirname = ML_(addStr)(di,data_str,-1); + VG_(addToXA) (dirname_xa, &dirname); + if (0) VG_(printf)("abs path %s\n", data_str); + } - if (ML_(cur_read_UChar)(data) != 0) { - ML_(symerr)(di, True, - "can't find NUL at end of DWARF2 directory table"); - goto out; + ML_(dinfo_free)(data_str); + + } else { + data = skip_line_form (di, ui, data, form); + } + } + } } - data = ML_(cur_plus)(data, 1); /* Read the contents of the File Name table. This produces a bunch of fndn_ix in fndn_ix_xa. */ @@ -547,33 +745,76 @@ void read_dwarf2_lineblock ( struct _DebugInfo* di, VG_(printf)(" Entry Dir Time Size Name\n"); } - i = 1; - while (ML_(cur_read_UChar)(data) != 0) { - HChar* name = ML_(cur_step_strdup)(&data, "di.rd2l.2"); - Int diridx = step_leb128U(&data); - Int uu_time = step_leb128U(&data); /* unused */ - Int uu_size = step_leb128U(&data); /* unused */ + if (info.li_version < 5) { + i = 1; + while (ML_(cur_read_UChar)(data) != 0) { + HChar* name = ML_(cur_step_strdup)(&data, "di.rd2l.2"); + Int diridx = step_leb128U(&data); + Int uu_time = step_leb128U(&data); /* unused */ + Int uu_size = step_leb128U(&data); /* unused */ + + dirname = safe_dirname_ix( dirname_xa, diridx ); + fndn_ix = ML_(addFnDn) (di, name, dirname); + VG_(addToXA) (fndn_ix_xa, &fndn_ix); + if (0) VG_(printf)("file %s diridx %d\n", name, diridx ); + if (di->ddump_line) + VG_(printf)(" %d\t%d\t%d\t%d\t%s\n", + i, diridx, uu_time, uu_size, name); + i++; + ML_(dinfo_free)(name); + } - dirname = safe_dirname_ix( dirname_xa, diridx ); - fndn_ix = ML_(addFnDn) (di, name, dirname); - VG_(addToXA) (fndn_ix_xa, &fndn_ix); - if (0) VG_(printf)("file %s diridx %d\n", name, diridx ); if (di->ddump_line) - VG_(printf)(" %d\t%d\t%d\t%d\t%s\n", - i, diridx, uu_time, uu_size, name); - i++; - ML_(dinfo_free)(name); - } + VG_(printf)("\n"); - if (di->ddump_line) - VG_(printf)("\n"); + if (ML_(cur_read_UChar)(data) != 0) { + ML_(symerr)(di, True, + "can't find NUL at end of DWARF2 file name table"); + goto out; + } + data = ML_(cur_plus)(data, 1); + } else { + UInt file_names_count; + UChar file_names_entry_format_count = ML_(cur_step_UChar)(&data); + UInt n; + for (n = 0; n < file_names_entry_format_count; n++) { + UInt lnct = step_leb128U(&data); + UInt form = step_leb128U(&data); + if (lnct == DW_LNCT_path) + p_ndx = n; + if (lnct == DW_LNCT_directory_index) + d_ndx = n; + forms[n] = form; + } + file_names_count = step_leb128U(&data); + for (n = 0; n < file_names_count; n++) { + UInt f; + HChar* name = NULL; + Int diridx = 0; + for (f = 0; f < file_names_entry_format_count; f++) { + UInt form = forms[f]; + if (f == p_ndx) + name = get_line_str (di, ui, &data, form, + debugstr_img, debuglinestr_img); + else if (n == d_ndx) + diridx = get_line_ndx (di, &data, form); + else + data = skip_line_form (di, ui, data, form); + } - if (ML_(cur_read_UChar)(data) != 0) { - ML_(symerr)(di, True, - "can't find NUL at end of DWARF2 file name table"); - goto out; + dirname = safe_dirname_ix( dirname_xa, diridx ); + fndn_ix = ML_(addFnDn) (di, name, dirname); + VG_(addToXA) (fndn_ix_xa, &fndn_ix); + if (0) VG_(printf)("file %s diridx %d\n", name, diridx ); + if (di->ddump_line) + VG_(printf)(" %u\t%d\t%d\t%d\t%s\n", + n, diridx, 0, 0, name); + ML_(dinfo_free)(name); + } + + if (di->ddump_line) + VG_(printf)("\n"); } - data = ML_(cur_plus)(data, 1); if (di->ddump_line) VG_(printf)(" Line Number Statements:\n"); @@ -772,9 +1013,12 @@ static DiCursor lookup_abbrev( DiCursor p, ULong acode ) (void)step_leb128U(&p); /* skip tag */ p = ML_(cur_plus)(p,1); /* skip has_children flag */ ULong name; + ULong form; do { name = step_leb128U(&p); /* name */ - (void)step_leb128U(&p); /* form */ + form = step_leb128U(&p); /* form */ + if (form == 0x21) /* DW_FORM_implicit_const */ + step_leb128S(&p); } while (name != 0); /* until name == form == 0 */ } @@ -804,13 +1048,14 @@ void read_unitinfo_dwarf2( /*OUT*/UnitInfo* ui, DiCursor unitblock_img, DiCursor debugabbrev_img, DiCursor debugstr_img, - DiCursor debugstr_alt_img ) + DiCursor debugstr_alt_img, + DiCursor debuglinestr_img) { UInt acode, abcode; ULong atoffs, blklen; UShort ver; - UChar addr_size; + UChar addr_size = 0; DiCursor p = unitblock_img; DiCursor end_img; DiCursor abbrev_img; @@ -823,16 +1068,25 @@ void read_unitinfo_dwarf2( /*OUT*/UnitInfo* ui, /* This block length */ blklen = step_initial_length_field( &p, &ui->dw64 ); - /* version should be 2, 3 or 4 */ + /* version should be 2, 3, 4 or 5 */ ver = ML_(cur_step_UShort)(&p); - /* get offset in abbrev */ - atoffs = ui->dw64 ? ML_(cur_step_ULong)(&p) - : (ULong)(ML_(cur_step_UInt)(&p)); + if (ver >= 5) + /* unit_type for DWARF5 */ + /* unit_type = */ ML_(cur_step_UChar)(&p); + else + /* get offset in abbrev */ + atoffs = ui->dw64 ? ML_(cur_step_ULong)(&p) + : (ULong)(ML_(cur_step_UInt)(&p)); /* Address size */ addr_size = ML_(cur_step_UChar)(&p); + if (ver >= 5) + /* get offset in abbrev */ + atoffs = ui->dw64 ? ML_(cur_step_ULong)(&p) + : (ULong)(ML_(cur_step_UInt)(&p)); + /* End of this block */ end_img = ML_(cur_plus)(unitblock_img, blklen + (ui->dw64 ? 12 : 4)); @@ -909,6 +1163,17 @@ void read_unitinfo_dwarf2( /*OUT*/UnitInfo* ui, sval = ML_(cur_plus)(debugstr_img, ML_(cur_read_ULong)(p)); p = ML_(cur_plus)(p, ui->dw64 ? 8 : 4); break; + case 0x1f: /* FORM_line_strp */ /* pointer in .debug_line_str */ + /* 2006-01-01: only generate a value if a debug_str + section was found) */ + if (ML_(cur_is_valid)(debuglinestr_img) && !ui->dw64) + sval = ML_(cur_plus)(debuglinestr_img, + ML_(cur_read_UInt)(p)); + if (ML_(cur_is_valid)(debuglinestr_img) && ui->dw64) + sval = ML_(cur_plus)(debuglinestr_img, + ML_(cur_read_ULong)(p)); + p = ML_(cur_plus)(p, ui->dw64 ? 8 : 4); + break; case 0x08: /* FORM_string */ sval = p; p = ML_(cur_plus)(p, ML_(cur_strlen)(p) + 1); @@ -928,7 +1193,13 @@ void read_unitinfo_dwarf2( /*OUT*/UnitInfo* ui, p = ML_(cur_plus)(p, 8); /* perhaps should assign unconditionally to cval? */ break; + case 0x21: /* FORM_implicit_const */ + cval = step_leb128S (&abbrev_img); + break; /* TODO : Following ones just skip data - implement if you need */ + case 0x1e: /* FORM_data16 */ + p = ML_(cur_plus)(p, 16); + break; case 0x01: /* FORM_addr */ p = ML_(cur_plus)(p, addr_size); break; @@ -1028,7 +1299,8 @@ void ML_(read_debuginfo_dwarf3) DiSlice escn_debug_abbv, /* .debug_abbrev */ DiSlice escn_debug_line, /* .debug_line */ DiSlice escn_debug_str, /* .debug_str */ - DiSlice escn_debug_str_alt ) /* .debug_str */ + DiSlice escn_debug_str_alt, /* .debug_str */ + DiSlice escn_debug_line_str) /* .debug_line_str */ { UnitInfo ui; UShort ver; @@ -1067,9 +1339,9 @@ void ML_(read_debuginfo_dwarf3) /* version should be 2 */ ver = ML_(cur_read_UShort)( ML_(cur_plus)(block_img, blklen_len) ); - if ( ver != 2 && ver != 3 && ver != 4 ) { + if ( ver != 2 && ver != 3 && ver != 4 && ver != 5) { ML_(symerr)( di, True, - "Ignoring non-Dwarf2/3/4 block in .debug_info" ); + "Ignoring non-Dwarf2/3/4/5 block in .debug_info" ); continue; } @@ -1082,7 +1354,8 @@ void ML_(read_debuginfo_dwarf3) read_unitinfo_dwarf2( &ui, block_img, ML_(cur_from_sli)(escn_debug_abbv), ML_(cur_from_sli)(escn_debug_str), - ML_(cur_from_sli)(escn_debug_str_alt) ); + ML_(cur_from_sli)(escn_debug_str_alt), + ML_(cur_from_sli)(escn_debug_line_str)); if (0) { HChar* str_name = ML_(cur_read_strdup)(ui.name, "di.rdd3.1"); HChar* str_compdir = ML_(cur_read_strdup)(ui.compdir, "di.rdd3.2"); @@ -1107,7 +1380,9 @@ void ML_(read_debuginfo_dwarf3) read_dwarf2_lineblock( di, &ui, ML_(cur_plus)(ML_(cur_from_sli)(escn_debug_line), ui.stmt_list), - escn_debug_line.szB - ui.stmt_list + escn_debug_line.szB - ui.stmt_list, + ML_(cur_from_sli)(escn_debug_str), + ML_(cur_from_sli)(escn_debug_line_str) ); } } diff --git a/coregrind/m_debuginfo/readdwarf3.c b/coregrind/m_debuginfo/readdwarf3.c index c4d529bc6..82bc8f241 100644 --- a/coregrind/m_debuginfo/readdwarf3.c +++ b/coregrind/m_debuginfo/readdwarf3.c @@ -384,6 +384,7 @@ typedef struct _name_form { ULong at_name; // Dwarf Attribute name ULong at_form; // Dwarf Attribute form + Long at_val; // Dwarf Attribute value (for implicit_const) UInt skip_szB; // Nr of bytes skippable from here ... UInt next_nf; // ... to reach this attr/form index in the g_abbv.nf } name_form; @@ -423,7 +424,7 @@ typedef void (*barf)( const HChar* ) __attribute__((noreturn)); /* Is this 64-bit DWARF ? */ Bool is_dw64; - /* Which DWARF version ? (2, 3 or 4) */ + /* Which DWARF version ? (2, 3, 4 or 5) */ UShort version; /* Length of this Compilation Unit, as stated in the .unit_length :: InitialLength field of the CU Header. @@ -452,12 +453,15 @@ typedef /* Image information for various sections. */ DiSlice escn_debug_str; DiSlice escn_debug_ranges; + DiSlice escn_debug_rnglists; + DiSlice escn_debug_loclists; DiSlice escn_debug_loc; DiSlice escn_debug_line; DiSlice escn_debug_info; DiSlice escn_debug_types; DiSlice escn_debug_info_alt; DiSlice escn_debug_str_alt; + DiSlice escn_debug_line_str; /* How much to add to .debug_types resp. alternate .debug_info offsets in cook_die*. */ UWord types_cuOff_bias; @@ -651,25 +655,35 @@ static GExpr* make_singleton_GX ( DiCursor block, ULong nbytes ) __attribute__((noinline)) static GExpr* make_general_GX ( const CUConst* cc, Bool td3, - ULong debug_loc_offset, + ULong offset, Addr svma_of_referencing_CU ) { + Bool done; Addr base; Cursor loc; XArray* xa; /* XArray of UChar */ GExpr* gx; Word nbytes; + Bool addBase = cc->version < 5; vg_assert(sizeof(UWord) == sizeof(Addr)); - if (!ML_(sli_is_valid)(cc->escn_debug_loc) || cc->escn_debug_loc.szB == 0) + if (cc->version < 5 && (!ML_(sli_is_valid)(cc->escn_debug_loc) + || cc->escn_debug_loc.szB == 0)) cc->barf("make_general_GX: .debug_loc is empty/missing"); + if (cc->version >= 5 && (!ML_(sli_is_valid)(cc->escn_debug_loclists) + || cc->escn_debug_loclists.szB == 0)) + cc->barf("make_general_GX: .debug_loclists is empty/missing"); - init_Cursor( &loc, cc->escn_debug_loc, 0, cc->barf, - "Overrun whilst reading .debug_loc section(2)" ); - set_position_of_Cursor( &loc, debug_loc_offset ); + if (cc->version < 5) + init_Cursor( &loc, cc->escn_debug_loc, 0, cc->barf, + "Overrun whilst reading .debug_loc section(2)" ); + else + init_Cursor( &loc, cc->escn_debug_loclists, 0, cc->barf, + "Overrun whilst reading .debug_loclists section(2)" ); + set_position_of_Cursor( &loc, offset ); - TRACE_D3("make_general_GX (.debug_loc_offset = %llu, ioff = %llu) {\n", - debug_loc_offset, get_DiCursor_from_Cursor(&loc).ioff ); + TRACE_D3("make_general_GX (offset = %llu, ioff = %llu) {\n", + offset, get_DiCursor_from_Cursor(&loc).ioff ); /* Who frees this xa? It is freed before this fn exits. */ xa = VG_(newXA)( ML_(dinfo_zalloc), "di.readdwarf3.mgGX.1", @@ -679,40 +693,86 @@ static GExpr* make_general_GX ( const CUConst* cc, { UChar c = 1; /*biasMe*/ VG_(addBytesToXA)( xa, &c, sizeof(c) ); } base = 0; - while (True) { + done = False; + while (!done) { Bool acquire; UWord len; - /* Read a (host-)word pair. This is something of a hack since - the word size to read is really dictated by the ELF file; - however, we assume we're reading a file with the same - word-sizeness as the host. Reasonably enough. */ - UWord w1 = get_UWord( &loc ); - UWord w2 = get_UWord( &loc ); - - TRACE_D3(" %08lx %08lx\n", w1, w2); - if (w1 == 0 && w2 == 0) - break; /* end of list */ - - if (w1 == -1UL) { - /* new value for 'base' */ - base = w2; - continue; + UWord w1; + UWord w2; + if (cc->version < 5) { + /* Read a (host-)word pair. This is something of a hack since + the word size to read is really dictated by the ELF file; + however, we assume we're reading a file with the same + word-sizeness as the host. Reasonably enough. */ + w1 = get_UWord( &loc ); + w2 = get_UWord( &loc ); + + TRACE_D3(" %08lx %08lx\n", w1, w2); + if (w1 == 0 && w2 == 0) { + done = True; + break; /* end of list */ + } + + if (w1 == -1UL) { + /* new value for 'base' */ + base = w2; + continue; + } + /* else a location expression follows */ + len = (UWord)get_UShort( &loc ); + } else { + w1 = 0; + w2 = 0; + len = 0; + DW_LLE r = get_UChar( &loc ); + switch (r) { + case DW_LLE_end_of_list: + done = True; + break; + case DW_LLE_base_address: + base = get_UWord( &loc ); + break; + case DW_LLE_start_length: + w1 = get_UWord( &loc ); + w2 = w1 + get_ULEB128( &loc ); + len = get_ULEB128( &loc ); + break; + case DW_LLE_offset_pair: + w1 = base + get_ULEB128( &loc ); + w2 = base + get_ULEB128( &loc ); + len = get_ULEB128( &loc ); + break; + case DW_LLE_start_end: + w1 = get_UWord ( &loc ); + w2 = get_UWord ( &loc ); + len = get_ULEB128( &loc ); + break; + case DW_LLE_GNU_view_pair: + get_ULEB128( &loc ); + get_ULEB128( &loc ); + break; + case DW_LLE_base_addressx: + case DW_LLE_startx_endx: + case DW_LLE_startx_length: + case DW_LLE_default_location: + default: + cc->barf( "Unhandled or unknown loclists entry" ); + done = True; + } } - /* else a location expression follows */ /* else enumerate [w1+base, w2+base) */ /* w2 is 1 past end of range, as per D3 defn for "DW_AT_high_pc" (sec 2.17.2) */ if (w1 > w2) { TRACE_D3("negative range is for .debug_loc expr at " "file offset %llu\n", - debug_loc_offset); + offset); cc->barf( "negative range in .debug_loc section" ); } /* ignore zero length ranges */ acquire = w1 < w2; - len = (UWord)get_UShort( &loc ); if (acquire) { UWord w; @@ -720,9 +780,9 @@ static GExpr* make_general_GX ( const CUConst* cc, UChar c; c = 0; /* !isEnd*/ VG_(addBytesToXA)( xa, &c, sizeof(c) ); - w = w1 + base + svma_of_referencing_CU; + w = w1 + (addBase ? base : 0) + svma_of_referencing_CU; VG_(addBytesToXA)( xa, &w, sizeof(w) ); - w = w2 -1 + base + svma_of_referencing_CU; + w = w2 -1 + (addBase ? base : 0) + svma_of_referencing_CU; VG_(addBytesToXA)( xa, &w, sizeof(w) ); s = (UShort)len; VG_(addBytesToXA)( xa, &s, sizeof(s) ); @@ -839,45 +899,96 @@ get_range_list ( const CUConst* cc, XArray* xa; /* XArray of AddrRange */ AddrRange pair; - if (!ML_(sli_is_valid)(cc->escn_debug_ranges) - || cc->escn_debug_ranges.szB == 0) + if (cc->version < 5 && (!ML_(sli_is_valid)(cc->escn_debug_ranges) + || cc->escn_debug_ranges.szB == 0)) cc->barf("get_range_list: .debug_ranges is empty/missing"); + if (cc->version >= 5 && (!ML_(sli_is_valid)(cc->escn_debug_rnglists) + || cc->escn_debug_rnglists.szB == 0)) + cc->barf("get_range_list: .debug_rnglists is empty/missing"); + + if (cc->version < 5) + init_Cursor( &ranges, cc->escn_debug_ranges, 0, cc->barf, + "Overrun whilst reading .debug_ranges section(2)" ); + else + init_Cursor( &ranges, cc->escn_debug_rnglists, 0, cc->barf, + "Overrun whilst reading .debug_rnglists section(2)" ); - init_Cursor( &ranges, cc->escn_debug_ranges, 0, cc->barf, - "Overrun whilst reading .debug_ranges section(2)" ); set_position_of_Cursor( &ranges, debug_ranges_offset ); /* Who frees this xa? varstack_preen() does. */ xa = VG_(newXA)( ML_(dinfo_zalloc), "di.readdwarf3.grl.1", ML_(dinfo_free), sizeof(AddrRange) ); base = 0; - while (True) { - /* Read a (host-)word pair. This is something of a hack since - the word size to read is really dictated by the ELF file; - however, we assume we're reading a file with the same - word-sizeness as the host. Reasonably enough. */ - UWord w1 = get_UWord( &ranges ); - UWord w2 = get_UWord( &ranges ); - - if (w1 == 0 && w2 == 0) - break; /* end of list. */ - - if (w1 == -1UL) { - /* new value for 'base' */ - base = w2; - continue; - } + if (cc->version < 5) { + while (True) { + /* Read a (host-)word pair. This is something of a hack since + the word size to read is really dictated by the ELF file; + however, we assume we're reading a file with the same + word-sizeness as the host. Reasonably enough. */ + UWord w1 = get_UWord( &ranges ); + UWord w2 = get_UWord( &ranges ); - /* else enumerate [w1+base, w2+base) */ - /* w2 is 1 past end of range, as per D3 defn for "DW_AT_high_pc" - (sec 2.17.2) */ - if (w1 > w2) - cc->barf( "negative range in .debug_ranges section" ); - if (w1 < w2) { - pair.aMin = w1 + base + svma_of_referencing_CU; - pair.aMax = w2 - 1 + base + svma_of_referencing_CU; - vg_assert(pair.aMin <= pair.aMax); - VG_(addToXA)( xa, &pair ); + if (w1 == 0 && w2 == 0) + break; /* end of list. */ + + if (w1 == -1UL) { + /* new value for 'base' */ + base = w2; + continue; + } + + /* else enumerate [w1+base, w2+base) */ + /* w2 is 1 past end of range, as per D3 defn for "DW_AT_high_pc" + (sec 2.17.2) */ + if (w1 > w2) + cc->barf( "negative range in .debug_ranges section" ); + if (w1 < w2) { + pair.aMin = w1 + base + svma_of_referencing_CU; + pair.aMax = w2 - 1 + base + svma_of_referencing_CU; + vg_assert(pair.aMin <= pair.aMax); + VG_(addToXA)( xa, &pair ); + } + } + } else { + Bool done = False; + while (!done) { + UWord w1 = 0; + UWord w2 = 0; + DW_RLE r = get_UChar( &ranges ); + switch (r) { + case DW_RLE_end_of_list: + done = True; + break; + case DW_RLE_base_address: + base = get_UWord( &ranges ); + break; + case DW_RLE_start_length: + w1 = get_UWord( &ranges ); + w2 = w1 + get_ULEB128( &ranges ); + break; + case DW_RLE_offset_pair: + w1 = base + get_ULEB128( &ranges ); + w2 = base + get_ULEB128( &ranges ); + break; + case DW_RLE_start_end: + w1 = get_UWord ( &ranges ); + w2 = get_UWord ( &ranges ); + break; + case DW_RLE_base_addressx: + case DW_RLE_startx_endx: + case DW_RLE_startx_length: + default: + cc->barf( "Unhandled or unknown range list entry" ); + done = True; + } + if (w1 > w2) + cc->barf( "negative range in .debug_rnglists section" ); + if (w1 < w2) { + pair.aMin = w1 + svma_of_referencing_CU; + pair.aMax = w2 - 1 + svma_of_referencing_CU; + vg_assert(pair.aMin <= pair.aMax); + VG_(addToXA)( xa, &pair ); + } } } return xa; @@ -930,6 +1041,8 @@ static void init_ht_abbvs (CUConst* cc, } ta->nf[ta_nf_n].at_name = get_ULEB128( &c ); ta->nf[ta_nf_n].at_form = get_ULEB128( &c ); + if (ta->nf[ta_nf_n].at_form == DW_FORM_implicit_const) + ta->nf[ta_nf_n].at_val = get_SLEB128( &c ); if (ta->nf[ta_nf_n].at_name == 0 && ta->nf[ta_nf_n].at_form == 0) { ta_nf_n++; break; @@ -1005,7 +1118,7 @@ void parse_CU_Header ( /*OUT*/CUConst* cc, Bool type_unit, Bool alt_info ) { - UChar address_size; + UChar address_size, unit_type; ULong debug_abbrev_offset; VG_(memset)(cc, 0, sizeof(*cc)); @@ -1021,10 +1134,21 @@ void parse_CU_Header ( /*OUT*/CUConst* cc, /* version */ cc->version = get_UShort( c ); - if (cc->version != 2 && cc->version != 3 && cc->version != 4) - cc->barf( "parse_CU_Header: is neither DWARF2 nor DWARF3 nor DWARF4" ); + if (cc->version != 2 && cc->version != 3 && cc->version != 4 + && cc->version != 5) + cc->barf( "parse_CU_Header: " + "is neither DWARF2 nor DWARF3 nor DWARF4 nor DWARF5" ); TRACE_D3(" Version: %d\n", (Int)cc->version ); + /* unit type */ + if (cc->version >= 5) { + unit_type = get_UChar( c ); + address_size = get_UChar( c ); + } else { + unit_type = type_unit ? DW_UT_type : DW_UT_compile; + address_size = 0; /* Will be read later. */ + } + /* debug_abbrev_offset */ debug_abbrev_offset = get_Dwarfish_UWord( c, cc->is_dw64 ); if (debug_abbrev_offset >= escn_debug_abbv.szB) @@ -1035,7 +1159,9 @@ void parse_CU_Header ( /*OUT*/CUConst* cc, give up. This makes it safe to assume elsewhere that DW_FORM_addr and DW_FORM_ref_addr can be treated as a host word. */ - address_size = get_UChar( c ); + if (cc->version < 5) + address_size = get_UChar( c ); + if (address_size != sizeof(void*)) cc->barf( "parse_CU_Header: invalid address_size" ); TRACE_D3(" Pointer Size: %d\n", (Int)address_size ); @@ -1043,7 +1169,7 @@ void parse_CU_Header ( /*OUT*/CUConst* cc, cc->is_type_unit = type_unit; cc->is_alt_info = alt_info; - if (type_unit) { + if (type_unit || (cc->version >= 5 && unit_type == DW_UT_type)) { cc->type_signature = get_ULong( c ); cc->type_offset = get_Dwarfish_UWord( c, cc->is_dw64 ); } @@ -1130,8 +1256,9 @@ typedef static void get_Form_contents ( /*OUT*/FormContents* cts, const CUConst* cc, Cursor* c, - Bool td3, DW_FORM form ) + Bool td3, const name_form *abbv ) { + DW_FORM form = abbv->at_form; VG_(bzero_inline)(cts, sizeof(*cts)); // !!! keep switch in sync with get_Form_szB. The nr of characters read below // must be computed similarly in get_Form_szB. @@ -1157,6 +1284,19 @@ void get_Form_contents ( /*OUT*/FormContents* cts, cts->szB = 8; TRACE_D3("%llu", cts->u.val); break; + case DW_FORM_data16: { + /* This is more like a block than an integral value. */ + ULong u64b; + DiCursor data16 = get_DiCursor_from_Cursor(c); + TRACE_D3("data16: "); + for (u64b = 16; u64b > 0; u64b--) { + UChar u8 = get_UChar(c); + TRACE_D3("%x ", (UInt)u8); + } + cts->u.cur = data16; + cts->szB = - (Long)16; + break; + } case DW_FORM_sec_offset: cts->u.val = (ULong)get_Dwarfish_UWord( c, cc->is_dw64 ); cts->szB = cc->is_dw64 ? 8 : 4; @@ -1242,6 +1382,26 @@ void get_Form_contents ( /*OUT*/FormContents* cts, cts->szB = - (Long)(1 + (ULong)ML_(cur_strlen)(str)); break; } + case DW_FORM_line_strp: { + /* this is an offset into .debug_line_str */ + UWord uw = (UWord)get_Dwarfish_UWord( c, cc->is_dw64 ); + if (!ML_(sli_is_valid)(cc->escn_debug_line_str) + || uw >= cc->escn_debug_line_str.szB) + cc->barf("get_Form_contents: DW_FORM_line_strp " + "points outside .debug_line_str"); + /* FIXME: check the entire string lies inside debug_line_str, + not just the first byte of it. */ + DiCursor line_str + = ML_(cur_plus)( ML_(cur_from_sli)(cc->escn_debug_line_str), uw ); + if (TD3) { + HChar* tmp = ML_(cur_read_strdup)(line_str, "di.getFC.1.5"); + TRACE_D3("(indirect line string, offset: 0x%lx): %s", uw, tmp); + ML_(dinfo_free)(tmp); + } + cts->u.cur = line_str; + cts->szB = - (Long)(1 + (ULong)ML_(cur_strlen)(line_str)); + break; + } case DW_FORM_string: { DiCursor str = get_AsciiZ(c); if (TD3) { @@ -1307,6 +1467,11 @@ void get_Form_contents ( /*OUT*/FormContents* cts, cts->u.val = 1; cts->szB = 1; break; + case DW_FORM_implicit_const: + cts->u.val = (ULong)abbv->at_val; + cts->szB = 8; + TRACE_D3("%llu", cts->u.val); + break; case DW_FORM_block1: { ULong u64b; ULong u64 = (ULong)get_UChar(c); @@ -1396,9 +1561,14 @@ void get_Form_contents ( /*OUT*/FormContents* cts, cts->szB = sizeof(UWord); break; } - case DW_FORM_indirect: - get_Form_contents (cts, cc, c, td3, (DW_FORM)get_ULEB128(c)); + case DW_FORM_indirect: { + /* Urgh, this is ugly and somewhat unclear how it works + with DW_FORM_implicit_const. HACK. */ + name_form nfi = *abbv; + nfi.at_form = (DW_FORM)get_ULEB128(c); + get_Form_contents (cts, cc, c, td3, &nfi); return; + } case DW_FORM_GNU_ref_alt: cts->u.val = get_Dwarfish_UWord(c, cc->is_dw64); @@ -1471,6 +1641,7 @@ UInt get_Form_szB (const CUConst* cc, DW_FORM form ) case DW_FORM_data2: return 2; case DW_FORM_data4: return 4; case DW_FORM_data8: return 8; + case DW_FORM_data16: return 16; case DW_FORM_sec_offset: if (cc->is_dw64) return 8; @@ -1488,6 +1659,7 @@ UInt get_Form_szB (const CUConst* cc, DW_FORM form ) else return sizeof_Dwarfish_UWord (cc->is_dw64); case DW_FORM_strp: + case DW_FORM_line_strp: return sizeof_Dwarfish_UWord (cc->is_dw64); case DW_FORM_string: return VARSZ_FORM; @@ -1522,6 +1694,8 @@ UInt get_Form_szB (const CUConst* cc, DW_FORM form ) return sizeof_Dwarfish_UWord(cc->is_dw64); case DW_FORM_GNU_strp_alt: return sizeof_Dwarfish_UWord(cc->is_dw64); + case DW_FORM_implicit_const: + return 0; /* Value inside abbrev. */ default: VG_(printf)( "get_Form_szB: unhandled %u (%s)\n", @@ -1544,13 +1718,13 @@ void skip_DIE (UWord *sibling, while (True) { if (abbv->nf[nf_i].at_name == DW_AT_sibling) { get_Form_contents( &cts, cc, c_die, False /*td3*/, - (DW_FORM)abbv->nf[nf_i].at_form ); + &abbv->nf[nf_i] ); if ( cts.szB > 0 ) *sibling = cts.u.val; nf_i++; } else if (abbv->nf[nf_i].skip_szB == VARSZ_FORM) { get_Form_contents( &cts, cc, c_die, False /*td3*/, - (DW_FORM)abbv->nf[nf_i].at_form ); + &abbv->nf[nf_i] ); nf_i++; } else { advance_position_of_Cursor (c_die, (ULong)abbv->nf[nf_i].skip_szB); @@ -1778,6 +1952,124 @@ static GExpr* get_GX ( const CUConst* cc, Bool td3, const FormContents* cts ) return gexpr; } +static +HChar * get_line_str (struct _DebugInfo* di, Bool is_dw64, + Cursor *data, const UInt form, + DiSlice debugstr_img, DiSlice debuglinestr_img) +{ + HChar *str = NULL; + switch (form) { + case DW_FORM_string: { + DiCursor distr = get_AsciiZ(data); + str = ML_(cur_step_strdup)(&distr, "di.gls.string"); + break; + } + case DW_FORM_strp: { + UWord uw = (UWord)get_Dwarfish_UWord( data, is_dw64 ); + DiCursor distr + = ML_(cur_plus)( ML_(cur_from_sli)(debugstr_img), uw ); + str = ML_(cur_read_strdup)(distr, "di.gls.strp"); + break; + } + case DW_FORM_line_strp: { + UWord uw = (UWord)get_Dwarfish_UWord( data, is_dw64 ); + DiCursor distr + = ML_(cur_plus)( ML_(cur_from_sli)(debuglinestr_img), uw ); + str = ML_(cur_read_strdup)(distr, "di.gls.line_strp"); + break; + } + default: + ML_(symerr)(di, True, + "Unknown path string FORM in .debug_line"); + break; + } + return str; +} + +static +Int get_line_ndx (struct _DebugInfo* di, + Cursor *data, const UInt form) +{ + Int res = 0; + switch (form) { + case DW_FORM_data1: + res = get_UChar(data); + break; + case DW_FORM_data2: + res = get_UShort(data); + break; + case DW_FORM_udata: + res = get_ULEB128(data); + break; + default: + ML_(symerr)(di, True, + "Unknown directory_index value FORM in .debug_line"); + break; + } + return res; +} + +static +void skip_line_form (struct _DebugInfo* di, Bool is_dw64, + Cursor *d, const UInt form) +{ + switch (form) { + case DW_FORM_block: { + ULong len = get_ULEB128(d); + advance_position_of_Cursor (d, len); + break; + } + case DW_FORM_block1: { + UChar len = get_UChar(d); + advance_position_of_Cursor (d, len); + break; + } + case DW_FORM_block2: { + UShort len = get_UShort(d); + advance_position_of_Cursor (d, len); + break; + } + case DW_FORM_block4: { + UInt len = get_UInt(d); + advance_position_of_Cursor (d, len); + break; + } + case DW_FORM_flag: + case DW_FORM_data1: + advance_position_of_Cursor (d, 1); + break; + case DW_FORM_data2: + advance_position_of_Cursor (d, 2); + break; + case DW_FORM_data4: + advance_position_of_Cursor (d, 4); + break; + case DW_FORM_data8: + advance_position_of_Cursor (d, 8); + break; + case DW_FORM_data16: + advance_position_of_Cursor (d, 16); + break; + case DW_FORM_string: + (void)get_AsciiZ (d); + break; + case DW_FORM_strp: + case DW_FORM_line_strp: + case DW_FORM_sec_offset: + advance_position_of_Cursor (d, is_dw64 ? 8 : 4); + break; + case DW_FORM_udata: + (void)get_ULEB128(d); + break; + case DW_FORM_sdata: + (void)get_SLEB128(d); + break; + default: + ML_(symerr)(di, True, "Unknown FORM in .debug_line"); + break; + } +} + /* Returns an xarray* of directory names (indexed by the dwarf dirname integer). If 'compdir' is NULL, entry [0] will be set to "." @@ -1786,8 +2078,8 @@ static GExpr* get_GX ( const CUConst* cc, Bool td3, const FormContents* cts ) whatever that means, according to the DWARF3 spec. FIXME??? readdwarf3.c/readdwarf.c have a lot of duplicated code */ static -XArray* read_dirname_xa (DebugInfo* di, const HChar *compdir, - Cursor *c, +XArray* read_dirname_xa (DebugInfo* di, UShort version, const HChar *compdir, + Cursor *c, const CUConst *cc, Bool td3 ) { XArray* dirname_xa; /* xarray of HChar* dirname */ @@ -1804,51 +2096,121 @@ XArray* read_dirname_xa (DebugInfo* di, const HChar *compdir, dirname = compdir; compdir_len = VG_(strlen)(compdir); } - VG_(addToXA) (dirname_xa, &dirname); - - TRACE_D3(" The Directory Table%s\n", - peek_UChar(c) == 0 ? " is empty." : ":" ); - - while (peek_UChar(c) != 0) { - - DiCursor cur = get_AsciiZ(c); - HChar* data_str = ML_(cur_read_strdup)( cur, "dirname_xa.1" ); - TRACE_D3(" %s\n", data_str); - - /* If data_str[0] is '/', then 'data' is an absolute path and we - don't mess with it. Otherwise, construct the - path 'compdir' ++ "/" ++ 'data'. */ - - if (data_str[0] != '/' - /* not an absolute path */ - && compdir - /* actually got something sensible for compdir */ - && compdir_len) - { - SizeT len = compdir_len + 1 + VG_(strlen)(data_str); - HChar *buf = ML_(dinfo_zalloc)("dirname_xa.2", len + 1); - - VG_(strcpy)(buf, compdir); - VG_(strcat)(buf, "/"); - VG_(strcat)(buf, data_str); - - dirname = ML_(addStr)(di, buf, len); - VG_(addToXA) (dirname_xa, &dirname); - if (0) VG_(printf)("rel path %s\n", buf); - ML_(dinfo_free)(buf); - } else { - /* just use 'data'. */ - dirname = ML_(addStr)(di,data_str,-1); - VG_(addToXA) (dirname_xa, &dirname); - if (0) VG_(printf)("abs path %s\n", data_str); + + /* For version 5, the compdir is the first (zero) entry. */ + if (version < 5) + VG_(addToXA) (dirname_xa, &dirname); + + if (version < 5) { + TRACE_D3("The Directory Table%s\n", + peek_UChar(c) == 0 ? " is empty." : ":" ); + + while (peek_UChar(c) != 0) { + + DiCursor cur = get_AsciiZ(c); + HChar* data_str = ML_(cur_read_strdup)( cur, "dirname_xa.1" ); + TRACE_D3(" %s\n", data_str); + + /* If data_str[0] is '/', then 'data' is an absolute path and we + don't mess with it. Otherwise, construct the + path 'compdir' ++ "/" ++ 'data'. */ + + if (data_str[0] != '/' + /* not an absolute path */ + && compdir + /* actually got something sensible for compdir */ + && compdir_len) + { + SizeT len = compdir_len + 1 + VG_(strlen)(data_str); + HChar *buf = ML_(dinfo_zalloc)("dirname_xa.2", len + 1); + + VG_(strcpy)(buf, compdir); + VG_(strcat)(buf, "/"); + VG_(strcat)(buf, data_str); + + dirname = ML_(addStr)(di, buf, len); + VG_(addToXA) (dirname_xa, &dirname); + if (0) VG_(printf)("rel path %s\n", buf); + ML_(dinfo_free)(buf); + } else { + /* just use 'data'. */ + dirname = ML_(addStr)(di,data_str,-1); + VG_(addToXA) (dirname_xa, &dirname); + if (0) VG_(printf)("abs path %s\n", data_str); + } + + ML_(dinfo_free)(data_str); + } + } else { + UChar forms[256]; + UChar p_ndx = 0; + UInt directories_count; + UChar directory_entry_format_count; + UInt n; + DiSlice debugstr_img = cc->escn_debug_str; + DiSlice debuglinestr_img = cc->escn_debug_line_str; + + directory_entry_format_count = get_UChar(c); + for (n = 0; n < directory_entry_format_count; n++) { + UInt lnct = get_ULEB128(c); + UInt form = get_ULEB128(c); + if (lnct == DW_LNCT_path) + p_ndx = n; + forms[n] = form; } + directories_count = get_ULEB128(c); + TRACE_D3("The Directory Table%s\n", + directories_count == 0 ? " is empty." : ":" ); + + for (n = 0; n < directories_count; n++) { + UInt f; + for (f = 0; f < directory_entry_format_count; f++) { + UInt form = forms[f]; + if (f == p_ndx) { + HChar *data_str = get_line_str (di, cc->is_dw64, c, form, + debugstr_img, + debuglinestr_img); + TRACE_D3(" %s\n", data_str); + + /* If data_str[0] is '/', then 'data' is an absolute path and we + don't mess with it. Otherwise, construct the + path 'compdir' ++ "/" ++ 'data'. */ + + if (data_str[0] != '/' + /* not an absolute path */ + && compdir + /* actually got something sensible for compdir */ + && compdir_len) + { + SizeT len = compdir_len + 1 + VG_(strlen)(data_str); + HChar *buf = ML_(dinfo_zalloc)("dirname_xa.2", len + 1); + + VG_(strcpy)(buf, compdir); + VG_(strcat)(buf, "/"); + VG_(strcat)(buf, data_str); + + dirname = ML_(addStr)(di, buf, len); + VG_(addToXA) (dirname_xa, &dirname); + if (0) VG_(printf)("rel path %s\n", buf); + ML_(dinfo_free)(buf); + } else { + /* just use 'data'. */ + dirname = ML_(addStr)(di,data_str,-1); + VG_(addToXA) (dirname_xa, &dirname); + if (0) VG_(printf)("abs path %s\n", data_str); + } - ML_(dinfo_free)(data_str); + ML_(dinfo_free)(data_str); + } else { + skip_line_form (di, cc->is_dw64, c, form); + } + } + } } TRACE_D3 ("\n"); - if (get_UChar (c) != 0) { + if (version < 5 && get_UChar (c) != 0) { ML_(symerr)(NULL, True, "could not get NUL at end of DWARF directory table"); VG_(deleteXA)(dirname_xa); @@ -1888,9 +2250,13 @@ void read_filename_table( /*MOD*/XArray* /* of UInt* */ fndn_ix_Table, get_Initial_Length( &is_dw64, &c, "read_filename_table: invalid initial-length field" ); version = get_UShort( &c ); - if (version != 2 && version != 3 && version != 4) - cc->barf("read_filename_table: Only DWARF version 2, 3 and 4 line info " - "is currently supported."); + if (version != 2 && version != 3 && version != 4 && version != 5) + cc->barf("read_filename_table: Only DWARF version 2, 3, 4 and 5 " + "line info is currently supported."); + if (version >= 5) { + /* addrs_size = */ get_UChar( &c ); + /* seg_size = */ get_UChar( &c ); + } /*header_length = (ULong)*/ get_Dwarfish_UWord( &c, is_dw64 ); /*minimum_instruction_length = */ get_UChar( &c ); if (version >= 4) @@ -1903,30 +2269,77 @@ void read_filename_table( /*MOD*/XArray* /* of UInt* */ fndn_ix_Table, for (i = 1; i < (Word)opcode_base; i++) (void)get_UChar( &c ); - dirname_xa = read_dirname_xa(cc->di, compdir, &c, td3); + dirname_xa = read_dirname_xa(cc->di, version, compdir, &c, cc, td3); /* Read and record the file names table */ vg_assert( VG_(sizeXA)( fndn_ix_Table ) == 0 ); - /* Add a dummy index-zero entry. DWARF3 numbers its files - from 1, for some reason. */ - fndn_ix = ML_(addFnDn) ( cc->di, "", NULL ); - VG_(addToXA)( fndn_ix_Table, &fndn_ix ); - while (peek_UChar(&c) != 0) { - DiCursor cur = get_AsciiZ(&c); - str = ML_(addStrFromCursor)( cc->di, cur ); - dir_xa_ix = get_ULEB128( &c ); - if (dirname_xa != NULL - && dir_xa_ix >= 0 && dir_xa_ix < VG_(sizeXA) (dirname_xa)) - dirname = *(HChar**)VG_(indexXA) ( dirname_xa, dir_xa_ix ); - else - dirname = NULL; - fndn_ix = ML_(addFnDn)( cc->di, str, dirname); - TRACE_D3(" read_filename_table: %ld fndn_ix %u %s %s\n", - VG_(sizeXA)(fndn_ix_Table), fndn_ix, - dirname, str); + if (version < 5) { + /* Add a dummy index-zero entry. DWARF3 numbers its files + from 1, for some reason. */ + fndn_ix = ML_(addFnDn) ( cc->di, "", NULL ); VG_(addToXA)( fndn_ix_Table, &fndn_ix ); - (void)get_ULEB128( &c ); /* skip last mod time */ - (void)get_ULEB128( &c ); /* file size */ + while (peek_UChar(&c) != 0) { + DiCursor cur = get_AsciiZ(&c); + str = ML_(addStrFromCursor)( cc->di, cur ); + dir_xa_ix = get_ULEB128( &c ); + if (dirname_xa != NULL + && dir_xa_ix >= 0 && dir_xa_ix < VG_(sizeXA) (dirname_xa)) + dirname = *(HChar**)VG_(indexXA) ( dirname_xa, dir_xa_ix ); + else + dirname = NULL; + fndn_ix = ML_(addFnDn)( cc->di, str, dirname); + TRACE_D3(" read_filename_table: %ld fndn_ix %u %s %s\n", + VG_(sizeXA)(fndn_ix_Table), fndn_ix, + dirname, str); + VG_(addToXA)( fndn_ix_Table, &fndn_ix ); + (void)get_ULEB128( &c ); /* skip last mod time */ + (void)get_ULEB128( &c ); /* file size */ + } + } else { + UChar forms[256]; + UChar p_ndx = 0, d_ndx = 0; + UInt file_names_count; + UChar file_names_entry_format_count; + UInt n; + DiSlice debugstr_img = cc->escn_debug_str; + DiSlice debuglinestr_img = cc->escn_debug_line_str; + file_names_entry_format_count = get_UChar( &c ); + for (n = 0; n < file_names_entry_format_count; n++) { + UInt lnct = get_ULEB128( &c ); + UInt form = get_ULEB128( &c ); + if (lnct == DW_LNCT_path) + p_ndx = n; + if (lnct == DW_LNCT_directory_index) + d_ndx = n; + forms[n] = form; + } + file_names_count = get_ULEB128( &c ); + for (n = 0; n < file_names_count; n++) { + UInt f; + dir_xa_ix = 0; + str = NULL; + for (f = 0; f < file_names_entry_format_count; f++) { + UInt form = forms[f]; + if (f == p_ndx) + str = get_line_str (cc->di, cc->is_dw64, &c, form, + debugstr_img, debuglinestr_img); + else if (n == d_ndx) + dir_xa_ix = get_line_ndx (cc->di, &c, form); + else + skip_line_form (cc->di, cc->is_dw64, &c, form); + } + + if (dirname_xa != NULL + && dir_xa_ix >= 0 && dir_xa_ix < VG_(sizeXA) (dirname_xa)) + dirname = *(HChar**)VG_(indexXA) ( dirname_xa, dir_xa_ix ); + else + dirname = NULL; + fndn_ix = ML_(addFnDn)( cc->di, str, dirname); + TRACE_D3(" read_filename_table: %ld fndn_ix %u %s %s\n", + VG_(sizeXA)(fndn_ix_Table), fndn_ix, + dirname, str); + VG_(addToXA)( fndn_ix_Table, &fndn_ix ); + } } /* We're done! The rest of it is not interesting. */ if (dirname_xa != NULL) @@ -2011,11 +2424,12 @@ static void trace_DIE( while (True) { DW_AT attr = (DW_AT) abbv->nf[nf_i].at_name; DW_FORM form = (DW_FORM)abbv->nf[nf_i].at_form; + const name_form *nf = &abbv->nf[nf_i]; nf_i++; if (attr == 0 && form == 0) break; VG_(printf)(" %-18s: ", ML_(pp_DW_AT)(attr)); /* Get the form contents, so as to print them */ - get_Form_contents( &cts, cc, &c, True, form ); + get_Form_contents( &cts, cc, &c, True, nf ); if (attr == DW_AT_sibling && cts.szB > 0) { sibling = cts.u.val; } @@ -2094,9 +2508,10 @@ static void parse_var_DIE ( while (True) { DW_AT attr = (DW_AT) abbv->nf[nf_i].at_name; DW_FORM form = (DW_FORM)abbv->nf[nf_i].at_form; + const name_form *nf = &abbv->nf[nf_i]; nf_i++; if (attr == 0 && form == 0) break; - get_Form_contents( &cts, cc, c_die, False/*td3*/, form ); + get_Form_contents( &cts, cc, c_die, False/*td3*/, nf ); if (attr == DW_AT_low_pc && cts.szB > 0) { ip_lo = cts.u.val; have_lo = True; @@ -2196,9 +2611,10 @@ static void parse_var_DIE ( while (True) { DW_AT attr = (DW_AT) abbv->nf[nf_i].at_name; DW_FORM form = (DW_FORM)abbv->nf[nf_i].at_form; + const name_form *nf = &abbv->nf[nf_i]; nf_i++; if (attr == 0 && form == 0) break; - get_Form_contents( &cts, cc, c_die, False/*td3*/, form ); + get_Form_contents( &cts, cc, c_die, False/*td3*/, nf ); if (attr == DW_AT_low_pc && cts.szB > 0) { ip_lo = cts.u.val; have_lo = True; @@ -2282,9 +2698,10 @@ static void parse_var_DIE ( while (True) { DW_AT attr = (DW_AT) abbv->nf[nf_i].at_name; DW_FORM form = (DW_FORM)abbv->nf[nf_i].at_form; + const name_form *nf = &abbv->nf[nf_i]; nf_i++; if (attr == 0 && form == 0) break; - get_Form_contents( &cts, cc, c_die, False/*td3*/, form ); + get_Form_contents( &cts, cc, c_die, False/*td3*/, nf ); n_attrs++; if (attr == DW_AT_name && cts.szB < 0) { name = ML_(addStrFromCursor)( cc->di, cts.u.cur ); @@ -2646,9 +3063,10 @@ static const HChar* get_inlFnName (Int absori, const CUConst* cc, Bool td3) while (True) { DW_AT attr = (DW_AT) abbv->nf[nf_i].at_name; DW_FORM form = (DW_FORM)abbv->nf[nf_i].at_form; + const name_form *nf = &abbv->nf[nf_i]; nf_i++; if (attr == 0 && form == 0) break; - get_Form_contents( &cts, cc, &c, False/*td3*/, form ); + get_Form_contents( &cts, cc, &c, False/*td3*/, nf ); if (attr == DW_AT_name) { HChar *fnname; if (cts.szB >= 0) @@ -2720,9 +3138,10 @@ static Bool parse_inl_DIE ( while (True) { DW_AT attr = (DW_AT) abbv->nf[nf_i].at_name; DW_FORM form = (DW_FORM)abbv->nf[nf_i].at_form; + const name_form *nf = &abbv->nf[nf_i]; nf_i++; if (attr == 0 && form == 0) break; - get_Form_contents( &cts, cc, c_die, False/*td3*/, form ); + get_Form_contents( &cts, cc, c_die, False/*td3*/, nf ); if (attr == DW_AT_low_pc && cts.szB > 0) { ip_lo = cts.u.val; have_lo = True; @@ -2764,9 +3183,10 @@ static Bool parse_inl_DIE ( while (True) { DW_AT attr = (DW_AT) abbv->nf[nf_i].at_name; DW_FORM form = (DW_FORM)abbv->nf[nf_i].at_form; + const name_form *nf = &abbv->nf[nf_i]; nf_i++; if (attr == 0 && form == 0) break; - get_Form_contents( &cts, cc, c_die, False/*td3*/, form ); + get_Form_contents( &cts, cc, c_die, False/*td3*/, nf ); if (attr == DW_AT_call_file && cts.szB > 0) { Int ftabIx = (Int)cts.u.val; if (ftabIx >= 1 @@ -3090,9 +3510,10 @@ static void parse_type_DIE ( /*MOD*/XArray* /* of TyEnt */ tyents, while (True) { DW_AT attr = (DW_AT) abbv->nf[nf_i].at_name; DW_FORM form = (DW_FORM)abbv->nf[nf_i].at_form; + const name_form *nf = &abbv->nf[nf_i]; nf_i++; if (attr == 0 && form == 0) break; - get_Form_contents( &cts, cc, c_die, False/*td3*/, form ); + get_Form_contents( &cts, cc, c_die, False/*td3*/, nf ); if (attr != DW_AT_language) continue; if (cts.szB <= 0) @@ -3132,9 +3553,10 @@ static void parse_type_DIE ( /*MOD*/XArray* /* of TyEnt */ tyents, while (True) { DW_AT attr = (DW_AT) abbv->nf[nf_i].at_name; DW_FORM form = (DW_FORM)abbv->nf[nf_i].at_form; + const name_form *nf = &abbv->nf[nf_i]; nf_i++; if (attr == 0 && form == 0) break; - get_Form_contents( &cts, cc, c_die, False/*td3*/, form ); + get_Form_contents( &cts, cc, c_die, False/*td3*/, nf ); if (attr == DW_AT_name && cts.szB < 0) { typeE.Te.TyBase.name = ML_(cur_read_strdup)( cts.u.cur, @@ -3243,9 +3665,10 @@ static void parse_type_DIE ( /*MOD*/XArray* /* of TyEnt */ tyents, while (True) { DW_AT attr = (DW_AT) abbv->nf[nf_i].at_name; DW_FORM form = (DW_FORM)abbv->nf[nf_i].at_form; + const name_form *nf = &abbv->nf[nf_i]; nf_i++; if (attr == 0 && form == 0) break; - get_Form_contents( &cts, cc, c_die, False/*td3*/, form ); + get_Form_contents( &cts, cc, c_die, False/*td3*/, nf ); if (attr == DW_AT_byte_size && cts.szB > 0) { typeE.Te.TyPorR.szB = cts.u.val; } @@ -3275,9 +3698,10 @@ static void parse_type_DIE ( /*MOD*/XArray* /* of TyEnt */ tyents, while (True) { DW_AT attr = (DW_AT) abbv->nf[nf_i].at_name; DW_FORM form = (DW_FORM)abbv->nf[nf_i].at_form; + const name_form *nf = &abbv->nf[nf_i]; nf_i++; if (attr == 0 && form == 0) break; - get_Form_contents( &cts, cc, c_die, False/*td3*/, form ); + get_Form_contents( &cts, cc, c_die, False/*td3*/, nf ); if (attr == DW_AT_name && cts.szB < 0) { typeE.Te.TyEnum.name = ML_(cur_read_strdup)( cts.u.cur, @@ -3356,9 +3780,10 @@ static void parse_type_DIE ( /*MOD*/XArray* /* of TyEnt */ tyents, while (True) { DW_AT attr = (DW_AT) abbv->nf[nf_i].at_name; DW_FORM form = (DW_FORM)abbv->nf[nf_i].at_form; + const name_form *nf = &abbv->nf[nf_i]; nf_i++; if (attr == 0 && form == 0) break; - get_Form_contents( &cts, cc, c_die, False/*td3*/, form ); + get_Form_contents( &cts, cc, c_die, False/*td3*/, nf ); if (attr == DW_AT_name && cts.szB < 0) { atomE.Te.Atom.name = ML_(cur_read_strdup)( cts.u.cur, @@ -3411,9 +3836,10 @@ static void parse_type_DIE ( /*MOD*/XArray* /* of TyEnt */ tyents, while (True) { DW_AT attr = (DW_AT) abbv->nf[nf_i].at_name; DW_FORM form = (DW_FORM)abbv->nf[nf_i].at_form; + const name_form *nf = &abbv->nf[nf_i]; nf_i++; if (attr == 0 && form == 0) break; - get_Form_contents( &cts, cc, c_die, False/*td3*/, form ); + get_Form_contents( &cts, cc, c_die, False/*td3*/, nf ); if (attr == DW_AT_name && cts.szB < 0) { typeE.Te.TyStOrUn.name = ML_(cur_read_strdup)( cts.u.cur, @@ -3498,9 +3924,10 @@ static void parse_type_DIE ( /*MOD*/XArray* /* of TyEnt */ tyents, while (True) { DW_AT attr = (DW_AT) abbv->nf[nf_i].at_name; DW_FORM form = (DW_FORM)abbv->nf[nf_i].at_form; + const name_form *nf = &abbv->nf[nf_i]; nf_i++; if (attr == 0 && form == 0) break; - get_Form_contents( &cts, cc, c_die, False/*td3*/, form ); + get_Form_contents( &cts, cc, c_die, False/*td3*/, nf ); if (attr == DW_AT_name && cts.szB < 0) { fieldE.Te.Field.name = ML_(cur_read_strdup)( cts.u.cur, @@ -3585,9 +4012,10 @@ static void parse_type_DIE ( /*MOD*/XArray* /* of TyEnt */ tyents, while (True) { DW_AT attr = (DW_AT) abbv->nf[nf_i].at_name; DW_FORM form = (DW_FORM)abbv->nf[nf_i].at_form; + const name_form *nf = &abbv->nf[nf_i]; nf_i++; if (attr == 0 && form == 0) break; - get_Form_contents( &cts, cc, c_die, False/*td3*/, form ); + get_Form_contents( &cts, cc, c_die, False/*td3*/, nf ); if (attr == DW_AT_type && cts.szB > 0) { typeE.Te.TyArray.typeR = cook_die_using_form( cc, (UWord)cts.u.val, form ); @@ -3626,9 +4054,10 @@ static void parse_type_DIE ( /*MOD*/XArray* /* of TyEnt */ tyents, while (True) { DW_AT attr = (DW_AT) abbv->nf[nf_i].at_name; DW_FORM form = (DW_FORM)abbv->nf[nf_i].at_form; + const name_form *nf = &abbv->nf[nf_i]; nf_i++; if (attr == 0 && form == 0) break; - get_Form_contents( &cts, cc, c_die, False/*td3*/, form ); + get_Form_contents( &cts, cc, c_die, False/*td3*/, nf ); if (attr == DW_AT_lower_bound && cts.szB > 0 && form_expected_for_bound (form)) { lower = (Long)cts.u.val; @@ -3714,9 +4143,10 @@ static void parse_type_DIE ( /*MOD*/XArray* /* of TyEnt */ tyents, while (True) { DW_AT attr = (DW_AT) abbv->nf[nf_i].at_name; DW_FORM form = (DW_FORM)abbv->nf[nf_i].at_form; + const name_form *nf = &abbv->nf[nf_i]; nf_i++; if (attr == 0 && form == 0) break; - get_Form_contents( &cts, cc, c_die, False/*td3*/, form ); + get_Form_contents( &cts, cc, c_die, False/*td3*/, nf ); if (attr == DW_AT_name && cts.szB < 0) { typeE.Te.TyTyDef.name = ML_(cur_read_strdup)( cts.u.cur, @@ -3764,9 +4194,10 @@ static void parse_type_DIE ( /*MOD*/XArray* /* of TyEnt */ tyents, while (True) { DW_AT attr = (DW_AT) abbv->nf[nf_i].at_name; DW_FORM form = (DW_FORM)abbv->nf[nf_i].at_form; + const name_form *nf = &abbv->nf[nf_i]; nf_i++; if (attr == 0 && form == 0) break; - get_Form_contents( &cts, cc, c_die, False/*td3*/, form ); + get_Form_contents( &cts, cc, c_die, False/*td3*/, nf ); if (attr == DW_AT_type && cts.szB > 0) { typeE.Te.TyQual.typeR = cook_die_using_form( cc, (UWord)cts.u.val, form ); @@ -4486,6 +4917,9 @@ static void trace_debug_abbrev (const DebugInfo* di, while (True) { ULong at_name = get_ULEB128( &abbv ); ULong at_form = get_ULEB128( &abbv ); + if (at_form == DW_FORM_implicit_const) { + /* Long at_val = */ get_SLEB128 ( &abbv ); + } if (at_name == 0 && at_form == 0) break; TRACE_D3(" %-18s %s\n", ML_(pp_DW_AT)(at_name), ML_(pp_DW_FORM)(at_form)); @@ -4502,9 +4936,10 @@ void new_dwarf3_reader_wrk ( DiSlice escn_debug_info, DiSlice escn_debug_types, DiSlice escn_debug_abbv, DiSlice escn_debug_line, DiSlice escn_debug_str, DiSlice escn_debug_ranges, + DiSlice escn_debug_rnglists, DiSlice escn_debug_loclists, DiSlice escn_debug_loc, DiSlice escn_debug_info_alt, DiSlice escn_debug_abbv_alt, DiSlice escn_debug_line_alt, - DiSlice escn_debug_str_alt + DiSlice escn_debug_str_alt, DiSlice escn_debug_line_str ) { XArray* /* of TyEnt */ tyents = NULL; @@ -4738,6 +5173,8 @@ void new_dwarf3_reader_wrk ( cc.escn_debug_str = pass == 0 ? escn_debug_str_alt : escn_debug_str; cc.escn_debug_ranges = escn_debug_ranges; + cc.escn_debug_rnglists = escn_debug_rnglists; + cc.escn_debug_loclists = escn_debug_loclists; cc.escn_debug_loc = escn_debug_loc; cc.escn_debug_line = pass == 0 ? escn_debug_line_alt : escn_debug_line; @@ -4746,6 +5183,7 @@ void new_dwarf3_reader_wrk ( cc.escn_debug_types = escn_debug_types; cc.escn_debug_info_alt = escn_debug_info_alt; cc.escn_debug_str_alt = escn_debug_str_alt; + cc.escn_debug_line_str = escn_debug_line_str; cc.types_cuOff_bias = escn_debug_info.szB; cc.alt_cuOff_bias = escn_debug_info.szB + escn_debug_types.szB; cc.cu_start_offset = cu_start_offset; @@ -5216,9 +5654,10 @@ ML_(new_dwarf3_reader) ( DiSlice escn_debug_info, DiSlice escn_debug_types, DiSlice escn_debug_abbv, DiSlice escn_debug_line, DiSlice escn_debug_str, DiSlice escn_debug_ranges, + DiSlice escn_debug_rnglists, DiSlice escn_debug_loclists, DiSlice escn_debug_loc, DiSlice escn_debug_info_alt, DiSlice escn_debug_abbv_alt, DiSlice escn_debug_line_alt, - DiSlice escn_debug_str_alt + DiSlice escn_debug_str_alt, DiSlice escn_debug_line_str ) { volatile Int jumped; @@ -5239,9 +5678,10 @@ ML_(new_dwarf3_reader) ( escn_debug_info, escn_debug_types, escn_debug_abbv, escn_debug_line, escn_debug_str, escn_debug_ranges, + escn_debug_rnglists, escn_debug_loclists, escn_debug_loc, escn_debug_info_alt, escn_debug_abbv_alt, escn_debug_line_alt, - escn_debug_str_alt ); + escn_debug_str_alt, escn_debug_line_str ); d3rd_jmpbuf_valid = False; TRACE_D3("\n------ .debug_info reading was successful ------\n"); } else { diff --git a/coregrind/m_debuginfo/readelf.c b/coregrind/m_debuginfo/readelf.c index bc5a732d7..404034df0 100644 --- a/coregrind/m_debuginfo/readelf.c +++ b/coregrind/m_debuginfo/readelf.c @@ -2577,7 +2577,10 @@ Bool ML_(read_elf_debug_info) ( struct _DebugInfo* di ) DiSlice debug_types_escn = DiSlice_INVALID; // .debug_types (dwarf4) DiSlice debug_abbv_escn = DiSlice_INVALID; // .debug_abbrev (dwarf2) DiSlice debug_str_escn = DiSlice_INVALID; // .debug_str (dwarf2) + DiSlice debug_line_str_escn = DiSlice_INVALID; // .debug_line_str(dwarf5) DiSlice debug_ranges_escn = DiSlice_INVALID; // .debug_ranges (dwarf2) + DiSlice debug_rnglists_escn = DiSlice_INVALID; // .debug_rnglists(dwarf5) + DiSlice debug_loclists_escn = DiSlice_INVALID; // .debug_loclists(dwarf5) DiSlice debug_loc_escn = DiSlice_INVALID; // .debug_loc (dwarf2) DiSlice debug_frame_escn = DiSlice_INVALID; // .debug_frame (dwarf2) DiSlice debug_line_alt_escn = DiSlice_INVALID; // .debug_line (alt) @@ -2683,10 +2686,22 @@ Bool ML_(read_elf_debug_info) ( struct _DebugInfo* di ) if (!ML_(sli_is_valid)(debug_str_escn)) FIND(".zdebug_str", debug_str_escn) + FIND( ".debug_line_str", debug_line_str_escn) + if (!ML_(sli_is_valid)(debug_line_str_escn)) + FIND(".zdebug_str", debug_line_str_escn) + FIND( ".debug_ranges", debug_ranges_escn) if (!ML_(sli_is_valid)(debug_ranges_escn)) FIND(".zdebug_ranges", debug_ranges_escn) + FIND( ".debug_rnglists", debug_rnglists_escn) + if (!ML_(sli_is_valid)(debug_rnglists_escn)) + FIND(".zdebug_rnglists", debug_rnglists_escn) + + FIND( ".debug_loclists", debug_loclists_escn) + if (!ML_(sli_is_valid)(debug_loclists_escn)) + FIND(".zdebug_loclists", debug_loclists_escn) + FIND( ".debug_loc", debug_loc_escn) if (!ML_(sli_is_valid)(debug_loc_escn)) FIND(".zdebug_loc", debug_loc_escn) @@ -2994,10 +3009,22 @@ Bool ML_(read_elf_debug_info) ( struct _DebugInfo* di ) if (!ML_(sli_is_valid)(debug_str_escn)) FIND(need_dwarf2, ".zdebug_str", debug_str_escn) + FIND( need_dwarf2, ".debug_line_str", debug_line_str_escn) + if (!ML_(sli_is_valid)(debug_line_str_escn)) + FIND(need_dwarf2, ".zdebug_line_str", debug_line_str_escn) + FIND( need_dwarf2, ".debug_ranges", debug_ranges_escn) if (!ML_(sli_is_valid)(debug_ranges_escn)) FIND(need_dwarf2, ".zdebug_ranges", debug_ranges_escn) + FIND( need_dwarf2, ".debug_rnglists", debug_rnglists_escn) + if (!ML_(sli_is_valid)(debug_rnglists_escn)) + FIND(need_dwarf2, ".zdebug_rnglists", debug_rnglists_escn) + + FIND( need_dwarf2, ".debug_loclists", debug_loclists_escn) + if (!ML_(sli_is_valid)(debug_loclists_escn)) + FIND(need_dwarf2, ".zdebug_loclists", debug_loclists_escn) + FIND( need_dwarf2, ".debug_loc", debug_loc_escn) if (!ML_(sli_is_valid)(debug_loc_escn)) FIND(need_dwarf2, ".zdebug_loc", debug_loc_escn) @@ -3231,7 +3258,8 @@ Bool ML_(read_elf_debug_info) ( struct _DebugInfo* di ) debug_abbv_escn, debug_line_escn, debug_str_escn, - debug_str_alt_escn ); + debug_str_alt_escn, + debug_line_str_escn); /* The new reader: read the DIEs in .debug_info to acquire information on variable types and locations or inline info. But only if the tool asks for it, or the user requests it on @@ -3242,9 +3270,10 @@ Bool ML_(read_elf_debug_info) ( struct _DebugInfo* di ) di, debug_info_escn, debug_types_escn, debug_abbv_escn, debug_line_escn, debug_str_escn, debug_ranges_escn, + debug_rnglists_escn, debug_loclists_escn, debug_loc_escn, debug_info_alt_escn, debug_abbv_alt_escn, debug_line_alt_escn, - debug_str_alt_escn + debug_str_alt_escn, debug_line_str_escn ); } } diff --git a/coregrind/m_debuginfo/readmacho.c b/coregrind/m_debuginfo/readmacho.c index f39ee006f..9153a74ca 100644 --- a/coregrind/m_debuginfo/readmacho.c +++ b/coregrind/m_debuginfo/readmacho.c @@ -1103,8 +1103,14 @@ Bool ML_(read_macho_debug_info)( struct _DebugInfo* di ) = getsectdata(dsli, "__DWARF", "__debug_line", NULL); DiSlice debug_str_mscn = getsectdata(dsli, "__DWARF", "__debug_str", NULL); + DiSlice debug_line_str_mscn + = getsectdata(dsli, "__DWARF", "__debug_line_str", NULL); DiSlice debug_ranges_mscn = getsectdata(dsli, "__DWARF", "__debug_ranges", NULL); + DiSlice debug_rnglists_mscn + = getsectdata(dsli, "__DWARF", "__debug_rnglists", NULL); + DiSlice debug_loclists_mscn + = getsectdata(dsli, "__DWARF", "__debug_loclists", NULL); DiSlice debug_loc_mscn = getsectdata(dsli, "__DWARF", "__debug_loc", NULL); @@ -1145,7 +1151,8 @@ Bool ML_(read_macho_debug_info)( struct _DebugInfo* di ) debug_abbv_mscn, debug_line_mscn, debug_str_mscn, - DiSlice_INVALID /* ALT .debug_str */ ); + DiSlice_INVALID, /* ALT .debug_str */ + debug_line_str ); /* The new reader: read the DIEs in .debug_info to acquire information on variable types and locations or inline info. @@ -1160,11 +1167,14 @@ Bool ML_(read_macho_debug_info)( struct _DebugInfo* di ) debug_line_mscn, debug_str_mscn, debug_ranges_mscn, + debug_rnglists_mscn, + debug_loclists_mscn, debug_loc_mscn, DiSlice_INVALID, /* ALT .debug_info */ DiSlice_INVALID, /* ALT .debug_abbv */ DiSlice_INVALID, /* ALT .debug_line */ - DiSlice_INVALID /* ALT .debug_str */ + DiSlice_INVALID, /* ALT .debug_str */ + debug_line_str_mscn /* .debug_line_str */ ); } } -- 2.18.4