[前][次][番号順一覧][スレッド一覧]

ruby-changes:64092

From: Yusuke <ko1@a...>
Date: Fri, 11 Dec 2020 14:08:51 +0900 (JST)
Subject: [ruby-changes:64092] c718c30007 (master): addr2line.c: support debuglink by build_id

https://git.ruby-lang.org/ruby.git/commit/?id=c718c30007

From c718c300079573392d4de6f51fbb28b3a34c5341 Mon Sep 17 00:00:00 2001
From: Yusuke Endoh <mame@r...>
Date: Sun, 4 Oct 2020 00:07:37 +0900
Subject: 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".

https://github.com/Debian/debhelper/blob/5d1bb29841043d8e47ebbdd043e6cd086cad508e/dh_strip#L292
https://github.com/Debian/debhelper/blob/5d1bb29841043d8e47ebbdd043e6cd086cad508e/dh_strip#L353

This changeset makes ruby backtrace support the second format.

diff --git a/addr2line.c b/addr2line.c
index e7ff990..dc4364a 100644
--- a/addr2line.c
+++ b/addr2line.c
@@ -526,13 +526,25 @@ append_obj(obj_info_t **objp) https://github.com/ruby/ruby/blob/trunk/addr2line.c#L526
 }
 
 #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
 follow_debuglink(const char *debuglink, int num_traces, void **traces,
 		 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";
     const size_t global_debug_dir_len = sizeof(global_debug_dir) - 1;
     char *p;
@@ -559,6 +571,37 @@ follow_debuglink(const char *debuglink, int num_traces, void **traces, https://github.com/ruby/ruby/blob/trunk/addr2line.c#L571
     o2->path = o1->path;
     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
 
 enum
@@ -1616,6 +1659,7 @@ fill_lines(int num_traces, void **traces, int check_debuglink, https://github.com/ruby/ruby/blob/trunk/addr2line.c#L1659
     ElfW(Ehdr) *ehdr;
     ElfW(Shdr) *shdr, *shstr_shdr;
     ElfW(Shdr) *gnu_debuglink_shdr = NULL;
+    ElfW(Shdr) *note_gnu_build_id = NULL;
     int fd;
     off_t filesize;
     char *file;
@@ -1688,6 +1732,11 @@ fill_lines(int num_traces, void **traces, int check_debuglink, https://github.com/ruby/ruby/blob/trunk/addr2line.c#L1732
 	    /* if (!strcmp(section_name, ".dynsym")) */
 	    dynsym_shdr = shdr + i;
 	    break;
+          case SHT_NOTE:
+            if (!strcmp(section_name, ".note.gnu.build-id")) {
+                note_gnu_build_id = shdr + i;
+            }
+            break;
 	  case SHT_PROGBITS:
 	    if (!strcmp(section_name, ".gnu_debuglink")) {
 		gnu_debuglink_shdr = shdr + i;
@@ -1803,6 +1852,13 @@ use_symtab: https://github.com/ruby/ruby/blob/trunk/addr2line.c#L1852
 			     num_traces, traces,
 			     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;
     }
 
-- 
cgit v0.10.2


--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]