Project

General

Profile

Actions

Feature #4096

closed

Follow .gnu_debuglink section.

Added by shinh (Shinichiro Hamaji) over 13 years ago. Updated about 13 years ago.

Status:
Closed
Assignee:
-
Target version:
-
[ruby-dev:42655]

Description

=begin
浜地です。

先日取り込んでいただいた行情報のパッチですが、
ディストリビューションなんかが配布する ruby バイナリは、

debug 情報を持っていない

/usr/bin/ruby

debug 情報を持っている

debug package をインストールした場合に存在する。

/usr/lib/debug/usr/bin/ruby

とかいう感じで二つに別れています。
バグレポートする人の中には debug package を入れている人も
いるかもしれませんし、これに対応するのは一定の価値があるかもなぁ
ということで書いたパッチです。

Subject: [PATCH] Follow .gnu_debuglink section.

With this patch, a user of distribution provided ruby will see line
info if s/he has a debug package for ruby.

addr2line.c | 97 ++++++++++++++++++++++++++++++++++++++++++----------------
1 files changed, 70 insertions(+), 27 deletions(-)

diff --git a/addr2line.c b/addr2line.c
index 443333f..97bd652 100644
--- a/addr2line.c
+++ b/addr2line.c
@@ -382,14 +382,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;
    @@ -411,11 +468,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;
    }

@@ -458,12 +523,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 */
    @@ -491,26 +553,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 */
    --
    1.7.2.3
    =end

Actions #1

Updated by naruse (Yui NARUSE) over 13 years ago

  • Status changed from Open to Closed
  • % Done changed from 0 to 100

=begin
This issue was solved with changeset r29987.
Shinichiro, thank you for reporting this issue.
Your contribution to Ruby is greatly appreciated.
May Ruby be with you.

=end

Actions

Also available in: Atom PDF

Like0
Like0