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

ruby-changes:52891

From: naruse <ko1@a...>
Date: Wed, 17 Oct 2018 08:52:32 +0900 (JST)
Subject: [ruby-changes:52891] naruse:r65103 (trunk): Correct the handling of .debug_ranges

naruse	2018-10-17 08:52:28 +0900 (Wed, 17 Oct 2018)

  New Revision: 65103

  https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=65103

  Log:
    Correct the handling of .debug_ranges
    
    Though DWARF specifies "the applicable base address defaults to the base
    address of the compilation unit", but GCC seems to use zero as default.

  Modified files:
    trunk/addr2line.c
Index: addr2line.c
===================================================================
--- addr2line.c	(revision 65102)
+++ addr2line.c	(revision 65103)
@@ -138,6 +138,7 @@ typedef struct obj_info { https://github.com/ruby/ruby/blob/trunk/addr2line.c#L138
     size_t mapped_size;
     void *uncompressed;
     uintptr_t base_addr;
+    uintptr_t vmaddr;
     struct dwarf_section debug_abbrev;
     struct dwarf_section debug_info;
     struct dwarf_section debug_line;
@@ -249,7 +250,7 @@ fill_line(int num_traces, void **traces, https://github.com/ruby/ruby/blob/trunk/addr2line.c#L250
 	  obj_info_t *obj, line_info_t *lines, int offset)
 {
     int i;
-    addr += obj->base_addr;
+    addr += obj->base_addr - obj->vmaddr;
     for (i = offset; i < num_traces; i++) {
 	uintptr_t a = (uintptr_t)traces[i];
 	/* We assume one line code doesn't result >100 bytes of native code.
@@ -506,6 +507,7 @@ follow_debuglink(const char *debuglink, https://github.com/ruby/ruby/blob/trunk/addr2line.c#L507
 
 enum
 {
+    DW_TAG_compile_unit = 0x11,
     DW_TAG_inlined_subroutine = 0x1d,
     DW_TAG_subprogram = 0x2e,
 };
@@ -734,6 +736,7 @@ typedef struct { https://github.com/ruby/ruby/blob/trunk/addr2line.c#L736
     obj_info_t *obj;
     char *file;
     char *current_cu;
+    uint64_t current_low_pc;
     char *debug_line_cu_end;
     char *debug_line_files;
     char *debug_line_directories;
@@ -937,31 +940,6 @@ di_read_debug_line_cu(DebugInfoReader *r https://github.com/ruby/ruby/blob/trunk/addr2line.c#L940
     reader->debug_line_files = p;
 }
 
-
-static int
-di_read_cu(DebugInfoReader *reader)
-{
-    DW_CompilationUnitHeader32 *hdr32 = (DW_CompilationUnitHeader32 *)reader->p;
-    reader->current_cu = reader->p;
-    if (hdr32->unit_length == 0xffffffff) {
-        DW_CompilationUnitHeader64 *hdr = (DW_CompilationUnitHeader64 *)hdr32;
-        reader->p += 23;
-        reader->q0 = reader->obj->debug_abbrev.ptr + hdr->debug_abbrev_offset;
-        reader->address_size = hdr->address_size;
-        reader->format = 64;
-    } else {
-        DW_CompilationUnitHeader32 *hdr = hdr32;
-        reader->p += 11;
-        reader->q0 = reader->obj->debug_abbrev.ptr + hdr->debug_abbrev_offset;
-        reader->address_size = hdr->address_size;
-        reader->format = 32;
-    }
-    reader->level = 0;
-    di_read_debug_abbrev_cu(reader);
-    di_read_debug_line_cu(reader);
-    return 0;
-}
-
 static void
 set_uint_value(DebugInfoValue *v, uint64_t n)
 {
@@ -1363,12 +1341,14 @@ ranges_include(DebugInfoReader *reader, https://github.com/ruby/ruby/blob/trunk/addr2line.c#L1341
         }
     }
     else if (ptr->ranges_set) {
+        /* TODO: support base address selection entry */
         char *p = reader->obj->debug_ranges.ptr + ptr->ranges;
+        uint64_t base = ptr->low_pc_set ? ptr->low_pc : reader->current_low_pc;
         for (;;) {
             uintptr_t from = read_uintptr(&p);
             uintptr_t to = read_uintptr(&p);
             if (!from && !to) break;
-            if (from <= addr && addr <= to) {
+            if (base + from <= addr && addr <= base + to) {
                 return from;
             }
         }
@@ -1414,6 +1394,56 @@ ranges_inspect(DebugInfoReader *reader, https://github.com/ruby/ruby/blob/trunk/addr2line.c#L1394
 #endif
 
 static void
+di_read_cu(DebugInfoReader *reader)
+{
+    DW_CompilationUnitHeader32 *hdr32 = (DW_CompilationUnitHeader32 *)reader->p;
+    reader->current_cu = reader->p;
+    if (hdr32->unit_length == 0xffffffff) {
+        DW_CompilationUnitHeader64 *hdr = (DW_CompilationUnitHeader64 *)hdr32;
+        reader->p += 23;
+        reader->q0 = reader->obj->debug_abbrev.ptr + hdr->debug_abbrev_offset;
+        reader->address_size = hdr->address_size;
+        reader->format = 64;
+    } else {
+        DW_CompilationUnitHeader32 *hdr = hdr32;
+        reader->p += 11;
+        reader->q0 = reader->obj->debug_abbrev.ptr + hdr->debug_abbrev_offset;
+        reader->address_size = hdr->address_size;
+        reader->format = 32;
+    }
+    reader->level = 0;
+    di_read_debug_abbrev_cu(reader);
+    di_read_debug_line_cu(reader);
+
+#if defined(__GNUC__) && !defined(__clang__) && !defined(__INTEL_COMPILER_BUILD_DATE)
+    /* Though DWARF specifies "the applicable base address defaults to the base
+       address of the compilation unit", but GCC seems to use zero as default */
+#else
+    do {
+        DIE die;
+
+        if (!di_read_die(reader, &die)) continue;
+
+        if (die.tag != DW_TAG_compile_unit) {
+            di_skip_records(reader);
+            break;
+        }
+
+        /* enumerate abbrev */
+        for (;;) {
+            DebugInfoValue v = {{}};
+            if (!di_read_record(reader, &v)) break;
+            switch (v.at) {
+              case DW_AT_low_pc:
+                reader->current_low_pc = v.as.uint64;
+                break;
+            }
+        }
+    } while (0);
+#endif
+}
+
+static void
 read_abstract_origin(DebugInfoReader *reader, uint64_t abstract_origin, line_info_t *line)
 {
     char *p = reader->p;
@@ -1494,10 +1524,10 @@ debug_info_read(DebugInfoReader *reader, https://github.com/ruby/ruby/blob/trunk/addr2line.c#L1524
         /* fprintf(stderr,"%d:%tx: %x ",__LINE__,diepos,die.tag); */
         for (int i=offset; i < num_traces; i++) {
             uintptr_t addr = (uintptr_t)traces[i];
-            uintptr_t offset = addr - reader->obj->base_addr;
+            uintptr_t offset = addr - reader->obj->base_addr + reader->obj->vmaddr;
             uintptr_t saddr = ranges_include(reader, &ranges, offset);
             if (saddr) {
-                //fprintf(stderr, "%d:%tx: %d %lx->%lx %x %s: %s/%s %d %s %s %s\n",__LINE__,die.pos, i,addr,offset, die.tag,line.sname,line.dirname,line.filename,line.line,reader->obj->path,line.sname,lines[i].sname);
+                /* fprintf(stderr, "%d:%tx: %d %lx->%lx %x %s: %s/%s %d %s %s %s\n",__LINE__,die.pos, i,addr,offset, die.tag,line.sname,line.dirname,line.filename,line.line,reader->obj->path,line.sname,lines[i].sname); */
                 if (lines[i].sname) {
                     line_info_t *lp = malloc(sizeof(line_info_t));
                     memcpy(lp, &lines[i], sizeof(line_info_t));
@@ -1702,13 +1732,12 @@ fill_lines(int num_traces, void **traces https://github.com/ruby/ruby/blob/trunk/addr2line.c#L1732
         i = 0;
         while (reader.p < reader.pend) {
             //fprintf(stderr, "%d:%tx: CU[%d]\n", __LINE__, reader.p - reader.obj->debug_info, i++);
-            if (di_read_cu(&reader)) goto use_symtab;
+            di_read_cu(&reader);
             debug_info_read(&reader, num_traces, traces, lines, offset);
         }
     }
     else {
         /* This file doesn't have dwarf, use symtab or dynsym */
-      use_symtab:
         if (!symtab_shdr) {
             /* This file doesn't have symtab, use dynsym instead */
             symtab_shdr = dynsym_shdr;

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

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