Fix issues from http://fpaste.org/iIwx/
[bug-buddy.git] / src / elf.c
blob5f8dac2fae2c0201d1e2cc17e034ff6ba960feb0
1 /* bug-buddy bug submitting program
3 * Copyright (C) 2008 - 2010 Fernando Herrera <fherrera@onirica.com>
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of version 2 of the GNU General Public
7 * License as published by the Free Software Foundation.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
19 #include <libelf.h>
20 #include <gelf.h>
21 #include <stdio.h>
22 #include <fcntl.h>
23 #include <string.h>
24 #include <unistd.h>
26 #include <glib.h>
28 #include <config.h>
30 #define N_TRIES 3
32 static gboolean
33 find_in_debug_path (const char *filename, const char *debug_filename)
35 char *dir;
36 char *tries[N_TRIES];
37 gboolean result = FALSE;
38 int i;
40 dir = g_path_get_dirname (filename);
41 tries[0] = g_build_filename (dir, debug_filename, NULL);
42 tries[1] = g_build_filename (dir, ".debug", debug_filename, NULL);
43 tries[2] = g_build_filename ("/usr", "lib", "debug", dir, debug_filename, NULL);
45 g_free (dir);
47 for (i = 0; i < N_TRIES; ++i) {
48 if (g_file_test (tries[i], G_FILE_TEST_EXISTS)) {
49 result = TRUE;
50 break;
54 for (i = 0; i < N_TRIES; i++)
55 g_free (tries [i]);
57 return result;
61 gboolean
62 elf_has_debug_symbols (gint pid)
64 gchar *proc_path;
65 gchar *filename;
66 int fd;
67 Elf *elf;
68 GElf_Ehdr elf_header;
69 Elf_Scn *section = 0;
71 if (pid <= 0)
72 return FALSE;
74 if (elf_version (EV_CURRENT) == EV_NONE ) {
75 fprintf(stderr, "Elf library out of date!n");
76 return FALSE;
79 proc_path = g_strdup_printf ("/proc/%d/exe", pid);
80 filename = g_file_read_link (proc_path, NULL);
81 g_free (proc_path);
82 if (!filename)
83 return FALSE;
85 fd = open (filename, O_RDONLY);
87 if ((elf = elf_begin (fd, ELF_C_READ, NULL)) == NULL){
88 close (fd);
89 return FALSE;
91 gelf_getehdr (elf, &elf_header);
92 while ((section = elf_nextscn (elf, section)) != 0) {
93 GElf_Shdr shdr;
95 /* Check for stabs debug information */
96 if (gelf_getshdr (section, &shdr) != 0) {
97 if (shdr.sh_type == SHT_SYMTAB) {
98 elf_end (elf);
99 return TRUE;
103 /* Check for .gnu_debuglink separete debug file */
104 if (shdr.sh_type == SHT_PROGBITS) {
105 char *name = elf_strptr(elf, elf_header.e_shstrndx, shdr.sh_name);
106 if (strcmp (name, ".gnu_debuglink") == 0) {
107 Elf_Data *edata;
109 edata = elf_getdata(section, NULL);
110 if (edata != NULL && find_in_debug_path (filename, (const char*) edata->d_buf)) {
111 elf_end (elf);
112 return TRUE;
118 /* no symtab neither debug file present */
119 elf_end (elf);
120 return FALSE;