mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
Correct the handling of .debug_ranges
Though DWARF specifies "the applicable base address defaults to the base address of the compilation unit", but GCC seems to use zero as default. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@65103 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
447d7a394f
commit
e9a284ab94
1 changed files with 60 additions and 31 deletions
91
addr2line.c
91
addr2line.c
|
@ -138,6 +138,7 @@ typedef struct obj_info {
|
||||||
size_t mapped_size;
|
size_t mapped_size;
|
||||||
void *uncompressed;
|
void *uncompressed;
|
||||||
uintptr_t base_addr;
|
uintptr_t base_addr;
|
||||||
|
uintptr_t vmaddr;
|
||||||
struct dwarf_section debug_abbrev;
|
struct dwarf_section debug_abbrev;
|
||||||
struct dwarf_section debug_info;
|
struct dwarf_section debug_info;
|
||||||
struct dwarf_section debug_line;
|
struct dwarf_section debug_line;
|
||||||
|
@ -249,7 +250,7 @@ fill_line(int num_traces, void **traces, uintptr_t addr, int file, int line,
|
||||||
obj_info_t *obj, line_info_t *lines, int offset)
|
obj_info_t *obj, line_info_t *lines, int offset)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
addr += obj->base_addr;
|
addr += obj->base_addr - obj->vmaddr;
|
||||||
for (i = offset; i < num_traces; i++) {
|
for (i = offset; i < num_traces; i++) {
|
||||||
uintptr_t a = (uintptr_t)traces[i];
|
uintptr_t a = (uintptr_t)traces[i];
|
||||||
/* We assume one line code doesn't result >100 bytes of native code.
|
/* We assume one line code doesn't result >100 bytes of native code.
|
||||||
|
@ -506,6 +507,7 @@ follow_debuglink(const char *debuglink, int num_traces, void **traces,
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
|
DW_TAG_compile_unit = 0x11,
|
||||||
DW_TAG_inlined_subroutine = 0x1d,
|
DW_TAG_inlined_subroutine = 0x1d,
|
||||||
DW_TAG_subprogram = 0x2e,
|
DW_TAG_subprogram = 0x2e,
|
||||||
};
|
};
|
||||||
|
@ -734,6 +736,7 @@ typedef struct {
|
||||||
obj_info_t *obj;
|
obj_info_t *obj;
|
||||||
char *file;
|
char *file;
|
||||||
char *current_cu;
|
char *current_cu;
|
||||||
|
uint64_t current_low_pc;
|
||||||
char *debug_line_cu_end;
|
char *debug_line_cu_end;
|
||||||
char *debug_line_files;
|
char *debug_line_files;
|
||||||
char *debug_line_directories;
|
char *debug_line_directories;
|
||||||
|
@ -937,31 +940,6 @@ di_read_debug_line_cu(DebugInfoReader *reader)
|
||||||
reader->debug_line_files = p;
|
reader->debug_line_files = p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
|
||||||
di_read_cu(DebugInfoReader *reader)
|
|
||||||
{
|
|
||||||
DW_CompilationUnitHeader32 *hdr32 = (DW_CompilationUnitHeader32 *)reader->p;
|
|
||||||
reader->current_cu = reader->p;
|
|
||||||
if (hdr32->unit_length == 0xffffffff) {
|
|
||||||
DW_CompilationUnitHeader64 *hdr = (DW_CompilationUnitHeader64 *)hdr32;
|
|
||||||
reader->p += 23;
|
|
||||||
reader->q0 = reader->obj->debug_abbrev.ptr + hdr->debug_abbrev_offset;
|
|
||||||
reader->address_size = hdr->address_size;
|
|
||||||
reader->format = 64;
|
|
||||||
} else {
|
|
||||||
DW_CompilationUnitHeader32 *hdr = hdr32;
|
|
||||||
reader->p += 11;
|
|
||||||
reader->q0 = reader->obj->debug_abbrev.ptr + hdr->debug_abbrev_offset;
|
|
||||||
reader->address_size = hdr->address_size;
|
|
||||||
reader->format = 32;
|
|
||||||
}
|
|
||||||
reader->level = 0;
|
|
||||||
di_read_debug_abbrev_cu(reader);
|
|
||||||
di_read_debug_line_cu(reader);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
set_uint_value(DebugInfoValue *v, uint64_t n)
|
set_uint_value(DebugInfoValue *v, uint64_t n)
|
||||||
{
|
{
|
||||||
|
@ -1363,12 +1341,14 @@ ranges_include(DebugInfoReader *reader, ranges_t *ptr, uint64_t addr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (ptr->ranges_set) {
|
else if (ptr->ranges_set) {
|
||||||
|
/* TODO: support base address selection entry */
|
||||||
char *p = reader->obj->debug_ranges.ptr + ptr->ranges;
|
char *p = reader->obj->debug_ranges.ptr + ptr->ranges;
|
||||||
|
uint64_t base = ptr->low_pc_set ? ptr->low_pc : reader->current_low_pc;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
uintptr_t from = read_uintptr(&p);
|
uintptr_t from = read_uintptr(&p);
|
||||||
uintptr_t to = read_uintptr(&p);
|
uintptr_t to = read_uintptr(&p);
|
||||||
if (!from && !to) break;
|
if (!from && !to) break;
|
||||||
if (from <= addr && addr <= to) {
|
if (base + from <= addr && addr <= base + to) {
|
||||||
return from;
|
return from;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1413,6 +1393,56 @@ ranges_inspect(DebugInfoReader *reader, ranges_t *ptr)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static void
|
||||||
|
di_read_cu(DebugInfoReader *reader)
|
||||||
|
{
|
||||||
|
DW_CompilationUnitHeader32 *hdr32 = (DW_CompilationUnitHeader32 *)reader->p;
|
||||||
|
reader->current_cu = reader->p;
|
||||||
|
if (hdr32->unit_length == 0xffffffff) {
|
||||||
|
DW_CompilationUnitHeader64 *hdr = (DW_CompilationUnitHeader64 *)hdr32;
|
||||||
|
reader->p += 23;
|
||||||
|
reader->q0 = reader->obj->debug_abbrev.ptr + hdr->debug_abbrev_offset;
|
||||||
|
reader->address_size = hdr->address_size;
|
||||||
|
reader->format = 64;
|
||||||
|
} else {
|
||||||
|
DW_CompilationUnitHeader32 *hdr = hdr32;
|
||||||
|
reader->p += 11;
|
||||||
|
reader->q0 = reader->obj->debug_abbrev.ptr + hdr->debug_abbrev_offset;
|
||||||
|
reader->address_size = hdr->address_size;
|
||||||
|
reader->format = 32;
|
||||||
|
}
|
||||||
|
reader->level = 0;
|
||||||
|
di_read_debug_abbrev_cu(reader);
|
||||||
|
di_read_debug_line_cu(reader);
|
||||||
|
|
||||||
|
#if defined(__GNUC__) && !defined(__clang__) && !defined(__INTEL_COMPILER_BUILD_DATE)
|
||||||
|
/* Though DWARF specifies "the applicable base address defaults to the base
|
||||||
|
address of the compilation unit", but GCC seems to use zero as default */
|
||||||
|
#else
|
||||||
|
do {
|
||||||
|
DIE die;
|
||||||
|
|
||||||
|
if (!di_read_die(reader, &die)) continue;
|
||||||
|
|
||||||
|
if (die.tag != DW_TAG_compile_unit) {
|
||||||
|
di_skip_records(reader);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* enumerate abbrev */
|
||||||
|
for (;;) {
|
||||||
|
DebugInfoValue v = {{}};
|
||||||
|
if (!di_read_record(reader, &v)) break;
|
||||||
|
switch (v.at) {
|
||||||
|
case DW_AT_low_pc:
|
||||||
|
reader->current_low_pc = v.as.uint64;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
read_abstract_origin(DebugInfoReader *reader, uint64_t abstract_origin, line_info_t *line)
|
read_abstract_origin(DebugInfoReader *reader, uint64_t abstract_origin, line_info_t *line)
|
||||||
{
|
{
|
||||||
|
@ -1494,10 +1524,10 @@ debug_info_read(DebugInfoReader *reader, int num_traces, void **traces,
|
||||||
/* fprintf(stderr,"%d:%tx: %x ",__LINE__,diepos,die.tag); */
|
/* fprintf(stderr,"%d:%tx: %x ",__LINE__,diepos,die.tag); */
|
||||||
for (int i=offset; i < num_traces; i++) {
|
for (int i=offset; i < num_traces; i++) {
|
||||||
uintptr_t addr = (uintptr_t)traces[i];
|
uintptr_t addr = (uintptr_t)traces[i];
|
||||||
uintptr_t offset = addr - reader->obj->base_addr;
|
uintptr_t offset = addr - reader->obj->base_addr + reader->obj->vmaddr;
|
||||||
uintptr_t saddr = ranges_include(reader, &ranges, offset);
|
uintptr_t saddr = ranges_include(reader, &ranges, offset);
|
||||||
if (saddr) {
|
if (saddr) {
|
||||||
//fprintf(stderr, "%d:%tx: %d %lx->%lx %x %s: %s/%s %d %s %s %s\n",__LINE__,die.pos, i,addr,offset, die.tag,line.sname,line.dirname,line.filename,line.line,reader->obj->path,line.sname,lines[i].sname);
|
/* fprintf(stderr, "%d:%tx: %d %lx->%lx %x %s: %s/%s %d %s %s %s\n",__LINE__,die.pos, i,addr,offset, die.tag,line.sname,line.dirname,line.filename,line.line,reader->obj->path,line.sname,lines[i].sname); */
|
||||||
if (lines[i].sname) {
|
if (lines[i].sname) {
|
||||||
line_info_t *lp = malloc(sizeof(line_info_t));
|
line_info_t *lp = malloc(sizeof(line_info_t));
|
||||||
memcpy(lp, &lines[i], sizeof(line_info_t));
|
memcpy(lp, &lines[i], sizeof(line_info_t));
|
||||||
|
@ -1702,13 +1732,12 @@ fill_lines(int num_traces, void **traces, int check_debuglink,
|
||||||
i = 0;
|
i = 0;
|
||||||
while (reader.p < reader.pend) {
|
while (reader.p < reader.pend) {
|
||||||
//fprintf(stderr, "%d:%tx: CU[%d]\n", __LINE__, reader.p - reader.obj->debug_info, i++);
|
//fprintf(stderr, "%d:%tx: CU[%d]\n", __LINE__, reader.p - reader.obj->debug_info, i++);
|
||||||
if (di_read_cu(&reader)) goto use_symtab;
|
di_read_cu(&reader);
|
||||||
debug_info_read(&reader, num_traces, traces, lines, offset);
|
debug_info_read(&reader, num_traces, traces, lines, offset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* This file doesn't have dwarf, use symtab or dynsym */
|
/* This file doesn't have dwarf, use symtab or dynsym */
|
||||||
use_symtab:
|
|
||||||
if (!symtab_shdr) {
|
if (!symtab_shdr) {
|
||||||
/* This file doesn't have symtab, use dynsym instead */
|
/* This file doesn't have symtab, use dynsym instead */
|
||||||
symtab_shdr = dynsym_shdr;
|
symtab_shdr = dynsym_shdr;
|
||||||
|
|
Loading…
Reference in a new issue