[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
- From: Fernando Herrera de las Heras <fherrera src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [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
- Date: Mon, 31 May 2010 13:12:09 +0000 (UTC)
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]