summaryrefslogtreecommitdiffstats
path: root/main/gdb/50_all_gdb-pie-1.patch
diff options
context:
space:
mode:
Diffstat (limited to 'main/gdb/50_all_gdb-pie-1.patch')
-rw-r--r--main/gdb/50_all_gdb-pie-1.patch1330
1 files changed, 1330 insertions, 0 deletions
diff --git a/main/gdb/50_all_gdb-pie-1.patch b/main/gdb/50_all_gdb-pie-1.patch
new file mode 100644
index 00000000..a20771f6
--- /dev/null
+++ b/main/gdb/50_all_gdb-pie-1.patch
@@ -0,0 +1,1330 @@
+2007-11-02 Jan Kratochvil <jan.kratochvil@redhat.com>
+
+ Port to GDB-6.7.1.
+
+2007-11-02 Jan Kratochvil <jan.kratochvil@redhat.com>
+
+ Port to post-GDB-6.7.1 multi-PC breakpoints.
+
+2007-11-09 Jan Kratochvil <jan.kratochvil@redhat.com>
+
+ * solib-svr4.c (svr4_current_sos): Fix segfault on NULL EXEC_BFD.
+
+2008-02-24 Jan Kratochvil <jan.kratochvil@redhat.com>
+
+ Port to GDB-6.8pre.
+
+2008-02-27 Jan Kratochvil <jan.kratochvil@redhat.com>
+
+ Port to gdb-6.7.50.20080227.
+
+Index: gdb/dwarf2read.c
+===================================================================
+--- a/gdb/dwarf2read.c 2008-02-27 08:57:20.000000000 +0100
++++ b/gdb/dwarf2read.c 2008-02-27 08:57:31.000000000 +0100
+@@ -1217,7 +1217,7 @@ dwarf2_build_psymtabs (struct objfile *o
+ else
+ dwarf2_per_objfile->loc_buffer = NULL;
+
+- if (mainline
++ if ((mainline == 1)
+ || (objfile->global_psymbols.size == 0
+ && objfile->static_psymbols.size == 0))
+ {
+Index: gdb/auxv.c
+===================================================================
+--- a/gdb/auxv.c 2008-01-16 17:27:37.000000000 +0100
++++ b/gdb/auxv.c 2008-02-27 08:57:31.000000000 +0100
+@@ -80,7 +80,7 @@ procfs_xfer_auxv (struct target_ops *ops
+ Return 1 if an entry was read into *TYPEP and *VALP. */
+ int
+ target_auxv_parse (struct target_ops *ops, gdb_byte **readptr,
+- gdb_byte *endptr, CORE_ADDR *typep, CORE_ADDR *valp)
++ gdb_byte *endptr, ULONGEST *typep, CORE_ADDR *valp)
+ {
+ const int sizeof_auxv_field = TYPE_LENGTH (builtin_type_void_data_ptr);
+ gdb_byte *ptr = *readptr;
+@@ -105,9 +105,10 @@ target_auxv_parse (struct target_ops *op
+ an error getting the information. On success, return 1 after
+ storing the entry's value field in *VALP. */
+ int
+-target_auxv_search (struct target_ops *ops, CORE_ADDR match, CORE_ADDR *valp)
++target_auxv_search (struct target_ops *ops, ULONGEST match, CORE_ADDR *valp)
+ {
+- CORE_ADDR type, val;
++ CORE_ADDR val;
++ ULONGEST at_type;
+ gdb_byte *data;
+ LONGEST n = target_read_alloc (ops, TARGET_OBJECT_AUXV, NULL, &data);
+ gdb_byte *ptr = data;
+@@ -117,10 +118,10 @@ target_auxv_search (struct target_ops *o
+ return n;
+
+ while (1)
+- switch (target_auxv_parse (ops, &ptr, data + n, &type, &val))
++ switch (target_auxv_parse (ops, &ptr, data + n, &at_type, &val))
+ {
+ case 1: /* Here's an entry, check it. */
+- if (type == match)
++ if (at_type == match)
+ {
+ xfree (data);
+ *valp = val;
+@@ -143,7 +144,8 @@ target_auxv_search (struct target_ops *o
+ int
+ fprint_target_auxv (struct ui_file *file, struct target_ops *ops)
+ {
+- CORE_ADDR type, val;
++ CORE_ADDR val;
++ ULONGEST at_type;
+ gdb_byte *data;
+ LONGEST len = target_read_alloc (ops, TARGET_OBJECT_AUXV, NULL,
+ &data);
+@@ -153,14 +155,14 @@ fprint_target_auxv (struct ui_file *file
+ if (len <= 0)
+ return len;
+
+- while (target_auxv_parse (ops, &ptr, data + len, &type, &val) > 0)
++ while (target_auxv_parse (ops, &ptr, data + len, &at_type, &val) > 0)
+ {
+ extern int addressprint;
+ const char *name = "???";
+ const char *description = "";
+ enum { dec, hex, str } flavor = hex;
+
+- switch (type)
++ switch (at_type)
+ {
+ #define TAG(tag, text, kind) \
+ case tag: name = #tag; description = text; flavor = kind; break
+@@ -213,7 +215,7 @@ fprint_target_auxv (struct ui_file *file
+ }
+
+ fprintf_filtered (file, "%-4s %-20s %-30s ",
+- paddr_d (type), name, description);
++ paddr_d (at_type), name, description);
+ switch (flavor)
+ {
+ case dec:
+Index: gdb/auxv.h
+===================================================================
+--- a/gdb/auxv.h 2008-01-01 23:53:09.000000000 +0100
++++ b/gdb/auxv.h 2008-02-27 08:57:31.000000000 +0100
+@@ -35,14 +35,14 @@ struct target_ops; /* Forward declarati
+ Return 1 if an entry was read into *TYPEP and *VALP. */
+ extern int target_auxv_parse (struct target_ops *ops,
+ gdb_byte **readptr, gdb_byte *endptr,
+- CORE_ADDR *typep, CORE_ADDR *valp);
++ ULONGEST *typep, CORE_ADDR *valp);
+
+ /* Extract the auxiliary vector entry with a_type matching MATCH.
+ Return zero if no such entry was found, or -1 if there was
+ an error getting the information. On success, return 1 after
+ storing the entry's value field in *VALP. */
+ extern int target_auxv_search (struct target_ops *ops,
+- CORE_ADDR match, CORE_ADDR *valp);
++ ULONGEST match, CORE_ADDR *valp);
+
+ /* Print the contents of the target's AUXV on the specified file. */
+ extern int fprint_target_auxv (struct ui_file *file, struct target_ops *ops);
+Index: gdb/breakpoint.h
+===================================================================
+--- a/gdb/breakpoint.h 2008-02-01 17:24:46.000000000 +0100
++++ b/gdb/breakpoint.h 2008-02-27 08:57:31.000000000 +0100
+@@ -144,6 +144,7 @@ enum enable_state
+ automatically enabled and reset when the call
+ "lands" (either completes, or stops at another
+ eventpoint). */
++ bp_startup_disabled,
+ bp_permanent /* There is a breakpoint instruction hard-wired into
+ the target's code. Don't try to write another
+ breakpoint instruction on top of it, or restore
+@@ -823,6 +824,10 @@ extern void remove_thread_event_breakpoi
+
+ extern void disable_breakpoints_in_shlibs (void);
+
++extern void disable_breakpoints_at_startup (int silent);
++
++extern void re_enable_breakpoints_at_startup (void);
++
+ /* This function returns TRUE if ep is a catchpoint. */
+ extern int ep_is_catchpoint (struct breakpoint *);
+
+Index: gdb/symfile-mem.c
+===================================================================
+--- a/gdb/symfile-mem.c 2008-01-01 23:53:13.000000000 +0100
++++ b/gdb/symfile-mem.c 2008-02-27 08:57:31.000000000 +0100
+@@ -108,7 +108,7 @@ symbol_file_add_from_memory (struct bfd
+ }
+
+ objf = symbol_file_add_from_bfd (nbfd, from_tty,
+- sai, 0, OBJF_SHARED);
++ sai, 2, OBJF_SHARED);
+
+ /* This might change our ideas about frames already looked at. */
+ reinit_frame_cache ();
+Index: gdb/infrun.c
+===================================================================
+--- a/gdb/infrun.c 2008-02-27 08:57:20.000000000 +0100
++++ b/gdb/infrun.c 2008-02-27 08:57:31.000000000 +0100
+@@ -2277,6 +2277,11 @@ process_event_stop_test:
+ #endif
+ target_terminal_inferior ();
+
++ /* For PIE executables, we dont really know where the
++ breakpoints are going to be until we start up the
++ inferior. */
++ re_enable_breakpoints_at_startup ();
++
+ /* If requested, stop when the dynamic linker notifies
+ gdb of events. This allows the user to get control
+ and place breakpoints in initializer routines for
+Index: gdb/objfiles.c
+===================================================================
+--- a/gdb/objfiles.c 2008-01-01 23:53:12.000000000 +0100
++++ b/gdb/objfiles.c 2008-02-27 08:57:31.000000000 +0100
+@@ -49,6 +49,9 @@
+ #include "source.h"
+ #include "addrmap.h"
+
++#include "auxv.h"
++#include "elf/common.h"
++
+ /* Prototypes for local functions */
+
+ static void objfile_alloc_data (struct objfile *objfile);
+@@ -260,7 +263,19 @@ init_entry_point_info (struct objfile *o
+ CORE_ADDR
+ entry_point_address (void)
+ {
+- return symfile_objfile ? symfile_objfile->ei.entry_point : 0;
++ int ret;
++ CORE_ADDR entry_addr;
++
++ /* Find the address of the entry point of the program from the
++ auxv vector. */
++ ret = target_auxv_search (&current_target, AT_ENTRY, &entry_addr);
++ if (ret == 1)
++ return entry_addr;
++ /*if (ret == 0 || ret == -1)*/
++ else
++ {
++ return symfile_objfile ? symfile_objfile->ei.entry_point : 0;
++ }
+ }
+
+ /* Create the terminating entry of OBJFILE's minimal symbol table.
+Index: gdb/solib-svr4.c
+===================================================================
+--- a/gdb/solib-svr4.c 2008-02-27 08:57:19.000000000 +0100
++++ b/gdb/solib-svr4.c 2008-02-27 08:59:06.000000000 +0100
+@@ -31,6 +31,8 @@
+ #include "gdbcore.h"
+ #include "target.h"
+ #include "inferior.h"
++#include "auxv.h"
++#include "command.h"
+
+ #include "gdb_assert.h"
+
+@@ -246,7 +248,9 @@ static char *debug_loader_name;
+
+ /* Local function prototypes */
+
++#if 0
+ static int match_main (char *);
++#endif
+
+ static CORE_ADDR bfd_lookup_symbol (bfd *, char *);
+
+@@ -349,10 +353,12 @@ scan_dyntag (int dyntag, bfd *abfd, CORE
+ int arch_size, step, sect_size;
+ long dyn_tag;
+ CORE_ADDR dyn_ptr, dyn_addr;
++ CORE_ADDR entry_addr;
+ gdb_byte *bufend, *bufstart, *buf;
+ Elf32_External_Dyn *x_dynp_32;
+ Elf64_External_Dyn *x_dynp_64;
+ struct bfd_section *sect;
++ int ret;
+
+ if (abfd == NULL)
+ return 0;
+@@ -360,19 +366,74 @@ scan_dyntag (int dyntag, bfd *abfd, CORE
+ if (arch_size == -1)
+ return 0;
+
++ /* The auxv vector based relocatable files reading is limited to the main
++ executable. */
++ gdb_assert (abfd == exec_bfd || ptr == NULL);
++
++ if (ptr != NULL)
++ {
++ /* Find the address of the entry point of the program from the
++ auxv vector. */
++ ret = target_auxv_search (&current_target, AT_ENTRY, &entry_addr);
++
++ if (ret == 0 || ret == -1)
++ {
++ /* No auxv info, maybe an older kernel. Fake our way through. */
++ entry_addr = bfd_get_start_address (exec_bfd);
++
++ if (debug_solib)
++ fprintf_unfiltered (gdb_stdlog,
++ "elf_locate_base: program entry address not found. Using bfd's 0x%s for %s\n",
++ paddr_nz (entry_addr), exec_bfd->filename);
++ }
++ else
++ {
++ if (debug_solib)
++ fprintf_unfiltered (gdb_stdlog,
++ "elf_locate_base: found program entry address 0x%s for %s\n",
++ paddr_nz (entry_addr), exec_bfd->filename);
++ }
++ }
++
+ /* Find the start address of the .dynamic section. */
+ sect = bfd_get_section_by_name (abfd, ".dynamic");
+ if (sect == NULL)
+- return 0;
++ {
++ if (debug_solib)
++ fprintf_unfiltered (gdb_stdlog,
++ "elf_locate_base: .dynamic section not found in %s -- return now\n",
++ exec_bfd->filename);
++ return 0;
++ }
++ else
++ {
++ if (debug_solib)
++ fprintf_unfiltered (gdb_stdlog,
++ "elf_locate_base: .dynamic section found in %s\n",
++ exec_bfd->filename);
++ }
++
+ dyn_addr = bfd_section_vma (abfd, sect);
++ if (debug_solib)
++ fprintf_unfiltered (gdb_stdlog,
++ "elf_locate_base: .dynamic addr 0x%s\n",
++ paddr_nz (dyn_addr));
+
+ /* Read in .dynamic from the BFD. We will get the actual value
+ from memory later. */
+ sect_size = bfd_section_size (abfd, sect);
+ buf = bufstart = alloca (sect_size);
++ if (debug_solib)
++ fprintf_unfiltered (gdb_stdlog,
++ "elf_locate_base: read in .dynamic section\n");
+ if (!bfd_get_section_contents (abfd, sect,
+ buf, 0, sect_size))
+- return 0;
++ {
++ if (debug_solib)
++ fprintf_unfiltered (gdb_stdlog,
++ "elf_locate_base: couldn't read .dynamic section -- return now\n");
++ return 0;
++ }
+
+ /* Iterate over BUF and scan for DYNTAG. If found, set PTR and return. */
+ step = (arch_size == 32) ? sizeof (Elf32_External_Dyn)
+@@ -405,9 +466,43 @@ scan_dyntag (int dyntag, bfd *abfd, CORE
+ CORE_ADDR ptr_addr;
+
+ ptr_addr = dyn_addr + (buf - bufstart) + arch_size / 8;
++ if (ptr != NULL)
++ {
++ if (debug_solib)
++ fprintf_unfiltered (gdb_stdlog,
++ "elf_locate_base: unrelocated ptr addr 0x%s\n",
++ paddr_nz (ptr_addr));
++ ptr_addr += entry_addr - bfd_get_start_address (exec_bfd);
++ if (debug_solib)
++ fprintf_unfiltered (gdb_stdlog,
++ "elf_locate_base: relocated ptr addr 0x%s"
++ " (auxv entry 0x%s, bfd start address 0x%s)"
++ " for %s\n",
++ paddr_nz (ptr_addr), paddr_nz (entry_addr),
++ paddr_nz (bfd_get_start_address (exec_bfd)),
++ exec_bfd->filename);
++ }
+ if (target_read_memory (ptr_addr, ptr_buf, arch_size / 8) == 0)
+- dyn_ptr = extract_typed_address (ptr_buf,
+- builtin_type_void_data_ptr);
++ {
++ dyn_ptr = extract_typed_address (ptr_buf,
++ builtin_type_void_data_ptr);
++ if (ptr != NULL)
++ {
++ if (debug_solib)
++ fprintf_unfiltered (gdb_stdlog,
++ "elf_locate_base: Tag entry has value 0x%s -- return now\n",
++ paddr_nz (dyn_ptr));
++ }
++ }
++ else
++ {
++ if (ptr != NULL)
++ {
++ if (debug_solib)
++ fprintf_unfiltered (gdb_stdlog,
++ "elf_locate_base: Couldn't read tag entry value -- return now\n");
++ }
++ }
+ *ptr = dyn_ptr;
+ }
+ return 1;
+@@ -544,6 +639,10 @@ solib_svr4_r_map (void)
+ {
+ struct link_map_offsets *lmo = svr4_fetch_link_map_offsets ();
+
++ if (debug_solib)
++ fprintf_unfiltered (gdb_stdlog,
++ "solib_svr4_r_map: read at 0x%s\n",
++ paddr_nz (debug_base + lmo->r_map_offset));
+ return read_memory_typed_address (debug_base + lmo->r_map_offset,
+ builtin_type_void_data_ptr);
+ }
+@@ -713,6 +812,11 @@ svr4_current_sos (void)
+ struct so_list *head = 0;
+ struct so_list **link_ptr = &head;
+ CORE_ADDR ldsomap = 0;
++ const char *filename = exec_bfd ? exec_bfd->filename : "<none>";
++
++ if (debug_solib)
++ fprintf_unfiltered (gdb_stdlog,
++ "svr4_current_sos: exec_bfd %s\n", filename);
+
+ /* Always locate the debug struct, in case it has moved. */
+ debug_base = 0;
+@@ -721,10 +825,19 @@ svr4_current_sos (void)
+ /* If we can't find the dynamic linker's base structure, this
+ must not be a dynamically linked executable. Hmm. */
+ if (! debug_base)
+- return svr4_default_sos ();
++ {
++ if (debug_solib)
++ fprintf_unfiltered (gdb_stdlog,
++ "svr4_current_sos: no DT_DEBUG found in %s -- return now\n",
++ filename);
++ return svr4_default_sos ();
++ }
+
+ /* Walk the inferior's link map list, and build our list of
+ `struct so_list' nodes. */
++ if (debug_solib)
++ fprintf_unfiltered (gdb_stdlog,
++ "svr4_current_sos: walk link map in %s\n", filename);
+ lm = solib_svr4_r_map ();
+
+ while (lm)
+@@ -740,23 +853,103 @@ svr4_current_sos (void)
+ new->lm_info->lm = xzalloc (lmo->link_map_size);
+ make_cleanup (xfree, new->lm_info->lm);
+
++ if (debug_solib)
++ fprintf_unfiltered (gdb_stdlog,
++ "svr4_current_sos: read lm at 0x%s\n", paddr_nz(lm));
+ read_memory (lm, new->lm_info->lm, lmo->link_map_size);
+
+ lm = LM_NEXT (new);
+
++ if (debug_solib)
++ fprintf_unfiltered (gdb_stdlog,
++ "svr4_current_sos: is first link entry? %d\n",
++ IGNORE_FIRST_LINK_MAP_ENTRY (new));
++
+ /* For SVR4 versions, the first entry in the link map is for the
+ inferior executable, so we must ignore it. For some versions of
+ SVR4, it has no name. For others (Solaris 2.3 for example), it
+ does have a name, so we can no longer use a missing name to
+ decide when to ignore it. */
+- if (IGNORE_FIRST_LINK_MAP_ENTRY (new) && ldsomap == 0)
+- free_so (new);
++ if (exec_bfd != NULL && IGNORE_FIRST_LINK_MAP_ENTRY (new) && ldsomap == 0)
++ {
++ /* It is the first link map entry, i.e. it is the main executable. */
++
++ if (bfd_get_start_address (exec_bfd) == entry_point_address ())
++ {
++ /* Non-pie case, main executable has not been relocated. */
++ free_so (new);
++ }
++ else
++ {
++ /* Pie case, main executable has been relocated. */
++ struct so_list *gdb_solib;
++
++ if (debug_solib)
++ fprintf_unfiltered (gdb_stdlog,
++ "svr4_current_sos: Processing first link map entry\n");
++ strncpy (new->so_name, exec_bfd->filename,
++ SO_NAME_MAX_PATH_SIZE - 1);
++ new->so_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0';
++ strcpy (new->so_original_name, new->so_name);
++ /*new->main = 1;*/
++ new->main_relocated = 0;
++
++ if (debug_solib)
++ {
++ fprintf_unfiltered (gdb_stdlog,
++ "svr4_current_sos: Processing nameless DSO\n");
++ fprintf_unfiltered (gdb_stdlog,
++ "svr4_current_sos: adding name %s\n",
++ new->so_name);
++ }
++
++ for (gdb_solib = master_so_list ();
++ gdb_solib;
++ gdb_solib = gdb_solib->next)
++ {
++ if (debug_solib)
++ fprintf_unfiltered (gdb_stdlog,
++ "svr4_current_sos: compare gdb %s and new %s\n",
++ gdb_solib->so_name, new->so_name);
++ if (strcmp (gdb_solib->so_name, new->so_name) == 0)
++ if (gdb_solib->main_relocated)
++ {
++ if (debug_solib)
++ fprintf_unfiltered (gdb_stdlog,
++ "svr4_current_sos: found main relocated\n");
++ break;
++ }
++ }
++
++ if ((gdb_solib && !gdb_solib->main_relocated) || (!gdb_solib))
++ {
++ add_to_target_sections (0 /*from_tty*/, &current_target, new);
++ new->main = 1;
++ }
++
++ /* We need this in the list of shared libs we return because
++ solib_add_stub will loop through it and add the symbol file. */
++ new->next = 0;
++ *link_ptr = new;
++ link_ptr = &new->next;
++ }
++ } /* End of IGNORE_FIRST_LINK_MAP_ENTRY */
+ else
+ {
++ /* This is not the first link map entry, i.e. is not the main
++ executable. Note however that it could be the DSO supplied on
++ certain systems (i.e. Linux 2.6) containing information about
++ the vsyscall page. We must ignore such entry. This entry is
++ nameless (just like the one for the main executable, sigh). */
++
+ int errcode;
+ char *buffer;
+
+ /* Extract this shared object's name. */
++ if (debug_solib)
++ fprintf_unfiltered (gdb_stdlog,
++ "svr4_current_sos: read LM_NAME\n");
++
+ target_read_string (LM_NAME (new), &buffer,
+ SO_NAME_MAX_PATH_SIZE - 1, &errcode);
+ if (errcode != 0)
+@@ -764,23 +957,35 @@ svr4_current_sos (void)
+ safe_strerror (errcode));
+ else
+ {
+- strncpy (new->so_name, buffer, SO_NAME_MAX_PATH_SIZE - 1);
+- new->so_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0';
+- strcpy (new->so_original_name, new->so_name);
+- }
+- xfree (buffer);
+-
+- /* If this entry has no name, or its name matches the name
+- for the main executable, don't include it in the list. */
+- if (! new->so_name[0]
+- || match_main (new->so_name))
+- free_so (new);
+- else
+- {
+- new->next = 0;
+- *link_ptr = new;
+- link_ptr = &new->next;
++ if (debug_solib)
++ fprintf_unfiltered (gdb_stdlog,
++ "svr4_current_sos: LM_NAME is <%s>\n",
++ buffer);
++ /* The name could be empty, in which case it is the
++ system supplied DSO. */
++ if (strcmp (buffer, "") == 0)
++ free_so (new);
++ else
++ {
++ strncpy (new->so_name, buffer, SO_NAME_MAX_PATH_SIZE - 1);
++ new->so_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0';
++ strcpy (new->so_original_name, new->so_name);
++ if (debug_solib)
++ {
++ fprintf_unfiltered (gdb_stdlog,
++ "svr4_current_sos: Processing DSO: %s\n",
++ new->so_name);
++ fprintf_unfiltered (gdb_stdlog,
++ "svr4_current_sos: first link entry %d\n",
++ IGNORE_FIRST_LINK_MAP_ENTRY (new));
++ }
++
++ new->next = 0;
++ *link_ptr = new;
++ link_ptr = &new->next;
++ }
+ }
++ xfree (buffer);
+ }
+
+ /* On Solaris, the dynamic linker is not in the normal list of
+@@ -796,6 +1001,9 @@ svr4_current_sos (void)
+ if (head == NULL)
+ return svr4_default_sos ();
+
++ if (debug_solib)
++ fprintf_unfiltered (gdb_stdlog, "svr4_current_sos: ENDS %s\n", filename);
++
+ return head;
+ }
+
+@@ -875,7 +1083,7 @@ svr4_fetch_objfile_link_map (struct objf
+ /* On some systems, the only way to recognize the link map entry for
+ the main executable file is by looking at its name. Return
+ non-zero iff SONAME matches one of the known main executable names. */
+-
++#if 0
+ static int
+ match_main (char *soname)
+ {
+@@ -889,6 +1097,7 @@ match_main (char *soname)
+
+ return (0);
+ }
++#endif
+
+ /* Return 1 if PC lies in the dynamic symbol resolution code of the
+ SVR4 run time loader. */
+@@ -1040,6 +1249,11 @@ enable_break (void)
+ /* Find the .interp section; if not found, warn the user and drop
+ into the old breakpoint at symbol code. */
+ interp_sect = bfd_get_section_by_name (exec_bfd, ".interp");
++
++ if (debug_solib)
++ fprintf_unfiltered (gdb_stdlog,
++ "enable_break: search for .interp in %s\n",
++ exec_bfd->filename);
+ if (interp_sect)
+ {
+ unsigned int interp_sect_size;
+@@ -1074,6 +1288,9 @@ enable_break (void)
+ if (tmp_fd >= 0)
+ tmp_bfd = bfd_fopen (tmp_pathname, gnutarget, FOPEN_RB, tmp_fd);
+
++ if (debug_solib)
++ fprintf_unfiltered (gdb_stdlog,
++ "enable_break: opening %s\n", tmp_pathname);
+ if (tmp_bfd == NULL)
+ goto bkpt_at_symbol;
+
+@@ -1180,6 +1397,9 @@ enable_break (void)
+ if (sym_addr != 0)
+ {
+ create_solib_event_breakpoint (load_addr + sym_addr);
++ if (debug_solib)
++ fprintf_unfiltered (gdb_stdlog,
++ "enable_break: solib bp set\n");
+ return 1;
+ }
+
+@@ -1440,6 +1660,8 @@ svr4_solib_create_inferior_hook (void)
+ while (stop_signal != TARGET_SIGNAL_TRAP);
+ stop_soon = NO_STOP_QUIETLY;
+ #endif /* defined(_SCO_DS) */
++
++ disable_breakpoints_at_startup (1);
+ }
+
+ static void
+@@ -1620,6 +1842,75 @@ svr4_lp64_fetch_link_map_offsets (void)
+
+ return lmp;
+ }
++void
++info_linkmap_command (char *cmd, int from_tty)
++{
++ CORE_ADDR lm;
++
++ /* Make sure we've looked up the inferior's dynamic linker's base
++ structure. */
++ if (! debug_base)
++ {
++ debug_base = locate_base ();
++
++ /* If we can't find the dynamic linker's base structure, this
++ must not be a dynamically linked executable. Hmm. */
++ if (! debug_base)
++ {
++ if (debug_solib)
++ fprintf_unfiltered (gdb_stdlog,
++ "svr4_print_linkmap: no DT_DEBUG found in %s -- return now\n",
++ exec_bfd->filename);
++ return;
++ }
++ }
++
++ /* Walk the inferior's link map list, and print the info. */
++
++ lm = solib_svr4_r_map ();
++ while (lm)
++ {
++ int errcode;
++ char *buffer;
++ CORE_ADDR load_addr;
++
++ struct link_map_offsets *lmo = svr4_fetch_link_map_offsets ();
++ struct so_list *new
++ = (struct so_list *) xmalloc (sizeof (struct so_list));
++ struct cleanup *old_chain = make_cleanup (xfree, new);
++
++ memset (new, 0, sizeof (*new));
++
++ new->lm_info = xmalloc (sizeof (struct lm_info));
++ make_cleanup (xfree, new->lm_info);
++
++ new->lm_info->lm = xmalloc (lmo->link_map_size);
++ make_cleanup (xfree, new->lm_info->lm);
++ memset (new->lm_info->lm, 0, lmo->link_map_size);
++
++ if (debug_solib)
++ fprintf_unfiltered (gdb_stdlog,
++ "svr4_print_linkmap: read lm at 0x%s\n", paddr_nz(lm));
++ read_memory (lm, new->lm_info->lm, lmo->link_map_size);
++
++ lm = LM_NEXT (new);
++
++ /* Load address. */
++ load_addr = LM_ADDR_CHECK (new, NULL);
++ /* Shared object's name. */
++ target_read_string (LM_NAME (new), &buffer,
++ SO_NAME_MAX_PATH_SIZE - 1, &errcode);
++ make_cleanup (xfree, buffer);
++ if (errcode != 0)
++ {
++ warning ("svr4_print_linkmap: Can't read pathname for load map: %s\n",
++ safe_strerror (errcode));
++ }
++ fprintf_filtered (gdb_stdout, "%-8s %-30s\n", paddr(load_addr), buffer);
++ do_cleanups (old_chain);
++ }
++}
++
+
+
+ struct target_so_ops svr4_so_ops;
+@@ -1678,4 +1969,7 @@ _initialize_svr4_solib (void)
+ svr4_so_ops.in_dynsym_resolve_code = svr4_in_dynsym_resolve_code;
+ svr4_so_ops.lookup_lib_global_symbol = elf_lookup_lib_symbol;
+ svr4_so_ops.same = svr4_same;
++
++ add_info ("linkmap", info_linkmap_command,
++ "Display the inferior's linkmap.");
+ }
+Index: gdb/varobj.c
+===================================================================
+--- a/gdb/varobj.c 2008-02-04 08:49:04.000000000 +0100
++++ b/gdb/varobj.c 2008-02-27 08:57:31.000000000 +0100
+@@ -1078,6 +1078,62 @@ install_new_value (struct varobj *var, s
+ return changed;
+ }
+
++void
++varobj_refresh (void)
++{
++ struct varobj *var;
++ struct varobj_root *croot;
++ int mycount = rootcount;
++ char * name;
++
++ croot = rootlist;
++ while ((croot != NULL) && (mycount > 0))
++ {
++ var = croot->rootvar;
++
++ /* Get rid of the memory for the old expression. This also
++ leaves var->root->exp == NULL, which is ok for the parsing
++ below. */
++ free_current_contents (&var->root->exp);
++
++ value_free (var->value);
++ var->type = NULL;
++
++ name = xstrdup (var->name);
++
++ /* Reparse the expression. Wrap the call to parse expression,
++ so we can return a sensible error. */
++ if (!gdb_parse_exp_1 (&name, var->root->valid_block, 0, &var->root->exp))
++ {
++ return;
++ }
++
++ /* We definitively need to catch errors here.
++ If evaluate_expression succeeds we got the value we wanted.
++ But if it fails, we still go on with a call to evaluate_type() */
++ if (gdb_evaluate_expression (var->root->exp, &var->value))
++ {
++ /* no error */
++ release_value (var->value);
++ if (value_lazy (var->value))
++ gdb_value_fetch_lazy (var->value);
++ }
++ else
++ var->value = evaluate_type (var->root->exp);
++
++ var->type = value_type (var->value);
++
++ mycount--;
++ croot = croot->next;
++ }
++
++ if (mycount || (croot != NULL))
++ warning
++ ("varobj_refresh: assertion failed - wrong tally of root vars (%d:%d)",
++ rootcount, mycount);
++}
++
++
+ /* Update the values for a variable and its children. This is a
+ two-pronged attack. First, re-parse the value for the root's
+ expression to see if it's changed. Then go all the way
+Index: gdb/solist.h
+===================================================================
+--- a/gdb/solist.h 2008-01-07 16:19:58.000000000 +0100
++++ b/gdb/solist.h 2008-02-27 08:57:31.000000000 +0100
+@@ -61,6 +61,8 @@ struct so_list
+ bfd *abfd;
+ char symbols_loaded; /* flag: symbols read in yet? */
+ char from_tty; /* flag: print msgs? */
++ char main; /* flag: is this the main executable? */
++ char main_relocated; /* flag: has it been relocated yet? */
+ struct objfile *objfile; /* objfile for loaded lib */
+ struct section_table *sections;
+ struct section_table *sections_end;
+@@ -127,9 +129,15 @@ void free_so (struct so_list *so);
+ /* Return address of first so_list entry in master shared object list. */
+ struct so_list *master_so_list (void);
+
++/* Return address of first so_list entry in master shared object list. */
++struct so_list *master_so_list (void);
++
+ /* Find solib binary file and open it. */
+ extern int solib_open (char *in_pathname, char **found_pathname);
+
++/* Add the list of sections in so_list to the target to_sections. */
++extern void add_to_target_sections (int, struct target_ops *, struct so_list *);
++
+ /* FIXME: gdbarch needs to control this variable */
+ extern struct target_so_ops *current_target_so_ops;
+
+@@ -140,4 +148,6 @@ struct symbol *solib_global_lookup (cons
+ const domain_enum domain,
+ struct symtab **symtab);
+
++/* Controls the printing of debugging output. */
++extern int debug_solib;
+ #endif
+Index: gdb/varobj.h
+===================================================================
+--- a/gdb/varobj.h 2008-01-30 08:17:31.000000000 +0100
++++ b/gdb/varobj.h 2008-02-27 08:57:31.000000000 +0100
+@@ -122,4 +122,6 @@ extern void varobj_invalidate (void);
+
+ extern int varobj_editable_p (struct varobj *var);
+
++extern void varobj_refresh(void);
++
+ #endif /* VAROBJ_H */
+Index: gdb/symfile.c
+===================================================================
+--- a/gdb/symfile.c 2008-01-29 23:47:20.000000000 +0100
++++ b/gdb/symfile.c 2008-02-27 08:57:31.000000000 +0100
+@@ -47,6 +47,7 @@
+ #include "readline/readline.h"
+ #include "gdb_assert.h"
+ #include "block.h"
++#include "varobj.h"
+ #include "observer.h"
+ #include "exec.h"
+ #include "parser-defs.h"
+@@ -778,7 +779,7 @@ syms_from_objfile (struct objfile *objfi
+
+ /* Now either addrs or offsets is non-zero. */
+
+- if (mainline)
++ if (mainline == 1)
+ {
+ /* We will modify the main symbol table, make sure that all its users
+ will be cleaned up if an error occurs during symbol reading. */
+@@ -806,7 +807,7 @@ syms_from_objfile (struct objfile *objfi
+
+ We no longer warn if the lowest section is not a text segment (as
+ happens for the PA64 port. */
+- if (!mainline && addrs && addrs->other[0].name)
++ if (/*!mainline &&*/ addrs && addrs->other[0].name)
+ {
+ asection *lower_sect;
+ asection *sect;
+@@ -975,17 +976,21 @@ new_symfile_objfile (struct objfile *obj
+ /* If this is the main symbol file we have to clean up all users of the
+ old main symbol file. Otherwise it is sufficient to fixup all the
+ breakpoints that may have been redefined by this symbol file. */
+- if (mainline)
++ if (mainline == 1)
+ {
+ /* OK, make it the "real" symbol file. */
+ symfile_objfile = objfile;
+
+ clear_symtab_users ();
+ }
+- else
++ else if (mainline == 0)
+ {
+ breakpoint_re_set ();
+ }
++ else
++ {
++ /* Don't reset breakpoints or it will screw up PIE. */
++ }
+
+ /* We're done reading the symbol file; finish off complaints. */
+ clear_complaints (&symfile_complaints, 0, verbo);
+@@ -1028,7 +1033,7 @@ symbol_file_add_with_addrs_or_offsets (b
+ interactively wiping out any existing symbols. */
+
+ if ((have_full_symbols () || have_partial_symbols ())
+- && mainline
++ && (mainline == 1)
+ && from_tty
+ && !query ("Load new symbol table from \"%s\"? ", name))
+ error (_("Not confirmed."));
+@@ -1212,6 +1217,10 @@ symbol_file_clear (int from_tty)
+ symfile_objfile->name)
+ : !query (_("Discard symbol table? "))))
+ error (_("Not confirmed."));
++#ifdef CLEAR_SOLIB
++ CLEAR_SOLIB ();
++#endif
++
+ free_all_objfiles ();
+
+ /* solib descriptors may have handles to objfiles. Since their
+@@ -2466,6 +2475,8 @@ reread_symbols (void)
+ /* Discard cleanups as symbol reading was successful. */
+ discard_cleanups (old_cleanups);
+
++ init_entry_point_info (objfile);
++
+ /* If the mtime has changed between the time we set new_modtime
+ and now, we *want* this to be out of date, so don't call stat
+ again now. */
+@@ -2834,6 +2845,7 @@ clear_symtab_users (void)
+ breakpoint_re_set ();
+ set_default_breakpoint (0, 0, 0, 0);
+ clear_pc_function_cache ();
++ varobj_refresh ();
+ observer_notify_new_objfile (NULL);
+
+ /* Clear globals which might have pointed into a removed objfile.
+Index: gdb/breakpoint.c
+===================================================================
+--- a/gdb/breakpoint.c 2008-02-27 08:57:20.000000000 +0100
++++ b/gdb/breakpoint.c 2008-02-27 08:57:31.000000000 +0100
+@@ -923,7 +923,7 @@ update_watchpoint (struct breakpoint *b,
+ value_release_to_mark (mark);
+
+ /* Look at each value on the value chain. */
+- for (; v; v = next)
++ for (; v; v = value_next (v))
+ {
+ /* If it's a memory location, and GDB actually needed
+ its contents to evaluate the expression, then we
+@@ -3882,7 +3882,8 @@ describe_other_breakpoints (CORE_ADDR pc
+ printf_filtered (" (thread %d)", b->thread);
+ printf_filtered ("%s%s ",
+ ((b->enable_state == bp_disabled ||
+- b->enable_state == bp_call_disabled)
++ b->enable_state == bp_call_disabled ||
++ b->enable_state == bp_startup_disabled)
+ ? " (disabled)"
+ : b->enable_state == bp_permanent
+ ? " (permanent)"
+@@ -4534,6 +4535,62 @@ disable_breakpoints_in_unloaded_shlib (s
+ }
+ }
+
++void
++disable_breakpoints_at_startup (int silent)
++{
++ struct breakpoint *b;
++ int disabled_startup_breaks = 0;
++
++ if (bfd_get_start_address (exec_bfd) != entry_point_address ())
++ {
++ ALL_BREAKPOINTS (b)
++ {
++ if (((b->type == bp_breakpoint) ||
++ (b->type == bp_hardware_breakpoint)) &&
++ b->enable_state == bp_enabled &&
++ !b->loc->duplicate)
++ {
++ b->enable_state = bp_startup_disabled;
++ if (!silent)
++ {
++ if (!disabled_startup_breaks)
++ {
++ target_terminal_ours_for_output ();
++ warning ("Temporarily disabling breakpoints:");
++ }
++ disabled_startup_breaks = 1;
++ warning ("breakpoint #%d addr 0x%s", b->number, paddr_nz(b->loc->address));
++ }
++ }
++ }
++ }
++}
++
++/* Try to reenable any breakpoints after startup. */
++void
++re_enable_breakpoints_at_startup (void)
++{
++ struct breakpoint *b;
++
++ if (bfd_get_start_address (exec_bfd) != entry_point_address ())
++ {
++ ALL_BREAKPOINTS (b)
++ if (b->enable_state == bp_startup_disabled)
++ {
++ char buf[1];
++
++ /* Do not reenable the breakpoint if the shared library
++ is still not mapped in. */
++ if (target_read_memory (b->loc->address, buf, 1) == 0)
++ {
++ /*printf ("enabling breakpoint at 0x%s\n", paddr_nz(b->loc->address));*/
++ b->enable_state = bp_enabled;
++ }
++ }
++ }
++}
++
++
+ static void
+ create_fork_vfork_event_catchpoint (int tempflag, char *cond_string,
+ enum bptype bp_kind)
+Index: gdb/solib.c
+===================================================================
+--- a/gdb/solib.c 2008-01-07 16:19:58.000000000 +0100
++++ b/gdb/solib.c 2008-02-27 08:57:31.000000000 +0100
+@@ -79,6 +79,8 @@ set_solib_ops (struct gdbarch *gdbarch,
+
+ /* external data declarations */
+
++int debug_solib;
++
+ /* FIXME: gdbarch needs to control this variable, or else every
+ configuration needs to call set_solib_ops. */
+ struct target_so_ops *current_target_so_ops;
+@@ -102,6 +104,8 @@ The search path for loading non-absolute
+ value);
+ }
+
++void add_to_target_sections (int, struct target_ops *, struct so_list *);
++
+ /*
+
+ GLOBAL FUNCTION
+@@ -391,7 +395,6 @@ free_so (struct so_list *so)
+ xfree (so);
+ }
+
+-
+ /* Return address of first so_list entry in master shared object list. */
+ struct so_list *
+ master_so_list (void)
+@@ -399,7 +402,6 @@ master_so_list (void)
+ return so_list_head;
+ }
+
+-
+ /* A small stub to get us past the arg-passing pinhole of catch_errors. */
+
+ static int
+@@ -411,15 +413,40 @@ symbol_add_stub (void *arg)
+ /* Have we already loaded this shared object? */
+ ALL_OBJFILES (so->objfile)
+ {
+- if (strcmp (so->objfile->name, so->so_name) == 0)
++ /* Found an already loaded shared library. */
++ if (strcmp (so->objfile->name, so->so_name) == 0
++ && !so->main)
+ return 1;
++ /* Found an already loaded main executable. This could happen in
++ two circumstances.
++ First case: the main file has already been read in
++ as the first thing that gdb does at startup, and the file
++ hasn't been relocated properly yet. Therefor we need to read
++ it in with the proper section info.
++ Second case: it has been read in with the correct relocation,
++ and therefore we need to skip it. */
++ if (strcmp (so->objfile->name, so->so_name) == 0
++ && so->main
++ && so->main_relocated)
++ return 1;
+ }
+
+ sap = build_section_addr_info_from_section_table (so->sections,
+ so->sections_end);
+
+- so->objfile = symbol_file_add (so->so_name, so->from_tty,
+- sap, 0, OBJF_SHARED);
++ if (so->main)
++ {
++ if (debug_solib)
++ fprintf_unfiltered (gdb_stdlog,
++ "symbol_add_stub: adding symbols for main\n");
++ so->objfile = symbol_file_add (so->so_name, /*so->from_tty*/ 0,
++ sap, 1, 0);
++ so->main_relocated = 1;
++ }
++ else
++ so->objfile = symbol_file_add (so->so_name, so->from_tty,
++ sap, 0, OBJF_SHARED);
++
+ free_section_addr_info (sap);
+
+ return (1);
+@@ -545,6 +572,10 @@ update_solib_list (int from_tty, struct
+ }
+ else
+ {
++ if (debug_solib)
++ fprintf_unfiltered (gdb_stdlog,
++ "update_solib_list: compare gdb:%s and inferior:%s\n",
++ gdb->so_original_name, i->so_original_name);
+ if (! strcmp (gdb->so_original_name, i->so_original_name))
+ break;
+ }
+@@ -599,28 +630,7 @@ update_solib_list (int from_tty, struct
+ /* Fill in the rest of each of the `struct so_list' nodes. */
+ for (i = inferior; i; i = i->next)
+ {
+- i->from_tty = from_tty;
+-
+- /* Fill in the rest of the `struct so_list' node. */
+- catch_errors (solib_map_sections, i,
+- "Error while mapping shared library sections:\n",
+- RETURN_MASK_ALL);
+-
+- /* If requested, add the shared object's sections to the TARGET's
+- section table. Do this immediately after mapping the object so
+- that later nodes in the list can query this object, as is needed
+- in solib-osf.c. */
+- if (target)
+- {
+- int count = (i->sections_end - i->sections);
+- if (count > 0)
+- {
+- int space = target_resize_to_sections (target, count);
+- memcpy (target->to_sections + space,
+- i->sections,
+- count * sizeof (i->sections[0]));
+- }
+- }
++ add_to_target_sections (from_tty, target, i);
+
+ /* Notify any observer that the shared object has been
+ loaded now that we've added it to GDB's tables. */
+@@ -716,6 +726,41 @@ solib_add (char *pattern, int from_tty,
+ }
+ }
+
++void
++add_to_target_sections (int from_tty, struct target_ops *target, struct so_list *solib)
++{
++ /* If this is set, then the sections have been already added to the
++ target list. */
++ if (solib->main)
++ return;
++
++ solib->from_tty = from_tty;
++
++ /* Fill in the rest of the `struct so_list' node. */
++ catch_errors (solib_map_sections, solib,
++ "Error while mapping shared library sections:\n",
++ RETURN_MASK_ALL);
++
++ /* If requested, add the shared object's sections to the TARGET's
++ section table. Do this immediately after mapping the object so
++ that later nodes in the list can query this object, as is needed
++ in solib-osf.c. */
++ if (target)
++ {
++ int count = (solib->sections_end - solib->sections);
++ if (count > 0)
++ {
++ int space = target_resize_to_sections (target, count);
++ if (debug_solib)
++ fprintf_unfiltered (gdb_stdlog,
++ "add_to_target_sections: add %s to to_sections\n",
++ solib->so_original_name);
++ memcpy (target->to_sections + space,
++ solib->sections,
++ count * sizeof (solib->sections[0]));
++ }
++ }
++}
+
+ /*
+
+@@ -1035,4 +1080,12 @@ This takes precedence over the environme
+ reload_shared_libraries,
+ show_solib_search_path,
+ &setlist, &showlist);
++
++ add_setshow_boolean_cmd ("solib", no_class, &debug_solib,
++ _("\
++Set debugging of GNU/Linux shlib module.\n"), _("\
++Show debugging status of GNU/Linux shlib module.\n"), _("\
++Enables printf debugging output of GNU/Linux shlib module.\n"),
++ NULL, NULL,
++ &setdebuglist, &showdebuglist);
+ }
+Index: gdb/elfread.c
+===================================================================
+--- a/gdb/elfread.c 2008-01-01 23:53:09.000000000 +0100
++++ b/gdb/elfread.c 2008-02-27 08:57:31.000000000 +0100
+@@ -644,7 +644,7 @@ elf_symfile_read (struct objfile *objfil
+ /* If we are reinitializing, or if we have never loaded syms yet,
+ set table to empty. MAINLINE is cleared so that *_read_psymtab
+ functions do not all also re-initialize the psymbol table. */
+- if (mainline)
++ if (mainline == 1)
+ {
+ init_psymbol_list (objfile, 0);
+ mainline = 0;
+Index: gdb/Makefile.in
+===================================================================
+--- a/gdb/Makefile.in 2008-02-27 08:57:20.000000000 +0100
++++ b/gdb/Makefile.in 2008-02-27 08:57:31.000000000 +0100
+@@ -1914,7 +1914,7 @@ amd64-tdep.o: amd64-tdep.c $(defs_h) $(a
+ $(dummy_frame_h) $(frame_h) $(frame_base_h) $(frame_unwind_h) \
+ $(inferior_h) $(gdbcmd_h) $(gdbcore_h) $(objfiles_h) $(regcache_h) \
+ $(regset_h) $(symfile_h) $(gdb_assert_h) $(amd64_tdep_h) \
+- $(i387_tdep_h)
++ $(i387_tdep_h) $(exceptions_h)
+ annotate.o: annotate.c $(defs_h) $(annotate_h) $(value_h) $(target_h) \
+ $(gdbtypes_h) $(breakpoint_h)
+ arch-utils.o: arch-utils.c $(defs_h) $(arch_utils_h) $(buildsym_h) \
+Index: gdb/amd64-tdep.c
+===================================================================
+--- a/gdb/amd64-tdep.c 2008-02-27 08:57:19.000000000 +0100
++++ b/gdb/amd64-tdep.c 2008-02-27 08:57:31.000000000 +0100
+@@ -36,6 +36,7 @@
+ #include "symfile.h"
+ #include "dwarf2-frame.h"
+ #include "gdb_assert.h"
++#include "exceptions.h"
+
+ #include "amd64-tdep.h"
+ #include "i387-tdep.h"
+@@ -731,16 +732,28 @@ amd64_alloc_frame_cache (void)
+ Any function that doesn't start with this sequence will be assumed
+ to have no prologue and thus no valid frame pointer in %rbp. */
+
+-static CORE_ADDR
+-amd64_analyze_prologue (CORE_ADDR pc, CORE_ADDR current_pc,
+- struct amd64_frame_cache *cache)
++struct amd64_analyze_prologue_data
++ {
++ CORE_ADDR pc, current_pc;
++ struct amd64_frame_cache *cache;
++ CORE_ADDR retval;
++ };
++
++static int
++amd64_analyze_prologue_1 (void *data_pointer)
+ {
++ struct amd64_analyze_prologue_data *data = data_pointer;
++ CORE_ADDR pc = data->pc, current_pc = data->current_pc;
++ struct amd64_frame_cache *cache = data->cache;
+ static gdb_byte proto[3] = { 0x48, 0x89, 0xe5 }; /* movq %rsp, %rbp */
+ gdb_byte buf[3];
+ gdb_byte op;
+
+ if (current_pc <= pc)
+- return current_pc;
++ {
++ data->retval = current_pc;
++ return 1;
++ }
+
+ op = read_memory_unsigned_integer (pc, 1);
+
+@@ -753,18 +766,57 @@ amd64_analyze_prologue (CORE_ADDR pc, CO
+
+ /* If that's all, return now. */
+ if (current_pc <= pc + 1)
+- return current_pc;
++ {
++ data->retval = current_pc;
++ return 1;
++ }
+
+ /* Check for `movq %rsp, %rbp'. */
+ read_memory (pc + 1, buf, 3);
+ if (memcmp (buf, proto, 3) != 0)
+- return pc + 1;
++ {
++ data->retval = pc + 1;
++ return 1;
++ }
+
+ /* OK, we actually have a frame. */
+ cache->frameless_p = 0;
+- return pc + 4;
++ data->retval = pc + 4;
++ return 1;
+ }
+
++ data->retval = pc;
++ return 1;
++}
++
++/* Catch memory read errors and return just PC in such case.
++ It occurs very early on enable_break->new_symfile_objfile->
++ ->breakpoint_re_set->decode_line_1->decode_variable_1->
++ ->find_function_start_sal */
++
++static CORE_ADDR
++amd64_analyze_prologue (CORE_ADDR pc, CORE_ADDR current_pc,
++ struct amd64_frame_cache *cache)
++{
++ int status;
++ struct amd64_analyze_prologue_data data;
++ struct ui_file *saved_gdb_stderr;
++
++ /* Suppress error messages. */
++ saved_gdb_stderr = gdb_stderr;
++ gdb_stderr = ui_file_new ();
++
++ data.pc = pc;
++ data.current_pc = current_pc;
++ data.cache = cache;
++ status = catch_errors (amd64_analyze_prologue_1, &data, "", RETURN_MASK_ALL);
++
++ /* Stop suppressing error messages. */
++ ui_file_delete (gdb_stderr);
++ gdb_stderr = saved_gdb_stderr;
++
++ if (status)
++ return data.retval;
+ return pc;
+ }
+