]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Add support for DWARF5 as produced by GCC11
authorMark Wielaard <mark@klomp.org>
Mon, 25 Jan 2021 14:33:34 +0000 (15:33 +0100)
committerMark Wielaard <mark@klomp.org>
Wed, 27 Jan 2021 12:15:53 +0000 (13:15 +0100)
Implement DWARF5 in readdwarf.c and readdwarf3.c

Since gcc11 will default to DWARF5 by default it is time for
valgrind to support it. The patch handles everything gcc11 produces
(except for the new DWARF expressions).

There is some duplication in the patch since we actually have two DWARF
readers which use slightly different abstractions (Slices vs Cursors).
It would be nice if we could merge these somehow. The reader in
readdwarf3.c is only used when --read-var-info=yes is used (which
drd uses to provide the allocation context).

The handling of DW_FORM_implicit_const is tricky with the current design.
An abbrev which contains an attribute encoded with DW_FORM_implicit_const
has its value also in the abbrev. The code in readdwarf3.c assumed it
always could simply get the data from the .debug_info/current Cursor.
For now I added a value field to the name_form field that holds the
associated value. This is slightly wasteful since the extra field is
not necessary for other forms.

Tested against GCC10 (defaulting to DWARF4) and GCC11 (defaulting to
DWARF5) on x86_64. No regressions in the regtests.

https://bugs.kde.org/show_bug.cgi?id=432102

coregrind/m_debuginfo/d3basics.c
coregrind/m_debuginfo/priv_d3basics.h
coregrind/m_debuginfo/priv_readdwarf.h
coregrind/m_debuginfo/priv_readdwarf3.h
coregrind/m_debuginfo/readdwarf.c
coregrind/m_debuginfo/readdwarf3.c
coregrind/m_debuginfo/readelf.c
coregrind/m_debuginfo/readmacho.c

index b6d13c1189c1db10e41439396ec900dd4215692a..e1127ffe2f6b17375cf607eed3b88e89140e142e 100644 (file)
@@ -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.  */
index b60e3e8eb473fe1431887ed935b04fcdaaa509cd..9d825e39ef4c8991954aac341c1d19bc21d9537c 100644 (file)
@@ -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 );
index 1e3f24c2a1da5ff58a1bed8f6b27a5fa1143624c..302266924fd1228442734b6237fdd7cc3a54130e 100644 (file)
@@ -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
index 1a5bd61c308fd2ad1199bdecca52ca03f798cd2f..f6d1dd1ee177f448086896329823b52cb333cee4 100644 (file)
@@ -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 */
index 5701c504bd8eedd81aef2be6311c9740f556a6ed..88d5d99f17b81225ae869650eb8144c1b5626da4 100644 (file)
@@ -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)
       );
    }
 }
index c4d529bc6db74c75410b8e118453881588fb9036..82bc8f241fc58a1df101ebf81c84bfa34c78093c 100644 (file)
@@ -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, "<unknown_file>", 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, "<unknown_file>", 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 {
index bc5a732d7b0a0e2fb6a0809ea06e7a3ee6b5a1d7..404034df06b1759df0a3617a770436e63f7569cd 100644 (file)
@@ -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
             );
          }
       }
index f39ee006fa7a8977d2c6a4eb98e2792f2dd00a2b..9153a74ca15ec04c5078a9bd64c664b07d272ac7 100644 (file)
@@ -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 */
             );
          }
       }