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

ruby-changes:33484

From: naruse <ko1@a...>
Date: Fri, 11 Apr 2014 13:48:34 +0900 (JST)
Subject: [ruby-changes:33484] naruse:r45563 (trunk): * addr2line.c (rb_dump_backtrace_with_lines): set base address

naruse	2014-04-11 13:48:26 +0900 (Fri, 11 Apr 2014)

  New Revision: 45563

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=45563

  Log:
    * addr2line.c (rb_dump_backtrace_with_lines): set base address
      which is retrived from dladdr to dladdr_fbases, to skip already
      parsed objects.

  Modified files:
    trunk/ChangeLog
    trunk/addr2line.c
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 45562)
+++ ChangeLog	(revision 45563)
@@ -1,3 +1,9 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1
+Fri Apr 11 12:02:30 2014  NARUSE, Yui  <naruse@r...>
+
+	* addr2line.c (rb_dump_backtrace_with_lines): set base address
+	  which is retrived from dladdr to dladdr_fbases, to skip already
+	  parsed objects.
+
 Fri Apr 11 12:44:50 2014  Nobuyoshi Nakada  <nobu@r...>
 
 	* array.c (ary_reject): may be turned into a shared array during
Index: addr2line.c
===================================================================
--- addr2line.c	(revision 45562)
+++ addr2line.c	(revision 45563)
@@ -478,20 +478,20 @@ fill_lines(int num_traces, void **traces https://github.com/ruby/ruby/blob/trunk/addr2line.c#L478
 
     fd = open(binary_filename, O_RDONLY);
     if (fd < 0) {
-	goto fail;
+	return;
     }
     filesize = lseek(fd, 0, SEEK_END);
     if (filesize < 0) {
 	int e = errno;
 	close(fd);
 	kprintf("lseek: %s\n", strerror(e));
-	goto fail;
+	return;
     }
 #if SIZEOF_OFF_T > SIZEOF_SIZE_T
     if (filesize > (off_t)SIZE_MAX) {
 	close(fd);
 	kprintf("Too large file %s\n", binary_filename);
-	goto fail;
+	return;
     }
 #endif
     lseek(fd, 0, SEEK_SET);
@@ -501,7 +501,7 @@ fill_lines(int num_traces, void **traces https://github.com/ruby/ruby/blob/trunk/addr2line.c#L501
 	int e = errno;
 	close(fd);
 	kprintf("mmap: %s\n", strerror(e));
-	goto fail;
+	return;
     }
 
     ehdr = (ElfW(Ehdr) *)file;
@@ -511,7 +511,7 @@ fill_lines(int num_traces, void **traces https://github.com/ruby/ruby/blob/trunk/addr2line.c#L511
 	 * it match non-elf file.
 	 */
 	close(fd);
-	goto fail;
+	return;
     }
 
     if (ehdr->e_type == ET_EXEC) obj->base_addr = 0;
@@ -555,8 +555,10 @@ fill_lines(int num_traces, void **traces https://github.com/ruby/ruby/blob/trunk/addr2line.c#L555
     }
 
     if (offset == -1) {
+	/* main executable */
 	offset = 0;
 	if (ehdr->e_type != ET_EXEC && dynsym_shdr && dynstr_shdr) {
+	    /* PIE (position-independent executable) */
 	    char *strtab = file + dynstr_shdr->sh_offset;
 	    ElfW(Sym) *symtab = (ElfW(Sym) *)(file + dynsym_shdr->sh_offset);
 	    int symtab_count = (int)(dynsym_shdr->sh_size / sizeof(ElfW(Sym)));
@@ -574,7 +576,7 @@ fill_lines(int num_traces, void **traces https://github.com/ruby/ruby/blob/trunk/addr2line.c#L576
 		    break;
 		}
 	    }
-	}
+	} /* otherwise, base address is 0 */
     }
 
     if (!symtab_shdr) {
@@ -611,27 +613,13 @@ fill_lines(int num_traces, void **traces https://github.com/ruby/ruby/blob/trunk/addr2line.c#L613
 			     num_traces, traces,
 			     objp, lines, offset);
 	}
