merge revision(s) 954b7ac81e: [Backport #19789]

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(-)
This commit is contained in:
nagachika 2023-08-12 13:46:25 +09:00
parent 1c76244698
commit 19823032ab
2 changed files with 27 additions and 15 deletions

View file

@ -1144,19 +1144,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);
@ -1208,13 +1214,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:

View file

@ -11,7 +11,7 @@
# define RUBY_VERSION_MINOR RUBY_API_VERSION_MINOR
#define RUBY_VERSION_TEENY 2
#define RUBY_RELEASE_DATE RUBY_RELEASE_YEAR_STR"-"RUBY_RELEASE_MONTH_STR"-"RUBY_RELEASE_DAY_STR
#define RUBY_PATCHLEVEL 107
#define RUBY_PATCHLEVEL 108
#include "ruby/version.h"
#include "ruby/internal/abi.h"