diff options
author | Yuta Saito <kateinoigakukun@gmail.com> | 2023-08-01 03:56:53 +0900 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-07-31 14:56:53 -0400 |
commit | 954b7ac81ef503df3c1efc5566df985b08951d52 (patch) | |
tree | 5d325620fa06c8035de13713adcde74ff3630d68 /addr2line.c | |
parent | 36d669b73db26368cb9492231be4b3d4ed97f111 (diff) |
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
Notes
Notes:
Merged-By: maximecb <maximecb@ruby-lang.org>
Diffstat (limited to 'addr2line.c')
-rw-r--r-- | addr2line.c | 40 |
1 files changed, 26 insertions, 14 deletions
diff --git a/addr2line.c b/addr2line.c index 1616ec9855..1b261e3c5b 100644 --- a/addr2line.c +++ b/addr2line.c @@ -1153,18 +1153,24 @@ resolve_strx(DebugInfoReader *reader, uint64_t idx) } 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: |