mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
addr2line.c: support debuglink by build_id
Currently, addr2line.c supports only one path format of debuglink: "/usr/lib/debug/usr/bin/ruby.debug". However, recent debian packages seem to use another format by build_id: "/usr/lib/debug/.build-id/ab/cdef1234.debug".5d1bb29841/dh_strip (L292)
5d1bb29841/dh_strip (L353)
This changeset makes ruby backtrace support the second format.
This commit is contained in:
parent
8c5ec10038
commit
c718c30007
Notes:
git
2020-12-11 14:09:00 +09:00
1 changed files with 59 additions and 3 deletions
62
addr2line.c
62
addr2line.c
|
@ -526,13 +526,25 @@ append_obj(obj_info_t **objp)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef USE_ELF
|
#ifdef USE_ELF
|
||||||
|
/* Ideally we should check 4 paths to follow gnu_debuglink:
|
||||||
|
*
|
||||||
|
* - /usr/lib/debug/.build-id/ab/cdef1234.debug
|
||||||
|
* - /usr/bin/ruby.debug
|
||||||
|
* - /usr/bin/.debug/ruby.debug
|
||||||
|
* - /usr/lib/debug/usr/bin/ruby.debug.
|
||||||
|
*
|
||||||
|
* but we handle only two cases for now as the two formats are
|
||||||
|
* used by some linux distributions.
|
||||||
|
*
|
||||||
|
* See GDB's info for detail.
|
||||||
|
* https://sourceware.org/gdb/onlinedocs/gdb/Separate-Debug-Files.html
|
||||||
|
*/
|
||||||
|
|
||||||
|
// 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)
|
obj_info_t **objp, line_info_t *lines, int offset)
|
||||||
{
|
{
|
||||||
/* Ideally we should check 4 paths to follow gnu_debuglink,
|
|
||||||
but we handle only one case for now as this format is used
|
|
||||||
by some linux distributions. See GDB's info for detail. */
|
|
||||||
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;
|
||||||
char *p;
|
char *p;
|
||||||
|
@ -559,6 +571,37 @@ follow_debuglink(const char *debuglink, int num_traces, void **traces,
|
||||||
o2->path = o1->path;
|
o2->path = o1->path;
|
||||||
fill_lines(num_traces, traces, 0, objp, lines, offset);
|
fill_lines(num_traces, traces, 0, objp, lines, offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check the path pattern of "/usr/lib/debug/.build-id/ab/cdef1234.debug"
|
||||||
|
static void
|
||||||
|
follow_debuglink_build_id(const char *build_id, size_t build_id_size, int num_traces, void **traces,
|
||||||
|
obj_info_t **objp, line_info_t *lines, int offset)
|
||||||
|
{
|
||||||
|
static const char global_debug_dir[] = "/usr/lib/debug/.build-id/";
|
||||||
|
const size_t global_debug_dir_len = sizeof(global_debug_dir) - 1;
|
||||||
|
char *p;
|
||||||
|
obj_info_t *o1 = *objp, *o2;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
if (PATH_MAX < global_debug_dir_len + 1 + build_id_size * 2 + 6) return;
|
||||||
|
|
||||||
|
memcpy(binary_filename, global_debug_dir, global_debug_dir_len);
|
||||||
|
p = binary_filename + global_debug_dir_len;
|
||||||
|
for (i = 0; i < build_id_size; i++) {
|
||||||
|
static const char tbl[] = "0123456789abcdef";
|
||||||
|
unsigned char n = build_id[i];
|
||||||
|
*p++ = tbl[n / 16];
|
||||||
|
*p++ = tbl[n % 16];
|
||||||
|
if (i == 0) *p++ = '/';
|
||||||
|
}
|
||||||
|
strcpy(p, ".debug");
|
||||||
|
|
||||||
|
append_obj(objp);
|
||||||
|
o2 = *objp;
|
||||||
|
o2->base_addr = o1->base_addr;
|
||||||
|
o2->path = o1->path;
|
||||||
|
fill_lines(num_traces, traces, 0, objp, lines, offset);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
enum
|
enum
|
||||||
|
@ -1616,6 +1659,7 @@ fill_lines(int num_traces, void **traces, int check_debuglink,
|
||||||
ElfW(Ehdr) *ehdr;
|
ElfW(Ehdr) *ehdr;
|
||||||
ElfW(Shdr) *shdr, *shstr_shdr;
|
ElfW(Shdr) *shdr, *shstr_shdr;
|
||||||
ElfW(Shdr) *gnu_debuglink_shdr = NULL;
|
ElfW(Shdr) *gnu_debuglink_shdr = NULL;
|
||||||
|
ElfW(Shdr) *note_gnu_build_id = NULL;
|
||||||
int fd;
|
int fd;
|
||||||
off_t filesize;
|
off_t filesize;
|
||||||
char *file;
|
char *file;
|
||||||
|
@ -1688,6 +1732,11 @@ fill_lines(int num_traces, void **traces, int check_debuglink,
|
||||||
/* if (!strcmp(section_name, ".dynsym")) */
|
/* if (!strcmp(section_name, ".dynsym")) */
|
||||||
dynsym_shdr = shdr + i;
|
dynsym_shdr = shdr + i;
|
||||||
break;
|
break;
|
||||||
|
case SHT_NOTE:
|
||||||
|
if (!strcmp(section_name, ".note.gnu.build-id")) {
|
||||||
|
note_gnu_build_id = shdr + i;
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
@ -1803,6 +1852,13 @@ use_symtab:
|
||||||
num_traces, traces,
|
num_traces, traces,
|
||||||
objp, lines, offset);
|
objp, lines, offset);
|
||||||
}
|
}
|
||||||
|
if (note_gnu_build_id && check_debuglink) {
|
||||||
|
ElfW(Nhdr) *nhdr = (ElfW(Nhdr)*) (file + note_gnu_build_id->sh_offset);
|
||||||
|
const char *build_id = (char *)(nhdr + 1) + nhdr->n_namesz;
|
||||||
|
follow_debuglink_build_id(build_id, nhdr->n_descsz,
|
||||||
|
num_traces, traces,
|
||||||
|
objp, lines, offset);
|
||||||
|
}
|
||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue