pvalena / rpms / ruby

Forked from rpms/ruby 6 years ago
Clone
9b149e5
--- a/addr2line.c
9b149e5
+++ b/addr2line.c
9b149e5
@@ -159,11 +159,12 @@
9b149e5
     struct dwarf_section debug_info;
9b149e5
     struct dwarf_section debug_line;
9b149e5
     struct dwarf_section debug_ranges;
9b149e5
+    struct dwarf_section debug_rnglists;
9b149e5
     struct dwarf_section debug_str;
9b149e5
     struct obj_info *next;
9b149e5
 } obj_info_t;
9b149e5
 
9b149e5
-#define DWARF_SECTION_COUNT 5
9b149e5
+#define DWARF_SECTION_COUNT 6
9b149e5
 
9b149e5
 static struct dwarf_section *
9b149e5
 obj_dwarf_section_at(obj_info_t *obj, int n)
9b149e5
@@ -173,6 +174,7 @@
9b149e5
         &obj->debug_info,
9b149e5
         &obj->debug_line,
9b149e5
         &obj->debug_ranges,
9b149e5
+        &obj->debug_rnglists,
9b149e5
         &obj->debug_str
9b149e5
     };
9b149e5
     if (n < 0 || DWARF_SECTION_COUNT <= n) {
9b149e5
@@ -411,7 +413,7 @@
9b149e5
 	    FILL_LINE();
9b149e5
 	    break;
9b149e5
 	case DW_LNS_advance_pc:
9b149e5
-	    a = uleb128((char **)&p);
9b149e5
+	    a = uleb128((char **)&p) * header.minimum_instruction_length;
9b149e5
 	    addr += a;
9b149e5
 	    break;
9b149e5
 	case DW_LNS_advance_line: {
9b149e5
@@ -450,7 +452,7 @@
9b149e5
 	    /* isa = (unsigned int)*/(void)uleb128((char **)&p);
9b149e5
 	    break;
9b149e5
 	case 0:
9b149e5
-	    a = *(unsigned char *)p++;
9b149e5
+	    a = uleb128((char **)&p);
9b149e5
 	    op = *p++;
9b149e5
 	    switch (op) {
9b149e5
 	    case DW_LNE_end_sequence:
9b149e5
@@ -807,6 +809,18 @@
9b149e5
     DW_FORM_addrx4 = 0x2c
9b149e5
 };
9b149e5
 
9b149e5
+/* Range list entry encodings */
9b149e5
+enum {
9b149e5
+    DW_RLE_end_of_list = 0x00,
9b149e5
+    DW_RLE_base_addressx = 0x01,
9b149e5
+    DW_RLE_startx_endx = 0x02,
9b149e5
+    DW_RLE_startx_length = 0x03,
9b149e5
+    DW_RLE_offset_pair = 0x04,
9b149e5
+    DW_RLE_base_address = 0x05,
9b149e5
+    DW_RLE_start_end = 0x06,
9b149e5
+    DW_RLE_start_length = 0x07
9b149e5
+};
9b149e5
+
9b149e5
 enum {
9b149e5
     VAL_none = 0,
9b149e5
     VAL_cstr = 1,
9b149e5
@@ -961,6 +975,23 @@
9b149e5
 }
9b149e5
 
9b149e5
 static void
9b149e5
+di_skip_die_attributes(char **p)
9b149e5
+{
9b149e5
+    for (;;) {
9b149e5
+        uint64_t at = uleb128(p);
9b149e5
+        uint64_t form = uleb128(p);
9b149e5
+        if (!at && !form) break;
9b149e5
+        switch (form) {
9b149e5
+          default:
9b149e5
+            break;
9b149e5
+          case DW_FORM_implicit_const:
9b149e5
+            sleb128(p);
9b149e5
+            break;
9b149e5
+        }
9b149e5
+    }
9b149e5
+}
9b149e5
+
9b149e5
+static void
9b149e5
 di_read_debug_abbrev_cu(DebugInfoReader *reader)
9b149e5
 {
9b149e5
     uint64_t prev = 0;
9b149e5
@@ -974,12 +1005,7 @@
9b149e5
         prev = abbrev_number;
9b149e5
         uleb128(&p); /* tag */
9b149e5
         p++; /* has_children */
9b149e5
-        /* skip content */
9b149e5
-        for (;;) {
9b149e5
-            uint64_t at = uleb128(&p);
9b149e5
-            uint64_t form = uleb128(&p);
9b149e5
-            if (!at && !form) break;
9b149e5
-        }
9b149e5
+        di_skip_die_attributes(&p);
9b149e5
     }
9b149e5
 }
9b149e5
 
9b149e5
@@ -1243,12 +1269,7 @@
9b149e5
     /* skip 255th record */
9b149e5
     uleb128(&p); /* tag */
9b149e5
     p++; /* has_children */
9b149e5
-    /* skip content */
9b149e5
-    for (;;) {
9b149e5
-        uint64_t at = uleb128(&p);
9b149e5
-        uint64_t form = uleb128(&p);
9b149e5
-        if (!at && !form) break;
9b149e5
-    }
9b149e5
+    di_skip_die_attributes(&p);
9b149e5
     for (uint64_t n = uleb128(&p); abbrev_number != n; n = uleb128(&p)) {
9b149e5
         if (n == 0) {
9b149e5
             fprintf(stderr,"%d: Abbrev Number %"PRId64" not found\n",__LINE__, abbrev_number);
9b149e5
@@ -1256,12 +1277,7 @@
9b149e5
         }
9b149e5
         uleb128(&p); /* tag */
9b149e5
         p++; /* has_children */
9b149e5
-        /* skip content */
9b149e5
-        for (;;) {
9b149e5
-            uint64_t at = uleb128(&p);
9b149e5
-            uint64_t form = uleb128(&p);
9b149e5
-            if (!at && !form) break;
9b149e5
-        }
9b149e5
+        di_skip_die_attributes(&p);
9b149e5
     }
9b149e5
     return p;
9b149e5
 }
