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; 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 static void
debug_info_reader_read_value(DebugInfoReader *reader, uint64_t form, DebugInfoValue *v) debug_info_reader_read_value(DebugInfoReader *reader, uint64_t form, DebugInfoValue *v)
{ {
switch (form) { switch (form) {
case DW_FORM_addr: case DW_FORM_addr:
if (reader->address_size == 4) { debug_info_reader_read_addr_value(reader, v);
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();
}
break; break;
case DW_FORM_block2: case DW_FORM_block2:
v->size = read_uint16(&reader->p); 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)); set_uint_value(v, read_uleb128(reader));
break; break;
case DW_FORM_ref_addr: case DW_FORM_ref_addr:
if (reader->format == 4) { if (reader->current_version <= 2) {
set_uint_value(v, read_uint32(&reader->p)); // DWARF Version 2 specifies that references have
} else if (reader->format == 8) { // the same size as an address on the target system
set_uint_value(v, read_uint64(&reader->p)); debug_info_reader_read_addr_value(reader, v);
} else { } else {
fprintf(stderr,"unknown format:%d", reader->format); if (reader->format == 4) {
abort(); 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; break;
case DW_FORM_ref1: case DW_FORM_ref1: