addr2line.c: Implement DW_AT_*_base
... and add code to parse the sections of .debug_addr_base and .debug_rnglists_base.
This commit is contained in:
parent
515f816b7f
commit
53c82a6ce4
Notes:
git
2022-12-22 15:32:54 +00:00
114
addr2line.c
114
addr2line.c
@ -871,6 +871,9 @@ typedef struct {
|
|||||||
uint8_t current_version;
|
uint8_t current_version;
|
||||||
const char *current_cu;
|
const char *current_cu;
|
||||||
uint64_t current_low_pc;
|
uint64_t current_low_pc;
|
||||||
|
uint64_t current_str_offsets_base;
|
||||||
|
uint64_t current_addr_base;
|
||||||
|
uint64_t current_rnglists_base;
|
||||||
const char *debug_line_cu_end;
|
const char *debug_line_cu_end;
|
||||||
uint8_t debug_line_format;
|
uint8_t debug_line_format;
|
||||||
uint16_t debug_line_version;
|
uint16_t debug_line_version;
|
||||||
@ -1014,6 +1017,9 @@ debug_info_reader_init(DebugInfoReader *reader, obj_info_t *obj)
|
|||||||
reader->pend = obj->debug_info.ptr + obj->debug_info.size;
|
reader->pend = obj->debug_info.ptr + obj->debug_info.size;
|
||||||
reader->debug_line_cu_end = obj->debug_line.ptr;
|
reader->debug_line_cu_end = obj->debug_line.ptr;
|
||||||
reader->current_low_pc = 0;
|
reader->current_low_pc = 0;
|
||||||
|
reader->current_str_offsets_base = 0;
|
||||||
|
reader->current_addr_base = 0;
|
||||||
|
reader->current_rnglists_base = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -1435,6 +1441,76 @@ di_skip_records(DebugInfoReader *reader)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct addr_header {
|
||||||
|
const char *ptr;
|
||||||
|
uint64_t unit_length;
|
||||||
|
uint8_t format;
|
||||||
|
uint8_t address_size;
|
||||||
|
/* uint8_t segment_selector_size; */
|
||||||
|
} addr_header_t;
|
||||||
|
|
||||||
|
static void
|
||||||
|
addr_header_init(obj_info_t *obj, addr_header_t *header) {
|
||||||
|
const char *p = obj->debug_addr.ptr;
|
||||||
|
|
||||||
|
header->ptr = p;
|
||||||
|
|
||||||
|
if (!p) return;
|
||||||
|
|
||||||
|
header->unit_length = *(uint32_t *)p;
|
||||||
|
p += sizeof(uint32_t);
|
||||||
|
|
||||||
|
header->format = 4;
|
||||||
|
if (header->unit_length == 0xffffffff) {
|
||||||
|
header->unit_length = *(uint64_t *)p;
|
||||||
|
p += sizeof(uint64_t);
|
||||||
|
header->format = 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
p += 2; /* version */
|
||||||
|
header->address_size = *p++;
|
||||||
|
p++; /* segment_selector_size */
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint64_t
|
||||||
|
read_addr(addr_header_t *header, uint64_t addr_base, uint64_t idx) {
|
||||||
|
if (header->address_size == 4) {
|
||||||
|
return ((uint32_t*)(header->ptr + addr_base))[idx];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return ((uint64_t*)(header->ptr + addr_base))[idx];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct rnglists_header {
|
||||||
|
uint64_t unit_length;
|
||||||
|
uint8_t format;
|
||||||
|
uint8_t address_size;
|
||||||
|
uint32_t offset_entry_count;
|
||||||
|
} rnglists_header_t;
|
||||||
|
|
||||||
|
static void
|
||||||
|
rnglists_header_init(obj_info_t *obj, rnglists_header_t *header) {
|
||||||
|
const char *p = obj->debug_rnglists.ptr;
|
||||||
|
|
||||||
|
if (!p) return;
|
||||||
|
|
||||||
|
header->unit_length = *(uint32_t *)p;
|
||||||
|
p += sizeof(uint32_t);
|
||||||
|
|
||||||
|
header->format = 4;
|
||||||
|
if (header->unit_length == 0xffffffff) {
|
||||||
|
header->unit_length = *(uint64_t *)p;
|
||||||
|
p += sizeof(uint64_t);
|
||||||
|
header->format = 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
p += 2; /* version */
|
||||||
|
header->address_size = *p++;
|
||||||
|
p++; /* segment_selector_size */
|
||||||
|
header->offset_entry_count = *(uint32_t *)p;
|
||||||
|
}
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint64_t low_pc;
|
uint64_t low_pc;
|
||||||
uint64_t high_pc;
|
uint64_t high_pc;
|
||||||
@ -1650,16 +1726,45 @@ di_read_cu(DebugInfoReader *reader)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
reader->current_str_offsets_base = 0;
|
||||||
|
reader->current_addr_base = 0;
|
||||||
|
reader->current_rnglists_base = 0;
|
||||||
|
|
||||||
|
DebugInfoValue low_pc = {{}};
|
||||||
/* enumerate abbrev */
|
/* enumerate abbrev */
|
||||||
for (;;) {
|
for (;;) {
|
||||||
DebugInfoValue v = {{}};
|
DebugInfoValue v = {{}};
|
||||||
if (!di_read_record(reader, &v)) break;
|
if (!di_read_record(reader, &v)) break;
|
||||||
switch (v.at) {
|
switch (v.at) {
|
||||||
case DW_AT_low_pc:
|
case DW_AT_low_pc:
|
||||||
reader->current_low_pc = v.as.uint64;
|
// clang may output DW_AT_addr_base after DW_AT_low_pc.
|
||||||
|
// We need to resolve the DW_FORM_addr* after DW_AT_addr_base is parsed.
|
||||||
|
low_pc = v;
|
||||||
|
break;
|
||||||
|
case DW_AT_str_offsets_base:
|
||||||
|
reader->current_str_offsets_base = v.as.uint64;
|
||||||
|
break;
|
||||||
|
case DW_AT_addr_base:
|
||||||
|
reader->current_addr_base = v.as.uint64;
|
||||||
|
break;
|
||||||
|
case DW_AT_rnglists_base:
|
||||||
|
reader->current_rnglists_base = v.as.uint64;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Resolve the DW_FORM_addr of DW_AT_low_pc
|
||||||
|
switch (low_pc.type) {
|
||||||
|
case VAL_uint:
|
||||||
|
reader->current_low_pc = low_pc.as.uint64;
|
||||||
|
break;
|
||||||
|
case VAL_addr:
|
||||||
|
{
|
||||||
|
addr_header_t header;
|
||||||
|
addr_header_init(reader->obj, &header);
|
||||||
|
reader->current_low_pc = read_addr(&header, reader->current_addr_base, low_pc.as.addr_idx);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
} while (0);
|
} while (0);
|
||||||
#endif
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
@ -1713,6 +1818,13 @@ read_abstract_origin(DebugInfoReader *reader, uint64_t form, uint64_t abstract_o
|
|||||||
static void
|
static void
|
||||||
debug_info_read(DebugInfoReader *reader, int num_traces, void **traces,
|
debug_info_read(DebugInfoReader *reader, int num_traces, void **traces,
|
||||||
line_info_t *lines, int offset) {
|
line_info_t *lines, int offset) {
|
||||||
|
|
||||||
|
addr_header_t addr_header = {};
|
||||||
|
addr_header_init(reader->obj, &addr_header);
|
||||||
|
|
||||||
|
rnglists_header_t rnglists_header = {};
|
||||||
|
rnglists_header_init(reader->obj, &rnglists_header);
|
||||||
|
|
||||||
while (reader->p < reader->cu_end) {
|
while (reader->p < reader->cu_end) {
|
||||||
DIE die;
|
DIE die;
|
||||||
ranges_t ranges = {};
|
ranges_t ranges = {};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user