From 954b7ac81ef503df3c1efc5566df985b08951d52 Mon Sep 17 00:00:00 2001 From: Yuta Saito Date: Tue, 1 Aug 2023 03:56:53 +0900 Subject: [PATCH] addr2line.c: fix `DW_FORM_ref_addr` parsing for DWARF 2 (#8146) addr2line.c: fix DW_FORM_ref_addr parsing for DWARF 2 This fixes a crash when retrieving backtrace info with YJIT enabled on macOS with Rust 1.71.0. Since Rust 1.71.0, the DWARF info generated by the Rust compiler uses DW_FORM_ref_addr instead of DW_FORM_ref4 for pointers to other DIEs. DW_FORM_ref_addr representation in DWARF 2 is different from DWARF 3+, so we need to handle it separately. This patch fixes the parsing of DW_FORM_ref_addr for DWARF 2, which is the default DWARF version Rustc uses on macOS. See the DWARF 2.0.0 spec, section 7.5.4 Attribute Encodings https://dwarfstd.org/doc/dwarf-2.0.0.pdf https://bugs.ruby-lang.org/issues/19789 --- addr2line.c | 40 ++++++++++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/addr2line.c b/addr2line.c index 1616ec9855..1b261e3c5b 100644 --- a/addr2line.c +++ b/addr2line.c @@ -1152,19 +1152,25 @@ resolve_strx(DebugInfoReader *reader, uint64_t idx) return reader->obj->debug_str.ptr + off; } +static void +debug_info_reader_read_addr_value(DebugInfoReader *reader, DebugInfoValue *v) +{ + if (reader->address_size == 4) { + set_uint_value(v, read_uint32(&reader->p)); + } else if (reader->address_size == 8) { + set_uint_value(v, read_uint64(&reader->p)); + } else { + fprintf(stderr,"unknown address_size:%d", reader->address_size); + abort(); + } +} + static void debug_info_reader_read_value(DebugInfoReader *reader, uint64_t form, DebugInfoValue *v) { switch (form) { case DW_FORM_addr: - if (reader->address_size == 4) { - set_uint_value(v, read_uint32(&reader->p)); - } else if (reader->address_size == 8) { - set_uint_value(v, read_uint64(&reader->p)); - } else { - fprintf(stderr,"unknown address_size:%d", reader->address_size); - abort(); - } + debug_info_reader_read_addr_value(reader, v); break; case DW_FORM_block2: v->size = read_uint16(&reader->p); @@ -1216,13 +1222,19 @@ debug_info_reader_read_value(DebugInfoReader *reader, uint64_t form, DebugInfoVa set_uint_value(v, read_uleb128(reader)); break; case DW_FORM_ref_addr: - if (reader->format == 4) { - set_uint_value(v, read_uint32(&reader->p)); - } else if (reader->format == 8) { - set_uint_value(v, read_uint64(&reader->p)); + if (reader->current_version <= 2) { + // DWARF Version 2 specifies that references have + // the same size as an address on the target system + debug_info_reader_read_addr_value(reader, v); } else { - fprintf(stderr,"unknown format:%d", reader->format); - abort(); + if (reader->format == 4) { + set_uint_value(v, read_uint32(&reader->p)); + } else if (reader->format == 8) { + set_uint_value(v, read_uint64(&reader->p)); + } else { + fprintf(stderr,"unknown format:%d", reader->format); + abort(); + } } break; case DW_FORM_ref1: