summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Frysinger <vapier@gentoo.org>2008-06-21 06:44:08 +0000
committerMike Frysinger <vapier@gentoo.org>2008-06-21 06:44:08 +0000
commit74f4ceab859fcf8952c1db7e7ba80c72331dfe77 (patch)
tree6a4907b117eae0063eb3e342fe6c71a5aee07364 /src/patchsets/gdb
parentadd a patch to build against latest ffmpeg (diff)
downloadgentoo-74f4ceab859fcf8952c1db7e7ba80c72331dfe77.tar.gz
gentoo-74f4ceab859fcf8952c1db7e7ba80c72331dfe77.tar.bz2
gentoo-74f4ceab859fcf8952c1db7e7ba80c72331dfe77.zip
add pie patches #223533
Diffstat (limited to 'src/patchsets/gdb')
-rw-r--r--src/patchsets/gdb/6.8/50_all_gdb-pie-1.patch1332
-rw-r--r--src/patchsets/gdb/6.8/50_all_gdb-pie-2.patch2124
-rw-r--r--src/patchsets/gdb/6.8/README.history4
3 files changed, 3460 insertions, 0 deletions
diff --git a/src/patchsets/gdb/6.8/50_all_gdb-pie-1.patch b/src/patchsets/gdb/6.8/50_all_gdb-pie-1.patch
new file mode 100644
index 0000000000..cb901ef440
--- /dev/null
+++ b/src/patchsets/gdb/6.8/50_all_gdb-pie-1.patch
@@ -0,0 +1,1332 @@
+http://bugs.gentoo.org/223533
+
+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
+===================================================================
+--- gdb/dwarf2read.c 2008-02-27 08:57:20.000000000 +0100
++++ 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
+===================================================================
+--- gdb/auxv.c 2008-01-16 17:27:37.000000000 +0100
++++ 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
+===================================================================
+--- gdb/auxv.h 2008-01-01 23:53:09.000000000 +0100
++++ 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
+===================================================================
+--- gdb/breakpoint.h 2008-02-01 17:24:46.000000000 +0100
++++ 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
+===================================================================
+--- gdb/symfile-mem.c 2008-01-01 23:53:13.000000000 +0100
++++ 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
+===================================================================
+--- gdb/infrun.c 2008-02-27 08:57:20.000000000 +0100
++++ 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
+===================================================================
+--- gdb/objfiles.c 2008-01-01 23:53:12.000000000 +0100
++++ 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
+===================================================================
+--- gdb/solib-svr4.c 2008-02-27 08:57:19.000000000 +0100
++++ 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
+===================================================================
+--- gdb/varobj.c 2008-02-04 08:49:04.000000000 +0100
++++ 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
+===================================================================
+--- gdb/solist.h 2008-01-07 16:19:58.000000000 +0100
++++ 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
+===================================================================
+--- gdb/varobj.h 2008-01-30 08:17:31.000000000 +0100
++++ 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
+===================================================================
+--- gdb/symfile.c 2008-01-29 23:47:20.000000000 +0100
++++ 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
+===================================================================
+--- gdb/breakpoint.c 2008-02-27 08:57:20.000000000 +0100
++++ 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
+===================================================================
+--- gdb/solib.c 2008-01-07 16:19:58.000000000 +0100
++++ 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
+===================================================================
+--- gdb/elfread.c 2008-01-01 23:53:09.000000000 +0100
++++ 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
+===================================================================
+--- gdb/Makefile.in 2008-02-27 08:57:20.000000000 +0100
++++ 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
+===================================================================
+--- gdb/amd64-tdep.c 2008-02-27 08:57:19.000000000 +0100
++++ 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;
+ }
+
diff --git a/src/patchsets/gdb/6.8/50_all_gdb-pie-2.patch b/src/patchsets/gdb/6.8/50_all_gdb-pie-2.patch
new file mode 100644
index 0000000000..0becc5874d
--- /dev/null
+++ b/src/patchsets/gdb/6.8/50_all_gdb-pie-2.patch
@@ -0,0 +1,2124 @@
+http://bugs.gentoo.org/223533
+
+Index: gdb-6.8/gdb/testsuite/configure
+===================================================================
+--- gdb-6.8.orig/gdb/testsuite/configure 2007-12-29 06:01:30.000000000 -0800
++++ gdb-6.8/gdb/testsuite/configure 2008-03-30 09:00:52.000000000 -0700
+@@ -3104,7 +3104,7 @@
+
+
+
+- ac_config_files="$ac_config_files Makefile gdb.ada/Makefile gdb.arch/Makefile gdb.asm/Makefile gdb.base/Makefile gdb.cp/Makefile gdb.disasm/Makefile gdb.dwarf2/Makefile gdb.fortran/Makefile gdb.server/Makefile gdb.java/Makefile gdb.mi/Makefile gdb.modula2/Makefile gdb.objc/Makefile gdb.opt/Makefile gdb.pascal/Makefile gdb.threads/Makefile gdb.trace/Makefile gdb.xml/Makefile"
++ ac_config_files="$ac_config_files Makefile gdb.ada/Makefile gdb.arch/Makefile gdb.asm/Makefile gdb.base/Makefile gdb.cp/Makefile gdb.disasm/Makefile gdb.dwarf2/Makefile gdb.fortran/Makefile gdb.server/Makefile gdb.pie/Makefile gdb.java/Makefile gdb.mi/Makefile gdb.modula2/Makefile gdb.objc/Makefile gdb.opt/Makefile gdb.pascal/Makefile gdb.threads/Makefile gdb.trace/Makefile gdb.xml/Makefile"
+ cat >confcache <<\_ACEOF
+ # This file is a shell script that caches the results of configure
+ # tests run on this system so they can be shared between configure
+@@ -3665,6 +3665,7 @@
+ "gdb.dwarf2/Makefile" ) CONFIG_FILES="$CONFIG_FILES gdb.dwarf2/Makefile" ;;
+ "gdb.fortran/Makefile" ) CONFIG_FILES="$CONFIG_FILES gdb.fortran/Makefile" ;;
+ "gdb.server/Makefile" ) CONFIG_FILES="$CONFIG_FILES gdb.server/Makefile" ;;
++ "gdb.pie/Makefile" ) CONFIG_FILES="$CONFIG_FILES gdb.pie/Makefile" ;;
+ "gdb.java/Makefile" ) CONFIG_FILES="$CONFIG_FILES gdb.java/Makefile" ;;
+ "gdb.mi/Makefile" ) CONFIG_FILES="$CONFIG_FILES gdb.mi/Makefile" ;;
+ "gdb.modula2/Makefile" ) CONFIG_FILES="$CONFIG_FILES gdb.modula2/Makefile" ;;
+Index: gdb-6.8/gdb/testsuite/configure.ac
+===================================================================
+--- gdb-6.8.orig/gdb/testsuite/configure.ac 2007-10-25 13:30:26.000000000 -0700
++++ gdb-6.8/gdb/testsuite/configure.ac 2008-03-30 09:00:22.000000000 -0700
+@@ -114,7 +114,7 @@
+ gdb.ada/Makefile \
+ gdb.arch/Makefile gdb.asm/Makefile gdb.base/Makefile \
+ gdb.cp/Makefile gdb.disasm/Makefile gdb.dwarf2/Makefile \
+- gdb.fortran/Makefile gdb.server/Makefile \
++ gdb.fortran/Makefile gdb.server/Makefile gdb.pie/Makefile \
+ gdb.java/Makefile gdb.mi/Makefile gdb.modula2/Makefile \
+ gdb.objc/Makefile gdb.opt/Makefile gdb.pascal/Makefile \
+ gdb.threads/Makefile gdb.trace/Makefile gdb.xml/Makefile])
+Index: gdb-6.8/gdb/testsuite/gdb.pie/Makefile.in
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ gdb-6.8/gdb/testsuite/gdb.pie/Makefile.in 2008-03-30 08:59:12.000000000 -0700
+@@ -0,0 +1,19 @@
++VPATH = @srcdir@
++srcdir = @srcdir@
++
++EXECUTABLES =
++MISCELLANEOUS = arch.inc
++
++all info install-info dvi install uninstall installcheck check:
++ @echo "Nothing to be done for $@..."
++
++clean mostlyclean:
++ -rm -f *~ *.o a.out *.x *.ci *.tmp
++ -rm -f core core.coremaker coremaker.core corefile $(EXECUTABLES)
++ -rm -f $(MISCELLANEOUS)
++
++distclean maintainer-clean realclean: clean
++ -rm -f *~ core
++ -rm -f Makefile config.status config.log
++ -rm -f *-init.exp
++ -rm -fr *.log summary detail *.plog *.sum *.psum site.*
+Index: gdb-6.8/gdb/testsuite/gdb.pie/attach.c
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ gdb-6.8/gdb/testsuite/gdb.pie/attach.c 2008-03-30 08:59:12.000000000 -0700
+@@ -0,0 +1,20 @@
++/* This program is intended to be started outside of gdb, and then
++ attached to by gdb. Thus, it simply spins in a loop. The loop
++ is exited when & if the variable 'should_exit' is non-zero. (It
++ is initialized to zero in this program, so the loop will never
++ exit unless/until gdb sets the variable to non-zero.)
++ */
++#include <stdio.h>
++
++int should_exit = 0;
++
++int main ()
++{
++ int local_i = 0;
++
++ while (! should_exit)
++ {
++ local_i++;
++ }
++ return 0;
++}
+Index: gdb-6.8/gdb/testsuite/gdb.pie/attach.exp
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ gdb-6.8/gdb/testsuite/gdb.pie/attach.exp 2008-03-30 08:59:12.000000000 -0700
+@@ -0,0 +1,432 @@
++# Copyright 1997, 1999, 2002 Free Software Foundation, Inc.
++
++# This program is free software; you can redistribute it and/or modify
++# it under the terms of the GNU General Public License as published by
++# the Free Software Foundation; either version 2 of the License, or
++# (at your option) any later version.
++#
++# This program is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++# GNU General Public License for more details.
++#
++# You should have received a copy of the GNU General Public License
++# along with this program; if not, write to the Free Software
++# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
++
++# Please email any bugs, comments, and/or additions to this file to:
++# bug-gdb@prep.ai.mit.edu
++
++if $tracelevel then {
++ strace $tracelevel
++ }
++
++set prms_id 0
++set bug_id 0
++
++# On HP-UX 11.0, this test is causing a process running the program
++# "attach" to be left around spinning. Until we figure out why, I am
++# commenting out the test to avoid polluting tiamat (our 11.0 nightly
++# test machine) with these processes. RT
++#
++# Setting the magic bit in the target app should work. I added a
++# "kill", and also a test for the R3 register warning. JB
++if { [istarget "hppa*-*-hpux*"] } {
++ return 0
++}
++
++# are we on a target board
++if [is_remote target] then {
++ return 0
++}
++
++set testfile "attach"
++set srcfile ${testfile}.c
++set srcfile2 ${testfile}2.c
++set binfile ${objdir}/${subdir}/${testfile}
++set binfile2 ${objdir}/${subdir}/${testfile}2
++set escapedbinfile [string_to_regexp ${objdir}/${subdir}/${testfile}]
++set cleanupfile ${objdir}/${subdir}/${testfile}.awk
++
++#execute_anywhere "rm -f ${binfile} ${binfile2}"
++remote_exec build "rm -f ${binfile} ${binfile2}"
++# For debugging this test
++#
++#log_user 1
++
++# Clean out any old files from past runs.
++#
++remote_exec build "${cleanupfile}"
++
++# build the first test case
++#
++if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug "additional_flags= -fpie -pie"}] != "" } {
++ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
++}
++
++# Build the in-system-call test
++
++if { [gdb_compile "${srcdir}/${subdir}/${srcfile2}" "${binfile2}" executable {debug "additional_flags= -fpie -pie"}] != "" } {
++ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
++}
++
++if [get_compiler_info ${binfile}] {
++ return -1
++}
++
++proc do_attach_tests {} {
++ global gdb_prompt
++ global binfile
++ global escapedbinfile
++ global srcfile
++ global testfile
++ global objdir
++ global subdir
++ global timeout
++
++ # Start the program running and then wait for a bit, to be sure
++ # that it can be attached to.
++ #
++ set testpid [eval exec $binfile &]
++ exec sleep 2
++
++ # Verify that we cannot attach to nonsense.
++ #
++ send_gdb "attach abc\n"
++ gdb_expect {
++ -re ".*Illegal process-id: abc.*$gdb_prompt $"\
++ {pass "attach to nonsense is prohibited"}
++ -re "Attaching to.*, process .*couldn't open /proc file.*$gdb_prompt $"\
++ {
++ # Response expected from /proc-based systems.
++ pass "attach to nonsense is prohibited"
++ }
++ -re "Attaching to.*$gdb_prompt $"\
++ {fail "attach to nonsense is prohibited (bogus pid allowed)"}
++ -re "$gdb_prompt $" {fail "attach to nonsense is prohibited"}
++ timeout {fail "(timeout) attach to nonsense is prohibited"}
++ }
++
++ # Verify that we cannot attach to what appears to be a valid
++ # process ID, but is a process that doesn't exist. Traditionally,
++ # most systems didn't have a process with ID 0, so we take that as
++ # the default. However, there are a few exceptions.
++ #
++ set boguspid 0
++ if { [istarget "*-*-*bsd*"] } {
++ # In FreeBSD 5.0, PID 0 is used for "swapper". Use -1 instead
++ # (which should have the desired effect on any version of
++ # FreeBSD, and probably other *BSD's too).
++ set boguspid -1
++ }
++ send_gdb "attach $boguspid\n"
++ gdb_expect {
++ -re "Attaching to.*, process $boguspid.*No such process.*$gdb_prompt $"\
++ {
++ # Response expected on ptrace-based systems (i.e. HP-UX 10.20).
++ pass "attach to nonexistent process is prohibited"
++ }
++ -re "Attaching to.*, process $boguspid failed.*Hint.*$gdb_prompt $"\
++ {
++ # Response expected on ttrace-based systems (i.e. HP-UX 11.0).
++ pass "attach to nonexistent process is prohibited"
++ }
++ -re "Attaching to.*, process $boguspid.*denied.*$gdb_prompt $"\
++ {pass "attach to nonexistent process is prohibited"}
++ -re "Attaching to.*, process $boguspid.*not permitted.*$gdb_prompt $"\
++ {pass "attach to nonexistent process is prohibited"}
++ -re "Attaching to.*, process .*couldn't open /proc file.*$gdb_prompt $"\
++ {
++ # Response expected from /proc-based systems.
++ pass "attach to nonexistent process is prohibited"
++ }
++ -re "$gdb_prompt $" {fail "attach to nonexistent process is prohibited"}
++ timeout {
++ fail "(timeout) attach to nonexistent process is prohibited"
++ }
++ }
++
++ # Verify that we can attach to the process by first giving its
++ # executable name via the file command, and using attach with
++ # the process ID.
++ #
++ # (Actually, the test system appears to do this automatically
++ # for us. So, we must also be prepared to be asked if we want
++ # to discard an existing set of symbols.)
++ #
++ send_gdb "file $binfile\n"
++ gdb_expect {
++ -re "Load new symbol table from.*y or n.*$" {
++ send_gdb "y\n"
++ gdb_expect {
++ -re "Reading symbols from $escapedbinfile\.\.\.*done.*$gdb_prompt $"\
++ {pass "(re)set file, before attach1"}
++ -re "$gdb_prompt $" {fail "(re)set file, before attach1"}
++ timeout {fail "(timeout) (re)set file, before attach1"}
++ }
++ }
++ -re "Reading symbols from $escapedbinfile\.\.\.*done.*$gdb_prompt $"\
++ {pass "set file, before attach1"}
++ -re "$gdb_prompt $" {fail "set file, before attach1"}
++ timeout {fail "(timeout) set file, before attach1"}
++ }
++
++ send_gdb "attach $testpid\n"
++ gdb_expect {
++ -re "Attaching to program.*`?$escapedbinfile'?, process $testpid.*main.*at .*$srcfile:.*$gdb_prompt $"\
++ {pass "attach1, after setting file"}
++ -re "$gdb_prompt $" {fail "attach1, after setting file"}
++ timeout {fail "(timeout) attach1, after setting file"}
++ }
++
++ # Verify that we can "see" the variable "should_exit" in the
++ # program, and that it is zero.
++ #
++ send_gdb "print should_exit\n"
++ gdb_expect {
++ -re ".* = 0.*$gdb_prompt $"\
++ {pass "after attach1, print should_exit"}
++ -re "$gdb_prompt $" {fail "after attach1, print should_exit"}
++ timeout {fail "(timeout) after attach1, print should_exit"}
++ }
++
++ # Detach the process.
++ #
++ send_gdb "detach\n"
++ gdb_expect {
++ -re "Detaching from program: .*$escapedbinfile.*$gdb_prompt $"\
++ {pass "attach1 detach"}
++ -re "$gdb_prompt $" {fail "attach1 detach"}
++ timeout {fail "(timeout) attach1 detach"}
++ }
++
++ # Wait a bit for gdb to finish detaching
++ #
++ exec sleep 5
++
++ # Purge the symbols from gdb's brain. (We want to be certain
++ # the next attach, which won't be preceded by a "file" command,
++ # is really getting the executable file without our help.)
++ #
++ set old_timeout $timeout
++ set timeout 15
++ send_gdb "file\n"
++ gdb_expect {
++ -re ".*gdb internal error.*$" {
++ fail "Internal error, prob. Memory corruption"
++ }
++ -re "No executable file now.*Discard symbol table.*y or n.*$" {
++ send_gdb "y\n"
++ gdb_expect {
++ -re "No symbol file now.*$gdb_prompt $"\
++ {pass "attach1, purging symbols after detach"}
++ -re "$gdb_prompt $" {fail "attach1, purging symbols after detach"}
++ timeout {fail "(timeout) attach1, purging symbols after detach"}
++ }
++ }
++ -re "$gdb_prompt $" {fail "attach1, purging file after detach"}
++ timeout {
++ fail "(timeout) attach1, purging file after detach"
++ }
++ }
++ set timeout $old_timeout
++
++ # Verify that we can attach to the process just by giving the
++ # process ID.
++ #
++ send_gdb "attach $testpid\n"
++ gdb_expect {
++ -re "Attaching to process $testpid.*Reading symbols from $escapedbinfile.*main.*at .*$gdb_prompt $"\
++ {pass "attach2"}
++ -re "$gdb_prompt $" {fail "attach2"}
++ timeout {fail "(timeout) attach2"}
++ }
++
++ # Verify that we can modify the variable "should_exit" in the
++ # program.
++ #
++ send_gdb "set should_exit=1\n"
++ gdb_expect {
++ -re "$gdb_prompt $" {pass "after attach2, set should_exit"}
++ timeout {fail "(timeout) after attach2, set should_exit"}
++ }
++
++ # Verify that the modification really happened.
++ #
++ send_gdb "tbreak 19\n"
++ gdb_expect {
++ -re "Breakpoint .*at.*$srcfile, line 19.*$gdb_prompt $"\
++ {pass "after attach2, set tbreak postloop"}
++ -re "$gdb_prompt $" {fail "after attach2, set tbreak postloop"}
++ timeout {fail "(timeout) after attach2, set tbreak postloop"}
++ }
++ send_gdb "continue\n"
++ gdb_expect {
++ -re "main.*at.*$srcfile:19.*$gdb_prompt $"\
++ {pass "after attach2, reach tbreak postloop"}
++ -re "$gdb_prompt $" {fail "after attach2, reach tbreak postloop"}
++ timeout {fail "(timeout) after attach2, reach tbreak postloop"}
++ }
++
++ # Allow the test process to exit, to cleanup after ourselves.
++ #
++ send_gdb "continue\n"
++ gdb_expect {
++ -re "Program exited normally.*$gdb_prompt $"\
++ {pass "after attach2, exit"}
++ -re "$gdb_prompt $" {fail "after attach2, exit"}
++ timeout {fail "(timeout) after attach2, exit"}
++ }
++
++ # Make sure we don't leave a process around to confuse
++ # the next test run (and prevent the compile by keeping
++ # the text file busy), in case the "set should_exit" didn't
++ # work.
++ #
++ remote_exec build "kill -9 ${testpid}"
++ # Start the program running and then wait for a bit, to be sure
++ # that it can be attached to.
++ #
++ set testpid [eval exec $binfile &]
++ exec sleep 2
++
++ # Verify that we can attach to the process, and find its a.out
++ # when we're cd'd to some directory that doesn't contain the
++ # a.out. (We use the source path set by the "dir" command.)
++ #
++ send_gdb "dir ${objdir}/${subdir}\n"
++ gdb_expect {
++ -re ".*Source directories searched: .*$gdb_prompt $"\
++ {pass "set source path"}
++ -re "$gdb_prompt $" {fail "set source path"}
++ timeout {fail "(timeout) set source path"}
++ }
++
++ send_gdb "cd /tmp\n"
++ gdb_expect {
++ -re ".*Working directory /tmp.*$gdb_prompt $"\
++ {pass "cd away from process' a.out"}
++ -re "$gdb_prompt $" {fail "cd away from process' a.out"}
++ timeout {fail "(timeout) cd away from process' a.out"}
++ }
++
++ # Explicitly flush out any knowledge of the previous attachment.
++ send_gdb "symbol\n"
++ gdb_expect {
++ -re ".*Discard symbol table from.*y or n. $"\
++ {send_gdb "y\n"
++ gdb_expect {
++ -re ".*No symbol file now.*$gdb_prompt $"\
++ {pass "before attach3, flush symbols"}
++ -re "$gdb_prompt $" {fail "before attach3, flush symbols"}
++ timeout {fail "(timeout) before attach3, flush symbols"}
++ }
++ }
++ -re ".*No symbol file now.*$gdb_prompt $"\
++ {pass "before attach3, flush symbols"}
++ -re "$gdb_prompt $" {fail "before attach3, flush symbols"}
++ timeout {fail "(timeout) before attach3, flush symbols"}
++ }
++ send_gdb "exec\n"
++ gdb_expect {
++ -re ".*No executable file now.*$gdb_prompt $"\
++ {pass "before attach3, flush exec"}
++ -re "$gdb_prompt $" {fail "before attach3, flush exec"}
++ timeout {fail "(timeout) before attach3, flush exec"}
++ }
++
++ send_gdb "attach $testpid\n"
++ gdb_expect {
++ -re "Attaching to process $testpid.*Reading symbols from $escapedbinfile.*main.*at .*$gdb_prompt $"\
++ {pass "attach when process' a.out not in cwd"}
++ -re "$gdb_prompt $" {fail "attach when process' a.out not in cwd"}
++ timeout {fail "(timeout) attach when process' a.out not in cwd"}
++ }
++
++ send_gdb "kill\n"
++ gdb_expect {
++ -re ".*Kill the program being debugged.*y or n. $"\
++ {send_gdb "y\n"
++ gdb_expect {
++ -re "$gdb_prompt $" {pass "after attach3, exit"}
++ timeout {fail "(timeout) after attach3, exit"}
++ }
++ }
++ -re "$gdb_prompt $" {fail "after attach3, exit"}
++ timeout {fail "(timeout) after attach3, exit"}
++ }
++
++ # Another "don't leave a process around"
++ remote_exec build "kill -9 ${testpid}"
++}
++
++proc do_call_attach_tests {} {
++ global gdb_prompt
++ global binfile2
++
++ # Start the program running and then wait for a bit, to be sure
++ # that it can be attached to.
++ #
++ set testpid [eval exec $binfile2 &]
++ exec sleep 2
++
++ # Attach
++ #
++ gdb_test "file $binfile2" ".*" "force switch to gdb64, if necessary"
++ send_gdb "attach $testpid\n"
++ gdb_expect {
++ -re ".*warning: reading register.*I.*O error.*$gdb_prompt $" {
++ fail "attach call, read register 3 error"
++ }
++ -re "Attaching to.*process $testpid.*libc.*$gdb_prompt $" {
++ pass "attach call"
++ }
++ -re "$gdb_prompt $" {fail "attach call"}
++ timeout {fail "(timeout) attach call"}
++ }
++
++ # See if other registers are problems
++ #
++ send_gdb "i r r3\n"
++ gdb_expect {
++ -re ".*warning: reading register.*$gdb_prompt $" {
++ pass "CHFts23490: known bug"
++ }
++ -re ".*r3.*$gdb_prompt $" {
++ pass "Bug fixed, Yayyy!"
++ }
++ timeout { fail "timeout on info reg" }
++ }
++
++ # Get rid of the process
++ #
++ gdb_test "p should_exit = 1" ".*"
++ gdb_test "c" ".*Program exited normally.*"
++
++ # Be paranoid
++ #
++ remote_exec build "kill -9 ${testpid}"
++
++}
++
++
++# Start with a fresh gdb
++#
++gdb_exit
++gdb_start
++gdb_reinitialize_dir $srcdir/$subdir
++gdb_load ${binfile}
++
++# This is a test of gdb's ability to attach to a running process.
++#
++do_attach_tests
++
++# Test attaching when the target is inside a system call
++#
++gdb_exit
++gdb_start
++
++gdb_reinitialize_dir $srcdir/$subdir
++do_call_attach_tests
++
++return 0
+Index: gdb-6.8/gdb/testsuite/gdb.pie/attach2.c
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ gdb-6.8/gdb/testsuite/gdb.pie/attach2.c 2008-03-30 08:59:12.000000000 -0700
+@@ -0,0 +1,24 @@
++/* This program is intended to be started outside of gdb, and then
++ attached to by gdb. Thus, it simply spins in a loop. The loop
++ is exited when & if the variable 'should_exit' is non-zero. (It
++ is initialized to zero in this program, so the loop will never
++ exit unless/until gdb sets the variable to non-zero.)
++ */
++#include <stdio.h>
++#include <stdlib.h>
++#include <unistd.h>
++
++int should_exit = 0;
++
++int main ()
++{
++ int local_i = 0;
++
++ sleep( 10 ); /* System call causes register fetch to fail */
++ /* This is a known HPUX "feature" */
++ while (! should_exit)
++ {
++ local_i++;
++ }
++ return (0);
++}
+Index: gdb-6.8/gdb/testsuite/gdb.pie/break.c
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ gdb-6.8/gdb/testsuite/gdb.pie/break.c 2008-03-30 08:59:12.000000000 -0700
+@@ -0,0 +1,146 @@
++/* This testcase is part of GDB, the GNU debugger.
++
++ Copyright 1992, 1993, 1994, 1995, 1999, 2002, 2003 Free Software
++ Foundation, Inc.
++
++ This program is free software; you can redistribute it and/or modify
++ it under the terms of the GNU General Public License as published by
++ the Free Software Foundation; either version 2 of the License, or
++ (at your option) any later version.
++
++ This program is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ GNU General Public License for more details.
++
++ You should have received a copy of the GNU General Public License
++ along with this program; if not, write to the Free Software
++ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++
++ Please email any bugs, comments, and/or additions to this file to:
++ bug-gdb@prep.ai.mit.edu */
++
++#ifdef vxworks
++
++# include <stdio.h>
++
++/* VxWorks does not supply atoi. */
++static int
++atoi (z)
++ char *z;
++{
++ int i = 0;
++
++ while (*z >= '0' && *z <= '9')
++ i = i * 10 + (*z++ - '0');
++ return i;
++}
++
++/* I don't know of any way to pass an array to VxWorks. This function
++ can be called directly from gdb. */
++
++vxmain (arg)
++char *arg;
++{
++ char *argv[2];
++
++ argv[0] = "";
++ argv[1] = arg;
++ main (2, argv, (char **) 0);
++}
++
++#else /* ! vxworks */
++# include <stdio.h>
++# include <stdlib.h>
++#endif /* ! vxworks */
++
++#ifdef PROTOTYPES
++extern int marker1 (void);
++extern int marker2 (int a);
++extern void marker3 (char *a, char *b);
++extern void marker4 (long d);
++#else
++extern int marker1 ();
++extern int marker2 ();
++extern void marker3 ();
++extern void marker4 ();
++#endif
++
++/*
++ * This simple classical example of recursion is useful for
++ * testing stack backtraces and such.
++ */
++
++#ifdef PROTOTYPES
++int factorial(int);
++
++int
++main (int argc, char **argv, char **envp)
++#else
++int
++main (argc, argv, envp)
++int argc;
++char *argv[], **envp;
++#endif
++{
++#ifdef usestubs
++ set_debug_traps(); /* set breakpoint 5 here */
++ breakpoint();
++#endif
++ if (argc == 12345) { /* an unlikely value < 2^16, in case uninited */ /* set breakpoint 6 here */
++ fprintf (stderr, "usage: factorial <number>\n");
++ return 1;
++ }
++ printf ("%d\n", factorial (atoi ("6"))); /* set breakpoint 1 here */
++ /* set breakpoint 12 here */
++ marker1 (); /* set breakpoint 11 here */
++ marker2 (43); /* set breakpoint 20 here */
++ marker3 ("stack", "trace"); /* set breakpoint 21 here */
++ marker4 (177601976L);
++ argc = (argc == 12345); /* This is silly, but we can step off of it */ /* set breakpoint 2 here */
++ return argc; /* set breakpoint 10 here */
++}
++
++#ifdef PROTOTYPES
++int factorial (int value)
++#else
++int factorial (value)
++int value;
++#endif
++{
++ if (value > 1) { /* set breakpoint 7 here */
++ value *= factorial (value - 1);
++ }
++ return (value); /* set breakpoint 19 here */
++}
++
++#ifdef PROTOTYPES
++int multi_line_if_conditional (int a, int b, int c)
++#else
++int multi_line_if_conditional (a, b, c)
++ int a, b, c;
++#endif
++{
++ if (a /* set breakpoint 3 here */
++ && b
++ && c)
++ return 0;
++ else
++ return 1;
++}
++
++#ifdef PROTOTYPES
++int multi_line_while_conditional (int a, int b, int c)
++#else
++int multi_line_while_conditional (a, b, c)
++ int a, b, c;
++#endif
++{
++ while (a /* set breakpoint 4 here */
++ && b
++ && c)
++ {
++ a--, b--, c--;
++ }
++ return 0;
++}
+Index: gdb-6.8/gdb/testsuite/gdb.pie/break.exp
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ gdb-6.8/gdb/testsuite/gdb.pie/break.exp 2008-03-30 08:59:12.000000000 -0700
+@@ -0,0 +1,973 @@
++# Copyright 1988, 1990, 1991, 1992, 1994, 1995, 1996, 1997, 1998, 1999,
++# 2000, 2002, 2003, 2004
++# Free Software Foundation, Inc.
++
++# This program is free software; you can redistribute it and/or modify
++# it under the terms of the GNU General Public License as published by
++# the Free Software Foundation; either version 2 of the License, or
++# (at your option) any later version.
++#
++# This program is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++# GNU General Public License for more details.
++#
++# You should have received a copy of the GNU General Public License
++# along with this program; if not, write to the Free Software
++# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++
++# Please email any bugs, comments, and/or additions to this file to:
++# bug-gdb@prep.ai.mit.edu
++
++# This file was written by Rob Savoye. (rob@cygnus.com)
++
++# Test the same stuff but with PIE executables
++
++if $tracelevel then {
++ strace $tracelevel
++}
++
++
++#
++# test running programs
++#
++set prms_id 0
++set bug_id 0
++
++set testfile "break"
++set srcfile ${testfile}.c
++set srcfile1 ${testfile}1.c
++set binfile ${objdir}/${subdir}/${testfile}
++
++if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}0.o" object {debug "additional_flags=-w -fpie -pie"}] != "" } {
++ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
++}
++
++if { [gdb_compile "${srcdir}/${subdir}/${srcfile1}" "${binfile}1.o" object {debug "additional_flags=-w -fpie -pie"}] != "" } {
++ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
++}
++
++if { [gdb_compile "${binfile}0.o ${binfile}1.o" "${binfile}" executable {debug "additional_flags=-w -fpie -pie"}] != "" } {
++ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
++}
++
++if [get_compiler_info ${binfile}] {
++ return -1
++}
++
++gdb_exit
++gdb_start
++gdb_reinitialize_dir $srcdir/$subdir
++gdb_load ${binfile}
++
++if [target_info exists gdb_stub] {
++ gdb_step_for_stub;
++}
++#
++# test simple breakpoint setting commands
++#
++
++# Test deleting all breakpoints when there are none installed,
++# GDB should not prompt for confirmation.
++# Note that gdb-init.exp provides a "delete_breakpoints" proc
++# for general use elsewhere.
++
++send_gdb "delete breakpoints\n"
++gdb_expect {
++ -re "Delete all breakpoints.*$" {
++ send_gdb "y\n"
++ gdb_expect {
++ -re "$gdb_prompt $" {
++ fail "Delete all breakpoints when none (unexpected prompt)"
++ }
++ timeout { fail "Delete all breakpoints when none (timeout after unexpected prompt)" }
++ }
++ }
++ -re ".*$gdb_prompt $" { pass "Delete all breakpoints when none" }
++ timeout { fail "Delete all breakpoints when none (timeout)" }
++}
++
++#
++# test break at function
++#
++gdb_test "break main" \
++ "Breakpoint.*at.* file .*$srcfile, line.*" \
++ "breakpoint function"
++
++#
++# test break at quoted function
++#
++gdb_test "break \"marker2\"" \
++ "Breakpoint.*at.* file .*$srcfile1, line.*" \
++ "breakpoint quoted function"
++
++#
++# test break at function in file
++#
++gdb_test "break $srcfile:factorial" \
++ "Breakpoint.*at.* file .*$srcfile, line.*" \
++ "breakpoint function in file"
++
++set bp_location1 [gdb_get_line_number "set breakpoint 1 here"]
++
++#
++# test break at line number
++#
++# Note that the default source file is the last one whose source text
++# was printed. For native debugging, before we've executed the
++# program, this is the file containing main, but for remote debugging,
++# it's wherever the processor was stopped when we connected to the
++# board. So, to be sure, we do a list command.
++#
++gdb_test "list main" \
++ ".*main \\(argc, argv, envp\\).*" \
++ "use `list' to establish default source file"
++gdb_test "break $bp_location1" \
++ "Breakpoint.*at.* file .*$srcfile, line $bp_location1\\." \
++ "breakpoint line number"
++
++#
++# test duplicate breakpoint
++#
++gdb_test "break $bp_location1" \
++ "Note: breakpoint \[0-9\]+ also set at pc.*Breakpoint \[0-9\]+ at.* file .*$srcfile, line $bp_location1\\." \
++ "breakpoint duplicate"
++
++set bp_location2 [gdb_get_line_number "set breakpoint 2 here"]
++
++#
++# test break at line number in file
++#
++gdb_test "break $srcfile:$bp_location2" \
++ "Breakpoint.*at.* file .*$srcfile, line $bp_location2\\." \
++ "breakpoint line number in file"
++
++set bp_location3 [gdb_get_line_number "set breakpoint 3 here"]
++set bp_location4 [gdb_get_line_number "set breakpoint 4 here"]
++
++#
++# Test putting a break at the start of a multi-line if conditional.
++# Verify the breakpoint was put at the start of the conditional.
++#
++gdb_test "break multi_line_if_conditional" \
++ "Breakpoint.*at.* file .*$srcfile, line $bp_location3\\." \
++ "breakpoint at start of multi line if conditional"
++
++gdb_test "break multi_line_while_conditional" \
++ "Breakpoint.*at.* file .*$srcfile, line $bp_location4\\." \
++ "breakpoint at start of multi line while conditional"
++
++set bp_location5 [gdb_get_line_number "set breakpoint 5 here"]
++set bp_location6 [gdb_get_line_number "set breakpoint 6 here"]
++
++#
++# check to see what breakpoints are set
++#
++if [target_info exists gdb_stub] {
++ set main_line $bp_location5
++} else {
++ set main_line $bp_location6
++}
++
++if {$hp_aCC_compiler} {
++ set proto "\\(int\\)"
++} else {
++ set proto ""
++}
++
++set bp_location7 [gdb_get_line_number "set breakpoint 7 here"]
++set bp_location8 [gdb_get_line_number "set breakpoint 8 here" $srcfile1]
++set bp_location9 [gdb_get_line_number "set breakpoint 9 here" $srcfile1]
++
++gdb_test "info break" \
++ "Num Type\[ \]+Disp Enb Address\[ \]+What.*
++\[0-9\]+\[\t \]+breakpoint keep y.* in main at .*$srcfile:$main_line.*
++\[0-9\]+\[\t \]+breakpoint keep y.* in marker2 at .*$srcfile1:($bp_location8|$bp_location9).*
++\[0-9\]+\[\t \]+breakpoint keep y.* in factorial$proto at .*$srcfile:$bp_location7.*
++\[0-9\]+\[\t \]+breakpoint keep y.* in main at .*$srcfile:$bp_location1.*
++\[0-9\]+\[\t \]+breakpoint keep y.* in main at .*$srcfile:$bp_location1.*
++\[0-9\]+\[\t \]+breakpoint keep y.* in main at .*$srcfile:$bp_location2.*
++\[0-9\]+\[\t \]+breakpoint keep y.* in multi_line_if_conditional at .*$srcfile:$bp_location3.*
++\[0-9\]+\[\t \]+breakpoint keep y.* in multi_line_while_conditional at .*$srcfile:$bp_location4" \
++ "breakpoint info"
++
++# FIXME: The rest of this test doesn't work with anything that can't
++# handle arguments.
++# Huh? There doesn't *appear* to be anything that passes arguments
++# below.
++if [istarget "mips-idt-*"] then {
++ return
++}
++
++#
++# run until the breakpoint at main is hit. For non-stubs-using targets.
++#
++if ![target_info exists use_gdb_stub] {
++ if [istarget "*-*-vxworks*"] then {
++ send_gdb "run vxmain \"2\"\n"
++ set timeout 120
++ verbose "Timeout is now $timeout seconds" 2
++ } else {
++ send_gdb "run\n"
++ }
++ gdb_expect {
++ -re "The program .* has been started already.*y or n. $" {
++ send_gdb "y\n"
++ exp_continue
++ }
++ -re "Starting program.*Breakpoint \[0-9\]+,.*main .*argc.*argv.* at .*$srcfile:$bp_location6.*$bp_location6\[\t \]+if .argc.* \{.*$gdb_prompt $"\
++ { pass "run until function breakpoint" }
++ -re ".*$gdb_prompt $" { fail "run until function breakpoint" }
++ timeout { fail "run until function breakpoint (timeout)" }
++ }
++} else {
++ if ![target_info exists gdb_stub] {
++ gdb_test continue ".*Continuing\\..*Breakpoint \[0-9\]+, main \\(argc=.*, argv=.*, envp=.*\\) at .*$srcfile:$bp_location6.*$bp_location6\[\t \]+if .argc.*\{.*" "stub continue"
++ }
++}
++
++#
++# run until the breakpoint at a line number
++#
++gdb_test continue "Continuing\\..*Breakpoint \[0-9\]+, main \\(argc=.*, argv=.*, envp=.*\\) at .*$srcfile:$bp_location1.*$bp_location1\[\t \]+printf.*factorial.*" \
++ "run until breakpoint set at a line number"
++
++#
++# Run until the breakpoint set in a function in a file
++#
++for {set i 6} {$i >= 1} {incr i -1} {
++ gdb_test continue "Continuing\\..*Breakpoint \[0-9\]+, factorial \\(value=$i\\) at .*$srcfile:$bp_location7.*$bp_location7\[\t \]+.*if .value > 1. \{.*" \
++ "run until file:function($i) breakpoint"
++}
++
++#
++# Run until the breakpoint set at a quoted function
++#
++gdb_test continue "Continuing\\..*Breakpoint \[0-9\]+, (0x\[0-9a-f\]+ in )?marker2 \\(a=43\\) at .*$srcfile1:($bp_location8|$bp_location9).*" \
++ "run until quoted breakpoint"
++#
++# run until the file:function breakpoint at a line number in a file
++#
++gdb_test continue "Continuing\\..*Breakpoint \[0-9\]+, main \\(argc=.*, argv=.*, envp=.*\\) at .*$srcfile:$bp_location2.*$bp_location2\[\t \]+argc = \\(argc == 12345\\);.*" \
++ "run until file:linenum breakpoint"
++
++# Test break at offset +1
++set bp_location10 [gdb_get_line_number "set breakpoint 10 here"]
++
++gdb_test "break +1" \
++ "Breakpoint.*at.* file .*$srcfile, line $bp_location10\\." \
++ "breakpoint offset +1"
++
++# Check to see if breakpoint is hit when stepped onto
++
++gdb_test "step" \
++ ".*Breakpoint \[0-9\]+, main \\(argc=.*, argv=.*, envp=.*\\) at .*$srcfile:$bp_location10.*$bp_location10\[\t \]+return argc;.*breakpoint 10 here.*" \
++ "step onto breakpoint"
++
++#
++# delete all breakpoints so we can start over, course this can be a test too
++#
++delete_breakpoints
++
++#
++# test temporary breakpoint at function
++#
++
++gdb_test "tbreak main" "Breakpoint.*at.* file .*$srcfile, line.*" "Temporary breakpoint function"
++
++#
++# test break at function in file
++#
++
++gdb_test "tbreak $srcfile:factorial" "Breakpoint.*at.* file .*$srcfile, line.*" \
++ "Temporary breakpoint function in file"
++
++#
++# test break at line number
++#
++send_gdb "tbreak $bp_location1\n"
++gdb_expect {
++ -re "Breakpoint.*at.* file .*$srcfile, line $bp_location1.*$gdb_prompt $" { pass "Temporary breakpoint line number #1" }
++ -re ".*$gdb_prompt $" { pass "Temporary breakpoint line number #1" }
++ timeout { fail "breakpoint line number #1 (timeout)" }
++}
++
++gdb_test "tbreak $bp_location6" "Breakpoint.*at.* file .*$srcfile, line $bp_location6.*" "Temporary breakpoint line number #2"
++
++#
++# test break at line number in file
++#
++send_gdb "tbreak $srcfile:$bp_location2\n"
++gdb_expect {
++ -re "Breakpoint.*at.* file .*$srcfile, line $bp_location2.*$gdb_prompt $" { pass "Temporary breakpoint line number in file #1" }
++ -re ".*$gdb_prompt $" { pass "Temporary breakpoint line number in file #1" }
++ timeout { fail "Temporary breakpoint line number in file #1 (timeout)" }
++}
++
++set bp_location11 [gdb_get_line_number "set breakpoint 11 here"]
++gdb_test "tbreak $srcfile:$bp_location11" "Breakpoint.*at.* file .*$srcfile, line $bp_location11.*" "Temporary breakpoint line number in file #2"
++
++#
++# check to see what breakpoints are set (temporary this time)
++#
++gdb_test "info break" "Num Type.*Disp Enb Address.*What.*\[\r\n\]
++\[0-9\]+\[\t \]+breakpoint del.*y.*in main at .*$srcfile:$main_line.*\[\r\n\]
++\[0-9\]+\[\t \]+breakpoint del.*y.*in factorial$proto at .*$srcfile:$bp_location7.*\[\r\n\]
++\[0-9\]+\[\t \]+breakpoint del.*y.*in main at .*$srcfile:$bp_location1.*\[\r\n\]
++\[0-9\]+\[\t \]+breakpoint del.*y.*in main at .*$srcfile:$bp_location6.*\[\r\n\]
++\[0-9\]+\[\t \]+breakpoint del.*y.*in main at .*$srcfile:$bp_location2.*\[\r\n\]
++\[0-9\]+\[\t \]+breakpoint del.*y.*in main at .*$srcfile:$bp_location11.*" \
++ "Temporary breakpoint info"
++
++
++#***********
++
++# Verify that catchpoints for fork, vfork and exec don't trigger
++# inappropriately. (There are no calls to those system functions
++# in this test program.)
++#
++if ![runto_main] then { fail "break tests suppressed" }
++
++send_gdb "catch\n"
++gdb_expect {
++ -re "Catch requires an event name.*$gdb_prompt $"\
++ {pass "catch requires an event name"}
++ -re "$gdb_prompt $"\
++ {fail "catch requires an event name"}
++ timeout {fail "(timeout) catch requires an event name"}
++}
++
++
++set name "set catch fork, never expected to trigger"
++send_gdb "catch fork\n"
++gdb_expect {
++ -re "Catchpoint \[0-9\]* .fork..*$gdb_prompt $"
++ {pass $name}
++ -re "Catch of fork not yet implemented.*$gdb_prompt $"
++ {pass $name}
++ -re "$gdb_prompt $"
++ {fail $name}
++ timeout {fail "(timeout) $name"}
++}
++
++
++set name "set catch vfork, never expected to trigger"
++send_gdb "catch vfork\n"
++
++# If we are on HP-UX 10.20, we expect an error message to be
++# printed if we type "catch vfork" at the gdb gdb_prompt. This is
++# because on HP-UX 10.20, we cannot catch vfork events.
++
++if [istarget "hppa*-hp-hpux10.20"] then {
++ gdb_expect {
++ -re "Catch of vfork events not supported on HP-UX 10.20..*$gdb_prompt $"
++ {pass $name}
++ -re "$gdb_prompt $"
++ {fail $name}
++ timeout {fail "(timeout) $name"}
++ }
++} else {
++ gdb_expect {
++ -re "Catchpoint \[0-9\]* .vfork..*$gdb_prompt $"
++ {pass $name}
++ -re "Catch of vfork not yet implemented.*$gdb_prompt $"
++ {pass $name}
++ -re "$gdb_prompt $"
++ {fail $name}
++ timeout {fail "(timeout) $name"}
++ }
++}
++
++set name "set catch exec, never expected to trigger"
++send_gdb "catch exec\n"
++gdb_expect {
++ -re "Catchpoint \[0-9\]* .exec..*$gdb_prompt $"
++ {pass $name}
++ -re "Catch of exec not yet implemented.*$gdb_prompt $"
++ {pass $name}
++ -re "$gdb_prompt $" {fail $name}
++ timeout {fail "(timeout) $name"}
++}
++
++# Verify that GDB responds gracefully when asked to set a breakpoint
++# on a nonexistent source line.
++#
++send_gdb "break 999\n"
++gdb_expect {
++ -re "No line 999 in file .*$gdb_prompt $"\
++ {pass "break on non-existent source line"}
++ -re "$gdb_prompt $"\
++ {fail "break on non-existent source line"}
++ timeout {fail "(timeout) break on non-existent source line"}
++}
++
++# Run to the desired default location. If not positioned here, the
++# tests below don't work.
++#
++gdb_test "until $bp_location1" "main .* at .*:$bp_location1.*" "until bp_location1"
++
++
++# Verify that GDB allows one to just say "break", which is treated
++# as the "default" breakpoint. Note that GDB gets cute when printing
++# the informational message about other breakpoints at the same
++# location. We'll hit that bird with this stone too.
++#
++send_gdb "break\n"
++gdb_expect {
++ -re "Breakpoint \[0-9\]*.*$gdb_prompt $"\
++ {pass "break on default location, 1st time"}
++ -re "$gdb_prompt $"\
++ {fail "break on default location, 1st time"}
++ timeout {fail "(timeout) break on default location, 1st time"}
++}
++
++send_gdb "break\n"
++gdb_expect {
++ -re "Note: breakpoint \[0-9\]* also set at .*Breakpoint \[0-9\]*.*$gdb_prompt $"\
++ {pass "break on default location, 2nd time"}
++ -re "$gdb_prompt $"\
++ {fail "break on default location, 2nd time"}
++ timeout {fail "(timeout) break on default location, 2nd time"}
++}
++
++send_gdb "break\n"
++gdb_expect {
++ -re "Note: breakpoints \[0-9\]* and \[0-9\]* also set at .*Breakpoint \[0-9\]*.*$gdb_prompt $"\
++ {pass "break on default location, 3rd time"}
++ -re "$gdb_prompt $"\
++ {fail "break on default location, 3rd time"}
++ timeout {fail "(timeout) break on default location, 3rd time"}
++}
++
++send_gdb "break\n"
++gdb_expect {
++ -re "Note: breakpoints \[0-9\]*, \[0-9\]* and \[0-9\]* also set at .*Breakpoint \[0-9\]*.*$gdb_prompt $"\
++ {pass "break on default location, 4th time"}
++ -re "$gdb_prompt $"\
++ {fail "break on default location, 4th time"}
++ timeout {fail "(timeout) break on default location, 4th time"}
++}
++
++# Verify that a "silent" breakpoint can be set, and that GDB is indeed
++# "silent" about its triggering.
++#
++if ![runto_main] then { fail "break tests suppressed" }
++
++send_gdb "break $bp_location1\n"
++gdb_expect {
++ -re "Breakpoint (\[0-9\]*) at .*, line $bp_location1.*$gdb_prompt $"\
++ {pass "set to-be-silent break bp_location1"}
++ -re "$gdb_prompt $"\
++ {fail "set to-be-silent break bp_location1"}
++ timeout {fail "(timeout) set to-be-silent break bp_location1"}
++}
++
++send_gdb "commands $expect_out(1,string)\n"
++send_gdb "silent\n"
++send_gdb "end\n"
++gdb_expect {
++ -re ".*$gdb_prompt $"\
++ {pass "set silent break bp_location1"}
++ timeout {fail "(timeout) set silent break bp_location1"}
++}
++
++send_gdb "info break $expect_out(1,string)\n"
++gdb_expect {
++ -re "\[0-9\]*\[ \t\]*breakpoint.*:$bp_location1\r\n\[ \t\]*silent.*$gdb_prompt $"\
++ {pass "info silent break bp_location1"}
++ -re "$gdb_prompt $"\
++ {fail "info silent break bp_location1"}
++ timeout {fail "(timeout) info silent break bp_location1"}
++}
++send_gdb "continue\n"
++gdb_expect {
++ -re "Continuing.\r\n$gdb_prompt $"\
++ {pass "hit silent break bp_location1"}
++ -re "$gdb_prompt $"\
++ {fail "hit silent break bp_location1"}
++ timeout {fail "(timeout) hit silent break bp_location1"}
++}
++send_gdb "bt\n"
++gdb_expect {
++ -re "#0 main .* at .*:$bp_location1.*$gdb_prompt $"\
++ {pass "stopped for silent break bp_location1"}
++ -re "$gdb_prompt $"\
++ {fail "stopped for silent break bp_location1"}
++ timeout {fail "(timeout) stopped for silent break bp_location1"}
++}
++
++# Verify that GDB can at least parse a breakpoint with the
++# "thread" keyword. (We won't attempt to test here that a
++# thread-specific breakpoint really triggers appropriately.
++# The gdb.threads subdirectory contains tests for that.)
++#
++set bp_location12 [gdb_get_line_number "set breakpoint 12 here"]
++send_gdb "break $bp_location12 thread 999\n"
++gdb_expect {
++ -re "Unknown thread 999.*$gdb_prompt $"\
++ {pass "thread-specific breakpoint on non-existent thread disallowed"}
++ -re "$gdb_prompt $"\
++ {fail "thread-specific breakpoint on non-existent thread disallowed"}
++ timeout {fail "(timeout) thread-specific breakpoint on non-existent thread disallowed"}
++}
++send_gdb "break $bp_location12 thread foo\n"
++gdb_expect {
++ -re "Junk after thread keyword..*$gdb_prompt $"\
++ {pass "thread-specific breakpoint on bogus thread ID disallowed"}
++ -re "$gdb_prompt $"\
++ {fail "thread-specific breakpoint on bogus thread ID disallowed"}
++ timeout {fail "(timeout) thread-specific breakpoint on bogus thread ID disallowed"}
++}
++
++# Verify that GDB responds gracefully to a breakpoint command with
++# trailing garbage.
++#
++send_gdb "break $bp_location12 foo\n"
++gdb_expect {
++ -re "Junk at end of arguments..*$gdb_prompt $"\
++ {pass "breakpoint with trailing garbage disallowed"}
++ -re "$gdb_prompt $"\
++ {fail "breakpoint with trailing garbage disallowed"}
++ timeout {fail "(timeout) breakpoint with trailing garbage disallowed"}
++}
++
++# Verify that GDB responds gracefully to a "clear" command that has
++# no matching breakpoint. (First, get us off the current source line,
++# which we know has a breakpoint.)
++#
++send_gdb "next\n"
++gdb_expect {
++ -re ".*$gdb_prompt $"\
++ {pass "step over breakpoint"}
++ timeout {fail "(timeout) step over breakpoint"}
++}
++send_gdb "clear 81\n"
++gdb_expect {
++ -re "No breakpoint at 81..*$gdb_prompt $"\
++ {pass "clear line has no breakpoint disallowed"}
++ -re "$gdb_prompt $"\
++ {fail "clear line has no breakpoint disallowed"}
++ timeout {fail "(timeout) clear line has no breakpoint disallowed"}
++}
++send_gdb "clear\n"
++gdb_expect {
++ -re "No breakpoint at this line..*$gdb_prompt $"\
++ {pass "clear current line has no breakpoint disallowed"}
++ -re "$gdb_prompt $"\
++ {fail "clear current line has no breakpoint disallowed"}
++ timeout {fail "(timeout) clear current line has no breakpoint disallowed"}
++}
++
++# Verify that we can set and clear multiple breakpoints.
++#
++# We don't test that it deletes the correct breakpoints. We do at
++# least test that it deletes more than one breakpoint.
++#
++gdb_test "break marker3" "Breakpoint.*at.*" "break marker3 #1"
++gdb_test "break marker3" "Breakpoint.*at.*" "break marker3 #2"
++gdb_test "clear marker3" {Deleted breakpoints [0-9]+ [0-9]+.*}
++
++# Verify that a breakpoint can be set via a convenience variable.
++#
++send_gdb "set \$foo=$bp_location11\n"
++gdb_expect {
++ -re "$gdb_prompt $"\
++ {pass "set convenience variable \$foo to bp_location11"}
++ timeout {fail "(timeout) set convenience variable \$foo to bp_location11"}
++}
++send_gdb "break \$foo\n"
++gdb_expect {
++ -re "Breakpoint (\[0-9\]*) at .*, line $bp_location11.*$gdb_prompt $"\
++ {pass "set breakpoint via convenience variable"}
++ -re "$gdb_prompt $"\
++ {fail "set breakpoint via convenience variable"}
++ timeout {fail "(timeout) set breakpoint via convenience variable"}
++}
++
++# Verify that GDB responds gracefully to an attempt to set a
++# breakpoint via a convenience variable whose type is not integer.
++#
++send_gdb "set \$foo=81.5\n"
++gdb_expect {
++ -re "$gdb_prompt $"\
++ {pass "set convenience variable \$foo to 81.5"}
++ timeout {fail "(timeout) set convenience variable \$foo to 81.5"}
++}
++send_gdb "break \$foo\n"
++gdb_expect {
++ -re "Convenience variables used in line specs must have integer values..*$gdb_prompt $"\
++ {pass "set breakpoint via non-integer convenience variable disallowed"}
++ -re "$gdb_prompt $"\
++ {fail "set breakpoint via non-integer convenience variable disallowed"}
++ timeout {fail "(timeout) set breakpoint via non-integer convenience variable disallowed"}
++}
++
++# Verify that we can set and trigger a breakpoint in a user-called function.
++#
++send_gdb "break marker2\n"
++gdb_expect {
++ -re "Breakpoint (\[0-9\]*) at .*, line ($bp_location8|$bp_location9).*$gdb_prompt $"\
++ {pass "set breakpoint on to-be-called function"}
++ -re "$gdb_prompt $"\
++ {fail "set breakpoint on to-be-called function"}
++ timeout {fail "(timeout) set breakpoint on to-be-called function"}
++}
++send_gdb "print marker2(99)\n"
++gdb_expect {
++ -re "The program being debugged stopped while in a function called from GDB.\r\nWhen the function .marker2$proto. is done executing, GDB will silently\r\nstop .instead of continuing to evaluate the expression containing\r\nthe function call...*$gdb_prompt $"\
++ {pass "hit breakpoint on called function"}
++ -re "$gdb_prompt $"\
++ {fail "hit breakpoint on called function"}
++ timeout {fail "(timeout) hit breakpoint on called function"}
++}
++
++# As long as we're stopped (breakpointed) in a called function,
++# verify that we can successfully backtrace & such from here.
++#
++# In this and the following test, the _sr4export check apparently is needed
++# for hppa*-*-hpux.
++#
++send_gdb "bt\n"
++gdb_expect {
++ -re "#0\[ \t\]*($hex in )?marker2.*:($bp_location8|$bp_location9)\r\n#1.*_sr4export.*$gdb_prompt $"\
++ {pass "backtrace while in called function"}
++ -re "#0\[ \t\]*($hex in )?marker2.*:($bp_location8|$bp_location9)\r\n#1.*function called from gdb.*$gdb_prompt $"\
++ {pass "backtrace while in called function"}
++ -re "$gdb_prompt $"\
++ {fail "backtrace while in called function"}
++ timeout {fail "(timeout) backtrace while in called function"}
++}
++
++# Return from the called function. For remote targets, it's important to do
++# this before runto_main, which otherwise may silently stop on the dummy
++# breakpoint inserted by GDB at the program's entry point.
++#
++send_gdb "finish\n"
++gdb_expect {
++ -re "Run till exit from .*marker2.* at .*($bp_location8|$bp_location9)\r\n.* in _sr4export.*$gdb_prompt $"\
++ {pass "finish from called function"}
++ -re "Run till exit from .*marker2.* at .*($bp_location8|$bp_location9)\r\n.*function called from gdb.*$gdb_prompt $"\
++ {pass "finish from called function"}
++ -re "Run till exit from .*marker2.* at .*($bp_location8|$bp_location9)\r\n.*Value returned.*$gdb_prompt $"\
++ {pass "finish from called function"}
++ -re "$gdb_prompt $"\
++ {fail "finish from called function"}
++ timeout {fail "(timeout) finish from called function"}
++}
++
++# Verify that GDB responds gracefully to a "finish" command with
++# arguments.
++#
++if ![runto_main] then { fail "break tests suppressed" }
++
++send_gdb "finish 123\n"
++gdb_expect {
++ -re "The \"finish\" command does not take any arguments.\r\n$gdb_prompt $"\
++ {pass "finish with arguments disallowed"}
++ -re "$gdb_prompt $"\
++ {fail "finish with arguments disallowed"}
++ timeout {fail "(timeout) finish with arguments disallowed"}
++}
++
++# Verify that GDB responds gracefully to a request to "finish" from
++# the outermost frame. On a stub that never exits, this will just
++# run to the stubs routine, so we don't get this error... Thus the
++# second condition.
++#
++
++send_gdb "finish\n"
++gdb_expect {
++ -re "\"finish\" not meaningful in the outermost frame.\r\n$gdb_prompt $"\
++ {pass "finish from outermost frame disallowed"}
++ -re "Run till exit from.*\r\n$gdb_prompt $" {
++ pass "finish from outermost frame disallowed"
++ }
++ -re "$gdb_prompt $"\
++ {fail "finish from outermost frame disallowed"}
++ timeout {fail "(timeout) finish from outermost frame disallowed"}
++}
++
++# Verify that we can explicitly ask GDB to stop on all shared library
++# events, and that it does so.
++#
++if [istarget "hppa*-*-hpux*"] then {
++ if ![runto_main] then { fail "break tests suppressed" }
++
++ send_gdb "set stop-on-solib-events 1\n"
++ gdb_expect {
++ -re "$gdb_prompt $"\
++ {pass "set stop-on-solib-events"}
++ timeout {fail "(timeout) set stop-on-solib-events"}
++ }
++
++ send_gdb "run\n"
++ gdb_expect {
++ -re ".*Start it from the beginning.*y or n. $"\
++ {send_gdb "y\n"
++ gdb_expect {
++ -re ".*Stopped due to shared library event.*$gdb_prompt $"\
++ {pass "triggered stop-on-solib-events"}
++ -re "$gdb_prompt $"\
++ {fail "triggered stop-on-solib-events"}
++ timeout {fail "(timeout) triggered stop-on-solib-events"}
++ }
++ }
++ -re "$gdb_prompt $"\
++ {fail "rerun for stop-on-solib-events"}
++ timeout {fail "(timeout) rerun for stop-on-solib-events"}
++ }
++
++ send_gdb "set stop-on-solib-events 0\n"
++ gdb_expect {
++ -re "$gdb_prompt $"\
++ {pass "reset stop-on-solib-events"}
++ timeout {fail "(timeout) reset stop-on-solib-events"}
++ }
++}
++
++# Hardware breakpoints are unsupported on HP-UX. Verify that GDB
++# gracefully responds to requests to create them.
++#
++if [istarget "hppa*-*-hpux*"] then {
++ if ![runto_main] then { fail "break tests suppressed" }
++
++ send_gdb "hbreak\n"
++ gdb_expect {
++ -re "No hardware breakpoint support in the target.*$gdb_prompt $"\
++ {pass "hw breaks disallowed"}
++ -re "$gdb_prompt $"\
++ {fail "hw breaks disallowed"}
++ timeout {fail "(timeout) hw breaks disallowed"}
++ }
++
++ send_gdb "thbreak\n"
++ gdb_expect {
++ -re "No hardware breakpoint support in the target.*$gdb_prompt $"\
++ {pass "temporary hw breaks disallowed"}
++ -re "$gdb_prompt $"\
++ {fail "temporary hw breaks disallowed"}
++ timeout {fail "(timeout) temporary hw breaks disallowed"}
++ }
++}
++
++#********
++
++
++#
++# Test "next" over recursive function call.
++#
++
++proc test_next_with_recursion {} {
++ global gdb_prompt
++ global decimal
++ global binfile
++
++ if [target_info exists use_gdb_stub] {
++ # Reload the program.
++ delete_breakpoints
++ gdb_load ${binfile};
++ } else {
++ # FIXME: should be using runto
++ gdb_test "kill" "" "kill program" "Kill the program being debugged.*y or n. $" "y"
++
++ delete_breakpoints
++ }
++
++ gdb_test "break factorial" "Breakpoint $decimal at .*" "break at factorial"
++
++ # Run until we call factorial with 6
++
++ if [istarget "*-*-vxworks*"] then {
++ send_gdb "run vxmain \"6\"\n"
++ } else {
++ gdb_run_cmd
++ }
++ gdb_expect {
++ -re "Break.* factorial .value=6. .*$gdb_prompt $" {}
++ -re ".*$gdb_prompt $" {
++ fail "run to factorial(6)";
++ gdb_suppress_tests;
++ }
++ timeout { fail "run to factorial(6) (timeout)" ; gdb_suppress_tests }
++ }
++
++ # Continue until we call factorial recursively with 5.
++
++ if [gdb_test "continue" \
++ "Continuing.*Break.* factorial .value=5. .*" \
++ "continue to factorial(5)"] then { gdb_suppress_tests }
++
++ # Do a backtrace just to confirm how many levels deep we are.
++
++ if [gdb_test "backtrace" \
++ "#0\[ \t\]+ factorial .value=5..*" \
++ "backtrace from factorial(5)"] then { gdb_suppress_tests }
++
++ # Now a "next" should position us at the recursive call, which
++ # we will be performing with 4.
++
++ if [gdb_test "next" \
++ ".* factorial .value - 1.;.*" \
++ "next to recursive call"] then { gdb_suppress_tests }
++
++ # Disable the breakpoint at the entry to factorial by deleting them all.
++ # The "next" should run until we return to the next line from this
++ # recursive call to factorial with 4.
++ # Buggy versions of gdb will stop instead at the innermost frame on
++ # the line where we are trying to "next" to.
++
++ delete_breakpoints
++
++ if [istarget "mips*tx39-*"] {
++ set timeout 60
++ }
++ # We used to set timeout here for all other targets as well. This
++ # is almost certainly wrong. The proper timeout depends on the
++ # target system in use, and how we communicate with it, so there
++ # is no single value appropriate for all targets. The timeout
++ # should be established by the Dejagnu config file(s) for the
++ # board, and respected by the test suite.
++ #
++ # For example, if I'm running GDB over an SSH tunnel talking to a
++ # portmaster in California talking to an ancient 68k board running
++ # a crummy ROM monitor (a situation I can only wish were
++ # hypothetical), then I need a large timeout. But that's not the
++ # kind of knowledge that belongs in this file.
++
++ gdb_test next "\[0-9\]*\[\t \]+return \\(value\\);.*" \
++ "next over recursive call"
++
++ # OK, we should be back in the same stack frame we started from.
++ # Do a backtrace just to confirm.
++
++ set result [gdb_test "backtrace" \
++ "#0\[ \t\]+ factorial .value=120.*\r\n#1\[ \t\]+ \[0-9a-fx\]+ in factorial .value=6..*" \
++ "backtrace from factorial(5.1)"]
++ if { $result != 0 } { gdb_suppress_tests }
++
++ if [target_info exists gdb,noresults] { gdb_suppress_tests }
++ gdb_continue_to_end "recursive next test"
++ gdb_stop_suppressing_tests;
++}
++
++test_next_with_recursion
++
++
++#********
++
++# build a new file with optimization enabled so that we can try breakpoints
++# on targets with optimized prologues
++
++set binfileo2 ${objdir}/${subdir}/${testfile}o2
++
++if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}O0.o" object {debug "additional_flags=-w -O2 -fpie -pie"}] != "" } {
++ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
++}
++
++if { [gdb_compile "${srcdir}/${subdir}/${srcfile1}" "${binfile}O1.o" object {debug "additional_flags=-w -O2 -fpie -pie"}] != "" } {
++ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
++}
++
++if { [gdb_compile "${binfile}O0.o ${binfile}O1.o" "${binfileo2}" executable {debug "additional_flags=-w -fpie -pie"}] != "" } {
++ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
++}
++
++if [get_compiler_info ${binfileo2}] {
++ return -1
++}
++
++gdb_exit
++gdb_start
++gdb_reinitialize_dir $srcdir/$subdir
++gdb_load ${binfileo2}
++
++if [target_info exists gdb_stub] {
++ gdb_step_for_stub;
++}
++
++#
++# test break at function
++#
++gdb_test "break main" \
++ "Breakpoint.*at.* file .*$srcfile, line.*" \
++ "breakpoint function, optimized file"
++
++#
++# test break at function
++#
++gdb_test "break marker4" \
++ "Breakpoint.*at.* file .*$srcfile1, line.*" \
++ "breakpoint small function, optimized file"
++
++#
++# run until the breakpoint at main is hit. For non-stubs-using targets.
++#
++if ![target_info exists use_gdb_stub] {
++ if [istarget "*-*-vxworks*"] then {
++ send_gdb "run vxmain \"2\"\n"
++ set timeout 120
++ verbose "Timeout is now $timeout seconds" 2
++ } else {
++ send_gdb "run\n"
++ }
++ gdb_expect {
++ -re "The program .* has been started already.*y or n. $" {
++ send_gdb "y\n"
++ exp_continue
++ }
++ -re "Starting program.*Breakpoint \[0-9\]+,.*main .*argc.*argv.* at .*$srcfile:$bp_location6.*$bp_location6\[\t \]+if .argc.* \{.*$gdb_prompt $"\
++ { pass "run until function breakpoint, optimized file" }
++ -re "Starting program.*Breakpoint \[0-9\]+,.*main .*argc.*argv.* at .*$gdb_prompt $"\
++ { pass "run until function breakpoint, optimized file (code motion)" }
++ -re ".*$gdb_prompt $" { fail "run until function breakpoint, optimized file" }
++ timeout { fail "run until function breakpoint, optimized file (timeout)" }
++ }
++} else {
++ if ![target_info exists gdb_stub] {
++ gdb_test continue ".*Continuing\\..*Breakpoint \[0-9\]+, main \\(argc=.*, argv=.*, envp=.*\\) at .*$srcfile:$bp_location6.*$bp_location6\[\t \]+if .argc.*\{.*" "stub continue, optimized file"
++ }
++}
++
++#
++# run until the breakpoint at a small function
++#
++
++#
++# Add a second pass pattern. The behavior differs here between stabs
++# and dwarf for one-line functions. Stabs preserves two line symbols
++# (one before the prologue and one after) with the same line number,
++# but dwarf regards these as duplicates and discards one of them.
++# Therefore the address after the prologue (where the breakpoint is)
++# has no exactly matching line symbol, and GDB reports the breakpoint
++# as if it were in the middle of a line rather than at the beginning.
++
++set bp_location13 [gdb_get_line_number "set breakpoint 13 here" $srcfile1]
++set bp_location14 [gdb_get_line_number "set breakpoint 14 here" $srcfile1]
++send_gdb "continue\n"
++gdb_expect {
++ -re "Breakpoint $decimal, marker4 \\(d=177601976\\) at .*$srcfile1:$bp_location13\[\r\n\]+$bp_location13\[\t \]+void marker4.*" {
++ pass "run until breakpoint set at small function, optimized file"
++ }
++ -re "Breakpoint $decimal, $hex in marker4 \\(d=177601976\\) at .*$srcfile1:$bp_location13\[\r\n\]+$bp_location13\[\t \]+void marker4.*" {
++ pass "run until breakpoint set at small function, optimized file"
++ }
++ -re "Breakpoint $decimal, marker4 \\(d=177601976\\) at .*$srcfile1:$bp_location14\[\r\n\]+$bp_location14\[\t \]+void marker4.*" {
++ # marker4() is defined at line 46 when compiled with -DPROTOTYPES
++ pass "run until breakpoint set at small function, optimized file (line bp_location14)"
++ }
++ -re ".*$gdb_prompt " {
++ fail "run until breakpoint set at small function, optimized file"
++ }
++ timeout {
++ fail "run until breakpoint set at small function, optimized file (timeout)"
++ }
++}
++
++
++# Reset the default arguments for VxWorks
++if [istarget "*-*-vxworks*"] {
++ set timeout 10
++ verbose "Timeout is now $timeout seconds" 2
++ send_gdb "set args main\n"
++ gdb_expect -re ".*$gdb_prompt $" {}
++}
+Index: gdb-6.8/gdb/testsuite/gdb.pie/break1.c
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ gdb-6.8/gdb/testsuite/gdb.pie/break1.c 2008-03-30 08:59:12.000000000 -0700
+@@ -0,0 +1,44 @@
++/* This testcase is part of GDB, the GNU debugger.
++
++ Copyright 1992, 1993, 1994, 1995, 1999, 2002, 2003 Free Software
++ Foundation, Inc.
++
++ This program is free software; you can redistribute it and/or modify
++ it under the terms of the GNU General Public License as published by
++ the Free Software Foundation; either version 2 of the License, or
++ (at your option) any later version.
++
++ This program is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ GNU General Public License for more details.
++
++ You should have received a copy of the GNU General Public License
++ along with this program; if not, write to the Free Software
++ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++
++ Please email any bugs, comments, and/or additions to this file to:
++ bug-gdb@prep.ai.mit.edu */
++
++/* The code for this file was extracted from the gdb testsuite
++ testcase "break.c". */
++
++/* The following functions do nothing useful. They are included
++ simply as places to try setting breakpoints at. They are
++ explicitly "one-line functions" to verify that this case works
++ (some versions of gcc have or have had problems with this).
++
++ These functions are in a separate source file to prevent an
++ optimizing compiler from inlining them and optimizing them away. */
++
++#ifdef PROTOTYPES
++int marker1 (void) { return (0); } /* set breakpoint 15 here */
++int marker2 (int a) { return (1); } /* set breakpoint 8 here */
++void marker3 (char *a, char *b) {} /* set breakpoint 17 here */
++void marker4 (long d) {} /* set breakpoint 14 here */
++#else
++int marker1 () { return (0); } /* set breakpoint 16 here */
++int marker2 (a) int a; { return (1); } /* set breakpoint 9 here */
++void marker3 (a, b) char *a, *b; {} /* set breakpoint 18 here */
++void marker4 (d) long d; {} /* set breakpoint 13 here */
++#endif
+Index: gdb-6.8/gdb/testsuite/gdb.pie/corefile.exp
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ gdb-6.8/gdb/testsuite/gdb.pie/corefile.exp 2008-03-30 08:59:12.000000000 -0700
+@@ -0,0 +1,243 @@
++# Copyright 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000
++# Free Software Foundation, Inc.
++
++# This program is free software; you can redistribute it and/or modify
++# it under the terms of the GNU General Public License as published by
++# the Free Software Foundation; either version 2 of the License, or
++# (at your option) any later version.
++#
++# This program is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++# GNU General Public License for more details.
++#
++# You should have received a copy of the GNU General Public License
++# along with this program; if not, write to the Free Software
++# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++
++# Please email any bugs, comments, and/or additions to this file to:
++# bug-gdb@prep.ai.mit.edu
++
++# This file was written by Fred Fish. (fnf@cygnus.com)
++
++if $tracelevel then {
++ strace $tracelevel
++}
++
++set prms_id 0
++set bug_id 0
++
++# are we on a target board
++if ![isnative] then {
++ return
++}
++
++set testfile "coremaker"
++set srcfile ${testfile}.c
++set binfile ${objdir}/${subdir}/${testfile}
++if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug "additional_flags=-fpie -pie"}] != "" } {
++ gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
++}
++
++# Create and source the file that provides information about the compiler
++# used to compile the test case.
++if [get_compiler_info ${binfile}] {
++ return -1;
++}
++
++# Create a core file named "corefile" rather than just "core", to
++# avoid problems with sys admin types that like to regularly prune all
++# files named "core" from the system.
++#
++# Arbitrarily try setting the core size limit to "unlimited" since
++# this does not hurt on systems where the command does not work and
++# allows us to generate a core on systems where it does.
++#
++# Some systems append "core" to the name of the program; others append
++# the name of the program to "core"; still others (like Linux, as of
++# May 2003) create cores named "core.PID". In the latter case, we
++# could have many core files lying around, and it may be difficult to
++# tell which one is ours, so let's run the program in a subdirectory.
++set found 0
++set coredir "${objdir}/${subdir}/coredir.[getpid]"
++file mkdir $coredir
++catch "system \"(cd ${coredir}; ulimit -c unlimited; ${binfile}; true) >/dev/null 2>&1\""
++# remote_exec host "${binfile}"
++foreach i "${coredir}/core ${coredir}/core.coremaker.c ${binfile}.core" {
++ if [remote_file build exists $i] {
++ remote_exec build "mv $i ${objdir}/${subdir}/corefile"
++ set found 1
++ }
++}
++# Check for "core.PID".
++if { $found == 0 } {
++ set names [glob -nocomplain -directory $coredir core.*]
++ if {[llength $names] == 1} {
++ set corefile [file join $coredir [lindex $names 0]]
++ remote_exec build "mv $corefile ${objdir}/${subdir}/corefile"
++ set found 1
++ }
++}
++if { $found == 0 } {
++ # The braindamaged HPUX shell quits after the ulimit -c above
++ # without executing ${binfile}. So we try again without the
++ # ulimit here if we didn't find a core file above.
++ # Oh, I should mention that any "braindamaged" non-Unix system has
++ # the same problem. I like the cd bit too, it's really neat'n stuff.
++ catch "system \"(cd ${objdir}/${subdir}; ${binfile}; true) >/dev/null 2>&1\""
++ foreach i "${objdir}/${subdir}/core ${objdir}/${subdir}/core.coremaker.c ${binfile}.core" {
++ if [remote_file build exists $i] {
++ remote_exec build "mv $i ${objdir}/${subdir}/corefile"
++ set found 1
++ }
++ }
++}
++
++# Try to clean up after ourselves.
++remote_file build delete [file join $coredir coremmap.data]
++remote_exec build "rmdir $coredir"
++
++if { $found == 0 } {
++ warning "can't generate a core file - core tests suppressed - check ulimit -c"
++ return 0
++}
++
++#
++# Test that we can simply startup with a "-core=corefile" command line arg
++# and recognize that the core file is a valid, usable core file.
++# To do this, we must shutdown the currently running gdb and restart
++# with the -core args. We can't use gdb_start because it looks for
++# the first gdb prompt, and the message we are looking for occurs
++# before the first prompt. Also, we can't include GDBFLAGS because
++# if it is empty, this confuses gdb with an empty argument that it
++# grumbles about (said grumbling currently being ignored in gdb_start).
++# **FIXME**
++#
++# Another problem is that on some systems (solaris for example), there
++# is apparently a limit on the length of a fully specified path to
++# the coremaker executable, at about 80 chars. For this case, consider
++# it a pass, but note that the program name is bad.
++
++gdb_exit
++if $verbose>1 then {
++ send_user "Spawning $GDB -nw $GDBFLAGS -core=$objdir/$subdir/corefile\n"
++}
++
++set oldtimeout $timeout
++set timeout [expr "$timeout + 60"]
++verbose "Timeout is now $timeout seconds" 2
++eval "spawn $GDB -nw $GDBFLAGS -core=$objdir/$subdir/corefile"
++expect {
++ -re "Couldn't find .* registers in core file.*$gdb_prompt $" {
++ fail "args: -core=corefile (couldn't find regs)"
++ }
++ -re "Core was generated by .*coremaker.*\r\n\#0 .*\(\).*\r\n$gdb_prompt $" {
++ pass "args: -core=corefile"
++ }
++ -re "Core was generated by .*\r\n\#0 .*\(\).*\r\n$gdb_prompt $" {
++ pass "args: -core=corefile (with bad program name)"
++ }
++ -re ".*registers from core file: File in wrong format.* $" {
++ fail "args: -core=corefile (could not read registers from core file)"
++ }
++ -re ".*$gdb_prompt $" { fail "args: -core=corefile" }
++ timeout { fail "(timeout) starting with -core" }
++}
++
++
++#
++# Test that startup with both an executable file and -core argument.
++# See previous comments above, they are still applicable.
++#
++
++close;
++
++if $verbose>1 then {
++ send_user "Spawning $GDB -nw $GDBFLAGS $binfile -core=$objdir/$subdir/corefile\n"
++}
++
++
++eval "spawn $GDB -nw $GDBFLAGS $binfile -core=$objdir/$subdir/corefile";
++expect {
++ -re "Core was generated by .*coremaker.*\r\n\#0 .*\(\).*\r\n$gdb_prompt $" {
++ pass "args: execfile -core=corefile"
++ }
++ -re "Core was generated by .*\r\n\#0 .*\(\).*\r\n$gdb_prompt $" {
++ pass "args: execfile -core=corefile (with bad program name)"
++ }
++ -re ".*registers from core file: File in wrong format.* $" {
++ fail "args: execfile -core=corefile (could not read registers from core file)"
++ }
++ -re ".*$gdb_prompt $" { fail "args: execfile -core=corefile" }
++ timeout { fail "(timeout) starting with -core" }
++}
++set timeout $oldtimeout
++verbose "Timeout is now $timeout seconds" 2
++
++close;
++
++# Now restart normally.
++
++gdb_start
++gdb_reinitialize_dir $srcdir/$subdir
++gdb_load ${binfile}
++
++# Test basic corefile recognition via core-file command.
++
++send_gdb "core-file $objdir/$subdir/corefile\n"
++gdb_expect {
++ -re ".* program is being debugged already.*y or n. $" {
++ # gdb_load may connect us to a gdbserver.
++ send_gdb "y\n"
++ exp_continue;
++ }
++ -re "Core was generated by .*coremaker.*\r\n\#0 .*\(\).*\r\n$gdb_prompt $" {
++ pass "core-file command"
++ }
++ -re "Core was generated by .*\r\n\#0 .*\(\).*\r\n$gdb_prompt $" {
++ pass "core-file command (with bad program name)"
++ }
++ -re ".*registers from core file: File in wrong format.* $" {
++ fail "core-file command (could not read registers from core file)"
++ }
++ -re ".*$gdb_prompt $" { fail "core-file command" }
++ timeout { fail "(timeout) core-file command" }
++}
++
++# Test correct mapping of corefile sections by printing some variables.
++
++gdb_test "print coremaker_data" "\\\$$decimal = 202"
++gdb_test "print coremaker_bss" "\\\$$decimal = 10"
++gdb_test "print coremaker_ro" "\\\$$decimal = 201"
++
++gdb_test "print func2::coremaker_local" "\\\$$decimal = \\{0, 1, 2, 3, 4\\}"
++
++# Somehow we better test the ability to read the registers out of the core
++# file correctly. I don't think the other tests do this.
++
++gdb_test "bt" "abort.*func2.*func1.*main.*" "backtrace in corefile.exp"
++gdb_test "up" "#\[0-9\]* *\[0-9xa-fH'\]* in .* \\(.*\\).*" "up in corefile.exp"
++
++# Test ability to read mmap'd data
++
++gdb_test "x/8bd buf1" ".*:.*0.*1.*2.*3.*4.*5.*6.*7" "accessing original mmap data in core file"
++setup_xfail "*-*-sunos*" "*-*-ultrix*" "*-*-aix*"
++set test "accessing mmapped data in core file"
++gdb_test_multiple "x/8bd buf2" "$test" {
++ -re ".*:.*0.*1.*2.*3.*4.*5.*6.*7.*$gdb_prompt $" {
++ pass "$test"
++ }
++ -re "0x\[f\]*:.*Cannot access memory at address 0x\[f\]*.*$gdb_prompt $" {
++ fail "$test (mapping failed at runtime)"
++ }
++ -re "0x.*:.*Cannot access memory at address 0x.*$gdb_prompt $" {
++ fail "$test (mapping address not found in core file)"
++ }
++}
++
++# test reinit_frame_cache
++
++gdb_load ${binfile}
++gdb_test "up" "#\[0-9\]* *\[0-9xa-fH'\]* in .* \\(\\).*" "up in corefile.exp (reinit)"
++
++gdb_test "core" "No core file now."
+Index: gdb-6.8/gdb/testsuite/gdb.pie/coremaker.c
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ gdb-6.8/gdb/testsuite/gdb.pie/coremaker.c 2008-03-30 08:59:12.000000000 -0700
+@@ -0,0 +1,142 @@
++/* Copyright 1992, 1993, 1994, 1995, 1996, 1999
++ Free Software Foundation, Inc.
++
++ This file is part of GDB.
++
++ This program is free software; you can redistribute it and/or modify
++ it under the terms of the GNU General Public License as published by
++ the Free Software Foundation; either version 2 of the License, or (at
++ your option) any later version.
++
++ This program is distributed in the hope that it will be useful, but
++ WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ General Public License for more details.
++
++ You should have received a copy of the GNU General Public License
++ along with this program; if not, write to the Free Software
++ Foundation, Inc., 59 Temple Place - Suite 330,
++ Boston, MA 02111-1307, USA. */
++
++/* Simple little program that just generates a core dump from inside some
++ nested function calls. */
++
++#include <stdio.h>
++#include <sys/types.h>
++#include <fcntl.h>
++#include <sys/mman.h>
++#include <signal.h>
++#include <stdlib.h>
++#include <unistd.h>
++
++#ifndef __STDC__
++#define const /**/
++#endif
++
++#define MAPSIZE (8 * 1024)
++
++/* Don't make these automatic vars or we will have to walk back up the
++ stack to access them. */
++
++char *buf1;
++char *buf2;
++
++int coremaker_data = 1; /* In Data section */
++int coremaker_bss; /* In BSS section */
++
++const int coremaker_ro = 201; /* In Read-Only Data section */
++
++/* Note that if the mapping fails for any reason, we set buf2
++ to -1 and the testsuite notices this and reports it as
++ a failure due to a mapping error. This way we don't have
++ to test for specific errors when running the core maker. */
++
++void
++mmapdata ()
++{
++ int j, fd;
++
++ /* Allocate and initialize a buffer that will be used to write
++ the file that is later mapped in. */
++
++ buf1 = (char *) malloc (MAPSIZE);
++ for (j = 0; j < MAPSIZE; ++j)
++ {
++ buf1[j] = j;
++ }
++
++ /* Write the file to map in */
++
++ fd = open ("coremmap.data", O_CREAT | O_RDWR, 0666);
++ if (fd == -1)
++ {
++ perror ("coremmap.data open failed");
++ buf2 = (char *) -1;
++ return;
++ }
++ write (fd, buf1, MAPSIZE);
++
++ /* Now map the file into our address space as buf2 */
++
++ buf2 = (char *) mmap (0, MAPSIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
++ if (buf2 == (char *) -1)
++ {
++ perror ("mmap failed");
++ return;
++ }
++
++ /* Verify that the original data and the mapped data are identical.
++ If not, we'd rather fail now than when trying to access the mapped
++ data from the core file. */
++
++ for (j = 0; j < MAPSIZE; ++j)
++ {
++ if (buf1[j] != buf2[j])
++ {
++ fprintf (stderr, "mapped data is incorrect");
++ buf2 = (char *) -1;
++ return;
++ }
++ }
++}
++
++void
++func2 ()
++{
++ int coremaker_local[5];
++ int i;
++
++#ifdef SA_FULLDUMP
++ /* Force a corefile that includes the data section for AIX. */
++ {
++ struct sigaction sa;
++
++ sigaction (SIGABRT, (struct sigaction *)0, &sa);
++ sa.sa_flags |= SA_FULLDUMP;
++ sigaction (SIGABRT, &sa, (struct sigaction *)0);
++ }
++#endif
++
++ /* Make sure that coremaker_local doesn't get optimized away. */
++ for (i = 0; i < 5; i++)
++ coremaker_local[i] = i;
++ coremaker_bss = 0;
++ for (i = 0; i < 5; i++)
++ coremaker_bss += coremaker_local[i];
++ coremaker_data = coremaker_ro + 1;
++ abort ();
++}
++
++void
++func1 ()
++{
++ func2 ();
++}
++
++int main ()
++{
++ mmapdata ();
++ func1 ();
++ return 0;
++}
++
diff --git a/src/patchsets/gdb/6.8/README.history b/src/patchsets/gdb/6.8/README.history
index 60f0d16cbd..a55ad0803c 100644
--- a/src/patchsets/gdb/6.8/README.history
+++ b/src/patchsets/gdb/6.8/README.history
@@ -1,3 +1,7 @@
+1.3 21.06.2008
+ + 50_all_gdb-pie-1.patch
+ + 50_all_gdb-pie-2.patch
+
1.2 07.04.2008
U 10_all_gdb-6.6-duel.patch
U 11_all_gdb-6.6-duel-integrate.patch