Expand tabs in addr2line.c
.git-blame-ignore-revs will be updated after this commit is merged.
This commit is contained in:
parent
bd88cffd8c
commit
2da92388b9
Notes:
git
2024-11-28 16:35:01 +00:00
502
addr2line.c
502
addr2line.c
@ -56,11 +56,11 @@
|
|||||||
# ifdef _AIX
|
# ifdef _AIX
|
||||||
#pragma alloca
|
#pragma alloca
|
||||||
# else
|
# else
|
||||||
# ifndef alloca /* predefined by HP cc +Olibcalls */
|
# ifndef alloca /* predefined by HP cc +Olibcalls */
|
||||||
void *alloca();
|
void *alloca();
|
||||||
# endif
|
# endif
|
||||||
# endif /* AIX */
|
# endif /* AIX */
|
||||||
# endif /* HAVE_ALLOCA_H */
|
# endif /* HAVE_ALLOCA_H */
|
||||||
# ifndef UNREACHABLE
|
# ifndef UNREACHABLE
|
||||||
# define UNREACHABLE __builtin_unreachable()
|
# define UNREACHABLE __builtin_unreachable()
|
||||||
# endif
|
# endif
|
||||||
@ -220,13 +220,13 @@ uleb128(const char **p)
|
|||||||
unsigned long r = 0;
|
unsigned long r = 0;
|
||||||
int s = 0;
|
int s = 0;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
unsigned char b = (unsigned char)*(*p)++;
|
unsigned char b = (unsigned char)*(*p)++;
|
||||||
if (b < 0x80) {
|
if (b < 0x80) {
|
||||||
r += (unsigned long)b << s;
|
r += (unsigned long)b << s;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
r += (b & 0x7f) << s;
|
r += (b & 0x7f) << s;
|
||||||
s += 7;
|
s += 7;
|
||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
@ -237,18 +237,18 @@ sleb128(const char **p)
|
|||||||
long r = 0;
|
long r = 0;
|
||||||
int s = 0;
|
int s = 0;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
unsigned char b = (unsigned char)*(*p)++;
|
unsigned char b = (unsigned char)*(*p)++;
|
||||||
if (b < 0x80) {
|
if (b < 0x80) {
|
||||||
if (b & 0x40) {
|
if (b & 0x40) {
|
||||||
r -= (0x80 - b) << s;
|
r -= (0x80 - b) << s;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
r += (b & 0x3f) << s;
|
r += (b & 0x3f) << s;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
r += (b & 0x7f) << s;
|
r += (b & 0x7f) << s;
|
||||||
s += 7;
|
s += 7;
|
||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
@ -257,16 +257,16 @@ static const char *
|
|||||||
get_nth_dirname(unsigned long dir, const char *p, FILE *errout)
|
get_nth_dirname(unsigned long dir, const char *p, FILE *errout)
|
||||||
{
|
{
|
||||||
if (!dir--) {
|
if (!dir--) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
while (dir--) {
|
while (dir--) {
|
||||||
while (*p) p++;
|
while (*p) p++;
|
||||||
p++;
|
p++;
|
||||||
if (!*p) {
|
if (!*p) {
|
||||||
kprintf("Unexpected directory number %lu in %s\n",
|
kprintf("Unexpected directory number %lu in %s\n",
|
||||||
dir, binary_filename);
|
dir, binary_filename);
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
@ -319,19 +319,19 @@ fill_filename(int file, uint8_t format, uint16_t version, const char *include_di
|
|||||||
|
|
||||||
static void
|
static void
|
||||||
fill_line(int num_traces, void **traces, uintptr_t addr, int file, int line,
|
fill_line(int num_traces, void **traces, uintptr_t addr, int file, int line,
|
||||||
uint8_t format, uint16_t version, const char *include_directories, const char *filenames,
|
uint8_t format, uint16_t version, const char *include_directories, const char *filenames,
|
||||||
obj_info_t *obj, line_info_t *lines, int offset, FILE *errout)
|
obj_info_t *obj, line_info_t *lines, int offset, FILE *errout)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
addr += obj->base_addr - obj->vmaddr;
|
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.
|
||||||
We may want more reliable way eventually... */
|
We may want more reliable way eventually... */
|
||||||
if (addr < a && a < addr + 100) {
|
if (addr < a && a < addr + 100) {
|
||||||
fill_filename(file, format, version, include_directories, filenames, &lines[i], obj, errout);
|
fill_filename(file, format, version, include_directories, filenames, &lines[i], obj, errout);
|
||||||
lines[i].line = line;
|
lines[i].line = line;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -362,8 +362,8 @@ parse_debug_line_header(obj_info_t *obj, const char **pp, struct LineNumberProgr
|
|||||||
|
|
||||||
header->format = 4;
|
header->format = 4;
|
||||||
if (header->unit_length == 0xffffffff) {
|
if (header->unit_length == 0xffffffff) {
|
||||||
header->unit_length = *(uint64_t *)p;
|
header->unit_length = *(uint64_t *)p;
|
||||||
p += sizeof(uint64_t);
|
p += sizeof(uint64_t);
|
||||||
header->format = 8;
|
header->format = 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -427,7 +427,7 @@ parse_debug_line_header(obj_info_t *obj, const char **pp, struct LineNumberProgr
|
|||||||
|
|
||||||
static int
|
static int
|
||||||
parse_debug_line_cu(int num_traces, void **traces, const char **debug_line,
|
parse_debug_line_cu(int num_traces, void **traces, const char **debug_line,
|
||||||
obj_info_t *obj, line_info_t *lines, int offset, FILE *errout)
|
obj_info_t *obj, line_info_t *lines, int offset, FILE *errout)
|
||||||
{
|
{
|
||||||
const char *p = (const char *)*debug_line;
|
const char *p = (const char *)*debug_line;
|
||||||
struct LineNumberProgramHeader header;
|
struct LineNumberProgramHeader header;
|
||||||
@ -448,105 +448,105 @@ parse_debug_line_cu(int num_traces, void **traces, const char **debug_line,
|
|||||||
return -1;
|
return -1;
|
||||||
is_stmt = header.default_is_stmt;
|
is_stmt = header.default_is_stmt;
|
||||||
|
|
||||||
#define FILL_LINE() \
|
#define FILL_LINE() \
|
||||||
do { \
|
do { \
|
||||||
fill_line(num_traces, traces, addr, file, line, \
|
fill_line(num_traces, traces, addr, file, line, \
|
||||||
header.format, \
|
header.format, \
|
||||||
header.version, \
|
header.version, \
|
||||||
header.include_directories, \
|
header.include_directories, \
|
||||||
header.filenames, \
|
header.filenames, \
|
||||||
obj, lines, offset, errout); \
|
obj, lines, offset, errout); \
|
||||||
/*basic_block = prologue_end = epilogue_begin = 0;*/ \
|
/*basic_block = prologue_end = epilogue_begin = 0;*/ \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
while (p < header.cu_end) {
|
while (p < header.cu_end) {
|
||||||
unsigned long a;
|
unsigned long a;
|
||||||
unsigned char op = *p++;
|
unsigned char op = *p++;
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case DW_LNS_copy:
|
case DW_LNS_copy:
|
||||||
FILL_LINE();
|
FILL_LINE();
|
||||||
break;
|
break;
|
||||||
case DW_LNS_advance_pc:
|
case DW_LNS_advance_pc:
|
||||||
a = uleb128(&p) * header.minimum_instruction_length;
|
a = uleb128(&p) * header.minimum_instruction_length;
|
||||||
addr += a;
|
addr += a;
|
||||||
break;
|
break;
|
||||||
case DW_LNS_advance_line: {
|
case DW_LNS_advance_line: {
|
||||||
long a = sleb128(&p);
|
long a = sleb128(&p);
|
||||||
line += a;
|
line += a;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DW_LNS_set_file:
|
case DW_LNS_set_file:
|
||||||
file = (unsigned int)uleb128(&p);
|
file = (unsigned int)uleb128(&p);
|
||||||
break;
|
break;
|
||||||
case DW_LNS_set_column:
|
case DW_LNS_set_column:
|
||||||
/*column = (unsigned int)*/(void)uleb128(&p);
|
/*column = (unsigned int)*/(void)uleb128(&p);
|
||||||
break;
|
break;
|
||||||
case DW_LNS_negate_stmt:
|
case DW_LNS_negate_stmt:
|
||||||
is_stmt = !is_stmt;
|
is_stmt = !is_stmt;
|
||||||
break;
|
break;
|
||||||
case DW_LNS_set_basic_block:
|
case DW_LNS_set_basic_block:
|
||||||
/*basic_block = 1; */
|
/*basic_block = 1; */
|
||||||
break;
|
break;
|
||||||
case DW_LNS_const_add_pc:
|
case DW_LNS_const_add_pc:
|
||||||
a = ((255UL - header.opcode_base) / header.line_range) *
|
a = ((255UL - header.opcode_base) / header.line_range) *
|
||||||
header.minimum_instruction_length;
|
header.minimum_instruction_length;
|
||||||
addr += a;
|
addr += a;
|
||||||
break;
|
break;
|
||||||
case DW_LNS_fixed_advance_pc:
|
case DW_LNS_fixed_advance_pc:
|
||||||
a = *(uint16_t *)p;
|
a = *(uint16_t *)p;
|
||||||
p += sizeof(uint16_t);
|
p += sizeof(uint16_t);
|
||||||
addr += a;
|
addr += a;
|
||||||
break;
|
break;
|
||||||
case DW_LNS_set_prologue_end:
|
case DW_LNS_set_prologue_end:
|
||||||
/* prologue_end = 1; */
|
/* prologue_end = 1; */
|
||||||
break;
|
break;
|
||||||
case DW_LNS_set_epilogue_begin:
|
case DW_LNS_set_epilogue_begin:
|
||||||
/* epilogue_begin = 1; */
|
/* epilogue_begin = 1; */
|
||||||
break;
|
break;
|
||||||
case DW_LNS_set_isa:
|
case DW_LNS_set_isa:
|
||||||
/* isa = (unsigned int)*/(void)uleb128(&p);
|
/* isa = (unsigned int)*/(void)uleb128(&p);
|
||||||
break;
|
break;
|
||||||
case 0:
|
case 0:
|
||||||
a = uleb128(&p);
|
a = uleb128(&p);
|
||||||
op = *p++;
|
op = *p++;
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case DW_LNE_end_sequence:
|
case DW_LNE_end_sequence:
|
||||||
/* end_sequence = 1; */
|
/* end_sequence = 1; */
|
||||||
FILL_LINE();
|
FILL_LINE();
|
||||||
addr = 0;
|
addr = 0;
|
||||||
file = 1;
|
file = 1;
|
||||||
line = 1;
|
line = 1;
|
||||||
/* column = 0; */
|
/* column = 0; */
|
||||||
is_stmt = header.default_is_stmt;
|
is_stmt = header.default_is_stmt;
|
||||||
/* end_sequence = 0; */
|
/* end_sequence = 0; */
|
||||||
/* isa = 0; */
|
/* isa = 0; */
|
||||||
break;
|
break;
|
||||||
case DW_LNE_set_address:
|
case DW_LNE_set_address:
|
||||||
addr = *(unsigned long *)p;
|
addr = *(unsigned long *)p;
|
||||||
p += sizeof(unsigned long);
|
p += sizeof(unsigned long);
|
||||||
break;
|
break;
|
||||||
case DW_LNE_define_file:
|
case DW_LNE_define_file:
|
||||||
kprintf("Unsupported operation in %s\n",
|
kprintf("Unsupported operation in %s\n",
|
||||||
binary_filename);
|
binary_filename);
|
||||||
break;
|
break;
|
||||||
case DW_LNE_set_discriminator:
|
case DW_LNE_set_discriminator:
|
||||||
/* TODO:currently ignore */
|
/* TODO:currently ignore */
|
||||||
uleb128(&p);
|
uleb128(&p);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
kprintf("Unknown extended opcode: %d in %s\n",
|
kprintf("Unknown extended opcode: %d in %s\n",
|
||||||
op, binary_filename);
|
op, binary_filename);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default: {
|
default: {
|
||||||
uint8_t adjusted_opcode = op - header.opcode_base;
|
uint8_t adjusted_opcode = op - header.opcode_base;
|
||||||
uint8_t operation_advance = adjusted_opcode / header.line_range;
|
uint8_t operation_advance = adjusted_opcode / header.line_range;
|
||||||
/* NOTE: this code doesn't support VLIW */
|
/* NOTE: this code doesn't support VLIW */
|
||||||
addr += operation_advance * header.minimum_instruction_length;
|
addr += operation_advance * header.minimum_instruction_length;
|
||||||
line += header.line_base + (adjusted_opcode % header.line_range);
|
line += header.line_base + (adjusted_opcode % header.line_range);
|
||||||
FILL_LINE();
|
FILL_LINE();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*debug_line = (char *)p;
|
*debug_line = (char *)p;
|
||||||
return 0;
|
return 0;
|
||||||
@ -554,17 +554,17 @@ parse_debug_line_cu(int num_traces, void **traces, const char **debug_line,
|
|||||||
|
|
||||||
static int
|
static int
|
||||||
parse_debug_line(int num_traces, void **traces,
|
parse_debug_line(int num_traces, void **traces,
|
||||||
const char *debug_line, unsigned long size,
|
const char *debug_line, unsigned long size,
|
||||||
obj_info_t *obj, line_info_t *lines, int offset, FILE *errout)
|
obj_info_t *obj, line_info_t *lines, int offset, FILE *errout)
|
||||||
{
|
{
|
||||||
const char *debug_line_end = debug_line + size;
|
const char *debug_line_end = debug_line + size;
|
||||||
while (debug_line < debug_line_end) {
|
while (debug_line < debug_line_end) {
|
||||||
if (parse_debug_line_cu(num_traces, traces, &debug_line, obj, lines, offset, errout))
|
if (parse_debug_line_cu(num_traces, traces, &debug_line, obj, lines, offset, errout))
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (debug_line != debug_line_end) {
|
if (debug_line != debug_line_end) {
|
||||||
kprintf("Unexpected size of .debug_line in %s\n",
|
kprintf("Unexpected size of .debug_line in %s\n",
|
||||||
binary_filename);
|
binary_filename);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -572,7 +572,7 @@ parse_debug_line(int num_traces, void **traces,
|
|||||||
/* read file and fill lines */
|
/* read file and fill lines */
|
||||||
static uintptr_t
|
static uintptr_t
|
||||||
fill_lines(int num_traces, void **traces, int check_debuglink,
|
fill_lines(int num_traces, void **traces, int check_debuglink,
|
||||||
obj_info_t **objp, line_info_t *lines, int offset, FILE *errout);
|
obj_info_t **objp, line_info_t *lines, int offset, FILE *errout);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
append_obj(obj_info_t **objp)
|
append_obj(obj_info_t **objp)
|
||||||
@ -600,7 +600,7 @@ append_obj(obj_info_t **objp)
|
|||||||
// check the path pattern of "/usr/lib/debug/usr/bin/ruby.debug"
|
// check the path pattern of "/usr/lib/debug/usr/bin/ruby.debug"
|
||||||
static void
|
static void
|
||||||
follow_debuglink(const char *debuglink, int num_traces, void **traces,
|
follow_debuglink(const char *debuglink, int num_traces, void **traces,
|
||||||
obj_info_t **objp, line_info_t *lines, int offset, FILE *errout)
|
obj_info_t **objp, line_info_t *lines, int offset, FILE *errout)
|
||||||
{
|
{
|
||||||
static const char global_debug_dir[] = "/usr/lib/debug";
|
static const char global_debug_dir[] = "/usr/lib/debug";
|
||||||
const size_t global_debug_dir_len = sizeof(global_debug_dir) - 1;
|
const size_t global_debug_dir_len = sizeof(global_debug_dir) - 1;
|
||||||
@ -610,13 +610,13 @@ follow_debuglink(const char *debuglink, int num_traces, void **traces,
|
|||||||
|
|
||||||
p = strrchr(binary_filename, '/');
|
p = strrchr(binary_filename, '/');
|
||||||
if (!p) {
|
if (!p) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
p[1] = '\0';
|
p[1] = '\0';
|
||||||
|
|
||||||
len = strlen(binary_filename);
|
len = strlen(binary_filename);
|
||||||
if (len >= PATH_MAX - global_debug_dir_len)
|
if (len >= PATH_MAX - global_debug_dir_len)
|
||||||
len = PATH_MAX - global_debug_dir_len - 1;
|
len = PATH_MAX - global_debug_dir_len - 1;
|
||||||
memmove(binary_filename + global_debug_dir_len, binary_filename, len);
|
memmove(binary_filename + global_debug_dir_len, binary_filename, len);
|
||||||
memcpy(binary_filename, global_debug_dir, global_debug_dir_len);
|
memcpy(binary_filename, global_debug_dir, global_debug_dir_len);
|
||||||
len += global_debug_dir_len;
|
len += global_debug_dir_len;
|
||||||
@ -2029,14 +2029,14 @@ uncompress_debug_section(ElfW(Shdr) *shdr, char *file, char **ptr)
|
|||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
if (chdr->ch_type != ELFCOMPRESS_ZLIB) {
|
if (chdr->ch_type != ELFCOMPRESS_ZLIB) {
|
||||||
/* unsupported compression type */
|
/* unsupported compression type */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
*ptr = malloc(destsize);
|
*ptr = malloc(destsize);
|
||||||
if (!*ptr) return 0;
|
if (!*ptr) return 0;
|
||||||
ret = uncompress((Bytef *)*ptr, &destsize,
|
ret = uncompress((Bytef *)*ptr, &destsize,
|
||||||
(const Bytef*)chdr + sizeof(ElfW(Chdr)),
|
(const Bytef*)chdr + sizeof(ElfW(Chdr)),
|
||||||
shdr->sh_size - sizeof(ElfW(Chdr)));
|
shdr->sh_size - sizeof(ElfW(Chdr)));
|
||||||
if (ret != Z_OK) goto fail;
|
if (ret != Z_OK) goto fail;
|
||||||
return destsize;
|
return destsize;
|
||||||
@ -2051,7 +2051,7 @@ fail:
|
|||||||
/* read file and fill lines */
|
/* read file and fill lines */
|
||||||
static uintptr_t
|
static uintptr_t
|
||||||
fill_lines(int num_traces, void **traces, int check_debuglink,
|
fill_lines(int num_traces, void **traces, int check_debuglink,
|
||||||
obj_info_t **objp, line_info_t *lines, int offset, FILE *errout)
|
obj_info_t **objp, line_info_t *lines, int offset, FILE *errout)
|
||||||
{
|
{
|
||||||
int i, j;
|
int i, j;
|
||||||
char *shstr;
|
char *shstr;
|
||||||
@ -2069,40 +2069,40 @@ fill_lines(int num_traces, void **traces, int check_debuglink,
|
|||||||
|
|
||||||
fd = open(binary_filename, O_RDONLY);
|
fd = open(binary_filename, O_RDONLY);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
filesize = lseek(fd, 0, SEEK_END);
|
filesize = lseek(fd, 0, SEEK_END);
|
||||||
if (filesize < 0) {
|
if (filesize < 0) {
|
||||||
int e = errno;
|
int e = errno;
|
||||||
close(fd);
|
close(fd);
|
||||||
kprintf("lseek: %s\n", strerror(e));
|
kprintf("lseek: %s\n", strerror(e));
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
#if SIZEOF_OFF_T > SIZEOF_SIZE_T
|
#if SIZEOF_OFF_T > SIZEOF_SIZE_T
|
||||||
if (filesize > (off_t)SIZE_MAX) {
|
if (filesize > (off_t)SIZE_MAX) {
|
||||||
close(fd);
|
close(fd);
|
||||||
kprintf("Too large file %s\n", binary_filename);
|
kprintf("Too large file %s\n", binary_filename);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
lseek(fd, 0, SEEK_SET);
|
lseek(fd, 0, SEEK_SET);
|
||||||
/* async-signal unsafe */
|
/* async-signal unsafe */
|
||||||
file = (char *)mmap(NULL, (size_t)filesize, PROT_READ, MAP_SHARED, fd, 0);
|
file = (char *)mmap(NULL, (size_t)filesize, PROT_READ, MAP_SHARED, fd, 0);
|
||||||
if (file == MAP_FAILED) {
|
if (file == MAP_FAILED) {
|
||||||
int e = errno;
|
int e = errno;
|
||||||
close(fd);
|
close(fd);
|
||||||
kprintf("mmap: %s\n", strerror(e));
|
kprintf("mmap: %s\n", strerror(e));
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
close(fd);
|
close(fd);
|
||||||
|
|
||||||
ehdr = (ElfW(Ehdr) *)file;
|
ehdr = (ElfW(Ehdr) *)file;
|
||||||
if (memcmp(ehdr->e_ident, "\177ELF", 4) != 0) {
|
if (memcmp(ehdr->e_ident, "\177ELF", 4) != 0) {
|
||||||
/*
|
/*
|
||||||
* Huh? Maybe filename was overridden by setproctitle() and
|
* Huh? Maybe filename was overridden by setproctitle() and
|
||||||
* it match non-elf file.
|
* it match non-elf file.
|
||||||
*/
|
*/
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
obj->mapped = file;
|
obj->mapped = file;
|
||||||
obj->mapped_size = (size_t)filesize;
|
obj->mapped_size = (size_t)filesize;
|
||||||
@ -2114,32 +2114,32 @@ fill_lines(int num_traces, void **traces, int check_debuglink,
|
|||||||
|
|
||||||
for (i = 0; i < ehdr->e_shnum; i++) {
|
for (i = 0; i < ehdr->e_shnum; i++) {
|
||||||
char *section_name = shstr + shdr[i].sh_name;
|
char *section_name = shstr + shdr[i].sh_name;
|
||||||
switch (shdr[i].sh_type) {
|
switch (shdr[i].sh_type) {
|
||||||
case SHT_STRTAB:
|
case SHT_STRTAB:
|
||||||
if (!strcmp(section_name, ".strtab")) {
|
if (!strcmp(section_name, ".strtab")) {
|
||||||
strtab_shdr = shdr + i;
|
strtab_shdr = shdr + i;
|
||||||
}
|
}
|
||||||
else if (!strcmp(section_name, ".dynstr")) {
|
else if (!strcmp(section_name, ".dynstr")) {
|
||||||
dynstr_shdr = shdr + i;
|
dynstr_shdr = shdr + i;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SHT_SYMTAB:
|
case SHT_SYMTAB:
|
||||||
/* if (!strcmp(section_name, ".symtab")) */
|
/* if (!strcmp(section_name, ".symtab")) */
|
||||||
symtab_shdr = shdr + i;
|
symtab_shdr = shdr + i;
|
||||||
break;
|
break;
|
||||||
case SHT_DYNSYM:
|
case SHT_DYNSYM:
|
||||||
/* if (!strcmp(section_name, ".dynsym")) */
|
/* if (!strcmp(section_name, ".dynsym")) */
|
||||||
dynsym_shdr = shdr + i;
|
dynsym_shdr = shdr + i;
|
||||||
break;
|
break;
|
||||||
case SHT_NOTE:
|
case SHT_NOTE:
|
||||||
if (!strcmp(section_name, ".note.gnu.build-id")) {
|
if (!strcmp(section_name, ".note.gnu.build-id")) {
|
||||||
note_gnu_build_id = shdr + i;
|
note_gnu_build_id = shdr + i;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SHT_PROGBITS:
|
case SHT_PROGBITS:
|
||||||
if (!strcmp(section_name, ".gnu_debuglink")) {
|
if (!strcmp(section_name, ".gnu_debuglink")) {
|
||||||
gnu_debuglink_shdr = shdr + i;
|
gnu_debuglink_shdr = shdr + i;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
const char *debug_section_names[] = {
|
const char *debug_section_names[] = {
|
||||||
".debug_abbrev",
|
".debug_abbrev",
|
||||||
@ -2169,17 +2169,17 @@ fill_lines(int num_traces, void **traces, int check_debuglink,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (offset == -1) {
|
if (offset == -1) {
|
||||||
/* main executable */
|
/* main executable */
|
||||||
offset = 0;
|
offset = 0;
|
||||||
if (dynsym_shdr && dynstr_shdr) {
|
if (dynsym_shdr && dynstr_shdr) {
|
||||||
char *strtab = file + dynstr_shdr->sh_offset;
|
char *strtab = file + dynstr_shdr->sh_offset;
|
||||||
ElfW(Sym) *symtab = (ElfW(Sym) *)(file + dynsym_shdr->sh_offset);
|
ElfW(Sym) *symtab = (ElfW(Sym) *)(file + dynsym_shdr->sh_offset);
|
||||||
int symtab_count = (int)(dynsym_shdr->sh_size / sizeof(ElfW(Sym)));
|
int symtab_count = (int)(dynsym_shdr->sh_size / sizeof(ElfW(Sym)));
|
||||||
void *handle = dlopen(NULL, RTLD_NOW|RTLD_LOCAL);
|
void *handle = dlopen(NULL, RTLD_NOW|RTLD_LOCAL);
|
||||||
if (handle) {
|
if (handle) {
|
||||||
for (j = 0; j < symtab_count; j++) {
|
for (j = 0; j < symtab_count; j++) {
|
||||||
@ -2196,14 +2196,14 @@ fill_lines(int num_traces, void **traces, int check_debuglink,
|
|||||||
}
|
}
|
||||||
dlclose(handle);
|
dlclose(handle);
|
||||||
}
|
}
|
||||||
if (ehdr->e_type == ET_EXEC) {
|
if (ehdr->e_type == ET_EXEC) {
|
||||||
obj->base_addr = 0;
|
obj->base_addr = 0;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* PIE (position-independent executable) */
|
/* PIE (position-independent executable) */
|
||||||
obj->base_addr = dladdr_fbase;
|
obj->base_addr = dladdr_fbase;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (obj->debug_info.ptr && obj->debug_abbrev.ptr) {
|
if (obj->debug_info.ptr && obj->debug_abbrev.ptr) {
|
||||||
@ -2249,21 +2249,21 @@ use_symtab:
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!obj->debug_line.ptr) {
|
if (!obj->debug_line.ptr) {
|
||||||
/* This file doesn't have .debug_line section,
|
/* This file doesn't have .debug_line section,
|
||||||
let's check .gnu_debuglink section instead. */
|
let's check .gnu_debuglink section instead. */
|
||||||
if (gnu_debuglink_shdr && check_debuglink) {
|
if (gnu_debuglink_shdr && check_debuglink) {
|
||||||
follow_debuglink(file + gnu_debuglink_shdr->sh_offset,
|
follow_debuglink(file + gnu_debuglink_shdr->sh_offset,
|
||||||
num_traces, traces,
|
num_traces, traces,
|
||||||
objp, lines, offset, errout);
|
objp, lines, offset, errout);
|
||||||
}
|
}
|
||||||
if (note_gnu_build_id && check_debuglink) {
|
if (note_gnu_build_id && check_debuglink) {
|
||||||
ElfW(Nhdr) *nhdr = (ElfW(Nhdr)*) (file + note_gnu_build_id->sh_offset);
|
ElfW(Nhdr) *nhdr = (ElfW(Nhdr)*) (file + note_gnu_build_id->sh_offset);
|
||||||
const char *build_id = (char *)(nhdr + 1) + nhdr->n_namesz;
|
const char *build_id = (char *)(nhdr + 1) + nhdr->n_namesz;
|
||||||
follow_debuglink_build_id(build_id, nhdr->n_descsz,
|
follow_debuglink_build_id(build_id, nhdr->n_descsz,
|
||||||
num_traces, traces,
|
num_traces, traces,
|
||||||
objp, lines, offset, errout);
|
objp, lines, offset, errout);
|
||||||
}
|
}
|
||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parse_debug_line(num_traces, traces,
|
if (parse_debug_line(num_traces, traces,
|
||||||
@ -2543,8 +2543,8 @@ main_exe_path(FILE *errout)
|
|||||||
size_t len = PATH_MAX;
|
size_t len = PATH_MAX;
|
||||||
int err = sysctl(mib, 4, binary_filename, &len, NULL, 0);
|
int err = sysctl(mib, 4, binary_filename, &len, NULL, 0);
|
||||||
if (err) {
|
if (err) {
|
||||||
kprintf("Can't get the path of ruby");
|
kprintf("Can't get the path of ruby");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
len--; /* sysctl sets strlen+1 */
|
len--; /* sysctl sets strlen+1 */
|
||||||
return len;
|
return len;
|
||||||
@ -2626,79 +2626,79 @@ rb_dump_backtrace_with_lines(int num_traces, void **traces, FILE *errout)
|
|||||||
char *main_path = NULL; /* used on printing backtrace */
|
char *main_path = NULL; /* used on printing backtrace */
|
||||||
ssize_t len;
|
ssize_t len;
|
||||||
if ((len = main_exe_path(errout)) > 0) {
|
if ((len = main_exe_path(errout)) > 0) {
|
||||||
main_path = (char *)alloca(len + 1);
|
main_path = (char *)alloca(len + 1);
|
||||||
if (main_path) {
|
if (main_path) {
|
||||||
uintptr_t addr;
|
uintptr_t addr;
|
||||||
memcpy(main_path, binary_filename, len+1);
|
memcpy(main_path, binary_filename, len+1);
|
||||||
append_obj(&obj);
|
append_obj(&obj);
|
||||||
obj->path = main_path;
|
obj->path = main_path;
|
||||||
addr = fill_lines(num_traces, traces, 1, &obj, lines, 0, errout);
|
addr = fill_lines(num_traces, traces, 1, &obj, lines, 0, errout);
|
||||||
if (addr != (uintptr_t)-1) {
|
if (addr != (uintptr_t)-1) {
|
||||||
dladdr_fbases[0] = (void *)addr;
|
dladdr_fbases[0] = (void *)addr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* fill source lines by reading dwarf */
|
/* fill source lines by reading dwarf */
|
||||||
for (i = 0; i < num_traces; i++) {
|
for (i = 0; i < num_traces; i++) {
|
||||||
Dl_info info;
|
Dl_info info;
|
||||||
if (lines[i].line) continue;
|
if (lines[i].line) continue;
|
||||||
if (dladdr(traces[i], &info)) {
|
if (dladdr(traces[i], &info)) {
|
||||||
const char *path;
|
const char *path;
|
||||||
void **p;
|
void **p;
|
||||||
|
|
||||||
/* skip symbols which is in already checked objects */
|
/* skip symbols which is in already checked objects */
|
||||||
/* if the binary is strip-ed, this may effect */
|
/* if the binary is strip-ed, this may effect */
|
||||||
for (p=dladdr_fbases; *p; p++) {
|
for (p=dladdr_fbases; *p; p++) {
|
||||||
if (*p == info.dli_fbase) {
|
if (*p == info.dli_fbase) {
|
||||||
if (info.dli_fname) lines[i].path = info.dli_fname;
|
if (info.dli_fname) lines[i].path = info.dli_fname;
|
||||||
if (info.dli_sname) lines[i].sname = info.dli_sname;
|
if (info.dli_sname) lines[i].sname = info.dli_sname;
|
||||||
goto next_line;
|
goto next_line;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*p = info.dli_fbase;
|
*p = info.dli_fbase;
|
||||||
|
|
||||||
append_obj(&obj);
|
append_obj(&obj);
|
||||||
obj->base_addr = (uintptr_t)info.dli_fbase;
|
obj->base_addr = (uintptr_t)info.dli_fbase;
|
||||||
path = info.dli_fname;
|
path = info.dli_fname;
|
||||||
obj->path = path;
|
obj->path = path;
|
||||||
if (path) lines[i].path = path;
|
if (path) lines[i].path = path;
|
||||||
if (info.dli_sname) {
|
if (info.dli_sname) {
|
||||||
lines[i].sname = info.dli_sname;
|
lines[i].sname = info.dli_sname;
|
||||||
lines[i].saddr = (uintptr_t)info.dli_saddr;
|
lines[i].saddr = (uintptr_t)info.dli_saddr;
|
||||||
}
|
}
|
||||||
strlcpy(binary_filename, path, PATH_MAX);
|
strlcpy(binary_filename, path, PATH_MAX);
|
||||||
if (fill_lines(num_traces, traces, 1, &obj, lines, i, errout) == (uintptr_t)-1)
|
if (fill_lines(num_traces, traces, 1, &obj, lines, i, errout) == (uintptr_t)-1)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
next_line:
|
next_line:
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* output */
|
/* output */
|
||||||
for (i = 0; i < num_traces; i++) {
|
for (i = 0; i < num_traces; i++) {
|
||||||
print_line(&lines[i], traces[i], errout);
|
print_line(&lines[i], traces[i], errout);
|
||||||
|
|
||||||
/* FreeBSD's backtrace may show _start and so on */
|
/* FreeBSD's backtrace may show _start and so on */
|
||||||
if (lines[i].sname && strcmp("main", lines[i].sname) == 0)
|
if (lines[i].sname && strcmp("main", lines[i].sname) == 0)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* free */
|
/* free */
|
||||||
while (obj) {
|
while (obj) {
|
||||||
obj_info_t *o = obj;
|
obj_info_t *o = obj;
|
||||||
for (i=0; i < DWARF_SECTION_COUNT; i++) {
|
for (i=0; i < DWARF_SECTION_COUNT; i++) {
|
||||||
struct dwarf_section *s = obj_dwarf_section_at(obj, i);
|
struct dwarf_section *s = obj_dwarf_section_at(obj, i);
|
||||||
if (s->flags & SHF_COMPRESSED) {
|
if (s->flags & SHF_COMPRESSED) {
|
||||||
free(s->ptr);
|
free(s->ptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (obj->mapped_size) {
|
if (obj->mapped_size) {
|
||||||
munmap(obj->mapped, obj->mapped_size);
|
munmap(obj->mapped, obj->mapped_size);
|
||||||
}
|
}
|
||||||
obj = o->next;
|
obj = o->next;
|
||||||
free(o);
|
free(o);
|
||||||
}
|
}
|
||||||
for (i = 0; i < num_traces; i++) {
|
for (i = 0; i < num_traces; i++) {
|
||||||
line_info_t *line = lines[i].next;
|
line_info_t *line = lines[i].next;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user