9b149e5
@@ -1389,6 +1405,21 @@
9b149e5
     }
9b149e5
 }
9b149e5
 
9b149e5
+static uint64_t
9b149e5
+read_dw_form_addr(DebugInfoReader *reader, char **ptr)
9b149e5
+{
9b149e5
+    char *p = *ptr;
9b149e5
+    *ptr = p + reader->format;
9b149e5
+    if (reader->format == 4) {
9b149e5
+        return read_uint32(&p);
9b149e5
+    } else if (reader->format == 8) {
9b149e5
+        return read_uint64(&p);
9b149e5
+    } else {
9b149e5
+        fprintf(stderr,"unknown address_size:%d", reader->address_size);
9b149e5
+        abort();
9b149e5
+    }
9b149e5
+}
9b149e5
+
9b149e5
 static uintptr_t
9b149e5
 ranges_include(DebugInfoReader *reader, ranges_t *ptr, uint64_t addr)
9b149e5
 {
9b149e5
@@ -1402,8 +1433,50 @@
9b149e5
     }
9b149e5
     else if (ptr->ranges_set) {
9b149e5
         /* TODO: support base address selection entry */
9b149e5
-        char *p = reader->obj->debug_ranges.ptr + ptr->ranges;
9b149e5
+        char *p;
9b149e5
         uint64_t base = ptr->low_pc_set ? ptr->low_pc : reader->current_low_pc;
9b149e5
+        if (reader->obj->debug_rnglists.ptr) {
9b149e5
+            p = reader->obj->debug_rnglists.ptr + ptr->ranges;
9b149e5
+            for (;;) {
9b149e5
+                uint8_t rle = read_uint8(&p);
9b149e5
+                uintptr_t base_address = 0;
9b149e5
+                uintptr_t from, to;
9b149e5
+                if (rle == DW_RLE_end_of_list) break;
9b149e5
+                switch (rle) {
9b149e5
+                  case DW_RLE_base_addressx:
9b149e5
+                    uleb128(&p);
9b149e5
+                    break;
9b149e5
+                  case DW_RLE_startx_endx:
9b149e5
+                    uleb128(&p);
9b149e5
+                    uleb128(&p);
9b149e5
+                    break;
9b149e5
+                  case DW_RLE_startx_length:
9b149e5
+                    uleb128(&p);
9b149e5
+                    uleb128(&p);
9b149e5
+                    break;
9b149e5
+                  case DW_RLE_offset_pair:
9b149e5
+                    from = base_address + uleb128(&p);
9b149e5
+                    to = base_address + uleb128(&p);
9b149e5
+                    if (base + from <= addr && addr < base + to) {
9b149e5
+                        return from;
9b149e5
+                    }
9b149e5
+                    break;
9b149e5
+                  case DW_RLE_base_address:
9b149e5
+                    base_address = read_dw_form_addr(reader, &p);
9b149e5
+                    break;
9b149e5
+                  case DW_RLE_start_end:
9b149e5
+                    read_dw_form_addr(reader, &p);
9b149e5
+                    read_dw_form_addr(reader, &p);
9b149e5
+                    break;
9b149e5
+                  case DW_RLE_start_length:
9b149e5
+                    read_dw_form_addr(reader, &p);
9b149e5
+                    uleb128(&p);
9b149e5
+                    break;
9b149e5
+                }
9b149e5
+            }
9b149e5
+            return false;
9b149e5
+        }
9b149e5
+        p = reader->obj->debug_ranges.ptr + ptr->ranges;
9b149e5
         for (;;) {
9b149e5
             uintptr_t from = read_uintptr(&p);
9b149e5
             uintptr_t to = read_uintptr(&p);
9b149e5
@@ -1747,6 +1820,7 @@
9b149e5
                     ".debug_info",
9b149e5
                     ".debug_line",
9b149e5
                     ".debug_ranges",
9b149e5
+                    ".debug_rnglists",
9b149e5
                     ".debug_str"
9b149e5
                 };
9b149e5
 
9b149e5
@@ -2003,6 +2077,7 @@
9b149e5
                     "__debug_info",
9b149e5
                     "__debug_line",
9b149e5
                     "__debug_ranges",
9b149e5
+                    "__debug_rnglists",
9b149e5
                     "__debug_str"
9b149e5
                 };
9b149e5
                 struct LP(segment_command) *scmd = (struct LP(segment_command) *)lcmd;