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
This commit is contained in:
Yuta Saito 2023-08-01 03:56:53 +09:00 committed by GitHub
parent 36d669b73d
commit 954b7ac81e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
Notes: git 2023-07-31 18:57:14 +00:00
Merged-By: maximecb <maximecb@ruby-lang.org>

View File

@ -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: