[bug-buddy/remove_breakpad: 3/3] Move elf debug symbols and gdb checks to bug-buddy. It is safer to run this code in the new process



commit d8e858dd5c6b84d315a75e895907b9f8c88f2531
Author: Fernando Herrera <fherrera onirica com>
Date:   Mon May 31 15:06:47 2010 +0200

    Move elf debug symbols and gdb checks to bug-buddy.
    It is safer to run this code in the new process than in the hanlder

 segv_handler/gnome-segvhanlder.c |  161 --------------------------------------
 src/Makefile.am                  |    1 +
 src/bug-buddy.c                  |   67 ++++++++++++++++
 src/elf.c                        |  103 ++++++++++++++++++++++++
 4 files changed, 171 insertions(+), 161 deletions(-)
---
diff --git a/segv_handler/gnome-segvhanlder.c b/segv_handler/gnome-segvhanlder.c
index eac1d12..d6b3954 100644
--- a/segv_handler/gnome-segvhanlder.c
+++ b/segv_handler/gnome-segvhanlder.c
@@ -19,9 +19,6 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
  */
 
-#include <libelf.h>
-#include <gelf.h>
-
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
@@ -44,7 +41,6 @@ const char *g_module_check_init (GModule *module);
 int gtk_module_init (int *argc, char** argv[]);
 
 static gboolean    run_bug_buddy   (const gchar *appname, pid_t pid);
-static void    check_if_gdb    ();
 
 static gchar *bugbuddy;
 static GLogFunc old_handler = NULL;
@@ -187,98 +183,9 @@ bugbuddy_segv_handle(int signum)
                 _exit(1);
         }
 
-	check_if_gdb ();
-
         _exit(1);
 }
 
-#define N_TRIES 3
-
-static gboolean 
-find_in_debug_path (const char *filename, const char *debug_filename)
-{
-	char *dir;
-	char *tries[N_TRIES];
-	gboolean result = FALSE;
-	int i;
-
-	dir = g_path_get_dirname (filename);
-	tries[0] = g_build_filename (dir, debug_filename, NULL);
-	tries[1] = g_build_filename (dir, ".debug", debug_filename, NULL);
-	tries[2] = g_build_filename ("/usr", "lib", "debug", dir, debug_filename, NULL);
-
-	g_free (dir);
-
-	for (i = 0; i < N_TRIES; ++i) {
-		if (g_file_test (tries[i], G_FILE_TEST_EXISTS)) {
-			result = TRUE;
-			break;
-		}
-	}
-
-	for (i = 0; i < N_TRIES; i++)
-		g_free (tries [i]);
-
-	return result;
-}
-
-
-static gboolean
-elf_has_debug_symbols (const char *filename)
-{
-       int fd;
-       Elf *elf;
-       GElf_Ehdr elf_header;
-       Elf_Scn *section = 0;
-       int number = 0;
-
-       if (elf_version(EV_CURRENT) == EV_NONE ) {
-               fprintf(stderr, "Elf library out of date!n");
-                return FALSE;
-       }
-
-       fd = open(filename, O_RDONLY);
-
-       if ((elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL){
-               close (fd);
-               return FALSE;
-       }
-       gelf_getehdr (elf, &elf_header);
-       while ((section = elf_nextscn(elf, section)) != 0) {
-               char *name = 0;
-               GElf_Shdr shdr;
-
-		/* Check for stabs debug information */
-               if (gelf_getshdr (section, &shdr) != 0) {
-                       if (shdr.sh_type == SHT_SYMTAB) {
-                               elf_end (elf);
-                               return TRUE;
-                       }
-               }
-
-		/* Check for .gnu_debuglink separete debug file */
-               if (shdr.sh_type == SHT_PROGBITS) {
-                 char *name = elf_strptr(elf, elf_header.e_shstrndx, shdr.sh_name);
-		 if (strcmp (name, ".gnu_debuglink") == 0) {
-			Elf_Data *edata;
-
-			edata = elf_getdata(section, NULL);
-			if (edata != NULL && find_in_debug_path (filename, (const char*) edata->d_buf)) {
-				elf_end (elf);
-				return TRUE;
-			}
-		}
-              }
-       }
-
-       /* no symtab neither debug file present */
-       elf_end (elf);
-       return FALSE;
-}
-
-
-
-
 static gboolean
 release_grabs (void)
 {
@@ -332,74 +239,6 @@ run_bug_buddy (const gchar *appname, pid_t pid)
 	return TRUE;
 }
 
-static gboolean
-run_gdb (const gchar *appname, pid_t pid)
-{
-	gchar *exec_str;
-	gchar *title;
-	gboolean res;
-	GError *error = NULL;
-
-	title = g_strdup_printf ("Debugging %s", appname);
-
-	exec_str = g_strdup_printf("gnome-terminal "
-				 "--title=\"%s\" "
-				 "--disable-factory "
-				 "--command=\"gdb %s %d\"",
-				title, appname, (int)pid);
-				g_free (title);
-	res = g_spawn_command_line_sync (exec_str, NULL, NULL,
-					 NULL, &error);
-	g_free(exec_str);
-	if (!res) {
-		g_warning("Couldn't run debugger\n");
-		return FALSE;
-	}
-
-	return TRUE;
-}
-
-static void
-check_if_gdb ()
-{
-	char *mypath;
-	gchar *gdb;
-	gboolean has_debug_symbols = FALSE;
-	char *filename;
-	gchar *appname;
-	pid_t pid;
-	gboolean res;
-
-	release_grabs ();
-
-	if (g_getenv ("GNOME_DISABLE_CRASH_DIALOG"))
-		_exit(0);
-
-	appname = g_get_prgname ();
-	pid = getpid ();
-	gdb = g_find_program_in_path ("gdb");
-
-	if (gdb && g_getenv("GNOME_HACKER")) {
-		res = run_gdb (appname, pid);
-		if (!res)
-			_exit (1);
-		_exit(0);
-	}
-	
-	mypath = g_file_read_link ("/proc/self/exe", NULL);
-	if (mypath)
-		has_debug_symbols = elf_has_debug_symbols (mypath);
-
-	g_free (mypath);
-
-	if (bugbuddy && gdb && has_debug_symbols) {
-		res = run_bug_buddy (appname, pid);
-		if (!res)
-			_exit (1);
-		_exit(0);
-	}
-}
-		
 int
 gtk_module_init (int *argc, char** argv[])
 {
diff --git a/src/Makefile.am b/src/Makefile.am
index b2cee3f..f980528 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -16,6 +16,7 @@ bin_PROGRAMS = bug-buddy
 bug_buddy_SOURCES = \
 	bug-buddy.c		\
 	bug-buddy.h		\
+	elf.c			\
 	bugzilla.c		\
 	bugzilla.h		\
 	gdb-buddy.c		\
diff --git a/src/bug-buddy.c b/src/bug-buddy.c
index a707d68..021e58f 100644
--- a/src/bug-buddy.c
+++ b/src/bug-buddy.c
@@ -1890,6 +1890,53 @@ fill_stderr_info (GtkBuilder *ui)
 	g_string_free (stderr_info, TRUE);
 }
 
+
+static gboolean
+has_gdb (void)
+{
+	gchar *gdb = g_find_program_in_path ("gdb");
+	if (gdb)
+		return TRUE;
+
+	return FALSE;
+}
+
+static gboolean
+is_gnome_hacker (void)
+{
+	if (g_getenv("GNOME_HACKER"))
+		return TRUE;
+
+	return FALSE;
+}
+
+static gboolean
+run_gdb (const gchar *appname, pid_t pid)
+{
+	gchar *exec_str;
+	gchar *title;
+	gboolean res;
+	GError *error = NULL;
+
+	title = g_strdup_printf ("Debugging %s", appname);
+
+	exec_str = g_strdup_printf("gnome-terminal "
+				 "--title=\"%s\" "
+				 "--disable-factory "
+				 "--command=\"gdb %s %d\"",
+				title, appname, (int)pid);
+				g_free (title);
+	res = g_spawn_command_line_sync (exec_str, NULL, NULL,
+					 NULL, &error);
+	g_free(exec_str);
+	if (!res) {
+		g_warning("Couldn't run debugger\n");
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
 int
 main (int argc, char *argv[])
 {
@@ -1931,6 +1978,26 @@ main (int argc, char *argv[])
 	g_set_application_name (_("Bug Buddy"));
 	gtk_window_set_default_icon_name ("bug-buddy");
 
+	if (gopt_data.app_file && gopt_data.pid) {
+		if (has_gdb () && is_gnome_hacker ()) {
+			gboolean res;
+			res = run_gdb (gopt_data.app_file, gopt_data.pid);
+			if (!res)
+				_exit (1);
+			_exit(0);
+		}
+	 	if (!has_gdb ()) {
+			/* FIXME: Request PackageKit to install gdb */
+			_exit(0);
+		}
+		
+		if (!elf_has_debug_symbols (gopt_data.pid)) {
+			/* FIXME: Request PackageKit to install debug symbols packages */
+			_exit(0);
+		}
+
+	}
+
 	s = g_build_filename (BUDDY_DATADIR, "bug-buddy.gtkbuilder", NULL);
 
 	ui = gtk_builder_new ();
diff --git a/src/elf.c b/src/elf.c
new file mode 100644
index 0000000..6a16732
--- /dev/null
+++ b/src/elf.c
@@ -0,0 +1,103 @@
+#include <libelf.h>
+#include <gelf.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <glib.h>
+
+#include <config.h>
+
+#define N_TRIES 3
+
+static gboolean 
+find_in_debug_path (const char *filename, const char *debug_filename)
+{
+	char *dir;
+	char *tries[N_TRIES];
+	gboolean result = FALSE;
+	int i;
+
+	dir = g_path_get_dirname (filename);
+	tries[0] = g_build_filename (dir, debug_filename, NULL);
+	tries[1] = g_build_filename (dir, ".debug", debug_filename, NULL);
+	tries[2] = g_build_filename ("/usr", "lib", "debug", dir, debug_filename, NULL);
+
+	g_free (dir);
+
+	for (i = 0; i < N_TRIES; ++i) {
+		if (g_file_test (tries[i], G_FILE_TEST_EXISTS)) {
+			result = TRUE;
+			break;
+		}
+	}
+
+	for (i = 0; i < N_TRIES; i++)
+		g_free (tries [i]);
+
+	return result;
+}
+
+
+gboolean
+elf_has_debug_symbols (gint pid)
+{
+	gchar *proc_path;
+	gchar *filename;
+	int fd;
+	Elf *elf;
+	GElf_Ehdr elf_header;
+	Elf_Scn *section = 0;
+
+	if (pid <= 0)
+		return FALSE;
+
+	if (elf_version(EV_CURRENT) == EV_NONE ) {
+		fprintf(stderr, "Elf library out of date!n");
+		return FALSE;
+	}
+
+	proc_path = g_strdup_printf ("/proc/%d/exe", pid);
+	filename = g_file_read_link (proc_path, NULL);
+	g_free (proc_path);
+	if (!filename)
+		return FALSE;
+
+	fd = open(filename, O_RDONLY);
+
+	if ((elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL){
+		close (fd);
+		return FALSE;
+	}
+	gelf_getehdr (elf, &elf_header);
+	while ((section = elf_nextscn(elf, section)) != 0) {
+		GElf_Shdr shdr;
+
+		/* Check for stabs debug information */
+		if (gelf_getshdr (section, &shdr) != 0) {
+			if (shdr.sh_type == SHT_SYMTAB) {
+				elf_end (elf);
+				return TRUE;
+			}
+		}
+
+		/* Check for .gnu_debuglink separete debug file */
+		if (shdr.sh_type == SHT_PROGBITS) {
+			char *name = elf_strptr(elf, elf_header.e_shstrndx, shdr.sh_name);
+			if (strcmp (name, ".gnu_debuglink") == 0) {
+				Elf_Data *edata;
+
+				edata = elf_getdata(section, NULL);
+				if (edata != NULL && find_in_debug_path (filename, (const char*) edata->d_buf)) {
+					elf_end (elf);
+					return TRUE;
+				}
+			}
+		}
+	}
+
+	/* no symtab neither debug file present */
+	elf_end (elf);
+	return FALSE;
+}



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]