gdb/gdb-6.6-buildid-locate-rpm.patch
Jan Kratochvil 09c22fd5fb - Split `gdb-6.6-buildid-locate.patch' to
`gdb-6.6-buildid-locate-rpm.patch'.
2009-03-07 01:42:03 +00:00

430 lines
13 KiB
Diff

--- ./gdb/Makefile.in 2009-03-07 01:45:51.000000000 +0100
+++ ./gdb/Makefile.in 2009-03-07 01:52:00.000000000 +0100
@@ -396,7 +396,7 @@ CONFIG_UNINSTALL = @CONFIG_UNINSTALL@
# your system doesn't have fcntl.h in /usr/include (which is where it
# should be according to Posix).
DEFS = @DEFS@
-GDB_CFLAGS = -I. -I$(srcdir) -I$(srcdir)/config -DLOCALEDIR="\"$(localedir)\"" $(DEFS)
+GDB_CFLAGS = -I. -I$(srcdir) -I$(srcdir)/config -I$(includedir)/rpm -DLOCALEDIR="\"$(localedir)\"" $(DEFS)
# MH_CFLAGS, if defined, has host-dependent CFLAGS from the config directory.
GLOBAL_CFLAGS = $(MH_CFLAGS)
@@ -449,7 +449,7 @@ INSTALLED_LIBS=-lbfd -lreadline -lopcode
CLIBS = $(SIM) $(READLINE) $(OPCODES) $(BFD) $(INTL) $(LIBIBERTY) $(LIBDECNUMBER) \
$(XM_CLIBS) $(NAT_CLIBS) $(GDBTKLIBS) @LIBS@ \
$(LIBICONV) $(LIBEXPAT) \
- $(LIBIBERTY) $(WIN32LIBS) $(LIBGNU)
+ $(LIBIBERTY) $(WIN32LIBS) $(LIBGNU) -lrpm
CDEPS = $(XM_CDEPS) $(NAT_CDEPS) $(SIM) $(BFD) $(READLINE_DEPS) \
$(OPCODES) $(INTL_DEPS) $(LIBIBERTY) $(CONFIG_DEPS) $(LIBGNU)
--- ./gdb/event-top.c 2009-03-07 02:29:51.000000000 +0100
+++ ./gdb/event-top.c 2009-03-07 01:52:00.000000000 +0100
@@ -33,6 +33,7 @@
#include "cli/cli-script.h" /* for reset_command_nest_depth */
#include "main.h"
#include "gdbthread.h"
+#include "symfile.h"
/* For dont_repeat() */
#include "gdbcmd.h"
@@ -193,6 +194,8 @@ cli_command_loop (void)
char *a_prompt;
char *gdb_prompt = get_prompt ();
+ debug_flush_missing ();
+
/* Tell readline what the prompt to display is and what function it
will need to call after a whole line is read. This also displays
the first prompt. */
@@ -264,6 +267,8 @@ display_gdb_prompt (char *new_prompt)
/* Reset the nesting depth used when trace-commands is set. */
reset_command_nest_depth ();
+ debug_flush_missing ();
+
/* Each interpreter has its own rules on displaying the command
prompt. */
if (!current_interp_display_prompt_p ())
--- ./gdb/symfile.c 2009-03-07 02:30:20.000000000 +0100
+++ ./gdb/symfile.c 2009-03-07 01:52:00.000000000 +0100
@@ -55,6 +55,7 @@
#include "solib.h"
#include "remote.h"
#include "libbfd.h"
+#include "elf/external.h"
#include <sys/types.h>
#include <fcntl.h>
@@ -63,6 +64,7 @@
#include <ctype.h>
#include <time.h>
#include <sys/time.h>
+#include <sys/param.h>
int (*deprecated_ui_load_progress_hook) (const char *section, unsigned long num);
@@ -1684,6 +1686,269 @@ build_id_to_filename (struct build_id *b
return retval;
}
+#include <rpm/rpmlib.h>
+#include <rpm/rpmts.h>
+#include <rpm/rpmdb.h>
+#include <rpm/header.h>
+
+/* This MISSING_RPM_HASH tracker is used to collect all the missing rpm files
+ and avoid their duplicities during a single inferior run. */
+
+static struct htab *missing_rpm_hash;
+
+/* This MISSING_RPM_LIST tracker is used to collect and print as a single line
+ all the rpms right before the nearest GDB prompt. It gets cleared after
+ each such print (it is questionable if we should clear it after the print).
+ */
+
+struct missing_rpm
+ {
+ struct missing_rpm *next;
+ char rpm[1];
+ };
+static struct missing_rpm *missing_rpm_list;
+static int missing_rpm_list_entries;
+
+/* Returns the count of newly added rpms. */
+
+static int
+missing_rpm_enlist (const char *filename)
+{
+ static int rpm_init_done = 0;
+ rpmts ts;
+ rpmdbMatchIterator mi;
+ int count = 0;
+
+ if (filename == NULL)
+ return 0;
+
+ if (!rpm_init_done)
+ {
+ if (rpmReadConfigFiles(NULL, NULL) != 0)
+ {
+ warning (_("Error reading the rpm configuration files"));
+ return 0;
+ }
+ rpm_init_done = 1;
+ }
+
+ ts = rpmtsCreate ();
+
+ mi = rpmtsInitIterator (ts, RPMTAG_BASENAMES, filename, 0);
+ if (mi != NULL)
+ {
+ for (;;)
+ {
+ Header h;
+ char *debuginfo, **slot, *s, *s2;
+ errmsg_t err;
+ size_t srcrpmlen = sizeof (".src.rpm") - 1;
+ size_t debuginfolen = sizeof ("-debuginfo") - 1;
+ rpmdbMatchIterator mi_debuginfo;
+
+ h = rpmdbNextIterator (mi);
+ if (h == NULL)
+ break;
+
+ /* Verify the debuginfo file is not already installed. */
+
+ debuginfo = headerFormat (h, "%{sourcerpm}-debuginfo.%{arch}", &err);
+ if (!debuginfo)
+ {
+ warning (_("Error querying the rpm file `%s': %s"), filename,
+ err);
+ continue;
+ }
+ /* s = `.src.rpm-debuginfo.%{arch}' */
+ s = strrchr (debuginfo, '-') - srcrpmlen;
+ s2 = NULL;
+ if (s > debuginfo && memcmp (s, ".src.rpm", srcrpmlen) == 0)
+ {
+ /* s2 = `-%{release}.src.rpm-debuginfo.%{arch}' */
+ s2 = memrchr (debuginfo, '-', s - debuginfo);
+ }
+ if (s2)
+ {
+ /* s2 = `-%{version}-%{release}.src.rpm-debuginfo.%{arch}' */
+ s2 = memrchr (debuginfo, '-', s2 - debuginfo);
+ }
+ if (!s2)
+ {
+ warning (_("Error querying the rpm file `%s': %s"), filename,
+ debuginfo);
+ xfree (debuginfo);
+ continue;
+ }
+ /* s = `.src.rpm-debuginfo.%{arch}' */
+ /* s2 = `-%{version}-%{release}.src.rpm-debuginfo.%{arch}' */
+ memmove (s2 + debuginfolen, s2, s - s2);
+ memcpy (s2, "-debuginfo", debuginfolen);
+ /* s = `XXXX.%{arch}' */
+ /* strlen ("XXXX") == srcrpmlen + debuginfolen */
+ /* s2 = `-debuginfo-%{version}-%{release}XX.%{arch}' */
+ /* strlen ("XX") == srcrpmlen */
+ memmove (s + debuginfolen, s + srcrpmlen + debuginfolen,
+ strlen (s + srcrpmlen + debuginfolen) + 1);
+ /* s = `-debuginfo-%{version}-%{release}.%{arch}' */
+
+ /* RPMDBI_PACKAGES requires keylen == sizeof (int). */
+ /* RPMDBI_LABEL is an interface for NVR-based dbiFindByLabel(). */
+ mi_debuginfo = rpmtsInitIterator (ts, RPMDBI_LABEL, debuginfo, 0);
+ xfree (debuginfo);
+ if (mi_debuginfo)
+ {
+ rpmdbFreeIterator (mi_debuginfo);
+ count = 0;
+ break;
+ }
+
+ /* The allocated memory gets utilized below for MISSING_RPM_HASH. */
+ debuginfo = headerFormat (h,
+ "%{name}-%{version}-%{release}.%{arch}",
+ &err);
+ if (!debuginfo)
+ {
+ warning (_("Error querying the rpm file `%s': %s"), filename,
+ err);
+ continue;
+ }
+
+ /* Base package name for `debuginfo-install'. We do not use the
+ `yum' command directly as the line
+ yum --enablerepo='*-debuginfo' install NAME-debuginfo.ARCH
+ would be more complicated than just:
+ debuginfo-install NAME-VERSION-RELEASE.ARCH
+ Do not supply the rpm base name (derived from .src.rpm name) as
+ debuginfo-install is unable to install the debuginfo package if
+ the base name PKG binary rpm is not installed while for example
+ PKG-libs would be installed (RH Bug 467901).
+ FUTURE: After multiple debuginfo versions simultaneously installed
+ get supported the support for the VERSION-RELEASE tags handling
+ may need an update. */
+
+ if (missing_rpm_hash == NULL)
+ {
+ /* DEL_F is passed NULL as MISSING_RPM_LIST's HTAB_DELETE
+ should not deallocate the entries. */
+
+ missing_rpm_hash = htab_create_alloc (64, htab_hash_string,
+ (int (*) (const void *, const void *)) streq,
+ NULL, xcalloc, xfree);
+ }
+ slot = (char **) htab_find_slot (missing_rpm_hash, debuginfo, INSERT);
+ /* XCALLOC never returns NULL. */
+ gdb_assert (slot != NULL);
+ if (*slot == NULL)
+ {
+ struct missing_rpm *missing_rpm;
+
+ *slot = debuginfo;
+
+ missing_rpm = xmalloc (sizeof (*missing_rpm) + strlen (debuginfo));
+ strcpy (missing_rpm->rpm, debuginfo);
+ missing_rpm->next = missing_rpm_list;
+ missing_rpm_list = missing_rpm;
+ missing_rpm_list_entries++;
+ }
+ else
+ xfree (debuginfo);
+ count++;
+ }
+
+ rpmdbFreeIterator (mi);
+ }
+
+ rpmtsFree (ts);
+
+ return count;
+}
+
+static int
+missing_rpm_list_compar (const char *const *ap, const char *const *bp)
+{
+ return strcoll (*ap, *bp);
+}
+
+/* It returns a NULL-terminated array of strings needing to be FREEd. It may
+ also return only NULL. */
+
+static void
+missing_rpm_list_print (void)
+{
+ char **array, **array_iter;
+ struct missing_rpm *list_iter;
+ struct cleanup *cleanups;
+
+ if (missing_rpm_list_entries == 0)
+ return;
+
+ array = xmalloc (sizeof (*array) * missing_rpm_list_entries);
+ cleanups = make_cleanup (xfree, array);
+
+ array_iter = array;
+ for (list_iter = missing_rpm_list; list_iter != NULL;
+ list_iter = list_iter->next)
+ {
+ *array_iter++ = list_iter->rpm;
+ }
+ gdb_assert (array_iter == array + missing_rpm_list_entries);
+
+ qsort (array, missing_rpm_list_entries, sizeof (*array),
+ (int (*) (const void *, const void *)) missing_rpm_list_compar);
+
+ printf_unfiltered (_("Missing separate debuginfos, use: %s"),
+ "debuginfo-install");
+ for (array_iter = array; array_iter < array + missing_rpm_list_entries;
+ array_iter++)
+ {
+ putchar_unfiltered (' ');
+ puts_unfiltered (*array_iter);
+ }
+ putchar_unfiltered ('\n');
+
+ while (missing_rpm_list != NULL)
+ {
+ list_iter = missing_rpm_list;
+ missing_rpm_list = list_iter->next;
+ xfree (list_iter);
+ }
+ missing_rpm_list_entries = 0;
+
+ do_cleanups (cleanups);
+}
+
+static void
+missing_rpm_change (void)
+{
+ debug_flush_missing ();
+
+ gdb_assert (missing_rpm_list == NULL);
+ if (missing_rpm_hash != NULL)
+ {
+ htab_delete (missing_rpm_hash);
+ missing_rpm_hash = NULL;
+ }
+}
+
+enum missing_exec
+ {
+ /* Init state. EXEC_BFD also still could be NULL. */
+ MISSING_EXEC_NOT_TRIED,
+ /* We saw a non-NULL EXEC_BFD but RPM has no info about it. */
+ MISSING_EXEC_NOT_FOUND,
+ /* We found EXEC_BFD by RPM and we either have its symbols (either embedded
+ or separate) or the main executable's RPM is now contained in
+ MISSING_RPM_HASH. */
+ MISSING_EXEC_ENLISTED
+ };
+static enum missing_exec missing_exec = MISSING_EXEC_NOT_TRIED;
+
+void
+debug_flush_missing (void)
+{
+ missing_rpm_list_print ();
+}
+
/* This MISSING_FILEPAIR_HASH tracker is used only for the duplicite messages
yum --enablerepo='*-debuginfo' install ...
avoidance. */
@@ -1739,11 +2004,13 @@ missing_filepair_change (void)
/* All their memory came just from missing_filepair_OBSTACK. */
missing_filepair_hash = NULL;
}
+ missing_exec = MISSING_EXEC_NOT_TRIED;
}
static void
debug_print_executable_changed (void)
{
+ missing_rpm_change ();
missing_filepair_change ();
}
@@ -1802,14 +2069,31 @@ debug_print_missing (const char *binary,
}
*slot = missing_filepair;
- /* We do not collect and flush these messages as each such message
- already requires its own separate lines. */
+ if (missing_exec == MISSING_EXEC_NOT_TRIED)
+ {
+ char *exec_filename;
- fprintf_unfiltered (gdb_stdlog,
- _("Missing separate debuginfo for %s\n"), binary);
- if (debug != NULL)
- fprintf_unfiltered (gdb_stdlog, _("Try: %s %s\n"),
- "yum --enablerepo='*-debuginfo' install", debug);
+ exec_filename = get_exec_file (0);
+ if (exec_filename != NULL)
+ {
+ if (missing_rpm_enlist (exec_filename) == 0)
+ missing_exec = MISSING_EXEC_NOT_FOUND;
+ else
+ missing_exec = MISSING_EXEC_ENLISTED;
+ }
+ }
+ if (missing_exec != MISSING_EXEC_ENLISTED)
+ if (missing_rpm_enlist (binary) == 0 && missing_rpm_enlist (debug) == 0)
+ {
+ /* We do not collect and flush these messages as each such message
+ already requires its own separate lines. */
+
+ fprintf_unfiltered (gdb_stdlog,
+ _("Missing separate debuginfo for %s\n"), binary);
+ if (debug != NULL)
+ fprintf_unfiltered (gdb_stdlog, _("Try: %s %s\n"),
+ "yum --enablerepo='*-debuginfo' install", debug);
+ }
}
static char *
--- ./gdb/symfile.h 2009-03-07 02:16:18.000000000 +0100
+++ ./gdb/symfile.h 2009-03-07 01:52:00.000000000 +0100
@@ -378,6 +378,7 @@ extern struct build_id *build_id_addr_ge
extern char *build_id_to_filename (struct build_id *build_id,
char **link_return, int add_debug_suffix);
extern void debug_print_missing (const char *binary, const char *debug);
+extern void debug_flush_missing (void);
/* From dwarf2read.c */
--- ./gdb/testsuite/lib/gdb.exp 2009-03-07 02:10:11.000000000 +0100
+++ ./gdb/testsuite/lib/gdb.exp 2009-03-07 01:52:00.000000000 +0100
@@ -1230,7 +1230,7 @@ proc default_gdb_start { } {
warning "Couldn't set the width to 0."
}
}
- # Turn off the missing warnings as the testsuite does not expect it.
+ # Turn off the missing RPMs warnings as the testsuite does not expect it.
send_gdb "set build-id-verbose 0\n"
gdb_expect 10 {
-re "$gdb_prompt $" {
--- ./gdb/tui/tui-interp.c 2009-03-07 02:28:47.000000000 +0100
+++ ./gdb/tui/tui-interp.c 2009-03-07 01:52:00.000000000 +0100
@@ -30,6 +30,7 @@
#include "tui/tui.h"
#include "tui/tui-io.h"
#include "exceptions.h"
+#include "symfile.h"
/* Set to 1 when the TUI mode must be activated when we first start
gdb. */
@@ -128,6 +129,8 @@ tui_command_loop (void *data)
char *a_prompt;
char *gdb_prompt = get_prompt ();
+ debug_flush_missing ();
+
/* Tell readline what the prompt to display is and what function
it will need to call after a whole line is read. This also
displays the first prompt. */