Skip to content

Commit

Permalink
* addr2line.c: Follow .gnu_debuglink section.
Browse files Browse the repository at this point in the history
  A user of distribution provided ruby will see line
  info if s/he has a debug package for ruby.
  patched by Shinichiro Hamaji [ruby-dev:42655]

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@29987 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
  • Loading branch information
nurse committed Dec 1, 2010
1 parent 3632f4c commit 22b2c63
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 28 deletions.
9 changes: 8 additions & 1 deletion ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
Wed Dec 1 09:28:27 2010 NARUSE, Yui <naruse@ruby-lang.org>

* addr2line.c: Follow .gnu_debuglink section.
A user of distribution provided ruby will see line
info if s/he has a debug package for ruby.
patched by Shinichiro Hamaji [ruby-dev:42655]

Wed Dec 1 07:42:42 2010 Ryan Davis <ryand-ruby@zenspider.com>

* lib/minitest/*.rb: Imported minitest 2.0.0 r5952.
Expand All @@ -23,7 +30,7 @@ Tue Nov 30 16:29:19 2010 NARUSE, Yui <naruse@ruby-lang.org>

* vm_dump.c: undef HAVE_BACKTRACE when the OS is FreeBSD (in other
words backtrace() is libexecinfo) and it is optimized.
This temporary hack should be also applied to other libexecinfo
This temporary hack may be also applied to other libexecinfo
environments.

Tue Nov 30 16:23:23 2010 NARUSE, Yui <naruse@ruby-lang.org>
Expand Down
97 changes: 70 additions & 27 deletions addr2line.c
Original file line number Diff line number Diff line change
Expand Up @@ -386,14 +386,71 @@ parse_debug_line(int num_traces, void **traces,

/* read file and fill lines */
static void
fill_lines(int num_traces, void **traces, char **syms,
char *file, line_info_t *lines)
fill_lines(int num_traces, void **traces, char **syms, int check_debuglink,
line_info_t *current_line, line_info_t *lines);

static void
follow_debuglink(char *debuglink, int num_traces, void **traces, char **syms,
line_info_t *current_line, line_info_t *lines)
{
/* 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";
char *p, *subdir;

p = strrchr(binary_filename, '/');
if (!p) {
return;
}
p[1] = '\0';

subdir = (char *)alloca(strlen(binary_filename) + 1);
strcpy(subdir, binary_filename);
strcpy(binary_filename, global_debug_dir);
strncat(binary_filename, subdir,
PATH_MAX - strlen(binary_filename) - 1);
strncat(binary_filename, debuglink,
PATH_MAX - strlen(binary_filename) - 1);

munmap(current_line->mapped, current_line->mapped_size);
close(current_line->fd);
fill_lines(num_traces, traces, syms, 0, current_line, lines);
}

/* read file and fill lines */
static void
fill_lines(int num_traces, void **traces, char **syms, int check_debuglink,
line_info_t *current_line, line_info_t *lines)
{
int i;
char *shstr;
char *section_name;
ElfW(Ehdr) *ehdr;
ElfW(Shdr) *shdr, *shstr_shdr, *debug_line_shdr = NULL;
ElfW(Shdr) *shdr, *shstr_shdr;
ElfW(Shdr) *debug_line_shdr = NULL, *gnu_debuglink_shdr = NULL;
int fd;
off_t filesize;
char *file;

fd = open(binary_filename, O_RDONLY);
if (fd < 0) {
return;
}
filesize = lseek(fd, 0, SEEK_END);
lseek(fd, 0, SEEK_SET);
/* async-signal unsafe */
file = (char *)mmap(NULL, filesize, PROT_READ, MAP_SHARED, fd, 0);
if (file == MAP_FAILED) {
int e = errno;
close(fd);
fprintf(stderr, "mmap: %s\n", strerror(e));
return;
}

current_line->fd = fd;
current_line->mapped = file;
current_line->mapped_size = filesize;

for (i = 0; i < num_traces; i++) {
const char *path;
Expand All @@ -415,11 +472,19 @@ fill_lines(int num_traces, void **traces, char **syms,
if (!strcmp(section_name, ".debug_line")) {
debug_line_shdr = shdr + i;
break;
} else if (!strcmp(section_name, ".gnu_debuglink")) {
gnu_debuglink_shdr = shdr + i;
}
}

if (!debug_line_shdr) {
/* this file doesn't have .debug_line section */
/* This file doesn't have .debug_line section,
let's check .gnu_debuglink section instead. */
if (gnu_debuglink_shdr && check_debuglink) {
follow_debuglink(file + gnu_debuglink_shdr->sh_offset,
num_traces, traces, syms,
current_line, lines);
}
return;
}

Expand Down Expand Up @@ -462,12 +527,9 @@ void
rb_dump_backtrace_with_lines(int num_traces, void **trace, char **syms)
{
int i;
int fd;
/* async-signal unsafe */
line_info_t *lines = (line_info_t *)calloc(num_traces,
sizeof(line_info_t));
off_t filesize;
char *file;

/* Note that line info of shared objects might not be shown
if we don't have dl_iterate_phdr */
Expand Down Expand Up @@ -495,26 +557,7 @@ rb_dump_backtrace_with_lines(int num_traces, void **trace, char **syms)
strncpy(binary_filename, path, len);
binary_filename[len] = '\0';

fd = open(binary_filename, O_RDONLY);
if (fd < 0) {
continue;
}
filesize = lseek(fd, 0, SEEK_END);
lseek(fd, 0, SEEK_SET);
/* async-signal unsafe */
file = (char *)mmap(NULL, filesize, PROT_READ, MAP_SHARED, fd, 0);
if (file == MAP_FAILED) {
int e = errno;
close(fd);
fprintf(stderr, "mmap: %s\n", strerror(e));
continue;
}

lines[i].fd = fd;
lines[i].mapped = file;
lines[i].mapped_size = filesize;

fill_lines(num_traces, trace, syms, file, lines);
fill_lines(num_traces, trace, syms, 1, &lines[i], lines);
}

/* fprintf may not be async-signal safe */
Expand Down

0 comments on commit 22b2c63

Please sign in to comment.