-	goto finish;
+	return;
     }
 
     parse_debug_line(num_traces, traces,
 		     file + debug_line_shdr->sh_offset,
 		     debug_line_shdr->sh_size,
 		     obj, lines, offset);
-finish:
-    for (i = offset; i < num_traces; i++) {
-	if (lines[i].line == -1) {
-	    lines[i].line = -2;
-	}
-    }
-    return;
-fail:
-    for (i = offset; i < num_traces; i++) {
-	if (obj->base_addr == lines[i].base_addr) {
-	    lines[i].line = -2;
-	}
-    }
-    return;
 }
 
 #define HAVE_MAIN_EXE_PATH
@@ -655,9 +643,10 @@ rb_dump_backtrace_with_lines(int num_tra https://github.com/ruby/ruby/blob/trunk/addr2line.c#L643
     /* async-signal unsafe */
     line_info_t *lines = (line_info_t *)calloc(num_traces, sizeof(line_info_t));
     obj_info_t *obj = NULL;
-    void **base_addrs = (void **)calloc(num_traces+1, sizeof(void *));
+    /* 2 is NULL + main executable */
+    void **dladdr_fbases = (void **)calloc(num_traces+2, sizeof(void *));
 #ifdef HAVE_MAIN_EXE_PATH
-    char *main_path = NULL; /* keep while this func */
+    char *main_path = NULL; /* used on printing backtrace */
     ssize_t len;
     if ((len = main_exe_path()) > 0) {
 	main_path = (char *)alloca(len + 1);
@@ -665,11 +654,20 @@ rb_dump_backtrace_with_lines(int num_tra https://github.com/ruby/ruby/blob/trunk/addr2line.c#L654
 	    obj_info_t *o;
 	    memcpy(main_path, binary_filename, len+1);
 	    append_obj(&obj);
-	    o = obj;
+	    o = obj; /* obj may be chaneged with gnu_debuglink */
 	    obj->path = main_path;
 	    fill_lines(num_traces, traces, 1, &obj, lines, -1);
-	    for (i=0; o=o->next; i++) { /* 1 or 2 times */
-		base_addrs[i] = (void *)o->base_addr;
+
+	    /* set dladdr.dli_fbase */
+	    if (o->base_addr) { /* PIE */
+		dladdr_fbases[0] = (void *)o->base_addr;
+	    }
+	    else { /* non PIE */
+		/* base addr is 0, but get dli_fbase to skip with dladdr */
+		Dl_info info;
+		if (dladdr(traces[i], &info)) {
+		    dladdr_fbases[0] = info.dli_fbase;
+		}
 	    }
 	}
     }
@@ -682,10 +680,18 @@ rb_dump_backtrace_with_lines(int num_tra https://github.com/ruby/ruby/blob/trunk/addr2line.c#L680
 	if (dladdr(traces[i], &info)) {
 	    const char *path;
 	    void **p;
-	    for (p=base_addrs; *p; p++) {
-		if (*p == info.dli_fbase)
+
+	    /* skip symbols which is in already checked objects */
+	    /* if the binary is strip-ed, this may effect */
+	    for (p=dladdr_fbases; *p; p++) {
+		if (*p == info.dli_fbase) {
+		    lines[i].path = info.dli_fname;
+		    lines[i].sname = info.dli_sname;
 		    goto next_line;
+		}
 	    }
+	    *p = info.dli_fbase;
+
 	    append_obj(&obj);
 	    obj->base_addr = (uintptr_t)info.dli_fbase;
 	    path = info.dli_fname;
@@ -741,7 +747,7 @@ next_line: https://github.com/ruby/ruby/blob/trunk/addr2line.c#L747
 	free(o);
     }
     free(lines);
-    free(base_addrs);
+    free(dladdr_fbases);
 }
 
 /* From FreeBSD's lib/libstand/printf.c */

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

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